前言

Seata是阿里开源的分布式事务解决方案,本文将详细介绍 Seata 的事务模式、原理以及使用。了解之前需清楚什么是分布式事务


一、什么是 Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了XA、AT、TCC 和 SAGA 事务模式,为用户打造一站式的分布式解决方案。

Seata 的几种角色:

角色 说明
TC Transaction Coordinator,事务协调者,用来协调全局和各个分支事务(不同服务)的状态, 驱动它们的回滚或提交。
TM Transaction Manager,事务管理者,业务层中用来开启/提交/回滚一个整体事务(在调用服务的方法中用注解开启事务)。
RM Resource Manager,资源管理者,管理分支事务,与 TC 进行协调注册分支事务,并且汇报分支事务的状态,驱动分支事务的提交或回滚。

简单流程图:

二、事务模式

1. XA 模式

Seata 的 XA 模式大体与 2PC 事务相似。

1.1 流程介绍

第一阶段:

  1. RM 注册分支事务到 TC;
  2. RM 执行分支业务的 SQL 但不提交
  3. RM 报告执行状态到 TC;

第二阶段:

  1. TC 检测检测各分支事务状态,判断整体事务提交或回滚;
  2. RM 接受 TC 的指令,进行统一的提交或回滚操作。

1.2 XA 优缺点

优点:

  1. 事务强一致性,满足 ACID 原则;
  2. 实现简单,无代码入侵。

缺点:

  1. 一阶段锁定资源,二阶段结束才释放,性能较差;
  2. 依赖关系型数据库实现事务;

2. AT 模式

Auto Transaction,基于 XA 演进而来,需要数据库支持,如果是 MySQL,则需要5.6以上版本才支持XA协议。

是一种无侵入的分布式事务解决方案,该模式下,用户只需关注自己的业务 SQL,Seata 框架会在第一阶段拦截并解析 SQL,生成 undo log,并自动生成事务二阶段的提交和回滚操作。

AT 模式下,是利用快照实现数据回滚,属于弱一致。

2.1 流程介绍

第一阶段:

  1. RM 注册分支事务到 TC;
  2. 记录 undo log(数据快照);
  3. RM 执行分支业务的 SQL 并提交
  4. RM 报告执行状态到 TC;

第二阶段:

  1. TC 检测检测各分支事务状态,判断整体事务提交或回滚;
  2. RM 接受 TC 的指令,进行统一的提交或回滚操作。
    1. 提交时,异步删除相应分支的 undo log;
    2. 回滚时,根据 undo log 生成补偿回滚的 SQL,执行分支回滚并返回结果给 TC;

例如,一个分支业务需要对account余额表中的money进行扣减 10 元,则需要进行如下流程:

2.2 脏写问题

如下图所示,并发事务之间,可能会产生脏写导致数据修改被覆盖。

如何解决脏写,Seata 通过全局锁来管理事务,持有全局锁的事务才有执行 SQL 的权利,这里全局锁只针对交由 Seata 管理的事务

如下图,简单流程大致如下:

  1. 一阶段本地事务提交前,需要确保先拿到全局锁 ;
  2. 拿不到全局锁 ,不能提交本地事务。
  3. 拿不到全局锁会重试,次数有限,超出限制将放弃,并回滚本地事务,释放本地锁。

2.3 数据快照

那么非 Seata 事务于 Seata 事务并发修改数据时如何处理?

RM 在第一阶段将分支事务注册到 TC 时,会在 undo log 保存两个数据快照,分别是:

  • before-image:数据修改前的快照
  • after-image:数据修改后的快照

当发生异常时,before-image用来做数据回滚,after-image来判断修改后数据于当前数据是否相同,相同则通过before-image做数据回滚,不同则说明被其他非 Seata 事务修改过,记录异常,人工介入。

具体流程见下图。

2.4 脏读问题

与脏写类似,是指在全局事务未提交前,被其它业务读到已提交的分支事务的数据,本质上 Seata 默认的全局事务是读未提交

那么怎么避免脏读现象呢?

  1. 业务查询时要使用@GlobalTransactional@GlobalLock来修饰查询方法的调用;
  2. 查询语句须使用select for update语句。

这样在执行 SQL 前会检查全局锁是否存在,只有当全局锁完成之后,才能继续执行 SQL,这样就防止了脏读。

不过,AT 事务模式下读已提交的成本很高,对于非必要场景还是要尽量避免使用。

传统的读已提交不需要本地锁,但这里却需要select for update语句,查询多出了加锁和竞争的开销,另外还要持锁调用 TC 的lockQuery接口以判断全局锁情况。

2.5 AT 优缺点

优点:

  1. 一阶段直接完成事务提交,释放数据库资源,性能比较好;
  2. 利用全局锁实现读写隔离;
  3. 没有代码入侵,框架自动完成回滚或提交。

缺点:

  1. 两阶段之间属于软状态,属于最终一直;
  2. 数据快照会影响性能,但比 XA 模式要好很多;

