前言

分布式微服务中事务问题,是一直困扰着大家的。之前老顾已经介绍过如何利用rocketmq的事务消息解决事务问题,今天老顾再来介绍另一个方案;提供小伙伴们另一个选择。

解决方案有哪些?

分布式事务方案大致分为对业务无侵入型和有侵入型。

无侵入型的方案有基于数据库的XA协议的两阶段提交,它的优点对业务无侵入,缺点也很明显;数据库必须支持XA协议,且支持XA协议对性能的影响很大,因为它会造成事务资源长时间得不到释放。数据库的吞吐量极低。

为了解决这个问题,就出来了很多业务层面的实现二阶段的提交方案,如:很出名的 TCC 方案,基于 TCC 也有很多成熟的框架,如 ByteTCC、tcc-transaction。

另一种就是最终一致性的方案,如:rocketmq事务消息。

但上面的TCC方案、或者最终一致性方案都会涉及到业务代码的改造,对业务有侵入。

下面我们来介绍一下今天的主角。

Seata

Seata的分布式事务解决方案是业务层面的解决方案,业务层上无需关心分布式事务机制的约束,它将给我们的微服务架构带来质的提升,只依赖于单台数据库的事务能力。

Seata 的设计思路是将一个分布式事务可以理解成一个全局事务,下面挂了若干个分支事务,而一个分支事务是一个满足 ACID 的本地事务,因此我们可以操作分布式事务像操作本地事务一样。

Seata 内部定义了 3个模块来处理全局事务和分支事务的关系和处理过程,这三个组件分别是:

1、Transaction Coordinator (TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。

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

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

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

下面是一个分布式事务在Seata中的执行流程:

1)TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。

2)XID 在微服务调用链路的上下文中传播。

3)RM 向 TC 注册分支事务,接着执行这个分支事务并提交(重点:RM在第一阶段就已经执行了本地事务的提交/回滚),最后将执行结果汇报给TC。

4)TM 根据 TC 中所有的分支事务的执行情况,发起全局提交或回滚决议。

5)TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

分支事务为什么能直接提交?

Seata能够在第一阶段直接提交事务,是因为Seata框架为每一个RM维护了一张UNDO_LOG表(这张表需要客户端自行创建),其中保存了每一次本地事务的回滚数据。因此,二阶段的回滚并不依赖于本地数据库事务的回滚,而是RM直接读取这张UNDO_LOG表,并将数据库中的数据更新为UNDO_LOG中存储的历史数据。

如果第二阶段是提交命令,那么RM事实上并不会对数据进行提交(因为一阶段已经提交了),而实发起一个异步请求删除UNDO_LOG中关于本事务的记录。

原理就是先保存之前的老数据,一旦出现异常,就是把老数据再更新回去。

Seata执行流程

下面是一个Seata中一个分布式事务执行的详细过程:

1)首先TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。

2)XID 在微服务调用链路的上下文中传播

3)RM 开始执行这个分支事务,RM首先解析这条SQL语句,生成对应的UNDO_LOG记录。下面是一条UNDO_LOG中的记录:

{    "branchId": 641789253,    "undoItems": [{        "afterImage": {            "rows": [{                "fields": [{                    "name": "id",                    "type": 4,                    "value": 1                }, {                    "name": "name",                    "type": 12,                    "value": "GTS"                }, {                    "name": "since",                    "type": 12,                    "value": "2014"                }]            }],            "tableName": "product"        },        "beforeImage": {            "rows": [{                "fields": [{                    "name": "id",                    "type": 4,                    "value": 1                }, {                    "name": "name",                    "type": 12,                    "value": "TXC"                }, {                    "name": "since",                    "type": 12,                    "value": "2014"                }]            }],            "tableName": "product"        },        "sqlType": "UPDATE"    }],    "xid": "xid:xxx"}

可以看到,UNDO_LOG表中记录了分支ID,全局事务ID,以及事务执行的redo和undo数据以供二阶段恢复。

4)RM在同一个本地事务中执行业务SQL和UNDO_LOG数据的插入。在提交这个本地事务前,RM会向TC申请关于这条记录的全局锁。如果申请不到,则说明有其他事务也在对这条记录进行操作,因此它会在一段时间内重试,重试失败则回滚本地事务,并向TC汇报本地事务执行失败。如下图所示:

5)RM在事务提交前,申请到了相关记录的全局锁,因此直接提交本地事务,并向TC汇报本地事务执行成功。此时全局锁并没有释放,全局锁的释放取决于二阶段是提交命令还是回滚命令。

6)TC根据所有的分支事务执行结果,向RM下发提交或回滚命令。

7)RM如果收到TC的提交命令,首先立即释放相关记录的全局锁,然后把提交请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。异步队列中的提交请求真正执行时,只是删除相应UNDO LOG 记录而已。

8)RM如果收到TC的回滚命令,则会开启一个本地事务,通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。将 UNDO LOG 中的后镜与当前数据进行比较

如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理。

否则,根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句并执行,然后提交本地事务达到回滚的目的。

最后释放相关记录的全局锁。

方案补充

上面的方案是Seata的默认模式,称为AT模式,它是类似于 XA 方案的两段式提交方案,并且是对业务无侵入,但是这种机制依然是需要依赖数据库本地事务的 ACID 特性

