<?php//原理概念请看我的上一篇随笔(http://www.cnblogs.com/tujia/p/5416614.html)或直接百度
/**
* 接口:hash(哈希插口)、distribution(分布式算法接口)
* 方法:
* hash
* _hash,处理并返回一个字符串的哈希值
* distribution
* _lookup:给它一个key,它要反正此key需要存取的目标服务器信息
*
*
* 一致性哈希分布式算法类:ConsistentHash
* 方法:
* addServ: 添加服务器
* addPos: 添加”虚拟节点“
* sortPos: 对所有”虚拟节点“进行排序,形成集群圈
* _hash: 实现插口的_hash方法
* _lookup: 实现插口的_lookup方法
*
* 测试用方法
* printServ: 打印集群中的服务器列表信息
* printPos: 打印集群中的虚拟节点列表信息
* decServ: 删除一台服务器及他的所有虚拟节点
*/
interface hash{
public function _hash($str);
}
interface distribution{
public function _lookup($key);
}
/**
* 一致性哈希算法类
*/
class ConsistentHash implements hash,distribution
{
protected $mem_serv = array();//服务器列表
protected $node_pos = array();//所有虚拟节点
protected $mul = 64;//第一台服务器弄64个虚拟节点
/**
* 添加服务器
* @param array $serv_info 服务器配置信息,格式为:array('host':'127.0.0.1', 'port':11211);
*/
public function addServ($serv_info){
if(!is_array($serv_info) || !isset($serv_info['host']) || !isset($serv_info['port'])) return false;
$str = $serv_info['host'] .':'. $serv_info['port'];
$serv_key = $this->_hash($str);
//记录服务器信息
$this->mem_serv[$serv_key] = $serv_info;
//添加虚拟节点
$this->addPos($serv_key);
return true;
}
/**
* 添加虚拟节点
* @param string $serv_key 服务器的key
*/
protected function addPos($serv_key){
for($i=0; $i<$this->mul; $i++){
$pos = 'node_' . $serv_key . '_' . $i;
$pos_hash = $this->_hash($pos);
$this->node_pos[$pos_hash] = $serv_key;
}
$this->sortPos();
return true;
}
/**
* 对所有虚拟节点进行排序
*/
protected function sortPos(){
return ksort($this->node_pos);
}
/**
* 对字符串进行hash处理,返回其整数无符号整数值
* @param string $str 要进行处理的字符串
*/
public function _hash($str){
return sprintf("%u", crc32($str));
}
/**
* 通过key计算它的落点服务器信息
* @param string $key 键
*/
public function _lookup($key){
$key_hash = $this->_hash($key);
$serv_key = key($this->mem_serv);
foreach ($this->node_pos as $pos=>$serv) {
if($key_hash<=$pos){
$serv_key = $serv;
break;
}
}
return $this->mem_serv[$serv_key];
}
/**
* 以下的方法做为测试用
*/
/**
* 打印服务器列表
* @return [type] [description]
*/
public function printServ(){
echo '<pre>';
print_r($this->mem_serv);
echo '</pre>';
}
public function printPos(){
echo '<pre>';
print_r($this->node_pos);
echo '</pre>';
}
/**
* 删除一个服务器及它的所有虚拟节点
* @param int $serv_key 服务器的hash值
*/
public function decServ($serv_key=''){
if(empty($serv_key)) $serv_key = key($this->mem_serv);
unset($this->mem_serv[$serv_key]);
return true;
}
}
//测试
/*$dis = new ConsistentHash();
$dis->addServ(array('host'=>'127.0.0.1', 'port'=>11211));
$dis->addServ(array('host'=>'127.0.0.1', 'port'=>11212));
$dis->addServ(array('host'=>'127.0.0.1', 'port'=>11213));
$dis->addServ(array('host'=>'127.0.0.1', 'port'=>11214));
$dis->addServ(array('host'=>'127.0.0.1', 'port'=>11215));
$dis->printServ();
$dis->printPos();
print_r($dis->_lookup('name'));
print_r($dis->_lookup('age'));
print_r($dis->_lookup('sex'));
print_r($dis->_lookup('height'));
print_r($dis->_lookup('weight'));*/
?>