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台缓存服务器要 ...
随机推荐
- s21day15 python笔记
s21day15 python笔记 一.内容回顾及补充 回顾 补充 range / xrange(python2与python3的区别六) python2: xrange:不会在内存中立即创建,而是在 ...
- npm,bower安装失败
安装一些软件时,总是会出现一些莫名其妙的问题.我在安装node.js时,默认安装到C:\Program Files\nodejs之后,安装bower时,bower_components默认装到C:\W ...
- Mac上,Apache启动正常,却无法访问localhost和127.0.0.1
mac系统,之前一直好好的,今天突然localhost以及127就突然打不开了.显示拒绝访问. 各种方法都试过了,不是端口占用, 不是日志文件缺失,任何情况都不是. 想了想,之前有升级过PHP从5升级 ...
- js判断页面在pc端打开还是移动端打开
js判断页面在pc端打开还是移动端打开,分别跳转不同的index.html window.addEventListener('load', function() { // true为手机,false为 ...
- 寒假作业 pta编程总结3
实验代码: 某地老鼠成灾,现悬赏抓老鼠,每抓到一只奖励10元,于是开始跟老鼠斗智斗勇:每天在墙角可选择以下三个操作:放置一个带有一块奶酪的捕鼠夹(T),或者放置一块奶酪(C),或者什么也不放(X).捕 ...
- 使用CMake生成解决方案后构建INSTALL报错
错误 1 error MSB3073: 命令“setlocal"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=Debug - ...
- qt+opencv LNK4272:library machine type 'x64' conflicts with target mathine type 'x86'
运行时报错如上图所示,原因是你使用的opencv库是64位的,qt里面使用的编译器MSVC是32位的,解决方法如下: 将构建套件修改位64bit:
- anki vector robot入门语音指令大全
vector机器人功能不断完善. 一:刚开始支持一些基础指令,你跟他说话他能在本机识别,然后做出相应的响应.在说这部分指令之前,需要加上Hey Vector.(嘿,维课的),然后他会准备听取你的指令, ...
- python 和python-m 的区别
首先在python自带的,help命令中,可以看到,官方的说明是:-m mod : run library module as a script (terminates option list) 意思 ...
- JNI学习笔记_Java调用C —— 非Android中使用的方法
一.学习笔记 1.java源码中的JNI函数本机方法声明必须使用native修饰. 2.相对反编译 Java 的 class 字节码文件来说,反汇编.so动态库来分析程序的逻辑要复杂得多,为了应用的安 ...