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

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算法 实现页面分布式缓存(转)的更多相关文章
- 一致性Hash算法在Redis分布式中的使用
由于redis是单点,但是项目中不可避免的会使用多台Redis缓存服务器,那么怎么把缓存的Key均匀的映射到多台Redis服务器上,且随着缓存服务器的增加或减少时做到最小化的减少缓存Key的命中率呢? ...
- 一致性Hash算法介绍(分布式环境算法)
32的整数环(这个环被称作一致性Hash环),根据节点名称的Hash值(其分布范围同样为0~232)将节点放置在这个Hash 环上.然后根据KEY值计算得到其Hash值(其分布范围也同样为0~232 ...
- 分布式缓存技术memcached学习(四)—— 一致性hash算法原理
分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...
- 分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理
分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前, ...
- 分布式一致性hash算法
写在前面 在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...
- memcache的一致性hash算法使用
一.概述 1.我们的memcache客户端(这里我看的spymemcache的源码),使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同,只是对我们要存储数据的k ...
- 分布式缓存一致性hash算法理解
今天阅读了一下大型网络技术架构这本苏中的分布式缓存一致性hash算法这一节,针对大型分布式系统来说,缓存在该系统中必不可少,分布式集群环境中,会出现添加缓存节点的需求,这样需要保障缓存服务器中对缓存的 ...
- 分布式缓存设计:一致性Hash算法
缓存作为数据库前的一道屏障,它的可用性与缓存命中率都会直接影响到数据库,所以除了配置主从保证高可用之外还需要设计分布式缓存来扩充缓存的容量,将数据分布在多台机器上如果有一台不可用了对整体影响也比较小. ...
- 分布式缓存一致性hash算法
当服务器不多,并且不考虑扩容的时候,可直接使用简单的路由算法,用服务器数除缓存数据KEY的hash值,余数作为服务器下标即可. 但是当业务发展,网站缓存服务需要扩容时就会出现问题,比如3台缓存服务器要 ...
随机推荐
- VS2010与Matlab2010b混合编程
环境: 1.VS2010 2.MATLAB 2010b 3.WINDOW 7 (X64) 1.Matlab环境设置 要建立独立运行的C应用程序,系统中需要安装Matlab.Matlab编译器.C/C+ ...
- 导入到eclipse里的工程挺大的,然后就一直报: An internal error occurred during: "Building workspace". GC overhead limit exceeded 这个错误。
解决方法: 原因是Eclipse默认配置内存太小需要更改Eclipse安装文件夹下的eclipse.ini文件. Eclipse.ini默认文件如下: 修改如下: -Xms1024m -Xmx2048 ...
- 让你真正了解Java(纯干货)
“你学习一门技术的最佳时机是三年前,其次是现在.”这句话对于哪一种行业都很适用,如果你已经学习过Java,那么恭喜你你很有先见之明,如果你并不了解Java,这篇文章带你快速掌握Java的几个核心知识点 ...
- Pagedown learning notes
Pagedown Links Google wiki page Download Markdown.Converter.js var converter = new Markdown.Converte ...
- 1. Packet sniffers (包嗅探器 14个)
十多年来,Nmap项目一直在编目网络安全社区最喜爱的工具. 2011年,该网站变得更加动态,提供打分,评论,搜索,排序和新工具建议表单. 本网站除了我们维护的那些工具(如Nmap安全扫描器,Ncat网 ...
- Go语言极速入门手册.go
Github: https://github.com/coderzh/CodeTips /* gotips_test.go: Golang速学速查速用代码手册 Source: github.com/c ...
- 芯灵思Sinlinx A64 开发板移植SQLite3
开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 首先到 http://ww ...
- apache做反向代理
实验目的 通过apache实现反向代理的功能,类似nginx反向代理和haproxy反向代理 环境准备 逻辑架构如下 前端是apche服务器,监听80端口,后端有两台web服务器,分别是node1和n ...
- neo4j通过LOAD CSV导入结点和关系
1.neo4j默认的导入入口是:安装路径/import,所以要将csv文件放在import目录下,像下面这样: 2.导入后中文乱码: 因为neo4j是utf-8的,而CSV默认保存是ANSI的,需要用 ...
- php设置cookie为httponly防止xss攻击
什么是XSS攻击? XSS攻击(Cross Site Scripting)中文名为跨站脚本攻击,XSS攻击时web中一种常见的漏洞.通过XSS漏洞可以伪造目标用户登录,从而获取登录后的账号操作. 网站 ...