面试题:Seata 的事务回滚是怎么实现的?

Seata 是一款开源的分布式事务解决方案,支持 AT(自动补偿型)、TCC(Try-Confirm-Cancel)、Saga 和 XA 等多种事务模式。其中,AT 模式是 Seata 的默认模式,也是最常用的模式。下面主要介绍 AT 模式 的事务回滚实现机制。


1. AT 模式的核心思想

AT 模式基于 两阶段提交(2PC) 的思想,分为两个阶段:

  1. 第一阶段(执行阶段):执行业务 SQL,生成回滚日志(undo log),并提交本地事务。
  2. 第二阶段(提交/回滚阶段):根据全局事务的状态,决定是提交还是回滚。

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 模式的回滚流程:

  1. 第一阶段
    • 扣减库存:生成库存表的回滚日志(before image:库存数量,after image:扣减后的数量)。
    • 创建订单:生成订单表的回滚日志(before image:空,after image:订单数据)。
    • 提交本地事务。
  2. 第二阶段
    • 如果全局事务失败,Seata 会根据回滚日志:
      • 恢复库存数量(执行反向 SQL)。
      • 删除订单(执行反向 SQL)。
    • 完成回滚。

总结

Seata 的 AT 模式通过 回滚日志(undo log) 实现事务回滚,具体步骤如下:

  1. 执行业务 SQL 并生成回滚日志。
  2. 提交本地事务。
  3. 如果全局事务失败,根据回滚日志执行反向 SQL,恢复数据。
  4. 清理回滚日志。

这种机制保证了分布式事务的原子性和一致性,同时对业务代码无侵入,适合大多数分布式事务场景。

THE END
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容