您如何确保应用事件以读取模型?

时间:2019-06-06 09:20:58

标签: cqrs event-sourcing get-event-store

这对于预订流中所有事件的投影很容易,您只需将上一个事件的版本保留在读取模型上即可。但是,当投影由多个流合成时,您会怎么做?您是否保留投影中参与的每个流的版本。但是,如果您不订阅所有事件,那么差距又如何呢?您最多可以断言该版本大于最后一个版本。其他人如何处理?您是否响应每个事件并提高版本?

3 个答案:

答案 0 :(得分:1)

对于EventStore,我建议使用$all流作为任何读取模型订阅的默认流。

我使用了类别流,该类别流本质上会生成给定实体类型的快照,但由于读取模型具有不同的用途,所以我停止这样做。

可能不希望使用$all流,因为它还可能获取不是域事件的事件。集成事件可能是一个例子。在这种情况下,向事件合同或元数据添加一些属性可能有助于创建内部(JS)投影,该投影将为域事件或这方面的任何事件类别创建特殊的 all 流,您可以在其中订阅。您还可以使用否定条件,例如,过滤掉所有系统事件以及原始流名称以Integration开头的事件。

答案 1 :(得分:0)

对于每个单独的流,通过从知道正确顺序的数据存储中获取事物,可以使事物保持秩序。一种思考的方式是查询数据存储,然后返回Document Message

回顾格雷格·杨(Greg Young)的Polyglot Data演讲可能会有所帮助。

关于多个流中事件的同步;您需要认识到的是,不同流中的事件本质上是并发的。

如果您将happens-before数据编码到消息中,则可以在不同的流之间获得一些松散的协调。 “事件B是响应事件A而发生的,因此事件A是在事件B之前发生的”。那可以让您部分订购。

如果您确实确实需要在所有地方都进行总排序,那么您就需要研究诸如Lamport Clocks之类的模式。

答案 2 :(得分:0)

除了以正确的顺序处理消息外,还存在重新启动投影后恢复投影的问题-如何确保重启后从正确的位置开始投影?

最简单的选择是使用事件存储或消息代理,它们既可以保证顺序,又可以提供某种全局流位置字段(例如,全局事件编号或带有歧义组件的有序时间戳,例如MongoDB的Timestamp类型)。您直接从商店中提取事件的事件存储(例如eventstore.org或基于数据库构建的本地事件)往往可以保证这一点。同样,某些消息代理(例如Apache Kafka)保证排序(同样,这是基于请求的)。理想情况下,您希望至少订购一次。

此方法限制了写可伸缩性(读取可扩展,可使用只读副本)-您可以通过多种方式在多个事件存储实例之间分流流,然后必须逐个跟踪位置,这增加了一些复杂性

如果您没有这些订购,交货和位置保证,则您的生活会困难得多,并且可能很难使系统完全可靠。您可以:

  • 在收到邮件后,将其保留一会儿,然后再对其进行处理,以允许其他邮件到达
  • 具有用于检测丢失或乱序消息的代码。正如您提到的,只有当您接收到具有全局序列号的所有事件或跟踪所有流的版本号时,此方法才有效,即使那样,在所有情况下也不可靠。