引言
随着互联网业务向高并发、高可用、大规模数据演进,传统单体架构中的本地事务(Local Transaction)越来越无法满足需求。数据库需要拆分、服务需要拆分,随之而来的就是对 分布式事务(Distributed Transaction) 的需求。
然而,分布式事务不仅复杂,而且涉及大量理论体系,因此常是中高级工程师绕不开的知识点。
本文将从背景、理论体系、事务模型到 2PC/3PC 协议,一次讲透分布式事务的全貌。
一、分布式事务产生的背景
分布式事务并不是无中生有,而是由业务规模和系统架构演进推动的 ------ 你无法避免,也无法绕过。
1. 数据库水平拆分(Sharding)
当单库数据量太大、连接数无法承受、IO发生瓶颈时,我们必须做:
-
垂直拆分(按业务拆表)
-
水平拆分(按用户ID、订单ID分片)
拆分之后,一个业务操作可能需要跨多个数据库完成。
例如:
订单库(order-db)保存订单信息
库存库(stock-db)保存库存信息
支付库(payment-db)保存支付流水
创建订单可能需要:
- 创建订单(order-db)
- 扣减库存(stock-db)
- 记录扣费流水(payment-db)
跨库意味着 事务不能再依赖单库的 ACID,本质上触发了分布式事务需求。
2. 业务服务化拆分(微服务化)
在微服务架构中,一个完整流程由多个服务协同完成,例如:
OrderService → StockService → PaymentService
每个服务背后有自己的数据库、缓存、消息队列...
服务之间通过网络调用,本质是分布式系统。
这意味着:
- 一个业务逻辑跨多个服务
- 因为每个服务有独立数据库,所以必然跨库
- 服务调用失败的概率远高于本地方法调用
- 需要通过分布式事务保障一致性
所以:
数据库的拆分 + 服务的拆分 == 分布式事务不可避免
二、分布式事务的理论基础
分布式事务必须建立在三个基础理论上:
- CAP 定理
- BASE 理论
- ACID 扩展
不过本文不展开 CAP/BASE,而直接进入事务的分类和模型。
三、分布式事务类型:刚性事务与柔性事务
分布式事务大体分两类:刚性事务(Rigid) 和 柔性事务(Flexible)。
1. 刚性事务(Rigid Transaction)------ 强一致性
特点:
- 保证 ACID
- 事务在分布式环境仍保持严格一致性
- 通常依赖 XA、2PC、3PC 协议实现
代表:
- XA(两阶段提交)
- 分布式数据库内部事务(如 OceanBase、TiDB 等)
优势:
- 强一致性
- 应用端简单
缺点:
- 高延迟
- 长时间锁资源
- 规模扩展受限
适用场景:
银行式核心金融交易、金额绝对不能错的场景。
2. 柔性事务(Flexible Transaction)------ 最终一致性
柔性事务追求 最终一致性 ,不会追求某一时刻必须一致。
柔性事务又分:
(1)补偿型事务:Saga、TCC
- 有明确的 正向操作 & 补偿操作
- 各阶段失败后通过补偿回滚
适用于:
- 业务可以"人工撤销"
- 可实现业务补偿逻辑
典型例子:
机票 + 酒店 + 租车的旅行预订。
(2)通知型事务(可靠事件型)
- 基于消息队列
- 生产者先落本地表,再投递消息
- 消费者最终处理成功即可
适用于:
- 对一致性要求不是绝对强
- 如:积分系统、异步通知、营销系统
四、为什么需要补偿型分布式事务?
因为分布式系统中有三个无法避免的问题:
- 网络是不可靠的(延迟、丢包)
- 服务会挂、节点会崩
- 资源跨库和跨服务,不可能锁住太久
传统的强一致(例如 2PC)有一个致命缺点:
- 阻塞:所有参与者必须等待协调者指令
- 网络抖动可能导致事务长时间锁表/锁资源
在现代高并发业务中,这种方式不可接受。
因此:
- 补偿型事务(Saga、TCC)成为主流
- 允许失败时通过业务逻辑修复(补偿)
- 避免长时间锁资源
五、分布式事务模式(AT / TCC / Saga / XA)详解
1. XA(2PC模型)------ 强一致性
优点:
- 标准化
- 框架支持简单
缺点:
- 性能差
- 强依赖协调器
- 容易阻塞
2. TCC(Try--Confirm--Cancel)
关键思想:
Try 预留资源
Confirm 真正提交
Cancel 释放资源
优点:
- 强控制力,业务可控
缺点:
- 需要大量补偿业务代码
- 成本高、开发复杂
3. Saga ------ 长事务补偿模型
Saga = 一系列可独立提交的本地事务 + 逆向补偿操作。
结构:
T1, T2, T3 ...
C1, C2, C3 ...(补偿)
优点:
- 最易落地
- 不锁资源
缺点:
- 不能解决强一致性
- 补偿逻辑较复杂
4. AT 模式(Seata)
AT = 自动回滚/提交,不需要业务侧写 TCC 代码。
原理:
- 通过 UndoLog 记录数据快照
- 通过二阶段自动提交或回滚
- 提供最终一致性
适合中间态,兼顾性能和易用性。
六、分布式事务协议:2PC 与 3PC
下面进入核心 ------ 分布式事务协议。
1. 两阶段提交(2PC)
2PC(Two Phase Commit)分两阶段:
阶段 1:准备阶段(Prepare)
协调者向所有参与者发送:
是否可以提交?(prepare)
参与者:
- 执行本地事务
- 写入 redo log
- 锁定资源
- 返回投票:YES 或 NO
阶段 2:提交阶段(Commit/Rollback)
如果所有参与者返回 YES:
- 协调者广播 COMMIT
- 参与者提交本地事务、释放锁
若任意一个返回 NO 或超时:
- 协调者广播 ROLLBACK
2PC 的优点
- 实现简单
- 实际使用最广泛
- 强一致性保证
2PC 的缺点(致命)
- 同步阻塞:所有参与者被锁住
- 协调者单点故障
- 无法解决网络分区导致的"悬挂问题"
- 例如:参与者已提交,但协调者以为失败并要求回滚
2PC 的这些缺陷催生了 3PC。
2. 三阶段提交(3PC)
3PC(Three Phase Commit)引入:
- 超时机制
- 增加一个准备确认阶段
三个阶段:
1. CanCommit(询问阶段)
协调者仅询问是否能提交,不执行事务。
2. PreCommit(预提交阶段)
参与者执行操作但不提交,进入预提交状态。
3. DoCommit(提交阶段)
协调者最终下达指令:
- 超时仍无响应默认提交(安全更好)
3PC 的优点
- 引入 超时机制
- 减少阻塞
- 降低协调者阻塞造成的风险
3PC 的缺点
- 实现复杂
- 即使加入超时,依然无法完全避免网络分区导致数据不一致
- 工业界采用相对较少(更多见于理论与特定分布式数据库)
总结
| 内容 | 说明 |
|---|---|
| 产生背景 | 数据库拆分、服务拆分 |
| 事务类型 | 刚性(ACID) vs 柔性(最终一致) |
| 模式 | XA、TCC、Saga、AT |
| 协议 | 2PC、3PC |
| 为什么要补偿 | 避免长锁、应对失败场景 |
| 实际落地 | 多用柔性事务(TCC/Saga/AT) |