Key-Value 的限制是為了換分片而付的價
Key-Value 資料庫結構上就是一張有主鍵索引的表:
CREATE TABLE kv (key text PRIMARY KEY, value bytea);「用 key 查得很快」的機制也真的就是主鍵索引(底層是 hash table 或 LSM-tree/B-tree)。用 SQL 實作一個 KV store 沒有任何理論障礙。
所以差別不在它多了什麼,在它刻意不給你什麼。
它拿掉的四樣東西
| 拿掉 | 意思 |
|---|---|
| 按 value 查 | 沒有 secondary index,只能問「key 是 X 的那個」 |
| JOIN | 沒有 |
| 跨 key 的交易 | 很受限或沒有,不能原子地同時改 key A 和 key B |
| 看得懂 value | value 是不透明的 bytes,所以沒有約束、沒有聚合、沒有型別 |
拿掉之後,分片變成免費的
每次操作只碰「一個 key」
→ key 唯一決定它在哪個節點
→ 每次操作只需要「一個節點」參與
→ 節點之間不需要任何協調 → 加機器就是純粹加吞吐
對照 SQL:JOIN 要配對兩張表、交易要改多列,跨節點就要 2PC 和分散式鎖。SQL 難分片,正是因為它允許你做「牽涉多筆資料」的操作。
限制不是缺陷,是換擴展性付的價。 KV 是一張只准用主鍵查、不准 JOIN、不准跨列交易的表——而那幾個「不准」,就是它能無痛分片的原因。
兩個邊界要記
- Redis 不完全符合上面的描述。它的 value 有豐富型別(list、set、sorted set、hash)並提供原子操作(
INCR、ZADD、LPUSH),所以才做得到 rate limiter——那需要「原子地加一並檢查」,純粹的不透明 KV 做不到。 - MongoDB 不是 KV,是 document database,它有 secondary index、可以按欄位查、還有 aggregation pipeline。上面那些「不准」對它不成立,它快的原因是另一個,見 Document DB 快在局部性:把該一起用的東西實際存在一起。
分片本身怎麼決定資料落點,見 key-range sharding 用順序換熱點,hash 用均勻換範圍查詢。