写在前面
本文是分布式系统系列第一篇。分布式系统的所有设计都绕不开一个理论:CAP 定理。它解释了为什么没有完美的分布式系统、为什么必须在一致性和可用性间取舍。
一、CAP 定理
1.1 三个性质
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| C — Consistency(一致性)
所有节点在同一时刻看到相同数据
读操作总能读到最新写入
(严格一致性 / 线性一致性)
A — Availability(可用性)
每个请求都能收到非错误响应(不保证是最新数据)
系统一直可用,不拒绝服务
P — Partition tolerance(分区容忍)
网络分区(节点间断连)时系统仍能运作
消息丢失、延迟、节点宕机不影响整体
CAP 定理:分布式系统最多同时满足三个中的两个
|
1.2 为什么是三选二
1
2
3
4
5
6
7
8
9
10
11
12
| 关键认知:P(分区容忍)不是可选的!
网络一定会分区(光纤断、交换机故障、节点宕机)
这是物理现实,无法避免
所以 P 必须保证
于是真正的取舍是:C 和 A 二选一
当分区发生时:
选 C → 拒绝服务(保证一致性,牺牲可用性)
选 A → 继续服务(可能返回旧数据,牺牲一致性)
所以实际是 CP 还是 AP 之争
|
二、CP vs AP 系统
2.1 CP 系统(强一致性)
1
2
3
4
5
6
7
8
9
10
11
12
13
| 分区时优先保证一致性,可能拒绝服务
代表:
Zookeeper — 强一致(ZAB 协议),写入需要多数节点同意
etcd — 强一致(Raft),K8s 用它存关键配置
HBase — 强一致
MongoDB — 单主,强一致
关系型数据库 — 主从复制时主写从读可能不一致,但单机内强一致
特点:
✓ 数据强一致,不会读到旧值
✗ 分区时部分请求失败(不可用)
✗ 性能/延迟通常更高(要协调多数节点)
|
2.2 AP 系统(高可用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 分区时优先保证可用性,允许数据暂时不一致(最终一致)
代表:
Cassandra — 可调一致性,默认高可用
DynamoDB — 高可用
CouchDB — 最终一致
Redis 集群 — 主从异步复制,故障切换可能丢少量数据(偏 AP)
Eureka — 服务注册,AP
特点:
✓ 始终可用,不拒绝请求
✓ 性能高、延迟低(不需协调多数)
✗ 可能读到旧数据(最终一致)
✗ 需要解决冲突(Vector Clock、最后写入获胜)
|
1
2
3
| CA 系统(没有 P):
单机数据库(MySQL 单机)—— 不分布式,无分区问题
一旦分布式,P 不可选,退化成 CP 或 AP
|
三、BASE 理论
CAP 的 AP 取舍的实践指导:
1
2
3
4
5
6
7
8
9
10
11
| B — Basically Available(基本可用)
故障时允许损失部分可用性(降级、响应慢),保证核心可用
S — Soft state(软状态)
允许数据存在中间状态(不一致),不要求时刻强一致
E — Eventually consistent(最终一致性)
系统保证最终数据会一致,但中间可以有窗口
BASE = 对 AP 的工程化诠释
大型互联网系统(电商、社交)多采用 BASE + 最终一致
|
四、一致性模型
一致性有强弱之分,不只是"强一致 vs 不一致"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 强一致性(线性一致性 Linearizability)
所有操作有全局顺序,读总能看到最新写
最严格,实现成本最高(CP 系统)
顺序一致性(Sequential Consistency)
所有节点看到操作顺序一致,但不一定是实时顺序
比线性一致弱(不要求按实时顺序)
因果一致性(Causal Consistency)
有因果关系的操作保序,无因果的可乱序
读己之所写(Read Your Writes)
你自己写入的数据,你自己后续一定读得到
单调读(Monotonic Reads)
不会读到比之前更旧的数据
最终一致性(Eventual Consistency)
停止写入后,最终所有节点一致(BASE 的核心)
|
1
2
3
4
5
6
| 强 ←────────────────────────────────────→ 弱
线性一致 顺序一致 因果一致 读己写 最终一致
越强越易用、越难实现、性能越差
越弱越快、越可用、但需要处理不一致
实际系统按业务选合适的级别
|
五、实际系统怎么选
1
2
3
4
5
6
7
8
9
10
11
12
| 场景 推荐
──────────────────────────────────────────────────
金融账户、库存扣减 强一致(CP)— 宁可不可用也不能错
配置中心、元数据 强一致(CP)— etcd/Zookeeper
用户资料、社交动态 最终一致(AP)— 可用优先
搜索、推荐、日志 最终一致(AP)
购物车、点赞、计数 最终一致(AP)
分布式锁、选主 强一致(CP)
核心交易 → 强一致
社交/内容 → 最终一致
两者结合 → 不同模块不同策略
|
六、常见误解
1
2
3
4
5
6
7
8
9
10
11
| 误解1:CAP 是"任何时候三选二"
正解:只在「分区发生时」才二选一,平时可以既 C 又 A
误解2:AP 就是不要一致性
正解:AP 是「最终一致」,不是不要,只是不要求时刻强一致
误解3:强一致一定比最终一致好
正解:强一致成本高、可用性低,很多场景最终一致更合适
误解4:MySQL 是 CA(没有 P)
正解:单机 MySQL 不涉及分区;主从/集群 MySQL 是分布式的,有分区问题
|
七、小结
- CAP:一致性、可用性、分区容忍三选二;P 不可避免,实际是 CP vs AP
- CP(Zookeeper/etcd/HBase):强一致,分区时可能不可用
- AP(Cassandra/DynamoDB/Redis 集群):高可用,最终一致
- BASE:基本可用 + 软状态 + 最终一致,AP 的工程实践
- 一致性模型:从线性一致到最终一致,有多个级别,按业务选
- 选择:核心交易强一致,社交/内容最终一致
下一篇讲共识算法 Raft——CP 系统如何达成强一致。