3. TCC 模式

关于什么是 TCC 模式及原理,详情见什么是分布式事务

TCC 与 AT 模式很相似,每阶段都是独立事务,不同的是 TCC 通过人工编码来实现数据恢复。

3.1 流程介绍

TCC 每个阶段是做什么的:

  1. Try:资源的检测和预留;
  2. Confirm:完成资源操作业务,要求Try成功,Confirm一定能成功;
  3. Cancel:预留资源释放,可以理解为Try的反向操作。

TCC 不存在资源阻塞的问题,因为每个方法都直接进行事务的提交,一旦出现异常通过则Cancel来进行回滚补偿,这也就是常说的补偿性事务

举例,一个扣减用户愈合的业务,假设账户 A 原来的余额是 100,需要扣减 30 元。

空回滚和业务悬挂

什么是空回滚?

分支事务Try操作阻塞时,可能导致全局事务超时触发Cancel操作。在Try未执行时先执行了Cancel,这时的Cancel理论上不应该回滚,这时就需要空回滚

什么是业务悬挂?

对于已经空回滚的业务,这时如果线程不再阻塞,继续执行Try,但不可能ConfirmCancel,这就是业务悬挂,需要避免空回滚后的Try操作。

如何解决空回滚和业务悬挂?

回滚时需要在执行Cancel操作时,判断有没有执行Try操作。相应的,在执行Try时判断有没有该事务是否回滚过。

这里,我们假设需要在冻结金额的时候进行事务操作。为了实现空回滚,防止业务悬挂,以及幂等性要求。我们必须在数据库记录冻结金额的同时,记录当前事务 ID 和执行状态,冻结金额表如下设计:

