zoukankan      html  css  js  c++  java
  • Memcached一致性哈希算法

    通俗理解一致性哈希

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

    疑问 1: 时钟上的指针最大才 11 点,如果我有上百个 memcached 节点怎么办?
    答: 时钟只是为了便于理解做的比喻,在实际应用中,我们可以在圆环上分布[0,2^32-1]的数字, 这样,全世界的服务器都可以装下了. 疑问 2: 我该如何把”节点名”,”键名”转化成整数?
    答: 你可以用现在的函数,如 crc32().
    也可以自己去设计转化规则,但注意转化后的碰撞率要低. 即不同的节点名,转换为相同的整数的概率要低.

    一致性哈希对其他节点的影响

    通过图可以看出,当某个节点 down 后,只影响该节点顺时针之后的 1 个节点,而其他节点

    不受影响.因此,Consistent Hashing 最大限度地抑制了键的重新分布

     一致性哈希+虚拟节点对缓存命中率的影响

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

     

    <?php
    

    class Hash
    {

    </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$nodeS</span> =<span style="color: #000000;"> [];
    </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$num</span> = 64<span style="color: #000000;">;
    </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$virtualNodeS</span> =<span style="color: #000000;"> [];
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">需要把字符串转换为正整数</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> strToInt(<span style="color: #800080;">$str</span><span style="color: #000000;">)
    {
        </span><span style="color: #0000ff;">return</span> <span style="color: #008080;">sprintf</span>('%u', <span style="color: #008080;">crc32</span>(<span style="color: #800080;">$str</span><span style="color: #000000;">));
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> findServer(<span style="color: #800080;">$key</span><span style="color: #000000;">)
    {
        </span><span style="color: #800080;">$point</span> = <span style="color: #800080;">$this</span>-&gt;strToInt(<span style="color: #800080;">$key</span><span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">foreach ($this-&gt;nodeS as $k =&gt; $v) {</span>
        <span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>-&gt;virtualNodeS <span style="color: #0000ff;">as</span> <span style="color: #800080;">$k</span> =&gt; <span style="color: #800080;">$v</span><span style="color: #000000;">) {
            </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$point</span> &lt;= <span style="color: #800080;">$k</span><span style="color: #000000;">) {
                </span><span style="color: #800080;">$node</span> = <span style="color: #800080;">$v</span><span style="color: #000000;">;
                </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;
            }
        }
    
        </span><span style="color: #800080;">$node</span> = <span style="color: #800080;">$node</span> ?: <span style="color: #008080;">reset</span>(<span style="color: #800080;">$this</span>-&gt;<span style="color: #000000;">nodeS);
        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$node</span><span style="color: #000000;">;
    
    
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> addServer(<span style="color: #800080;">$node</span><span style="color: #000000;">)
    {
    
        </span><span style="color: #008000;">/*</span><span style="color: #008000;">$this-&gt;nodeS[$this-&gt;hashStr($node)] = $node;
        ksort($this-&gt;nodeS);</span><span style="color: #008000;">*/</span>
        <span style="color: #0000ff;">for</span> (<span style="color: #800080;">$i</span> = 1; <span style="color: #800080;">$i</span> &lt;= <span style="color: #800080;">$this</span>-&gt;num; <span style="color: #800080;">$i</span>++<span style="color: #000000;">) {
    
            </span><span style="color: #800080;">$this</span>-&gt;virtualNodeS[<span style="color: #800080;">$this</span>-&gt;strToInt(<span style="color: #800080;">$node</span>['host'] . '_' . <span style="color: #800080;">$node</span>['port'] . '_' . <span style="color: #800080;">$i</span>)] = <span style="color: #800080;">$node</span>['host'] . '_' . <span style="color: #800080;">$node</span>['port'<span style="color: #000000;">];
        }
        </span><span style="color: #008080;">ksort</span>(<span style="color: #800080;">$this</span>-&gt;<span style="color: #000000;">virtualNodeS);
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> removeServer(<span style="color: #800080;">$key</span><span style="color: #000000;">)
    {
        </span><span style="color: #800080;">$keyS</span> = <span style="color: #008080;">array_keys</span>(<span style="color: #800080;">$this</span>-&gt;virtualNodeS, <span style="color: #800080;">$key</span><span style="color: #000000;">);
    
        </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>-&gt;virtualNodeS <span style="color: #0000ff;">as</span> <span style="color: #800080;">$k</span> =&gt; &amp;<span style="color: #800080;">$v</span><span style="color: #000000;">) {
            </span><span style="color: #0000ff;">if</span> (<span style="color: #008080;">in_array</span>(<span style="color: #800080;">$k</span>, <span style="color: #800080;">$keyS</span><span style="color: #000000;">)) {
                </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$v</span><span style="color: #000000;">);
            }
        }
        </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$v</span><span style="color: #000000;">);
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getServerList()
    {
        </span><span style="color: #008080;">var_dump</span>(<span style="color: #800080;">$this</span>-&gt;<span style="color: #000000;">nodeS);
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getVirtualNodeList()
    {
        </span><span style="color: #008080;">var_dump</span>(<span style="color: #800080;">$this</span>-&gt;<span style="color: #000000;">virtualNodeS);
    }
    

    }

    $Hash = new Hash();

    (Hash</span>-&gt;addServer(['host' =&gt; '10.16.134.65', 'port' =&gt; '11211'<span style="color: #000000;">]); </span><span style="color: #800080;">)Hash->addServer(['host' => '10.16.134.65', 'port' => '11212']);
    (Hash</span>-&gt;addServer(['host' =&gt; '10.16.134.65', 'port' =&gt; '11213'<span style="color: #000000;">]); </span><span style="color: #800080;">)Hash->getVirtualNodeList();
    echo "<br>";
    echo (Hash</span>-&gt;strToInt('name'<span style="color: #000000;">); </span><span style="color: #0000ff;">echo</span> "&lt;br&gt;"<span style="color: #000000;">; </span><span style="color: #0000ff;">echo</span> <span style="color: #800080;">)Hash->findServer('name');

     

  • 相关阅读:
    Codeforces 841 D
    Codeforces 838 B
    Codeforces 833 C
    Codeforces 101572 D
    Codeforces 101173 C
    Codeforces 444 C
    POJ 3076 Sudoku
    Codeforces 1025 D
    算法笔记--基环树
    Codeforces 1016 E
  • 原文地址:https://www.cnblogs.com/yhq-qhh/p/10218218.html
Copyright © 2011-2022 走看看