一致性:CAP 与一致性模型
0. 引言
单机数据库中,一致性由事务的 ACID 保证。引入网络与多副本后,同一份数据的不同副本可能返回不同结果——分布式一致性要解决的问题,就是在网络分区、节点失效的前提下,让系统对外表现出可预期的数据状态。本文从 CAP 定理出发,展开一致性谱系与选型权衡。
1. 为什么需要分布式一致性
- 单机:ACID 事务保证"读到的总是正确状态";
- 分布式:写入发生在主节点,副本异步/同步传播——副本间必然存在可见性差异;
- 目标:在分区与故障下,定义并保证"读操作返回什么状态是合理的"。
2. CAP 定理与常见误解
CAP 指出分布式系统在三个属性中最多同时满足两个:
| 属性 | 含义 |
|---|---|
| 一致性(C) | 每次读取都能拿到最新写入(线性一致) |
| 可用性(A) | 每个非故障节点都能在有限时间内响应请求 |
| 分区容错性(P) | 网络分区发生时,系统仍能继续工作 |
由于网络分区是必然事件,P 是必选项,实践中的权衡是 CP(保一致弃可用) 还是 AP(保可用弃强一致)。
常见误解:
- "三选二"是静态的——实际是分区发生时决定牺牲哪一项,分区恢复后二者都可恢复;
- CAP 中的 C 是线性一致,不等于事务隔离级别中的"一致性",也不同于最终一致性;
- 可用性指"每个请求都有响应",而非响应内容正确。
3. 一致性的实现基础
一致性依赖两件事:
text
复制(Replication):在多副本间传播数据(详见《数据分布:分片与复制》)
共识(Consensus):在多个副本间就写入顺序达成一致(详见《分布式协调》章)- 只有复制无共识 → 副本各自为政,收敛靠运气;
- 复制 + 共识 → 全局顺序确定,可支持强一致读。
4. 一致性谱系(从强到弱)
图表渲染中…
| 级别 | 定义 | 代价 | 典型 |
|---|---|---|---|
| 线性一致 | 任意读都能看到最新写入,所有操作有全局一致的时间顺序(= CAP 的 C) | 需全局排序,延迟高,地理分布难实现 | ZooKeeper、etcd |
| 顺序一致 | 所有节点看到同一顺序,但不要求与真实时间一致 | 中 | Raft 日志应用顺序 |
| 因果一致 | 有因果关系的操作保序,并发操作可乱序 | 中低 | 社交评论、IM |
| 会话一致 | 同一会话内读己之写(Read-Your-Writes),跨会话不保证 | 低 | 购物车、登录态 |
| 单调读 | 同一客户端多次读,不会读到比之前更旧的值 | 低 | 缓存、Feed |
| 最终一致 | 无新写入经过足够时间,所有副本最终收敛 | 最低 | AP 系统(Cassandra/DynamoDB) |
text
最强 → 最弱:线性一致 > 顺序一致 > 因果一致 > 会话/单调读 > 最终一致5. 选型权衡
| 级别 | 延迟 | 可用性 | 适用 |
|---|---|---|---|
| 线性一致 | 高 | 低 | 元数据、分布式锁、选主 |
| 因果一致 | 中 | 中 | 社交、协作编辑 |
| 会话一致 | 低 | 高 | 用户会话类业务 |
| 最终一致 | 低 | 高 | 缓存、浏览计数、Feed |
决策原则:先问业务"读旧值会造成什么后果"——锁/选主/账务必须线性一致;内容/计数最终一致即可;不要为"显得严谨"给全系统上强一致(详见《不同数据一致性模型有哪些应用?》)。
6. 与复制的关系
一致性级别由复制同步策略与共识协议共同决定:
text
异步复制(无共识) → 最终一致
半同步/Quorum → 近似强一致(多数派内)
同步复制 + 共识协议 → 线性一致(TiDB Raft、etcd)分布式数据库的典型实现:Raft 多数派复制 + 线性化读(TiDB/PolarDB-X/OceanBase),在"不丢已提交数据"与"分区可用性"之间给出工程最优解。
7. 小结
- CAP:分区是必然,实际权衡是 CP vs AP;C 指线性一致;
- 一致性谱系:线性 > 顺序 > 因果 > 会话/单调读 > 最终,强度与延迟/可用性成反比;
- 实现基础:复制(传播数据)+ 共识(确定顺序);
- 选型:按"读旧值的业务后果"决定级别,避免全系统一刀切。
下一章讲解存储引擎与查询:LSM-Tree 与 B+ Tree 的存储原理。