Domain driven design 丢失的事件是如何重播的?

Domain driven design 丢失的事件是如何重播的?,domain-driven-design,cqrs,event-sourcing,Domain Driven Design,Cqrs,Event Sourcing,我试图了解更多关于CQR和事件源(事件商店)的信息 我的理解是,在这种情况下通常不使用消息队列/总线-消息总线可用于促进微服务之间的通信,但通常不专门用于CQR。然而,我目前的看法是,消息总线非常有用,可以确保读取模型最终同步,从而最终保持一致性,例如,当承载读取模型数据库的服务器重新联机时 我理解,CQR通常可以接受最终的一致性。我的问题是,;读端如何知道它与写端不同步?例如,假设在一个典型的日子里,在事件存储中创建了2000000个事件,并且1999050也被写入了读取存储。其余的950个事

我试图了解更多关于CQR和事件源(事件商店)的信息

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

我理解,CQR通常可以接受最终的一致性。我的问题是,;读端如何知道它与写端不同步?例如,假设在一个典型的日子里,在事件存储中创建了2000000个事件,并且1999050也被写入了读取存储。其余的950个事件没有写入,因为某个地方有软件错误,或者因为承载读取模型的服务器离线了几秒钟SETC。最终的一致性在这里是如何工作的?应用程序如何知道重播在一天结束时丢失的950个事件或十分钟前由于停机而丢失的x个事件

在过去一周左右的时间里,我在这里读到了一些问题,其中谈到了从事件存储中重播的消息,例如:这一条:,但是没有人谈到如何做到这一点。是否需要设置每天运行一次的计划任务,并重播自计划任务上次成功之日起创建的所有事件?有没有更优雅的方法呢?

这篇文章可能会有所帮助

应用程序如何知道重播在一天结束时丢失的950个事件或十分钟前由于停机而丢失的x个事件

所以这里有两种不同的方法

其中一个可能比您预期的要简单—每次需要重建读取模型时,只需从流中的事件0开始

是的,这方面的规模最终会很糟糕,所以你不会希望这成为你的第一个战略。但请注意,它确实有效

对于具有不太令人尴尬的缩放特性的更新,通常的想法是读取模型跟踪有关用于构建前一个模型的流位置的元数据。因此,来自read模型的查询变成“自事件#1999050以来发生了什么”

在的情况下,调用可能类似于

EventStore.ReadStreamEventsForwardAsync(stream, 1999050, 100, false)

应用程序不知道由于错误它没有处理某些事件

首先,我不理解为什么您假设写端写入的事件数必须等于读端处理的事件数。某些投影可能订阅同一事件,而某些事件在读取端可能没有订阅


如果投影/基础结构中出现错误,导致某个投影无效,您可能需要重建此投影。在大多数情况下,这将是一种手动干预,将投影的检查点重置为0(时间开始),因此投影将从头开始从事件存储中拾取所有事件,并再次重新处理所有事件

事件存储应该在所有事件中都有一个全局序列号,比如从1开始

每个投影都有一个沿序列号的位置跟踪。这些投影类似于逻辑队列

可以清除投影的数据并将位置重置回0,然后应重新生成投影


在您的情况下,投影由于某种原因失败,例如服务器在位置1999050处脱机,但当服务器再次启动时,投影将从这一点继续进行。

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

  • 同步、进程中读取模型。事件被持久化后,在相同的请求生存期内,在相同的过程中,Readmodels将收到这些事件。如果某个Readmodel出现故障(bug或可捕获的错误/异常),则会记录该错误,并跳过该Readmodel,然后向下一个Readmodel提供事件等。然后按照传说进行,这可能会生成生成更多事件的命令,并重复该循环
  • 当业务部门可以接受Readmodel故障的影响时,当Readmodel数据的就绪性比故障风险更重要时,我使用这种方法。例如,他们希望数据在UI中立即可用

    错误日志应该可以在一些管理面板上轻松访问,以便有人在客户端报告写/命令和读/查询之间不一致时查看它

    如果您的Readmodels彼此耦合,也就是说,一个Readmodel需要来自另一个规范Readmodel的数据,那么这种方法同样有效。虽然这看起来很糟糕,但事实并非如此,这要看情况而定。在某些情况下,您需要将更新程序代码/逻辑重复与恢复能力进行权衡

  • 异步,在另一个进程中readmodel updater。当我使用Readmodel与其他Readmodels的完全分离时,当一个Readmodel的故障不会使整个读取端下降时,就会使用这个选项;或者当一个Readmodel需要另一种不同于monolith的语言时。基本上这是一个微型服务。当Readmodel内部发生错误时,必须通知某个权威的更高级别组件,即通过电子邮件或SMS或其他方式通知管理员 Readmodel还应该有一个状态面板,其中包含关于其处理的事件的各种度量,如果存在间隙,如果存在错误或警告;它还应该有一个命令面板,管理员可以随时重建它,最好不要让系统停机

    在任何方法中,Readmodels都应该易于重建

    你会如何选择拉进近和推进近?您会使用带有推送(事件)的消息队列吗

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

    • 是的