Seata Saga 模式快速入门和最佳实践

news2024/11/24 7:08:22

dfcd8ac6b769da9908656fc42862bf62.gif

文|王特(花名:亦夏)

Email:yixia.wt@antgroup.com

蚂蚁集团数据中间件核心开发

本文 4927 字 阅读 13 分钟

Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。Seata 为用户提供了 AT、TCC、SAGA、XA 等多种事务模式,帮助解决不同业务场景下的事务一致性问题。

本文主要介绍 Seata Saga 模式的使用以及最佳实践,围绕三个部分展开,第一部分是 Seata Saga 的简介、第二部分旨在快速介绍 Seata Saga 模式的使用方法并帮助大家入门,最后一部分将会给大家分享一些 Seata Saga 实践中的经验,帮助用户更快、更好得使用 Seata Saga 模式。

Seata Saga 简介

Part One

1.1 Saga 模式

Saga 模式是分布式事务的解决方案之一,理念起源于 1987 年 Hector & Kenneth 发表的 Sagas 论文。它将整个分布式事务流程拆分成多个阶段,每个阶段对应我们的子事务,子事务是本地事务执行的,执行完成就会真实提交。

82b397ff72c2fd6d0db81e25b5fc1e86.png

它是一种基于失败的设计,如上图可以看到,每个活动或者子事务流程,一般都会有对应的补偿服务。如果分布式事务发生异常的话,在 Saga 模式中,就要进行所谓的“恢复”,恢复有两种方式,逆向补偿正向重试。比如上面的分布式事务执行到 T3 失败,逆向补偿将会依次执行对应的 C3、C2、C1 操作,取消事务活动的“影响”。那正向补偿,它是一往无前的,T3 失败了,会进行不断的重试,然后继续按照流程执行 T4、T5 等。

根据 Saga 模式的设计,我们可以得到 Saga 事务模式的优缺点。

优点:

  • 子事务(或流程),提交是本地事务级别的,没有所谓的全局锁,在长事务流程下,避免了长时间的资源锁定;另外这种流水线的处理模型天然符合阶段式信号处理模型,能发掘出更高的性能和吞吐。

  • 正向服务和补偿服务都是交给业务开发实现的,所以 Saga 模式和底层数据库协议是无关的。XA/AT 模式可能依赖特定的数据库类型和版本,比如 MySQL 是 5.0 之后才支持的 XA,那么低版本的 MySQL 就不能适用到 XA 模式。

缺点:

  • 也是因为正向服务和补偿服务都由业务开发者实现,所以业务上是有开发成本的,侵入性相对 XA/AT 打一个注解的方式会高很多。

  • 因为一阶段子事务活动提交是本地事务级别的,所以 Saga 模式不保证隔离性。提交之后就可能“影响”其他分布式事务、或者被其他分布式事务所“影响”。例如:其他分布式事务读取到了当前未完成分布式事务中子事务的更新,导致脏读;其他分布式事务更新了当前未完成分布式事务子事务更新过的字段,导致当前事物更新丢失;还有不可重复读的场景等。

所以 Saga 模式的使用也需要考虑这些问题带来的“影响”。一般 Saga 模式的使用场景有如下几个:

  • 长事务流程,业务上难以接受长时间的资源锁定,Saga 的特性使得它在长事务流程上处理非常容易;

  • 业务性质上,业务可以接受或者解决缺乏隔离性导致的“影响”。例如部分业务只要求最终一致性,对于隔离性要求没有那么严格,其实是可以落地 Saga 模式的;

  • 分布式事务参与者包含其他机构或者三方的服务,数据资源服务不是我们自身维护,无法提供 TCC 模式要求的几个接口。

1.2 Seata Saga

