分片策略:範圍 vs 雜湊 (Range vs Hash)

★★★★★Reviewed

FromDDIA

📚 From the Books

分片策略:範圍 vs 雜湊 (Range vs Hash)Partitioning

分片的第一個決策:key 怎麼對應到分片。Range 保留鍵的順序(範圍查詢快、但易熱點);Hash 打散鍵(分佈均勻、但失去範圍查詢)。這一刀直接決定你能跑哪些查詢、會不會被熱點打爆。

🧠 Intuition

TIP

一句話:range 是「照字典順序排書」——找一段連號很快,但暢銷區會被擠爆;hash 是「按書名亂數丟進櫃子」——每櫃平均,但想「找 A 到 C 的所有書」就得翻遍每個櫃子。

⚖️ 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

✍️ My Notes

2026-07-01

  • Q: 既然 hash 分片能均勻分佈,為什麼還會有熱點問題?
  • A: 要分清兩種熱點。Hash 解決的是「key 分佈不均」造成的熱點(例如 range 模式下 timestamp 全擠在尾端)。但它解不了「單一 key 太熱」——名人用戶的所有流量都綁在同一個 key 上,hash 對整個 key 算一次,永遠落同一分片,沒有更細的粒度可拆。這時只能在應用層對該 key 加隨機後綴人工拆分。換句話說,hash 攤平的是「鍵的維度」,攤不平「單鍵的流量維度」。

📖 Further Reading

🔗 Dive Deeper