CREATE TABLE 'account_freeze_tbl'(
'xid' varchar (128) NOT NULL,
'user_id' varchar(255) DEFAULT NULL COMMENT '用户id',
'freeze_money' int(11) unsigned DEFAULT '0' COMMENT '冻结金额',
'state' int(1) DEFAULT NULL COMMENT '事务状态, O:try, 1:confirm, 2:cancel',
PRIMARY KEY ('xid') USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

表字段设计完成后,执行如下的业务逻辑即可避免空回滚和业务悬挂。

3.2 TCC 优缺点

优点:

  1. 一阶段直接完成事务提交,释放数据库资源,性能比较好;
  2. 相比 AT,无需生成快照和使用全局锁,性能最好;
  3. 不依赖数据库事务,依赖补偿操作,可用于非事务型数据库。

缺点:

  1. 代码入侵,每个阶段都需要编写对应的业务代码;
  2. 软状态,属于最终一致;
  3. 需要考虑ConfirmCancel的失败情况,做好幂等处理。

4. Saga 模式

关于什么是 Saga 模式及原理,详情见什么是分布式事务

Saga 模式是 Seata 提供的长事务解决方案。也分为两个阶段:

  • 一阶段: 直接提交本地事务
  • 二阶段: 成功则什么都不做;失败则通过编写补偿业务来回滚

优点:

  1. 事务参与者可以基于事件驱动实现异步调用,吞吐高;
  2. 一阶段直接提交本地事务,无锁,性能好;
  3. 代码入侵较 TCC 低,实现简单。

缺点:

  1. 软状态持续时间不确定,时效性差;
  2. 没有锁和事务隔离,可能会有脏写。

三、代码实现

具体代码使用,可参考 Seata 官方文档

这里需要注意每个模式需要的准备工作不同,如AT模式下就需要准备如下几点:

  1. lock_table 导入 Seata 数据库,就是 TC 服务关联的数据库;
  2. undo_log 导入业务相关的数据库;
  3. 修改事务模式。

四、对比总结

对比维度 XA AT TCC Saga
数据一致性 强一致性 弱一致性 最终一致性 最终一致性
隔离性 完全隔离 基于全局锁 基于资源预留 无隔离
代码入侵
性能 较低
依赖本地事务 依赖 依赖 不依赖 不依赖
场景 一致性,隔离性要求高的业务场景。 继续关系型数据库的大多分布式事务的场景均适合。 对性能要求高,且有非关系型数据库参与的事务。 业务流程较长,数据时效性要求较低的场景。

参考:

[1] B站黑马. Seata从入门到进阶.

Seata原理浅析的更多相关文章

  1. HTTP长连接和短连接原理浅析

    原文出自:HTTP长连接和短连接原理浅析

  2. Javascript自执行匿名函数(function() { })()的原理浅析

    匿名函数就是没有函数名的函数.这篇文章主要介绍了Javascript自执行匿名函数(function() { })()的原理浅析的相关资料,需要的朋友可以参考下 函数是JavaScript中最灵活的一 ...

  3. [转帖]Git数据存储的原理浅析

    Git数据存储的原理浅析 https://segmentfault.com/a/1190000016320008   写作背景 进来在闲暇的时间里在看一些关系P2P网络的拓扑发现的内容,重点关注了Ma ...

  4. Android-Binder原理浅析

    Android-Binder原理浅析 学习自 <Android开发艺术探索> 写在前头 在上一章,我们简单的了解了一下Binder并且通过 AIDL完成了一个IPC的DEMO.你可能会好奇 ...

  5. Dubbo学习(一) Dubbo原理浅析

    一.初入Dubbo Dubbo学习文档: http://dubbo.incubator.apache.org/books/dubbo-user-book/ http://dubbo.incubator ...

  6. 沉淀,再出发:docker的原理浅析

    沉淀,再出发:docker的原理浅析 一.前言 在我们使用docker的时候,很多情况下我们对于一些概念的理解是停留在名称和用法的地步,如果更进一步理解了docker的本质,我们的技术一定会有质的进步 ...

  7. 阻塞和唤醒线程——LockSupport功能简介及原理浅析

    目录 1.LockSupport功能简介 1.1 使用wait,notify阻塞唤醒线程 1.2 使用LockSupport阻塞唤醒线程 2. LockSupport的其他特色 2.1 可以先唤醒线程 ...

  8. 【Spark Core】TaskScheduler源代码与任务提交原理浅析2

    引言 上一节<TaskScheduler源代码与任务提交原理浅析1>介绍了TaskScheduler的创建过程,在这一节中,我将承接<Stage生成和Stage源代码浅析>中的 ...

  9. vue的双向绑定原理浅析与简单实现

    很久之前看过vue的一些原理,对其中的双向绑定原理也有一定程度上的了解,只是最近才在项目上使用vue,这才决定好好了解下vue的实现原理,因此这里对vue的双向绑定原理进行浅析,并做一个简单的实现. ...

  10. 消息队列——ActiveMQ使用及原理浅析

    文章目录 引言 正文 一.ActiveMQ是如何产生的? 产生背景 JMS规范 基本概念 JMS体系结构 二.如何使用? 基本功能 消息传递 P2P pub/sub 持久订阅 消息传递的可靠性 事务型 ...

随机推荐

  1. 实用 Linux 命令 Windos 命令 实例演示 持续更新中

    实用 Linux 命令 Windos 命令 实例演示 持续更新中 目录 实用 Linux 命令 Windos 命令 实例演示 持续更新中 Linux 命令 [Command [options] [lo ...

  2. AtCoder Grand Contest 037(without F)

    AGC037 A - Dividing a String 洛谷传送门 AGC037A 分析 考虑每一段长度只可能是一或二,设 \(dp[i]\) 表示以 \(i\) 为结尾的前缀最多可以分成多少段. ...

  3. SQL语言分为哪几类

    SQL 语言分为哪几类 介绍 SQL 语言分为三类,包括 DDL.DML 和 DCL. DDL DDL(Data Definition Language,数据定义语言) 用来创建或者删除存储数据用的数 ...

  4. 一个简单的开源消息中间件 FolkMQ v1.4.2 发布

    功能简表 角色 功能 生产者(客户端) 发布消息.定时消息(或叫延时).顺序消息.可过期消息.事务消息.支持 Qos0.Qos1 消费者(客户端) 订阅.取消订阅.消费-ACK(自动.手动) 服务端 ...

  5. 试用阿里云GPU服务器进行深度学习模型训练

    试用阿里云GPU服务器进行深度学习模型训练 最近在用PyTorch时发现在本地训练模型速度一言难尽,然后发现阿里云可以白嫖gpu服务器,只要没有申请过PAI-DSW资源的新老用户都可以申请5000CU ...

  6. eclipse 配置tomcat(更新了比较详细的版本)

    eclipse 配置tomcat 打开eclipse,在上栏找到Window,点开找到preferences,点击,就有一个弹框出现 然后找到server,点开找到runtime environmen ...

  7. 第五課-Channel Study TCP Listener & Web Service Listener

    示例描述: 我们将研究如何获取相当常见的HL7 v2消息并将其映射到自定义Web Service接口服务.在许多实际情况下,当我们要连接到HIE,EMPI,数据仓库或数据存储库时,必须这样做.此用例说 ...

  8. 力扣1113(MySQL)-报告的记录(简单)

    题目: 动作表:Actions 此表没有主键,所以可能会有重复的行. action 字段是 ENUM 类型的,包含:('view', 'like', 'reaction', 'comment', 'r ...

  9. 通过部署流行Web框架掌握Serverless技术

    简介: 通过学习部署流行Web框架,如SpringBoot,Express,Web IDE,让你掌握Serverless函数计算架构和技术,领略弹性并发,高可用的好处.大家好,我是霍大侠,欢迎来到我的 ...

  10. IT人的年夜饭,也太香了吧

    ​简介: 平时的IT人,奋战在修复bug前线,起早与贪黑齐飞,调休共假期待定.到了新春佳节,对于IT人来说,没有什么是比一顿年夜饭更让人熨贴肺腑的了.为了让废寝忘食编程序.闻机起早保运维的IT人过一个 ...