CQRS和事件溯源无需DDD

5
我正在构建一个非常数据中心的系统。我有大量分层的数据集,但没有业务规则。系统的输出来自于对数据的一些计算和多个报告。出于监管原因,我需要完整的审计跟踪,并能够针对其过去任何时间点的数据集运行计算。
因此,我认为使用CQRS的事件源系统是正确的选择。我看到的所有示例都围绕着创建聚合来做ES。我的问题在于,因为每个数据片段都是一个大而相关的集合,所以我会有少量的大型聚合。另一种选择似乎是将集合拆分成其各个部分,并将每个部分称为聚合。但是,为了进行任何计算,我必须加载数十万个聚合。
我的问题是,是否有人有使用CQRS + ES系统处理数据中心问题的经验,以及可能的解决方法?
是否有更好的方法来存储数据集的历史记录,而不使用ES?
感谢任何帮助。

没有数据集的具体大小和计算方式等细节,很难回答这个问题。 - Tomasz Jaskuλa
这是一个资产管理系统。每个资产都有100k+件设备。每个资产还有一些与之相关的项目。每个项目都有一个层次结构,针对资产中每个设备的1k+项。计算是针对项目运行的,并需要设备(100k+项)以及项目中每个设备所持有的所有数据。 - Colin
2个回答

9
但是,为了进行任何计算,我必须加载数十万个聚合物。
语言检查:聚合物只存在于写模型(C)中。计算和报告来自读取模型(Q)。毕竟,当您对其进行报告时,您并没有更改/附加事件历史记录。
这是一个资产管理系统。每个资产都有100k+件设备。
这听起来有点像库存跟踪系统。 Greg Young曾说过:“在大多数库存系统中,没有命令。
因为“记录簿”是真实世界,而不是模型,“命令”没有意义-模型不允许拒绝现实。没有命令,聚合物消失了;没有业务规则可强制执行。只有宣布对现实世界的更改的事件。
CQRS + ES的基本模式仍然有效,也就是说,您将事件历史记录写入持久性层(这是您的审计跟踪),并从此记录发布事件,以便您的其他投影可以更新。

您需要考虑在您的情况下有多少事件流是合适的。在CQRS解决方案中,领域模型是记录的基础,每个聚合通常写入一个独占的事件历史(减少争用);需要来自多个流的数据的模型将它们连接在一起。因此,您可能希望针对不同的外部事件源执行类似的操作。或者,您可以让它们全部发布到单个事件流中,然后让读取模型过滤掉不需要的事件。


2
自从我熟悉了事件溯源的思想后,我一直使用事件存储来存储我正在处理的系统中发生的事情。我称之为“轻量级事件溯源”,在这种情况下,你不需要真正构建聚合,而是遵循贫血模型路线,只需将所有逻辑放在应用服务层中(就像洋葱中的一样)。
我很少见到不跟随“事件溯源”进行“轻量级”版本的理由。它就像审计+记录,但在代码增长时具有更好的应用范围。 只有当你的领域非常丰富时,你才可能考虑开始构建聚合和快照,并将它们缓存在内存中等等。对于浅显的领域,如果您需要最大性能和巨大负载,也可以使用聚合。正确地构建ES聚合需要技能和时间进行分析和实验。在开始这项冒险之前,请确保您拥有它。

感谢您的回复。所以,在这个事件溯源轻量级想法中,我有一个资产对象和与特定资产相关联的设备对象,使用AssetId。这两个对象是单独的贫血模型。我正在使用CQRS,在我的命令处理程序中,我想迭代特定资产的所有设备。如果我只能通过它们的ID在命令端加载对象,那么我如何知道要加载哪个设备? - Colin
我应该将所有ID存储在资产中吗?我是否使用我的读模型来存储AssetIDs和设备的查找?我读到过不应该在命令处理程序中使用读模型,因为它不能保证一致性。你有什么想法? - Colin
我通常先按照经典方式实现所有内容(洋葱模型、贫血模型、关系型数据库),这样你的命令就是一致的,一切都按预期工作。你还可以编写和自动化负载测试,以更好地了解性能瓶颈。然后你可以开始考虑优化高频命令和查询。你可以考虑为其中一些实现CQRS和“ES full”。 - IlliakaillI
1
我的意思是,CQRS/ES正在成为流行词。你不能盲目地应用这些原则,没有充分的理由。当你应用'ES full'或'CQRS'时,总会有一个代价,而大多数情况下这个代价就是代码复杂性。在命令端,你可以按照自己喜欢的方式加载任何内容,只要命令保持一致(如果你依赖于cqrs读模型中的过期数据,则不是这样)。你可以以命令执行时间为代价使你的读模型同步。没有一个模型可以解决所有应用程序的所有问题。 - IlliakaillI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接