saga中的saga(A Saga on Sagas)

此文翻译自msdn,侵删。

原文地址:https://msdn.microsoft.com/en-us/library/jj591569.aspx

Process Managers, Coordinating Workflows, and Sagas

分清术语

saga这个名词通常被用在CQRS的讨论中,它是指一段在限定上下文(bounded contexts )和聚合(aggregates)之间起协作和路由(coordinates and routes )消息作用的代码。然而,在这个指南中我们更喜欢用Process manager这个词语去表示saga。有两个原因:

  • 之前已经有了一个广泛被熟知的名词saga,这个saga和CQRS中的saga有着不同的含义。
  • process manager 是一个更合适用来描述saga在这里扮演角色的名词。

虽然saga经常在CQRS模式中见到,然而它已经在这之前有了其自己的含义。在这个指南中我们使用process manager 以便于和saga之前的含义区分开来。

saga,与分布式相关,最早被定义在Hector Garcia-Molina和Kenneth Salem的论文"Sagas"中。这篇论文提出了一个saga机制来作为分布式事务的替代品以解决长时间运行的分布式事务(long-running process)的问题。这篇论文认为业务过程经常由很多步骤组成,每个步骤都涉及一个事务,如果将这些事务组成一个分布式事务,就可以实现总体一致(overall consistency )。然而在长时间运行的分布式事务中,使用分布式事务会影响效率和系统的并发处理能力,因为在执行分布式事务的时候会有锁产生。

注意:

saga通过确保每一个业务过程都有修正事务(compensating transaction)来减少了系统对分布式事务的依赖。在这种方式下,如果业务过程遇到了错误的情况并且无法继续,它就可以执行修正事务来修正已经完成的步骤。这种在业务流程中去撤销已经完成的工作的方式保证了系统的一致性。

尽管我们已经选择使用process manager这个名词了,sagas仍然在实现CQRS系统中的限定上下文中扮演着一些角色。比如说,你可能会希望看到process manager在一个限定上下文中的聚合中路由消息,你也可能会希望看到saga管理一个在多个限定上下文中长时间运行的业务过程。

以下的几个部分描述了process manager,这个是我们在我们的CQRS之旅项目中对saga的定义。

注意:

在使用process manager之前,我们的团队曾经有一段时间使用coordinating workflow 这个名词。这种模式在Gregor Hohpe 和 Bobby Woolf的书"Enterprise Integration Patterns”中有所描述。

Process Manager

这一节概括了我们的process manager定义。在描述process manager之前有一段简短的关于CQRS使用消息(messages)在聚合和限定上下文中通讯的回顾。

消息和CQRS

当你实现CQRS模式的时候,你可能会思考两种类型的消息如何在你的系统中交换数据:command和事件。

command是一种请求,他们请求系统去执行一个任务或者动作。例如“预定两个X会议的座位”或者“把演讲者Y分配到Z室”。command通常只被一个接收者执行一次。

事件是一种通知,他们告诉系统中一些它们感兴趣的部分:有一些事情已经发生了。例如“支付被拒绝了”或者“产生了X类型座位”。注意他们使用的是过去式——事件已经被产生并且可能有许多订阅者。

通常来说,command被发送到同一个限定上下文中。事件的订阅者可能在它们发布的限定上下文中,或者在其他的限定上下文中。

引用指南中的"A CQRS and ES Deep Dive"章节详细地介绍了这两种不同的消息类型。

process manager是什么?

在一个复杂系统建模中,你可能已经使用了聚合和限定上下文,他们可能有一些包含了很多聚合的业务过程,或者在一个限定上下文中有很多的聚合。在这个业务过程中,许多不同类型的消息被交换。例如,在一个会议管理系统中,有一个预定座位的业务过程包含了order聚合,一个reservation聚合和一个payment的聚合。他们必须结合起来以保证一个客户能够完成预定交易。

图1表示了一个简化的消息场景,在这个场景中这些聚合互相交互来完成这个订单。数字表明了消息流转的顺序

注意:

这个图并没有展示这个实现如何处理订单

图1

不使用process manager的订单处理过程

