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服务器是不提供分布 ...
随机推荐
- Python线程的常见的lock
IO阻塞分析: 下面该需求很简单将一个数值100做自减处到0.主函数中有0.1秒的IO阻塞 import threading import time def sub(): global num # 掌 ...
- Linux入门(12)——解决双系统下Ubuntu16.04不能访问Windows分区
解决办法一: 进入windows系统,关闭快速启动,关机. 解决办法二: 如果办法一不能解决问题,用这个办法. 查看盘符: sudo fdisk -l 需要在查看盘符后记下目标盘符的数字,比如想解除C ...
- 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)
文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...
- Linux.挖矿.cpuminer方法记录
挖矿一般都要用高端显卡做矿机, 不是一般人玩得起 这里讲的是一种用CPU来挖矿的方法, 纯玩玩, 不要指望能致富喔 本方法在CentOS和树莓派原生系统上测试通过 先从git下载cpuminer gi ...
- $(window).on("load",function(){} 和 $(document).ready(function() {}
$(window).on("load",function(){ //页面属性,图片,内容完全加载完,执行 } $(document).ready(function() { 或者$( ...
- 浅析C#中单点登录的原理和使用
什么是单点登录?我想肯定有一部分人"望文生义"的认为一个用户只能在一处登录.其实这是错误的理解(我记得我第一次也是这么理解的).单点登录指的是多个子系统只需要登录一个,其他系统不需 ...
- Django1.11搭建一个简易上传显示图片的后台
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 项目展示需要,之前没研究过Django,网上查资料快速做了一个后台,写下了防止自己忘了. p ...
- oracle赋值问题(将同一表中某一字段赋值给另外一个字段的语句)
将同一表中某一字段赋值给另外一个字段的语句update jxc_ckmx ckmx1 set ckmx1.ddsl = (select ckmx2.sl from jxc_ckmx ckmx2 whe ...
- 数据分析基础之Linalg的使用
Linear algebra 简介 When SciPy is built using the optimized ATLAS LAPACK and BLAS libraries, it has ve ...
- github和本地仓库关联
1.安装git 2.在github上注册账号 3.github上创建repository 4.克隆github上的repository 5.在target directory中右键打开git gui