接下来我们来看看 Seata Saga 的实现。Saga 主流的实现分为两种:编排式和协调式。Seata Saga 的实现方式是编排式,是基于状态机引擎实现的。状态机执行的最小单位是节点:节点可以表示一个服务调用,对应 Saga 事务就是子事务活动或流程,也可以配置其补偿节点,通过链路的串联,编排出一个状态机调用流程。在 Seata 里,调用流程目前使用 JSON 描述,由状态机引擎驱动执行,当异常的时候,我们也可以选择补偿策略,由 Seata 协调者端触发事务补偿。

有没有感觉像是服务编排,区别于服务编排,Seata Saga 状态机是 Saga+服务编排,支持补偿服务,保证最终一致性。

我们来看看一个简单的状态机流程定义:

ba17b8ad4b8b126b5da0d5c2468c9d68.jpeg

上方是一个 Name 为 reduceIncentoryAndBalance 的状态机描述,里面定了 ServiceTask 类型的服务调用节点以及对应的补偿节点 CompensateReduceInventory

看看几个基本的属性:

  • Type:节点类型,Seata Saga 支持多种类型的节点。例如 ServiceTask 是服务调用节点

  • ServiceName/ServiceMethod:标识 ServiceTask 服务及对应方法

  • Input/Output:定义输入输出参数,输入输出参数取值目前使用的是 SPEL 表达式

  • Retry:控制重试流程

  • Catch/Next:用于流程控制、衔接,串联整个状态机流程

更多类型和语法可以参考 Seata 官方文档[1],可以看到状态机 JSON 声明还是有些难度的,为了简化状态机 JSON 的编写,我们也提供了可视化的编排界面[2],如下所示,编排了一个较为复杂的流程。

41e12d3fa3e144a3358abeebd866e6f9.png

话不多说,我们进入下面的实践环节。

Seata Saga 使用入门

Part Two

2.1 从 Seata 官网新人文档开始

Seata 分 TC、TM 和 RM 三个角色,TC(Server 端)为单独服务端部署,TM 和 RM(Client 端)由业务系统集成。

Server 端存储模式(store.mode)现有 file、db、redis 三种(后续将引入 Raft、MongoDB),file 模式无需改动,直接启动即可。

部署 Seata Server

从新人文档,可以看出 Seata 还是传统的 CS 模型。首先我们需要部署 Seata Server 端。Server 端默认的存储模式时 file 模式,无需改动,直接执行 SpringBoot 启动类 main 方法即可启动 Seata Server。为了方便,本次演示就使用 file 模式启动,其他模式的启动方式可以参考新人文档的详细介绍。

创建 Client 端测试应用

同时我们需要创建一个客户端的测试应用,这里命名 seata-saga-test,测试应用使用 SpringBoot 框架,配置好 spring 的 aplication.pname 和 port,并且引入 seata-spring-boot-starter 依赖,完成 Client 端应用的搭建。

267e65dc2669df8c2ba11069ba92f496.png

2.2 从 Seata Saga 单元测试看起

一般了解一个框架的功能,建议是从入口的单元测试类开始看起。在 Seata 仓库中找到 Seata Saga 的 test 模块,从最外围的测试类 io.seata.saga.engine.StateMachineTests 看起(一般开源项目最外围的测试类即是入口类)

b2287c954435722ff01d945b72c0989c.png

从上面的截图可以看出,入口测试方法主要分为三个部分:

【1】处的 spring 配置文件声明了 StateMachineEngine Bean 以及对应的属性,【2】处也引用了该类执行 start,判断该类为我们状态机的入口类,其实 StateMachineEngine 该类也就是 Seata Saga 状态机操作入口,控制状态机的开始、恢复等操作。StateMachineEngine 有一个重要的属性 resources,该属性声明了状态机 JSON 文件的存储路径,Seata Saga 状态机引擎启动的时候会加载对应路径下的状态机定义,以供后续使用,这里的路径根据我们需求更改。

【3】处调用了 StateMachineEngine 的 start 方法,传递状态机名称、启动参数,开启一个状态机流程调用。简单跟下实现,可以看到其中状态名称对应 resources 路径下状态机 JSON 定义中的 Name 属性。

