Saga模式

Saga模式使用一系列本地事务来提供事务管理,而一个本地事务对应一个Saga参与者,在Saga流程里面每一个本地事务只操作本地数据库,然后通过消息或事件来触发下一个本地事务,如果其中一个本地事务失败了,Saga就会执行一系列补偿事务来实现回滚操作。(补偿事务简单来讲就是对之前本地事务做的修改导致不一致的情况执行反向操作来消除掉不一致的状态)。

上图左侧是正常的事务流程,当执行事务T3时出现异常,则开始反向执行右边的事务补偿,其中C3是T3的补偿,C2是T2的补偿,C1是T1的补偿,将T3,T2,T1已经修改的数据做补偿处理。

实现分析

对Saga事务流程进行排序,当Ti事务完成之后,需要决定下一步要怎么进行。如果成功执行T(i+1)分支,如果失败,则执行C(i-1)分支。这类似一个工作流或是状态机的概念。从实现来看,有两种方式:

集中式实现

集中式协调器负责服务调用以及事务协调(Orchestration)即编排实现:集中式协调器负责服务调用以及事务协调。Saga提供一个控制类,其方便参与者之间的协调工作。事务执行的命令从控制类发起,按照逻辑顺序请求Saga的参与者,从参与者那里接受到反馈以后,控制类在发起向其他参与者的调用。所有Saga的参与者都围绕这个控制类进行沟通和协调工作。

去中心化实现

分布式的实现方式——通过事件驱动的方式进行事务协调(Choreography)即协同实现:Saga参与者(子事务)之间的调用、分配、决策和排序,通过交换事件进行进行。是一种去中心化的模式,参与者之间通过消息机制进行沟通,通过监听器的方式监听其他参与者发出的消息,从而执行后续的逻辑处理。由于没有中间协调点,靠参与者自己进行相互协调。

实现比对

我个人认为在计算机的世界里没有银弹!任何的解决方案只能说是合适与不合适,而没有完美的契合并解决。

如上两种解决方式都有一定的弊端;对于集中式的实现方式,其弊端如下:

  • 必须额外实现一个协调器,相当于增加了系统复杂度
  • 需要考虑协调器自身发生故障时应对措施

分布式的实现方式,其弊端如下:

  • 添加新的事务步骤时比较麻烦,需要确定哪个Saga参与者订阅了哪个事件。
  • 有可能出现循环依赖的问题,每一个Saga参与者都可能订阅其他参与者的事件。
  • 集成测试异常复杂,需要运行所有服务来模拟事务。

实现方式

目前看到市面上已经有很多的saga实现,他们都具备saga的基本功能。

这些实现,可以大致可以分为两类

状态机实现
Seata

这一类的典型实现有seata的saga,他引入了一个DSL语言定义的状态机,允许用户做以下操作:

在某一个子事务结束后,根据这个子事务的结果,决定下一步做什么

能够把子事务执行的结果保存到状态机,并在后续的子事务中作为输入

允许没有依赖的子事务之间并发执行。

  • 优点:

    功能强大,事务可以灵活自定义

  • 缺点:

    状态机的使用门槛非常高,需要了解相关DSL,可读性差,出问题难调试。官方例子是一个包含两个子事务的全局事务,Json格式的状态机定义大约有95行,较难入门。

    接口入侵强,只能使用特定的输入输出接口参数类型,在云原生时代,对强类型的gRPC不友好(gRPC协议,在TM拿不到用户自定义的输入输出pb文件,因此无法解析结果中的字段)

Masstransit Saga State Machines

Masstransit是一个免费、开源的.NET 分布式应用框架。其功能之一就是提供了强大的状态机编排能力。通过集成消息队列中间件,基于C#高效易用的语法,支持了状态机的编排。其使用语法示例如下

