【发布时间】:2015-08-13 01:55:35
【问题描述】:
我正在启动一个新应用程序,我想使用 cqrs 和事件源。我想到了重播事件以重新创建聚合和快照以在需要时加速,在内存模型、缓存等中使用。
我的问题是关于我不想保留在内存中的大型读取模型。假设我有一个销售产品的应用程序,我想监听诸如“ProductRegistered”“ProductSold”之类的事件流,并在关系数据库中构建一个表,用于报告或与另一个系统集成。假设有很多记录,并且此表可能需要几秒钟到几分钟的时间来截断/重建,并且应用程序会出于多种目的导出数十个这样的预测。
在这种情况下如何处理预测的一致性?
使用内存中的数据,回放事件非常简单和快速。但我觉得保存在磁盘中的外部预测重建速度会慢得多。
我是否应该始终使用 TRUNCATE TABLE + 重建每个外部投影来启动我的应用程序?随着时间的推移,这对我来说似乎不切实际,但我可能会担心我还没有遇到的问题。
由于表本身就像一个快照,我可以保留一个“控制表”来判断哪个事件是我为该投影处理的最后一个事件,因此我可以只重播需要的内容。但是如果应用程序或数据库崩溃,我担心会出现不一致。看来检查表的一致性和重建会是一样的,这又指向了解决方案1。
您将如何以可随时间推移进行维护的方式来处理它?有没有更好的解决方案?
非常感谢。
【问题讨论】:
-
读取模型应该(在大多数情况下)存储在数据库中,而不是留在内存中。如果您担心由于应用程序崩溃而无法同步,那么您应该考虑使用 MSMQ 来实现事件总线。
-
这并不能真正解决任何问题,即使使用消息队列,也存在投影可能不同步的情况。问题不在于交通。
-
好的,如果读取模型不同步,我会将所有事件重播到读取模型。这将需要时间,具体取决于硬件、数据库等。您可以使用 事务性 MQ 最小化这种“不同步”,因为这只会在事件存储完成后崩溃发生时发生在事件发送到 MQ 之前写入。而这只是一个很小的时间间隔。
-
如您所见,这是关于如何管理从事件存储到投影的事件传输;o)
-
好的,我现在明白你在说什么了。如果队列是事务性的,我只会在写入投影表后确认消息接收。这解决了交付保证,您不必在应用重新启动时截断表以确保一致性。对于任何其他问题,你会重建而不关心它需要多少时间,因为它偶尔会发生。是这样吗?您可能应该写一些东西作为答案而不是评论。
标签: cqrs event-sourcing