已發布·持續改進
Algorithm
一致性雜湊將鍵分配到多台伺服器上,讓新增或移除節點時只搬移必要的鍵,廣泛用於分散式快取、儲存與負載平衡。
一致性雜湊(consistent hashing)是一種將鍵分散到多台伺服器的方法,由 Karger 等人於 1997 年為分散式 Web 快取提出。它把雜湊值空間視為一個環,伺服器和鍵都放在同一個環上,每個鍵歸屬於從它出發順時針遇到的第一台伺服器。為每台伺服器在環上放置多個點(虛擬節點)可以讓負載更平均。
使用 hash(key) % N 時,伺服器數量一改變,幾乎所有鍵的位置都會跟著改變,快取命中率驟降,還會產生大量資料搬移。一致性雜湊在新增一台伺服器時平均只搬移全部鍵的 1/(N+1),而且只搬往新伺服器,因此可以在運作中輕鬆擴充與縮減。Memcached 用戶端的 ketama、Amazon 的 Dynamo 論文、Cassandra,以及 Nginx 和 HAProxy 的一致性雜湊選項都以這個原理為基礎。
建議先算算 mod-N 分片會搬移多少鍵,再用排序陣列與二分搜尋實作雜湊環。接著測量虛擬節點數量增加時負載偏差如何縮小,並比較副本選擇、Rendezvous 雜湊與跳躍一致性雜湊。打好這些基礎後,在系統設計面試中也能清楚說明各種取捨。
新增或移除節點時,期望只搬移約 1/(N+1) 的鍵,既有節點之間不會互相交換鍵。
把雜湊空間視為一個圓,鍵歸屬於順時針方向的第一個節點。查詢就是在排序後的位置上做二分搜尋。
每個節點在環上放置多個點,以降低負載偏差,並用點的數量表示伺服器容量的差異(權重)。
沿順時針方向選出 R 個不同節點存放副本;Rendezvous 雜湊與跳躍一致性雜湊以其他方式達成相同目標。
以 MD5 摘要的前 8 個位元組作為環上的位置,每個節點有 100 個虛擬節點,透過 bisect.insort 插入排序清單。get 以 bisect_left 找出位置不小於鍵雜湊值的第一個點,超過結尾時回到開頭。加入節點 D 後只有約四分之一的鍵被搬移,再將它移除,所有鍵都會回到原本的節點。
consistent_hashing.py
import bisect
import hashlib
def h(key: str) -> int:
return int.from_bytes(hashlib.md5(key.encode()).digest()[:8], "big")
class HashRing:
def __init__(self, nodes=(), vnodes=100):
self.vnodes = vnodes
self.points = [] # sorted hash positions on the ring
self.owner = {} # position -> physical node
for node in nodes:
self.add(node)
def add(self, node):
for i in range(self.vnodes):
p = h(f"{node}#{i}")
bisect.insort(self.points, p)
self.owner[p] = node
def remove(self, node):
for i in range(self.vnodes):
p = h(f"{node}#{i}")
self.points.pop(bisect.bisect_left(self.points, p))
del self.owner[p]
def get(self, key):
if not self.points:
raise LookupError("ring is empty")
i = bisect.bisect_left(self.points, h(key)) % len(self.points)
return self.owner[self.points[i]]
ring = HashRing(["A", "B", "C"])
keys = [f"user:{n}" for n in range(10_000)]
before = {k: ring.get(k) for k in keys}
ring.add("D")
moved = sum(before[k] != ring.get(k) for k in keys)
print(f"moved {moved / len(keys):.1%} of keys") # about 25%
ring.remove("D")
print(all(ring.get(k) == before[k] for k in keys)) # True
python consistent_hashing.py共六章,帶你從安裝一步步認識 一致性雜湊 的核心概念。
在這裡提問、分享經驗,交流關於 一致性雜湊 的看法。
還沒有討論。來發起第一則吧。
0 則留言
登入 · 登入後即可留言。
來留下第一則留言吧。