首页 NoSQL Memcache 正文

Memcached 一致性哈希算法

金鹏头像 金鹏 Memcache 2022-10-26 11:10:19 0 837
导读:通俗理解一致性哈希把各服务器节点映射放在钟表的各个时刻上,把key也映射到钟表的某个时刻上.该key沿钟表顺时针走,碰到的第1个节点即为该key的存储节点疑问...

通俗理解一致性哈希
把各服务器节点映射放在钟表的各个时刻上, 把 key 也映射到钟表的某个时刻上. 该 key 沿钟表顺时针走,碰到的第 1 个节点即为该 key 的存储节点

图片.png


疑问 1: 时钟上的指针最大才 11 点,如果我有上百个 memcached 节点怎么办?
答: 时钟只是为了便于理解做的比喻,在实际应用中,我们可以在圆环上分布[0,2^32-1]的数字, 这样,全世界的服务器都可以装下了.

疑问 2: 我该如何把”节点名”,”键名”转化成整数?
答: 你可以用现在的函数,如 crc32(),也可以自己去设计转化规则,但注意转化后的碰撞率要低. 即不同的节点名,转换为相同的整数的概率要低. 一致性哈希对其他节点的影响通过图可以看出,当某个节点 down 后,只影响该节点顺时针之后的 1 个节点,而其他节点 不受影响.因此,Consistent Hashing 最大限度地抑制了键的重新分布

图片.png




一致性哈希+虚拟节点对缓存命中率的影响
由图中可以看到,理想状态下, 1) 节点在圆环上分配分配均匀,因此承担的任务也平均,但事实上, 一般的 Hash 函数对于节 点在圆环上的映射,并不均匀. 2) 当某个节点 down 后,直接冲击下 1 个节点,对下 1 个节点冲击过大,能否把 down 节点上的 压力平均的分担到所有节点上? 完全可以—引入虚拟节点来达到目标 虚拟节点即----N 个真实节点,把每个真实节点映射成 M 个虚拟节点, 再把 M*N 个虚拟节点, 散列在圆环上. 各真实节点对应的虚拟节点相互交错分布 这样,某真实节点 down 后,则把其影响平均分担到其他所有节点上

图片.png


<?php
/**
 * 一致性哈希
 *
 * @author jinpeng
 * @date 2022/10/26
 */

class Content{

    protected $_node = [];
    protected $_position = [];
    protected $_mul = 64; //散列成64个虚拟节点

    // 查找key所处的位置
    public function find($key)
    {
        $point = $this->_hash($key);

        echo "<br/>";
        echo 'key节点位置:'. $point;
        echo "<br/>";

        $node = current($this->_position);
        foreach ($this->_position as $key => $item)
        {
            if ($point <= $key)
            {
                $node = $item;
                break;
            }
        }

        return $node;
    }

    // 排序节点
    protected function _sortNode()
    {
        ksort($this->_position, SORT_REGULAR);
    }

    // 新增节点
    public function addNode($node)
    {
        // 分布散列点
        for ($i =1; $i < $this->_mul; $i ++)
        {
            $posName = $node . '_' . $i;
            $this->_position[$this->_hash($posName)] = $node;
        }

        $this->_sortNode();
    }

    // 删除节点
    public function delNode($node)
    {
        foreach ($this->_position as $key => $item)
        {
            if ($node == $item)
            {
                unset($this->_position[$key]);
            }
        }
    }

    protected function _hash($str)
    {
        return sprintf("%u", crc32($str)); // 无符号的 0-2^32
    }


    // 测试方法
    public function getPosition()
    {
        echo "<pre>";
        print_r($this->_position);
    }
}


$con = new Content();
$con->addNode('a');
$con->addNode('b');
$con->addNode('c');

$con->getPosition();

echo '获取到环上节点:'. $con->find('name');


本文地址:https://www.jinpeng.work/?id=143
若非特殊说明,文章均属本站原创,转载请注明原链接。
广告3

欢迎 发表评论:

  • 请填写验证码

日历

«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930

控制面板

您好,欢迎到访网站!
  查看权限
广告2

退出请按Esc键