一、CAP 是什么?
| 字母 | 含义 | 解释 |
|---|---|---|
| C | **Consistency(一致性) | 所有节点同一时间看到的数据完全一致 |
| A | **Availability(可用性) | 每个请求都能得到响应(不保证数据最新) |
| P | **Partition tolerance(分区容错) | 网络分区(节点间通信失败)时系统仍能继续工作 |
二、为什么不能同时实现?
"因为 P(分区容错)是分布式系统的 前提条件**。网络分区一定可能发生(断网、丢包、节点宕机) 。所以你必须在 C 和 A 之间二选一 ------这就是 CAP 的本质。"
2.1 分布式系统必选 P
为什么 P 必选?
- 分布式系统有多个节点
- 节点间通过网络通信
- 网络一定可能断(网线被挖断、交换机故障、DNS 故障)
- 只要是分布式系统,P 就必须满足
2.2 P 满足后,C 和 A 只能二选一
假设场景 :MySQL 主从集群,主从之间网络断了
主库 (192.168.1.1) ← 网络断 → 从库 (192.168.1.2)
↓ ↓
写数据 w=1 没收到
情况 1:选 C(一致性) ------ 拒绝写
主库:检测到从库没收到
主库:拒绝写入,返回错误
主库:保证数据一致(主从都是空)
↓
❌ 可用性没了(用户写不进去)
情况 2:选 A(可用性) ------ 继续写
主库:不管从库,先写入主库
主库:返回写入成功
↓
✅ 可用性有了
❌ 一致性没了(主库有 w=1,从库没有)
**所以 P 满足后,C 和 A 是互斥的 ------你必须牺牲一个。
三、CAP 三选二的 3 种组合
| 组合 | 含义 | 实际系统 | 项目 |
|---|---|---|---|
| CA(放弃 P) | 单点系统,不是分布式 | 传统单机数据库(MySQL 单机) | 单库测试 |
| CP(放弃 A) | 强一致 + 分区容错 ,可用性差 | ZooKeeper、etcd、HBase | 关键功能(强一致) |
| AP(放弃 C) | 可用性 + 分区容错 ,最终一致 | Eureka、Cassandra、Redis | 报表(高可用) |
⚠️ 关键点:
- CA 不是真正的分布式(单机就满足,不分 P)
- 真实分布式只能在 CP 和 AP 之间选
四、CAP 的"扩展"理解
4.1 CAP 不是三选一,而是"权衡"
老哥注意:
- CAP 不是绝对的 ------不是非黑即白
- 大部分系统在 C 和 A 之间 做权衡(不是完全牺牲)
- 比如:ZooKeeper 标榜 CP,但实际写入失败后还会重试 (不是完全不可用)
4.2 实际系统的 CAP 表现
| 系统 | CAP | 实际表现 |
|---|---|---|
| Eureka | AP | 节点挂了服务还能用(不一致但可用) |
| Nacos 临时实例 | AP | 同 Eureka |
| Nacos 非临时实例 | CP | 网络断后不剔除(保证一致) |
| ZooKeeper | CP | 选举时不可用(保证一致) |
| Redis Cluster | AP | 主从切换时短暂不可用 |
| MySQL 主从 | AP | 主从延迟(最终一致) |
| MongoDB | CP | 单机模式可 CA,集群模式 CP |
| HBase | CP | 强一致(金融级) |
五、记忆口诀
"P 必选,C 和 A 二选一"
"网络一定会断,所以 P 必须满足"
"CP 强一致,AP 高可用"
"关键功能用 CP,普通报表用 AP"
"CA 不是分布式,是单机"
"ZooKeeper / HBase = CP,Eureka / Cassandra = AP"
六、深入理解:为什么 P 满足后 C 和 A 矛盾?
6.1 用"两阶段提交"举例
2PC 协调者 + 参与者模型:
协调者 参与者 A 参与者 B
↓ ↓ ↓
prepare → vote yes vote yes
↓ ↓ ↓
网络断(参与者 A 收到 commit,参与者 B 没收到)
↓
协调者不知道参与者 B 的状态
↓
?
这时候,协调者只有 2 个选择:
选 C(一致性):
协调者:宁可卡住也不提交
↓
协调者:等待网络恢复
↓
数据一致 ✅
可用性 ❌(业务卡住)
选 A(可用性):
协调者:直接放弃等待,返回成功
↓
数据可能不一致(参与者 A 提交了,B 没提交)
↓
数据一致 ❌
可用性 ✅(业务继续)
**所以 P 满足后,C 和 A 在网络分区时一定是矛盾的。