PHP实现的一致性HASH算法示例
本文实例讲述了PHP实现的一致性HASH算法。分享给大家供大家参考,具体如下:
//+----------------------------------------------------------------------
//|Datetime:2017-01-1116:01:36
//+----------------------------------------------------------------------
//|Copyright:PerfectIsShit
//+----------------------------------------------------------------------
classConsistentHashing
{
//圆环
//hash->节点
private$_ring=array();
//所有节点
//节点->hash
public$nodes=array();
//每个节点的虚拟节点
public$virtual=64;
/**
*构造
*@paramarray$nodes初始化的节点列表
*/
publicfunction__construct($nodes=array())
{
if(!empty($nodes)){
foreach($nodesas$value){
$this->addNode($value);
}
}
}
/**
*获取圆环内容
*@returnarray$this->_ring
*/
publicfunctiongetRing()
{
return$this->_ring;
}
/**
*time33函数
*@paramstring$str
*@return32位正整数
*@author大神们
*/
publicfunctiontime33($str)
{
//hash(i)=hash(i-1)*33+str[i]
//$hash=5381;##将hash设置为0,竟然比设置为5381分布效果更好!!!
$hash=0;
$s=md5($str);//相比其它版本,进行了md5加密
$seed=5;
$len=32;//加密后长度32
for($i=0;$i<$len;$i++){
//(hash<<5)+hash相当于hash*33
//$hash=sprintf("%u",$hash*33)+ord($s{$i});
//$hash=($hash*33+ord($s{$i}))&0x7FFFFFFF;
$hash=($hash<<$seed)+$hash+ord($s{$i});
}
return$hash&0x7FFFFFFF;
}
/**
*增加节点
*@paramstring$node节点名称
*@returnobject$this
*/
publicfunctionaddNode($node)
{
if(in_array($node,array_keys($this->nodes))){
return;
}
for($i=1;$i<=$this->virtual;$i++){
$key=$this->time33($node.'-'.$i);
$this->_ring[$key]=$node;
$this->nodes[$node][]=$key;
}
ksort($this->_ring,SORT_NUMERIC);
return$this;
}
/**
*获取字符串的HASH在圆环上面映射到的节点
*@paramstring$key
*@returnstring$node
*/
publicfunctiongetNode($key)
{
$node=current($this->_ring);
$hash=$this->time33($key);
foreach($this->_ringas$key=>$value){
if($hash<=$key){
$node=$value;
break;
}
}
return$node;
}
/**
*获取映射到特定节点的KEY
*此方法需手动调用,非特殊情况不建议程序中使用此方法
*@paramstring$node
*@paramstring$keyPre
*@returnmixed
*/
publicfunctiongetKey($node,$keyPre=""){
if(!in_array($node,array_keys($this->nodes))){
returnfalse;
}
$result=false;
for($i=1;$i<=10000;$i++){
$key=$keyPre.md5(rand(1000,9999));
if($this->getNode($key)==$node){
$result=true;
break;
}
}
return$result?$key:false;
}
}
$ch_obj=newConsistentHashing();
$ch_obj->addNode('node_1');
$ch_obj->addNode('node_2');
$ch_obj->addNode('node_3');
$ch_obj->addNode('node_4');
$ch_obj->addNode('node_5');
$ch_obj->addNode('node_6');
//+----------------------------------------------------------------------
//|查看key映射到的节点
//+----------------------------------------------------------------------
$key1="asofiwjamfdalksjfkasasdflasfja";
$key2="jaksldfjlasfjsdjfioafaslkjflsadkjfl";
$key3="asjldflkjasfsdjflkajkldsjfksajdlflajs";
$key4="iowanfasijfmasdnfoas";
$key5="pqkisndfhoalnfiewlkl";
$key6="qjklasjdifoajfalsjflsa";
echosprintf("%-50s映射到节点%s\n",$key1,$ch_obj->getNode($key1));
echosprintf("%-50s映射到节点%s\n",$key2,$ch_obj->getNode($key2));
echosprintf("%-50s映射到节点%s\n",$key3,$ch_obj->getNode($key3));
echosprintf("%-50s映射到节点%s\n",$key4,$ch_obj->getNode($key4));
echosprintf("%-50s映射到节点%s\n",$key5,$ch_obj->getNode($key5));
echosprintf("%-50s映射到节点%s\n",$key6,$ch_obj->getNode($key6));
//+----------------------------------------------------------------------
//|查看圆环和节点信息
//+----------------------------------------------------------------------
//var_dump($ch_obj->getRing());
//var_dump($ch_obj->nodes);
//+----------------------------------------------------------------------
//|获取特定节点的KEY
//+----------------------------------------------------------------------
//$key1=$ch_obj->getKey('node_1','pre_');
//var_dump($key1);
//+----------------------------------------------------------------------
//|测试分布
//+----------------------------------------------------------------------
//$keys=array();
//$rings=array();
//for($i=1;$i<=60000;$i++){
//$key=sha1(rand(1000000,9999999));
//$node=$ch_obj->getNode($key);
//$rings[$node]=isset($rings[$node])?++$rings[$node]:1;
//}
//var_dump($rings);
运行结果:
asofiwjamfdalksjfkasasdflasfja映射到节点node_1 jaksldfjlasfjsdjfioafaslkjflsadkjfl映射到节点node_2 asjldflkjasfsdjflkajkldsjfksajdlflajs映射到节点node_1 iowanfasijfmasdnfoas映射到节点node_2 pqkisndfhoalnfiewlkl映射到节点node_3 qjklasjdifoajfalsjflsa映射到节点node_5
PS:这里再为大家提供2款hash相关在线工具供大家参考使用:
在线散列/