普通 Hash 分布算法的 PHP 实现

首先假设有 2 台服务器:127.0.0.1:11211 和 192.168.186.129:11211

当存储的 key 经过对 2 (2 台服务器)取模运算得出该 key 应该保存到的服务器:

<?php
$server = array(
array('host' => '127.0.0.1', 'port' => 11211),
array('host' => '192.168.186.129', 'port' => 11211),
); $key = 'TheKey';
$value = 'TheValue'; //假设是两台服务器
$sc = $server[crc32($key) % 2];
var_dump($sc);//得出该 key 应保存在第一台服务器上 $mc = new Memcache();
$mc->connect($sc['host'], $sc['port']);
$mc->set($key, $value);

var_dump($sc) 输出的结果是:

array
'host' => string '127.0.0.1' (length=9)
'port' => int 11211

此时使用 telnet 连接本机(127.0.0.1:11211)的 Memcached 服务器,get 该 key:

再当 key 应该存储到第二台服务器上时:

<?php
$server = array(
array('host' => '127.0.0.1', 'port' => 11211),
array('host' => '192.168.186.129', 'port' => 11211),
); $key = 'TheKey%';
$value = 'TheValueSecond'; //假设是两台服务器
$sc = $server[crc32($key) % 2];
var_dump($sc);//得出该 key 应保存在第二台服务器上 $mc = new Memcache();
$mc->connect($sc['host'], $sc['port']);
$mc->set($key, $value);

var_dump($sc) 输出的结果是:

array
'host' => string '192.168.186.129' (length=15)
'port' => int 11211

此时使用 telnet 连接虚拟机(192.168.186.129:11211)的 Memcached 服务器,get 该 key:

普通 Hash 分布的缺点是:当服务器数量发生变化时,同一个 key 经过 Hash 之后,与服务器取模的结果跟没有增加或减少服务器之前的结果可能会不一样。例如:原来有 8 台服务器,宕掉 1 台之后,还剩 7 台,则 8 台服务器 $key % 8 = 0,$key % 7 = 0,此时为命中(hits);如果 $key % 8 = 0,%key % 7 = 1,则此时 miss。

为了把丢失的数据减小到最少,可以使用 一致性哈希算法(Consistent Hashing)。

一致性哈希算法

step 1. 将一个 32 位的整数(0~2^32 - 1)想象成一个环,0 作为圆环的头,2^32 - 1 作为圆环的尾。

step 2. 通过 Hash 函数把 key 处理成整数:

$key1 = crc32($key1);
$key2 = crc32($key2);
$key3 = crc32($key3);
$key4 = crc32($key4);

step 3. 把 Memcached 群映射到环上。使用 Hash 函数把服务器的 IP 地址处理成整数:

$server1 = crc32('127.0.0.1');
$server2 = crc32('192.168.186.129');
$server3 = crc32('192.168.186.130');

通过以上步骤,把 key 和 服务器都映射到环上。

step 4. 把数据映射到服务器上。

如图,key1 落在了 server 3 上,key 4 和 key 3 落在了 server 2 上,key 2 落在了 server 1 上。

step 5. 移除服务器

当 server 2 宕机了,受到影响的仅仅是圆环上 server 3 和 server 2 之间的数据(key 3 和 key 4),即映射到 server 2 的数据。

step 6. 添加服务器

如果要增加 server 4,通过映射,它将出现在 key 3 和 key 4 之间,则此时受到影响的将是 server 3 和 server 4 之间的数据(key 4)。把 key 4 重新映射到 server 4 上即可。

