← 返回题目列表

CAP 理论是什么?实际系统如何取舍?

高频 中等 第 13 / 27 题 更新于 2026/10/03
CAP分布式一致性可用性
学习 AI 实战项目

简化版

CAP 指分布式系统的三个特性:一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。它真正表达的是:网络分区发生时,系统无法同时保证强一致和可用,只能在 CP 与 AP 之间取舍。因为分布式系统无法避免网络分区,所以 P 不是可选项,面试里要答成“分区时 C 和 A 的取舍”。

详细版

CAP 的三个含义要讲准确:

特性含义关键点
C 一致性所有节点对外表现得像一份数据这里通常指强一致,读到最新写入
A 可用性每个收到请求的非故障节点都在有限时间返回非错误响应用“明确失败”拒绝请求已经牺牲了 CAP 定义下的 A
P 分区容错性节点间任意消息丢失或延迟时,系统仍按所选语义运行分区是故障条件,不是一个“性能开关”

分布式系统里,网络故障、机房隔离、交换机异常、丢包超时都可能造成分区。分区出现后,如果继续让两个分区都读写,就可能产生不一致;如果为了不产生不一致而拒绝某些请求,就牺牲了可用性。所以实际取舍是:

  • CP:分区时宁可拒绝服务,也要保证数据一致,常见于 ZooKeeper、etcd、强一致元数据系统。
  • AP:分区时尽量让两侧继续响应,允许短暂不一致,后续靠同步、冲突解决、补偿达到最终一致,常见于部分多主存储、缓存和可合并的社交数据。

面试要避免把 CAP 简单说成“三选二”。更准确的表达是:没有分区时 C 和 A 可以同时满足;分区发生时,P 已经摆在面前,系统必须在 C 和 A 之间选一边倾斜。

完整版教学

一、先把 CAP 放进一个真实场景

假设订单服务有两个副本,A 在上海机房,B 在北京机房。正常情况下,用户扣库存写到 A,数据同步到 B,两个机房都能读到同样的库存。现在两个机房之间网络断了,A 和 B 互相不知道对方的最新状态,这就是网络分区。

此时北京用户访问 B,如果 B 继续扣库存,系统可用性很好,但 A 和 B 可能同时卖出最后一件商品,库存就不一致了。如果 B 为了保证不超卖而拒绝写请求,就保护了一致性,但北京用户看到的是服务不可用。CAP 的矛盾就出现在这一刻:不是平时不能一致又可用,而是分区时无法同时做到“继续服务”和“绝不产生分歧”。

二、为什么 P 不是你想不想选的问题

很多初学者会问:我能不能选 CA,不要 P?CAP 中的分区是网络可能丢失任意多消息的执行条件,不是部署时勾选的产品特性。跨机器系统无法靠配置排除这种条件;分区发生后,系统即使选择停止一侧服务,也是在用可用性换一致性,而不是让 P 消失。

所以工程上不会问“要不要 P”,而是问:“当 P 发生时,业务更怕什么?”如果更怕脏数据、重复扣款、超卖,就偏 CP;如果更怕服务不可用、用户无法浏览、服务发现完全瘫痪,就偏 AP。

三、CP 系统牺牲的不是全部可用,而是部分请求

CP 不等于整个系统挂掉。它的做法通常是让无法确认多数派、无法确认主节点身份、无法确认最新数据的节点停止对外写入,甚至停止提供强一致读。比如 etcd/Raft 集群中,如果某个少数派分区没有 Leader,它就不能接受写请求,因为它无法保证这个写会被集群承认。

这样做的代价是:一部分节点明明还活着,却不能响应某些请求。好处是:系统不会产生两个权威结果,不会出现两个 Leader 同时写配置、两个库存中心同时扣库存这样的灾难。

四、AP 系统牺牲的不是永远一致,而是实时一致

AP 也不是“数据随便乱”。AP 的核心是先保服务,允许副本在一段时间内不一致,等网络恢复后通过同步、版本比较、冲突合并、补偿任务让数据收敛。比如用户点赞数、浏览量、推荐候选集、服务注册表,短时间旧一点通常可以接受。

AP 系统真正难的是冲突处理。两个分区都写了同一份数据,恢复后谁覆盖谁?常见策略有最后写入胜出、版本号比较、向量时钟、业务合并、人工介入。AP 的成本不是没有成本,而是把成本从“请求当场等待一致”转移到“后台修复和冲突解决”。

五、CAP 与 PACELC 的关系

CAP 只讲分区时的取舍,但系统大部分时间没有分区。PACELC 把问题补完整:如果发生 Partition,就在 Availability 和 Consistency 之间取舍;Else 没有分区时,也要在 Latency 和 Consistency 之间取舍。强一致读写通常要等待复制确认,延迟更高;最终一致通常延迟更低,但可能读到旧数据。

面试答到 PACELC,会显得你不是背概念,而是在做系统设计。真实系统往往是:核心链路局部 CP,外围链路偏 AP;写链路更强一致,读链路通过缓存和副本降低延迟。

分区期间的操作守住 C 的行为守住 A 的行为必须承担的后果
余额写入少数派拒绝写两侧都接受写后者可能破坏资金不变量
商品描述读取等待/拒绝不确定读返回本地旧副本后者要标明新鲜度并恢复同步
购物车编辑单一多数派接受两侧接受并发版本后者需要业务合并或提示冲突

六、面试追问怎么接

如果面试官问“Redis、MySQL、ZooKeeper 是 CP 还是 AP”,不要机械贴标签。要说明具体模式和场景:ZooKeeper/etcd 的一致性协议偏 CP;Redis 主从默认异步复制,故障切换时可能丢数据,更偏可用和低延迟;MySQL 单主强一致事务在单库内成立,跨机房复制通常又涉及延迟和一致性取舍。CAP 是分析框架,不是给产品永久贴一个字母标签。

七、常见误区与追问

两个副本初始都保存 x=0,随后网络分区:
客户端在 A 把 x 写成 1,但 B 收不到该写。
B 若必须响应读取,只能返回本地 x=0,违反线性一致;
B 若拒绝或无限等待读取,则不满足 CAP 的可用性。

关键边界:CAP 的 A 不等于日常 SLA,也不允许用错误响应冒充成功;它要求所有到达非故障节点的请求最终得到非错误响应。

  • 误区:CAP 是 C、A、P 三选二。 严格说分布式系统必须容忍 P,分区发生时才在 C 和 A 之间取舍。
  • 误区:牺牲一致性就是数据错误。 AP 系统通常牺牲的是强一致,仍会通过同步、重试和修复达到最终一致。
  • 误区:数据库强一致就不用考虑 CAP。 跨节点复制和网络分区仍然存在,强一致会以可用性或延迟为代价。
  • 追问:注册中心为什么常说选 AP? 因为服务发现更怕完全不可用,短暂旧地址可由客户端重试和健康检查兜底。
  • 追问:什么时候更偏 CP? 库存、余额、配置元数据等不能接受旧值写入的场景更偏 CP。
  • 追问:CAP 和 BASE 有什么关系? BASE 是在 AP/最终一致方向上的工程思想,接受软状态换取可用性。

八、加强记忆

CAP 要记成一句工程话:分布式必须面对网络分区,分区发生时,如果继续服务就可能不一致,如果保证强一致就必须拒绝部分请求。所以真正选择是 CP 还是 AP,不是简单“三选二”。钱、库存、锁、元数据通常偏 CP;点赞、浏览、推荐、服务发现常常偏 AP;更完整的设计还要用 PACELC 思考平时的一致性与延迟权衡。