CQRS:写入 RDBMS,从 NoSQL 读取?

CQRS: write to RDBMS, read from NoSQL?

我一直在考虑分离读取和写入流程,甚至让它们使用不同的数据库,通过水平扩展 "read" 数据库来提供最佳的快速数据可用性。我要让我的项目写入数据库,将对象更改通知推送到队列中,以便另一个服务读取消息并将更新的数据复制到一个或多个非规范化 "read" 数据库。考虑到这一点,我发现如果 "write" 数据库也被非规范化,这会很糟糕。
示例:假设有一个名为大学用户的用户配置文件已毕业。假设我将此信息存储在 "write" 数据库中,如下所示:

{ userId: 100, name: "John", universityId: 200, universityName: "Cambridge"}

假设用户打开了他的个人资料进行编辑,而在他这样做的同时,另一个人,剑桥代表,将名字从 "Cambridge" 更改为 "C.U." 并保存了更改,因此他们都去了 "write" 和 "read" 数据库。更新大学名称的服务已完成工作,"thinks" 现在大学到处都可以了。这一刻之后,第一个用户使用旧大学名称保存更新的个人资料,这个名字将出现在他的个人资料出现的每个地方。
这类问题让我认为 "write" 数据库 必须 始终规范化,不包含重复项。但是我从来没有从关于 CQRS 的文章中遇到过这个原则。我是不是想错了?

你没看错!

这个 "principle" 在 Eric Evans 的 DDD book 中写得非常清楚和详细。规则是 聚合只能通过其 ID 引用其他聚合。在 CQRS 中,聚合 used/accessed 仅在写入端。

另一方面,读取模型应该针对读取进行优化,反规范化是一种方法。我总是这样做。它们可以通过监听正确的事件来保持同步。