///// 下单 初始化 → 已初始化
///// 翻译:当前状态是Initial且执行OrderProcessInitializationEvent事件时,Then(然后)执行xxxx,最后将状态转换(TransitionTo)为OrderProcessInitializedState During(Initial,
When(OrderProcessInitializationEvent)
.Then(x => {
x.Saga.OrderStartDate = DateTime.Now;
})
.TransitionTo(OrderProcessInitializedState)); ///// 库存 已初始化 → 校验库存
///// 翻译:当前状态是OrderProcessInitializedState且执行CheckProductStockEvent事件时,Then(然后)执行xxxx,最后将状态转换(TransitionTo)为CheckProductStockState During(OrderProcessInitializedState,
When(CheckProductStockEvent)
.Then(x => {
System.Console.WriteLine(x.Message.OrderId);
})
.TransitionTo(CheckProductStockState)); ///// 支付 校验库存 → 支付
During(CheckProductStockState,
When(TakePaymentEvent)
.TransitionTo(TakePaymentState)); ///// 订单 支付 → 创建订单
During(TakePaymentState,
When(CreateOrderEvent).Then(x => {
System.Console.WriteLine(x.Message.OrderId);
})
.TransitionTo(CreateOrderState)); ///// 创建订单失败
DuringAny(When(CreateOrderFaultEvent)
.TransitionTo(CreateOrderFaultedState)
.Then(context => context.Publish<Fault<TakePaymentEvent>>(new {context.Message}))); ///// 支付失败
DuringAny(When(TakePaymentEventFaultEvent)
.TransitionTo(TakePaymentFaultedState)
.Then(context => context.Publish<Fault<CheckProductStockEvent>>(new {context.Message}))); ///// 校验库存失败
DuringAny(When(CheckProductStockFaultEvent)
.TransitionTo(CheckProductStockFaultedState)
.Then(context => context.Publish<Fault<OrderProcessInitializationEvent>>(new {context.Message}))); ///// 下单失败
DuringAny(When(OrderProcessInitializationFaultEvent)
.TransitionTo(OrderProcessInitializedFaultedState)
.Then(context => context.Publish<OrderProcessFailedEvent>(new {OrderId = context.Saga.CorrelationId}))); ///// 下单流程失败
DuringAny(When(OrderProcessFailedEvent)
.TransitionTo(OrderProcessFailedState));

流程逻辑:当客户端请求下单服务时,业务逻辑正常执行,执行成功后发布事件到消息队列,状态机监听到对应的订单事件后,修改当前状态,发布事件标识成功或失败,订单服务业务监听事件,响应状态的调整(一般是标识或回滚业务)。

  • 优点

    方便简单,而且强大,流程编排能力很强。

  • 缺点:引入了rabbitmq,有中间件依赖。

可参考实现:

使用 Masstransit中的 Request/Response 与 Courier 功能实现最终一致性

分布式事务 | 基于MassTransit的StateMachine实现Saga编排式分布式事务

非状态机实现

这一类的实现有eventuate的saga,dtm的saga。

在这一类的实现中,没有引入新的DSL来实现状态机,而是采用函数接口的方式,定义全局事务下的各个分支事务。

优点:

简单易上手,易维护

缺点:

难以做到状态机的事务灵活自定义

ACID与Saga