测试 Seata Saga 状态机流程,我们得先有一个状态机 JSON 定义。使用 Seata Saga StateMachine Designer[3],定义一个简单 AService#doA 方法调用 BService#doB 方法的状态机流程,再加个入参,最终我们的类#方法和状态机 JSON 如下所示。

ce354d67b6f49a6826207b160237ae54.png

有了基础的调用模型和状态机 JSON 定义,按照测试用例,我们同样声明出状态机 Bean 及执行入口(注意:start 方法里面的状态机名称需要和状态机 JSON 定义里面的 Name 名称保持一致),执行下 main 方法,我们可以发现 AService#doA 方法和 BService#doB 方法都被成功调用了。

5f99100eb61ebddb18c92fa1699abd99.png

至此,我们已经完成了 Seata Saga 状态机的入门使用。继续观察单测,我们发现 Seata Saga 单测还有两个模块,分别是 db 和 mock。

4a01b3728d1a744409129d1af48baf7a.png

我们先来看看 db 模块的单测,可以看到 db 模块的单测类和上面基本类似,唯一的区别就在于 StateMachineEngine,指定了 db 存储,执行了 DDL SQL(初始化 Seata Saga 相关表)。指定了 db 存储,那么我们的状态机执行过程将会持久化在 db 存储,方便事务执行过程查询和异常恢复,也是生产环境的实践方式。

fc428d8002870c1975b2ddce2e9e4014.png

mock 模块通过 Mock Transcation,脱离 Seata Sever,仅使用了 Seata Saga 的服务编排能力。有兴趣的同学可以再去实践下 db 和 mock 模块的使用,这里就不展开了。

Seata Saga 最佳实践

Part Three

3.1 基本使用

  • 在应用层面,Seata Saga 状态机模式使用上不同于 AT、TCC 注解化方式,要使用状态机 API 执行;

  • 在状态机模式里面,恢复策略分为向前重试和向后补偿,根据业务场景,要选择合适的补偿策略;

  • Seata Saga 支持异步状态执行、状态机异步执行,适时使用异步,可以提升整个系统的吞吐量。

3.2 Saga 服务

  • Saga 服务可能被多次调用,所以要保证幂等

  • 补偿服务较原服务可能先执行、需要允许空补偿、同时需要拒绝后续的原服务请求,进行防悬挂控制

3.3 隔离性问题应对

  • 业务驱动,如果业务上可以接受缺乏隔离性的影响,可以不用做任何操作

  • 语义锁,对操作资源进行语义级别的锁定

  • 使用悲观流程,例如 A->B 转账操作,先给 B 加钱,再给 B 减钱;换成悲观视图就是先给 A 减钱,再给 B 加钱,防止 B 加钱之后立刻消费导致的短款问题

  • 其它方式

3.4 稳定性

基于 db 存储的 Saga 模式,需要注意:重试或者补偿默认会插入一条状态执行记录,频繁重试或者补偿,会导致状态执行记录爆炸,如果有大对象存储,可能会导致内存 crash。Seata Saga 提供了 update 模式,使用 update 记录代替新增执行记录,用来避免此类问题。

3.5 扩展

  • Seata Saga 状态机存储、语法解析等都是面向 SPI 设计的,业务上可以平滑替换对应的存储或者状态机语言实现。例如将状态机的 JSON 解析替换到 YAML 解析。

  • Seata Saga 支持 Mock Transaction 的方式,仅使用服务编排能力,也支持状态机定义(JSON)动态发布,也就是编排的动态发布,这一点在做 DSL 动态管控端的时候将会非常有用。

讲了这么多,Seata Saga 目前状态机的实现,上手成本相对还是比较高。一方面我们致力提升 Seata Saga 状态机模式的易用性,同时也在设计 Saga 的注解化模式、流式编排模式,期望提供给用户更具产品化能力的 Seata Saga。有兴趣的同学,也非常欢迎加入共建。

