一,简介
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
1.1,三种角色
1,Transaction Coordinator (TC): 事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
2,Transaction Manager ™: 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
3,Resource Manager (RM): 控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚。
其中,TM是一个分布式事务的发起者和终结者,TC负责维护分布式事务的运行状态,而RM则负责本地事务的运行。如下图所示:
1.2,Seata实现2PC与传统2PC的差别
架构层次方面,传统 2PC 方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身,通过 XA 协议实现,而会Seata 的 RM 是以 jar 包的形式作为中间件层部署在应用程序这一侧的。
两阶段提交方面,传统2PC无论第二阶段的决议是 commit 还是 rollback,事务性资源的锁都要保持到第二阶段完成才释放。而Seata的做法是在第一阶段就将本地事务提交
,这样就可以省去第二阶段持锁的时间,整体提高效率。
二,一个分布式事务在Seata中的执行流程
① TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID,
XID 在微服务调用链路的上下文中传播。
② RM 向 TC 注册分支事务,接着执行这个分支事务并提交(重点:RM在第一阶段就已经执行了本地事务的提交/回滚),最后将执行结果汇报给TC。
③ TM 根据 TC 中所有的分支事务的执行情况,发起全局提交或回滚决议。
④ TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
2.1,Seata 执行流程要点
1、每个RM使用 DataSourceProxy 连接数据库,其目的是使用 ConnectionProxy,使用数据源和数据连接代理的目的就是在第一阶段将 undo_log 和业务数据放在一个本地事务提交,这样就保存了只要有业务操作就一定有undo_log。
2、在第一阶段 undo_log 中存放了数据修改前和修改后的值,为事务回滚作好准备,所以第一阶段完成就已经将分支事务提交,也就释放了锁资源。
3、TM 开启全局事务开始,将 XID 全局事务id放在事务上下文中,通过 feign 调用也将 XID 传入下游分支事务,每个分支事务将自己的 Branch ID 分支事务 ID 与 XID 关联。
4、第二阶段全局事务提交,TC 会通知各各分支参与者提交分支事务,在第一阶段就已经提交了分支事务,这里各各参与者只需要删除 undo_log 即可,并且可以异步执行,第二阶段很快可以完成。
5、第二阶段全局事务回滚,TC 会通知各各分支参与者回滚分支事务,通过 XID 和 Branch ID 找到相应的回滚日志,通过回滚日志生成反向的 SQL 并执行,以完成分支事务回滚到之前的状态,如果回滚失败则会重试回滚操作。
2.2,Seata实现2PC要点
1、全局事务开始使用 @GlobalTransactional标识 。
GlobalTransactionalInterceptor 会拦截 @GlobalTransactional 注解的方法,生成全局事务 ID(XID),XID 会在整个分布式事务中传递。在远程调用时,spring-cloud-alibaba-seata 会拦截 Feign 调用将 XID 传递到下游服务。
2、每个本地事务方案仍然使用 @Transactional 标识。
3、每个数据都需要创建 undo_log 表,此表是 seata 保证本地事务一致性的关键。
评论区