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

首先创建一个接口,有 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 算法只会改变很少一部分数据的存储服务器,从而减少了数据丢失的情况。

 

posted @ 2015-10-11 01:11  nemo20  阅读(800)  评论(0编辑  收藏  举报
访客数:AmazingCounters.com
2016/05/17 起统计