CONSISTENT HASHING算法實現

 

  在做服務器負載均衡時候可供選擇的負載均衡的算法有很多,包括:  輪循算法(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 是分佈式系統負載均衡的首選算法。

1、Consistent Hashing算法描述

    下面以Memcached中的Consisten Hashing算法爲例說明(參考memcached的分佈式算法)。

    由於hash算法結果一般爲unsigned int型,因此對於hash函數的結果應該均勻分佈在[0,232-1]間,如果我們把一個圓環用232  個點來進行均勻切割,首先按照hash(key)函數算出服務器(節點)的哈希值, 並將其分佈到0~232的圓上。

    用同樣的hash(key)函數求出需要存儲數據的鍵的哈希值,並映射到圓上。然後從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器(節點)上。

Consistent hashing,memcached,load balancing,負載均衡,算法,key-value store Consistent Hashing原理示意圖

    新增一個節點的時候,只有在圓環上新增節點逆時針方向的第一個節點的數據會受到影響。刪除一個節點的時候,只有在圓環上原來刪除節點順時針方向的第一個節點的數據會受到影響,因此通過Consistent Hashing很好地解決了負載均衡中由於新增節點、刪除節點引起的hash值顛簸問題。

Consistent hashing,memcached,load balancing,負載均衡,算法,key-value storeConsistent Hashing添加服務器示意圖

    虛擬節點(virtual nodes):之所以要引進虛擬節點是因爲在服務器(節點)數較少的情況下(例如只有3臺服務器),通過hash(key)算出節點的哈希值在圓環上並不是均勻分佈的(稀疏的),仍然會出現各節點負載不均衡的問題。虛擬節點可以認爲是實際節點的複製品(replicas),本質上與實際節點實際上是一樣的(key並不相同)。引入虛擬節點後,通過將每個實際的服務器(節點)數按照一定的比例(例如200倍)擴大後並計算其hash(key)值以均勻分佈到圓環上。在進行負載均衡時候,落到虛擬節點的哈希值實際就落到了實際的節點上。由於所有的實際節點是按照相同的比例複製成虛擬節點的,因此解決了節點數較少的情況下哈希值在圓環上均勻分佈的問題。

Consistent hashing,memcached,load balancing,負載均衡,算法,key-value store

虛擬節點對Consistent Hashing結果的影響

    從上圖可以看出,在節點數爲10個的情況下,每個實際節點的虛擬節點數爲實際節點的100-200倍的時候,結果還是很均衡的。

2、Consistent Hashing算法實現:

    文章Consistent Hashing中 描述了Consistent Hashing的Java實現,很簡潔。

 

 

發佈了77 篇原創文章 · 獲贊 3 · 訪問量 62萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章