TL;DR | 面試情境模擬 #
👴 面試官:什麼是 Consistent Hashing?解決了什麼問題?
🧑💻 你:傳統 Hash 分配(key % N)在增減節點時,幾乎所有 key 都要重新分配,對資料庫或 Cache 是災難。Consistent Hashing 把所有節點和 key 都映射到一個 0 到 2^32 的環上,每個 key 順時針找到最近的節點。增減一個節點時,只有這個節點附近的 key 需要搬移,其他資料不受影響。
為什麼普通 Hash 不夠用 #
假設有 3 台 Cache Server,用 key % 3 決定存哪台:
key "user:1" → hash 101 → 101 % 3 = 2 → Server 2
key "user:2" → hash 102 → 102 % 3 = 0 → Server 0
現在加一台 Server,變成 key % 4:
key "user:1" → hash 101 → 101 % 4 = 1 → Server 1 ← 換了!
key "user:2" → hash 102 → 102 % 4 = 2 → Server 2 ← 換了!
問題:幾乎每個 key 都換了位置,舊的 Cache 全部 Miss,所有請求直打資料庫 → Cache Stampede(雪崩)。
Consistent Hashing:Hash Ring #
把所有可能的 Hash 值排成一個環(0 到 2^32-1),節點和 key 都映射到環上的位置:
0
Server A (100)
╱ ╲
3000 500
│ │
Server C (2800) Server B (700)
╲ ╱
2500
查找規則:每個 key 對應的值,順時針方向找到的第一個節點,就是它的目標。
加入新節點 #
加入 Server D (1200)
原本:hash 值在 700-2800 之間的 key 都在 Server C
加入後:700-1200 的 key 移到 Server D,其餘不變
只有一小段 key 需要搬移
虛擬節點(Virtual Nodes) #
問題:節點數量少時,每個節點的負載可能不均衡(有的節點管的範圍特別大)。
解法:每個實體節點在環上放多個虛擬節點(例如 150 個),讓負載更平均分散。
Server A → A-1, A-2, A-3, ..., A-150(散布在環的各個位置)
Server B → B-1, B-2, B-3, ..., B-150
Cassandra、Amazon DynamoDB 都用了虛擬節點。
💡 面試官可能會追問 #
Q1:Consistent Hashing 用在哪些地方? #
- 分散式 Cache:Memcached、Redis Cluster
- CDN:決定哪台邊緣節點快取這個資源
- 負載均衡 (Load Balancer):讓同一個 client 的請求路由到同一台 Server(Sticky Session)
- 分散式資料庫:Cassandra、DynamoDB 的資料分片
Q2:Consistent Hashing 能完全解決資料不均衡嗎? #
不完全。即使有虛擬節點,如果某個節點的資料特別「熱」(Hot Key),依然會有熱點問題。需要額外的解法,例如:在 Hot Key 後面加隨機後綴分散到多個節點、讀取時加本地 Cache 等。
Q3:節點 Crash 後資料怎麼辦? #
這是 Consistent Hashing 本身不解決的問題,需要搭配副本機制(Replication)。每個資料在環上順時針存到 N 個節點(例如 N=3),一台 Crash 了,其他副本可以繼續服務。