聊聊分布式解决方案Saga模式的更多相关文章

  1. 分布式事务 | 使用DTM 的Saga 模式

    DTM 简介 前面章节提及的MassTransit.dotnetcore/CAP都提供了分布式事务的处理能力,但也仅局限于Saga和本地消息表模式的实现.那有没有一个独立的分布式事务解决方案,涵盖多种 ...

  2. 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾

    https://mp.weixin.qq.com/s/67NvEVljnU-0-6rb7MWpGw 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾 原创 蚂蚁金 ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(十九)——分布式事务之Saga模式

    在之前的系列文章中聊过分布式事务的一种实现方案,即通过在集群中暴露actor服务来实现分布式事务的本地原子化.但是actor服务本身有其特殊性,场景上并不通用.所以今天来讲讲分布式事务实现方案之sag ...

  4. 微服务痛点-基于Dubbo + Seata的分布式事务(AT)模式

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

  5. 微服务痛点-基于Dubbo + Seata的分布式事务(TCC模式)

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

  6. Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式

    Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式 1.1. Kiosk Software广泛用于公共电脑或者嵌入系统,最常用的就是ATM机.自动服务机之类的系统了.,1 ...

  7. Solr系列二:solr-部署详解(solr两种部署模式介绍、独立服务器模式详解、SolrCloud分布式集群模式详解)

    一.solr两种部署模式介绍 Standalone Server 独立服务器模式:适用于数据规模不大的场景 SolrCloud  分布式集群模式:适用于数据规模大,高可靠.高可用.高并发的场景 二.独 ...

  8. Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config

    目录 Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config Spring Cloud Config(二):基于Git搭建配置中心 Spring Cl ...

  9. 分布式事务:Saga模式

    1 Saga相关概念 1987年普林斯顿大学的Hector Garcia-Molina和Kenneth Salem发表了一篇Paper Sagas,讲述的是如何处理long lived transac ...

  10. 聊聊分布式下的WebSocket解决方案

    前言 最近王子自己搭建了个项目,项目本身很简单,但是里面有使用WebSocket进行消息提醒的功能,大体情况是这样的. 发布消息者在系统中发送消息,实时的把消息推送给对应的一个部门下的所有人. 这里面 ...

随机推荐

  1. 新版TinyCore Linux系统安装

    1.设置软件仓库源echo "https://mirrors.163.com/tinycorelinux">/opt/tcemirror 2.安装启动加载器及其依赖tce-l ...

  2. Synchronized 关键字详解

    更多内容,前往 IT-BLOG Synchronized原理分析 加锁和释放锁的原理 深入JVM看字节码,创建如下的代码: 1 public class SynchronizedDemo2 { 2 O ...

  3. urllib.parse的使用

    urllib简介 urllib是pyhton自带的标准库用于网络请求库,无需安装,直接引用 通常用于爬虫开发,API(应用程序编程接口)数据获取和测试 urllib库的4大模块 urllib.requ ...

  4. void关键字

    在C++中,void表示为无类型,主要有三个用途: (1)函数的 返回值用void,表示函数没有返回值. void func(int a, int b) { //函数体代码 return; } (2) ...

  5. 可视化—AntV G6 紧凑树实现节点与边动态样式、超过X条展示更多等实用小功能

    通过一段时间的使用和学习,对G6有了更一步的经验,这篇博文主要从以下几个小功能着手介绍,文章最后会给出完整的demo代码. 目录 1. 树图的基本布局和使用 2. 根据返回数据的属性不同,定制不一样的 ...

  6. offsetX与offsetLeft

    offsetX:鼠标指针距离当前绑定元素左侧距离,他并不是相对于带有定位的父盒子的x,y坐标, 记住了,很多博客都解释错了 offsetLeft,offsetTop 相对于最近的祖先定位元素.

  7. Python3.8环境安装PyHook3

    Python3.8环境安装PyHook3 1. 安装python对应版本的pyhook3网  址:https://pypi.org/project/PyHook3/#files如果没有对应版本,请下载 ...

  8. 使用CURL调用接口[*示例*]

    <?php header("content-type:text/html;charset=utf-8"); /* 这是 使用CURL调用接口 */ $ch = curl_in ...

  9. MySQL(七)索引

    索引的数据结构 1 为什么使用索引 索引概述 索引(Index)是帮助MySQL高效获取数据的数据结构.是"排好序的快速查找结构",满足特定的查找算法 索引是在存储引擎中实现的,每 ...

  10. 用 Gaussian Process 建模 state-action 空间相关性,加速 Multi-Fidelity RL

    目录 全文快读 1 intro 3 背景 4 method 4.1 model-based 算法:GP-VI-MFRL 4.2 model-free 算法:GPQ-MFRL 5 experiment ...