CAP 与一致性取舍

CAP 用来解释分布式数据在网络分区时不能同时满足的一组保证。它最有用的地方,是帮助我们把“出故障时怎样处理读写”讲清楚,而不是给整个产品贴一个 CP 或 AP 标签。

根据业务不变量选择分区期间的行为

先准确理解三个词

一致性(Consistency)在 CAP 的常见形式中指线性一致性(Linearizability):操作看起来像在调用与返回之间的某个时刻生效,并尊重真实时间先后。如果一次写已经返回成功,之后发起的读取不能返回被它覆盖的旧值。

可用性(Availability)要求非故障节点接收到的请求最终得到相应的操作结果;让节点一直等或一律报错,并不能满足这个要求。它不是月度 99.9% 可用率,也不直接给出固定的延迟上限。

分区(Partition)指节点之间的通信可能中断或消息被持续丢弃。工程上不能通过口头选择“不要 P”来排除网络隔离。网络没有分区时,CAP 也不要求系统主动放弃一致性或可用性。

两个区域断连时的具体矛盾

假设美国和欧洲各有一个 GPU 配额副本,初始都显示剩余 1。断连之后,两边各收到一次分配请求。如果两边都立即承诺成功,就可能承诺了两份资源;如果欧洲无法确认最新状态而拒绝或等待,它就牺牲了这部分操作在分区期间的可用性。

一致性优先并不意味着所有节点、所有功能全部停止。有多数派协议的系统可能继续在能形成多数派的一侧处理写入,而隔离少数派停止承诺;这一行为仍取决于协议、故障假设和读路径。不能只在架构图上画一个 Leader 就宣称强一致。

按操作选择,而不是按公司或数据库类型选择

操作需要维护的约束分区时可能的策略
分配最后一份 GPU 配额不能重复承诺同一份资源。只允许授权写入方提交,其他请求失败或等待。
展示训练进度可以容忍短暂落后。返回已知进度,并表达时间或版本。
浏览公开模型介绍可接受旧内容。继续读本地副本,恢复通信后更新。
发布可恢复检查点不得把未完成对象标为可用。由受控提交路径决定可见状态。

“涉及资金就整个系统强一致”过于粗糙。真正要描述的是哪些记录、哪些读写和哪些不变量不能被破坏,以及故障时允许哪些操作继续。

几种一致性保证不能混为一谈

线性一致性关注单个对象或规定范围内操作的实时顺序;可串行化(Serializability)关注多个事务的效果是否等价于某种串行执行,两者并不自动互相推出。严格可串行化(Strict Serializability)再加入真实时间约束。

读己之写(Read-your-writes)保证会话能看到自己已完成的写;单调读(Monotonic Reads)避免同一会话倒退。它们不等于全局线性一致。最终一致性(Eventual Consistency)要求在停止新写入并满足通信与修复等条件后收敛,不自动承诺几秒内完成,也不规定冲突如何解决。

ACID 中的一致性是数据库约束与合法状态的概念,不是 CAP 里的同一个 C。SQL、NoSQL、事务和复制这些词,也都不能单独证明跨区域的端到端保证。

复制、Quorum 与读取路径

同步复制增加确认前的协调;异步复制允许更快返回,但读副本可能落后。读请求是否经过最新 Leader、是否读取已提交版本,以及故障切换是否可能丢失已确认写入,都会影响用户看到的保证。

读写 Quorum 满足 R + W > N 可以让集合相交,但集合相交本身并不是线性一致性的完整证明。并发写、版本选择、失败写入、成员变更和故障恢复仍需要正确的协议。

不同访问路径也可能有不同语义。例如 DynamoDB 文档区分表、局部二级索引与全局二级索引的读取保证。不能因为主表支持强一致读取,就推断所有查询入口都一样。

没有分区时,延迟也有代价

PACELC 强调:发生分区时讨论可用性与一致性;正常通信时仍可能在延迟(Latency)与一致性之间付出协调成本。跨洲确认通常比本地副本读取需要更多网络等待,但具体保证取决于实现,不能只靠地理距离给系统分类。

从接口到客户端的完整路径都要保持约定:如果数据库读是强一致的,但前面返回旧缓存,用户看到的接口仍然可能是陈旧的。设计讨论应把缓存、会话、复制和故障切换放在一起。

关联与来源

缓存 · 数据建模 · 分片

学习入口:Hello Interview · CAP Theorem(已登录核对书面章节)。本页用配额分配与具体读路径解释语义,不把定理简化成任何时候任选两个。