一致性哈希算法原理詳解

一、普通 hash 算法 (取模算法):
在瞭解一致性哈希算法之前,我們先了解一下緩存中的一個應用場景,瞭解了這個應用場景之後,再來理解一致性哈希算法,就容易多了,也更能體現出一致性哈希算法的優點,那麼,我們先來描述一下這個經典的分佈式緩存的應用場景。

1、普通 hash算法 與 使用場景描述:
假設我們有三臺緩存服務器,用於緩存圖片,我們爲這三臺緩存服務器編號爲 0號、1號、2號,現在有3萬張圖片需要緩存,我們希望這些圖片被均勻的緩存到這3臺服務器上,以便它們能夠分攤緩存的壓力。也就是說,我們希望每臺服務器能夠緩存1萬張左右的圖片,那麼我們應該怎樣做呢?常見的做法是對緩存項的鍵進行哈希,將hash後的結果對緩存服務器的數量進行取模操作,通過取模後的結果,決定緩存項將會緩存在哪一臺服務器上

我們舉例說明,以剛纔描述的場景爲例,假設圖片名稱是不重複的,那我們就可以使用圖片名稱作爲訪問圖片的key,使用如下公式,計算出圖片應該存放在哪臺服務器上。

hash(圖片名稱)% N

當我們對同一個圖片名稱做相同的哈希計算時,得出的結果應該是不變的,如果我們有3臺服務器,使用哈希後的結果對3求餘,那麼餘數一定是0、1或者2;如果求餘的結果爲0, 就把當前圖片緩存在0號服務器上,如果餘數爲1,就緩存在1號服務器上,以此類推;同理,當我們訪問任意圖片時,只要再次對圖片名稱進行上述運算,即可得出圖片應該存放在哪一臺緩存服務器上,我們只要在這一臺服務器上查找圖片即可,如果圖片在對應的服務器上不存在,則證明對應的圖片沒有被緩存,也不用再去遍歷其他緩存服務器了,通過這樣的方法,即可將3萬張圖片隨機的分佈到3臺緩存服務器上了,而且下次訪問某張圖片時,直接能夠判斷出該圖片應該存在於哪臺緩存服務器上,我們暫時稱上述算法爲 HASH 算法或者取模算法,取模算法的過程可以用下圖表示:

 

2、普通 hash 算法的缺陷:
上述HASH算法時,會出現一些缺陷:如果服務器已經不能滿足緩存需求,就需要增加服務器數量,假設我們增加了一臺緩存服務器,此時如果仍然使用上述方法對同一張圖片進行緩存,那麼這張圖片所在的服務器編號必定與原來3臺服務器時所在的服務器編號不同,因爲除數由3變爲了4,最終導致所有緩存的位置都要發生改變,也就是說,當服務器數量發生改變時,所有緩存在一定時間內是失效的,當應用無法從緩存中獲取數據時,則會向後端服務器請求數據;同理,假設突然有一臺緩存服務器出現了故障,那麼我們則需要將故障機器移除,那麼緩存服務器數量從3臺變爲2臺,同樣會導致大量緩存在同一時間失效,造成了緩存的雪崩,後端服務器將會承受巨大的壓力,整個系統很有可能被壓垮。爲了解決這種情況,就有了一致性哈希算法。

 

二、一致性哈希算法:
1、什麼是一致性 hash 算法:
一致性哈希算法也是使用取模的方法,但是取模算法是對服務器的數量進行取模,而一致性哈希算法是對 2^32 取模,具體步驟如下:

步驟一:一致性哈希算法將整個哈希值空間按照順時針方向組織成一個虛擬的圓環,稱爲 Hash 環;
步驟二:接着將各個服務器使用 Hash 函數進行哈希,具體可以選擇服務器的IP或主機名作爲關鍵字進行哈希,從而確定每臺機器在哈希環上的位置
步驟三:最後使用算法定位數據訪問到相應服務器:將數據key使用相同的函數Hash計算出哈希值,並確定此數據在環上的位置,從此位置沿環順時針尋找,第一臺遇到的服務器就是其應該定位到的服務器
下面我們使用具體案例說明一下一致性哈希算法的具體流程:

