memcached一致性哈希及php客户端实现
memcached分布式算法
memcached的分布式是依靠客户端的算法来实现,假设键名为$key,服务器数量为N,常规的实现方式有两种:
- 取模哈希
- crc32($key)%N,通过这个算法将键名映射到某一台服务器,比如需要存取一个键名为myname的缓存,服务器数量为3,那么通过算法计算:crc32('myname')%3=0,那么这个缓存就落到第1台服务器上面
- 这种方式虽然简单可行,但是增减服务器的时候,缓存将面临大量的重建,比如上面的例子中,新增了1台服务器,服务器数量变为4台,通过算法计算:crc32('myname')%4=3,从第1台变成第3台了,导致缓存重建;又比如第1台服务器挂了,缓存的存取都会失败,导致短时间内大量的请求涌入mysql
- 一致性哈希
- 一致性哈希就是为了解决上面的缓存重建而设计的,取模法不理想的原因就是算法的本质就是根据服务器数量来计算的,缓存跟服务器是一一对应,要想灵活一点就不能是一对一的关系,一致性哈希算法首先创建出一个首( 0 )尾( 2^32-1 )相接的环形的哈希空间,如下图的圆环,然后把服务器通过hash算法映射到环形的某一点,如下图中node1、node2、node3、node4,然后再把缓存的键映射到环形的某一点,获取某个键的内容是从这个键的节点按顺时针方向开始查找服务器节点,找到的第一台服务器就是这个缓存要进行存取的服务器,如此一来当node1服务器挂了,影响到的只是从node3到node1节点之间的缓存数据,这些数据将会去node2中存取,这样可以把缓存重建的代价降低

