面试知识库
极高 进阶

CAP定理#

一句话答案#

分布式系统不可能同时满足一致性(C)、可用性(A)、分区容忍性(P),实际在 CP(强一致)和 AP(高可用)间选择。

核心要点

CAP 定理(Brewer 定理): 一个分布式系统不可能同时满足以下三个特性,最多只能同时满足其中两个。

特性英文含义
C — 一致性Consistency不管访问哪个非故障节点,读到的都是同一份最新写入的数据,要么读取失败
A — 可用性Availability不管访问哪个非故障节点,都能在合理时间内得到响应(不保证是最新数据)
P — 分区容错性Partition Tolerance当网络出现分区故障(部分节点间通信中断)时,系统仍然能够对外提供服务

为什么只能三选二?本质是网络分区时 C 和 A 的矛盾:

场景:节点 A 和节点 B 之间网络分区(P 发生了)

客户端写入 v2 到节点 A,但 A 无法同步给 B(网络断了)

此时客户端读节点 B:
  选择 C(一致性):B 发现自己数据可能不是最新 → 拒绝响应 → 牺牲 A(可用性)
  选择 A(可用性):B 返回自己的旧数据 v1 → 牺牲 C(一致性)

无法同时满足:B 既返回最新数据(C),又保证有响应(A)
plaintext

为什么 P 必须保证?

分布式系统中,网络分区是无法避免的客观现实(网线断了、交换机故障、机房间网络抖动)。如果不满足 P,则意味着只要一个节点故障或网络中断,整个系统就不可用——这就失去了分布式的意义。因此 P 是必选项,真正的选择是在 CP 和 AP 之间。

常见系统的 CAP 选择:

系统选择说明
ZooKeeperCPLeader 挂了需要重新选举,选举期间不可用(牺牲 A),但保证数据一致
EurekaAP节点间 P2P 复制,某个节点挂了其他节点仍能提供服务(牺牲 C),可能读到旧注册表
NacosAP + CP 可切换临时实例用 AP(Distro 协议),持久化实例用 CP(Raft 协议)
Redis SentinelAP主从切换期间可能丢数据(异步复制),但始终可读写
etcdCP基于 Raft,写入需要多数节点确认,网络分区时少数派不可写

面试加分点: CAP 不是”三选二”那么简单,它是在网络分区发生的前提下,对 C 和 A 进行权衡。正常情况下(没有分区)C 和 A 可以同时满足。真实系统设计中,更常见的做法是根据业务场景对一致性做分级——核心数据强一致(如账户余额),非核心数据最终一致(如用户昵称缓存)。

面试回答(2分钟版)

CAP定理是说分布式系统不可能同时满足一致性C、可用性A和分区容错性P这三个特性。一致性要求所有节点读到的数据都是最新写入的,可用性要求每个请求都能在合理时间内得到响应,分区容错性要求网络分区发生时系统仍然可用。由于网络分区在分布式环境中不可避免,P是必选项,真正的选择是在CP和AP之间做权衡。当网络分区发生时,节点A写入新数据无法同步到节点B,这时如果选CP就让B拒绝服务保证一致性,如果选AP就让B返回旧数据保证可用性。典型的CP系统有ZooKeeper和etcd,Leader选举期间牺牲可用性保证数据一致;典型的AP系统有Eureka,节点间P2P复制,某个节点挂了其他节点仍然服务但可能读到旧数据。Nacos比较灵活,临时实例用AP模式的Distro协议,持久化实例用CP模式的Raft协议。实际工程中更常见的做法是按业务分级,核心数据如账户余额用强一致性,非核心数据如用户昵称缓存接受最终一致性。

追问与易错

追问方向:

  • “为什么说 P 是必须的?”→ 网络分区在分布式环境中不可避免(网线断、交换机故障),不满足 P 意味着单点故障就全挂,所以 P 必选,实际在 CP 和 AP 间权衡
  • “Zookeeper 是 CP 还是 AP?Eureka 呢?”→ ZK 是 CP(Leader 选举期间不可用但保证一致),Eureka 是 AP(节点间 P2P 复制,某节点挂了仍可服务但可能读到旧数据)
  • “BASE 和 CAP 什么关系?”→ BASE 是 CAP 中选择 AP 方向的工程实践指南,放弃强一致性追求最终一致性,用软状态过渡来换取基本可用

易错点:

  • ❌ “CAP 只能三选二”——更准确说是分区发生时在 C 和 A 间选择,没分区时 CA 都可以
  • ❌ “CAP 的 C 和 ACID 的 C 一样”——CAP 的 C 是线性一致性,ACID 的 C 是约束满足