CQRS stands for Command Query Responsibility Segregation.
The mainstream approach people use for interacting with an information system is to treat it as a CRUD datastore. By this I mean that we have mental model of some record structure where we can create new records, read records, update existing records, and delete records when we're done with them. In the simplest case, our interactions are all about storing and retrieving these records.
CQRS最早来自于Betrand Meyer(Eiffel语言之父,开-闭原则OCP提出者)在 Object-Oriented Software Construction 这本书中提到的一种 命令查询分离 (Command Query Separation,CQS) 的概念。其基本思想在于,任何一个对象的方法可以分为两大类:
命令(Command):不返回任何结果(void),但会改变对象的状态。
查询(Query):返回结果,但是不会改变对象的状态,对系统没有副作用。
As our needs become more sophisticated we steadily move away from that model. We may want to look at the information in a different way to the record store, perhaps collapsing multiple records into one, or forming virtual records by combining information for different places. On the update side we may find validation rules that only allow certain combinations of data to be stored, or may even infer data to be stored that's different from that we provide.
As this occurs we begin to see multiple representations of information. When users interact with the information they use various presentations of this information, each of which is a different representation. Developers typically build their own conceptual model which they use to manipulate the core elements of the model. If you're using a Domain Model, then this is usually the conceptual representation of the domain. You typically also make the persistent storage as close to the conceptual model as you can.
This structure of multiple layers of representation can get quite complicated, but when people do this they still resolve it down to a single conceptual representation which acts as a conceptual integration point between all the presentations.
The change that CQRS introduces is to split that conceptual model into separate models for update and display, which it refers to as Command and Query respectively following the vocabulary of CommandQuerySeparation. The rationale is that for many problems, particularly in more complicated domains, having the same conceptual model for commands and queries leads to a more complex model that does neither well.
By separate models we most commonly mean different object models, probably running in different logical processes, perhaps on separate hardware. A web example would see a user looking at a web page that's rendered using the query model. If they initiate a change that change is routed to the separate command model for processing, the resulting change is communicated to the query model to render the updated state.
There's room for considerable variation here. The in-memory models may share the same database, in which case the database acts as the communication between the two models. However they may also use separate databases, effectively making the query-side's database into a real-time ReportingDatabase. In this case there needs to be some communication mechanism between the two models or their databases.
The two models might not be separate object models, it could be that the same objects have different interfaces for their command side and their query side, rather like views in relational databases. But usually when I hear of CQRS, they are clearly separate models.
CQRS模式有一些优点:
1、分工明确,可以负责不同的部分
2、将业务上的命令和查询的职责分离能够提高系统的性能、可扩展性和安全性。并且在系统的演化中能够保持高度的灵活性,能够防止出现CRUD模式中,对查询或者修改中的某一方进行改动,导致另一方出现问题的情况。
3、逻辑清晰,能够看到系统中的那些行为或者操作导致了系统的状态变化。
4、可以从数据驱动(Data-Driven) 转到任务驱动(Task-Driven)以及事件驱动(Event-Driven).
在下场景中,可以考虑使用CQRS模式:
1、当在业务逻辑层有很多操作需要相同的实体或者对象进行操作的时候。CQRS使得我们可以对读和写定义不同的实体和方法,从而可以减少或者避免对某一方面的更改造成冲突
2、对于一些基于任务的用户交互系统,通常这类系统会引导用户通过一系列复杂的步骤和操作,通常会需要一些复杂的领域模型,并且整个团队已经熟悉领域驱动设计技术。写模型有很多和业务逻辑相关的命令操作的堆,输入验证,业务逻辑验证来保证数据的一致性。读模型没有业务逻辑以及验证堆,仅仅是返回DTO对象为视图模型提供数据。读模型最终和写模型相一致。
3、适用于一些需要对查询性能和写入性能分开进行优化的系统,尤其是读/写比非常高的系统,横向扩展是必须的。比如,在很多系统中读操作的请求时远大于写操作。为适应这种场景,可以考虑将写模型抽离出来单独扩展,而将写模型运行在一个或者少数几个实例上。少量的写模型实例能够减少合并冲突发生的情况
4、适用于一些团队中,一些有经验的开发者可以关注复杂的领域模型,这些用到写操作,而另一些经验较少的开发者可以关注用户界面上的读模型。
5、对于系统在将来会随着时间不段演化,有可能会包含不同版本的模型,或者业务规则经常变化的系统
6、需要和其他系统整合,特别是需要和事件溯源Event Sourcing进行整合的系统,这样子系统的临时异常不会影响整个系统的其他部分。
但是在以下场景中,可能不适宜使用CQRS:
1、领域模型或者业务逻辑比较简单,这种情况下使用CQRS会把系统搞复杂。
2、对于简单的,CRUD模式的用户界面以及与之相关的数据访问操作已经足够的话,没必要使用CQRS,这些都是一个简单的对数据进行增删改查。
3、不适合在整个系统中到处使用该模式。在整个数据管理场景中的特定模块中CQRS可能比较有用。但是在有些地方使用CQRS会增加系统不必要的复杂性
CQRS naturally fits with some other architectural patterns.
1)As we move away from a single representation that we interact with via CRUD, we can easily move to a task-based UI.
2)CQRS fits well with event-based programming models. It's common to see CQRS system split into separate services communicating with Event Collaboration. This allows these services to easily take advantage of Event Sourcing.
3)Having separate models raises questions about how hard to keep those models consistent, which raises the likelihood of using eventual consistency.
4)For many domains, much of the logic is needed when you're updating, so it may make sense to use EagerReadDerivation to simplify your query-side models.
5)If the write model generates events for all updates, you can structure read models as EventPosters, allowing them to be MemoryImages and thus avoiding a lot of database interactions.
6)CQRS is suited to complex domains, the kind that also benefit from Domain-Driven Design.
When to use it
Like any pattern, CQRS is useful in some places, but not in others. Many systems do fit a CRUD mental model, and so should be done in that style. CQRS is a significant mental leap for all concerned, so shouldn't be tackled unless the benefit is worth the jump. While I have come across successful uses of CQRS, so far the majority of cases I've run into have not been so good, with CQRS seen as a significant force for getting a software system into serious difficulties.
In particular CQRS should only be used on specific portions of a system (a BoundedContext in DDD lingo) and not the system as a whole. In this way of thinking, each Bounded Context needs its own decisions on how it should be modeled.
The other main benefit is in handling high performance applications. CQRS allows you to separate the load from reads and writes allowing you to scale each independently. If your application sees a big disparity between reads and writes this is very handy. Even without that, you can apply different optimization strategies to the two sides. An example of this is using different database access techniques for read and update.
If your domain isn't suited to CQRS, but you have demanding queries that add complexity or performance problems, remember that you can still use a ReportingDatabase. CQRS uses a separate model for all queries. With a reporting database you still use your main system for most queries, but offload the more demanding ones to the reporting database.
Despite these benefits, you should be very cautious about using CQRS. Many information systems fit well with the notion of an information base that is updated in the same way that it's read, adding CQRS to such a system can add significant complexity. I've certainly seen cases where it's made a significant drag on productivity, adding an unwarranted amount of risk to the project, even in the hands of a capable team. So while CQRS is a pattern that's good to have in the toolbox, beware that it is difficult to use well and you can easily chop off important bits if you mishandle it.
相关推荐
《基于DDD领域驱动设计与CQRS命令查询职责分离的.NET Core框架详解》 在软件开发领域,领域驱动设计(Domain-Driven Design,简称DDD)和CQRS(Command Query Responsibility Segregation,命令查询职责分离)是两...
本文介绍了命令查询职责分离模式(CommandQueryResponsibilitySegregation,CQRS),该模式从业务上分离修改(Command,增,删,改,会对系统状态进行修改)和查询(Query,查,不会对系统状态进行修改)的行为。...
**CQRS(命令查询责任分离)模式详解** CQRS,全称为Command Query Responsibility Segregation,中文译为“命令查询责任分离”模式。这是一种设计模式,主要用于处理复杂的分布式系统中的数据管理,通过将读操作...
满足命令查询职责隔离(CQRS)模式实现的两个应用程序。 简单的CQRS CQRS代表命令查询责任隔离。 它是一种设计模式,用于强制将修改应用程序状态的操作与使应用程序状态保持完整的操作分开。 引用:“对象被分为两...
**CQRS(命令查询职责分离)**是一种设计模式,它将应用程序的读写操作分离,使得处理命令(写操作)和执行查询(读操作)在不同的对象或服务中进行。这种模式可以提高系统的可伸缩性和性能,尤其适用于大数据量和高...
本篇文章将深入探讨一个遵循Clean、领域驱动设计(DDD)、Saga、命令查询职责分离(CQRS)和六边形架构设计模式的食品订购系统,同时结合Python编程语言的应用,以揭示这些模式如何协同工作,构建出高效、可扩展的...
CQRS(Command Query Responsibility Segregation,命令查询职责分离)是一种软件设计模式,它将读取操作和写入操作分离,旨在提高系统的可读性、可维护性和性能。CQRS的核心思想是将一个应用程序的模型分为两个独立...
在软件开发领域,领域驱动设计(Domain-Driven Design, DDD)和命令查询职责分离(Command Query Responsibility Segregation, CQRS)是两种重要的设计模式,它们旨在提高复杂系统的可维护性和性能。本文将基于...
【CQRS(命令查询责任分离)】 CQRS(Command Query Responsibility Segregation)是CQS原则的扩展,特别是在分布式系统和领域驱动设计(DDD)中更为常见。CQRS建议将读操作和写操作分离到不同的模型或服务中,从而...
**CQRS(命令查询责任分离)**是一种软件设计模式,它将读操作和写操作分离,使得系统在处理复杂业务逻辑时能保持高可读性和高性能。CQRS的核心思想是,一个模型不适合处理所有的应用程序操作,因此,我们将系统分为...
本项目是一个基于ASP.NET Core和CQRS(命令查询职责分离)框架开发的身份验证与企业管理系统。项目主要功能包括用户身份验证、授权管理、企业信息管理等。通过CQRS模式,系统能够高效地处理命令和查询,确保数据的...
命令查询职责分离(CQRS)将命令(写操作)和查询(读操作)分离,提高系统的性能和可扩展性。 事件溯源记录所有事件,确保系统的可追溯性和数据一致性。 事件驱动架构(EDA)通过事件驱动的方式实现系统的松耦合...
CQRS,即Command Query Responsibility Segregation(命令查询职责分离),是一种软件设计模式,源自Erik Evans的《领域驱动设计》一书。该模式的核心思想是将一个应用程序的读写操作分离,形成两个独立的模型:一个...
在本案例中,我们将深入探讨JdonFramework如何与CQRS(命令查询职责分离)和Event Sourcing(事件溯源)模式相结合,以实现JdonFrameworkTest的应用。 CQRS,全称为Command Query Responsibility Segregation,是一...
在.NET开发领域,CQRS(命令查询职责分离)和事件源是两种先进的设计模式,用于构建可扩展、高性能和高可用性的分布式系统。本示例程序"FoxOffice"旨在教授开发者如何利用这些技术来构建一个.NET Core应用程序。下面...
CQRS(Command Query Responsibility Segregation)是一种软件架构模式,它提倡将系统的命令(修改数据)与查询(读取数据)职责分离。这种模式对于构建高度可扩展、可维护的应用程序特别有用,尤其是在复杂的业务...
CQRS的核心理念是将系统中的读操作(查询)与写操作(命令)分离,每个部分都有专门的模型来处理,从而实现职责明确、模块化的系统设计。 在传统的单一职责原则中,一个类或方法同时负责读取数据和修改数据。但随着...
Axon框架是一种轻量级的Java框架,其核心设计思想是基于领域驱动设计(Domain-Driven Design,DDD)的命令查询职责分离(Command Query Responsibility Segregation,CQRS)模式。CQRS模式将系统的读取和写入操作...