什么是分布式事务Seata?Seata的几种事务模式详解

最后更新于:2020-04-08 17:37

概念

Seata(原名Fescar) 是 阿里巴巴 开源的 分布式事务中间件,以 高效 并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题。

发展历程

2014 年,阿里中间件团队发布 TXC(Taobao Transaction Constructor),为集团内应用提供分布式事务服务。

2016 年,TXC 经过产品化改造,以 GTS(Global Transaction Service) 的身份登陆阿里云,成为当时业界唯一一款云上分布式事务产品,在阿云里的公有云、专有云解决方案中,开始服务于众多外部客户。

2019 年起,基于 TXC 和 GTS 的技术积累,阿里中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社区一起建设这个分布式事务解决方案。

Fescar 开源后,蚂蚁金服加入 Fescar 社区参与共建,并在 Fescar 0.4.0 版本中贡献了 TCC 模式。

为了打造更中立、更开放、生态更加丰富的分布式事务开源社区,经过社区核心成员的投票,大家决定对 Fescar 进行品牌升级,并更名为 Seata,意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案。

核心组件

Seata官方针对TXC模型制作的示意图:
在这里插入图片描述
TXC的实现通过三个组件来完成。也就是上图的三个深黄色部分,其作用如下:

TC(Transaction Coordinator): 事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚(server端)。这个组件需要独立部署维护,目前0.6.1版本已经支持集群部署。

TM(Transaction Manager): 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议(client端)。

RM(Resource Manager):控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚(client端)。

TM是一个分布式事务的发起者和终结者,TC负责维护分布式事务的运行状态,而RM则负责本地事务的运行。

从模型图中可以看出,这三者的核心是TC,下图是Seata-Server整体的模块图:
在这里插入图片描述
1)Coordinator Core:最下面的模块是事务协调器核心代码,主要用来处理事务协调的逻辑,如是否 Commit、Rollback 等协调活动。

2)Store:存储模块,用来将我们的数据持久化,防止重启或者宕机数据丢失。

3)Discover:服务注册/发现模块,用于将 Server 地址暴露给 Client。

4)Config:用来存储和查找服务端的配置。

5)Lock:锁模块,用于给 Seata 提供全局锁的功能。

6)Rpc:用于和其他端通信。

7)HA-Cluster:高可用集群,目前还没开源。为 Seata 提供可靠的高可用功能。

这里暂不做详细讲解,可参考:http://seata.io/zh-cn/blog/seata-analysis-java-server.html

三种事务模式

AT模式

今年 1 月份,Seata 开源了 AT 模式。AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

前提

1.基于支持本地 ACID 事务的关系型数据库。
2.Java 应用,通过 JDBC 访问数据库。

一个分布式事务在Seata中的执行流程

在这里插入图片描述
执行步骤:
1.TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID(由 ip:port:sequence 组成)。XID 在微服务调用链路的上下文中传播。
2.RM 向 TC 注册分支事务,接着执行这个分支事务并提交,最后将执行结果汇报给TC。
3.TM 根据 TC 中所有的分支事务的执行情况,发起全局提交或回滚决议。
4.TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

Seata 的事务提交方式与 XA 协议的两段式提交有什么不同呢?

XA协议

在这里,先说一下XA协议,以下是百度百科的介绍:
XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。
以下的函数是事务管理器可以对资源管理器进行的操作:
1)xa_open,xa_close:建立和关闭与资源管理器的连接。
2)xa_start,xa_end:开始和结束一个本地事务。
3)xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个本地事务。
4)xa_recover:回滚一个已进行预提交的事务。
5)ax_开头的函数使资源管理器可以动态地在事务管理器中进行注册,并可以对XID(TRANSACTION IDS)进行操作。
6)ax_reg,ax_unreg;允许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。

