一致性雜湊演算法(Consistent Hashing)最早在論文《Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web》中被提出。簡單來說,一致性雜湊將整個雜湊值空間組織成一個虛擬的圓環,如假設某雜湊函式 H 的值空間為 0-2^32-1(即雜湊值是一個 32 位無符號整形),整個雜湊空間環如下:
整個空間按順時針方向組織。0 和 232-1 在零點中方向重合。
下一步將各個伺服器使用 Hash 進行一個雜湊,具體可以選擇伺服器的 ip 或主機名作為關鍵字進行雜湊,這樣每臺機器就能確定其在雜湊環上的位置,這裡假設將上文中四臺伺服器使用 ip 地址雜湊後在環空間的位置如下:
接下來使用如下演算法定位資料訪問到相應伺服器:將資料 key 使用相同的函式 Hash 計算出雜湊值,並確定此資料在環上的位置,從此位置沿環順時針“行走”,第一臺遇到的伺服器就是其應該定位到的伺服器。
例如我們有 Object A、Object B、Object C、Object D 四個資料物件,經過雜湊計算後,在環空間上的位置如下:
根據一致性雜湊演算法,資料 A 會被定為到 Node A 上,B 被定為到 Node B 上,C 被定為到 Node C 上,D 被定為到 Node D 上。
下面分析一致性雜湊演算法的容錯性和可擴充套件性。現假設 Node C 不幸當機,可以看到此時物件 A、B、D 不會受到影響,只有 C 物件被重定位到 Node D。一般的,在一致性雜湊演算法中,如果一臺伺服器不可用,則受影響的資料僅僅是此伺服器到其環空間中前一臺伺服器(即沿著逆時針方向行走遇到的第一臺伺服器)之間資料,其它不會受到影響。
下面考慮另外一種情況,如果在系統中增加一臺伺服器 Node X,如下圖所示:
此時物件 Object A、B、D 不受影響,只有物件 C 需要重定位到新的 Node X 。一般的,在一致性雜湊演算法中,如果增加一臺伺服器,則受影響的資料僅僅是新伺服器到其環空間中前一臺伺服器(即沿著逆時針方向行走遇到的第一臺伺服器)之間資料,其它資料也不會受到影響。
綜上所述,一致性雜湊演算法對於節點的增減都只需重定位環空間中的一小部分資料,具有較好的容錯性和可擴充套件性。
另外,一致性雜湊演算法在服務節點太少時,容易因為節點分部不均勻而造成資料傾斜問題。例如系統中只有兩臺伺服器,其環分佈如下,
此時必然造成大量資料集中到 Node A 上,而只有極少量會定位到 Node B 上。為了解決這種資料傾斜問題,一致性雜湊演算法引入了虛擬節點機制,即對每一個服務節點計算多個雜湊,每個計算結果位置都放置一個此服務節點,稱為虛擬節點。具體做法可以在伺服器 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 甚至更大,因此即使很少的服務節點也能做到相對均勻的資料分佈。