[php]对服务器进行一致性hash分布算法

<?php  
/** 
 * 对服务器进行一致性hash分布算法 
 */  
class HashRing  
{  
    private $servers = array();  
    private $nodeList = array();  
    private $nodeHashList = array();  
    private $nodeTotalNum = 0;  
    private $virtualNodeNum = 32;  
    private $keyHash = '';  
  
    public function __construct($servers)  
    {  
        $this->servers = $servers;  
        foreach ($servers as $server) {  
            for ($i = 0; $i < $this->virtualNodeNum; $i++) {  
                $this->nodeList[sprintf("%u", crc32($server.'-'.$i))] = array($server, $i);  
            }  
        }  
        ksort($this->nodeList);  
        $this->nodeHashList = array_keys($this->nodeList);  
    }  
  
    private function getNodeIndex($key)  
    {  
        $this->keyHash = sprintf("%u", crc32($key));  
        if ($this->keyHash > end($this->nodeHashList)) {  
            $this->keyHash = $this->keyHash % end($this->nodeHashList);  
        }  
        if ($this->keyHash <= reset($this->nodeHashList)) {  
            return 0;  
        }  
        $this->nodeTotalNum = count($this->nodeHashList);  
        return $this->binaryChopIndex(0, $this->nodeTotalNum);  
    }  
  
    private function binaryChopIndex($l=0, $r=0)  
    {  
        if ($l < $r) {  
            $avg = intval(($l+$r) / 2);  
            if ($this->nodeHashList[$avg] == $this->keyHash) {  
                return $avg;  
            } elseif ($this->keyHash < $this->nodeHashList[$avg] && ($avg > 0)) {  
                return $this->binaryChopIndex($l, $avg-1);  
            } else {  
                return $this->binaryChopIndex($avg+1, $r);  
            }  
        } else {  
            return $l;  
        }  
    }  
  
    public function getServersByKey($key, $num=1)  
    {  
        $index = $this->getNodeIndex($key);  
        $server = $this->nodeList[$this->nodeHashList[$index]];  
        if ($num == 1) {  
            return $server[0];  
        }  
        if ($num >= count($this->servers)) {  
            $num = count($this->servers);  
        }  
        $result = array($server[0]);  
        for ($i=$index+1; true; $i++) {  
            if ($i >= $this->nodeTotalNum) {  
                $i = 0;  
            }  
            $nextServer = $this->nodeList[$this->nodeHashList[$i]];  
            if (!in_array($nextServer[0], $result)) {  
                $result[] = $nextServer[0];  
            }  
            if (count($result) == $num) {  
                break;  
            }  
        }  
        return $result;  
    }  
}  
  
  
  
//示例  
$servers = array(  
    '127.0.0.1:11211',  
    '127.0.0.1:11212',  
    '127.0.0.1:11213',  
    '127.0.0.1:11214',  
    '127.0.0.1:11215'  
);  
$obj = new HashRing($servers);  
$servers = $obj->getServersByKey('testkey', 2);  
print_r($servers);  
echo "\n";  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值