gpt4 book ai didi

design-patterns - 事件溯源和 CQRS,我错过了什么?

转载 作者:行者123 更新时间:2023-12-03 18:25:05 24 4
gpt4 key购买 nike

我开始阅读结合 CQRS 的 Event-Sourcing 模式。
据我了解,CQRS 模式是一种我们将写入和读取操作分开的模式。
事件溯源是一种模式,其中系统中的一切都由触发事件的命令启动。事件溯源模式需要一个事件总线。
有几件事我没能理解。
事件存储包含发生在某个实体上的所有事件。如果我想查询这个实体的当前状态,我需要查询这个实体发生的所有事件,并重新创建它的当前状态。
所有事件历史记录都存在于事件存储中。
为什么我不能有一个负责将每个事件保存到事件数据库的微服务(如果我想记录这些事件以进行进一步的操作。比如 Kafka)和一个单独的微服务,它可以定期更新实体上的更改数据库(例如对 MongoDB 中实体文档的简单更新)。当这些微服务完成它们的工作时,这个事件将从事件存储中删除(假设我使用队列实现了这个事件存储)。
这样,每当我需要查询实体的当前状态时,我只需查询数据库,而不是查询事件存储并重建当前状态(或根据事件存储重新计算状态并定期缓存结果) .我不明白为什么必须永久存储所有事件,为什么它不是可选的?
例如,接收事件的 Lambda 函数会生成事件并将它们存储在针对每种事件类型的单独 SQS 中。每个 SQS 都有自己的 lambda 函数,负责处理相应的事件类型。处理完事件后将删除该事件。

最佳答案

Event-sourcing pattern requires an event bus.



事件溯源不需要总线,除非您需要将更改(事件)通知其他系统/域。

If I want to query the current state of this entity, I need to query all the events that happened to this entity, and recreate it's current state.



嗯,有点。您只需要在处理新命令时执行此操作,并且需要验证应用该命令不会使“实体”(如您所称)不一致。请注意,这涉及 CQRS 的命令端,而不是查询端。

对于查询/读取模型方面,您有很多不同的选择。使用事件溯源时,通常有一个单独的数据存储来维护事件的非规范化版本以及在事件发生时更新的相关数据。这家单独的商店通常是 Eventually Consistent ,就这个答案而言,这太多了。您的读取模型也可以是关系数据库、平面文件或您能想到的任何其他存储数据的方式。通过在事件发生时通过总线、轮询数据库或其他方式接收事件,它的数据与写入模型保持一致。

查询事件流并实时处理(或部分处理)它们以构建查询也是绝对有效的,但这种情况相对不常见。

All the events history is present in the event store. Why can't I have a microservice that is responsible for saving each event to a event-database (If I want to log those events for further actions. something like kafka) and a separate microservice that updates the changes on an entity in a regular database (simple update to entity's document in mongodb for example).



你可以!

When those microservices finished their work, this event will be removed from the event-store (lets say I implement this event store using a queue).



你也可以这样做,但是你没有在做事件溯源。这更像是“事件驱动架构”,它在不使用事件溯源的情况下是可能且完全有效的,但并没有提供所有相同的好处。在事件源系统中,事件存储是数据的真实来源,而队列不是存储真实数据的有效位置,因为它并不真正意味着长期存储数据。

当你做 CQRS 时,尤其是当你做事件溯源时,你需要改变你对“当前状态”意味着什么的心理模型。实际真相存储在某处(事件存储、关系数据库等),当您查询时,您将该真相投影为您需要的任何格式。

例如,我有一个用户数据库,其中一列存储 FirstName,另一列存储 LastName。代表我的行在 FirstName 列中包含“Phil”,在 LastName 列中包含“Sandler”。当我在 UI 中显示数据时,我将其显示为“Sandler, Phil”。为什么不将它作为“Sandler, Phil”存储在文档数据库中并完成它呢?因为通过规范化数据,我已经准确地记录了真相,并且可以选择在 future 需要时以不同的方式投影数据。

那么上面示例中的当前状态是存储在两列中的数据,还是“Sandler, Phil”?在 CQRS 中,您不应该根据当前状态来考虑它,而是根据您的两个独立模型、真相(写入端)以及它如何被投影(读取端)来考虑它。

关于design-patterns - 事件溯源和 CQRS,我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60523277/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com