【发布时间】:2016-09-05 16:09:31
【问题描述】:
我的 CQRS/ES 设计中有一个计时案例。为了便于讨论,让我们基于微软的 关于这个主题的示例,会议管理 (https://msdn.microsoft.com/en-us/library/jj554200.aspx)。
两个上下文:会议管理和订单管理。在会议管理中,您可以创建会议并更改其属性(例如:最大席位)。会议管理通过事件总线与订单管理进行通信。通过这种方式,订单管理知道何时创建新会议,并在其上下文中实例化跟踪对象(座位可用性)。诸如“最大座位可用性从 100 减少到 80”之类的事件也通过事件总线从 conf mgmt 传递到 order mgmt。
- 假设在第 1 分钟创建了会议(最多 20 个座位)。
- 在第 4 分钟,事件到达订单管理上下文,因此创建了座位可用性。
- 在第 7 分钟,用户下了订单(通过订单管理),购买了全部 20 个席位。 (这也应该从 - 订单管理到 conf 管理进行沟通,以便 conf 管理员可以做出正确的决定)。
- 在第 8 分钟,会议管理员更改了席位可用性(在会议管理上下文中),将其减少到 15 个。
- 订单管理的通知(关于已售出所有 20 个座位的事实)在第 9 分钟到达。
- 现在该怎么办? (在会议上?当您已经收到 20 个席位的付款时,您不应该将席位减少到 15 个;但是在第 8 分钟管理员不知道这件事)。
这是第一种情况。
现在是第二种情况:
- 假设在第 1 分钟创建了会议(最多 20 个座位)。
- 在第 4 分钟,事件到达订单管理上下文,因此创建了座位可用性。
- 在第 6 分钟,会议管理员更改了席位可用性(在会议管理上下文中),将其减少到 15 个。
- 在第 7 分钟,用户下了订单(通过订单管理),购买了全部 20 个席位。他不知道可用性已减少到 15,因为此时活动尚未到来。
- 在第 10 分钟,来自 conf mgmt 的通知终于到达。
- 现在该怎么办?
这些问题源于技术问题(事件传输延迟)。有没有纯粹的技术方法来避免它? 如果没有,克服它的商业方式/设计方式是什么?
补充说明:我知道这是与 CQRS/ES 架构相关的最终一致性问题。在单一上下文中,这可能更容易解决,因为您可以为此设置命令(例如:撤消)。但是,在有界上下文之间你不应该传递命令,你只与事件通信,我认为事件不是这个的正确抽象(因为它代表了发生的事情)。还是我错过了什么?
补充说明:也许这篇文章可以提供更多上下文和提示解决方案,但对于这个问题中的这个特定情况,我不这么认为(这不是关于无序消息)。 http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-i-of-ii/
补充说明:或者也许......,在订单管理上下文中,我们可以简单地排队购买座位的命令,直到我们知道我们从会议管理上下文中收到了最新/最后一个事件。我的意思是,事件带有时间戳,对吗?因此,我们可以将我们从 conf mgmt 上下文中收到的最后一个事件的时间戳与座位购买命令的时间戳进行比较。如果最后一个事件的 ts 小于命令的 ts,我们简单地推迟命令的执行,直到我们收到一个 ts 大于命令的 ts 的事件。这种事情将是流程经理(saga)的责任。
这行得通吗?这是正确的方法吗?
添加注释:相关线程> Implementing a Saga/Process Manager in a CQRS http application 。我认为我们在流程管理器方面走在正确的轨道上。正如回答者所说:“您根本不会立即回答“订单确认”。看看亚马逊和其他购物网站是如何做到的:提交订单后,您只会收到“订单接受确认”(例如,HTTP Code 202 Accepted )。”。
由您的流程管理器的逻辑来决定何时实际执行命令(基于特定条件、可能是内部状态,或者在这种情况下是从其他上下文接收到的最新事件)。
有什么意见吗?
谢谢, 拉卡
【问题讨论】:
-
在你描述的场景中,业务说做什么?询问领域专家在这种情况下应该发生什么
标签: cqrs event-sourcing