以MySQL XA方案为例
RM(Resource Manager):资源管理器,用于直接执行本地事务的提交和回滚。在分布式集群中,一台MySQL服务器就是一个RM。
TM(Transaction Manager):事务管理器,它是分布式事务的核心管理者。事务管理器与每个RM进行通信,协调并完成分布式事务的处理。发起一个分布式事务的MySQL客户端就是一个TM。

XA的两阶段提交分为Prepare阶段和Commit阶段,过程如下:

阶段一为准备阶段(prepare)。即所有的RM锁住需要的资源,在本地执行这个事务(执行sql,写redo/undo log等),但不提交,然后向Transaction Manager报告已准备就绪。
阶段二为提交阶段(commit)。当Transaction Manager确认所有参与者都ready后,向所有参与者发送commit命令。
在这里插入图片描述
XA 协议它依赖的是数据库层面来保障事务的一致性,也即是说 XA 的各个分支事务是在数据库层面上驱动的,由于 XA 的各个分支事务需要有 XA 的驱动程序,一方面会导致数据库与 XA 驱动耦合,另一方面它会导致各个分支的事务资源锁定周期长(直到两阶段提交完成才释放资源)。

基于这些问题,Seata另辟蹊径,在应用层做手脚,Seata的RM模块内部做了对数据库操作的代理层,如下:
在这里插入图片描述

Seata分支事务是如何提交和回滚的呢?

第一阶段
分支事务利用 RM 模块中对 JDBC 数据源代理,加入了若干流程,对业务 SQL 进行解释,把业务数据在更新前后的数据镜像组织成回滚日志,并生成 undo log 日志,对全局事务锁的检查以及分支事务的注册等,利用本地事务 ACID 特性,将业务 SQL 和 undo log 写入同一个事物中一同提交到数据库中,保证业务 SQL 必定存在相应的回滚日志,最后对分支事务状态向 TC 进行上报。
在这里插入图片描述
第二阶段

  • TM决议全局提交:

当 TM 决议提交时,就不需要同步协调处理了,TC 会异步调度各个 RM 分支事务删除对应的 undo log 日志即可,这个步骤非常快速地可以完成。这个机制对于性能提升非常关键,我们知道正常的业务运行过程中,事务执行的成功率是非常高的,因此可以直接在本地事务中提交,这步对于提升性能非常显著。
在这里插入图片描述

  • TM决议全局回滚:

当 TM 决议回滚时,RM 收到 TC 发送的回滚请求,RM 通过 XID 找到对应的 undo log 回滚日志,然后利用本地事务 ACID 特性,执行回滚日志完成回滚操作并删除 undo log 日志,最后向 TC 进行回滚结果上报。

在这里插入图片描述
业务对以上所有的流程都无感知,业务完全不关心全局事务的具体提交和回滚,而且最重要的一点是 Seata 将两段式提交的同步协调分解到各个分支事务中了,分支事务与普通的本地事务无任何差异,这意味着我们使用 Seata 后,分布式事务就像使用本地事务一样,完全将数据库层的事务协调机制交给了中间件层 Seata 去做了,这样虽然事务协调搬到应用层了,但是依然可以做到对业务的零侵入,从而剥离了分布式事务方案对数据库在协议支持上的要求,且 Seata 在分支事务完成之后直接释放资源,极大减少了分支事务对资源的锁定时间,完美避免了 XA 协议需要同步协调导致资源锁定时间过长的问题。

为了加深理解,我们用一个示例来更具体的说明AT模式下分支事务的工作过程:
业务表:product

Field Type Key
id bigint(20) PRI
name varchar(100)
since varchar(100)

分支事务的业务逻辑:

update product set name = 'GTS' where name = 'TXC';

一阶段

过程:

1.解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = ‘TXC’)等相关的信息。
2.查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。

select id, name, since from product where name = 'TXC';

得到前镜像:

id name since
1 TXC 2014

3.执行业务 SQL:更新这条记录的 name 为 ‘GTS’。
4.查询后镜像:根据前镜像的结果,通过 主键 定位数据。

select id, name, since from product where id = 1`;

得到后镜像:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值