一致性hash算法

1、爲Redis集羣使用Hash

若是咱們使用Hash的方式,每一張圖片在進行分庫的時候均可以定位到特定的服務器,示意圖以下:html

640

上圖中,假設咱們查找的是」a.png」,因爲有4臺服務器(排除從庫),所以公式爲hash(a.png) % 4 = 2 ,可知定位到了第2號服務器。算法

2、使用Hash的問題

優勢:再也不須要對整個Redis服務器進行遍歷!緩存

缺點:服務器數量變更的時候,全部緩存的位置都要發生改變!服務器

3、一致性Hash算法的神祕面紗

一致性Hash算法也是使用取模的方法,只是,剛纔描述的取模法是對服務器的數量進行取模,而一致性Hash算法是對2^32取模,什麼意思呢?簡單來講,一致性Hash算法將整個哈希值空間組織成一個虛擬的圓環,如假設某哈希函數H的值空間爲0-2^32-1(即哈希值是一個32位無符號整形),整個哈希環以下:  函數

640

整個空間按順時針方向組織,圓環的正上方的點表明0,0點右側的第一個點表明1,以此類推,二、三、四、五、6……直到2^32-1,也就是說0點左側的第一個點表明2^32-1, 0和2^32-1在零點中方向重合,咱們把這個由2^32個點組成的圓環稱爲Hash環。code

下一步將各個服務器使用Hash進行一個哈希,具體能夠選擇服務器的IP或主機名做爲關鍵字進行哈希,這樣每臺機器就能肯定其在哈希環上的位置,這裏假設將上文中四臺服務器使用IP地址哈希後在環空間的位置以下:  htm

640

接下來使用以下算法定位數據訪問到相應服務器:將數據key使用相同的函數Hash計算出哈希值,並肯定此數據在環上的位置,今後位置沿環順時針「行走」,第一臺遇到的服務器就是其應該定位到的服務器!對象

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

640

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

4、一致性Hash算法的容錯性和可擴展性

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

640

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

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

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

5、Hash環的數據傾斜問題

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

640

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

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

640

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

6、一致性hash實現

http://www.javashuo.com/article/p-hnmmqjzp-gx.html

相關文章
相關標籤/搜索