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

时间: 2024-10-09 22:19:23

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

memcached 笔记之windows 7 下面 安装memcached 报错

windows 7 下面 安装memcached 报错 两种情况: 一:服务确实已经安装过 .如需要重新安装,当然是先memcached.exe -d uninstall 二:奇怪的是服务确实没有安装过的情况,在memcached.exe -d install也会出现上面定位报错.此时关掉cmd窗口  然后以管理员身份运行cmd,在执行上面的install,不出意外你会顺利的执行成功. 常用命令: 安装.卸载.启动.配置相关 -p 监听的端口 -l 连接的IP地址, 默认是本机 -d start

Memcached 笔记与总结(5)Memcached 的普通哈希分布和一致性哈希分布

普通 Hash 分布算法的 PHP 实现 首先假设有 2 台服务器:127.0.0.1:11211 和 192.168.186.129:11211 当存储的 key 经过对 2 (2 台服务器)取模运算得出该 key 应该保存到的服务器: <?php $server = array( array('host' => '127.0.0.1', 'port' => 11211), array('host' => '192.168.186.129', 'port' => 11211

Memcached 笔记与总结(9)Memcached 与 Session

一.Memcached 存储 Session 由于 Memcached 是分布式的内存对象缓存系统,因此可以用来实现 Session 同步:把 Web 服务器中的内存组合起来,成为一个“内存池”,不管是哪个服务器产生的 Sessoin 都可以放到这个“内存池”中,其他的 Web 服务器都可以使用.使用 Memcached 来同步 Session 的优点是:不会加大数据库的负担,并且安全性比 Cookie 高,把 Session 放到内存里面,读取速度比其他处理方式要快很多. 自定义使用 Memc

Memcached 笔记与总结(7)增加虚拟节点

仅仅把 Memcached 服务器集群地址通过一致性哈希转映射在圆环上,可能会出现数据不能均匀地分配给各台 Memcached 服务器. 解决方案是引入虚拟节点,就是把每个映射在圆环上的服务器地址(物理节点)转变成更多的(注:关于虚拟节点的个数参考①)虚拟节点. 修改 Memcached 笔记与总结(6)PHP 实现 Memcached 的一致性哈希分布算法 中的代码: 类 consistentHash 增加私有的成员属性:$position,以键值形式保存所有虚拟节点的哈希值(键)和对应的服务

Memcached笔记——(二)XMemcached&amp;Spring集成

今天研究Memcached的Java的Client,使用XMemcached 1.3.5,做个简单的测试,并介绍如何与Spring集成. 相关链接: Memcached笔记——(一)安装&常规错误&监控Memcached笔记——(二)XMemcached&Spring集成 Memcached笔记——(三)Memcached使用总结 Memcached笔记——(四)应对高并发攻击  一.Memcached Client简要介绍 Memcached Client目前有3种: Memca

memcached笔记

启动memcached:./memcached -d -m 10 -l 127.0.0.1 -p 11211 -u root 连接memcached:telnet 127.0.0.1 11211 查看memcached所有key:stats items 结果: STAT items:16:number 1 STAT items:16:age 195 STAT items:16:evicted 0 STAT items:16:evicted_nonzero 0 STAT items:16:evic

Memcached笔记——(一)安装&amp;常规错误&amp;监控

08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接: Memcached笔记——(一)安装&常规错误&监控Memcached笔记——(二)XMemcached&Spring集成 Memcached笔记——(三)Memcached使用总结 Memcached笔记——(四)应对高并发攻击  一.下载 1.Libevent 简单的说就是一个事件

Memcached笔记——(四)应对高并发攻击

近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Missing Loading前,强占这其中十几毫秒的时间,进行恶意攻击. 相关链接: Memcached笔记——(一)安装&常规错误&监控Memcached笔记——(二)XMemcached&Spring集成 Memcached笔记——(三)Memcached使用总结  Memcached

Memcached笔记——(三)Memcached使用总结

为了将N个前端数据同步,通过Memcached完成数据打通,但带来了一些新问题: 使用iBatis整合了Memcached,iBatis针对每台server生成了唯一标识,导致同一份数据sql会产生不同的key,造成重复缓存.——通过重写iBatis部分原码,终止了唯一标识的生成,同一个SQL产生同一个Key,同时对生成key做hash,控制长度,使得数据统一在Memcached. 为了迎合iBatis的架构,通过CacheModel模式,对缓存数据分组管理.最初通过Map实现CacheMode