關於一致性Hash演算法

2022-03-20 15:13:00 字數 3070 閱讀 1932

在大型web應用中,快取可算是當今的乙個標準開發配置了。在大規模的快取應用中,應運而生了分布式快取系統。分布式快取系統的基本原理,大家也有所耳聞。key-value如何均勻的分散到集群中?說到此,最常規的方式莫過於hash取模的方式。比如集群中可用機器適量為n,那麼key值為k的的資料請求很簡單的應該路由到hash(k) mod n對應的機器。的確,這種結構是簡單的,也是實用的。但是在一些高速發展的web系統中,這樣的解決方案仍有些缺陷。隨著系統訪問壓力的增長,快取系統不得不通過增加機器節點的方式提高集群的相應速度和資料承載量。增加機器意味著按照hash取模的方式,在增加機器節點的這一時刻,大量的快取命不中,快取資料需要重新建立,甚至是進行整體的快取資料遷移,瞬間會給db帶來極高的系統負載,設定導致db伺服器宕機。 那麼就沒有辦法解決hash取模的方式帶來的詬病嗎?看下文。

選擇具體的機器節點不在只依賴需要快取資料的key的hash本身了,而是機器節點本身也進行了hash運算。

(1) hash機器節點

首先求出機器節點的hash值(怎麼算機器節點的hash?ip可以作為hash的引數吧。。當然還有其他的方法了),然後將其分布到0~2^32的乙個圓環上(順時針分布)。如下圖所示:

集群中有機器:a , b, c, d, e五颱機器,通過一定的hash演算法我們將其分布到如上圖所示的環上。

(2)訪問方式

如果有乙個寫入快取的請求,其中key值為k,計算器hash值hash(k),

hash(k)

對應於圖 – 1環中的某乙個點,如果該點對應沒有對映到具體的某乙個機器節點,那麼順時針查詢,直到第一次找到有對映機器的節點,該節點就是確定的目標節點,如果超過了2^32仍然找不到節點,則命中第乙個機器節點。比如

hash(k)

的值介於a~b之間,那麼命中的機器節點應該是b節點(如上圖 )。

(3)增加節點的處理

如上圖 – 1,在原有集群的基礎上欲增加一台機器f,增加過程如下:

計算機器節點的hash值,將機器對映到環中的乙個節點,如下圖:

增加機器節點f之後,訪問策略不改變,依然按照(2)中的方式訪問,此時快取命不中的情況依然不可避免,不能命中的資料是hash(k)在增加節點以前落在c~f之間的資料。儘管依然存在節點增加帶來的命中問題,但是比較傳統的 hash取模的方式,一致性hash已經將不命中的資料降到了最低。

consistent hashing最大限度地抑制了hash鍵的重新分布。另外要取得比較好的負載均衡的效果,往往在伺服器數量比較少的時候需要增加虛擬節點來保證伺服器能均勻的分布在圓環上。因為使用一般的hash方法,伺服器的對映地點的分布非常不均勻。使用虛擬節點的思想,為每個物理節點(伺服器)在圓上分配100~200個點。這樣就能抑制分布不均勻,最大限度地減小伺服器增減時的快取重新分布。使用者資料對映在虛擬節點上,就表示使用者資料真正儲存位置是在該虛擬節點代表的實際物理伺服器上。

下面有乙個圖描述了需要為每台物理伺服器增加的虛擬節點。

x軸表示的是需要為每台物理伺服器擴充套件的虛擬節點倍數(scale),y軸是實際物理伺服器數,可以看出,當物理伺服器的數量很小時,需要更大的虛擬節點,反之則需要更少的節點,從圖上可以看出,在物理伺服器有10台時,差不多需要為每台伺服器增加100~200個虛擬節點才能達到真正的負載均衡。

一致性hash和memcached

一致性hash演算法在redis中的應用

當伺服器不多,並且不考慮擴容的時候,可直接使用簡單的路由演算法,用伺服器數除快取資料key的hash值,餘數作為伺服器下標即可。

但是當業務發展,**快取服務需要擴容時就會出現問題,比如3臺快取伺服器要擴容到4臺,就會導致75%的資料無法命中,當100臺伺服器中增加一台,不命中率會到達99%(n/(n+1)),這顯然是不能接受的。

在設計分布式快取集群的時候,需要考慮集群的伸縮性,也就是當向集群中增加伺服器的時候,要盡量減小對集群的影響,而一致性hash演算法就是用來解決集群伸縮性。

一致性hash演算法通過構造乙個長度為2^32的整數環,根據節點名的hash值將快取伺服器節點放置在這個環上,然後計算要快取的資料的key的hash值,順時針找到最近的伺服器節點,將資料放到該伺服器上。

有node0,node1,node2三個節點,假設node0的hash值是1024,key1的hash值是500,key1在環上順時針查詢,最近的節點就是node0。

當伺服器集群又開始擴容,新增了node3節點,從三個節點擴容到了四個節點。

node3加到了node2和node1之間,除了node2到node3之間原本是node1的資料無法再命中,其它的資料不受影響,3臺擴容到4臺可命中率高達75%,

而且集群越大,影響越小,100臺伺服器增加一台,命中率可達到99%。

查詢不小於查詢樹的最小值是用的二叉查詢樹實現的。

但是這樣子還是會存在乙個問題,就是負載不均衡的問題,當node3加到node2和node1之間時,原本會訪問node1的快取資料有50%的概率會快取到node3上了,這樣node0和node2的負載會是node1和node3的兩倍。

要解決一致性hash演算法帶來的負載不均衡問題,可通過將每台物理伺服器虛擬成一組虛擬快取伺服器,將虛擬伺服器的hash值放置在hash環上,key在環上先找到虛擬伺服器節點,然後再對映到實際的伺服器上。

這樣在node0,1,2虛擬節點都已存在的情況下,將node3的多個虛擬節點分散到它們中間,多個虛擬的node3節點會影響到其它的多個虛擬節點,而不是只影響其中乙個,這樣將命中率不會有變化,但是負載卻更加均衡了而且虛擬節點越多越均衡。

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

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

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

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

一致性hash演算法

july部落格16章開始 第一題 全排列,輸入乙個字串,列印出該字串中字元的所有排列 1.個人思路 回溯法建立的排序樹 2.july部落格 遞迴實現,依次固定第乙個字母,後面的交換,和上面描述的使用回溯法相似 c stl 演算法 next permutation的思想,關於next permutat...