何时使用 CQRS 设计模式?
我和我的团队一直在讨论使用 CQRS(命令查询职责分离)设计模式,我们仍在尝试评估使用它的利弊。根据:http://martinfowler.com/bliki/CQRS.html
我们还没有看到足够多的 CQRS 在该领域的使用,但还没有信心 我们了解它的优点和缺点
那么你们觉得什么时候问题需要使用 CQRS 呢?
My team and I have been discussing using the CQRS (Command Query Responsibility Segregation) design pattern and we are still trying to asses the pros and cons of using it. According to: http://martinfowler.com/bliki/CQRS.html
we haven't seen enough uses of CQRS in the field yet to be confident
that we understand its pros and cons
So what do you guys think, when does a problem call for using CQRS?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
CQRS 不是包含整个应用程序的模式。
它是一个建立在领域驱动设计(DDD)基础上的概念。而DDD的一个重要的战略概念就是所谓的限界上下文。
在典型的应用程序中,存在多个有界上下文,其中任何一个都可以按照有意义的方式实现。例如
这可能无法回答您的问题,但它可能会让您对这个主题有更多的了解。老实说,如果不考虑项目的具体情况,我认为根本无法回答这个问题,而且即使如此,也很少有明确的最佳实践。
CQRS is not a pattern that encompasses the whole application.
It is a concept that builds on Domain Driven Design (DDD). And an important strategic concept of DDD is the so-called Bounded Context.
In a typical application there are multiple bounded contexts, any of which can be implemented the way it makes sense. For instance
This probably doesn't answer your question but it might give a little more insight into the topic. To be honest, I don't think it can be answered at all without considering a project's specifics, and even then there is rarely something like a definite best practice.
CQRL 批评者可能会说 CQRS 很复杂,这可能是真的。
当然,这会增加以 CQRS 风格开发简单 CRUD 应用程序的开销,因此我只会在以下情况下考虑使用 CQRS:
Well CQRL critics may say that CQRS is complicated and that might be true.
Of course, it's adding overhead developing a simple CRUD application in the CQRS style, so I'd consider using CQRS only in the following cases:
当您有一个复杂或困难的业务领域并且:
或者您有需要对通用数据进行操作的用户:
您有可扩展性要求:
瓶颈,或者您有性能问题(可扩展性的另一面):
或者你有一个物理上分离的团队:
并不是 CQRS 过于复杂,而是计算机过于复杂。
When you have a complex or hard business domain and:
OR you have users that need to act on common data:
OR you have scalability requirements:
OR you have performance problems (other side of scalability):
OR you have a team that is physically disjunct:
It's not CQRS that's overly complicated, it's computers that are.
当难以从存储库查询用户需要查看的所有数据时,可以使用 CQRS 架构模式。当用户体验设计创建跨多个聚合类型和实例的数据视图时尤其如此。您的领域越复杂,这种情况就越可能发生。
当不适合在 UX 设计上妥协时,使用 CQRS 尝试缓解与其他解决方案相关的问题,例如:
总结一下:当难以从用户需要查看的存储库中查询数据时,请使用 CQRS,您的领域越复杂,这种情况就越容易发生。
The CQRS architecture pattern could be used when it is difficult to query from repositories all the data that users need to view. This is especially true when UX design creates views of data that cuts across several aggregate types and instances. The more sophisticated your domain, the more this tends to be true.
When it is unsuitable to compromise on UX design, using CQRS attempts to mitigate the problems associated with other solutions, such as:
To summarize: Use CQRS when its difficult to query from repositories data users need to view, which tend to happen the more sophisticated your domain is.
在现实场景中,当您的前端/Web 服务客户端需要来自多个域的大量数据并且从数据库检索这些数据需要很长时间时,CQRS 可能会很有用。
在这种情况下,您可能会考虑创建单独的读取模型,该模型的开发速度更快,并且执行时间可能更快。
In real world scenario CQRS might be useful when you have front end/web service client which needs lots of data from multiple domains and retrieval of these data from database takes long time.
In such case you might consider creation of separate read model which will be faster to develop and might have faster execution time.
以下是使用 CQRS 的原因:
Following are the reasons to use CQRS:
嗯,你的问题没有直接的答案,但我想给你一些如何实现 CRQS 的真实示例,这可以帮助你弄清楚如何在你的应用程序中使用它,
1. Instagram
我们经常看到Instagram的故事/卷轴等。这些商店是读取密集型的,最好有一个单独的只读数据库来存储此类数据。外部世界只能处理特定的数据库来渲染朋友时间线中的故事,这样做系统不需要打扰存储主要业务密集型信息的主数据库。
2.亚马逊
下订单时,订单服务会发出一个事件,该事件由其他服务订阅,可以更新非规范化的只读数据库,而其他服务(比如说消息服务)可以简单地接收从只读数据库标准化信息,如用户 ID、订购等,并继续进行电子邮件处理以确认订单
Well, there is no straightforward answer to your question, but I would like to give you some real-world examples of how CRQS could be implemented which could help you figure out how it could be used in your application,
1. Instagram
We often see Instagram stories/reels etc. These stores are read-intensive, it's better to have a separate read-only database for such data. The outer world can only deal with that particular DB for rendering stories in your friend's timelines, doing so the system does not need to bother the main DB where major business-intensive information is stored.
2. Amazon
When an order is placed, the order service emits an event, this event is subscribed by other services out of which one could update denormalized Read-Only DB, and other services(let's say messaging service) could simply pick up normalized information like userId, ordered, etc, etc from Read-only DB and proceed with email processing for order confirmed
以下是
CQRS 模式
非常适合的一些场景:需要可扩展性。
您可以将读取与写入分开,以使其更简单。
模型和其他团队致力于编写模型。
阅读这篇文章,了解有关
CQRS 的更多信息模式
。Below are some scenarios where the
CQRS Pattern
fits perfectly:scalability is required.
you can separate your reads from write to make it more simple.
models & other team works on write models.
Read this Article to understand more about
CQRS Pattern
.在以下情况下使用它:
https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs#when-to-use-this-pattern
Use it when :
https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs#when-to-use-this-pattern
我对这个问题的看法与其他人不同。我使用 CQRS 来构建一切。即使是简单的 CRUD 应用程序。
不过,我把它简化了很多,让事情变得灵活。
以下是原因和方法:
DDD
) 概念之上。查询
和命令
。QueryHandler
或CommandHandler
处理。Query
及其Response
和QueryHandler
位于同一个类中,代表一个小的独立功能。就我而言,我的查询和命令可通过 API、Blazor、Azure Functions 等使用,从而使消费者尽可能精简。
因此,以我的拙见,我发现使用 CQRS 和单个存储来构建功能比使用往往会快速增长并变得混乱的 CRUD 更高效。
最困难的部分是当您必须切换到
读取存储
和写入存储
并且必须保持它们同步时。有一些机制可以实现这一点,但当您达到这一点时,您将能够通过优化查询中的 SQL 等方式解决大部分性能问题。甚至内存缓存。在发布这个问题 11 年后,您可能已经下定决心了,但对于看到这个问题的任何人,我建议您查看一下这个 CQRS 实现 github 上使用单个存储的存储库。它是 .NET 7 特定的,但它可以应用于任何语言。
I have a different take on the subject to everyone else. I literary build everything using
CQRS
. Even the simple CRUD applications.However, I simplify it a lot and make things flexible.
Here is why and how:
DDD
) concept.Queries
andCommands
.QueryHandler
orCommandHandler
.Query
and itsResponse
andQueryHandler
live in the same class and represent a single small self-contained functionality.In my case my queries and commands are consumable by API, Blazor, Azure Functions etc keeping the consumers as thin as possible.
So in my humble opinion I find it way more productive to build features using CQRS with a single storage than doing CRUD that tend to grow quickly and become cluttered.
The hardest part is when you have to switch to
read storage
andwrite storage
and you have to keep them in sync. There are mechanism out there to make it happen but by the time you reach this point you will be able to solve most of your performance issues with things like optimizing your SQL in queries or even in-memory caching.After 11 years of posting this question you probably made up your mind but for anyone seeing this question I recommend to check out this CQRS implementation repo on github that uses a single storage. It's .NET 7 specific but it can applied to any language out there.
如果您发现问题域不太适合更通用的架构,或者您正在尝试域驱动设计,我建议您尝试一下 CQRS。
这是一种强大的模式,可以让您很好地了解问题领域并解决一些技术和基础设施挑战。但值得注意的是,它会带来价格,并且由于与其他架构的概念差异,它将需要思维模型的转变。
CQRS:简介
If you are seeing that the problem domain doesn’t fit well into more generic architecture or you are experimenting with domain-driven design, I’d recommend you to give CQRS a shot.
It is a powerful pattern, which might give you good exposure to the problem domain as well as solve some technical and infrastructural challenges. But it is worth keeping in mind that it will come with its price and due to conceptual differences with other architectures, it will require a mental-model shift.
CQRS: Intro
每个人都解释了为什么需要使用 CQRS,但让我们谈谈为什么不使用它:
因此,CQRS 应用程序的主要特征之一是数据将最终一致性。这意味着由于更新数据的同步过程,查询检索的数据可能并不总是最新数据。在处理这些请求时,可能会导致命令和查询之间存在一定的滞后。如果您打算使用 CQRS,您必须意识到这一点,并且在您的业务需要强一致性的情况下,您不应该使用 CQRS。 (银行应用程序,即)
Everyone explained why you need to use CQRS, but let's talk about why NOT use it:
So, one of the main characteristics of CQRS application is that data will be eventual consistency. This means the data that the query retrieves may not always be latest data because of the synchronization process that updates the data. When processing those requests, it can cause a certain lag between command and queries. If you are going to use CQRS you must be aware of that and in the case of your business needs to have strong consistency, you should not use CQRS. (Banking applications i.e.)
简而言之,仅当应用程序速度非常重要以至于您准备为此牺牲时间和金钱并且不需要立即一致性时才使用 CQRS 模式。
他们说 CQRS 带来了以下价值:
在我看来,可扩展性是 CQRS 最突出的优点,其他优点可以说尚未得到证实或较弱。我的意思是,单一职责、解耦或独立团队都很难基于你如何解释你的设计。您可以拥有任何其他架构,并且仍然受益于“可测试性”和“安全性”。 “解耦”和“消除复杂性”不会发生,因为这些功能只是从一个地方移动到另一个地方;复杂的查询始终保持复杂;你只需改变它的位置。另一个例子,在实践中,您不会看到两个独立的团队正在处理同一个模块(一个用于命令,一个用于查询)。
此外,CQRS 不会添加上述任何值,除非您决定(至少)拥有两个数据库以便从一个数据库进行查询并在另一个数据库上执行命令。通过这种方式,您消除了数据库读/写瓶颈,有利于获得更快的响应,但也给您的代码带来了缺点,例如:
In short, use CQRS pattern only if the application velocity is so important that you're ready to sacrifice time and money on it, and immediate consistency is not desired.
They say CQRS brings the following values:
In my opinion, scalability is the most prominent benefit of CQRS, other pros are arguably not proven or weak. I mean, single responsibility or decoupling or separate-team are poorly based on how do you interpret your design. You can have any other architecture and you still benefit from “testability” and “security”. “decoupling” and “removal Complexity” doesn’t happen as those functionalities are merely moved from one place to another; a complex query is always remained complex; you just change its place. As another example, in practice you won’t see two separate teams are working on a same module (one for commands and one for queries).
Moreover, CQRS does not add any value mentioned above except when you decide to have two databases (at least) in order to query from one and execute command on the other. This way, you removed the database read/write bottleneck in favor of gaining faster response, yet brought disadvantages to your code such as:
关于实现 CQRS,我喜欢当前端/Web 服务客户端需要来自多个域的大量数据时分离读取模型的想法,我想尝试一下。我想尝试它的主要原因是开发和执行过程“缓慢”的问题;尤其是在处理大型数据集或“大数据”时。我正在研究降低复杂性、增加混合架构的可扩展性、弹性和灵活性的所有可用选项。
With regards to implementing CQRS, I like the idea of separating read models when you have a front end/web service client requiring lots of data from multiple domains, and I would like to try it. My primary reason for wanting to try it is due to the issue with 'slowness'in development and execution processes; especially when it comes to handling large data sets, or 'big data'. I'm looking at all the various options available in reducing complexity(ies), adding scalability, resiliency, and flexibility to a hybrid architecture.