跳到主要内容

CAP 理论

CAP 理论说明:发生网络分区时,分布式系统无法同时保证线性一致性和每个非故障节点上的请求都得到响应。

1. CAP 中的三个性质有严格定义

CAP 讨论的是一个通过网络复制数据的系统:

  • Consistency:这里指类似线性一致性的单副本语义,每次读都表现得像读取一个按实时顺序更新的值。
  • Availability:每个发送到非故障节点的请求最终都收到非错误响应,但该响应不要求包含最新写入。
  • Partition tolerance:即使节点之间的消息被任意延迟或丢失,系统仍按既定规则运行。

这里的可用性比工程中的“99.99% 可用”更严格,Consistency 也不等同于 ACID 中业务约束的一致性。讨论 CAP 时要先统一这些定义。

2. 约束只在网络分区期间出现

假设一份数据复制在节点 A 与 B,网络分区使两者无法通信。客户端在 A 写入新值后,又向 B 发起读取:

  • B 如果必须立即返回,就可能返回旧值,放弃线性一致性。
  • B 如果拒绝或等待到能够确认最新值,就放弃 CAP 定义中的可用性。

在网络正常时,系统可以同时提供一致响应与可用服务。CAP 不表示一个分布式系统在任何时刻“最多只能选两个”,也不要求在设计表格中把 P 当成可随意关闭的功能。网络分区是否发生由运行环境决定,系统要设计的是分区期间各类操作怎样响应。

3. 一致优先会拒绝无法确认的操作

一致优先的系统在无法获得足够副本确认时,会拒绝或阻塞可能破坏单副本语义的读写。例如多数派复制系统失去多数派后,少数派不能继续确认写入。

这样可以避免两个分区分别接受冲突写入,但代价是部分仍在运行的节点无法服务相关操作。它适合余额扣减、唯一所有权和配置元数据等不能接受冲突结果的状态。

“等待所有副本同步”不是一致性的必要条件。多数派、leader lease 和共识日志都可以在明确条件下确认写入;关键是后续读取与领导权切换不能遗漏已经承诺的数据。

4. 可用优先会接受暂时分歧

可用优先的系统允许不同分区继续响应,并在网络恢复后传播和合并结果。它需要定义冲突语义,例如:

  • last-write-wins 依据可比较版本选择一个值。
  • 集合合并或 CRDT 保留双方可组合的更新。
  • 业务层保留冲突,交给用户或补偿流程处理。

“最终会同步”还不够。系统要说明是否存在无法自动合并的操作、收敛需要多久,以及读者能否接受分区期间的旧值或冲突值。

5. 选择通常落实到具体操作

一个产品可以对不同数据和操作采用不同策略:

  • 商品详情允许读取旧副本,库存扣减要求多数派确认。
  • 用户发布内容可以先本地受理,账号所有权变更必须一致。
  • 系统允许旧数据读取,但在无法确认领导权时拒绝写入。

因此,“这个系统是 CP 还是 AP”只能作为粗略标签。更有效的问题是:哪项操作需要何种一致性,分区发生时从哪个节点请求,会得到成功、旧值、冲突还是错误。

6. CAP 与一致性模型需要分开理解

线性一致性要求操作看起来在调用与返回之间某个时刻原子生效,并尊重真实时间顺序。顺序一致性只要求所有进程看到相同操作顺序,不要求该顺序符合真实时间。因果一致性保证有因果关系的操作顺序;最终一致性只描述停止更新后副本最终收敛。

这些模型不能简单排列成“性能逐步变快”的固定阶梯。实现成本还取决于网络往返、副本位置、冲突概率和工作负载。CAP 中的 C 对应的是强单副本语义,不能把所有一致性模型都塞进 C 与 A 的一条连续滑杆。

7. 延迟在没有分区时仍然需要权衡

即使网络没有完全分区,跨地域副本也会出现高延迟。同步等待远端副本可以降低数据丢失或旧读风险,却增加写入延迟;就近响应可以降低延迟,但需要接受复制滞后或冲突。

PACELC 用一句话补充这个工程问题:发生 Partition 时在 Availability 与 Consistency 之间取舍;Else 情况下仍要在 Latency 与 Consistency 之间取舍。它补充了正常网络下的延迟成本,并不替代 CAP 的证明。

8. 常见问题

8.1 单机数据库需要讨论 CAP 吗

单个节点没有副本间网络分区,CAP 的三方约束不适用于其内部读写。一旦数据库通过网络复制并允许客户端访问多个副本,故障切换和分区行为就需要讨论。

8.2 返回错误算可用吗

在 CAP 的严格定义中,无法完成操作而返回错误不满足 availability。工程系统仍可能选择快速失败,因为它比无限等待更容易恢复;这属于产品可用性设计,不能与 CAP 定义混用。

9. 面试题

9.1 网络分区发生时,为什么一致性和可用性无法同时保证

出现公司:字节跳动

考察重点

  • CAP 三个性质的严格定义。
  • 分区期间旧读、拒绝请求与多数派。
  • 操作级权衡、一致性模型和延迟成本。

相关内容:第 1 节“CAP 中的三个性质有严格定义”至第 7 节“延迟在没有分区时仍然需要权衡”。

参考回答

假设数据复制在 A、B 两个节点,网络分区后 A 接受了新写入,B 无法知道该值。B 若仍要对每个请求立即给出非错误响应,就可能返回旧值,失去线性一致性;若为了确认最新值而拒绝或等待,就不满足 CAP 定义的可用性。因此约束发生在网络分区期间,正常通信时可以同时提供一致响应和服务。

实际设计要落到操作:强一致写入可以要求多数派确认,失去多数派时拒绝;允许冲突的数据可以在两侧受理,恢复后按版本、CRDT 或业务规则合并。同一个系统对库存与商品详情也可能使用不同策略。CAP 的 C 是单副本一致语义,A 是每个非故障节点上的请求都响应,不能直接等同于 ACID 一致性或可用率指标。