Aar*_*nHS 3 mongodb cqrs event-sourcing
我正在设计一个 CQRS 事件源系统(不是我的第一个),其中我的读取模型被非规范化并存储在读取优化的文档数据库 (MongoDb) 中。没什么特别的。现在这个特定的读取模型是一个包含用户 ID 和用户所属的潜在大型组数组的文档:
{
"userId": 1,
"userName": "aaron",
"groups": [
{
"groupId": 1,
"name": "group 1"
},
{
"groupId": 2,
"name": "group 2"
}
]
}
Run Code Online (Sandbox Code Playgroud)
可能有成千上万的用户是一个组的成员(举个例子:想象一个每个工作人员都是成员的组)。
请记住,我首先使用 CQRS 的原因是我需要扩展我的读取(或者更确切地说,鉴于需要避免大量连接,以不同方式处理我的读取),并且我期待大量写道。这不是我使用 CQRS 和事件溯源的唯一原因,但它是一个主要的催化剂。
现在我遇到的问题是当有人更新组名时(我预测这会经常发生)我的读取模型需要更新。这意味着单个用户对单个数据的修改将在我的读取存储中导致成千上万的更新。
我很清楚我可以应用的所有技术来处理调度更新以避免时间耦合,但是我担心每个用户修改将更新的文档数量。
我已经阅读了几个问这种确切类型问题的 SO 答案,大多数答案表明您要么需要取得平衡,要么不必担心大规模更新。但是 IMO,这不是一个真正的选择。在这种类型的读取模型中确实没有平衡(任何对文档的重新建模仍然需要组名出现同样多次,无论它如何重新建模),并且简单地接受大量更新对于超快速读取存储的想法会适得其反,因为由于几乎总是在进行的持续更新,它现在将承受严重的负载要排队。本质上会发生什么,是非规范化过程将成为瓶颈,并且队列将随着时间的推移而增长(直到用户更新组名有一些喘息的机会),并且读取将变得缓慢作为副作用。
在有人跳到我身上问我是否知道这个瓶颈会发生之前,答案是“应该,但显然我不能确定”。但是,基于知道在我要替换的现有系统中进行了多少更改,并且请记住,这不是文档数据库中唯一需要更新的模型类型,我有充分的理由担心. 正如我所说,还有其他几种读取模型——它们可能没有相同数量的更新——但仍然会增加读取存储中的写入负载。而且,读取存储只能进行如此多的写入。
我可以想到两种解决方案(一种愚蠢,一种不那么愚蠢):
在每个文档中存储一个版本,并且在事件发生时不更新读取模型。然后,当读取特定文档时,我会检查是否过时,如果版本过时(由于执行命令),我会在存储和返回该文档之前对该文档应用最后一次更改。然而,我的直觉告诉我,不管怎样,最终每个文档都会得到更新,这只是给读取增加了额外的开销。我也不知道版本控制实际上是如何工作的
使用关系读取模型并具有单个连接。这似乎是最明智的选择,因为我只会更新连接表,一切都很好。但是读取不会那么快,而且感觉比纯 select * from tablename 方法要差一些。
我的问题:
是否有任何标准技术可以解决此类问题?我提供的第二个选项是我所能希望的最好的选择吗?
老实说,我原以为这种类型的问题会一直发生在 CQRS 事件源系统中,其中非规范化数据需要保持同步,但社区中似乎缺乏关于它的讨论,这导致我相信我错过了一个明显的解决方案,或者我的阅读模型需要改进。
我认为当您期望一个用户成为成千上万个群组的成员时,您选择的模型是错误的。您需要从用户文档中删除组列表并坚持使用关系模型,只保留组 ID。想象一下,您的组需要比名称更多的属性,您将再次面临同样的问题。然后再次。
| 归档时间: |
|
| 查看次数: |
528 次 |
| 最近记录: |