一致性
No related notes
Outlinks (0)
No outlinks found
Backlinks (0)
No backlinks found
1 · 一致性
1.1 · 一致性模型层次
参考: https://jepsen.io/consistency/models 层次图源自 Bailis et al. 和 Viotti & Vukolić
一致性模型定义了系统允许哪些操作历史(histories)。模型 A 蕴含 模型 B (A ⊂ B),意味着 A 更强、更具约束性。
1.1.1 · 全景图
Strict Serializable
/ \
Serializable Linearizable
/ \ |
Snapshot Repeatable Sequential
Isolation Read |
\ / Causal
Monotonic Atomic View / | \
| WFR PRAM ...
Cursor Stability / | \
\ MR MW RYW
Read Committed
|
Read Uncommitted
- 左侧: 事务(多对象)模型族
- 右侧: 单对象模型族
- Strict Serializable 是两族的交汇点,同时满足事务全序 + 实时约束
1.1.2 · 可用性与一致性的权衡
| 可用性级别 | 可达到的最强模型 |
|---|---|
| 完全可用(Total) | Read Committed, Monotonic Atomic View 及更弱模型 |
| 粘性可用(Sticky) | Read Your Writes, PRAM 及更弱模型 |
| 不可用 | Sequential, Linearizable, Serializable 及更强 |
CAP 定理的精炼: 在异步网络分区下,Sequential 及以上的模型都无法保证全可用
1.2 · 核心模型详解
1.2.1 · Strict Serializable (严格可串行化)#
操作看起来按某个全序执行,且该全序与实时顺序一致。
- 事务模型 + 多对象 + 实时约束
- = Serializable 的全序 + Linearizable 的实时约束
- 可以把整个数据库视为一个 Linearizable 对象
- 典型系统: Spanner, CockroachDB (默认), FaunaDB
1.2.2 · Serializable (可串行化)#
事务看起来按某个全序执行,但不要求与实时顺序一致。
- 事务 T1 完成写 w 后,T2 开始读 r,r 不一定能看到 w
- 甚至进程可能看不到自己上一个事务的写(跨事务)
- 禁止的异象: P0(脏写)、P1(脏读)、P2(不可重复读)、P3(幻读)
- 典型系统: PostgreSQL (SSI), MySQL (InnoDB with
SERIALIZABLE)
1.2.3 · Snapshot Isolation (快照隔离)#
每个事务在一个一致快照上操作;提交时检测写冲突(first-committer-wins)。
- 不要求全序,只要求偏序
- 允许 Write Skew: 两个事务读重叠数据、写不相交数据后都提交成功
- SI ≠ Serializable: SI 弱于 Serializable (在广义定义下)
- 典型系统: PostgreSQL (默认
REPEATABLE READ实际是 SI), Oracle, TiDB
1.2.4 · Linearizable (线性一致性)#
单对象操作看起来原子执行,且与实时顺序一致。
- 如果操作 A 在操作 B 开始前完成,则 B 必须逻辑上在 A 之后生效
- 单对象模型:作用域取决于系统 (单 key / 单表 / 单库)
- 跨对象需要 Strict Serializable
- 典型系统: etcd, ZooKeeper (写操作), 单主 Redis
1.2.5 · Sequential (顺序一致性)#
操作看起来按某个全序执行,且与每个进程内部的顺序一致,但不要求与实时顺序一致。
- 进程可以读到任意旧的状态
- 但一旦进程 A 观察到进程 B 的某个操作,A 就不会再观察到 B 更早的状态
- 典型系统: ZooKeeper (读操作+sync)
1.2.6 · Causal (因果一致性)#
因果相关的操作在所有进程上以相同顺序出现;因果无关的操作可以以不同顺序出现。
- 粘性可用: 网络分区时,只要客户端粘在同一节点就能继续
- Real-Time Causal 是异步网络全可用系统中可达到的最强模型
- 典型系统: MongoDB (causal sessions), Cassandra (轻量事务外)
1.2.7 · Read Committed (已提交读)#
事务只能看到已提交的数据(禁止脏读)。
- 禁止: P0(脏写), P1(脏读)
- 允许: P2(不可重复读), P3(幻读)
- 完全可用
- 典型系统: PostgreSQL (默认), MySQL (InnoDB 默认), Oracle
1.3 · SCQA 场景分析#
1.3.1 · 场景一: 分布式数据库 — 银行转账
- S(场景): 用户 A 向用户 B 转账 100 元,涉及两个账户的读写
- C(冲突): 转账事务中 A 的扣款和 B 的加款必须原子完成;并发转账可能导致余额不一致
- Q(问题): 如何保证跨账户操作的原子性和正确性?
- A(回答): 需要 Serializable 或 Strict Serializable。Snapshot Isolation 可能出现 Write Skew (如两个并发事务各检查总余额充足后都扣款,实际透支)。银行场景通常选择 Serializable + 悲观锁 / SSI
1.3.2 · 场景二: 分布式缓存 — 配置更新
- S(场景): 运维更新配置项后,通过侧信道通知业务服务读取新配置
- C(冲突): 业务服务可能从副本读到旧配置 (Sequential 允许读旧数据)
- Q(问题): 如何保证 “写完就能读到”?
- A(回答): 需要 Linearizable。Sequential 不够,因为它不保证实时约束。可通过共识协议 (Raft/Paxos) 实现线性一致读,或使用
ReadIndex/LeaseRead优化延迟
1.3.3 · 场景三: 社交网络 — 消息时间线
- S(场景): 用户 A 发帖 “午饭?“,B 回复 “好”,C 回复 “不行”
- C(冲突): 不同用户可能看到不同的回复顺序,但不应在问题之前看到回复
- Q(问题): 如何保证因果关系(先有问题才有回复),同时允许高可用?
- A(回答): Causal Consistency 是最佳选择。它保证因果相关操作的顺序,允许因果无关操作的顺序不同,且可以做到粘性可用。典型实现: 向量时钟 / 混合逻辑时钟(HLC)
1.3.4 · 场景四: 电商库存 — 秒杀扣减
- S(场景): 100 个用户并发秒杀 1 件商品
- C(冲突): Read Committed 下多个事务都读到库存=1,都成功扣减,超卖
- Q(问题): 如何防止超卖且保持高性能?
- A(回答): 方案梯度:
- Serializable: 最安全但性能差
- SI + 显式锁 (SELECT FOR UPDATE): 在快照隔离上通过悲观锁消除 Write Skew
- Linearizable 计数器 (Redis DECR): 用单对象线性一致性保证原子扣减,性能最优
1.3.5 · 场景五: 微服务 — 事件驱动架构
- S(场景): 订单服务写入订单后发布事件,库存服务消费事件扣减库存
- C(冲突): 订单写入成功但事件发布失败 → 数据不一致;或事件重复消费
- Q(问题): 跨服务如何保证数据一致性?
- A(回答): 跨服务无法直接使用分布式事务(性能/可用性代价太大)。通常采用最终一致性:
- Transactional Outbox: 订单和事件写入同一个本地事务 (保证本地 Serializable)
- 幂等消费 + 至少一次投递
- Saga 模式用补偿操作处理失败
1.4 · 如何选择一致性模型
需要跨对象事务的实时全序? ──是──→ Strict Serializable
│否
需要跨对象事务全序? ──是──→ Serializable
│否
需要单对象实时全序? ──是──→ Linearizable
│否
需要全局全序(允许旧读)? ──是──→ Sequential
│否
需要因果顺序? ──是──→ Causal
│否
需要避免脏读? ──是──→ Read Committed
│否
Read Uncommitted (几乎没有保证)
核心权衡: 一致性越强 → 延迟越高、可用性越低、吞吐越低
1.5 · 参考资料
- Jepsen Consistency Models
- Herlihy & Wing, Linearizability: A Correctness Condition for Concurrent Objects, 1990
- Lamport, How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs, 1979
- Berenson et al., A Critique of ANSI SQL Isolation Levels, 1995
- Bailis et al., Highly Available Transactions: Virtues and Limitations, VLDB 2014
- Viotti & Vukolić, Consistency in Non-Transactional Distributed Storage Systems, ACM Computing Surveys, 2016
- Cerone et al., A Framework for Transactional Consistency Models with Atomic Visibility, CONCUR 2015
- Adya, Weak Consistency: A Generalized Theory and Optimistic Implementations for Distributed Transactions, MIT, 1999