关于java:Seata-Saga-模式快速入门和最佳实践

62次阅读

共计 4718 个字符,预计需要花费 12 分钟才能阅读完成。

文|王特 (花名:亦夏)

Email:yixia.wt@antgroup.com

蚂蚁团体数据中间件外围开发

本文4927 字 浏览 13 分钟

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

本文次要介绍 Seata Saga 模式的应用以及最佳实际,围绕三个局部开展,第一局部是 Seata Saga 的简介、第二局部旨在疾速介绍 Seata Saga 模式的应用办法并帮忙大家入门,最初一部分将会给大家分享一些 Seata Saga 实际中的教训,帮忙用户更快、更好得应用 Seata Saga 模式。

1 Seata Saga 简介

1.1 Saga 模式

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

它是一种基于失败的设计,如上图能够看到,每个流动或者子事务流程,个别都会有对应的弥补服务。如果分布式事务产生异样的话,在 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+ 服务编排,反对弥补服务,保障最终一致性。

咱们来看看一个简略的状态机流程定义:

上方是一个 Name 为 reduceIncentoryAndBalance 的状态机形容,外面定了 ServiceTask 类型的服务调用节点以及对应的弥补节点 CompensateReduceInventory

看看几个根本的属性:

  • Type:节点类型,Seata Saga 反对多种类型的节点。例如 ServiceTask 是服务调用节点
  • ServiceName/ServiceMethod:标识 ServiceTask 服务及对应办法
  • Input/Output:定义输入输出参数,输入输出参数取值目前应用的是 SPEL 表达式
  • Retry:管制重试流程
  • Catch/Next:用于流程管制、连接,串联整个状态机流程

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

话不多说,咱们进入上面的实际环节。

2 Seata Saga 应用入门

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 端利用的搭建。

2.2 从 Seata Saga 单元测试看起

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

从下面的截图能够看出,入口测试方法次要分为三个局部:

【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 如下所示。

有了根底的调用模型和状态机 JSON 定义,依照测试用例,咱们同样申明出状态机 Bean 及执行入口 (留神:start 办法外面的状态机名称须要和状态机 JSON 定义外面的 Name 名称保持一致),执行下 main 办法,咱们能够发现 AService#doA 办法和 BService#doB 办法都被胜利调用了。

至此,咱们曾经实现了 Seata Saga 状态机的入门应用。持续察看单测,咱们发现 Seata Saga 单测还有两个模块,别离是 db 和 mock。

咱们先来看看 db 模块的单测,能够看到 db 模块的单测类和下面根本相似,惟一的区别就在于 StateMachineEngine,指定了 db 存储,执行了 DDL SQL (初始化 Seata Saga 相干表)。指定了 db 存储,那么咱们的状态机执行过程将会长久化在 db 存储,不便事务执行过程查问和异样复原,也是生产环境的实际形式。

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

Seata Saga 最佳实际

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

相干链接:

[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

正文完
 0