CAP Theorem 的基本定義
Eric Brewer 在 2000 年提出,2002 年被正式證明:
- C(Consistency):所有節點看到同樣的資料(線性一致性——任何讀都能看到最新的寫)
- A(Availability):每個請求都能收到回應(不保證是最新資料,但一定有回應)
- P(Partition Tolerance):即使部分節點之間網路中斷,系統繼續運作
CAP 說:這三個同時只能有兩個。
P 不是真正的選項
這是最常見的誤解:以為可以選 CA(放棄 P)。
現實是:分散式系統必然面對 Network Partition(節點之間的網路連線可能失敗)——這不是設計選擇,是物理現實。任何跨機器的系統都有網路中斷的可能。
所以真正的選擇是:Network Partition 發生的時候,你要 C 還是 A?
- CP(選 C 放 A):partition 發生時,拒絕服務(返回 error),不允許讀到舊資料。ZooKeeper、etcd、HBase。
- AP(選 A 放 C):partition 發生時,繼續服務,但可能讀到舊資料(暫時不一致)。Cassandra、DynamoDB、CouchDB。
不同 DB 的定位
| 系統 | 分類 | 說明 |
|---|---|---|
| PostgreSQL(單機) | CA | 沒有分散,不存在 partition 問題 |
| MySQL Group Replication | CP | 多數派 quorum 才能寫入 |
| ZooKeeper / etcd | CP | 強一致,partition 時拒絕寫 |
| Cassandra | AP | Tunable consistency,預設 eventual |
| DynamoDB | AP(可調) | 支援 strong consistency read(額外費用) |
| MongoDB | CP(可調) | 預設 majority write concern |
PACELC:CAP 的延伸
CAP 只描述 partition 時的行為。大多數時間系統是正常運作的,正常運作時也有 trade-off:
PACELC = 如果 Partition,選 A 還是 C;Else(正常時)選 Latency 還是 Consistency
- DynamoDB:PA/EL——partition 時選 A,正常時選 L(低延遲)
- etcd / ZooKeeper:PC/EC——partition 時選 C,正常時選 C(強一致,高延遲)
- Cassandra:PA/EL——partition 時選 A,正常時低延遲優先
PACELC 更完整地描述了實際 DB 的行為,因為 partition 是少見的,正常時的 latency vs consistency 才是日常選型的核心考量。
常見誤解
誤解 1:「我用 MySQL 主從複製,有 Availability 也有 Consistency」
主從複製是 AP,不是 CA:主庫掛掉的時候需要手動或自動 failover(這段期間不可用),而且從庫可能落後主庫(replication lag = 讀到舊資料)。
誤解 2:「Consistency 就是 ACID 的 C」
不一樣:
- ACID C = transaction 執行完畢後資料符合 schema 約束(完整性)
- CAP C = 分散式系統中所有節點同時看到相同的資料(線性一致性)
誤解 3:「CP 系統就是完全一致」
CP 的 C 是強一致性 in partition scenarios——正常時可能也會有 consistency 和 latency 的 trade-off,取決於 quorum 設定。
實務影響
CAP 不是理論,它直接影響設計決策:
電商下單(不能讀到舊庫存)→ CP,可以稍微降低 availability(用戶偶爾看到「系統維護」比超賣嚴重)
社群 Feed(讀到晚 1 秒的貼文沒關係)→ AP,高可用比強一致更重要
分散式 Counter / 排行榜(短暫不精確可接受)→ AP + 定期同步
分散式鎖 / 配置中心(需要強一致,不然多個節點行為不一樣)→ CP(ZooKeeper / etcd)