1. 程式人生 > 實用技巧 >簡明講解一致性雜湊演算法

簡明講解一致性雜湊演算法

雜湊演算法

如果我們用(使用者id)%伺服器機器數這樣的方法來分配伺服器。

雖然我們能保證資料的均勻性,但穩定性差,比如我們增加一個節點,會導致大量的對映失效。

1%3  ==  1%4
2%3  ==  2%4
3%3  !=  3%4
4%3  !=  4%4

這就難搞了,3之後的全亂了,直接體驗了一把快取雪崩。

所以雜湊演算法只適用於節點數比較固定的情況,並不能很好的應對節點的變化。

一致性雜湊演算法

這個時候一致性演算法就來了,你看這個雜湊環它是又大又圓,用它來降低對映關係大量失效的可能性剛剛好。

任何一條線段都有無數個點,這個大家應該沒什麼意見吧?所以理論上這個雜湊圈是能儲存無限多的東西的。

那資料該如何儲存呢?一致性雜湊演算法也是取模,一般來說落在圓環上的點是順時針儲存在離他最近的那個伺服器。

如果此時我們增加一臺伺服器E在CD之間,那麼受影響的只有D。

也就是說當伺服器數量發生改變時,受影響的只有順時針相鄰的後續節點,後端不至於短時間內承擔大量的壓力,不會發生大規模資料遷移。這也是一致性雜湊演算法的優點。

但ABCD一定會在環上均勻分佈嗎?完全有可能四臺伺服器的IP hash取模之後出現下圖的情況,出現hash環的偏斜。

如果運氣特別好,請求全集中在左邊的圓弧上,A就直接炸了。

設定儲存上限

最簡單的辦法就是根據當前負載情況對所有節點限制一個最大負載,防止某個節點承擔大部分的壓力。

當要儲存資料時,先判斷是否已經達到上限。如果已經滿了,那麼接著順時針尋找下一個節點。

不過如果各臺伺服器效能不一的話,這樣做也不是太好。

增加虛擬結點

解決辦法我相信你也想到了,只是沒敢說。如果伺服器夠多,不就不存在分佈不均的問題了嗎?

沒錯,就是這樣,但問題是從哪來找那麼多伺服器呢?

根據你想要要加倍的伺服器倍數,搞虛擬節點即可。節點越多,對映到環上就越均勻。比如說你可以由A映射出A^1-A^(2^23),BCD也是如此。這4*2^23個伺服器對映到雜湊環上,環都直接長成小煤球了。絕對的均勻,偏斜問題得到了極大的解決。

也就是將雜湊取模的N進行固定,但多一步虛擬節點對映到物理機上的步驟。這樣就可以確保相同的key必然是相同的位置,從而避免之前牽一髮而動全身的問題。

並且我們還可以根據各臺伺服器的效能來設定不同數量的虛擬節點。

引入虛擬節點的另外一個好處就是當某臺機器扛不住崩了,可以防止環上的下個機器要扛2倍的流量。

因為當某個節點被移除時,該節點對應的所有虛擬節點也會消失。而這些虛擬節點順時針對應的下一個節點對應的可能是不同的物理機,等於大家均攤了節點變化的壓力。

不過虛擬節點的引入在提高了穩定性的同時,也增加了維護和管理的複雜度,也算是有利有弊吧。