何时使用CQRS设计模式?

79

我和我的团队一直在讨论使用CQRS(命令查询职责分离)设计模式,我们仍在尝试评估使用它的利弊。根据:http://martinfowler.com/bliki/CQRS.html

我们还没有看到足够多的CQRS在现场使用,因此无法确信我们理解其优缺点

那么你们认为,在什么情况下需要使用CQRS呢?


Darren Cauthon做了一次关于CQRS和事件溯源的精彩演讲,包括缺点 - Google说它可以在这里找到(http://vimeo.com/25801867),但我无法通过我们的防火墙验证。 - TrueWill
1
他个人在现场没有看到过。 - Henrik
14个回答

78

CQRS不是一个包含整个应用程序的模式。

它是建立在领域驱动设计(DDD)基础上的概念。DDD的一个重要战略概念是所谓的有界上下文

在典型的应用程序中,有多个有界上下文,可以根据实际情况实现。例如:

  • 用户管理 -> CRUD
  • 发票管理 -> CRUD
  • 保险单管理(核心领域)- > CQRS
  • ......

这可能并不能回答你的问题,但可以更深入地了解主题。老实说,我认为在考虑项目的具体情况之前,很少有像明确的最佳实践这样的东西可言。


4
不同意“CQRS不是一种模式,而且一旦决定使用它,将经常涵盖整个应用程序”的说法。 CQRS是一种架构模式,而不是顶层架构。因此,您必须评估是否在每个特定的有界上下文中应用它。请参阅http://cqrsjourney.github.com并阅读第二个参考章节。 - Grigori Melnik
8
@GrigoriMelnik也许我回答的第一句话表述不够清楚(我也不是母语使用者)。据我所知,我的意思与您相同。CQRS应该基于有界上下文进行应用,而不是整个应用程序。 - Dennis Traub
25
我认为你的句子表达得很恰当,是Grigori Melnik理解错了它。 - Dave Van den Eynde
我正在重新阅读这篇文章,我认为你真正想表达的不是使用CQRS的真正原因。它与CRUD和非CRUD(基于任务的UI)有关。而且,你不需要使用CQRS来实现基于任务的UI。你可以仅使用命令而没有任何查询,也不需要分离命令和查询来实现基于任务的UI。只需使用类似命令的模式,你就不需要将命令与查询分开来实现基于任务的UI。 - Konrad
但是,人们经常认为这是处理基于任务的用户界面时唯一可用的方法,我认为这是错误的。 - Konrad
显示剩余4条评论

41

有些人批评CQRS过于复杂,这可能是真的。

当然,在以CQRS风格开发简单的CRUD应用程序时,会增加额外的开发负担,因此我建议只在以下情况下考虑使用CQRS:

  1. 庞大的团队 - 如果你采用了CQRS架构,你可���轻松地将开发任务分配给不同的人。高水平的人员可以专注于领域逻辑,而将常规工作留给技术较差的开发者。
  2. 复杂的业务逻辑 - CQRS强制你避免混合领域逻辑和基础设施操作。
  3. 可扩展性很重要 - 采用CQRS可以实现出色的读写性能,指令处理可以在多个节点上扩展,而查询是只读操作,可���优化为快速的读操作。

13
在考虑CQRS时,我不确定会想到拥有分布式团队。任何一种分层/多层应用程序都可以被分解为良好的隔离任务。 - James
1
难以理解还是复杂?你应该更清楚地区分这些批评。在我看来,它可以简化你生活的许多方面,当然这不是你在学校所学到的,因此需要额外的努力去理解它。 - Nicolas Henin

17
当您拥有复杂或困难的业务领域,并且:
  • 使用事件源技术时,您需要一种良好的逻辑测试方式
  • 使用事件源技术时,您想通过测试和推理证明自己的行为
  • 您有多个客户或消费者使用您的领域服务(不仅仅是单个Web服务器)
或者您有需要对共同数据进行操作的用户:
  • 您想要规范化您的领域中数据合并概念
  • 或者您想要应用逻辑来合并事件
或者您有可扩展性要求:
  • 您将模式应用为去除瓶颈的非规范化模式
  • 您想要水平扩展而不是垂直扩展
或者您有性能问题(可扩展性的另一面):
  • 例如,您需要将架构迁移到事件驱动的体系结构-CQRS作为一个很好的跨步石。
或者您有一个分散的团队:
  • 例如,您的某些团队成员在另一个国家
  • 或者难以进行面对面交流,因此您希望将读模型与写方面的事务(Sagas、Domain、CRUD)解耦
CQRS并不过于复杂,而是计算机过于复杂。

请参见@MairbekKhadikov答案上的评论。 - James

15
何时使用CQRS设计模式?
当从存储库中查询用户需要查看的所有数据变得困难时,可以使用CQRS架构模式。特别是当UX设计创建跨越多个聚合类型和实例的数据视图时,这一点尤为真实。您的领域越复杂,这种情况就越常见。
当无法在UX设计上做出妥协时,使用CQRS尝试缓解与其他解决方案相关的问题,例如:
- 要求客户端使用多个存储库来检索所有聚合实例;或 - 设计专用查找器在各个存储库上使用单个查询收集不连贯的数据。
总之:当从存储库中查询用户需要查看的数据变得困难时,请使用CQRS,这通常发生在您的领域越复杂时。

1
如果数据难以查询,通常情况下,你不一定需要使用CQRS,使用物化视图通常就足够了。 - matino
物化视图要求数据存储在同一个数据库中。这在微服务架构中通常不是这种情况,因为CQRS经常与事件溯源配对使用。 - Frederik Krautwald

7
在现实世界的场景中,当您需要从多个领域获取大量数据并且从数据库检索这些数据需要很长时间时,CQRS可能会非常有用。在这种情况下,您可以考虑创建一个单独的读模型,该模型开发速度更快,执行时间更快。

5
以下是使用CQRS的原因:
  1. 可扩展性(读取操作超过写入操作,因此每个操作的扩展需求不同,可以更好地解决)
  2. 灵活性(分离读/写模型)
  3. 减少复杂性(将复杂性转移到单独的关注点)
  4. 专注于领域/业务
  5. 有助于设计直观的基于任务的用户界面

4

嗯,对于你的问题没有简单明了的答案,但我想给你一些实际应用CRQS的例子,这些例子可能会帮助你理解如何在你的应用中使用它。

1. Instagram

我们经常看到Instagram的故事和短视频等内容。这些故事是只读的,最好为此类数据创建一个独立的只读数据库。外部世界只能处理该特定数据库,以渲染朋友时间线中的故事,这样系统就不需要关心主要的业务密集型信息存储在何处。

2. Amazon

当下订单时,订单服务会发出一个事件,这个事件被其他服务订阅,其中一个服务可以更新反规范化的只读数据库,而其他服务(比如消息服务)可以从只读数据库中获取归一化信息,如userId,ordered等进行邮件处理以确认订单。


3
以下是一些适用于 CQRS 模式的场景:
  • 需要高性能和独立可扩展性的大型项目。
  • 在业务逻辑复杂的应用程序中,可以将读取与写入分离以使其更加简单。
  • 如果您希望进行并行开发,则一个团队可以处理读模型,而另一个团队可以处理写模型。
阅读此文章了解有关 CQRS 模式的更多信息:文章

2

1
如果您发现问题域无法很好地适应通用架构,或者正在尝试领域驱动设计,我建议您尝试使用CQRS。
这是一种强大的模式,可能会让您更好地了解问题域,并解决一些技术和基础设施方面的挑战。但值得注意的是,它将付出代价,并且由于与其他架构的概念差异,它需要进行思维模型转换。 CQRS: Intro

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