Seata 的4种事务模式(XA、AT、TCC、SAGA)

目录

前言

Seata架构

事务模式

XA

AT

TCC

区别


前言

在分布式系统中,实现一个功能可能需要由几个不同的服务来共同实现。这就会带来一个问题,不同的服务之间无法做到使用同一个事务,这就无法保证数据的一致性了。在一些对数据一致性要求不要的业务场景中,可以基于本地消息表来实现分布式事务,只需要保证最终一致性就行了。

基于本地消息表实现分布式事务(最终一致性)_本地消息表处理分布式事务-CSDN博客文章浏览阅读1k次,点赞33次,收藏11次。传统单体架构下,所有的功能模块都在一个应用下,所有的代码和业务逻辑都在同一个应用下实现,所以保证数据的一致性就很简单,保证相关操作都在同一个本地事务下就可以了。但是在微服务架构下,将一个应用拆分成了多个独立的服务,每个服务都能有自己的数据库,服务间通信都是通过远程调用实现,实现一个功能可能需要由几个不同的服务来共同实现。这就会带来一个问题,不同的服务之间无法做到使用同一个事务,这就无法保证数据的一致性了。_本地消息表处理分布式事务https://blog.csdn.net/typeracer/article/details/140998899但是也存在一些需要强一致性的业务场景,实际工作中开发过一个事件设计器,设计器中支持各种业务节点,对节点进行编排从而来自定义业务逻辑。不同的节点的实现需要调用不同的服务来实现,故存在分布式事务的问题。对各个节点的服务调用,需要保证所有事务的原子性,要么一起提交,要么一起回滚,所以最后通过引入Seata来解决

在学习 Seata 时,对各种事务模式都做了了解,对比后才能为系统选择最合适的事务模式。在事件设计器中,由于业务对实时性要求不高,所以直接使用XA模式,集成最简单,没有代码侵入。

Seata架构

  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

分布式事务基本流程

事务模式

  1. XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
  2. AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
  3. TCC模式:最终一致的分阶段事务模式,有业务侵入
  4. SAGA模式:长事务模式,有业务侵入

XA

plantuml

@startuml
'https://plantuml.com/sequence-diagram

autonumber 1.1

participant TM
participant RM
participant TC

TM -> TC: 开启全局事务
TM <-- TC: XID
TM -> RM: 远程调用 XID
RM -> TC: 注册分支事务
RM -> RM: 执行业务sql
RM -> TC: 报告分支事务状态

autonumber inc A

TM -> TC: 提交/回滚全局事务
TC -> TC: 检查分支事务状态
RM <- TC: 提交/回滚

@enduml

优点

  • 事务的强一致性,满足ACID原则。
  • 常用数据库都支持,实现简单,并且没有代码侵入

缺点

  • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
  • 依赖关系型数据库实现事务

AT

AT模式是Seata的默认事务模式

在使用前,需要在对应的业务库中创建一张 undo_log 表,用来保存快照

建表语句(MySQL)

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

流程图

plantuml

@startuml
'https://plantuml.com/sequence-diagram

autonumber 1.1

database undo_log
participant TM
participant RM
participant TC

TM -> TC: 开启全局事务
TM <-- TC: XID
TM -> RM: 远程调用 XID
RM -> TC: 注册分支事务
RM -> RM: 执行业务sql并提交
undo_log <- RM: 记录更新前后快照
RM -> TC: 报告分支事务状态

autonumber inc A

TM -> TC: 提交/回滚全局事务
TC -> TC: 检查分支事务状态
RM <- TC: 提交/回滚
undo_log <- RM: 删除log/回复log数据

@enduml

优点

  • 一阶段完成直接提交事务,释放数据库资源,性能比较好
  • 没有代码侵入,框架自动完成回滚和提交

缺点

  • 软状态,事务是最终一致
  • 框架的快照功能会影响性能,但比XA模式要好很多

