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

2021-09-14 02:41:00 字數 2243 閱讀 8361

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

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

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

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

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

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

從原理來看,一致性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作對映時,先找到對應的虛擬節點,再對應到實節點。如下圖所示, 每個節點虛擬出兩個虛擬節點,從而提高均衡性。

對於集群中快取類資料key的節點分配問題,有這幾種解決方法,簡單的hash取模,槽對映,一致性hash。

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

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

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

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

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

consistent hasing

redis cluster

一致性hash演算法 面試必備 一致性hash演算法

最近公司在招人,我們準備的問題中有一道是關於一致性hash演算法的問題,只有一些面試者能夠回答上來,而且答的也不是很全面,有的面試者只是聽說過,有的連聽都沒聽過,下面我把一致性hash演算法整理一下分享給大家 一致性雜湊演算法在1997年由麻省理工學院的karger等人在解決分布式cache中提出的...

一致性hash演算法虛擬節點 一致性hash演算法

hash 演算法也叫做雜湊演算法,他可以讓任意長度的資料m對映成為長度固定的值h。hash演算法的第乙個作用就是資料的快速儲存與查詢。寫過程式的人都知道,基本上主流的程式語言裡面都有個資料結構叫做map dictionary或者 hash table 它是根據key來直接訪問結果的資料結構。key的...

一致性Hash演算法原理白話

1 技術背景 1.1 技術舉例 memcache 1.2 技術瓶頸 memcached伺服器端本身不提供分布式cache的一致性,由客戶端實現提供。以餘數分布式演算法為例。餘數分布式演算法是根據新增進入快取時key的hash值通過特定的演算法得出餘數,然後根據餘數對映到關聯的快取伺服器,將該key ...