一致性雜湊演算法

2021-10-10 15:49:51 字數 1884 閱讀 8455

1.基本概念

一致性雜湊演算法在很多領域有應用,例如分布式快取領域的 memcache,redis,負載均衡領域的 nginx,各類 rpc 框架。在移除或者新增乙個伺服器時,一致性雜湊演算法能夠盡可能小地改變已存在的服務請求與處理請求伺服器之間的對映關係。一致性雜湊解決了簡單雜湊演算法在分布式雜湊表中存在的動態伸縮等問題。

2.特點

一致性雜湊演算法有以下的特點:

3.分布式快取應用

我們從乙個具體場景來看:redis 是如何使用一致性 hash 演算法保證快取命中率、容錯性和可擴充套件性的。

從上圖的狀態中新增一台 redis 伺服器。採用餘數分布式演算法,會由於儲存鍵的快取例項發生變化而影響快取的命中率。但一致性hash演算法中,只有在增加節點(node5)的逆時針的一小部分hash會受到影響,如下圖所示:

這種方式很好的解決了快取命中率、容錯性和可擴充套件性,但是當服務節點很少的時候,這時候會帶來另外乙個問題,就是「資料傾斜」,也就是很多 key 被分配到同乙個服務例項上。為避免這樣的問題,大多數一致性雜湊演算法的實現都引入了虛擬節點的概念。

例如我們的系統中有兩台伺服器,其環分布如下:

此時必然造成大量資料集中到 redis2 上,而只有極少量會定位到 redis1 上。為了解決這種資料傾斜問題,一致性 hash 演算法引入了虛擬節點機制,即對每乙個服務節點計算多個雜湊,每個計算結果位置都放置乙個此服務節點,稱為虛擬節點。具體做法可以在伺服器 ip 或主機名的後面增加編號來實現。

同時資料定位演算法不變,只是多了一步虛擬節點到實際節點的對映,例如定位到「redis2#1」、「redis2#2」 兩個虛擬節點的資料均定位到 redis2 上。這樣就解決了服務節點少時資料傾斜的問題。在實際應用中,通常將虛擬節點數設定得更大,因此即使很少的服務節點也能做到相對均勻的資料分布。

4.一致性雜湊負載均衡應用

負載均衡這個概念可以抽象為:從n 個候選伺服器中選擇乙個進行通訊的過程。負載均衡演算法有多種多樣的實現方式:隨機、輪詢、最小負載優先等,其中也包括了今天的主角:一致性雜湊負載均衡。一致性雜湊負載均衡需要保證的是「相同的請求盡可能落到同乙個伺服器上」。

「盡可能」 —為什麼不是一定?

因為伺服器可能發生上下線,所以少數伺服器的變化不應該影響大多數的請求。這也呼應了演算法名稱中的「一致性」。

同時,乙個優秀的負載均衡演算法還有乙個隱性要求:流量盡可能均勻分布。

綜上所述,我們可以概括出一致性雜湊負載均衡演算法的設計思路:

實現原理:

簡單介紹下這個負載均衡中的一致性雜湊環,首先將伺服器(ip+埠號)進行雜湊,對映成環上的乙個節點,在請求到來時,根據指定的 hash key 同樣對映到環上,並順時針選取最近的乙個伺服器節點進行請求(在本圖中,使用的是 userid 作為 hash key)。

當環上的伺服器較少時,即使雜湊演算法選擇得當,依舊會遇到大量請求落到同乙個節點的問題,為避免這樣的問題,大多數一致性雜湊演算法的實現度引入了虛擬節點的概念。

在上圖中,只有兩台物理伺服器節點:11.1.121.1 和 11.1.121.2,我們通過新增字尾的方式,轉殖出了另外三份節點,使得環上的節點分布的均勻。一般來說,物理節點越多,所需的虛擬節點就越少。

一致性雜湊演算法

好吧,我們決定打破這種基於資料項商業邏輯的劃分思維,來考慮一種基於 key 的劃分方式,這有些類似於後面介紹的資料庫水平分割槽 sharding 我們需要設計一種不依賴資料項內容的雜湊演算法,將所有資料項的 key 均衡分配在這三颱快取伺服器上。乙個簡單而有效的方法是 取餘 運算,這就像打撲克時的發...

一致性雜湊演算法

在分布式系統中,如果某業務可以由多個相同的節點處理,很容易想到用hash的方式將業務請求分散到這些節點處理,如果有n個節點,計算方法為 hash id n。如果只是簡單的計算,不涉及使用者狀態,這是乙個簡單有效的方案。如果節點的計算涉及使用者狀態,比如維護購物車 memcache快取服務等,好像也沒...

一致性雜湊演算法

判定好壞的四個定義 1 平衡性 balance 平衡性是指雜湊的結果能夠盡可能分布到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。2 單調性 monotonicity 單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的...