Seata 是一款开源的分布式事务解决方案,支持 AT(自动补偿型)、TCC(Try-Confirm-Cancel)、Saga 和 XA 等多种事务模式。其中,AT 模式是 Seata 的默认模式,也是最常用的模式。下面主要介绍 AT 模式 的事务回滚实现机制。
1. AT 模式的核心思想
AT 模式基于 两阶段提交(2PC) 的思想,分为两个阶段:
- 第一阶段(执行阶段):执行业务 SQL,生成回滚日志(undo log),并提交本地事务。
- 第二阶段(提交/回滚阶段):根据全局事务的状态,决定是提交还是回滚。
2. 事务回滚的实现机制
在 AT 模式下,事务回滚的核心依赖于 回滚日志(undo log)。以下是具体的实现步骤:
(1)生成回滚日志
- 在执行业务 SQL 之前,Seata 会解析 SQL,生成对应的 回滚日志(undo log)。
- 回滚日志记录了数据修改前的快照(before image)和修改后的快照(after image)。
- 回滚日志会与业务数据一起提交到本地数据库中。
(2)本地事务提交
- 业务 SQL 和回滚日志会作为一个本地事务提交到数据库中。
- 如果本地事务提交成功,Seata 会向事务协调器(TC)报告分支事务的状态。
(3)全局事务回滚
- 如果全局事务需要回滚,Seata 会从 TC 获取所有分支事务的回滚日志。
- 根据回滚日志中的 before image,生成反向 SQL(如将 UPDATE 还原为原来的值,将 DELETE 还原为 INSERT)。
- 执行反向 SQL,恢复数据到修改前的状态。
- 删除回滚日志,完成回滚操作。
3. 回滚日志的结构
回滚日志(undo log)通常包含以下信息:
- branch_id:分支事务的唯一标识。
- xid:全局事务的唯一标识。
- table_name:操作的表名。
- sql_type:SQL 类型(INSERT、UPDATE、DELETE)。
- before_image:数据修改前的快照。
- after_image:数据修改后的快照。
4. 回滚的触发条件
- 全局事务失败:如果全局事务中的某个分支事务失败,TC 会通知所有分支事务回滚。
- 超时回滚:如果全局事务未在规定时间内完成,TC 会触发回滚。
- 手动回滚:开发者可以通过代码手动触发回滚。
5. 回滚的注意事项
- 幂等性:回滚操作必须是幂等的,确保多次回滚不会导致数据不一致。
- 并发控制:在回滚过程中,需要加锁防止其他事务修改同一数据。
- 回滚日志清理:回滚完成后,需要及时清理回滚日志,避免日志膨胀。
6. AT 模式的优缺点
优点:
- 对业务代码无侵入:开发者只需关注业务逻辑,无需手动编写回滚逻辑。
- 性能较高:第一阶段提交本地事务,第二阶段只需异步提交或回滚。
缺点:
- 依赖数据库:需要数据库支持本地事务和回滚日志。
- 锁竞争:在回滚过程中可能会产生锁竞争,影响性能。
7. 示例
假设有一个订单服务,需要扣减库存和创建订单。以下是 AT 模式的回滚流程:
- 第一阶段:
- 扣减库存:生成库存表的回滚日志(before image:库存数量,after image:扣减后的数量)。
- 创建订单:生成订单表的回滚日志(before image:空,after image:订单数据)。
- 提交本地事务。
- 第二阶段:
- 如果全局事务失败,Seata 会根据回滚日志:
- 恢复库存数量(执行反向 SQL)。
- 删除订单(执行反向 SQL)。
- 完成回滚。
- 如果全局事务失败,Seata 会根据回滚日志:
总结
Seata 的 AT 模式通过 回滚日志(undo log) 实现事务回滚,具体步骤如下:
- 执行业务 SQL 并生成回滚日志。
- 提交本地事务。
- 如果全局事务失败,根据回滚日志执行反向 SQL,恢复数据。
- 清理回滚日志。
这种机制保证了分布式事务的原子性和一致性,同时对业务代码无侵入,适合大多数分布式事务场景。
THE END
暂无评论内容