Memcached 笔记与总结(5)Memcached 的普通哈希分布和一致性哈希分布的更多相关文章

  1. Memcached笔记——(三)Memcached使用总结

    为了将N个前端数据同步,通过Memcached完成数据打通,但带来了一些新问题: 使用iBatis整合了Memcached,iBatis针对每台server生成了唯一标识,导致同一份数据sql会产生不 ...

  2. Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比

    准备工作: ① 配置文件 config.php ② 封装 Memcached 类 hash.class.php,包含普通哈希算法(取模)和一致性哈希算法 ③ 初始化 Memcached 节点信息 in ...

  3. Memcached笔记——(四)应对高并发攻击【转】

    http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...

  4. Memcached笔记——(四)应对高并发攻击

    近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...

  5. Memcached笔记——(二)XMemcached&Spring集成

    今天研究Memcached的Java的Client,使用XMemcached 1.3.5,做个简单的测试,并介绍如何与Spring集成. 相关链接: Memcached笔记--(一)安装&常规 ...

  6. Memcached笔记——(一)安装&常规错误&监控

    08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接: ...

  7. Linux实战教学笔记32:企业级Memcached服务应用实践

    一, Memcached介绍 1.1 Memcached与常见同类软件对比 (1)Memcached是什么? Memcached是一个开源的,支持高性能,高并发的分布式内存缓存系统,由C语言编写,总共 ...

  8. Memcached 笔记与总结(7)增加虚拟节点

    仅仅把 Memcached 服务器集群地址通过一致性哈希转映射在圆环上,可能会出现数据不能均匀地分配给各台 Memcached 服务器. 解决方案是引入虚拟节点,就是把每个映射在圆环上的服务器地址(物 ...

  9. Memcached 笔记与总结(9)Memcached 与 Session

    一.Memcached 存储 Session 由于 Memcached 是分布式的内存对象缓存系统,因此可以用来实现 Session 同步:把 Web 服务器中的内存组合起来,成为一个“内存池”,不管 ...

随机推荐

  1. 【Android 进阶】临时卸载root和恢复root功能

    [前言]为什么有这个需求? Q:首先,谈谈为啥想要root呢? A:有root才能有控制权,也才能折腾很多东西,比如:删删流氓软件,用用代理.软件自动安装等: Q:然后,那么为何又需要删除root呢? ...

  2. JS输入框邮箱自动提示(带有demo和源码)(转载)

    今天在javascriptQQ群里面 有童鞋问到 有没有 "JS输入框邮箱自动提示"插件,即说都找遍了github上源码 都没有看到这样类似的插件,然后我想了下 "JS输 ...

  3. POJ3264Balanced Lineup 线段树练手

    题目意思:给定Q(1<=Q<=200000)个数A1,A2,```,AQ,多次求任一区间Ai-Aj中最大数和最小数的差 #include <iostream> #include ...

  4. org.apache.flume.FlumeException: NettyAvroRpcClient { host: xxx.xxx.xxx.xxx, port: 41100 }: RPC

    2014-12-19 01:05:42,141 (lifecycleSupervisor-1-1) [WARN - org.apache.flume.sink.AbstractRpcSink.star ...

  5. intersection

    用来找到两个rdd的交集,注意,最终的new rdd的分区数量取决于两个rdd中的最大分区数量. 测试一下: val data1 = sc.parallelize(1 to 20,1) val dat ...

  6. yuv rgb 像素格式1

    ===========大小============= 一般,直接采集到的视频数据是RGB24的格式 RGB24一帧的大小size=width×heigth×3 Byte, RGB32的size=wid ...

  7. push和join

    Push,向数组末尾添加元素,并返回长度. Join,将数组按照join参数连接起来. 不同浏览器对JS解析不同,Join比连接字符串快,要用大量数据测试,然后比时间.

  8. 贪心 Codeforces Round #301 (Div. 2) B. School Marks

    题目传送门 /* 贪心:首先要注意,y是中位数的要求:先把其他的都设置为1,那么最多有(n-1)/2个比y小的,cnt记录比y小的个数 num1是输出的1的个数,numy是除此之外的数都为y,此时的n ...

  9. WPF之TextBox

    1. TextBox实现文字垂直居中 TextBox纵向长度比较长但文字字体比较小的时候,在输入时就会发现文字不是垂直居中的. 而使用中我们发现,TextBox虽然可以设置文字的水平对齐方式,但却没有 ...

  10. cocos2d CCDictionary

    CCDictionary* dict=CCDictionary::create(); CCString* str1=CCString::create("); CCString* str2=C ...