CAP 定理
解释网络分区发生时,分布式系统为何无法同时保证线性一致性与每个请求都得到成功响应,并澄清“CAP 三选二”的常见误解。
[!info] related notes
- 所属 MOC:Distributed Systems MOC
- 前置:分布式系统、一致性模型
- 数据复制:数据复制
CAP 定理
[!abstract] 一句话定义 CAP 讨论的是:当分布式数据系统发生网络分区(P)时,无法同时保证线性一致意义下的 Consistency(C)和每个非故障节点都及时返回成功结果的 Availability(A)。工程选择发生在 Partition 期间,不是平时简单“三选二”。
三个字母分别指什么
Consistency
每次读都像从一个单一、最新、按全局顺序更新的副本读取,通常接近线性一致性语义。
它不是 ACID 中“满足业务约束”的 Consistency,也不是所有一致性模型的总称。
Availability
每个发送到非故障节点的请求最终都得到非错误响应,但不保证响应包含最新数据。
它不是“全年 99.99% uptime”的普通可用性指标。
Partition Tolerance
节点之间的消息可能丢失或延迟到无法接受,系统仍必须定义行为。
现实跨节点系统无法假设永远没有 Partition,因此 P 通常是故障前提,而不是可随意放弃的第三个功能按钮。
最小例子
Client A → Replica A
Replica A X Replica B (partition)
Client B → Replica B
Client A 在 A 写入 x=2,但 B 收不到更新。
偏向 C
Replica B 无法确认最新状态时拒绝或等待请求。
preserve single-copy illusion
→ some requests unavailable
偏向 A
Replica B 继续返回本地 x=1 或接受独立写入。
keep serving
→ stale reads or conflicting writes possible
分区恢复后还要合并或修复状态。
为什么不是“数据库永久属于 CP 或 AP”
真实系统可能按操作、数据和配置做不同选择:
- 账户余额写入 Fail Closed;
- 商品浏览允许 Stale Read;
- 同一系统读写使用不同 Quorum;
- 正常无分区时同时获得良好一致性和可用性;
- 分区期间不同 API 有不同降级策略。
因此标签只能表达默认倾向,不能代替具体操作语义。
PACELC 补充了什么
CAP 关注 Partition 时的选择;正常没有 Partition 时,系统仍常在 Latency 与 Consistency 之间取舍:
if Partition: Availability vs Consistency
else: Latency vs Consistency
PACELC 更接近日常工程调优,但也不能替代具体模型和 SLO。
CAP 不能直接回答什么
- 复制拓扑怎么选;
- 冲突怎样合并;
- 数据能否丢失;
- 延迟是多少;
- 事务隔离级别;
- Exactly-once 是否成立;
- 故障恢复需要多久。
这些还要结合 Replication、Consistency Model、Quorum、Durability 和业务不变量分析。
常见误区
[!warning] “CA 系统不需要容忍分区” 只有不发生跨节点分区的单节点/共享故障域模型才可能绕开该问题;一旦数据跨网络复制,就必须定义 Partition 行为。
[!warning] “AP 就是数据随便乱” AP 系统仍可提供因果、一致前缀、最终收敛、Read-your-writes 等约束,只是不在 Partition 时维持线性一致的单副本视图。
设计问题
面对一个 API,依次问:
- 网络分区时,返回旧数据、拒绝还是等待?
- 接受双边写入后如何检测和合并冲突?
- 哪些业务不变量不能被暂时破坏?
- 用户能否看到处理中/不确定状态?
- 分区恢复后如何 Reconcile?
掌握标准
- 能解释 CAP 的 C、A、P 精确定义。
- 能说明选择只在 Partition 期间成为硬冲突。
- 能区分 CAP Consistency 与 ACID Consistency。
- 能用具体 API 而不是数据库品牌做分析。
- 知道 CAP 不能替代 Replication、Durability 和 Transaction 设计。