CAP 理论
CAP 理论说明:发生持续的网络分区时,分布式系统无法同时保证线性一致性和每个非故障节点的可用性。理解它的关键是推导一条具体请求该怎么办:节点联系不上其他副本时,是返回可能过期的值,还是等待、拒绝请求?这也决定了业务在故障期间还能提供哪些功能。
1. 面试核心
先记住这几条,再读正文- CAP 的 C 指线性一致性:每次操作看起来瞬间生效,并遵守非重叠操作的真实时间顺序。
- CAP 的 A 要求每个非故障节点收到的请求最终正常完成,返回错误不算完成数据操作。卡 · 多数派服务与请求范围
- 持续网络分区下,节点无法获知另一侧的新写入,因此无法同时保证 C 与 A。卡 · 三个性质的定义
- 多数派继续服务时,少数派拒绝请求仍不满足 CAP 的全节点可用性,即使大部分用户还能正常使用系统。
- 网络正常时也有取舍:等待远端确认会增加延迟,PACELC 把这类延迟与一致性的取舍也纳入讨论。
2. 三个性质的定义
CAP 中的三个字母有各自明确的含义,不能直接套用日常所说的“一致”和“可用”。
- 一致性(Consistency,C)在这里指线性一致性:每次操作看起来在调用与返回之间的某一刻原子生效。一次写入已经返回成功,之后才开始的读就应看到这次写入或更新的结果。
- 可用性(Availability,A)要求每个非故障节点收到的请求最终正常完成。它没有规定固定的毫秒级期限,但不能靠返回错误来满足要求,因为数据操作并未完成。
- 分区容忍性(Partition tolerance,P)要求把节点间可能持续无法通信的情况纳入保证范围。即使消息一直被丢弃,系统也得有处理读写的规则。
这里的网络分区不等于节点宕机。节点可以仍在运行,也能接收客户端请求,只是无法和另一部分节点交换信息。
3. 网络分区时的约束
分区造成的困难是:节点必须回答请求,却拿不到作出正确回答所需的信息。假设 A、B 都保存初始值 0,按下面的顺序执行:
- A、B 之间发生网络分区。
- A 接受写入 1,并向客户端返回成功。
- 写入返回后,另一个客户端从 B 读取这个值。
B 仍然只知道初始值 0。如果返回 0,就违反了线性一致性,因为读取发生在写入成功之后。如果一直等待 A 的消息,而分区始终不恢复,这个请求就无法最终完成。
B 也不能靠猜测解决问题。A 写入的是 1 还是 2,对 B 来说没有区别:它没有收到任何新信息。无论猜哪个值,都无法保证正确。所以在允许持续分区的前提下,C 与 A 不能同时得到保证。
这个结论不妨碍系统在网络可通信、节点足够时提供一致的服务。它限制的是分区期间仍然能承诺什么。
4. 一致优先
一致优先意味着:无法确认读写安全时,就不完成这次操作。多数派复制可以让拥有有效多数的一侧继续写入,少数派则拒绝相关请求,避免两侧各自确认互相冲突的结果。
保留一致性不需要等待所有副本,但提交、读取和选举规则必须配套:写入已经确认后,后续读取和新主接管都要保留这个结果。具体多数派规则见Raft。
5. 可用优先
可用优先意味着:各分区继续处理本地请求,接受暂时读到旧值或产生冲突。网络恢复后,系统再传播和合并不同版本。
如何合并取决于允许丢掉什么。最后写入胜出(LWW)按约定的时间或版本顺序选出一个值,落选的更新会被丢弃。无冲突复制数据类型(CRDT)为特定数据类型规定可合并的更新规则。业务也可以保留多个冲突版本,交给用户选择。
因此,选择可用优先时,要同时说明分区期间返回什么、恢复后怎样处理冲突。只说“最终会一致”,还没有回答数据该如何处理。
6. 按操作选择
同一个系统里的不同操作,可以接受不同的保证。商品描述允许暂时读取旧副本,库存扣减却可能需要协调,避免多个节点各自扣掉同一份库存。系统也可以开放陈旧读,同时拒绝无法确认写入权限的操作。
CP、AP 只能粗略描述这种取舍。落实到接口时,要写清分区期间会返回成功、陈旧值、冲突还是错误。
6.1 多数派服务与请求范围
多数派能继续服务,不代表全系统满足 CAP 的 A。三节点分成两节点和单节点两个分区后,多数侧可以继续确认写入;但单节点侧如果仍能收到请求却拒绝处理,就不满足“每个非故障节点”的要求。
把客户端路由到多数侧,可以提高实际请求的成功率,但这改变的是访问路径。工程上的服务等级目标(SLO)按指定入口、时间窗口和事件范围统计,不能与 CAP 的全节点要求直接等同。
7. CAP 与一致性模型
CAP 的 C 与 ACID 的一致性说的是不同问题。前者约束读写操作能观察到的结果,采用线性一致性定义;后者指事务维护业务约束。其他可见性保证的区别见一致性模型。
8. 延迟与一致性
PACELC 把分区期间和平时的取舍放在一起:发生分区(P)时,在可用性(A)与一致性(C)之间取舍;否则(E),也可能需要在延迟(L)与一致性(C)之间取舍。
例如,写入要等远端副本确认,响应时间就包含这段网络等待;本地先返回,其他副本则有一段尚未收到新值的时间。具体代价取决于副本放在哪里,以及请求需要访问哪些副本。
9. 常见问题
9.1 单机也需要在 CAP 之间取舍吗?
单节点内部没有副本之间的网络分区。把数据通过网络复制到其他节点后,才需要分析分区时各节点如何读写,以及故障切换时保留哪些保证。
9.2 请求超时算不算违反 CAP 的可用性?
如果请求因超时而没有正常完成数据操作,就不满足这里的可用性要求。但 CAP 的 A 本身没有固定响应时限,不能把“超过 100 毫秒”直接当作它的判定标准。工程系统用超时限制用户等待,并按 SLO 统计影响,这是另一种衡量范围。
10 · 面试题卡片
本页题目与参考回答
10.1 网络分区发生时,为什么一致性和可用性无法同时保证
考察重点
- 说明 CAP 三个性质的含义。
- 用一次写后读推导旧读、等待和拒绝请求的后果。
- 区分操作级取舍、全节点可用性和工程可用率。
参考回答
持续分区时,一侧无法获知另一侧的新写入,因此无法同时保证线性一致性和每个非故障节点的可用性。
节点 A 已确认写入后,节点 B 若返回旧值,会破坏线性一致性;若一直等待分区恢复,请求就无法保证最终完成;返回错误也没有完成数据操作。
多数派协议可以保留一致性,让少数侧拒绝操作。允许旧值或冲突的业务则可以继续在本地受理。CAP 的 A 覆盖每个非故障节点,且没有固定响应时限;工程可用率按 SLO 定义的范围统计。
10.2 三节点分区后多数侧仍可读写,是否满足 CAP 的可用性?
考察重点:区分全节点请求范围与工程可用率。
相关内容:多数派服务与请求范围。
参考回答
不满足全系统的 CAP 可用性保证,因为仍在运行的少数侧节点拒绝了收到的相关请求。
多数侧继续服务、把客户端路由到多数侧,都可以改善实际请求的成功率。但 CAP 的定义覆盖每个非故障节点,不能只统计多数侧的请求。
11. 参考资料
- Gilbert 与 Lynch:Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services
- Brewer:CAP Twelve Years Later
- Daniel Abadi:Consistency Tradeoffs in Modern Distributed Database System Design
来源:Coding 101 原文 · 免费阅读,引用请保留出处。内容使用说明