`
gaojingsong
  • 浏览: 1154948 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

【CQRS 命令查询职责分离模式介绍】

阅读更多

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.

  • 大小: 125.8 KB
  • 大小: 144.7 KB
  • 大小: 77.8 KB
0
0
分享到:
评论

相关推荐

    浅谈命令查询职责分离(CQRS)模式

    本文介绍了命令查询职责分离模式(CommandQueryResponsibilitySegregation,CQRS),该模式从业务上分离修改(Command,增,删,改,会对系统状态进行修改)和查询(Query,查,不会对系统状态进行修改)的行为。...

    spring-boot-103:满足命令查询责任分离(CQRS)模式实现的两个应用程序

    满足命令查询职责隔离(CQRS)模式实现的两个应用程序。 简单的CQRS CQRS代表命令查询责任隔离。 它是一种设计模式,用于强制将修改应用程序状态的操作与使应用程序状态保持完整的操作分开。 引用:“对象被分为两...

    CQRS体系结构模式实践案例:TinyLibrary

    读过我这一系列文章的朋友一定听说过Apworks框架,虽然这个框架至今仍未成熟到能够用在...在阅读本系列文章之前,如果您对领域驱动设计(DDD)、命令与查询职责分离(CQRS)、事件溯源(EventSourcing)、事件存储

    DDD中的那些模式—CQRS

    DDD作为一种系统分析的方法论,最大的问题是如何在项目中实践。而在实践过程中必然会面临许多的问题,「模式」是系统架构领域中一种常见的...CQRS,中文名为命令查询职责分离。 毋庸置疑「领域」在DDD中占据了核心的地

    cqrs-sample:命令调度程序模式示例项目

    命令查询职责分离Projeto de exemplo do 模式 CQRS using System . Threading . Tasks ;using System . Web . Mvc ;namespace Sample . CQRS . MVC . Controllers{public class HomeController : Controller{private...

    cqrsjs:CQRS 模式适用于 javascript

    cqrs 表示命令和查询职责分离。 它来自遥远的地方,所以将是一个更好的地方来了解更多。安装npm install --save cqrs.jsbower install --save cqrs.js require ( [ 'cqrsjs' , ...例子建立在 restify 和 socket.io ...

    WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例

    我经过两周业余时间的努力,凭着自己对微服务架构的理解,从无到有,基于.NET打造了一个演示微服务架构的应用程序案例,并结合领域驱动设计(DDD)以及命令查询职责分离(CQRS)体系结构模式,对事件驱动的微服务...

    akka-persistence-mongo-samples:使用 Akka Persistence Plugin for Mongo 的示例应用程序

    除了 Akka 持久性之外,还探讨了其他主题,例如 (命令查询职责分离)、命令源、 和分布式域模型。 免责声明 请注意,虽然所有示例代码都编译通过并测试通过,但它仅用于示例目的,绝不应被解释为生产就绪代码。 ...

    lab-springboot-rest-sample:Spring Boot RESTful 服务的示例代码

    lab-springboot-rest-sample Spring Boot RESTful 服务研讨会的示例代码该代码基于 Greg Young 引入的 CQRS 模式(命令查询职责分离),将读/写操作的模型解耦。 Martin Fowler 在他的博客 ( ) 中更好地描述了该模式...

    贝岭的matlab的代码-dotnet-challenge:dotnet-挑战

    贝岭的matlab的代码Cdiscount 的 .NetCore 挑战 结果:挑战结束,获胜者...CQRS(命令查询职责分离) 参加 在本地克隆存储库; 项目编译通过,但 6 个测试失败; 完成ArmsController和SqlServerArmRepository类中的实

    clean-flutter-app:使用TDD,Clean Architecture,设计模式和SOLID原理的Flutter应用程序

    4Dev Flutter-程序员的民意测验 ... 命令查询职责隔离(CQRS) 继承而不是继承 小承诺 设计模式 工厂 适配器 合成的 装潢师 依赖注入 抽象服务器 组成根 建造者 辛格尔顿 观察者 战略 AAA(安排,行动和主张)

    java区块链源码完整可运行-Programming-Is-Awesome:软件开发框架和工具的集合

    命令和查询职责分离 (CQRS) 是一种模式,它通过使用单独的接口将读取数据的操作(查询)与更新数据的操作(命令)分离。 - 事件溯源将每个业务实体作为事件序列持久化,并且事件是不可变的。 - 物化视图是包含查询...

Global site tag (gtag.js) - Google Analytics