分布式理論(八)—— 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!!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM