seata执行闪退_seata 事务提交流程

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 事务状态。更详细流程如下:

当需要发起一个分布式事务流程时,TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。

XID 在微服务调用链路的上下文中传播(这里需要适配 dubbo/spring cloud 分布式框架)。

当进行数据操作时,RM首先进行本地事务操作,但是先不 commit,然后向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。

RM提交本地事务,上报本地事务状态给 TC。

TM 向 TC 发起针对 XID 的全局提交或回滚决议。

TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

你可能感兴趣的:(seata执行闪退)