CAP 定理与 PACELC:一致性还是可用性
03-一致性与复制
核心
约 15 分钟
#CAP#PACELC#权衡
更新 2026-10-02
当前状态:未学
本文基于模型知识整理(生成时未联网核对),关键结论建议对照经典文献复核。
一句话定义
CAP 定理指出:网络分区(P)发生时,一致性与可用性不可兼得(只能 C 或 A 择一);PACELC 进一步补充——即使没有分区,也必须在一致性与延迟之间取舍。
为什么重要
CAP 是分布式系统最广为引用也最常被误读的定理。正确理解它能建立"权衡是制度性的"这一直觉:不存在又强一致、又永远可用、又低延迟的系统;工程选型的本质是决定在哪个维度让步、让多少。
前置知识
kp-005(网络分区这一故障形态)、kp-002(延迟指标)。
核心概念
- C(Consistency):特指线性一致性——所有读写表现得像单机,读总返回最近已完成的写(不是泛指一切一致性,见 kp-013)。
- A(Availability):每个非故障节点收到的请求都必须有(非错误的)响应,不允许"稍后再试"。
- P(Partition tolerance):网络可以任意分区/丢消息。这不是可选项——跨节点网络必然会坏,所以现代解读是:分区发生时,C 与 A 二选一。
- PACELC:Else(无分区时),Latency 与 Consistency 取舍——例如 Dynamo 无分区时也因 quorum 副本数而存在读写延迟/一致性权衡。
原理与机制
证明思路(两节点反例):网络把节点 N1、N2 隔断后,客户端分别向二者发起读写。若两者都可响应(A),则它们的副本独立演化,读到的数据可以互相矛盾(破坏 C);若要保证 C,必须有一侧拒绝服务(破坏 A)。而在无分区时,这个矛盾不存在——CAP 只在分区时咬人。
误读纠正(工程上最重要的一节):
- "CAP 三选二,所以选 CP 或 AP"——P 不可弃,真正的选择只在分区时刻:封写(CP)还是继续读写然后修复(AP)。
- "AP 系统没有一致性"——AP 系统通常提供最终一致(kp-013),只是放弃线性一致。
- "分区很少发生所以 CAP 不重要"——恰恰因为分区不可预测、随时发生,系统必须预先声明分区时的行为;且 PACELC 告诉你无分区时也没有免费午餐。
PACELC 的实用价值:即使单机房、无分区,跨副本同步(强一致)也要付 RTT 延迟;Dynamo 选择 quorum 弱化一致性以降延迟,Spanner 用 commit wait 换外部一致——两条路线的差异就是 ELC 分支。
图示
分区发生 (P 必然存在)
/ \
保证 C (线性一致) 保证 A (人人可响应)
→ 拒绝部分请求 → 允许副本分叉,事后修复
(CP: etcd/ZooKeeper) (AP: Cassandra/Dynamo)
无分区时 (PACELC): 强一致 ⇄ 低延迟 依然二选一
实例或案例
- etcd/ZooKeeper(CP 路线):分区时少数派一侧不可用(拒绝写甚至拒绝服务),保证配置数据绝不读旧。
- Cassandra/DynamoDB 可调一致性(AP 倾向):正常时以 R/W 参数平衡延迟与新鲜度;分区时按 sloppy quorum 继续服务。
- Spanner(CP + 高可用):用 TrueTime + Paxos 在全球范围保线性一致,但接受写延迟与少数派不可用。
常见误区
- 误区一:"我们的系统是 CA 的"。跨节点的系统不存在 CA——P 是物理现实;自认 CA 通常意味着没测过分区行为。
- 误区二:"CAP 里的 C 就是一般说的数据一致性"。它特指线性一致,系统文档说"我们保 CAP-C"时务必确认口径。
- 误区三:"AP + 最终一致 = 不需要考虑冲突"。分区窗口内的冲突写必须靠版本向量/CRDT/业务补偿解决(kp-015),不会自己消失。
与其他知识点的关系
自测题
- CAP 中 C、A、P 的精确含义?
答:C=线性一致;A=每个非故障节点对请求给出非错误响应;P=容忍任意网络分区,不可放弃。
- 为什么说"三选二"是常见误读?
答:P 不可选;分区的常态下只是"分区时保 C 还是保 A",无分区时选择的是延迟与一致(PACELC)。
- PACELC 比 CAP 多回答了什么问题?
答:无分区时的一致性与延迟权衡——强一致必然增加跨副本通信延迟,弱一致可降延迟但读旧。
延伸阅读
- Eric Brewer, "Towards Robust Distributed Systems"(PODC 2000 keynote);Gilbert & Lynch 的形式化证明(SIGACT News 2002)。
- Daniel Abadi, "Problems with CAP, and Yahoo's little known NoSQL system"(PACELC, 2012)。
- Martin Kleppmann, "Please stop calling databases CP or AP"(2015 博文)。