何时使用 CQRS 设计模式?

发布于 2024-12-25 22:20:26 字数 284 浏览 2 评论 0原文

我和我的团队一直在讨论使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

静待花开 2025-01-01 22:20:26

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

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

在典型的应用程序中,存在多个有界上下文,其中任何一个都可以按照有意义的方式实现。例如

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

这可能无法回答您的问题,但它可能会让您对这个主题有更多的了解。老实说,如果不考虑项目的具体情况,我认为根本无法回答这个问题,而且即使如此,也很少有明确的最佳实践

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

  • User Management -> CRUD
  • Invoicing -> CRUD
  • Insurance Policy Management (the Core Domain) -> CQRS
  • ...

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.

﹏雨一样淡蓝的深情 2025-01-01 22:20:26

CQRL 批评者可能会说 CQRS 很复杂,这可能是真的。

当然,这会增加以 CQRS 风格开发简单 CRUD 应用程序的开销,因此我只会在以下情况下考虑使用 CQRS:

  1. 大型团队 - 如果您有能力,您可以轻松地在人员之间分配开发任务选择CQRS架构。您的高层人员可以从事领域逻辑工作,将常用的工作留给技能较差的开发人员。
  2. 困难的业务逻辑 - CQRS 迫使您避免混合域逻辑和基础设施操作。
  3. 可扩展性很重要 - 通过 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:

  1. Large team - You can split development tasks between people easily if you have chosen CQRS architecture. Your top people can work on domain logic leaving usual stuff to less skilled developers.
  2. Difficult business logic - CQRS forces you to avoid mixing domain logic and infrastructural operations.
  3. Scalability matters - With CQRS you can achieve great read and write performance, command handling can be scaled out on multiple nodes and as queries are read-only operations they can be optimized to do fast read operations.
银河中√捞星星 2025-01-01 22:20:26

当您有一个复杂或困难的业务领域并且:

  • 具有事件溯源; 测试逻辑的好方法
  • 您想要一种通过事件溯源 ;您想通过测试和推理来证明您的行为
  • 您的域服务有多个客户端或消费者(不仅仅是单个 Web 服务器)

或者您有需要对通用数据进行操作的用户:

  • 并且您想要形式化数据合并概念 或者
  • 或者您想要应用合并事件的逻辑,

您有可扩展性要求:

  • 您将该模式应用为非规范化模式,以消除
  • 您想要水平而不是垂直扩展的

瓶颈,或者您有性能问题(可扩展性的另一面):

  • 例如你需要迁移你的向事件驱动架构迈进的架构 - CQRS 作为一种模式是一个很好的垫脚石。

或者你有一个物理上分离的团队:

  • 例如,你的团队的一部分位于另一个国家
  • ,或者很难进行面对面的沟通,因此你希望将读取模型与事物的写入端(传奇,域)分离、CRUD)

并不是 CQRS 过于复杂,而是计算机过于复杂。

When you have a complex or hard business domain and:

  • with event sourcing; you want a nice way of testing logic
  • with event sourcing; you want to prove your behaviours through testing and reasoning
  • you have multiple clients, or consumers, of your domain service (not just single web server)

OR you have users that need to act on common data:

  • and you want to formalize the data merge concepts of your domain
  • or you want to apply logic for merging events

OR you have scalability requirements:

  • you apply the pattern as a denormalization pattern that removes bottlenecks
  • you want to scale horizontally and not vertically

OR you have performance problems (other side of scalability):

  • e.g. you need to migrate your architecture towards an event driven architecture - CQRS as a pattern is a good stepping stone.

OR you have a team that is physically disjunct:

  • e.g. parts of your team is in another country
  • or it's hard to get face-to-face communication, so you want to decouple the read models from the write-side of things (sagas, domain, CRUD)

It's not CQRS that's overly complicated, it's computers that are.

ぇ气 2025-01-01 22:20:26

何时使用 CQRS 设计模式?

当难以从存储库查询用户需要查看的所有数据时,可以使用 CQRS 架构模式。当用户体验设计创建跨多个聚合类型和实例的数据视图时尤其如此。您的领域越复杂,这种情况就越可能发生。

当不适合在 UX 设计上妥协时,使用 CQRS 尝试缓解与其他解决方案相关的问题,例如:

  • 要求客户端使用多个存储库来检索所有聚合实例;或者
  • 在各种存储库上设计专门的查找器,以使用单个查询收集脱节的数据。

总结一下:当难以从用户需要查看的存储库中查询数据时,请使用 CQRS,您的领域越复杂,这种情况就越容易发生。

When to use the CQRS design pattern?

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:

  • requiring clients to use multiple repositories to retrieve all aggregate instances; or
  • the design of specialized finders on various repositories to gather disjointed data using a single query.

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.

我的黑色迷你裙 2025-01-01 22:20:26

在现实场景中,当您的前端/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.

