vlambda博客
学习文章列表

分布式事务(五)常见解决方案-Seata AT模式

介绍

Seata把分布式事务理解为一个包含的若干个分支事务的全局事务。目前提供了AT、TCC、SAGA、XA四种事务模式。

AT模式

AT模式是由2PC演变而来,在XA2PC的基础上增加了数据镜像的功能来实现分布式事务的回滚。而与XA2PC最明显的一个区别就是在阶段一中本地事务和数据镜像会同时在一个本地事务中提交,然后释放本地锁;在阶段二中如果产生异常,直接通过阶段一中数据镜像回滚进行反省补偿。

前提:使用AT模式必须使用JDBC的方式访问数据库,且数据库必须是支持本地事务的关系型数据库。

AT模式是由2PC演变而来,在XA2PC的基础上增加了数据镜像的功能来实现分布式事务的回滚。而与XA2PC最明显的一个区别就是在阶段一中本地事务和数据镜像会同时在一个本地事务中提交,然后释放本地锁;在阶段二中如果产生异常,直接通过阶段一中数据镜像回滚进行反省补偿。

执行过程

执行过程这继续采用下单扣库存的案件描述。根据Seata的概念可以把“下单扣库存”这一个全局事务理解为“下单事务”、“扣库存事务”两个分支事物。这个全局事务是由最上游操作开启的。

  1. 订单模块生成订单执行insert order SQL前先获得本地锁

  2. 执行Insert order(如果是update或者delete会将数据做镜像写入到回滚日志中undo_log)结束后尝试获取全局锁。

  3. 拿到全局锁后提交本地事务,

  4. 本地事务提交成功,释放本地锁,

  5. 提交全局事务,提交成功后释放全局锁

  6. 在上诉步骤执行的同时商品模块也在执行自己的本地事务

  7. 商品模块先获取本地锁后执行update productStock,同时将这条记录写入到回滚日志中

  8. 执行成功尝试获取全局锁,因为此时全局锁可被订单模块持有,会在这里等待全局锁,所以这里必须有重试机制,不断的获取全局锁

  9. 拿到全局锁后,提交商品模块本地事务

  10. 提交成功,释放全局锁

  11. 如果在此期间没有发生异常,会异步删除回滚日志,这个全局事务就完成了。

  12. 如果订单模块提交全局事务失败,当前分支执行回滚,商品模块一直获取不到全局锁,达到重试机制的阈值,也将回滚本地事务。

  13. 如果在商品模块提交全局事务失败,也会通知订单模块根本回滚日志反向补偿数据。

要点说明

  1. 每个RM都使用DataSourceProxy链接数据库,其目的是为了ConnectionProxy, 使用数据源和数据链接代理的目的是为了阶段一中本地业务数据和undo_log在同一个本地事务中提交,保证每一个本地事务操作和undo_log一一对应。

  2. 在阶段一中undo_log中存放了数据修改前和修改后的值,为后续的事务回滚做好准备。

  3. TM开启全局事务开始,将XID(全局事务标识)放在事务上下文中,在远程调用的过程中将XID传给下游服务,从而贯穿全局。

  4. 每个分支事务都有BranhID做唯一标识,并且和XID关联。

  5. 阶段二中全局事务提交,TC会通知各个相关联的分支事务提交,因为阶段一中已经提交了分支事务,所以这里只需要异步删除undo_log即可。

  6. 阶段二中全局事务回滚,TC会通知各个相关联的分支事务回滚,通过XID和BranchID可找到对应的undo_log日志,通过日志反向生成SQL并执行,即可恢复到本地分支事务提交前的状态。如果回滚失败会有重试机制。