分布式事务框架seata

seata

  • 前两篇文中总结了一下分布式事务已经现阶段常用的解决方案,现在来讨论一下现有的分布式事务框架seata,点击此处是seata的官网seata致力于微服务框架下提供高性能和简单易用的分布式事务服务。它提供了AT,TCC,Saga ,XA这几种事务模型,为开发者提供了一站式的分布式事务解决方案。其中TCC和XA我们上一篇文中已经有说明,接下来我们讨论一下Seata中AT和Saga这两种事务模型是怎么样的。
AT模式
  • AT模式是Seata最主推的分布式事务解决方案,他是基于XA演进过来的一种分布式事务模式,随意他同样分为三大模块,分别是TM(Transaction Manager),RM(Resource Manager)和TC(Transaction Server),其中TM和RM作为Seata客户端与业务系统集成,TC作为Seata的服务器端独立部署,TM表示事务管理器,他负责向TC注册一个全局事务,并生成一个全局事务唯一XID。在AT模式下,每个数据库资源被称作一个RM,在业务层通过JDBC标准接口范问RM的时候,Seata会对所有请求进行拦截。每一个本地事务进行提交时候,RM都会想TC事务协调器注册一个分支事务。Seata的AT模式如下图说明:

在这里插入图片描述

  • 具体流程如下:
    • TM向TC注册一个全局的事务,并生成全局XID
    • 期间整个业务流程内每个RM想TC注册分支事务,并将其纳入改XID对应的全局事务范围
    • RM想TC汇报资源的准备状态
    • TC汇总所有事务参与者的状态,决定分布式事务是全部回滚还是全部提交
    • TC通知所有RM提交/回滚事务
  • AT模式和XA模式一样,都是一个两阶段提交的事务模型,不过和XA相比,做了一些优化,这个官网着重讲解了一下AT的原理,之后开一节着重看下一AT模式的实现原理。
Saga模式
  • Saga模式是SEATA提供的长事务解决方案,这种理论模型是由普林斯顿大学的Hector Garcia-Molina 和 Kenneth Salem 提出的,主要描述的是在没有两阶段提交的前提下如何解决分布式事务问题。核心思想是:将一个业务流程中长事务拆分为多个本地的短事务,业务流程中每个参与者都提交正式的提交给本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿签名已经成功的参与者。

  • 如下图说明Saga由一系列sub-transaction Ti 组成,每个Ti 都有对应的补偿动作Ci ,补偿动作用于撤回Ti 造成的数据变化。和TCC相比,少了Try这一步,每个操作都是真实的数据库操作。

在这里插入图片描述

  • 按照Saga的工作模式,有两种执行方式:

    • T1, T2, T3, …,Ti: 这种方式表示所有事务都正常执行。
    • T1, T2, …, Tj,Cj,…,C2,C1: 这种情况是表示执行到Tj的时候,Tj 事务出现异常,通过补偿操作撤销之前所有成功的sub-transaction
  • 另外Saga还提供了一下两种补偿恢复方式:

    • 向后恢复,也就是上面提到的第二中工作模式,如果任何一个子事务执行失败,则吧之前执行的结果逐个撤销
    • 向前恢复,也就是不进行补偿,而是对失败的事务进行重试,这种方式比较适合事务必须要执行成功的场景。
Saga的优势
  • 和XA和TCC比较,他的优势包括:一阶段直接提交本地事务;没有锁,没有锁,没有锁!!!,性能较高;在事件驱动的模式下,段事务可以异步执行;补偿机制的实现比较简单。
  • 缺点是Saga并不提供原子性和隔离性支持,隔离性的影响是比较大的,比如用户购买一个情感课程后会赠送一段时间会员,或者赠送打折卷,如果用户在回滚之前将优惠券用掉了,会在在回滚之前使用了会员的一些特殊服务,那么事务出现异常回滚的时候就无法收回这部分,会出现业务上的问题。