小伙伴们有没有发现,整个流程的基础必须是支持 ACID 特性的关系型数据库,那么问题就来了,非关系型或者不支持 ACID 的数据库就无法使用 Seata 了?

Seata 现阶段为我们准备了另外一种模式,叫 MT 模式,它是一种对业务有入侵的方案,提交回滚等操作需要我们自行定义,业务逻辑需要被分解为 Prepare/Commit/Rollback 3 部分,形成一个 MT 分支,加入全局事务,其本质就是TCC方案。

不过MT模式,它不是 Seata “主打”的模式,它的存在仅仅作为补充的方案,从以上官方的发展远景就可以看出来,Seata 的目标是始终是对业务无入侵的方案。

总结

今天老顾介绍seata整体原理,以及执行流程,希望小伙伴们能够在原理本质上去先了解一下seata,后面的文章老顾会介绍一下项目实战,谢谢!!!

是兄弟,就来“kan”

seata分布式事务原理_又见分布式事务之Seata相关推荐

  1. seata xid是什么_微服务分布式事务解决方案-springboot整合分布式seata1.3.0

    概述 Seat是蚂蚁金服和阿里巴巴联合推出的一个开源的分布式事务框架,在阿里云商用的叫做GTS. 项目地址:https://github.com/longxiaonan/springcloud-dem ...

  2. 同事操作两个数据源保持事务一致_微服务分布式事务4种解决方案实战

    分布式事务 分布式事务是指事务的参与者,支持事务的服务器,资源服务器分别位于分布式系统的不同节点之上,通常一个分布式 事物中会涉及到对多个数据源或业务系统的操作. 典型的分布式事务场景:跨银行转操作就 ...

  3. springcloud分布式事务解决方案_搞懂分布式技术18:分布式事务常用解决方案

    本文转载自 http://linkedkeeper.com 本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 http ...

  4. spring手动控制事务开启_“上帝视角”图解Spring事务的传播机制原理

    转载:https://mp.weixin.qq.com/s/odP1DKgRtXsCcAKxwGahug 数据库事务的"抓手" 数据库的事务功能已经由数据库自身实现,它留给用户的就 ...

  5. 不同类的方法 事务问题_深入理解 Spring 事务原理

    Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...

  6. mysql数据库执行事务日志_第十章 MySQL事务及其日志介绍

    一.数据库升级 #1.提出方案 1)升级的方法 2)升级的步骤 3)升级的时间 4)升级步骤可能会出现的问题 5)出现的问题怎么解决,解决时间 6)升级后出现的问题 #2.搭建新的数据库 #3.备份就 ...

  7. mysql读会产生事务吗_来谈谈MySQL事务及事务引发的问题

    说起事务,肯定能够想到这样一句话,这个事情要么不做,要么做完:或者是好兄弟不求同年同月同日生,但求同年同月同日死.有点过分,但是是这个理儿. 四大特性 我们都知道,提到事务,就不能不提事务的四大特性, ...

  8. mysql如何查看事务日记_详解 Mysql 事务和Mysql 日志

    事务特性 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节. 2.一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破 ...

  9. ceph存储原理_热门的分布式存储系统ceph入门介绍

    一.什么是ceph ceph是当前最热门的分布式存储系统之一,是软件定义存储(SDS,SoftwareDefinedStorage)解决方案中的典范.其具备良好的可靠性.可扩展性,应用范围包括块存储( ...

最新文章

  1. DL练习1:基于boston_house_prices的BP神经网络
  2. 字节跳动学习笔记:java多线程实现原理
  3. 产品经验谈:设计思维 统计思维
  4. 允许同站跨域Nginx配置方案
  5. Probe:Android线上OOM问题定位组件
  6. 【linux】make出现遗漏分隔符
  7. C# XML文件读取
  8. 数据层处理和性能优化
  9. 剑指offer 面试26题
  10. libiconv_百度百科
  11. Win32屏幕保护程序
  12. Unity Hex与Color之间进行颜色转换
  13. Element 之loading颜色修改
  14. JavaScript学习笔记01——简介(李炎恢JavaScript教程)
  15. python作业——SVM预测交通流量
  16. drop、delete、truncate比较
  17. Caffe Scale层
  18. Javascript轻应用命令行工具
  19. 2021下半年教资综合素质——主观题
  20. wordpress模板_如何在WordPress中添加漂亮的电子邮件模板

热门文章

  1. 三维坐标 偏转_三维坐标变换原理-平移, 旋转, 缩放
  2. springboot中mongodb自定义类型转换器
  3. java mcv_Spring和SpringMCV配置
  4. java扫描一个端口状态_java扫描端口,如何判断端口是用来做什么的(提供什么服务的)?...
  5. 控制只读_用Python控制硬件44-四位半万用表UT61E
  6. html做app的切换效果,Vue-router结合transition实现app动画切换效果实例分享
  7. java 类型转换原理_9.java数据类型的转换
  8. Linux系统文件夹权限475,linux系统中文件的特殊权限
  9. 2评分标准多少分_突发!财政部刚刚通知!2020年中级考试题目分值及评分标准大变!...
  10. mysql 修改字段长度_面试官:InnoDB记录存储结构都不知道,你敢说你懂MySQL?