在图1展示的例子中,每一个聚合都向与流程下一步相关的聚合发送一个相应的command。Order聚合首先发送一个MakeReservation 的command给Reservation聚合来预定客户需要的位置。在座位被预定之后,Reservation聚合就会发送一个SeatsReserved事件通知Order聚合,然后Order聚合就会向Payment聚合发送一个MakePayment的command。如果付款成功,Order聚合就会生成一个OrderConfirmed的事件通知Reservation聚合确定座位已经被预定,并且通知客户订单完成。

图2

使用process manager 的订单业务过程

图2中展示的例子描述了和图1一样的业务过程,但是这次使用了process manager 。现在,这些消息通过process manager 来管理,而不是聚合根直接向另外一个聚合跟发送消息。

这样明显地将整个过程复杂化了:这个过程现在多了一个对象(process manager )和一些消息。然而这些都是有益的。

首先,聚合不再需要知道流程的下一步是什么。之前Order聚合必须知道在完成预定之后,它需要尝试着去向Payment 聚合发送一个消息来完成一个支付。现在它只要报告一个订单已经生成就可以了。

然后,这个消息流的处理被限定在一个地方,那就是process manager,而不是分散到这些聚合中。

在一个类似于图1或者图2的简单业务过程中,这么做的好处很小。然而如果你有一个包含六个聚合和数十个消息的业务过程,这么做的好处就很明显了。这尤其在一个系统中某个业务容易发生变化的部分中更加明显:在这种情况下,业务的改变更容易被限定在有限的对象中。

在图3中,为了描述这个观点,我们向其中引入了一个等待列表。如果一些作为预定请求不能被预定,那么系统就会把这些请求添加到一个等待列表中。在发布SeatsReserved 事件(报告还有多少座位可以被预定)功能的基础上,我们为Reservation 聚合新增了一个发布SeatsNotReserved 事件的功能去报告还有多少座位不可以被预定。process manager可以向WaitList 聚合中发送一个command来添加一个待处理请求。

图3

包含一个process manager 和一个等待列表的订单业务过程

很重要的一点需要注意,process manager本身不包含任何业务逻辑。它仅仅路由消息,或者在一些情况下转换消息类型。例如,当它接受到一个SeatsNotReserved事件,它发布一个AddToWaitList的command。

我应该什么时候使用process manager?

有两个重要的使用process manager的原因:

  • 当你在一个限定上下文使用很多事件和command的时候,难以把聚合之间的交互(point-to-point interactions between aggregates)统一管理。
  • 当你想要在限定上下文中更容易地去修改消息的路由。一个process manager会提供一个单独的路由定义位置。

我应该什么时候不使用process manager?

下面列了不适用process manager的原因:

  • 如果你的限定上下文仅包含很少数量的使用少量的消息的聚合类型。
  • 你不可以在你的领域中使用process manager来实现任何业务逻辑。业务逻辑应该在相应的聚合类中。

sagas和CQRS

尽管我们在之前的章节中已经选择了process manager这个名词,saga仍然在使用CQRS模式的系统中扮演一定的角色。比如说,你可能会希望看到process manager在一个限定上下文中的聚合中路由消息,你也可能会希望看到saga管理一个在多个限定上下文中长时间运行的业务过程。

时间: 2024-10-01 04:49:31

saga中的saga(A Saga on Sagas)的相关文章

Saga的实现模式——控制者(Saga implementation patterns – Controller)

https://lostechies.com/jimmybogard/2013/03/14/saga-implementation-patterns-controller/ 之前的文章中我们介绍了观察者模式.在这个模式里,saga在整个业务中是一个被动的参与者,和大多数快餐店完成订单流程类似.但是并不是所有的快餐店都用这种方式,还有更多的更有效率的方式能够完成这种工作. 我们可以让我们的saga在整个业务过程中扮演一个主动的角色.saga直接控制整个流程,向特定的工作者发出command,等待回

架构模式: Saga

架构模式: Saga 上下文 您已应用每服务数据库模式.每个服务都有自己的数据库.但是,某些业务事务跨越多个服务,因此您需要一种机制来确保服务之间的数据一致性.例如,假设您正在建立一个客户有信用额度的电子商务商店.申请必须确保新订单不会超过客户的信用额度.由于订单和客户位于不同的数据库中,因此应用程序不能简单地使用本地ACID事务. 问题 如何跨服务维护数据一致性? 要点 可以不选择2PC 结论 实现跨越多个服务的每个业务事务作为传奇.传奇是一系列本地交易.每个本地事务都更新数据库并发布消息或事

