cqrs - 在 CQRS 读取端处理乱序事件

标签 cqrs event-sourcing

我读过 Jonathan Oliver 关于处理乱序事件的好文章。

http://blog.jonathanoliver.com/cqrs-out-of-sequence-messages-and-read-models/

The solution that we use is to dequeue a message and to place it in a “holding table” until all messages with a previous sequence are received. When all previous messages have been received we take all messages out of the holding table and run them in sequence through the appropriate handlers. Once all handlers have been executed successfully, we remove the messages from the holding table and commit the updates to the read models.

This works for us because the domain publishes events and marks them with the appropriate sequence number. Without this, the solution below would be much more difficult—if not impossible.

This solution is using a relational database as a persistence storage mechanism, but we’re not using any of the relational aspects of the storage engine. At the same time, there’s a caveat in all of this. If message 2, 3, and 4 arrive but message 1 never does, we don’t apply any of them. The scenario should only happen if there’s an error processing message 1 or if message 1 somehow gets lost. Fortunately, it’s easy enough to correct any errors in our message handlers and re-run the messages. Or, in the case of a lost message, to re-build the read models from the event store directly.



有几个问题特别是关于他如何说我们可以随时向事件商店询问丢失的事件。
  • CQRS 的写入端是否必须公开读取服务
    “要求”重播事件的一面?例如,如果事件 1 不是
    已收到但只有 2、4、3 条 我们可以通过
    从 1 开始重新发布事件的服务?
  • 该服务是否由 CQRS 的写入端负责?
  • 我们如何使用它重新构建读取模型?
  • 最佳答案

    如果您有序列号,那么您可以检测当前事件无序的情况,例如currentEventNumber != lastReceivedEventNumber + 1

    一旦你检测到这一点,你只需抛出一个异常。如果您的订阅者具有“重试”机制,它将尝试在一秒钟左右再次处理此事件。在此期间,很可能会处理较早的事件并且顺序是正确的。如果无序事件很少发生,这是一种解决方案。

    如果您经常遇到这种情况,则需要实现全局锁定机制,这将允许某些事件按顺序处理。
    例如,我们在 MSSQL 中使用 sp_getapplock 来实现某些情况下的全局“临界区”行为。当分布式应用程序的多个部分需要的不仅仅是一个简单的锁时,Apache ZooKeeper 提供了一个框架来处理更复杂的场景。

    关于cqrs - 在 CQRS 读取端处理乱序事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40703348/

    相关文章:

    c# - EventStore 和 RavenDB 持久化 JsonReaderException

    domain-driven-design - 事件溯源 : proper way of rolling back aggregate state

    domain-driven-design - 在 CQRS/Event sourcing 中,是否所有数据都需要在 Command 和 Events 中?

    c# - 使用 CQRS 方法处理并发

    soa - API 与微服务中的事件方法

    projection - 事件溯源 : denormalizing relationships in projections

    c# - 事件源增量 int id

    domain-driven-design - DDD、CQRS/ES 和微服务 是否应该根据微服务的 View 或聚合做出决策?

    CQRS 和最终一致性

    c# - 如何返回验证结果?