这对于预订流中所有事件的投影很容易,您只需将上一个事件的版本保留在读取模型上即可。但是,当投影由多个流合成时,您会怎么做?您是否保留投影中参与的每个流的版本。但是,如果您不订阅所有事件,那么差距又如何呢?您最多可以断言该版本大于最后一个版本。其他人如何处理?您是否响应每个事件并提高版本?
答案 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)保证排序(同样,这是基于请求的)。理想情况下,您希望至少订购一次。
此方法限制了写可伸缩性(读取可扩展,可使用只读副本)-您可以通过多种方式在多个事件存储实例之间分流流,然后必须逐个跟踪位置,这增加了一些复杂性
如果您没有这些订购,交货和位置保证,则您的生活会困难得多,并且可能很难使系统完全可靠。您可以: