四張圖理解一致性哈希算法(Consistent Hashing)

1.簡述

1.1.哈希算法

哈希算法:將任意長度的輸入通過散列算法轉換成固定長度的輸出。

哈希算法是一種映射算法,將任意個數的輸入映射爲固定個數的哈希值。

1.2.應用場景舉例

分佈式緩存

現有用戶數據3000萬,爲提高訪問速度,將用戶基本信息保存在緩存中,其中:

  • key=user:{uid},其中uid爲用戶ID,由UUID生成。value爲姓名、賬號級別等構成的Json串。
  • 爲了分擔單臺服務器壓力,將緩存數據分攤在3臺服務器上。
  • 爲了能夠快速定位某個用戶所在的服務器,通過 key % 3的哈希算法分配圖片的存儲位置。
  • 理想情況下,服務器node2有1000萬用戶信息,相當於1000萬個key經過哈希都映射爲哈希值2.

其他應用:

  • 數據庫分表

1.3.普通哈希算法的缺陷

正常情況下,上述哈希算法是沒有問題的。

但是,因爲一些原因,需要增減服務器,這是必然導致哈希算法的變化,例如變爲 key % 5

當哈希算法的模數發送變化時,原有的映射值幾乎全部失效,需要重新映射幾乎全部數據,這個工作量十分巨大。

缺陷總結當增加或移除節點時,普通哈希算法幾乎需要重新映射全部關鍵字。

一致性哈希算法能夠在一定程度上解決上述缺陷。

2.一致性哈希算法

一致性哈希 是一種特殊的哈希算法。

在使用一致哈希算法後,節點的改變平均只需要對K/N 個關鍵字重新映射,其中K是關鍵字的數量,N是節點數量。

下面分表講述一致性哈希的幾個關鍵問題:算法步驟、節點增減、哈希偏斜、虛擬節點。

2.1.算法步驟

哈希算法也是一種取模算法,只是,模數固定爲2^32,也就是說哈希值範圍:0 ~ (2^31 - 1),如下圖所示:

算法步驟

一致性哈希環:

  • 圖中的圓環稱之爲一致性哈希環,由2^32個節點構成。。
  • 節點按照順時針排列,正上方節點爲0,節點0的左側相鄰節點爲2^31-1節點。

一致性哈希算法:

  1. 對服務器進行ip % (2^32)哈希,結果如圖中綠色的點所示。
  2. 對key進行key % (2^32)哈希,結果如同種紫色的點所示。
  3. 判斷key所屬服務器:從紫色點的位置開始,順時針探索,遇到的第一個綠色的點,就是其所屬的服務器。

2.2.增減節點

那麼,一致性哈希算法,如何在一定程度上解決節點增減引起的問題呢?如下圖所示:

算法步驟

節點增加:

  • 圖中節點D爲新增節點。
  • 此時,只需將節點D節點B之間的key重新映射節點D即可,圖中只有1個key受此影響。

節點減少

  • 圖中節點A爲移除節點。
  • 此時,只需將節點A節點C之間的key重新映射節點BB即可,圖中只有3個key受此影響。

總結:(理想情況下)

  • 假定共有K個key和N個節點,每個節點上存儲K/N個key。
  • 當新增節點時,只需將新增節點內新增節點的上個節點之間的key重新映射至新增節點即可,共計(K/N)/2個key。
  • 當移除節點時,只需將移除節點移除節點的上個節點之間的key重新映射至移除節點的下個節點即可,共計(K/N)個key。
  • 所以說,一致性哈希能夠在一定程度上解決增減節點的問題,而不是完全解決。

2.3.哈希偏斜

討論哈希問題,必然需要討論哈希偏斜問題。下圖就是一致性哈希偏斜的例子:

算法步驟

如圖中所示:

  • 節點A上映射了9個key,而節點C上只映射了1個key。
  • 這種情況下,理論上,服務器A需要承受的壓力是服務器C的9倍。

那麼,一致性哈希如何解決哈希偏斜問題,這就需要進入虛擬節點的概念了。

2.4.虛擬節點

下圖就是增加了虛擬節點的一致性哈希環:

算法步驟

如圖所示:

  • 深綠色節點爲實際服務器的哈希結果,淺綠色節點爲虛擬節點。
  • 虛擬節點如何產生?很多種方法,如:ip+number % (2^32)
  • 如圖,虛擬節點B1和B2都是服務器B的IP+順序號進行一致性哈希算法生成的,所以映射到B1和B2的key其實還是映射到了節點B上。
  • 增加虛擬節點之後,節點A、B、C上分別映射了3、4、5個節點,偏斜情況大大改觀。

總結:

  • 在一致性哈希算法中,可以通過虛擬節點解決哈希偏斜問題。
  • 理論上,增加的虛擬節點越多,哈希值分佈越平均。
  • 當然,也要注意虛擬節點的生成算法是否合理,生成的虛擬節點是否分佈平均。

3.參考

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