具有事件驱动架构但没有事件源的 CQRS

CQRS with event driven architecture but without event sourcing

在发布这篇文章之前,我参考了许多网站和学习平台,但看到了使用事件溯源开发 CQRS 的类似模式。再次要有适当的事件,您需要遵循 DDD 模式。我有以下问题。

  1. 我们能否仅通过从写入模型发布事件并使用事件处理程序在读取模型中使用它并更新读取数据库来保持读写数据库同步
  2. 如果我的要求是只查看最新数据,为什么需要事件溯源和事件重播
  3. 我可以在事件到达事件处理程序时管理数据审计
  4. 我可以根据时间戳对消息进行版本控制,以防竞争条件。
  5. 请通过第 1、3 和 4 步进行解释,我是否仍在遵循 CQRS 模式?

仅供参考,我正在使用 .NetCore 3.1、AWS Lambda 服务、MassTransit 作为 MessageBus 和 SQS 作为传输。

提前致谢。

一旦您拥有用于读取和写入的单独数据模型,您就在遵循 CQRS。事件溯源并非严格要求。

请注意,以一种保持读取端与写入端的预期最终一致性的方式在应用程序中完成 1 是相当困难的。您需要确保当且仅当写入数据库的更新成功时才发布事件(即永远不会出现您发布但不更新的情况,也不会出现您更新但不发布的情况:如果其中任何一个可能发生,您不能保证最终的一致性)。例如,如果您的应用程序进行了更新,并且如果更新成功,则发布事件,如果在更新和发布之间进程崩溃(或者您的网络与数据库分区,或者您的 lambda 超出其时间限制......)会发生什么?

确保最终一致性的两种最佳方法是

  • 通过订阅发布的事件流来更新写端数据库
  • 在写入端 DB 上使用更改数据捕获来生成要发布的事件

第一个至少非常接近于事件溯源(无论哪种方式都可以争论:我会说这取决于您的设计在多大程度上将已发布的事件流视为真实来源)。其次,请记住,您基本上已经失去了围绕该事件发生的所有上下文领域知识:您只能看到数据库的模型表示发生了什么变化。

事件溯源和CQRS相互促进(不做CQRS也可以做事件溯源,只是在某些应用中不使用CQRS的ES才是实用的);事件溯源往往让您将域保持在前端和中心,并且由于它是仅附加的,因此它是您可以拥有的最优化的写入模型。

Can we keep read and write DB in sync just by publishing event from write model and consume it at read model using event handler and updating read database

有点;有一些折衷。在“快乐路径”上,它只需要更长的时间,因为您必须等待两次写入完成。当写入第二个数据库出现问题时,它会变得混乱,因为您的两个数据库不再同步,您必须决定要恢复什么(如果有的话)。

如果您的读取和写入是针对 相同的 数据库,那么如果您在同一事务中更新它们,那么第二个问题就会消失。

Why Event-Sourcing and replay of events needed if my requirement is to only see latest data

你不知道。如果您不需要重建信息过去的样子的能力,那么您就不需要事件溯源。

(您可能会将其视为源代码 - 如果您只需要最新版本的源代码,那么这会简化对“源代码控制系统”的要求。)

Please explain by doing steps 1,3 and 4, am I still following CQRS pattern?

当然可以。 “CQRS 只是在以前只有一个对象的地方创建两个对象。” -- Greg Young, 2010。您可能无法享受 CQRS 的“所有”优势(因为您做出了不同的权衡)。

重要的是要意识到您正在做出权衡,以及影响是什么。