【问题标题】:Is CQRS still helpful when your read and writes have similar scaling requirements?当您的读取和写入具有类似的扩展要求时,CQRS 是否仍然有用?
【发布时间】:2021-05-01 01:59:26
【问题描述】:
我有一个 .NET MVC 电子商务购物篮应用程序,它可以跟踪客户放置在购物篮中的商品。我们使用存储库模式来读取/写入购物篮表中的项目,有时这个应用程序会承受来自用户的巨大压力,从而导致 SQL 数据库受到影响。
我想知道使用 CQRS 是否有帮助,但在这种情况下,两种情况下对篮子的读取/写入次数都非常高。另外(除非我被误解了),感觉最终一致性在这里不太合适,因为对篮子的更新需要立即读取,以便用户可以跟踪并查看他们添加的内容。一秒钟的延迟会引起巨大的混乱。
这是一个完全不适合 CQRS 的场景吗?只关注水平扩展应用程序和数据库会更好(也许通过将客户分成不同的组),还是有其他架构样式可以提供帮助?
【问题讨论】:
标签:
.net
database
architecture
cqrs
【解决方案1】:
只是为了清楚起见:CQRS 读取面不必最终一致。在 SQL 中,实际上很容易拥有一致的读取模型:只需在与写入操作相同的事务中创建它即可。甚至使用物化视图。 CQRS 仅意味着在代码和数据存储中为写入和读取保留一个单独的模型,并不自然地暗示最终(或任何其他)一致性模型。
对于您的确切用例,我真的不明白为什么篮子会从单独的读取模型中受益(它甚至可能会使情况变得更糟),但我不知道您的完整规格。如果您正确索引数据,则读取应该不是问题。我会朝另一个方向优化写入性能,优化架构可能会有所帮助。
此外,如果篮子的耐用性并不重要,您可以考虑仅使用 memcache(例如 redis)来存储篮子。与性能收益相比,如果 redis 失败(无论如何应该非常罕见)并且所有篮子都被丢弃,最坏的情况/业务影响是什么?我认为一个缓慢的系统所造成的伤害比一年可能发生一到两次(或从不发生)的故障可能造成的影响更大。
【解决方案2】:
如果您正在执行简单的 CRUD,CQRS 并不是您真正要寻找的模式。我会更多地研究缓存模式。一个小的缓存在这里可以帮助扩展小表。如果您愿意利用最终一致性,将其设为回写缓存,用户将只能看到缓存,而数据存储将滞后于用户......这对于正在购买东西的用户来说似乎有点冒险,并且从添加到购物车到“结帐”之间的时间可能很短。