一致性hash算法

来源:互联网 发布:安居客网络经纪人登陆 编辑:程序博客网 时间:2024/05/15 02:28

算法实现如下:

<?php// Consistent hash algorithm实现class ConsistentHash implements Countable{// 存储节点到hash值的映射, 便于删除节点private $nodeToHashPos = array();// 存储hash值到节点的映射private $hashPosToNode = array();// 虚拟节点数private $virtualNodeNumber = 32;// 节点数量private $nodeCount = 0;// 记录虚拟节点是否已排序private $isSort = false;// 返回节点数,count($this)public function count(){return $this->nodeCount;}// 计算hash值protected function _hash($key){// 使用int型节省内存,但是php的int都是有符号的,会产生负数return sprintf('%u', crc32($key));// return sprintf('%u', substr(md5($key),0,8));}// 添加节点public function addNode($nodeKey){// 已经存在的节点if(isset($this->nodeToHashPos[$nodeKey])){return false;}for($i = 0; $i < $this->virtualNodeNumber; $i++){$hash = $this->_hash($nodeKey . '#' . $i); //计算hash值$this->nodeToHashPos[$nodeKey][] = $hash;$this->hashPosToNode[$hash] = $nodeKey;}$this->nodeCount++; //节点数加一}// 批量添加节点public function addNodes($nodeKeys){if(!is_array($nodeKeys)){return false;}foreach($nodeKeys as $val){$this->addNode($val);}}// 移除节点public function removeNode($nodeKey){// 不存在的节点if(!isset($this->nodeToHashPos[$nodeKey])){return false;}foreach($this->nodeToHashPos[$nodeKey] as $key){unset($this->hashPosToNode[$key]);}unset($this->nodeToHashPos[$nodeKey]);$this->nodeCount --;}// 批量删除节点public function removeNodes($nodeKeys){if(!is_array($nodeKeys)){return false;}foreach($nodeKeys as $val){$this->removeNode($val);}}public function getAllNodes(){return array_keys($this->nodeToHashPos);}// 对 hashPosToNode 进行排序protected function sortHashToNodePos(){if(!$this->isSort){ksort($this->hashPosToNode, SORT_NUMERIC); //作为数字比较$this->isSort = true;}}// 计算应该落在哪个节点上public function lookupNode($key){// 没有一个节点if(empty($this->nodeToHashPos)){return false;}// 只有一个节点的时候直接返回第一个if($this->nodeCount == 1){return key($this->nodeToHashPos);}$hashKey = $this->_hash($key);$this->sortHashToNodePos();// 先取最小的值作为结果,确保当全部没有找到的时候,将资源的位置确定为有序位置的第一个(形成一个环)$result = current($this->hashPosToNode);foreach($this->hashPosToNode as $k=>$v){if($hashKey <= $k){$result = $v;break;}}reset($this->hashPosToNode); //重置数组指针return $result;}}

0 0
原创粉丝点击