您的位置:首页 > 数据库 > Memcache

Memcached 笔记与总结(6)PHP 实现 Memcached 的一致性哈希分布算法

2016-10-20 17:52 656 查看
首先创建一个接口,有 3 个方法:

addServer:添加一个服务器到服务器列表中

removeServer:从服务器列表中移除一个服务器

lookup:在当前的服务器列表中找到合适的服务器存放数据

interface distribute{
//在当前的服务器列表中找到合适的服务器存放数据
public function lookup($key);

//添加一个服务器到服务器列表中
public function addServer($server);

//从服务器列表中删除一个服务器
public function removeServer($server);
}


 

再定义一个接口把字符串转换为整数:

interface hash{
public function _hash($str);
}


 

创建类 consistentHash 继承以上两个接口,它有两个成员变量:

$serverList:保存的服务器列表

$isSorted:记录服务器列表是否已经排列过序

 

addServer 方法的实现:

public function addServer($server){
$hash = $this->_hash($server);

if (!isset($this->serverList[$hash])) {
//通过此Hash值定位服务器列表上的某个位置
$this->serverList[$hash] = $server;
}

//此时服务器列表发生了变化,因此标识为FALSE
$this->isSorted = FALSE;
return TRUE;
}


 

removeServer 方法的实现:

public function removeServer($server){
$hash = $this->_hash($server);

if (isset($this->serverList[$hash])) {
unset($this->serverList[$hash]);
}

$this->isSorted = FALSE;
return TRUE;
}


 

lookup 方法的实现:

public function lookup($key){
//计算出服务器的Hash值
$hash = $this->_hash($key);

//判断服务器列表是否排过序
if (!$this->isSorted) {
//倒序排列(把服务器列表装换成逆时针圆环)
krsort($this->serverList, SORT_NUMERIC);
$this->isSorted = TRUE;
}

//遍历服务器列表,找到合适的服务器并返回
foreach($this->serverList as $pos => $server){
if ($hash >= $pos) return $server;
}
return end($this->serverList);
}


 

完整代码:

<?php
//把字符串转换为整数
interface hash{ public function _hash($str); }

interface distribute{ //在当前的服务器列表中找到合适的服务器存放数据 public function lookup($key); //添加一个服务器到服务器列表中 public function addServer($server); //从服务器列表中删除一个服务器 public function removeServer($server); }

class consistentHash implements hash, distribute{

private $serverList = array();//保存的服务器列表
private $isSorted = FALSE; //记录服务器列表是否已经排列过序

public function _hash($str){
return sprintf('%u', crc32($str));//把字符串转成32为无符号整数
}

public function lookup($key){
//计算出服务器的Hash值
$hash = $this->_hash($key);

//判断服务器列表是否排过序
if (!$this->isSorted) {
//倒序排列(把服务器列表转换成逆时针圆环)
krsort($this->serverList, SORT_NUMERIC);
$this->isSorted = TRUE;
}

//遍历服务器列表,找到合适的服务器并返回
foreach($this->serverList as $pos => $server){
if ($hash >= $pos) return $server;
}
return end($this->serverList);
}

public function addServer($server){
$hash = $this->_hash($server);

if (!isset($this->serverList[$hash])) {
//通过此Hash值定位服务器列表上的某个位置
$this->serverList[$hash] = $server;
}

//此时服务器列表发生了变化,因此标识为FALSE
$this->isSorted = FALSE;
return TRUE;
}

public function removeServer($server){
$hash = $this->_hash($server);

if (isset($this->serverList[$hash])) {
unset($this->serverList[$hash]);
}

$this->isSorted = FALSE;
return TRUE;
}
}

$hashserver = new consistentHash();

$hashserver->addServer('192.168.1.1');
$hashserver->addServer('192.168.1.2');
$hashserver->addServer('192.168.1.3');
$hashserver->addServer('192.168.1.4');
$hashserver->addServer('192.168.1.5');

echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br />';
echo '=======================<br /><br />';

$hashserver->removeServer('192.168.1.2');
echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br />';
echo '=======================<br /><br />';

$hashserver->addServer('192.168.1.6');
echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br />';
echo '=======================<br /><br />';


输出:

save key1 on server:192.168.1.2
save key2 on server:192.168.1.5
=======================

save key1 on server:192.168.1.3
save key2 on server:192.168.1.5
=======================

save key1 on server:192.168.1.6
save key2 on server:192.168.1.5
=======================


结论:在增加或减少服务器的时候,一致性 Hash 算法只会改变很少一部分数据的存储服务器,从而减少了数据丢失的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: