外观
一句话答案
分布式系统不可能同时满足一致性(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)为什么 P 必须保证?
分布式系统中,网络分区是无法避免的客观现实(网线断了、交换机故障、机房间网络抖动)。如果不满足 P,则意味着只要一个节点故障或网络中断,整个系统就不可用——这就失去了分布式的意义。因此 P 是必选项,真正的选择是在 CP 和 AP 之间。
常见系统的 CAP 选择:
| 系统 | 选择 | 说明 |
|---|---|---|
| ZooKeeper | CP | Leader 挂了需要重新选举,选举期间不可用(牺牲 A),但保证数据一致 |
| Eureka | AP | 节点间 P2P 复制,某个节点挂了其他节点仍能提供服务(牺牲 C),可能读到旧注册表 |
| Nacos | AP + CP 可切换 | 临时实例用 AP(Distro 协议),持久化实例用 CP(Raft 协议) |
| Redis Sentinel | AP | 主从切换期间可能丢数据(异步复制),但始终可读写 |
| etcd | CP | 基于 Raft,写入需要多数节点确认,网络分区时少数派不可写 |
面试加分点: CAP 不是"三选二"那么简单,它是在网络分区发生的前提下,对 C 和 A 进行权衡。正常情况下(没有分区)C 和 A 可以同时满足。真实系统设计中,更常见的做法是根据业务场景对一致性做分级——核心数据强一致(如账户余额),非核心数据最终一致(如用户昵称缓存)。
追问与易错
追问方向:
- 为什么说 P 是必须的?(网络分区不可避免,所以实际在 CP 和 AP 间选)
- Zookeeper 是 CP 还是 AP?Eureka 呢?(ZK 是 CP,Eureka 是 AP)
- BASE 和 CAP 什么关系?(BASE 是 CAP 中 AP 方向的延伸)
易错点:
- ❌ "CAP 只能三选二"——更准确说是分区发生时在 C 和 A 间选择,没分区时 CA 都可以
- ❌ "CAP 的 C 和 ACID 的 C 一样"——CAP 的 C 是线性一致性,ACID 的 C 是约束满足
💡 记忆锚点
分布式三角:一致性(C)、可用性(A)、分区容错(P)只能三选二,而网络分区不可避免,所以实际是在CP(宁可不服务也要一致,如ZK/etcd)和AP(先服务再修数据,如Eureka)之间选。记住:没分区时CA都能满足,分区时才做选择题。