一致性哈希算法

一致性哈希算法

一致性哈希算法是在1997年由麻省理工學院的Karger等人爲了解決熱點(Hot spot)問題而提出的. 一致性哈希算法在分佈式系統中有很是普遍的使用, 好比如何將數據進行分區, 如何將數據映射到對應的緩存中. 本文會首先介紹採用通常的hash算法會有什麼問題, 而後在提出一致性hash算法的原理以及一致性hash算法的好處以及缺點.redis

爲了說明通常的hash算法和一致性hash算法, 咱們這裏假設一個實際的場景. 採用redis集羣來進行說明算法

redis集羣的使用

在redis集羣中, 若是數據量比較大, 因爲沒法在一個節點將全部的數據所有保存, 咱們會將數據進行分區. 假設以下圖所示, 採用了四個分區:數據庫

redis集羣

若是咱們將數據隨機的分配到不一樣的分區中, 那麼查詢指定的數據就須要遍歷全部的分區, 因此咱們須要算法來告訴咱們將數據放置到那個分區中.後端

通常的hash算法

咱們常見的hash算法就是採用取模運算. 好比針對上面有四個分區的集羣, 咱們能夠將數據對4取模, 則就能夠將數據指定到對應的分區中.緩存

雖然這種hash方法提高了性能, 可是它也有很嚴重的問題. 主要是在服務器數量變更的時候, 全部的緩存位置都要發生變化.服務器

假設如今因爲數據量增長比較多, 須要增長緩存服務器. 假設增長了1臺服務器, 則服務器從4臺變成5臺. 那麼以前的對4取模如今變成對5取模. 能夠想象數據的取模結果都發生了變化. 這樣形成咱們沒法從緩存中查詢到數據, 在必定的時間範圍內,緩存中的數據是失效的, 那麼請求就會落到後端的數據庫中, 形成緩存雪崩.分佈式

或者若是緩存中有一臺服務器出現故障, 那麼服務器從4臺變成3臺, 仍然存在同樣的問題.函數

爲了解決上面說到的問題, 出現了一致性hash算法.性能

一致性hash算法原理

一致性hash算法也是採用取模的方法, 可是不一樣於對服務器數量取模, 而是對2^32取模. 就是一致性hash算法將整個哈希值空間組織成一個虛擬的圓環, 圓環以下: 一致性hash對象

整個空間按順時針方法組織, 圓環的正上方表明0, 0右側的第一個點表明1, 依次類推, 之道2^32 -1. 組成的這個圓環稱爲hash環.

下一步是將各個服務器hash到圓環上對應的點上, 具體能夠選擇服務器的IP地址或服務器主機名等. 好比將上文中提到的四個服務器對應到圓環上,以下:

接下來就是定位數據訪問到哪一個服務器上, 將數據的可使用相同的hash函數(就是對2^32取模)計算出hash值, 肯定數據在hash環上的位置, 今後位置沿環順時針"行走", 遇到的第一個服務器就是其應該定位的服務器!

例如咱們有Object A、Object B、Object C、Object D四個數據對象,通過哈希計算後,在環空間上的位置以下:

根據一致性Hash算法,數據A會被定爲到Node A上,B被定爲到Node B上,C被定爲到Node C上,D被定爲到Node D上。

一致性hash算法的擴展性

現假設Node C不幸宕機,能夠看到此時對象A、B、D不會受到影響,只有C對象被重定位到Node D。通常的,在一致性Hash算法中,若是一臺服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一臺服務器(即沿着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響,以下所示:

下面考慮另一種狀況,若是在系統中增長一臺服務器Node X,以下圖所示:

此時對象Object A、B、D不受影響,只有對象C須要重定位到新的Node X !通常的,在一致性Hash算法中,若是增長一臺服務器,則受影響的數據僅僅是新服務器到其環空間中前一臺服務器(即沿着逆時針方向行走遇到的第一臺服務器)之間數據,其它數據也不會受到影響。

綜上所述,一致性Hash算法對於節點的增減都只需重定位環空間中的一小部分數據,具備較好的容錯性和可擴展性。

一致性hash數據傾斜

一致性Hash算法在服務節點太少時,容易由於節點分部不均勻而形成數據傾斜(被緩存的對象大部分集中緩存在某一臺服務器上)問題,例如系統中只有兩臺服務器,其環分佈以下:

此時必然形成大量數據集中到Node A上,而只有極少許會定位到Node B上。爲了解決這種數據傾斜問題,一致性Hash算法引入了虛擬節點機制,即對每個服務節點計算多個哈希,每一個計算結果位置都放置一個此服務節點,稱爲虛擬節點。具體作法能夠在服務器IP或主機名的後面增長編號來實現。

例如上面的狀況,能夠爲每臺服務器計算三個虛擬節點,因而能夠分別計算 「Node A#1」、「Node A#2」、「Node A#3」、「Node B#1」、「Node B#2」、「Node B#3」的哈希值,因而造成六個虛擬節點:

同時數據定位算法不變,只是多了一步虛擬節點到實際節點的映射,例如定位到「Node A#1」、「Node A#2」、「Node A#3」三個虛擬節點的數據均定位到Node A上。這樣就解決了服務節點少時數據傾斜的問題。在實際應用中,一般將虛擬節點數設置爲32甚至更大,所以即便不多的服務節點也能作到相對均勻的數據分佈。

代碼

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息