一致性哈希
把各服务器节点映射放在钟表的各个时刻上,把 key 也映射到钟表的某个时刻上。该 key 沿钟表顺时针走,碰到的第 1 个节点即为该 key 的存储节点
实现:
<?php
//hash接口
interface hash{
public function _hash($key);
}
//分布式接口
interface distribution{
public function looup($key);
}
/**
*一致性哈希算法
*/
class Consistent implements hash,distribution{
public $nodes = [];//服务器节点
public $points = [];//服务器节点的虚拟节点
public $_mul = 64;//每个节点的虚拟节点数量
//hash方法
public function _hash($key){
return sprintf("%u",crc32($key));
}
//查找节点的方法
public function looup($key){
$hashKey = $this->_hash($key);
$target = current($this->points);
foreach ($this->points as $k => $v) {
if($k >= $hashKey){
$target = $v;
break;
}
}
reset($this->points);
return $target;
}
//添加服务器节点
public function addNode($node){
//判断服务器节点是否存在
if(isset($this->nodes[$node])){
return ;
}
//生成虚拟节点
for($i=1;$i<=$this->_mul;$i++){
$point = $this->_hash($node.$i);//虚拟节点的hash值
$this->points[$point] = $node;//将虚拟节点和服务器节点绑定
$this->nodes[$node][] = $point;//在服务器节点上添加对应的虚拟节点
}
$this->_sort();//将虚拟节点排序
}
//删除服务器节点
public function delNode($node){
foreach ($this->nodes[$node] as $p) {
unset($this->points[$p]);
}
unset($this->nodes[$node]);
}
//给虚拟节点排序
public function _sort(){
ksort($this->points,SORT_NUMERIC);
}
}
$con = new Consistent();
$con->addNode('a');
$con->addNode('b');
$con->addNode('c');
$con->addNode('d');
echo $con->looup('title');
echo $con->looup('name');
echo $con->looup('age');
首先创建一个Consistent类的实例,然后调用addNode方法,这个方法用于添加服务器节点,首先判断该节点是否存在,如果不存在,然后创建出来对应的虚拟节点,并添加上关联关系,最后将虚拟节点进行排序。
调用looup方法就可以查找key值落在的服务器,首先将key值hash,得到hash值,然后遍历所有的虚拟节点,找到第一个大于key的hash值的虚拟节点,并返回该虚拟节点所对应的服务器节点。