网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化、实现分布式高速缓存就是其中的一个很好的解决方案...

1)先来看看Nginx负载均衡

Nginx负载均衡依赖自带的 ngx_http_upstream_module 、 ngx_http_memcached_module两大功能模块,其中一致性hash算法Nginx本身是不支持的,可以借助第三方模块: ngx_http_upstream_consistent_hash

或者直接使用淘宝的Tengine:

http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html

模块的添加

unzip ngx_http_consistent_hash-master.zip
cd nginx-1.6.3 #进入nginx安装原始文件夹
./configure --user=www --group=www --add-module=../ngx_http_consistent_hash-master --with-http_ssl_module --with-http_stub_status_module --prefix=/application/nginx-1.6.3/ #添加模块
make #如果是生产环境添加模块,切记不要make install,否则会覆盖文件
cp objs/nginx /application/nginx/sbin/nginx #停掉nginx进程,覆盖二进制文件
[root@lb01 sbin]# ./nginx -V #查看模块是否添加成功
nginx version: nginx/1.6.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
TLS SNI support enabled
configure arguments: --user=www --group=www --add-module=../ngx_http_consistent_hash-master --with-http_ssl_module --with-http_stub_status_module --prefix=/application/nginx-1.6.3/

2)调度算法选择

如上图,在我们确定要将数据采用分布式memcache服务器缓存起来后,就面临一个问题:采用一种什么方式去缓存和调度数据?很显然,最简单的策略就是将每一次Memcache请求都随机发送到一台Memcache服务器,但这种策略可能又会带来两个问题:一是同一份数据可能被存在不同机器上而造成数据冗余,二是可能某数据已经被缓存但是没法命中。因此,随机策略无论是时间效率还是空间效率都利用的不是很好。

url_hash算法

url_hash算法是Nginx负载均衡动态调度算法中的一种,是将一个完整的URL经过哈希运算key=HASH($URL)%3(3是memcache节点台数)得到一个key值,具有相同key值得URL也就是Memcache请求将会发往同一台缓存服务器,比如,H=0发往Memcache_server01、H=1发往Memcache_server02、H=2发往Memcache_server03,避免了数据冗余和命中率低的两个问题;

普通url_hash的缺点就是,计算公式key=HASH($URL)%N中,一旦缓存节点N数量发生变化,那么所有数据都要重新按照公式key=HASH($URL)%(N-1)计算,之前计算得到的key值结果就会全部发生变化,意味着缓存节点下缓存的数据全部失效!要重新缓存全部节点数据。如果是高并发大数据量的话,对后端节点服务器的冲击是致命的,很有可能会导致系统的全面瘫痪。这也是为什么在使用大量的分布式缓存系统在遭遇系统重启时,要对缓存预热及严格遵守集群服务启动顺序的原因。

一致性HASH算法

一致性HASH算法的出现有效的解决了上面普通url_hash调度算法在节点变动后面临全部缓存失效的问题

简单地说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某空间哈希函数H的值空间是0-2^32-1(即哈希值是一个32位无符号整形),整个哈希空间如下:

下一步将各个服务器使用H进行一个哈希计算,具体可以使用服务器的IP地址或者主机名作为关键字,这样每台机器能确定其在上面的哈希环上的位置了,并且是按照顺时针排列,这里我们假设三台节点memcache经计算后位置如下

接下来使用相同算法计算出数据的哈希值h,并由此确定数据在此哈希环上的位置

假如我们有数据A、B、C、D、4个对象,经过哈希计算后位置如下:

根据一致性哈希算法,数据A就被绑定到了server01上,D被绑定到了server02上,B、C在server03上,是按照顺时针找最近服务节点方法

这样得到的哈希环调度方法,有很高的容错性和可扩展性:

假设server03宕机

可以看到此时A、C、B不会受到影响,只是将B、C节点被重定位到Server 1。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

考虑另外一种情况,如果我们在系统中增加一台服务器Memcached Server 04:

此时A、D、C不受影响,只有B需要重定位到新的Server 4。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

一致性哈希的缺点:在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。我们可以采用增加虚拟节点的方式解决。

为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希【具体可以这么做:根据服务器的名字或者是ip计算节点hash的时候,可以加上编号,然后再计算哈希值】,在每个计算的结果位置都放置一个服务节点,称为虚拟节点。这样,数据再被存储的时候,就不会因为服务器在环上的间距太大而导致“数据倾斜”了。

同时数据定位算法不变,只是多了一步虚拟节点 到实际节点的映射,例如定位到“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”三个虚拟节点的数据均定位到Server 1上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分 布,避免出现雪崩的情况

3)Nginx配置

upstream memcached {
consistent_hash $request_uri; #采用一致性哈希计算请求字段request_rui值
server 172.16.2.11:11211; #节点服务器
server 172.16.2.12:11212;
server 172.16.2.13:11213;
} server {
listen 80;
server_name lichengbing.cn; location ^~ /cache/ { #匹配带cache目录时将请求转发给计算好的哈希节点服务器
set $enhanced_memcached_key $request_uri;
enhanced_memcached_pass memcached;
} error_page 404 502 504 = @fallback;
}
location @fallback {
proxy_pass http://backend;
}

4)修改示例PHP页面

$htmlContent = file_get_contents('http://lichengbing.cn');