(1)步驟一:哈希環的組織:

我們將 2^32 想象成一個圓,像鐘錶一樣,鐘錶的圓可以理解成由60個點組成的圓,而此處我們把這個圓想象成由2^32個點組成的圓,示意圖如下:

 

圓環的正上方的點代表0,0點右側的第一個點代表1,以此類推,2、3、4、5、6……直到2^32-1,也就是說0點左側的第一個點代表2^32-1,我們把這個由 2^32 個點組成的圓環稱爲hash環。

(2)步驟二:確定服務器在哈希環的位置:

哈希算法:hash(服務器的IP) % 2^32

上述公式的計算結果一定是 0 到 2^32-1 之間的整數,那麼上圖中的 hash 環上必定有一個點與這個整數對應,所以我們可以使用這個整數代表服務器,也就是服務器就可以映射到這個環上,假設我們有 ABC 三臺服務器,那麼它們在哈希環上的示意圖如下:

 

(3)步驟三:將數據映射到哈希環上:

我們還是使用圖片的名稱作爲 key,所以我們使用下面算法將圖片映射在哈希環上:hash(圖片名稱) % 2^32,假設我們有4張圖片,映射後的示意圖如下,其中橘黃色的點表示圖片:

 

那麼,怎麼算出上圖中的圖片應該被緩存到哪一臺服務上面呢?我們只要從圖片的位置開始,沿順時針方向遇到的第一個服務器就是圖片存放的服務器了。最終,1號、2號圖片將會被緩存到服務器A上,3號圖片將會被緩存到服務器B上,4號圖片將會被緩存到服務器C上。

2、一致性 hash 算法的優點:
前面提到,如果簡單對服務器數量進行取模,那麼當服務器數量發生變化時,會產生緩存的雪崩,從而很有可能導致系統崩潰,而使用一致性哈希算法就可以很好的解決這個問題,因爲一致性Hash算法對於節點的增減都只需重定位環空間中的一小部分數據,只有部分緩存會失效,不至於將所有壓力都在同一時間集中到後端服務器上,具有較好的容錯性和可擴展性。

假設服務器B出現了故障,需要將服務器B移除,那麼移除前後的示意圖如下圖所示:

 

在服務器B未移除時,圖片3應該被緩存到服務器B中,可是當服務器B移除以後,按照之前描述的一致性哈希算法的規則,圖片3應該被緩存到服務器C中,因爲從圖片3的位置出發,沿順時針方向遇到的第一個緩存服務器節點就是服務器C,也就是說,如果服務器B出現故障被移除時,圖片3的緩存位置會發生改變,但是,圖片4仍然會被緩存到服務器C中,圖片1與圖片2仍然會被緩存到服務器A中,這與服務器B移除之前並沒有任何區別,這就是一致性哈希算法的優點。

3、hash 環的傾斜與虛擬節點:
一致性哈希算法在服務節點太少的情況下,容易因爲節點分部不均勻而造成數據傾斜問題,也就是被緩存的對象大部分集中緩存在某一臺服務器上,從而出現數據分佈不均勻的情況,這種情況就稱爲 hash 環的傾斜。如下圖所示:

 

hash 環的傾斜在極端情況下,仍然有可能引起系統的崩潰,爲了解決這種數據傾斜問題,一致性哈希算法引入了虛擬節點機制,即對每一個服務節點計算多個哈希,每個計算結果位置都放置一個此服務節點,稱爲虛擬節點,一個實際物理節點可以對應多個虛擬節點,虛擬節點越多,hash環上的節點就越多,緩存被均勻分佈的概率就越大,hash環傾斜所帶來的影響就越小,同時數據定位算法不變,只是多了一步虛擬節點到實際節點的映射。具體做法可以在服務器ip或主機名的後面增加編號來實現,加入虛擬節點以後的hash環如下:


————————————————
 參考一致性hash算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章