3.1 CAP 定理:分布式系统的三选二


3.1 CAP 定理:分布式系统的三选二

通用内功第一课必须从 CAP 定理开始——它是分布式数据库一切设计取舍的母法则。第 2 章出现的"AP 倾向""CP 倾向"说法,本节给出精确含义;第 4、5 章所有高可用机制的配置项,都会回到这里找到理论坐标。

学习目标

阅读完本节,你应当能够:

  1. 准确陈述一致性、可用性、分区容错的定义,指出最常见的三种误读;
  2. 解释"三选二"为什么实际是"分区发生时 C 与 A 不可兼得";
  3. 用 PACELC 把 CAP 从"故障时刻的分析"扩展到"平时的取舍";
  4. 对给定业务场景判断该倾向 CP 还是 AP,并说出对应的系统行为。

三个字母的准确定义

先精确措辞,再谈理解。

一致性(Consistency):这里指线性一致性——任何读操作都能读到最近一次写入的值,仿佛全系统只有一份数据。注意它不是数据库事务里的 C(那指约束不被破坏),也不是常说的 ACID 一致性。

可用性(Availability):每个收到的请求最终都能收到响应(可以不是最新数据),不保证响应的节点是非故障节点。注意"响应错误"不算可用,超时不响应更不算。

分区容错(Partition Tolerance):节点间的网络可以任意丢失消息(被切成若干孤岛),系统仍能继续运转。

最常见的误读是"三选二 = 随便挑两个"。实际上分区容错不是可选项:在多节点网络上,交换机故障、光缆被挖断、网卡丢包是物理现实,任何声称不容忍分区的系统在分区发生时直接不可用,等于没有答案。所以 CAP 的准确表述是:当网络分区发生时,一致性与可用性只能保住一个。系统设计者的选择空间在于分区发生那一刻,系统把哪边放进牺牲名单——拒绝写入保数据一致(CP),还是照常服务保业务在线(AP)。

PACELC:平时的取舍也要记账

CAP 只描述分区发生时的极端时刻,但分区是小概率事件,系统绝大多数时间在"无分区(Else)"状态运行,此时依然存在取舍:延迟与一致性不可兼得。追求强一致就要等副本确认(延迟高),追求低延迟就要异步复制(副本可能落后)。这就是 PACELC 的含义:分区时在 A 与 C 间选,平时在 L(延迟)与 C 间选。

这个推广让很多产品行为变得可解释。DynamoDB 可配置强一致读但收费更高、延迟更高,是典型的 Else 分支选择;MongoDB 的写关注可以要求多数节点确认才返回,也是拿延迟换一致。

演练:两个业务,两种倾向

背景:同一张电商系统里有两个服务:商品详情浏览与下单扣库存,大促期间机房级网络故障出现了 30 秒。

操作:分别推演两种倾向下的系统行为。商品详情走 AP 倾向的缓存与副本:分区期间旧价格、旧库存展示照常,用户能继续浏览下单入口。下单扣库存走 CP 倾向:库存服务在无法与多数副本通信时拒绝写入,返回"系统繁忙请重试"。

结果:30 秒恢复后,商品详情的旧数据经短暂追平收敛到一致;下单链路没有出现超卖,但丢失了分区窗口内的部分订单请求。

解读:两种选择都对,因为两种业务对"错"的定义不同——浏览页容忍旧数据但不能白屏,库存扣减容忍拒绝请求但不能超卖。CAP 不是用来贴标签的("我们是 AP 系统"),而是用来给每个业务操作定行为的。

变式:若业务改成"库存是虚拟商品且允许事后补货",扣减也可放松为 AP,用补偿流程兜底少数超卖。可见倾向是业务决策,不是技术偏好。

易错点

三个高频误读值得集中澄清。误读一:CAP 说明 NoSQL 必然不可靠。恰恰相反,它说明"既强一致又全可用还不怕分区"的免费午餐不存在,关系型数据库的分布式方案同样逃不脱,只是把选择藏在配置里。误读二:CP 系统分区时完全不可用。CP 通常只是拒绝写入或部分写入,读服务可能照常。误读三:AP 系统数据会永久不一致。AP 的配套承诺是最终一致——分区愈合后副本收敛,3.3 节展开这个承诺的细节。

分区发生时的选择矩阵

CAP 常被人误读成"三选二",更准确的说法是:当网络分区(P)发生时,你只能在一致性(C)与可用性(A)之间选一个。分区不发生的时候,系统可以同时满足 C 与 A。

场景 分区时的选择 具体表现 适用数据
银行转账 保 C,牺牲 A 无法确认对端状态时拒绝写入,宁可报错也不给错数 账务、库存、配额
社交点赞 保 A,牺牲 C 两侧都接受写入,恢复后合并,短暂计数偏少 点赞、浏览数、动态流
商品详情页 保 A,牺牲 C 展示稍旧的商品信息,允许几秒延迟 目录、配置、内容
秒杀库存 保 C,牺牲 A 库存扣减走强一致路径,超卖零容忍 库存、优惠券发放

演练:一次网络分区的两种结局

假设三个节点(N1、N2、N3)组成一个集群,N1 与另外两个节点之间网络中断,形成"少数派 N1"与"多数派 N2+N3"两个分区。此时客户端仍在向两边写入同一个用户的昵称。

保一致性的做法:多数派继续服务(它仍能与多数节点确认),少数派 N1 拒绝写入。客户端在 N1 侧收到错误,需要重试到多数派。代价是 N1 分区期间该用户无法修改资料;收益是不存在冲突版本,恢复后无需合并。

保可用性的做法:两边都接受写入,N1 记录"昵称改为 A",多数派记录"昵称改为 B"。分区恢复后系统必须解决冲突——常见策略有"最后写入胜利"(按时间戳取新,依赖时钟可靠)、"保留多版本交应用层处理"(如购物车合并)、"按业务规则自动合并"(如计数取最大值)。代价是恢复逻辑复杂,且可能丢失用户感知上已经"成功"的写入。

这个演练揭示了 CAP 的真实含义:选择发生在分区期间,代价兑现于分区恢复之后。保可用不是没有代价,只是把代价从"报错"变成了"事后合并"。因此选型时真正要回答的问题是——这类数据,你更受不了"暂时不能用"还是"暂时不对"?

本节要点回顾

  • 准确定义:C 是线性一致,A 是请求必有响应,P 是容忍网络分区。
  • 分区不是选项而是现实,真正的选择是分区时刻保 C 还是保 A。
  • PACELC 把取舍推广到平时:延迟与一致性同样不可兼得。
  • 倾向判定应落到单个业务操作层面,而不是给整个系统贴标签。
  • 拒绝写入保一致、放行旧数据保可用,两者没有优劣,只有业务匹配。

CAP 定理判了强一致的"刑",BASE 理论则是接受判决后的生活指南。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U