设为首页 收藏本站
查看: 806|回复: 0

[经验分享] Nginx+Memcache+一致性hash算法 实现页面分布式缓存

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-8-25 09:34:55 | 显示全部楼层 |阅读模式
网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化、实现分布式高速缓存就是其中的一个很好的解决方案...
wKiom1e9fSuDjgqsAAAddvnKaJw695.jpg

1)先来看看Nginx负载均衡
Nginx负载均衡依赖自带的ngx_http_upstream_module、ngx_http_memcached_module两大功能模块,其中一致性hash算法Nginx本身是不支持的,可以借助第三方模块:ngx_http_upstream_consistent_hash
或者直接使用淘宝的Tengine:
http://tengine.taobao.org/docume ... istent_hash_cn.html

模块的添加
1
2
3
4
5
6
7
8
9
10
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进程,覆盖二进制文件
[iyunv@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算法
wKioL1e9fTyi1fGhAAA1HOt6-g4588.jpg
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位无符号整形),整个哈希空间如下:

wKiom1e9fU7SZWY2AABMe44cWJg748.jpg
下一步将各个服务器使用H进行一个哈希计算,具体可以使用服务器的IP地址或者主机名作为关键字,这样每台机器能确定其在上面的哈希环上的位置了,并且是按照顺时针排列,这里我们假设三台节点memcache经计算后位置如下
wKioL1e9fV3iXjBhAABjgElWH1I924.jpg
接下来使用相同算法计算出数据的哈希值h,并由此确定数据在此哈希环上的位置
假如我们有数据A、B、C、D、4个对象,经过哈希计算后位置如下:
wKioL1e9fWijweyBAABtLYlDIQk620.jpg
根据一致性哈希算法,数据A就被绑定到了server01上,D被绑定到了server02上,B、C在server03上,是按照顺时针找最近服务节点方法

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

假设server03宕机
wKiom1e9fXSjdcmXAABxdTLVl-U544.jpg
可以看到此时A、C、B不会受到影响,只是将B、C节点被重定位到Server 1。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。
考虑另外一种情况,如果我们在系统中增加一台服务器Memcached Server 04:
wKioL1e9fX6hfmxDAACEiAG-_RE204.jpg
此时A、D、C不受影响,只有B需要重定位到新的Server 4。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。
综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
一致性哈希的缺点:在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。我们可以采用增加虚拟节点的方式解决。


3)Nginx配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$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对缓存页面的访问,但这只是后端的简单实现,在前端还需要实现对页面缓存的管理等等的工作。




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-262689-1-1.html 上篇帖子: 解决nginx环境网站css文件加载报错 下篇帖子: Nginx的Rewrite详解
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表