Seata 是一款阿里开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案

github地址:https://github.com/seata/seata。

在分析 seata 事务二阶段执行流程之前,首先来看下XA的2PC 流程:

 

对于 XA 来说,无论 Phase2 的决议是 commit 还是 rollback,事务性资源的锁都要保持到 Phase2 完成才释放。一般对于一个正常运行的业务,大概率是 90% 以上的事务最终应该是可以成功提交的,我们是否可以在 Phase1 就将本地事务提交呢?这样 90% 以上的情况下,可以省去 Phase2 持锁的时间,降低锁粒度,整体提高效率。

如果在Phase1就将本地事务提交,那么当第二阶段要求回滚时,只需要根据 xid 找到对应的原数据,进行恢复即可,这时事务的 commit 和 rollback 所属2个事务。

 

  • 分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。
  • 同时,随着本地事务结束,连接 也得以释放。
  • 分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。

这个设计,极大地减少了分支事务对资源(数据和连接)的锁定时间,给服务整体并发和吞吐的提升提供了基础。

分支事务提交和回滚

首先,应用需要使用 Seata 的 JDBC 数据源代理,才能进行分布式事务操作。

Phase1:Seata 的 JDBC 数据源代理通过对业务 SQL 的解析,把业务数据在更新前后的数据镜像组织成回滚日志,利用 本地事务 的 ACID 特性,将业务数据的更新和回滚日志的写入在同一个 本地事务 中提交(也就是 undolog 功能)。这样,可以保证:任何提交的业务数据的更新一定有相应的回滚日志存在。

 

基于这样的机制,分支的本地事务便可以在全局事务的 Phase1 提交,马上释放本地事务锁定的资源。

Phase2

如果决议是全局提交,此时分支事务此时已经完成提交,不需要同步协调处理(只需要异步清理回滚日志),Phase2 可以非常快速地完成。

 

如果决议是全局回滚,RM 收到协调器发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。

 

针对全局事务的所有分支事务发起回滚操作,如果某个分支事务回滚操作执行异常,那么在seata-server会由retryRollbacking定时任务始终驱动的,默认5s。

retryRollbacking.scheduleAtFixedRate(() -> {
    try {
        handleRetryRollbacking();
    } catch (Exception e) {
        LOGGER.info("Exception retry rollbacking ... ", e);
    }
}, 0, rollbackingRetryDelay, TimeUnit.SECONDS);

注意:seata 中有很多这样的线程池,比如心跳、commit 重试等场景就是线程池来完成对应操作。

最后来一张整体的seata 执行流程图:

 

注意:全局事务的开始是在 TM 的业务代码中开始的,比如@GlobalTransactional处,而 RM 的注册是在数据层开始的,首先进行数据操作并记录 undolog 数据,然后进行 RM 分支注册,再进行本地事务提交,最后上报给 TC 事务状态。更详细流程如下:

  1. 当需要发起一个分布式事务流程时,TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
  2. XID 在微服务调用链路的上下文中传播(这里需要适配 dubbo/spring cloud 分布式框架)。
  3. 当进行数据操作时,RM首先进行本地事务操作,但是先不 commit,然后向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。
  4. RM提交本地事务,上报本地事务状态给 TC。
  5. TM 向 TC 发起针对 XID 的全局提交或回滚决议。
  6. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

原文链接:https://mp.weixin.qq.com/s?__biz=MzIwNTI2ODY5OA==&mid=2649939258&idx=1&sn=0ac3776e057aab8c7df126763bbc4364

如果觉得本文对你有帮助,可以关注一下我公众号,回复关键字【面试】即可得到一份Java核心知识点整理与一份面试大礼包!另有更多技术干货文章以及相关资料共享,大家一起学习进步!