Saga的实现方式
  • 就像刚才的案例,用户购买情感课程,这个业务场景下会涉及到订单创建,课程库存的修改,微信支付,会员赠送,整个流程如下:
    在这里插入图片描述

  • 在以上支付下单的流程上一个典型的长事务,根据Saga模式的定义,先将长事务拆分成对个本地端事务,每个服务的本地事务按照执行顺序逐一提交,一旦其中一个服务的事务出现异常,则采用补偿的方式逐一撤回。这一过程的实现会设计Saga的协调模式,他有两种常用的协调模型。

    • 事件/编排式:把Saga的决策和执行顺序逻辑分布在Saga的每一个参与者中,他们通过交换事件的方式来进行沟通
    • 命令/协同式:把Saga的角色和执行顺序逻辑集中在一个Saga控制类中,他以命令/回复的方式与每一项服务进行通信,告诉他们应该执行哪个操作。
事件/编排式
  • 在基于时间的编排模式中,第一个服务执行完一个本地事务之后,发送一个事件。这个事件会被一个或者多个服务监听,监听到事件的服务接着执行他自己的本地事务并发布新的事件,此后一直延续这种事件触发模式,直到整个业务流程中最后一个服务的本地事务执行结束,才意味着整个分布式长事务也执行结束。我们用如下图说明:

在这里插入图片描述

  • 如上图流程看起来复杂,但是他是比较常见的解决方案,解释以上流程:
    • 订单服务创建新的订单,吧订单状态设置为待支付,并发布一个“创建订单”事件
    • 库存服务监听到 “创建订单”事件后,执行本地库存冻结方法,如果执行成功,则发布一个“库存准备事件”
    • 支付服务监听到 “库存准备事件”事件后,执行账户扣款方法,并发布 “支付事件”
    • 最后,积分服务监听到“支付事件”事件后,增加账户积分,并更新订单状态为成功
  • 如果上述任何一次执行失败,当前时间都变成失败的时间,例如“库存准备事件” 变成 “库存准备失败事件”,每个服务需要监听失败的情况根据实际需求进行逐一回滚。
命令/协同式
  • 命令/协同 模式需要定义一个Saga协调器,负责告诉每一个参与者该做啥。Saga协调器以命令/回复的方式与每一个服务进行通信,如下流程:

在这里插入图片描述

  • 命令协同模式流程如下:

    • 订单服务手下创建一个订单,然后创建一个订单的协调器,用来协调之后的事务,启动订单事务。
    • Saga协调器向库存服务发送冻结库存命令,库存服务通过订单 Saga回复队列回复直接的结果
    • 接着,Saga协调器继续向支付服务发起咋呼扣款命令,支付服务通过订单 Saga回复队列回复执行结果
    • 最后,Saga协调器向会员服务发起添加会员命令,会员服务回复执行结果。
  • 整个流程需要有一个前置条件,订单Saga协调器必须提前知道“创建订单事务”的所有流程,并且在整个流程中任何一个环节执行失败,他都需要向每个参与者发送命令,撤销之前的事务操作。

上一篇:分布式事务解决方案
下一篇:分布式事务 – seata框架AT模式实现原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310433.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[一起读源码]走进C#并发队列ConcurrentQueue的内部世界 — .NET Core篇

在上一篇《走进C#并发队列ConcurrentQueue的内部世界》中解析了Framework下的ConcurrentQueue实现原理,经过抛砖引玉,得到了一众大佬的指点,找到了.NET Core版本下的ConcurrentQueue源码,位于以下地址:https://github.…

Java语法基础50题训练(上)