TCC

 TCC模式将事务拆成了三个接口实现(try,commit,cancel),同时也带来了以下三个问题

  1. 幂等:在 commit/cancel 阶段,因为 TC 没有收到分支事务的响应,需要进行重试,这就要分支事务支持幂等
  2. 空回滚:在 try 阶段发生了故障,try 阶段在不考虑重试的情况下,全局事务必须要走向结束状态,这样就需要执行一次 cancel 操作
  3. 悬挂:因为网络问题,RM 开始没有收到 try 指令,但是执行了 cancel 后 RM 又收到了 try 指令并且预留资源成功,这时全局事务已经结束,最终导致预留的资源不能释放

在1.5.1以前,这些问题需要自己在代码中解决,而1.5.1版本以后(包含1.5.1),Seata就自己解决这些问题了

需要在对应的业务库中创建一张 tcc_fence_log 表

建表语句(MySQL)

CREATE TABLE IF NOT EXISTS `tcc_fence_log`
(
    `xid`           VARCHAR(128)  NOT NULL COMMENT 'global id',
    `branch_id`     BIGINT        NOT NULL COMMENT 'branch id',
    `action_name`   VARCHAR(64)   NOT NULL COMMENT 'action name',
    `status`        TINYINT       NOT NULL COMMENT 'status(tried:1;committed:2;rollbacked:3;suspended:4)',
    `gmt_create`    DATETIME(3)   NOT NULL COMMENT 'create time',
    `gmt_modified`  DATETIME(3)   NOT NULL COMMENT 'update time',
    PRIMARY KEY (`xid`, `branch_id`),
    KEY `idx_gmt_modified` (`gmt_modified`),
    KEY `idx_status` (`status`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

流程图

plantuml

@startuml
'https://plantuml.com/sequence-diagram

autonumber 1.1

database tcc_fence_log
participant TM
participant RM
participant TC

TM -> TC: 开启全局事务
TM <-- TC: XID
TM -> RM: 远程调用 XID
RM -> TC: 注册分支事务
RM -> RM: 锁定资源(try)
tcc_fence_log <- RM: 插入防空回滚记录
note left
    插入一条记录
    status值为STATUS_TRIED
    在 Rollback 阶段判断记录是否存在
    如果不存在,则不执行回滚操作
end note
RM -> TC: 报告分支事务状态

autonumber inc A

TM -> TC: 提交/回滚全局事务
TC -> TC: 检查分支事务状态
RM <- TC: 提交/回滚

tcc_fence_log <- RM: 幂等判断
note left
    判断 tcc_fence_log 表中是否已经有记录
    如果有记录,则判断事务执行状态是否为 STATUS_COMMITTED
    是的话就不会再次提交,保证了幂等
    如果 tcc_fence_log 表中没有记录
    则插入一条记录,供后面重试时判断。
end note

tcc_fence_log <- RM: 插入防悬挂记录
note left
    执行 cancel 方法时
    判断 tcc_fence_log 是否存在当前 xid 的记录
    如果没有则向 tcc_fence_log 表插入一条记录
    状态是 STATUS_SUSPENDED,并且不再执行回滚操作
    后面执行 try 阶段方法时首先会向 tcc_fence_log 表插入一条当前 xid 的记
    这样就造成了主键冲突
end note

RM <- RM: 提交(commit)/回滚(cancel)

@enduml

优点

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库

缺点

  • 有代码侵入,需要人为编写try、Confirm和Cancel接口
  • 软状态,事务是最终一致

区别

XAATTCCSAGA
一致性
强一致
弱一致
弱一致
最终一致
隔离性
完全隔离
基于全局锁隔离
基于资源预留隔离
无隔离
代码侵入
有,要编写三个接口
有,要编写状态机和补偿业务 
性能
非常好
非常好
场景
对一致性、隔离性有高要求的业务
基于关系型数据库的大多数分布式事务场景
对性能要求较高的事务
有非关系型数据库要参与的事务
业务流程长、业务流程多 
参与者包含其它公司或遗留系统服务,无法提供 TCC 模式要求的三个接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值