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 ReplicationCP多數派 quorum 才能寫入
ZooKeeper / etcdCP強一致,partition 時拒絕寫
CassandraAPTunable consistency,預設 eventual
DynamoDBAP(可調)支援 strong consistency read(額外費用)
MongoDBCP(可調)預設 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)