3

这是一个关于在我们使用 ES 和 CQRS 和 DDD 的系统中引入新 BC 的理论问题。所以不会有具体的例子。

引入新的 BC-s 可能会出现有趣的问题,新的 BC-s 通过接收和发布域事件与旧的通信。这些问题的根源在于我们在事件存储中已经有了领域事件。当新的 BC 对那些旧的域事件做出反应时,它会以不同步和/或失序的方式进行。

例如,我们有一个旧的 BCA并且我们引入了一个新的 BC B。两者都发布我们称之为a和的领域事件b。例如,在新系统中,订单事项b1必须始终在之后a1,但在之前a2。当我们已经在事件存储中拥有a1, a2,序列时,我们能做什么?a3我们应该注射b1之后a1等等吗?这是一个巨大的事件存储的可行解决方案吗?将所有旧事件一一重播并做出反应肯定需要很长时间。我们如何通过处理新创建的b1事件来防止向客户发送电子邮件,该事件对 5 年前的主题作出反应?是否有防止此类问题的模式?

4

2 回答 2

3

问题分析

这些问题的根源在于我们在事件存储中已经有了领域事件。

如果您将新的 BC 引入B现有系统,则意味着该系统在没有B. 上述陈述清楚地表明了这一点,并具有以下后果:

  • 不需要发布为响应来自的事件而产生的事件B A任何其他系统都不应该根据这些事件采取行动,因为它们是人为的。
  • 您可以随时选择直播B。您需要事先做的唯一一件事就是B与系统的当前状态保持同步。

同步B_

如果您进行相应的设计,这并不难B

  1. 首先,您需要一个重播模式机制来将所有域事件导入其中,而无需从响应中B 发布事件。BB如果您使用事件源,您当然需要在内部保留s 事件,但不要发布它们。另外,请确保B不要在重播模式下通过其他方式修改世界状态,例如不要发送电子邮件。
  2. 然后,切换B实时模式。现在B使用来自系统的新事件并发布自己的事件。

您提到的事件排序问题仅在您为所有域事件使用统一事件存储并且还使用该存储从中发布事件时才会出现问题。如果是这种情况,那么您需要B在重播阶段将 s 事件标记为“内部”,并将它们从发布机制中隐藏起来。

注意:如果B是一个纯粹的反应式 BC(这可能是一个非常简单的 BC 的情况),那么你甚至不需要重播的东西。但大多数 BC 可能会这样做。

于 2015-11-25T08:56:22.377 回答
1

首先,DDD 不需要事件溯源。

我们有一个旧的 BC A,我们引入了一个新的 BC B。两者都发布了我们称为 a 和 b 的域事件。在新系统中,顺序很重要,例如 b1 必须始终在 a1 之后,但在 a2 之前。

即使在同一个组件(有界上下文)中,事件也可能是无序的。事务完整性仅在聚合中得到保证。

当我们在事件存储中已经有了 a1、a2、a3 序列时?

没关系。顺便说一句,除非您在SERIALIZABLE 隔离(或其供应商特定的等价物)中工作,否则您对 SQL 数据库没有此保证。Protip:它对性能的要求如此之高,以至于默认情况下从未启用它;因此你没有使用它。

特别注意上面链接中的这部分:

在当前事务完成之前,其他事务不能插入键值落在当前事务中的任何语句读取的键范围内的新行。

此外,尽管事件存储不应具有事件的多个副本,但事件(和其他消息,例如命令)可能会在组件之间多次到达。

我们应该在 a1 之后注入 b1 吗?

由于您的组件应该能够处理乱序(和重复事件)没有

我们能做什么,

取决于用于集成组件的技术和消息的语义:

  • 如果您正在从 Web 服务、Feed、DB 表中读取事件;这样它永远不会消失;您可能可以忽略某个事件,直到它相关为止。

  • 等效地,您可以将事件放回它来自的消息队列,直到它相关为止。

  • 您可以使用称为 Saga/Process Manager 的模式。

  • 有真正的比赛条件吗?

于 2015-11-25T15:41:49.077 回答