安装依赖软件
[root@localhost ~]# yum install gcc
[root@localhost ~]# yum install gcc-c++
[root@localhost ~]# yum install autoconf
安装libmemcached
memcached扩展依赖于libmemcached,因此先安装libmemcached
[root@localhost ~]# cd /usr/local/src
[root@localhost src]# wget https://launchpad.net/libmemcached/1.0/1.0.17/+download/libmemcached-1.0.17.tar.gz
[root@localhost src]# tar -zxvf libmemcached-1.0.18.tar.gz
[root@localhost src]# cd libmemcached-1.0.18
[root@localhost libmemcached-1.0.18]# ./configure --prefix=/usr/local/libmemcached --with-memcached
[root@localhost libmemcached-1.0.18]# make && make install
安装php的memcached扩展
[root@localhost ~]# cd /usr/local/src
[root@localhost src]# wget http://pecl.php.net/get/memcached-3.0.3.tgz
[root@localhost src]# cd memcached-3.0.3
[root@localhost memcached-3.0.3]# tar -zxvf memcached-3.0.3.tgz
[root@localhost memcached-3.0.3]# ./configure --prefix=/usr/local/pecl-memcached --with-php-config=/usr/local/php/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached
error: no, sasl.h is not available
[root@localhost memcached-3.0.3]# yum install cyrus-sasl-devel
[root@localhost memcached-3.0.3]# make && make install
#修改php配置,加入memcache扩展
[root@localhost memcached-3.0.3]# vi /usr/local/php/lib/php.ini
extension=memcached.so #重启apache
[root@localhost memcached-3.0.3]# apachectl restart #启动memcached服务器并记录日志
[root@localhost src]# memcached -d -u nobody -p 32054 -vv >> /tmp/memcached.32054.log 2>&1
[root@localhost src]# memcached -d -u nobody -p 32055 -vv >> /tmp/memcached.32055.log 2>&1
[root@localhost src]# memcached -d -u nobody -p 32056 -vv >> /tmp/memcached.32056.log 2>&1
测试一致性哈希
$m = new Memcached();
$m->setOptions(array(
Memcached::OPT_DISTRIBUTION=>Memcached::DISTRIBUTION_CONSISTENT,
Memcached::OPT_LIBKETAMA_COMPATIBLE=>true,
Memcached::OPT_REMOVE_FAILED_SERVERS=>true,
));
$m->addServers(array(
array('localhost', 32054),
array('localhost', 32055),
array('localhost', 32056),
//array('localhost', 32057),
));
$m->set('key1', 1);
$m->set('key2', 'abc');
$m->set('key3', array('foo', 'bar'));
$m->set('key4', new stdClass);
$m->set('key5', 'pigfly');
$m->set('key6', 999);
var_dump($m->get('key1'), $m->get('key2'), $m->get('key3'), $m->get('key4'), $m->get('key5'), $m->get('key6'));
运行这段php代码,我们再查看日志:
#memcached.32054.log
36 STORED
36 STORED
36 sending key key2
>36 END
36 sending key key3
>36 END
#memcached.32055.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key1 1 0 1
>36 STORED
<36 set key4 4 0 19
>36 STORED
<36 get key1
>36 sending key key1
>36 END
<36 get key4
>36 sending key key4
>36 END
<36 quit
<36 connection closed.
#memcached.32056.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key5 0 0 6
>36 STORED
<36 set key6 1 0 3
>36 STORED
<36 get key5
>36 sending key key5
>36 END
<36 get key6
>36 sending key key6
>36 END
<36 quit
<36 connection closed.
缓存的分布情况:
| host | key |
|---|---|
| 32054 | key2,key3 |
| 32055 | key1,key4 |
| 32056 | key5,key6 |
现在我们加一台32057的memcached试试:
[root@localhost src]# memcached -d -u nobody -p 32057 -vv >> /tmp/memcached.32057.log 2>&1
取消php代码第13行的注释,运行php,查看日志文件:
#memcached.32054.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key3 4 0 34
>36 STORED
<36 get key3
>36 sending key key3
>36 END
<36 quit
#memcached.32055.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key1 1 0 1
>36 STORED
<36 set key4 4 0 19
>36 STORED
<36 get key1
>36 sending key key1
>36 END
<36 get key4
>36 sending key key4
>36 END
<36 quit
<36 connection closed.
#memcached.32056.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key5 0 0 6
>36 STORED
<36 set key6 1 0 3
>36 STORED
<36 get key5
>36 sending key key5
>36 END
<36 get key6
>36 sending key key6
>36 END
<36 quit
<36 connection closed.
#memcached.32057.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key2 0 0 3
>36 STORED
<36 get key2
>36 sending key key2
>36 END
<36 quit
<36 connection closed.
缓存的分布情况:
| host | key |
|---|---|
| 32054 | key3 |
| 32055 | key1,key4 |
| 32056 | key5,key6 |
| 32057 | key2 |
我们发现32054的key2跑到32057去了,32055和32056的key都没有受到影响,说明一致性哈希起作用了,我们再来模拟一下有一台memcached服务器宕机的情况
[root@local htdocs]# ps -aux | grep memcached
nobody 7621 0.0 0.3 415860 3440 ? Ssl 16:16 0:00 memcached -d -u nobody -p 32054 -vv
nobody 7632 0.0 0.4 414832 4432 ? Ssl 16:16 0:00 memcached -d -u nobody -p 32055 -vv
nobody 7643 0.0 0.8 414832 8532 ? Ssl 16:17 0:00 memcached -d -u nobody -p 32056 -vv
nobody 7659 0.0 0.4 414832 4432 ? Ssl 16:26 0:00 memcached -d -u nobody -p 32057 -vv
[root@local htdocs]# kill 7621 #杀掉32054
运行php代码,查看日志:
#memcached.32055.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key1 1 0 1
>36 STORED
<36 set key3 4 0 34
>36 STORED
<36 set key4 4 0 19
>36 STORED
<36 get key1
>36 sending key key1
>36 END
<36 get key3
>36 sending key key3
>36 END
<36 get key4
>36 sending key key4
>36 END
<36 quit
<36 connection closed.
#memcached.32056.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key5 0 0 6
>36 STORED
<36 set key6 1 0 3
>36 STORED
<36 get key5
>36 sending key key5
>36 END
<36 get key6
>36 sending key key6
>36 END
<36 quit
<36 connection closed.
#memcached.32057.log
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 set key2 0 0 3
>36 STORED
<36 get key2
>36 sending key key2
>36 END
<36 quit
<36 connection closed.
缓存的分布情况:
| host | key |
|---|---|
| 32055 | key1,key3,key4 |
| 32056 | key5,key6 |
| 32057 | key2 |
由于32054挂了,我们看到32054的key3跑到32055去了,其他端口的缓存没有受到影响,这样就把缓存的重建代价降低了
memcached一致性哈希及php客户端实现的更多相关文章
- memcached 一致性哈希算法
本文转载自:http://blog.csdn.net/kongqz/article/details/6695417 一.概述 1.我们的memcache客户端使用了一致性hash算法ketama进行数 ...
- 10 Memcached 一致性哈希分布式算法原理与实现[PHP实现]
<?php header("Content-type:text/html;charset=utf-8"); interface hash{ public function _ ...
- Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比
准备工作: ① 配置文件 config.php ② 封装 Memcached 类 hash.class.php,包含普通哈希算法(取模)和一致性哈希算法 ③ 初始化 Memcached 节点信息 in ...
- Memcached 笔记与总结(5)Memcached 的普通哈希分布和一致性哈希分布
普通 Hash 分布算法的 PHP 实现 首先假设有 2 台服务器:127.0.0.1:11211 和 192.168.186.129:11211 当存储的 key 经过对 2 (2 台服务器)取模运 ...
- memcached分布式一致性哈希算法
<span style="font-family: FangSong_GB2312; background-color: rgb(255, 255, 255);">如果 ...
- Nginx网络架构实战学习笔记(四):nginx连接memcached、第三方模块编译及一致性哈希应用
文章目录 nginx连接memcached 第三方模块编译及一致性哈希应用 总结 nginx连接memcached 首先确保nginx能正常连接php location ~ \.php$ { root ...
- memcache 的内存管理介绍和 php实现memcache一致性哈希分布式算法
1 网络IO模型 安装memcached需要先安装libevent Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描 ...
- 一致性哈希算法——算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据
一致性哈希算法 摘自:http://blog.codinglabs.org/articles/consistent-hashing.html 算法简述 一致性哈希算法(Consistent Hashi ...
- 一致性哈希(consistent hashing)算法
文章同步发表在博主的网站朗度云,传输门:http://www.wolfbe.com/detail/201608/341.html 1.背景 我们都知道memcached服务器是不提供分布 ...
随机推荐
- Gradle sync failed 异常
今天开发过程中出现如下异常 Gradle sync failed: Connection timed out: connect. If you are behind an HTTP proxy, pl ...
- Web前端性能优化——如何有效提升静态文件的加载速度
WeTest 导读 此文总结了笔者在Web静态资源方面的一些优化经验. 一.如何优化 用户在访问网页时, 最直观的感受就是页面内容出来的速度,我们要做的优化工作, 也主要是为了这个目标.那么为了提高页 ...
- 史上最简单的MySQL安装教程之Linux(CentOS6.8)下安装MySQL5.6
一.准备 安装包:Percona-Server-5.6.21-70.0-r688-el6-x86_64-bundle.tar MySQL下载地址:http://www.percona.com/doc/ ...
- Docker 如何支持多种日志方案?- 每天5分钟玩转 Docker 容器技术(88)
将容器日志发送到 STDOUT 和 STDERR 是 Docker 的默认日志行为.实际上,Docker 提供了多种日志机制帮助用户从运行的容器中提取日志信息.这些机制被称作 logging driv ...
- SEO诊断之关于网站收录(转)
如何让网站被搜索引擎收录?我的网站有收录无排名怎么办?这些网站收录问题估计是seo最应关心的根本问题之一,网站收录都没有何来排名?我整理了每天咨询最多最具代表性的 8 个关于网站收录的问题及其答案统一 ...
- cocos-Lua中的class与require机制
cocos-Lua中的class与require机制 local layer = require("PaiGow.src.GamePlayerListLayer")local Ga ...
- Toxophily
Problem Description The recreation center of WHU ACM Team has indoor billiards, Ping Pang, chess and ...
- linq 在查询表达式中处理异常
在查询表达式的上下文中可以调用任何方法. 但是,我们建议避免在查询表达式中调用任何会产生副作用(如修改数据源内容或引发异常)的方法. 此示例演示在查询表达式中调用方法时如何避免引发异常,而不违反有关异 ...
- 高性能Ajax
XMLHttpRequest javascript 高性能的Ajax应该考虑数据传输技术和数据格式,以及其他的如数据缓存等优化技术. 一.请求数据 请求数据的常用技术有XHR,动态脚本注入.Mul ...
- 拓扑排序 HDU - 5695
众所周知,度度熊喜欢各类体育活动. 今天,它终于当上了梦寐以求的体育课老师.第一次课上,它发现一个有趣的事情.在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的ID,从1到NN,在排好队之 ...