Memcached的分布式算法

memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。服务器端仅包括内存存储功能,其实现非常简单。至于memcached的分布式,则是完全由客户端程序库实现的。这种分布式是memcached的最大特点
下面假设memcached服务器有node1~node3三台,应用程序要保存键名为“yale”的数据,首先向memcached中添加“yale”。将“yale”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存“yale”及其值, 接下来获取保存的数据。获取时也要将要获取的键“yale”传递给函数库。函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值,这样,将不同的键保存到不同的服务器上,就实现了memcached的分布式。 memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行,但需要注意一些问题:
1、 当选择的服务器无法连接时,会将连接次数添加到键之后,再次计算哈希值并尝试连接。这个动作称为rehash。不希望rehash时可以在生成对象时指定“rehash => 0”选项。
2、 当添加或移除服务器时,缓存重组的代价相当巨大。添加服务器后,算法可能会影响服务器的选择,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率。

Consistent Hashing
Consistent Hashing如下所示:首先求出memcached服务器(节点)的哈希值,并将其配置到0~2SUP(32)的圆(continuum)上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2SUP(32)仍然找不到服务器,就会保存到第一台memcached服务器上。


从上图的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化而影响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响。


因此,Consistent Hashing最大限度地抑制了键的重新分布。而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想。使用一般的hash函数的话,服务器的映射地点的分布非常不均匀。因此,使用虚拟节点的思想,为每个物理节点(服务器)在continuum上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。
通过下文中介绍的使用Consistent Hashing算法的memcached客户端函数库进行测试的结果是,由服务器台数(n)和增加的服务器台数(m)计算增加服务器后的命中率计算公式如下:(1 - n/(n+m)) * 100