如何重播丢失的事件? [英] How are the missing events replayed?

查看:58
本文介绍了如何重播丢失的事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解有关CQRS和事件源(事件存储)的更多信息。

I am trying to learn more about CQRS and Event Sourcing (Event Store).

我的理解是,在这种情况下通常不使用消息队列/总线-消息总线可用于促进微服务之间的通信,但是通常不专门用于CQRS。但是,我目前的方式-消息总线将非常有用,可以确保读取模型最终同步,从而最终实现一致性,例如当托管读取模型数据库的服务器重新联机时。

My understanding is that a message queue/bus is not normally used in this scenario - a message bus can be used to facilitate communication between Microservices, however it is not typically used specifically for CQRS. However, the way I see it at the moment - a message bus would be very useful guaranteeing that the read model is eventually in sync hence eventual consistency e.g. when the server hosting the read model database is brought back online.

我知道CQRS通常可以接受最终的一致性。我的问题是;读方如何知道它与写方不同步?例如,假设在典型的一天在事件存储中创建了2,000,000个事件,并且1,999,050也被写入读取的存储中。剩余的950个事件由于某个地方的软件错误或托管读取模型的服务器离线几秒钟等而未写入。最终的一致性在这里如何工作?应用程序如何知道重播一天结束时丢失的950个事件或十分钟前由于停机而丢失的x个事件?

I understand that eventual consistency is often acceptable with CQRS. My question is; how does the read side know it is out of sync with the write side? For example, lets say there are 2,000,000 events created in Event Store on a typical day and 1,999,050 are also written to the read store. The remaining 950 events are not written because of a software bug somewhere or because the server hosting the read model is offline for a few secondsetc. How does eventual consistency work here? How does the application know to replay the 950 events that are missing at the end of the day or the x events that were missed because of the downtime ten minutes ago?

I在过去一周左右的时间里,已经在这里阅读了一些问题,这些问题涉及从事件存储中重播的消息,例如此内容: CQRS-用于读取端的事件重播,但是没有人谈论如何这个完成了。我是否需要设置每天运行一次的计划任务并重播自计划任务上一次成功日期以来创建的所有事件?有没有更优雅的方法?

I have read questions on here over the last week or so, which talk about messages being replayed from event store e.g. this one: CQRS - Event replay for read side, however none talk about how this is done. Do I need to setup a scheduled task that runs once per day and replays all events that were created since the date the scheduled task last succeeded? Is there a more elegant approach?

推荐答案

我在项目中使用了两种方法,具体取决于需求:

I've used two approaches in my projects, depending on the requirements:


  1. 同步,进行中读取模型。在事件持久化之后,在相同的请求生存期内,在相同的过程中,将这些事件提供给Readmodels。万一Readmodel发生故障(错误或可捕获的错误/异常),则会记录错误,并会跳过该Readmodel,并向下一个Readmodel传递事件,依此类推。然后跟随Sagas,这可能会生成生成更多事件的命令,并且循环会重复。

  1. Synchronous, in-process Readmodels. After the events are persisted, in the same request lifetime, in the same process, the Readmodels are fed with those events. In case of a Readmodel's failure (bug or catchable error/exception) the error is logged and that Readmodel is just skipped and the next Readmodel is fed with the events and so on. Then follow the Sagas, that may generate commands that generate more events and the cycle is repeated.

当当Readmodel数据的就绪性比故障风险更重要时,Readmodel的故障将为企业所接受。例如,他们希望用户界面中的数据立即可用。

I use this approach when the impact of a Readmodel's failure is acceptable by the business, when the readiness of a Readmodel's data is more important than the risk of failure. For example, they wanted the data immediately available in the UI.

错误日志应该可以在某些管理面板上方便地访问,以便有人查看以防客户报告

The error log should be easily accessible on some admin panel so someone would look at it in case a client reports inconsistency between write/commands and read/query.

如果您的Readmodel相互耦合,即一个Readmodel需要来自另一个规范Readmodel的数据,这也可以工作。尽管这看起来很糟糕,但事实并非如此,这要视情况而定。在某些情况下,您可以使用具有弹性的更新程序代码/逻辑副本进行交易。

This also works if you have your Readmodels coupled to each other, i.e. one Readmodel needs data from another canonical Readmodel. Although this seems bad, it's not, it always depends. There are cases when you trade updater code/logic duplication with resilience.


  1. 异步,互为替代-处理 readmodel更新程序。当我将Readmodel与其他Readmodel完全分开时,将使用此方法,这时Readmodel的故障不会使整个读取面朝下。或当Readmodel需要另一种语言(不同于整体语言)时。基本上,这是一个微服务。当Readmodel内部发生问题时,有必要通知某些权威的更高级别的组件,即通过电子邮件或SMS或其他方式通知管理员。

  1. Asynchronous, in-another-process readmodel updater. This is used when I use total separation of the Readmodel from the other Readmodels, when a Readmodel's failure would not bring the whole read-side down; or when a Readmodel needs another language, different from the monolith. Basically this is a microservice. When something bad happens inside a Readmodel it necessary that some authoritative higher level component is notified, i.e. an Admin is notified by email or SMS or whatever.

Readmodel还应该有一个状态面板,其中包含有关已处理事件的各种指标,如果有差距,是否有错误或警告;它也应该有一个命令面板,管理员可以在任何时候重建它,最好在没有系统停机的情况下进行。

The Readmodel should also have a status panel, with all kinds of metrics about the events that it has processed, if there are gaps, if there are errors or warnings; it also should have a command panel where an Admin could rebuild it at any time, preferable without a system downtime.

在任何方法中,Readmodels应该都易于重建。 / p>

In any approach, the Readmodels should be easily rebuildable.


您将如何选择拉入法和推入法?您是否将消息队列与推送(事件)一起使用

How would you choose between a pull approach and a push approach? Would you use a message queue with a push (events)

我更喜欢基于拉的方法,因为:

I prefer the pull based approach because:


  • 它不使用另一个有状态组件,例如消息队列,另一个必须管理的东西,它消耗资源并且可能(因此将)失败

  • 每个Readmodel以所需的速率消耗事件

  • 每个Readmodel可以随时随时更改其消耗的事件类型

  • 通过从头开始请求所有事件,可以随时轻松地重建每个Readmodel。

  • 事件的顺序与真相完全相同,因为您从真相中提取真相

  • it does not use another stateful component like a message queue, another thing that must be managed, that consume resources and that can (so it will) fail
  • every Readmodel consumes the events at the rate it wants
  • every Readmodel can easily change at any moment what event types it consumes
  • every Readmodel can easily at any time be rebuild by requesting all the events from the beginning
  • there order of events is exactly the same as the source of truth because you pull from the source of truth

在某些情况下,我会选择消息队列:

There are cases when I would choose a message queue:


  • 即使活动商店不存在,您仍需要活动可用

  • 您需要竞争/平行消费者

  • 您不想追踪您所传送的讯息总结消耗完它们后,它们会自动从队列中删除

这篇关于如何重播丢失的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