这是一个关于在我们使用ES和CQRS与DDD的系统中引入新BC的理论问题。所以没有具体的例子。
通过引入新的BC-s可能会产生一些有趣的问题,这些新的BC-s通过接收和发布域事件与旧的BC-s进行通信。我们在事件存储中已经有域事件的这些问题的根源。当新的BC对那些旧的域事件作出反应时,它将以不同步和/或不按顺序的方式做到这一点。
例如,我们有一个旧的BC A
,我们引入了一个新的BC B
。两者都发布我们称之为a
和b
的域事件。在新系统中,例如b1
的顺序必须始终在a1
之后,而在a2
之前。当我们在事件存储中已经有a1
,a2
,a3
序列时,我们可以做些什么?我们应该在b1
之后注入a1
等等吗?这是一个巨大的事件存储可行的解决方案吗?肯定需要很长时间才能逐一重播所有旧事件并对其作出反应。我们如何通过处理新创建的b1
事件来阻止向客户发送电子邮件,该事件会对5年前的主题做出反应?是否有防止这类问题的模式?
答案 0 :(得分:3)
我们在事件存储中已经有域事件的这些问题的根源。
如果您向现有系统引入新的BC B
,则表示系统在没有B
的情况下正常运行。上述陈述清楚了这一点,并产生以下后果:
B
为响应来自A
的事件而生成的事件。没有其他系统应该根据这些事件采取行动,因为它们是 artificial 。B
。您需要事先做的唯一事情就是让B
与系统的当前状态保持同步。B
同步如果您相应地设计B
,这并不困难。
B
而不从B
发布响应事件。您需要如果您使用事件来源,当然要在内部保留B
个事件,但不要发布它们。此外,请确保B
不会修改世界状态通过其他方式重放模式,例如不要发送电子邮件。B
切换到实时模式。现在B
使用系统中的新事件并发布自己的事件。当您对所有域事件使用统一事件存储时,您提及的事件排序问题只是一个问题,并且还使用该存储来发布事件。如果是这种情况,那么您需要将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的模式。