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相关在线工具供大家参考使用:
在线散列/