扫码进入钉钉群:

Seata Group 开源交流群:44816898

f1b672aca585b698c38db2f92f55b431.png

相关链接:

[1]Seata 官方文档:

http://seata.io/zh-cn/docs/user/saga.html

[2]可视化的编排界面

http://seata.io/saga_designer/index.html#/

[3]Seata Saga StateMachine Designer:

http://seata.io/saga_designer/index.html#/

Seata Star 一下✨:
https://github.com/seata/seata

  本周推荐阅读  

7d23396edf274ee32cde08e8633f5746.png

生产环境可用的 Seata-go 1.2.0 来啦!!!

789255dc98e4e5ba841bfed3385d8487.jpeg

Seata-go 1.1.0 发布,补齐 AT 模式支持

a8568f4d73edb85927bbf361ab9965f3.png

Seata-go 1.0 重磅发版

2ccd5471fbaf5ea02ba2dc2a61c490ba.png

Seata AT 模式代码级详解

38c90dbd62cb8a2a2b2a8304ec0f7c30.jpeg

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

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

相关文章

ssm+java高校图书馆图书借阅导航系统

智能图书馆导航管理系统是一款基于BS架构模式开发的图书馆宣传网站,网页端采用SSM框架技术开发,MySQL作为数据库,同时使用了JSP、java web等技术进行开发,最终达到智能图书导航的实现,能够实现用户搜索书籍&#xff0c…

Vue中如何进行图片处理与滤镜效果?

Vue中如何进行图片处理与滤镜效果? 在 Vue 应用程序中,处理图片和应用滤镜效果是非常常见的需求。这可以让你的应用程序更加生动而丰富,吸引更多用户的眼球。Vue 提供了多种方式来处理图片和应用滤镜效果,让你可以轻松地实现这些…

一文带你读懂验厂审核!

验厂是什么? 验厂似乎是非汽车行业通俗的叫法,指的是下游客户对上游供应商的考核;在汽车行业,更准确的称呼为供应商审核,包括潜在供应商审核和供应商年审。所以为了避免误解,跟汽车行业的客户沟通的时候&am…

千万级入口服务[Gateway]框架设计(二)

本文将以技术调研模式编写,非技术同学可跳过。 文章目录 背景实现二:开源 go-pluginDemo 实现Benchwork 基准性能小结 附录 背景 基于组件(插件)模式设计构建的入口服务,在使用 Go 原生包 plugin 实现的时候,会存在功能缺陷问题…

PSP - RoseTTAFold2 的 PDB 结果预处理

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/131201456 RoseTTAFold2 是蛋白质结构预测算法,利用了深度学习和三维几何建模的技术,能够快速准确地预测蛋白质的…

【社区图书馆】《看漫画学Python:有趣、有料、好玩、好用(全彩修订版)》

背景 Python是一门既简单又强大的编程语言,被广泛应用于数据分析、大数据、网络爬虫、自动化运维、科学计算和人工智能等领域。Python也越来越重要,成为国家计算机等级考试科目,某些中小学也开设了Python编程课程。本书秉承有趣、有料、好玩…

【方法】PDF文档可以转图片吗?如何操作?

需要把PDF文档转换成图片,你会怎么做呢? 有些小伙伴可能会直接截图保存,确实是一个快捷的方法,但这种方法容易造成图片质量的损失,也可能遇到无法截图整个页面的情况,或者文档页面多,截图耗费很…

【Android -- JNI 和 NDK】JNI 基础知识以及如何使用

JNI 基础知识 我们来系统梳理一下JNI中涉及的基本知识。 JNI定义了以下数据类型,这些类型和Java中的数据类型是一致的: Java原始类型:jint, jbyte, jshort, jlong, jfloat, jdouble, jchar, jboolean这些分别对应这 java 的int, byte, shor…

java反射调用get/set方法

