• php实现一致性hash算法


    使用php实现一致性hash算法

    <?php
    
    use FlexihashHasherHasherInterface;
    use FlexihashHasherCrc32Hasher;
    
    use FlexihashException;
    
    /**
     * 参考:https://github.com/pda/flexihash
     * 一致性哈希算法实现
     * Class MyFlexiHash
     * 主要的方法有三个:addTarget、removeTarget、lookupList,其它都是语法糖
     * lookupList(key)的实现方式是在一个有序列表上先搜索大于key的部分,数量不够再从头选取元素进行补充
     */
    class MyFlexiHash {
    
    
        private $replicas = 64;
    
        private $hasher = null;
    
        private $positionTargetMap = array();
    
        private $targetPositionsMap = array();
    
        public function __construct(HasherInterface $hasher = null, $replicas = null)
        {
            $this->hasher = isset($hasher) ? $hasher : new Crc32Hasher();
            isset($replicas) && $this->replicas = $replicas;
        }
    
        public function addTarget($target, $weight = 1) {
            $positions = array();
            $existPositions = array_keys($this->positionTargetMap);
            for ($i = 0; $i < $this->replicas * $weight; $i++) {
                //find an position not in exist positions
                $suffix = '';
                do {
                    $suffix .= $i;
                    $position = $this->hasher->hash($target.''.$suffix);
                } while (in_array($position, $existPositions));
                //record position's target
                $this->positionTargetMap[$position] = $target;
                //collect position
                $positions[] = $position;
            }
            //sort position
            ksort($this->positionTargetMap);
            //record target's positions
            $this->targetPositionsMap[$target] = $positions;
        }
    
        public function removeTarget($target) {
            if (!isset($this->targetPositionsMap[$target])) {
                throw new Exception('remove not exists target: '.$target);
            }
            $positions = $this->targetPositionsMap[$target];
            //remove target's positions
            unset($this->targetPositionsMap[$target]);
            //remove position's target
            foreach ($positions as $position) {
                unset($this->positionTargetMap[$position]);
            }
        }
    
        public function lookup($resource) {
            return $this->lookupList($resource, 1)[0];
        }
    
        public function lookupList($resource, $count) {
            if ($this->isTargetsEmpty()) {
                throw new Exception('lookup targets empty');
            }
            if ($count > count($this->targetPositionsMap)) {
                throw new Exception('lookup targets not enough');
            }
            $targetList = array();
            $hash = $this->hasher->hash($resource);
            //find in the above positions
            foreach ($this->positionTargetMap as $position => $t) {
                if (count($targetList) == $count) {
                    break;
                }
                if ($hash >= $position) {
                    $targetList[] = $t;
                }
            }
            //find in the below positions
            if (count($targetList) < $count) {
                foreach ($this->positionTargetMap as $position => $t) {
                    if (count($targetList) == $count) {
                        break;
                    }
                    $targetList[] = $t;
                }
            }
            return $targetList;
        }
    
        public function isTargetsEmpty() {
            return count($this->targetPositionsMap) == 0;
        }
    
        public function addTargets($targets) {
            foreach ($targets as $target) {
                $this->addTarget($target);
            }
        }
    
        public function removeTargets($targets) {
            foreach ($targets as $target) {
                $this->removeTarget($target);
            }
        }
    }
    

     

  • 相关阅读:
    自己写的一些公共js方法
    node(03)--利用 HTTP 模块 URl 模块 PATH 模块 FS 模块创建一个 WEB 服务器
    node(03 fs文件模块)
    node (02 CommonJs 和 Nodejs 中自定义模块)顺便讲讲module.exports和exports的区别 dependencies 与 devDependencies 之间的区别
    node.js (01http 模块 url 模块)
    Ubuntu 16.04 下python2和python3及对应的pip的方法
    MySQL划重点-查询-聚合
    MySQL划重点-查询-条件
    MySQL命令
    使用Navicat for Mysql连接装在虚拟机Ubuntu16.04上的mysql服务器
  • 原文地址:https://www.cnblogs.com/livepeace/p/8952045.html
Copyright © 2020-2023  润新知