Memcached的分布式算法
Memcache的分布式
memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。服务器端仅包括内存存储功能,其实现非常简单。至于memcached的分布式,则是完全由客户端程序库实现的。这种分布式是memcached的最大特点。
memcache的分布式原理
下面假设memcached服务器有node1~node3三台,应用程序要保存键名为'tokyo''kanagawa''chiba''saitama''gunma'
的数据。
首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存“tokyo”及其值。
同样,“kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存。
接下来获取保存的数据。获取时也要将要获取的键“tokyo”传递给函数库。函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值。
这样,将不同的键保存到不同的服务器上,就实现了memcached的分布式。memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行。
Memcache的hash策略配置
Memcache安装完成之后,可以设置哈希策略,memcache.hash_strategy。目前有standard模式和consistent模式。standard模式其实就是%,即取模。而consistent,就是hash的一致性算法。
在Memcache中,hash策略在PHP.ini文件中设置
[Memcache] Memcache.allow_failover = 1 …… …… Memcache.hash_strategy =consistent Memcache.hash_function =crc32
在Memcached中,hash策略在PHP的参数中设置:
$mem = new memcached(); $mem->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT); $mem->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true);
memcache分布式算法
1.余数分散法
余数分散法,就是“根据服务器台数的余数进行分散”。 求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器。
在PHP客户端中,默认采用该算法,也可以在php.ini中设置
Memcached::OPT_DISTRIBUTION=Memcached::DISTRIBUTION_MODULA。
余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。 那就是当添加或移除服务器时,缓存重组的代价相当巨大。 添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器, 从而影响缓存的命中率。为了在解决这个问题,实现了另一种分布式算法,hash一致性算法。
实例:
<?php $m = new Memcached(); $m->addServers(array( array('127.0.0.1', 11211, 90), array('127.0.0.1', 11212, 70), )); $m->setOption(Memcached::OPT_HASH, Memcached::HASH_CRC); $m->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); for ($i = 0; $i < 100; $i++) { $key = "k_$i"; $m->set($key, 'v_' . $key); }
2.hash一致性算法(Consistent Hashing)
Consistent Hashing如下所示:首先求出memcached服务器(节点)的哈希值,并将其配置到0~2^32的圆(continuum)上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。 然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2^32仍然找不到服务器,就会保存到第一台memcached服务器上。
在php客户端中在php.ini中设置
Memcached::OPT_DISTRIBUTION=Memcached::DISTRIBUTION_CONSISTENT
从如上的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化 而影响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响。
因此,Consistent Hashing最大限度地抑制了键的重新分布。 而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想。 使用一般的hash函数的话,服务器的映射地点的分布非常不均匀。因此,使用虚拟节点的思想,为每个物理节点(服务器)在continuum上分配100~200个点。这样就能抑制分布不均匀, 最大限度地减小服务器增减时的缓存重新分布。
目前Consistent Hashing基本成为了分布式系统组件的标准配置
实例:
<?php $m = new Memcached(); $m->addServers(array( array('127.0.0.1', 11211, 90), array('127.0.0.1', 11212, 70), )); $mem->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT); $mem->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true); for ($i = 0; $i < 100; $i++) { $key = "k_$i"; $m->set($key, 'v_' . $key); }