1 前言 最新工作中,遇到了通过反射调用get/set方法的地方,虽然反射的性能不是很好,但是相比较于硬编码的不易扩展,getDeclareFields可以拿到所有的成员变量,后续添加或删除成员变量时,不用修改代码&#x…

Vue组件——动态、缓存、异步组件

1. 动态组件 component 语法&#xff1a;静态&#xff1a;<component is"组件名"></component> 动态&#xff1a;<component :is"组件名"></component> 可以用来实现页面的切换&#xff1a; // 模板<component :is"n&q…

目标检测数据集---三星工业缺陷数据集

✨✨✨✨✨✨目标检测数据集✨✨✨✨✨✨ 本专栏提供各种场景的数据集,主要聚焦:工业缺陷检测数据集、小目标数据集、遥感数据集、红外小目标数据集,该专栏的数据集会在多个专栏进行验证,在多个数据集进行验证mAP涨点明显,尤其是小目标、遮挡物精度提升明显的数据集会在该…

如何利用工业RFID识别设备帮助企业提高产品质量?

ANDEAWELL作为国内知名的工业识别设备厂家&#xff0c;今天就跟大家一起来了解一下&#xff0c;企业如何利用工业RFID识别设备帮助企业提高产品质量。 1. 严格的质量控制流程 在生产过程中&#xff0c;我们需要建立一套严格的质量控制流程。这个流程应该包括原材料的采购、生产…

【前端 - CSS】第 16 课 - 伪类选择器(鼠标悬停状态)

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、伪类选择器 3、伪类 - 超链接&#xff08;拓展&#xff09; 4、总结 1、缘起 在 CSS 中&#xff0c;我们使用 hover…

4、nacos服务的linux部署

1、下载nacoz注册中心 Nacos 快速开始通过这个里面查找地址进行下载, 2、下载之后通过xshell的xftp上传到服务器上&#xff0c;比如上传到home下的soft&#xff0c;如果没有soft进行创建 chmod对文件夹进行授权&#xff0c;不然xftp应该上传不到这个文件夹 3、解压缩 解压缩之…

【笔试强训选择题】Day26.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

100种思维模型之复利原理-77

关于复利&#xff0c;有一个广为流传的故事&#xff0c;相信大家都听过&#xff1a;在国际象棋的棋盘上&#xff0c;第一个格子放1粒米&#xff0c;第二格翻倍放2粒&#xff0c;第三格再翻倍放4粒&#xff0c;以此类推&#xff0c;下一格都是前一格的一倍&#xff0c;一直放到最…

Stimulsoft Reports用户手册:Report Designer介绍

Stimulsoft Reports.Net是一个基于.NET框架的报表生成器&#xff0c;能够帮助你创建结构、功能丰富的报表。StimulReport.Net 的报表设计器不仅界面友好&#xff0c;而且使用便捷&#xff0c;能够让你轻松创建所有报表&#xff1b;该报表设计器在报表设计过程中以及报表运行的过…

005、体系结构之TiKV_Raft日志

Raft日志 1、Raft与Multi Raft2、Raft 日志复制2.1、复制流程总览2.2、Propose2.3、Append2.3、Replicate(Append)2.4 Committed2.4 Apply 3、Raft Leader 选举3.1、原理3.2、节点故障Leader&#xff08;主副本&#xff09;选举⽇志复制 1、Raft与Multi Raft 一个region的大小是…

MPI期末复习指南

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; C/C专栏 &#x1f319;那些看似波澜不惊的日复一日&#xff0c;…

国家版权局正版化检查工具添加自定义检查软件及问题处理

使用国家版权局正版化检查工具进行软件正版化检查时&#xff0c;根据各个单位购买的正版化软件的不同&#xff0c;需要将自购软件和禁用软件增加到检查清单&#xff0c;本文件介绍添加自定义检查软件的方法及问题处理。 一、检查清单文件介绍及修改方法 国家版权局正版化检查工…