DHT和一致性哈希算法總結

 

Hash算法比較重要的考量點有兩個:

1.單調性(新增或者減少映射節點時,儘量不影響原有映射關係) 2.平衡性(儘量均勻分佈)

 

分佈式領域常見負載均衡算法:

(1)取餘法:%n

如果有3個節點,Hash之後取模求餘  Hash(x)%3,

如果加一個節點,則 Hash(x)%4。

 

這種方法帶來的問題:

1 一個 cache 服務器 m down 掉了(在實際應用中必須要考慮這種情況),這樣所有映射到 cache m 的對象都會失效,怎麼辦,需要把 cache m 從 cache 中移除,這時候 cache 是 N-1 臺,映射公式變成了 hash(object)%(N-1) ; 2 由於訪問加重,需要添加 cache ,這時候 cache 是 N+1 臺,映射公式變成了 hash(object)%(N+1) ; 1 和 2 意味着什麼?這意味着突然之間幾乎所有的 cache 都失效了。對於服務器而言,這是一場災難,洪水般的訪問都會直接衝向後臺服務器; 再來考慮第三個問題,由於硬件能力越來越強,你可能想讓後面添加的節點多做點活,顯然上面的 hash 算法也做不到。 有什麼方法可以改變這個狀況呢,這就是 consistent hashing...

 解釋下爲什麼cache會失效:

  假如有6個數據分別是1,2,3,4,5,6,有3臺機器,用取餘算法%3。設定餘數爲0對應的是第一臺機器,餘數爲1對應的是第二臺機器,餘數爲2對應的是第三臺機器。那麼數據3和6存儲在第一臺機器,1和4存儲在第二臺機器,2和5存儲在第三臺機器。如果這時候增加一臺機器變成4臺,用取餘算法%4實現,映射到某臺機器的規則和之前的類似,那麼數據4存儲在第一臺機器,數據1和5存儲在第二臺機器,數據2和6存儲在第三臺機器,數據3存儲在第4臺機器。

  原來3臺機器: M1:(3,6) M2: (1,4)  M3: (2,5)

  變成4臺機器:M1: (4) M2: (1,5) M3: (2,6) M4: (3) 

   可以看到1,2,3,4臺機器的數據都將會有變化。

而如果採用一致性hash算法,則能減少數據變化的機器。

 

(2)一致性hash算法

  實現步驟:

第一步:採用一種hash算法,把服務器地址或者主機名映射到一個2的32次方的環上。爲什麼是2的32次方?IPv4的ip地址佔4個字節,可以存儲2的32次方比特位信息。

第二步:把要存儲的key採用同樣的hash算法映射到環上,如果命中某個服務器地址則存在該臺服務器,如果在服務器1和服務器2的地址的中間,則按從小到大去搜索,找到的第一個服務器,就映射到該臺服務器上。

好處:增加和減少節點時,隻影響附近的一個節點,不會像取餘法一樣影響全部節點的數據。

 

改進:

另外,一致性哈希算法在服務節點太少時,容易因爲節點分部不均勻而造成數據傾斜問題。例如系統中只有兩臺服務器,可能大量的數據都存在一臺服務器,另一臺服務器只存儲了很少的數據。爲了解決這種情況,可以增加虛擬環。

爲了解決這種數據傾斜問題,一致性哈希算法引入了虛擬節點機制,即對每一個服務節點計算多個哈希,注意,這裏的多個哈希算法應該使得結果儘量分佈均勻,才能最大程度減少數據傾斜的情況。每個計算結果位置都放置一個此服務節點,稱爲虛擬節點。具體做法可以在服務器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甚至更大,因此即使很少的服務節點也能做到相對均勻的數據分佈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章