记忆で 2025-01-01 22:20:26

以下是使用 CQRS 的原因:

  1. 可扩展性(读取超过写入,因此每个方面的扩展要求不同,可以更好地解决)
  2. 灵活性(单独的读/写模型)
  3. 降低复杂性(将复杂性转移到单独的关注点)
  4. 专注于域/业务
  5. 有利于设计直观的基于任务的 UI

Following are the reasons to use CQRS:

  1. Scalability (read exceeds the write, so does the scaling requirements for each differs and can be addressed better)
  2. Flexibility (separate read / write models)
  3. Reduced Complexity (shifting complexity into separate concerns)
  4. Concentrate on Domain / Business
  5. Facilitates designing intuitive task-based UIs
妥活 2025-01-01 22:20:26

嗯,你的问题没有直接的答案,但我想给你一些如何实现 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

断舍离 2025-01-01 22:20:26

以下是 CQRS 模式 非常适合的一些场景:

  • 需要高性能且独立的大型项目
    需要可扩展性。
  • 在业务逻辑复杂的应用程序中。在这种情况下,
    您可以将读取与写入分开,以使其更简单。
  • 如果您想要并行开发,让一个团队可以进行阅读
    模型和其他团队致力于编写模型。

阅读这篇文章,了解有关 CQRS 的更多信息模式

Below are some scenarios where the CQRS Pattern fits perfectly:

  • Large projects where high performance is required and independent
    scalability is required.
  • In the applications where business logic is complex. In such a case,
    you can separate your reads from write to make it more simple.
  • If you want parallel development where one team can work on the read
    models & other team works on write models.

Read this Article to understand more about CQRS Pattern.

雪落纷纷 2025-01-01 22:20:26

在以下情况下使用它:

  1. 具有复杂的域并且需要通过命令了解域
  2. 读写的应用程序负载不同
  3. 希望在任何时间点扩展读取操作

https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs#when-to-use-this-pattern

Use it when :

  1. Have a complex domain and need to understand domain by commands
  2. Application load with read and write differes
  3. Want to scale read operations at any point of time

https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs#when-to-use-this-pattern

猫腻 2025-01-01 22:20:26

我对这个问题的看法与其他人不同。我使用 CQRS 来构建一切。即使是简单的 CRUD 应用程序。

不过,我把它简化了很多,让事情变得灵活。

以下是原因和方法:

  1. 它建立在域驱动设计 (DDD) 概念之上。
  2. 我总是将事物分为查询命令
  3. 每个都由 QueryHandlerCommandHandler 处理。
  4. Query 及其 ResponseQueryHandler 位于同一个类中,代表一个小的独立功能。
  5. 它们非常容易进行单元测试。
  6. 我从查询和命令的单一存储开始,并在需要时将它们分开。通常将所有内容都存储在 SQL Server 中,并根据需要将一些内容移动到 Cosmos DB (noSQL) 或 Redis 中进行查询。
  7. 它增强了一致性,并使项目中的功能分组变得容易。

就我而言,我的查询和命令可通过 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:

  1. It is built on top of Domain Drive Design (DDD) concept.
  2. I always separate things into Queries and Commands.
  3. Each are handled by either QueryHandler or CommandHandler.
  4. Query and its Response and QueryHandler live in the same class and represent a single small self-contained functionality.
  5. They are very easy to unit test.
  6. I start with a single storage for both queries and commands and separate them if needed. Usually have it all in SQL Server and move some stuff to Cosmos DB (noSQL) or Redis for queries if needed.
  7. It enforces consistency and makes it easy to group functionalities in the project.

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 and write 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.

余厌 2025-01-01 22:20:26

如果您发现问题域不太适合更通用的架构,或者您正在尝试域驱动设计,我建议您尝试一下 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

甜味超标? 2025-01-01 22:20:26

每个人都解释了为什么需要使用 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.)

enter image description here

独夜无伴 2025-01-01 22:20:26

简而言之,仅当应用程序速度非常重要以至于您准备为此牺牲时间和金钱并且不需要立即一致性时才使用 CQRS 模式。

他们说 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:

  • Scalability: You can have different Database for read and write.
  • Single responsibility.
  • Decoupling.
  • Testability.
  • Security.
  • Complexity removal.
  • Different teams: For example, one team works on commands and another works on queries.

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:

  • Eventual consistency: As query-database need to be aligned with the latest changes happening in the command-database, and it takes time to update query-database accordingly which may not suitable for some crucial situations (e.g., real-time payment or trade).
  • Complexity: This is not the end of the story. Your dilemma is just about to begin. CQRS doesn’t improve application’s velocity if you immediately apply each and every incoming change-request into the query-database Hence, you need to utilize a message broker to channelize and priorities changes toward query-database. You also may need a mechanism to apply those changes in batch; otherwise, the query-database performance degrades.
提笔落墨 2025-01-01 22:20:26

关于实现 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文