一致性hash演算法原理及golang實現

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

概述

這裡存在一種情境, 當一個服務由多個伺服器組共同提供時, key應該路由到哪一個服務.這裡假如採用最通用的方式key%N(N為伺服器數目), 這裡乍一看沒什麼問題, 但是當伺服器數目發送增加或減少時, 分配方式則變為key%(N+1)或key%(N-1).這裡將會有大量的key失效遷移,如果後端key對應的是有狀態的儲存資料,那麼毫無疑問,這種做法將導致伺服器間大量的資料移轉,從而照成服務的不穩定. 為瞭解決類問題,一致性hash演算法應運而生.

1. 一致性hash演算法特點

在分布式緩衝中, 一個好的hash演算法應該要滿足以下幾個條件:

  • 均衡性(Balance)

均衡性主要指,通過演算法分配, 叢集中各節點應該要儘可能均衡.

  • 單調性(Monotonicity)

單調性主要指當叢集發生變化時, 已經分配到老節點的key, 儘可能的任然分配到之前節點,以防止大量資料移轉, 這裡一般的hash模數就很難滿足這點,而一致性hash演算法能夠將發生遷移的key數量控制在較低的水平.

  • 分散性(Spread)

分散性主要針對同一個key, 當在不同用戶端操作時,可能存在用戶端擷取到的緩衝叢集的數量不一致,從而導致將key映射到不同節點的問題,這會引發資料的不一致性.好的hash演算法應該要儘可能避免分散性.

  • 負載(Load)

負載主要是針對一個緩衝而言, 同一緩衝有可能會被使用者映射到不同的key上,從而導致該緩衝的狀態不一致.

從原理來看,一致性hash演算法針對以上問題均有一個合理的解決.

2. 一致性hash詳解

一致性hash的核心思想為將key作hash運算, 並按一定規律取整得出0-2^32-1之間的值, 環的大小為2^32,key計算出來的整數值則為key在hash環上的位置,如何將一個key,映射到一個節點, 這裡分為兩步.
第一步, 將服務的key按該hash演算法計算,得到在服務在一致性hash環上的位置.
第二步, 將緩衝的key,用同樣的方法計算出hash環上的位置,按順時針方向,找到第一個大於等於該hash環位置的服務key,從而得到該key需要分配的伺服器。

, 各key根據hash演算法分配到各節點,當某一節點失效實效時, 如NODE 2, 則NODE 2 上的key將分配到hash環上相鄰的節點,而其他key所在位置不變。

虛擬節點提高均衡性

如可看到, 由於節點只有3個,存在某些節點所在位置周圍有大量的hash點從而導致分配到這些節點到key要比其他節點多的多,這樣會導致叢集中各節點負載不均衡,為解決這個問題,引入虛擬節點, 即一個實節點對應多個虛擬節點。緩衝的key作映射時,先找到對應的虛擬節點,再對應到實節點。如所示, 每個節點虛擬出兩個虛擬節點,從而提高均衡性。

3. 一致性hash演算法與其他演算法對比

對於叢集中緩衝類資料key的節點分配問題,有這幾種解決方案,簡單的hash模數,槽映射,一致性hash。

  • hash模數

對於hash模數,均衡性沒有什麼問題,但是如果叢集中新增一個節點時,將會有N/(N+1)的資料實效,當N值越大,失效率越高。這顯然是不可接受的。

  • 槽映射

redis採用的就是這種演算法, 其思想是將key值做一定運算(如crc16, crc32,hash), 獲得一個整數值,再將該值與固定的槽數模數(slots), 每個節點處理固定的slots。擷取key所在的節點時,先要計算出key與槽的對應關係,再通過槽與節點的對應關係找到節點,這裡每次新增節點時,只需要遷移一定槽對應的key即可,而不遷移的槽點key值則不會實效,這種方式將實效率降低到了 N/(N+1)。不過這種方式有個缺點就是所有節點都需要知道槽與節點對應關係,如果client端不儲存槽與節點的對應關係的話,它需要實現重新導向的邏輯。

  • 一致性hash

一致性hash如上文所言,其新增一個節點的實效率僅為N/(N+1),通過一致性hash最大程度的降低了實效率。同時相比於槽映射的方式,不需要引人槽來做中間對應,最大限度的簡化了實現。

4. 基於golang的一致性hash演算法實現

這裡講採用golang實現一致性hash,考慮到實際使用情境中,存在服務節點之間機器配置可能不一樣,因此提供了基於節點權重進行虛擬節點再分配的邏輯,從而儘可能讓權重高的節點多承擔一些key,而權重低的節點少承擔一些key,當然這裡權重的計算也涉及到較多東西,代碼見:
https://github.com/g4zhuj/has...

5. 總結

本文分析了一致性性hash的原理,並與其它的分布式叢集分配演算法進行了對比,從分布式緩衝的角度來說,兩大出名的分布儲存系統redis, memcached分別採用了槽映射,及一致性hash來實現,由於採用的演算法不同,叢集中節點變更時所觸發的一系列動作也不盡相同,各有各的考慮。

6.參考

Consistent Hasing https://en.wikipedia.org/wiki...
Redis Cluster https://redis.io/topics/clust...

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.