温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PHP实现一致性hash

发布时间:2020-06-22 23:20:03 来源:网络 阅读:799 作者:hgditren 栏目:软件技术
<?php

/**
 * 一致性哈希实现接口
 * Interface ConsistentHash
 */
interface ConsistentHash
{
    //将字符串转为hash值
    public function cHash(string $str): int;

    //添加一台服务器到服务器列表中
    public function addServer(string $serverHost);

    //从服务器删除一台服务器
    public function removeServer(string $serverHost);

    //在当前的服务器列表中找到合适的服务器存放数据
    public function lookup(string $key);
}

/**
 * 具体一致性哈希实现
 * author chenqionghe
 * Class MyConsistentHash
 */
class MyConsistentHash implements ConsistentHash
{
    public $serverList = []; //服务器列列表
    public $virtualPos = []; //虚拟节点的位置
    public $virtualPosNum = 5;  //每个节点对应5个虚节点

    /**
     * 将字符串转换成32位无符号整数hash值
     * @param $str
     * @return int
     */
    public function cHash(string $str): int
    {
        $str = md5($str);
        return sprintf('%u', crc32($str));
    }

    /**
     * 添加一台服务器到服务器列表中
     * @param $server 服务器IP地址
     * @return bool
     */
    public function addServer(string $server)
    {
        if (!isset($this->serverList[$server])) {
            //增加虚拟节点
            for ($i = 0; $i < $this->virtualPosNum; $i++) {
                $pos = $this->cHash($server . '#' . $i);

                //存放虚拟节点存放的对应的服务器
                $this->virtualPos[$pos] = $server;

                //存放单台服务器包含的所有节点
                $this->serverList[$server][] = $pos;
            }

            //虚拟节点根据位置排序
            ksort($this->virtualPos, SORT_NUMERIC);
        }
    }

    /**
     * 移除一台服务器(循环所有的虚节点,删除值为该服务器地址的虚节点)
     * @param $key
     * @return bool
     */
    public function removeServer($key)
    {
        if (isset($this->serverList[$key])) {

            //删除一台服务器上的所有虚节点
            foreach ($this->serverList[$key] as $pos) {
                unset($this->virtualPos[$pos]);
            }

            //删除对应服务器
            unset($this->serverList[$key]);
        }
    }

    /**
     * 在当前的服务器列表中找到合适的服务器存放数据
     * @param $key 键名
     * @return mixed 返回服务器IP地址
     */
    public function lookup(string $key)
    {
        $point = $this->cHash($key);//落点的hash值

        $finalServer = current($this->virtualPos);//先取圆环上最小的一个节点当成结果(数组的第一个索引单元)

        //找到虚拟节点最接近的服务器
        foreach ($this->virtualPos as $pos => $server) {
            if ($point <= $pos) {
                $finalServer = $server;
                break;
            }
        }
        reset($this->virtualPos);//重置圆环的指针为第一个(重置数组的指针)

        return $finalServer;
    }

}

$hashServer = new MyConsistentHash();
$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');
$hashServer->addServer('192.168.1.6');
$hashServer->addServer('192.168.1.7');
$hashServer->addServer('192.168.1.8');
$hashServer->addServer('192.168.1.9');
$hashServer->addServer('192.168.1.10');
echo "增加十台服务器192.168.1.1~192.168.1.10<br />";

echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';

echo "<pre>";
print_r($hashServer->virtualPos);
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI