版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013862108/article/details/83866111
一致性哈希的算法把取余算法的等于号来选择mem服务器变成了大于号来选择mem服务器,这应该是才是关键,可以使一个键的mem服务器落点变成是动态选择(一个服务器down掉然后选择crc32(key)后大于这个服务器的落点....)
添加虚拟节点,虚拟节点其实还是原来那几台服务器,每个虚拟节点都对应一个真实的服务器,起到分散节点的作用
原理如:关键点 hash环的理解和构建。
代码如下:libraries/MemCluster.php
<?php
/**
*/
//一致性hash
// 功能 添加节点; ;根据用户数据key 获取应该使用那台node
class MemCluster
{
protected $nodes = array();
protected $position = array();
protected $virtualNum=32; //每个节点有32个虚拟节点;具体数量也可以 16 ,8等
public function hash($str){
//将字符串转成32位符号整数
return sprintf("%u", crc32($str));
}
//查找key 落到哪个节点上
public function findNode($key){
$point = $this->hash($key);
//先取圆环上最小的一个节点
//$key 哈希后比最大的节点都大就放到第一个节点
$node = current($this->position);
//下面这个查找可以 后期优化为二分查找法。
foreach($this->position as $k=>$v){
if($point <= $k){
$node = $v;
break;
}
}
//复位数组指针
reset($this->position);
return $node;
}
public function addNode($node){
if(isset($this->nodes[$node])){
return;
}
for($i=0; $i<$this->virtualNum; $i++){
$pos = $this->hash($node.'-'.$i);
$this->position[$pos] = $node;
//方便删除对应的虚拟节点
$this->nodes[$node][] = $pos;
}
$this->sortPos();
}
public function delNode($node){
if(!isset($this->nodes[$node])){
return;
}
//删除对应的虚拟节点
foreach($this->nodes[$node] as $k){
unset($this->position[$k]);
}
unset($this->nodes[$node]);
}
protected function sortPos(){
//正常比较单元,不改变类型
ksort($this->position, SORT_REGULAR);
}
}
测试代码 如下:contoller/Mem.php
public function test(){
$this->load->library('memcluster');
$memServerArr = array('192.168.0.1:6666', '192.168.0.2:8888', '192.168.0.3:9999');
foreach ($memServerArr as $mem){
$this->memcluster->addNode($mem);
}
$key = "goods:1688";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "goods:1689";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "goods:1670";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "goods:1671";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "goods:1672";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "goods:1673";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "order:1673";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "order:1674";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "order:1675";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
$key = "post:1675";
$memNode = $this->memcluster->findNode($key);
echo $memNode,"<br/>";
}