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

  • 相关阅读:
    Redis-内存优化(一)
    window激活
    ArrayDeque原理详解
    CountDownLatch原理详解
    DelayQueue延迟队列原理剖析
    浅析PriorityBlockingQueue优先级队列原理
    修改QT库的路径
    数据同步Datax与Datax_web的部署以及使用说明
    HTTP头的Expires与Cache-control
    python生成随机数、随机字符串
  • 原文地址:https://www.cnblogs.com/dee0912/p/4865564.html
Copyright © 2011-2022 走看看