普通Hash分布简介
普通Hash分布比较简单,Hash函数大致如下:
function mHash($key){
$md5 = substr(md5($key),0,8);
$seed = 31;
$hash = 0;
for($i = 0; $i < 8; $i++){
$hash = $hash*$seed + ord($md5{$i});
$i++;
}
return $hash & 0x7FFFFFFF;
}
首先通过md5把key处理成一个32位的字符串,取其前8位。再经过Hash算法处理成一个整数并返回,然后映射到其中一台Memcached服务器。
假设配置两台Memcached服务器,可以使用下面的代码映射:
<?php
$servers = array(
array('127.0.0.1',11211),
array('127.0.0.2',11211),
);
/*需要设置的key*/
$key = "TheKey";
/*需要设置的value*/
$value = "TheValue";
/*求出用第几台服务器(通过Hash函数吧key转化成整数后,利用这个整数与Memcached服务器数量取模)*/
$sc = $servers[mHash($key)%2];
$m = new Memcached();
$m ->addServers(array($sc));
$m -> set($key,$value,0);
这样就完成了分布式的配置。取数据跟保存数据的方法一样,把set命令给为get命令就可以了。
例如:
有两台服务器,编号:0,1
有3个数,1,2,3
1%2=1;存入1号
2%2=0;存入0号
3%2=1;存入1号
普通Hash分布缺点分析
假如有8台Memcached服务器,其中存放的内容分别如下所示
突然down掉一台服务器
则此时,服务器数量为7,即更改为除7取余,那么问题来了:
当使用get获取数据时
key1%8=1,key1%7=1 hit
…
key6%8=6,key6%7=6 hit
key8%8=0,key8%7=1 miss
key9%8=1,key9%7=2 miss
…
key55%8=7,key55%7=6 miss
key56%8=0,key56%7=0 hit
可以看出,命中率大大降低
所以,命中率会在服务器down的短期内,急剧降低。服务器越多,则down机造成的后果越严重。
同理,增加一台服务器,也会造成同样的结果。