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. 近期调研和使用 zeromq 与 cppzmq 的一些问题

    关于message 消息分片 消息分片的发送 消息分片允许将多个消息封装成一条消息.在发送自定义协议数据时,我们经常需要在消息前"填充"一个包头.如下代码,在发送的时候加上 zmq ...

  2. ThreadLocal 类

    更多内容,访问 IT-BLOG ThreadLocal 并不是一个Thread,而是 ThreadLocalVariable(线程局部变量).也许把它命名为 ThreadLocalVar更加合适.线程 ...

  3. Kafka 之 HW 与 LEO

    更多内容,前往 IT-BLOG HW(High Watermark):俗称高水位,它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个 offset 之前的消息.分区 ISR 集合中的每 ...

  4. 关于js类的继承

    原型链继承 特点:基于原型链,既是父类的实例,也是子类的实例. 缺点: 无法实现多继承. 构造继承 特点: 可以实现多继承. 缺点: 之能继承父类实例的属性和方法,不能继承原型上的属性和方法. 实例继 ...

  5. OSM(OpenStreetMap)全球路网数据下载方式介绍

      本文对OpenStreetMap(OSM)网页与各类OSM数据的多种下载方式加以详细介绍,并对不同数据下载方式加以对比.   OSM数据包含道路与铁路路网.建筑.水体.土地利用.兴趣点.行政区边界 ...

  6. QtDesigner安装

    QtDesigner简单介绍 Qtdesigner是Python设计里面一个非常实用的工具,使得人们编写qt界面可以不仅仅是使用纯代码,而可以在可视化的基础上设置,非常方便. QtDesigner安装 ...

  7. 五月九号java基础知识点

    1.哈希集合元素不按顺序排序,若要排序使用LinkedHashSet类2.树集合类不仅实现Set接口,还实现java.lang.SortedSet接口来实现排序操作3.TreeSet<Strin ...

  8. day107:MoFang:Python操作MongoDB数据库:PyMongo

    目录 PyMongo 1.PyMongo安装 2.数据库连接 3.数据库管理 4.集合管理 5.文档管理 PyMongo 1.PyMongo安装 pip install pymongo 2.数据库连接 ...

  9. VMware Workstation Pro许可证

    永久许可证:ZC10K-8EF57-084QZ-VXYXE-ZF2XF 备用许可证: UF71K-2TW5J-M88QZ-8WMNT-WKUY4 AZ7MK-44Y1J-H819Z-WMYNC-N7A ...

  10. scikit-learn 中 Boston Housing 数据集问题解决方案

    scikit-learn 中 Boston Housing 数据集问题解决方案 在部分旧教程或教材中是 sklearn,现在[2023]已经变更为 scikit-learn 作用:开源机器学习库,支持 ...