CQRS:写入 RDBMS,从 NoSQL 读取?

LIN*_*dka 2 sql-server mongodb cqrs

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

{ userId: 100, name: "John", universityId: 200, universityName: "Cambridge"}
Run Code Online (Sandbox Code Playgroud)

假设用户打开了他的个人资料进行编辑,当他在编辑时,另一个人(剑桥代表)已将名称从“剑桥”更改为“CU”并保存更改,因此它们同时进入“写入”和“读取”数据库。更新大学名称的服务结束了,现在"想"大学到处都OK。在这一刻之后,第一个用户用旧的大学名称保存更新的个人资料,这个名字将出现在他的个人资料出现的每个地方。
这类问题让我觉得“写”数据库必须始终规范化,不能包含重复项。但是我从来没有从关于 CQRS 的文章中找到这个原则。我想错了吗?

Con*_*enu 5

你做对了!

这个“原则”在Eric Evans的DDD 书中写得非常清楚和详细。规则是聚合只能通过它们的 ID 引用其他聚合。在 CQRS 中,聚合仅在写入端使用/访问。

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