阿里开源的分布式事务框架 Seata

原文请关注:性能与架构公众号
1. Seata 概述Seata 是 Simple Extensible Autonomous Transaction Architecture 的简写,由 feascar 改名而来 。
Seata 是阿里开源的分布式事务框架,属于二阶段提交模式 。
目前github上已经有 12267 颗星了,也很活跃,最新的提交时间很多都是几天前 。
首先我们回顾一下在单体应用中,例如一个业务调用了3个模块,他们都使用同一个数据源,是靠本地事务来保证事务一致性 。
阿里开源的分布式事务框架 Seata

文章插图
 
但在微服务架构中,这3个模块会变为3个独立的微服务,各自有自己的数据源,调用逻辑就变为:
阿里开源的分布式事务框架 Seata

文章插图
 
Seata 如何处理呢?
阿里开源的分布式事务框架 Seata

文章插图
 
Business 是业务入口,在程序中会通过注解来说明他是一个全局事务,这时他的角色为 TM(事务管理者) 。
Business 会请求 TC(事务协调器,一个独立运行的服务),说明自己要开启一个全局事务,TC 会生成一个全局事务ID(XID),并返回给 Business 。
Business 得到 XID 后,开始调用微服务,例如调用 Storage 。
阿里开源的分布式事务框架 Seata

文章插图
 
(和上面的图一样,方便查看,防止滚到到这儿时已经看不到上面的图片了)
Storage 会收到 XID,知道自己的事务属于这个全局事务 。Storage 执行自己的业务逻辑,操作本地数据库 。
Storage 会把自己的事务注册到 TC,作为这个 XID 下面的一个分支事务,并且把自己的事务执行结果也告诉 TC 。
此时 Storage 的角色是 RM(资源管理者),资源是指本地数据库 。
Order、Account 的执行逻辑与 Storage 一致 。
在各个微服务都执行完成后,TC 可以知道 XID 下各个分支事务的执行结果,TM(Business) 也就知道了 。
Business 如果发现各个微服务的本地事务都执行成功了,就请求 TC 对这个 XID 提交,否则回滚 。
TC 收到请求后,向 XID 下的所有分支事务发起相应请求 。
各个微服务收到 TC 的请求后,执行相应指令,并把执行结果上报 TC 。
重要机制
(1)全局事务的回滚是如何实现的呢?
Seata 有一个重要的机制:回滚日志 。
每个分支事务对应的数据库中都需要有一个回滚日志表 UNDO_LOG,在真正修改数据库记录之前,都会先记录修改前的记录值,以便之后回滚 。
在收到回滚请求后,就会根据 UNDO_LOG 生成回滚操作的 SQL 语句来执行 。
如果收到的是提交请求,就把 UNDO_LOG 中的相应记录删除掉 。
(2)RM 是怎么自动和 TC 交互的?
是通过监控拦截JDBC实现的,例如监控到开启本地事务了,就会自动向 TC 注册、生成回滚日志、向 TC 汇报执行结果 。
(3)二阶段回滚失败怎么办?
例如 TC 命令各个 RM 回滚的时候,有一个微服务挂掉了,那么所有正常的微服务也都不会执行回滚,当这个微服务重新正常运行后,TC 会重新执行全局回滚 。
1.3 核心组件
回顾一下其中的核心组件:
  • 事务协调器 TC
维护全局和分支事务的状态,指示全局提交或者回滚 。
  • 事务管理者 TM
开启、提交或者回滚一个全局事务 。
  • 资源管理者 RM
管理执行分支事务的那些资源,向TC注册分支事务、上报分支事务状态、控制分支事务的提交或者回滚 。
1.4 具体工作过程
再从宏观上梳理一下 Seata 的工作过程:
阿里开源的分布式事务框架 Seata

文章插图
 
  • TM 请求 TC,开始一个新的全局事务,TC 会为这个全局事务生成一个 XID 。
  • XID 通过微服务的调用链传递到其他微服务 。
  • RM 把本地事务作为这个XID的分支事务注册到TC 。
  • TM 请求 TC 对这个 XID 进行提交或回滚 。
  • TC 指挥这个 XID 下面的所有分支事务进行提交、回滚 。
2. Seata 详细工作流程示例下面我们通过一个分支事务的执行过程来了解 Seata 的工作流程 。
例如有一个业务表 product(id,name),分支事务的业务逻辑:
  •  
update product set name = 'GTS' where name = 'TXC';2.1 一阶段
(1)解析 SQL
得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息 。


推荐阅读