概述
Seata官网:http://seata.io/zh-cn/
在前一篇文章:分布式事务2PC协议之——XA方案中,我们最后提到了XA方案存在的两个问题:
- 需要本地数据库支持XA协议
- 资源锁需要等到两个阶段都完成之后才能释放,性能受影响。
这两个问题在Seata方案中得以解决。
- Seata不要求数据库支持XA协议,只要求数据库可以完成其本地事务就可以了(实际就是支持ACID的关系型数据库)
- 对数据库资源占用时间短
Seata方案是阿里中间件团队发起的开源项目Fescar,之后更名为Seata,它是一个开源的分布式事务框架。它通过对本地关系数据库的分支事务的协调来驱动完成全局事务,是工作在应用层的中间件。主要有点就是性能较好,且不长时间占用数据库资源,它以高效的、对业务零入侵的方式解决微服务场景下面临的分布式事务问题,它目前提供AT模式(即2PC)、TCC模式、XA模式以及Saga 模式四种分布式事务解决方案。
设计思想
Seata的设计目标其一是对业务无侵入,因此从业务无侵入的2PC方案着手,在传统2PC(XA方案)的基础上演进,并解决2PC方案面临的问题。
Seata把一个分布式事务理解成为了一个包含若干分支事务的全局事务。全局事务的职责是协调其中管辖的分支事务达成一致,要么一起成功,要么一起失败回滚。此外分支事务本身就是一个关系型数据库的本地事务。
与传统的2PC模型类似,Seata定义了三个组件来处理分布式事务:
- Transaction Coordinator(TC 事务协调器):,相对于传统2PC而言多增加了一个事务协调器,它是独立的中间件,需要独立部署运行,维护全局和分支事务的状态,驱动全局事务提交或回滚。接收TM指令发起的全局事务的提交和回滚操作,负责与RM通讯协调各个分支事务的提交和回滚。
- Transaction Manager(TM):定义全局事务的范围,开始全局事务、提交或回滚全局事务。TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向TC发起全局提交或者全局回滚的指令
-
Resource Manager (RM):管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。简单来说就是控制分支事务,负责分支事务的注册、状态汇报,接手事务协调器(TC)的指令,真正的完成分支事务的提交和回滚
总结一下就是TM做决策,TC负责传话,RM真正的干活。
该示例执行流程如下:
- 用户服务的TM向TC申请开启一个全局事务,TC创建成功全局事务并生成一个全局唯一的XID(这里为什么是用户服务嵌入了TM呢?而不是积分服务?因为用户服务是业务的发起者,先注册再送积分,所以用户服务有一个TM),TM是一个全局事务的开端
- 用户服务的RM首先向TC注册分支事务,该分支事务再用户服务执行新增用户操作,并将其纳入XID对应的全局事务的管辖,此时事务已经提交并释放数据库资源,数据已经真正的持久化。与XA方案不同,这里就是解决数据库资源锁定时间长的关键
- 用户服务执行分支事务,向用户表插入一条记录
- 逻辑执行到远程调用积分服务时(XID在微服务调用链路的上下文中传播)。积分服务的RM向TC注册分支事务,该分之十五执行增加积分的操作,并将其纳入XID对应的全局事务管辖
- 积分服务执行分支事务,向积分记录表插入一条记录。此时事务已经提交并释放数据库资源,数据已经真正的持久化
- 用户服务分支事务都执行完毕
- TM向TC发起针对的XID的全局事务提交或者回滚决议
- TC调用XID下管辖的全部分支事务完成提交或者回滚请求。
这个过程讲完了,会有人一脸懵逼,黑人问号?两次分支事务的数据库操作不都已经持久化数据了嘛,TM向TC发起针对XID的全局事务提交或者回滚决议还有什么用?还怎么来回滚各个分支事务啊?
答:很简单,就是反向操作就行了,注册用户不是插入了一条记录了嘛?把这条数据删掉!积分服务不是已经插入一条数据了嘛?删掉这条数据!Seata就是这么干的,这样就能解决XA方案对数据库资源占用时间长的问题。
Seata实现的2PC和传统2PC的差别
架构层面,传统2PC方案的RM实际上就是在数据库层面(依托于数据库对2PC的支持),RM本质上就是数据自身,通过XA协议实现。而Seata的RM是以jar包的形式作为中间件层部署在应用程序一侧。
两阶段提交方面,传统2PC无论是第二阶段的决议是Commit还是rollback,占用的数据库资源都要等到第二阶段完成之后才能释放,Seata在第一阶段就将各个分支事提交,提高效率。