将新BC引入DDD应用程序的最佳做法是什么?

时间:2015-11-24 21:32:21

标签: domain-driven-design cqrs event-sourcing bounded-contexts

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

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

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

2 个答案:

答案 0 :(得分:3)

问题分析

  

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

如果您向现有系统引入新的BC B,则表示系统在没有B 的情况下正常运行。上述陈述清楚了这一点,并产生以下后果:

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

B同步

如果您相应地设计B,这并不困难。

  1. 首先,您需要一个重播模式机制,将所有域事件导入B 而不从B发布响应事件。您需要如果您使用事件来源,当然要在内部保留B个事件,但不要发布它们。此外,请确保B不会修改世界状态通过其他方式重放模式,例如不要发送电子邮件。
  2. 然后,将B切换到实时模式。现在B使用系统中的新事件并发布自己的事件。
  3. 当您对所有域事件使用统一事件存储时,您提及的事件排序问题只是一个问题,并且还使用该存储来发布事件。如果是这种情况,那么您需要将B个事件标记为"内部"在重播阶段,将它们从发布机制中隐藏起来。

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

答案 1 :(得分:1)

首先,DDD不需要事件采购。

  

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

即使在同一个组件(有界上下文)中,事件也可能出现故障。交易完整性仅在聚合中得到保证。

  

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

没关系。顺便说一句,除非您使用SERIALIZABLE isolation(或其特定于供应商的等效项),否则您不能使用SQL数据库。 Protip:它在性能上非常沉重,默认情况下从未启用过;因此你没有使用它。

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

  

其他事务无法插入具有键值的新行   落在当前任何语句读取的键范围内   交易直到当前交易完成。

此外,虽然事件存储不应该有多个事件副本,但事件(以及其他消息,如命令)可能会在组件之间多次到达。

  

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

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

  

我们能做什么,

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

  • 如果您正在从Web服务,Feed,DB表中读取事件;它永远不会消失;在相关事件发生之前,您可能会忽略该事件。

  • 同样,您可以将事件放回到它所来自的消息队列中,直到它相关为止。

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

  • Is there a real race condition, at all?