题目1: 有两只老虎,一只体重为180kg,一只体重为200kg,请用程序实现判断两只老虎的体重是否相同。 代码如下: public class OperatorTest {public static void main (String[] args) {int w1 180;int w2 200;boolean ans w1 w2?true:f…

EFCore.Sharding(EFCore开源分表框架)

简介本框架旨在为EF Core提供Sharding(即读写分离分库分表)支持,不仅提供了一套强大的普通数据操作接口,并且降低了分表难度,支持按时间自动分表扩容,提供的操作接口简洁统一.源码地址:EFCore.SHarding引言读写分离分库分表一直是数据库领域中的重难点,当数据规模达到单库极限的…

分布式事务 -- seata框架AT模式实现原理

Seata AT 模式 上一节中我们提到AT模式是基于XA事务模型演变过来的,所以他的整体机制也是一个改进版本的两阶段提交协议。 第一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和链接资源第二阶段:提交异步化&…

[Java基础]数据输入

Scanner使用的基本步骤: 1.导包: import java.util.Scanner;2.创建对象: Scanner sc new Scanner(System.in);3.接收数据: int i sc.nextInt();代码如下: import java.util.Scanner;public class OperatorTest {public static void main (String[] args) {//创建对象Scan…

k8s中流量分离以及资源隔离实战

源宝导读:明源云客的终端用户越来越多,也涌现出线上流量活动的场景,大量的访问和接口请求导致服务器出现较高负载。本文将介绍云客团队为了缓解服务器压力,通过K8S进行分流与资源隔离的实践过程。一、背景PaaS和B2C的主要客户云客…

怎样实现WPF Prism Module的国际化和本地化?

English | 简体中文上一篇有简单介绍主工程的国际化,使用的资源字典(XAML)实现的。这几天我添加了几个Prism模块(Module),发现子模块使用资源字典的方式实现国际化和本地化不好做,没有找到比较好的参考文章,所以换了一种方式&…

dotNET Core 3.X 使用 Jwt 实现接口认证

在前后端分离的架构中,前端需要通过 API 接口的方式获取数据,但 API 是无状态的,没有办法知道每次请求的身份,也就没有办法做权限的控制。如果不做控制,API 就对任何人敞开了大门,只要拿到了接口地址就可以…

数据结构与算法--代码鲁棒性案例分析

代码鲁棒性 鲁棒是robust的音译,就是健壮性。指程序能够判断输入是否符合规范,对不合要求的输入能够给出合理的结果。容错性是鲁棒的一个重要体现。不鲁棒的代码发生异常的时候,会出现不可预测的异常,或者程序奔溃。由于鲁棒性非…

【半译】两个gRPC的C#库:grpc-dotnet vs Grpc.Core

grpc-dotnet 是在2019年随着 .NET Core 3.0 一起发布的一个gPRC官方库。在ASP.NET Core 的 gRPC项目模板里面就使用了这个库。.NET Core 3.0之前难道不可以使用gRPC吗?目前,gRPC 在.NET上有两种官方实现:Grpc.Core:这个是原来的gR…

[Java基础]String对象的特点(易错点)

String对象的特点: 1.通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同。 2.以""方式给出的字符串,只要字符串相同(顺序和大小写),无论在程序代码中出现几次&#xff0…

数据结构与算法--解决问题的方法- 二叉树的的镜像

解决问题的思路 工作中遇到的问题可能用到的数据结构由很多,并且各种数据结构都不简单,我们不可能光凭借想象就能得到问题的解法,因此画图是在家具问题过程中用来帮助自己分析,推理的常用手段。很多问题比较抽象,不容…

使用dnSpy调试asp.net core源码

环境:window 10vs2019 16.5.1dnspy v6.1.4.netcore3.1参考:.Net反编译技术详解及4个反编译工具介绍一、关于dnSpydnSpy是近几年的新秀,功能远比ILSpy强大,甩.net Reflector几条街,被汉化、破解、逆向方面的人才奉为神器…

数据结构与算法--解决问题的方法-顺时针打印矩阵

顺时针打印矩阵 题目输入一个矩阵,按照从外向里顺时针的顺序依次打印每一个数字。例如下案例: 如上图矩阵,顺时针打印:1,2,3,4,8,12,16,15,14,13,9,5,6,7,1,10 以上问题看起来比较复杂,但是又没有涉及到复杂的数据结…

.NET与鲲鹏共展翅,昇腾九万里(二)

在上一篇文章 .NET与鲲鹏共展翅,昇腾九万里(一)中,我们通过在鲲鹏架构的Euler系统上跑Docker的方式把dotnet core 跑起来了,有读者反馈说“还是走docker喽,你这个标题应该改成鲲鹏和docker两条鲸鱼的故事”…

[Java基础]final和static修饰符

final: final修饰局部变量时: static: static访问特点:

优化委托的 DynamicInvoke

优化委托的 DynamicInvokeIntro委托方法里有一个 DynamicInvoke 的方法,可以在不清楚委托实际类型的情况下执行委托方法,但是用 DynamicInvoke 去执行的话会比直接用 Invoke 的方法会慢上很多,差了两个数量级,所以在知道委托类型的…

数据结构与算法-- 广度优先打印二叉树

广度优先打印二叉树 题目:从上往下打印出二叉树的每一个节点,同一层节点按照从左到右顺序打印,例如下图中二叉树,依次打印出是8,6,10,5,7,9,11 如上题中二叉树的节点定义我们用之前文章 二叉树实现原理中定义的节点结构。此处提议…