分佈式理論(八)—— Consistent Hash(一致性哈希算法)

分佈式理論(八)—— Consistent Hash(一致性哈希算法)

前言

在分佈式系統中,常常需要使用緩存,而且通常是集羣,訪問緩存和添加緩存都需要一個 hash 算法來尋找到合適的 Cache 節點。但,通常不是用取餘hash,而是使用我們今天的主角—— 一致性 hash 算法。

今天樓主就來說說這個一致性 hash 算法。

1. 爲什麼普通的 hash 算法不行?

普通的 hash 算法通常都是對機器數量進行取餘,比如集羣環境中有 3 臺 redis,當我們放入對象的時候,通常是對 3 進行取餘。這種做法在大部分情況下是沒有問題的。但是,注意:如果緩存機器需要增減,問題就來了。

什麼問題呢?

假設原本是 3 個 redis,這時候,加了一臺 redis,那麼取餘算法就變成了取餘 4。

這樣有什麼問題呢?
答:當使用負載均衡的時候,負載均衡器根據對象的 key 對機器進行取餘,這個時候,原有的 key 取餘現有的機器數 4 就找不到那臺機器了!笨一點的辦法,就是在增加機器的時候,清除所有緩存,但這會導致緩存擊穿甚至緩存雪崩,嚴重情況下引發 DB 宕機。

2. 一致性 hash 怎麼解決這個問題?

很簡單,既然問題出在對機器取餘上,那麼就不對機器取餘。

具體怎麼做呢?

答:我們可以假設有一個 2 的 32 次方的環形,緩存節點通過 hash 落在環上。而對象的添加也是使用 hash,但很大的機率是 hash 不到緩存節點的。怎麼辦呢?找離他最近的那個節點。 比如順時針找前面那個節點。

能解決問題嗎?想象一下:當增減機器時,環形節點變化的只會影響一個節點,就是新節點的順時針方向的前面的節點。這個時候,我們只需要清除那一個節點的數據就足夠了,不用想取餘 hash 那樣,清除所有節點的數據。

具體類似於下圖:

image.png

上圖中,節點中的五角星代表對象,紅綠黃代表節點,每個對象都會找他的上一個節點。如有增減,隻影響一個節點。

如下圖所示:

image.png

紅色和綠色節點不受影響。

3. 一致性 hash 有什麼問題呢?

是否這麼做就完美了呢?

不是的。

如果認真看是上面的圖的話,會發現,黃色節點的負載壓力最大,這個集羣環境負載不夠均衡。

image.png

什麼原因導致的呢?原因是:如果緩存節點分佈不均勻,就會出現這樣的情況。但是,你不能奢望是均勻的。

怎麼辦呢?

我們可以在不均的地方給他弄均勻。在空閒的地方加入 虛擬節點,這些節點的數據映射到真實節點上,就可以了,如下圖所示:

image.png

上圖中,我們給每個節點都做了虛擬節點(虛線),從而讓整個集羣在 hash 環比較均勻,從圖中也可以看出,這樣現對比之前均勻多了,黃色節點的負載和綠色節點額的負載相同。

4. 總結

總的來說,一致性 hash 還是比較簡單的。核心思想是,不使用對機器取餘的算法。這樣就能避免機器增減帶來的影響。

同時,使用 就近尋址 的方式找到最近的節點。當然,這會引起負載不均衡,所以需要引入虛擬節點的方式,變相的增加節點,讓整個集羣的負載能夠均衡。

後面,我們將自己寫一個一致性 hash 算法以加深印象。

good luck!!!!

作者:莫那魯道

 

出處: 博客園:http://www.cnblogs.com/stateis0/ 
            個人博客: thinkinjava.cn

 

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連接,否則保留追究法律責任的權利。

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