我读过 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.
有几个问题特别是关于他如何说我们可以随时向事件商店询问丢失的事件。
“要求”重播事件的一面?例如,如果事件 1 不是
已收到但只有 2、4、3 条 我们可以通过
从 1 开始重新发布事件的服务?
最佳答案
如果您有序列号,那么您可以检测当前事件无序的情况,例如currentEventNumber != lastReceivedEventNumber + 1
一旦你检测到这一点,你只需抛出一个异常。如果您的订阅者具有“重试”机制,它将尝试在一秒钟左右再次处理此事件。在此期间,很可能会处理较早的事件并且顺序是正确的。如果无序事件很少发生,这是一种解决方案。
如果您经常遇到这种情况,则需要实现全局锁定机制,这将允许某些事件按顺序处理。
例如,我们在 MSSQL 中使用 sp_getapplock 来实现某些情况下的全局“临界区”行为。当分布式应用程序的多个部分需要的不仅仅是一个简单的锁时,Apache ZooKeeper 提供了一个框架来处理更复杂的场景。
关于cqrs - 在 CQRS 读取端处理乱序事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40703348/