CAP 与 BASE 理论
问题
什么是 CAP 定理?什么是 BASE 理论?分布式系统中如何在一致性和可用性之间做权衡?
答案
CAP 定理
CAP 定理(又称布鲁尔定理)指出:在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)三者最多只能同时满足两个。
| 属性 | 含义 |
|---|---|
| C(Consistency) | 所有节点在同一时刻看到的数据一致(强一致性) |
| A(Availability) | 每个请求都能在合理时间内收到非错误响应 |
| P(Partition Tolerance) | 网络分区(节点间通信中断)时系统仍能运行 |
为什么必须选择 P?
在分布式系统中,网络分区是不可避免的(网线可能断、路由器可能故障)。因此 P 是必选项,实际选择是 CP 还是 AP。
- CP:分区时拒绝部分请求,保证返回的数据一定正确(如 ZooKeeper 选举期间不可用)
- AP:分区时继续提供服务,但返回的数据可能不是最新的(如 Eureka 的自我保护模式)
CAP 的实际案例
BASE 理论
BASE 是对 AP 方案的延伸,核心思想是 放弃强一致性,追求最终一致性。
| 概念 | 英文 | 含义 |
|---|---|---|
| BA | Basically Available | 基本可用:分布式系统出故障时,允许损失部分可用性(响应时间变长、功能降级) |
| S | Soft State | 软状态:允许系统中存在中间状态,即数据副本之间存在短暂不一致 |
| E | Eventually Consistent | 最终一致性:经过一段时间后,数据副本最终会达到一致 |
ACID vs BASE
| 对比 | ACID | BASE |
|---|---|---|
| 适用范围 | 单机数据库事务 | 分布式系统 |
| 一致性 | 强一致性 | 最终一致性 |
| 可用性 | 不做保证 | 基本可用 |
| 代表 | MySQL 事务 | NoSQL、微服务 |
| 思想 | 悲观,严格正确 | 乐观,允许中间状态 |
一致性级别
| 级别 | 说明 | 示例 |
|---|---|---|
| 强一致性 | 写入后立即可读到最新值 | CP 系统、分布式事务 |
| 弱一致性 | 不保证何时能读到最新值 | UDP 通信 |
| 最终一致性 | 一段时间后一定能读到最新值 | DNS、Redis 主从、Eureka |
| 因果一致性 | 有因果关系的操作有序 | 社交网络评论 |
| 读己之写 | 自己写的数据能立即读到 | 用户昵称修改后自己能看到 |
| 会话一致性 | 同一会话内保证一致 | Session Sticky |
常见面试问题
Q1: CAP 为什么不能同时满足?
答案:
假设两个节点 N1、N2 之间发生网络分区:
- 客户端向 N1 写入数据
- N1 无法将数据同步到 N2(网络断了)
- 此时客户端去 N2 读取:
- 若要保证 一致性(C):N2 必须拒绝响应或等待同步完成 → 牺牲了可用性(A)
- 若要保证 可用性(A):N2 返回旧数据 → 牺牲了一致性(C)
在网络分区(P)存在的前提下,C 和 A 必然矛盾。
Q2: ZooKeeper 是 CP 还是 AP?
答案:
ZooKeeper 是 CP 系统:
- Leader 选举期间(约 30s~120s),集群不对外提供写服务 → 牺牲可用性
- 写入必须过半节点确认,保证数据一致性
- 读可以从 Follower 读,可能读到旧数据(若需强一致读用
sync()命令)
对比 Eureka 是 AP:节点间互相注册,任何节点宕机不影响服务发现,但可能返回过期的服务列表。
Q3: 如何在一致性和可用性之间权衡?
答案:
根据业务场景选择:
- 金融/支付:选 CP,宁可不可用,不能数据错误(分布式事务、强一致性)
- 社交/电商展示:选 AP,允许短暂看到旧数据,保证服务可用(最终一致性)
- 库存扣减:核心操作用 CP(强一致),库存展示用 AP(最终一致)
实践中通常是 混合方案:核心链路保证强一致,非核心链路接受最终一致。
Q4: 什么是最终一致性?怎么实现?
答案:
最终一致性是指:数据更新后,经过一段时间(通常秒级),所有副本最终会达到一致状态。
常见实现:
- 异步复制:主库写入后异步同步到从库(MySQL 主从、Redis 主从)
- 消息队列:通过 MQ 异步通知下游更新数据
- 定时对账:定时比对上下游数据,修复不一致
- 反熵(Anti-Entropy):节点间定期互相对比数据、修复差异(如 Cassandra)