1. 背景
在单体系统中,数据库通常是单一实例,事务(ACID)能保证强一致性。
但在 微服务 + 分布式系统 中:
- 数据分散在不同服务(订单、库存、支付等)
- 不同数据库(MySQL、Redis、MongoDB 等)
- 跨网络通信,不可避免有延迟、失败、重试
👉 结果是:强一致性难以保证。
因此,后端工程师必须掌握 数据一致性模式 来保证业务正确性。
2. 一致性模型回顾
- 强一致性(Strong Consistency) :所有副本数据在同一时刻相同。
- 最终一致性(Eventual Consistency) :经过一段时间,副本数据最终一致。
- 因果一致性(Causal Consistency) :保证有因果关系的操作顺序一致。
微服务架构下,大部分场景采用 最终一致性,通过补偿和事件机制来保证。
3. 常见的一致性模式
3.1 两阶段提交(2PC, Two-Phase Commit)
- 原理:协调者先“准备”,所有参与者同意后再“提交”。
- 优点:接近强一致性。
- 缺点:阻塞、性能差、单点故障。
- 适用场景:少数强一致性要求极高的分布式事务。
3.2 Saga 模式
Saga 是 长事务拆分 + 补偿 的思路:
- 将全局事务拆成一系列本地事务,每个事务有对应的补偿操作。
- 如果中途失败,执行补偿事务撤销之前的操作。
例子:下单流程
- 订单服务 → 创建订单
- 库存服务 → 扣减库存
- 支付服务 → 扣款
❌ 如果支付失败 → 触发补偿:库存回滚、订单取消。
👉 Saga 可以通过 事件驱动 或 集中编排(Orchestrator) 实现。
3.3 TCC 模式(Try-Confirm-Cancel)
- Try:预留资源(冻结库存、预扣款)
- Confirm:真正提交
- Cancel:取消预留
适合对资源一致性要求更高的场景(金融转账、机票预定)。
3.4 Outbox Pattern
为了解决“本地事务 + 事件发送”不一致的问题:
- 把事件和业务数据写入同一个数据库事务(Outbox 表)。
- 由异步任务(CDC 或定时器)将事件发送到消息队列。
- 保证业务操作和事件投递要么同时成功,要么同时失败。
👉 常见在 Kafka + MySQL 场景。
3.5 基于事件的最终一致性
- 使用 Kafka / Pulsar 等消息队列传递事件。
- 消费者异步处理,保证最终一致性。
- 通过幂等性、重试机制保证可靠。
4. 实践要点
-
幂等性设计:
- 数据库操作使用 UPSERT
- API 使用全局请求 ID 去重
-
补偿机制:
- Saga、TCC 必须有对应的 Cancel/Compensate 流程
-
监控与告警:
- 一致性问题往往不是完全自动可解,需要监控 + 人工介入
-
事务边界:
- 明确哪些操作必须强一致,哪些可以最终一致
5. 应用场景
电商系统
- 下单 → 库存 → 支付 → 物流
- 常用 Saga 或 Outbox
金融系统
- 转账 → 扣款 + 入账
- 常用 TCC,保证资金安全
SaaS 平台
- 用户订阅服务 → 开通功能 → 发放优惠券
- 常用事件驱动 + 最终一致性
6. 对比总结
| 模式 | 一致性 | 性能 | 复杂度 | 典型场景 |
|---|---|---|---|---|
| 2PC | 强一致 | 低 | 高 | 跨库事务 |
| Saga | 最终一致 | 中 | 中 | 电商订单 |
| TCC | 接近强一致 | 中 | 高 | 金融转账 |
| Outbox | 最终一致 | 高 | 中 | 事件驱动 |
| 事件驱动 | 最终一致 | 高 | 中 | 微服务解耦 |
7. 总结
在分布式后端架构中:
- 不存在万能方案,一致性模式必须结合业务权衡。
- 高并发、高可用的系统往往依赖 Saga + Outbox + 幂等性。
- 对安全性要求极高的系统(金融)则会采用 TCC 或部分 2PC。
👉 一句话总结:
强一致性很昂贵,最终一致性更常见,但需要工程上精心设计补偿与幂等。