一致性Hash算法分析與實現

關於一致性Hash算法的原理講解,可先閱讀:緩存算法與應用詳解

引言

在做服務器負載均衡時候可供選擇的負載均衡的算法有很多,包括: 輪循算法(Round Robin)、哈希算法(HASH)、最少連接算法(Least Connection)、響應速度算法(Response Time)、加權法(Weighted )等。其中哈希算法是最爲常用的算法.

典型的應用場景是: 有N臺服務器提供緩存服務,需要對服務器進行負載均衡,將請求平均分發到每臺服務器上,每臺機器負責1/N的服務。

常用的算法是對hash結果取餘數 (hash() mod N ):對機器編號從0到N-1,按照自定義的 hash()算法,對每個請求的hash()值按N取模,得到餘數i,然後將請求分發到編號爲i的機器。但這樣的算法方法存在致命問題,如果某一臺機器宕機,那麼應該落在該機器的請求就無法得到正確的處理,這時需要將當掉的服務器從算法從去除,此時候會有(N-1)/N的服務器的緩存數據需要重新進行計算;如果新增一臺機器,會有N /(N+1)的服務器的緩存數據需要進行重新計算。對於系統而言,這通常是不可接受的顛簸(因爲這意味着大量緩存的失效或者數據需要轉移)。那麼,如何設計一個負載均衡策略,使得受到影響的請求儘可能的少呢?

在Memcached、Key-Value Store 、Bittorrent DHT、LVS中都採用了Consistent Hashing算法,可以說Consistent Hashing 是分佈式系統負載均衡的首選算法。


目錄

  • 數據結構的選取;
  • 一致性Hash算法;
  • 引入虛擬節點機制優化;

一致性Hash的算法設計目標

考慮到分佈式系統每個節點都有可能失效,並且新的節點很可能動態的增加進來,如何保證當系統的節點數目發生變化時仍然能夠對外提供良好的服務,這是值得考慮的,尤其實在設計分佈式緩存系統時,如果某臺服務器失效,對於整個系統來說如果不採用合適的算法來保證一致性,那麼緩存於系統中的所有數據都可能會失效(即由於系統節點數目變少,客戶端在請求某一對象時需要重新計算其hash值(通常與系統中的節點數目有關),由於hash值已經改變,所以很可能找不到保存該對象的服務器節點),因此一致性hash就顯得至關重要,良好的分佈式cahce系統中的一致性hash算法應該滿足以下幾個方面:

平衡性(Balance)

平衡性是指哈希的結果能夠儘可能分佈到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多哈希算法都能夠滿足這一條件。

單調性(Monotonicity)

單調性是指如果已經有一些內容通過哈希分派到了相應的緩衝中,又有新的緩衝區加入到系統中,那麼哈希的結果應能夠保證原有已分配的內容可以被映射到新的緩衝區中去,而不會被映射到舊的緩衝集合中的其他緩衝區。簡單的哈希算法往往不能滿足單調性的要求,如最簡單的線性哈希:x = (ax + b) mod (P),在上式中,P表示全部緩衝的大小。不難看出,當緩衝大小發生變化時(從P1到P2),原來所有的哈希結果均會發生變化,從而不滿足單調性的要求。哈希結果的變化意味着當緩衝空間發生變化時,所有的映射關係需要在系統內全部更新。而在P2P系統內,緩衝的變化等價於Peer加入或退出系統,這一情況在P2P系統中會頻繁發生,因此會帶來極大計算和傳輸負荷。單調性就是要求哈希算法能夠應對這種情況。

分散性(Spread)

在分佈式環境中,終端有可能看不到所有的緩衝,而是隻能看到其中的一部分。當終端希望通過哈希過程將內容映射到緩衝上時,由於不同終端所見的緩衝範圍有可能不同,從而導致哈希的結果不一致,最終的結果是相同的內容被不同的終端映射到不同的緩衝區中。這種情況顯然是應該避免的,因爲它導致相同內容被存儲到不同緩衝中去,降低了系統存儲的效率。分散性的定義就是上述情況發生的嚴重程度。好的哈希算法應能夠儘量避免不一致的情況發生,也就是儘量降低分散性。

負載(Load)

負載問題實際上是從另一個角度看待分散性問題。既然不同的終端可能將相同的內容映射到不同的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不同的用戶映射爲不同的內容。與分散性一樣,這種情況也是應當避免的,因此好的哈希算法應能夠儘量降低緩衝的負荷。

平滑性(Smoothness)

平滑性是指緩存服務器的數目平滑改變和緩存對象的平滑改變是一致的。


參考文獻

 

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