分片的第一個決策:key 怎麼對應到分片。Range 保留鍵的順序(範圍查詢快、但易熱點);Hash 打散鍵(分佈均勻、但失去範圍查詢)。這一刀直接決定你能跑哪些查詢、會不會被熱點打爆。
🧠 Intuition
TIP
一句話:range 是「照字典順序排書」——找一段連號很快,但暢銷區會被擠爆;hash 是「按書名亂數丟進櫃子」——每櫃平均,但想「找 A 到 C 的所有書」就得翻遍每個櫃子。
- 核心張力:順序性與均勻性不可兼得。保留順序就保留了熱點;打散熱點就打散了範圍。
- Range:key 有序地切成連續區間,每個分片負責一段。天生支援
WHERE key BETWEEN ...與排序掃描。 - Hash:對 key 取雜湊再決定分片,相鄰 key 被打散到不同分片。負載均勻,但範圍查詢退化成對所有分片的 scatter/gather。
- 分片邊界本身要可被所有節點一致地計算或查詢(routing),否則 client 不知道 key 在哪。
⚖️ Tradeoffs
Range 分片 — 範圍查詢友善,但易熱點
- 按 key 排序切成連續區間(如
[a–f] [g–m] ...),邊界可隨資料量動態分裂/合併。 - 優點:範圍掃描、排序、
BETWEEN都只命中少數相鄰分片,效率高。 - 缺點:若寫入集中在 key 的某一段(如以 timestamp 當 key,新資料全往最後一個分片擠),就會產生寫入熱點。
- 代表:HBase、MongoDB(range mode)、Bigtable。
Hash 分片 — 分佈均勻,但失去範圍查詢
- 對 key 算
hash(key),再映射到分片。好的 hash 讓相鄰 key 也被均勻打散。 - 優點:負載與儲存天然均勻,連續寫入的 timestamp 也會被攤平,不易單點熱點。
- 缺點:範圍查詢失效——相鄰 key 散落各分片,
BETWEEN變成查全部分片再彙整。 - 注意:別用
hash(key) % N,N 一變幾乎全部要搬(見 rebalancing)。 - 代表:Cassandra、DynamoDB、Riak。
一致性雜湊 (Consistent Hashing)
- 把 hash 空間想成一個環,節點與 key 都落在環上,key 順時針找到的第一個節點即歸屬。
- 目的不是均勻分佈本身,而是讓加減節點時只搬遷環上相鄰的一小段,而非全量重雜湊。
- 實務再加 virtual node(vnode):每個實體節點在環上放多個點,讓負載更平滑、異質機器好配權重。
- 是 Dynamo / Cassandra 風格再平衡的基礎。
熱點與名人問題 (Hot Spot / Celebrity Problem)
- 即使用 hash 分片,單一 key 過熱仍救不了——某個爆紅用戶(名人)的所有讀寫都打到同一分片。
- 因為 hash 是對「整個 key」算的,同一個 key 永遠落同一分片,hash 無法再細分。
- 折衷:對熱 key 加隨機後綴(如
userid_00~userid_99)人工拆成多個 key 分散寫入,代價是讀取要彙整這 N 個子 key,且要自己記錄哪些 key 需要特殊處理。
複合鍵折衷 (Compound Key)
- 把主鍵拆成兩段:前段 hash 決定分片,後段保留排序(Cassandra 的 partition key + clustering key 即此設計)。
- 效果:跨分片均勻分佈,但「同一 partition key 內」仍可做有序範圍掃描。
- 典型用法:
(user_id, timestamp)——不同使用者打散到各分片,單一使用者的時間序列在分片內連續,可高效掃一段時間範圍。 - 代價:範圍查詢只能在「固定前段」的前提下進行;跨多個 partition key 的範圍查詢仍要 scatter/gather。
🔑 Takeaways
- Range vs Hash 的本質取捨:順序性 ↔ 均勻性。要範圍查詢就選 range(承受熱點風險),要均勻負載就選 hash(放棄範圍查詢)。
- Range 配動態分裂/合併避免區間爆量;hash 配一致性雜湊 + vnode 讓再平衡只搬一小段。
- Hash 解「鍵分佈不均」的熱點,但解不了「名人問題」(單鍵過熱)——需在應用層加隨機後綴拆分。
- 複合鍵(前段 hash、後段排序)是兼顧均勻與局部範圍查詢的經典折衷。
2026-07-01
- Q: 既然 hash 分片能均勻分佈,為什麼還會有熱點問題?
- A: 要分清兩種熱點。Hash 解決的是「key 分佈不均」造成的熱點(例如 range 模式下 timestamp 全擠在尾端)。但它解不了「單一 key 太熱」——名人用戶的所有流量都綁在同一個 key 上,hash 對整個 key 算一次,永遠落同一分片,沒有更細的粒度可拆。這時只能在應用層對該 key 加隨機後綴人工拆分。換句話說,hash 攤平的是「鍵的維度」,攤不平「單鍵的流量維度」。