[转帖]如何选择分布式事务形态(Fescar、TCC、SAGA、补偿、基于消息的最终一致

如何选择分布式事务形态(Fescar.TCC.SAGA.补偿.基于消息的最终一致 https://blog.csdn.net/zhangjunli/article/details/100015236 各种形态的分布式事务分布式事务有多种主流形态,包括: 基于消息实现的分布式事务基于补偿实现的分布式事务基于TCC实现的分布式事务基于SAGA实现的分布式事务基于2PC实现的分布式事务这些形态的原理已经在很多文章中进行了剖析,用“分布式事务”关键字就能搜到对应的文章,本文不再赘述这些形态的原理,并将重

React Native工程中TSLint静态检查工具的探索之路

建立的代码规范没人遵守,项目中遍地风格迥异的代码,你会不会抓狂? 通过测试用例的程序还会出现Bug,而原因仅仅是自己犯下的低级错误,你会不会抓狂? 某种代码写法存在问题导致崩溃时,只能全工程检查代码,这需要人工花费大量时间Review代码,你会不会抓狂? 以上这些问题,可以通过静态检查有效地缓解! 静态检查(Static Program Analysis)主要是以不运行程序的方式对于程序源代码进行检查分析的技术,而与之相反的就是动态检查(Dynamic Program Analysis),通过实

CQRS FAQ (翻译)

我从接触ddd到学习cqrs有6年多了, 其中也遇到了不少疑问, 也向很多的前辈牛人请教得到了很多宝贵的意见和建议. 偶尔的机会看到国外有个站点专门罗列了ddd, cqrs和事件溯源的常见问题. 其中很多也是我一路过来都曾遇到过的. 这是原站地址http://www.cqrs.nu/Faq. 在ENODE群中不少新学习cqrs的朋友都会遇到一些类似的入门问题, 作为群管理员的我也想为群里朋友做点贡献, 所以有了翻译一下CQRS FAQ的念头, 并加入一些自己的理解, 希望对大家会有所帮助. PS

CQRS(命令查询职责分离)和 EDA(事件驱动架构)

转载CQRS(命令查询职责分离)和 EDA(事件驱动架构) 上一篇:<IDDD 实现领域驱动设计-SOA.REST 和六边形架构> 阅读目录: CQRS-命令查询职责分离 EDA-事件驱动架构 Domin Event-领域事件 Long-Running Process(Saga)-长时处理过程 Event Sourcing-事件溯源 CQRS Journey-微软示例项目 ENode-netfocus 实践项目 存在即是理由,每一种架构的产生都会有一种特定的场景,或者解决某一种实际应用问题,经

Redux-Saga学习心得

# Redux Saga ## 简述- Reducers负责处理action的state更新:- Sagas负责协调那些复杂或异步的操作. ## 安装 npm install --save redux-saga ```// ...import { createStore, applyMiddleware } from 'redux'import createSagaMiddleware from 'redux-saga' // ...import { rootSaga } from './sag

Apache RocketMQ 正式开源分布式事务消息

近日,Apache RocketMQ 社区正式发布4.3版本.此次发布不仅包括提升性能,减少内存使用等原有特性增强,还修复了部分社区提出的若干问题,更重要的是该版本开源了社区最为关心的分布式事务消息,而且实现了对外部组件的零依赖.接下来,本文将详细探秘RocketMQ事务消息的设计原理以及实现机制. 一.需求缘起 在微服务架构中,随着服务的逐步拆分,数据库私有已经成为共识,这也导致所面临的分布式事务问题成为微服务落地过程中一个非常难以逾越的障碍,但是目前尚没有一个完整通用的解决方案. 其实不仅仅

React手稿之 React-Saga

Redux-Saga redux-saga 是一个用于管理应用程序副作用(例如异步获取数据,访问浏览器缓存等)的javascript库,它的目标是让副作用管理更容易,执行更高效,测试更简单,处理故障更容易. redux-saga相当于一个放置在action与reducer中的垫片. 之所以称之谓副作用呢,就是为了不让触发一个action时,立即执行reducer.也就是在action与reducer之间做一个事情,比如异步获取数据等. redux-saga使用了ES6中的Generator功能,