// 页面过期时间
$expiresTime = 60 * 5; // Last-Modified头设置的时间
$lastModified = gmdate('D, d M Y H:i:s \G\M\T', time()); // Expires头设置的时间
$expires = gmdate('D, d M Y H:i:s \G\M\T', time() + $expiresTime); // 最终缓存的内容
$cacheContent = "EXTRACT_HEADERS
Content-Type: text/html
Cache-Control:max-age=$expiresTime
Expires:$expires
Last-Modified:$lastModified $htmlContent"; // 获取memcache实例
$memcached = new Memcache();
$memcached->addServer('172.16.2.11', 11211);
$memcached->addServer('172.16.2.12', 11212);
$memcached->addServer('172.16.2.13', 11213); // 写入缓存
$memcached->set('/cache/index.html', $cacheContent, $expiresTime);

至此,我们已经简单的完成了使用Nginx和Memcached对缓存页面的访问,但这只是后端的简单实现,在前端还需要实现对页面缓存的管理等等的工作。

原文地址(http://www.tuicool.com/articles/BZBVfaM)

Nginx+Memcache+一致性hash算法 实现页面分布式缓存(转)的更多相关文章

  1. 一致性Hash算法在Redis分布式中的使用

    由于redis是单点,但是项目中不可避免的会使用多台Redis缓存服务器,那么怎么把缓存的Key均匀的映射到多台Redis服务器上,且随着缓存服务器的增加或减少时做到最小化的减少缓存Key的命中率呢? ...

  2. 一致性Hash算法介绍(分布式环境算法)

    32的整数环(这个环被称作一致性Hash环),根据节点名称的Hash值(其分布范围同样为0~232)将节点放置在这个Hash 环上.然后根据KEY值计算得到其Hash值(其分布范围也同样为0~232  ...

  3. 分布式缓存技术memcached学习(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...

  4. 分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前, ...

  5. 分布式一致性hash算法

    写在前面  在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...

  6. memcache的一致性hash算法使用

    一.概述 1.我们的memcache客户端(这里我看的spymemcache的源码),使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同,只是对我们要存储数据的k ...

  7. 分布式缓存一致性hash算法理解

    今天阅读了一下大型网络技术架构这本苏中的分布式缓存一致性hash算法这一节,针对大型分布式系统来说,缓存在该系统中必不可少,分布式集群环境中,会出现添加缓存节点的需求,这样需要保障缓存服务器中对缓存的 ...

  8. 分布式缓存设计:一致性Hash算法

    缓存作为数据库前的一道屏障,它的可用性与缓存命中率都会直接影响到数据库,所以除了配置主从保证高可用之外还需要设计分布式缓存来扩充缓存的容量,将数据分布在多台机器上如果有一台不可用了对整体影响也比较小. ...

  9. 分布式缓存一致性hash算法

    当服务器不多,并且不考虑扩容的时候,可直接使用简单的路由算法,用服务器数除缓存数据KEY的hash值,余数作为服务器下标即可. 但是当业务发展,网站缓存服务需要扩容时就会出现问题,比如3台缓存服务器要 ...

随机推荐

  1. Win10激活密钥key(可激活所有版本)

    Win10激活密钥key(可激活所有版本) Win10一年的免费升级服务已经到期,用户要使用Win10系统,就需要最新Win10密钥来激活Win10,一般激活Win10系统有两种方式,一个是使用Win ...

  2. 从零开始在iPhone上运行视频流实时预测模型应用,只需10步

    1、买一台苹果电脑,建议MacBook Pro. 2、安装Xcode. 3、克隆TensorFlow:https://github.com/tensorflow/tensorflow.git 4、下载 ...

  3. Go实例解析

    Go语言包的加载顺序如图 可以通过如下实例详细了解 代码来源于<Go实战> 代码地址:https://github.com/goinaction/code 项目代码结构 程序架构 首先分析 ...

  4. [工作积累] UE4 并行渲染的同步 - Sync between FParallelCommandListSet & FRHICommandListImmediate calls

    UE4 的渲染分为两个模式1.编辑器是同步绘制的 2.游戏里是FParallelCommandListSet并行派发的. mesh渲染也分两类,static mesh 使用TStaticMeshDra ...

  5. numpy 和tensorflow 中的乘法

    矩阵乘法:tf.matmul()   np.dot() ,@ 逐元素乘法:tf.multiply()  np.multiply()

  6. 敏捷开发SCM

    敏捷的目标:自组织,提高交付质量和交付速度:敏捷中实现拥抱变化是通过迭代增量实现的:所谓的迭代是循环,循环一种机制和模式,增量则是价值的增加,迭代增量,就是通过每次工作流程的循环实现业务价值的提升:那 ...

  7. MVC 验证规则扩展(当RoleID 属性值为A,B 时,Email 属性必填)

    public class RoleRequiredAttribute : ValidationAttribute, IClientValidatable { public string RoleIDS ...

  8. html限制文本框只能输入数字和一个小数点

    近期在做一个前台页面,有一个文本框是用来输入充值金额的,就想到了限制用户只能输入纯数字的数据且只能包含一个小数点.下面就是我实现的代码 $(function() { //阻止数字键以外的按键输入 $( ...

  9. CentOS7.5 安装MySQL8 tar

    1.查看是否安装mariadb 执行命令: [root@mysql ~]# rpm -qa | grep mariadb 显示: mariadb-libs-5.5.56-2.el7.x86_64 2. ...

  10. django ORM多对多操作

    创建多对多: 方式一:自定义关系表 class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = mode ...