`
liuzhaodong89
  • 浏览: 59811 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

CQRS——命令与查询职责分离【翻译】

阅读更多

CQRS

翻译自大牛Martin Fowler的CQRS。原文地址:http://martinfowler.com/bliki/CQRS.html

==================================================================

CQRS代表着命令查询责任分离。我第一次听到这个模式是从Greg Young那里。这个模式的核心就是你在更新数据时所使用的模型可以与读取和查询时所用的数据模型不一样。这个最为简单的概念实际上却引出了在信息系统设计上具有深远意义的一些结论。

实际上用户与信息系统进行交互的主旋律方式,还是将信息系统当做一个能做增删改查的数据库。我的意思是指当我们新增记录、修改记录、读取记录和删除记录的时候,我们对它实际上已经建立了心智模型。在最简单的场景里,我们对数据的操作实际上就是写入和读出两种。

然而随着我们的需求变得越来越复杂,系统实现也一点一点的脱离最初的模型。也许我们希望能够有其他的方式来查阅数据库中的数据,比如将多条数据扁平化为一条,或者将来源于不同系统的数据组成虚拟的记录来展现。在存储端我们也许会发现校验规则或许只允许固定的几种数据组合被持久化,甚至要求用不同于上层提供的数据模型的方式来持久化数据。

当这些情况发生的时候我们开始思考信息的多种表现方式。当用户对用户进行互动操作的时候,他们会使用各种不同的数据展现样式,其中每一种实际上都是一种具有代表性的模式。开发人员通常会在开发时建立他们自己的模型来操纵系统模型中所用的核心部分。如果你在使用一个领域模型,那么它通常是对一个领域在概念上具有代表性的模型。你也可以将持久化的数据模型设计的尽可能与概念模型一致。

这种多层次的代表性模式架构可能会很复杂,但在实际应用中程序员通常会将其简化为一个的概念上的代表模型,而这个代表模型聚合了所有的展现方式。

CQRS带来的变化就是将原本统一的概念模型拆分成更新和查询时所使用的不同模型,就是CommandQuerySeparation这个单词中的命令(Command)和查询(Query)。这么做的原理是对于很多问题,尤其是那种十分复杂的领域,执行命令和进行查询时使用相同的模型会导致更加复杂的情况,而且此时的模型可能对哪种情况都无法完全满足。

通过拆分模型我们通常会隐含的暗示着这是不同的模型对象,可能运行在不同的逻辑流程中,甚至可能是在不同的硬件资源上。一个web上的例子是,用户看到的页面是通过查询模型渲染出来的。如果用户提交了一个变更,这个变更路由到了正确的命令模型上并且执行了,那么作为结果查询模型会通过通信的方式获知这个变更并更新渲染出的数据。

当然我们也为可能的变化做了提前准备。内存中的多种模型可能会基于同一个数据库,此时数据库作为不同模型间的数据沟通方式。与此同时不同的模型间也可以依赖不同的数据库,比如通过采用报告型数据库来高效的搭建起查询端的数据库。在这种情况下就需要其他的数据沟通方式来完成模型或数据库间的数据同步问题。

查询和命令两种场景下的模型不一定是两个完全不同的模型,他们也许只是有着不同的接口用以满足所在的场景。这更类似于数据库中的视图概念。但是当提到CQRS的时候,有一个清晰的信号就是这些模型是完全不同的。

CQRS天然的能够与其他一些架构模式相配合。

当我们抛弃原有的基于增删改查方式的代表模式时,可以轻易的迁移到基于任务的UI界面上。

以命令模式作为蓝本设计会自然而然的使用到命令和事件,而这些又引出了事件溯源。

同时拥有多个独立的模型增加了保持数据一致性的难度,同时也增加了使用最终一致性策略的可能性。

在许多领域里,更新数据时可能会涉及到大量的规则校验,所以采用饥饿式更新的策略可以简化查询端的复杂度。

增删改查的方式适用于比较复杂的领域,但同时领域驱动模式也适用。

什么时候使用?

和其他的模式一样,CQRS也有适用的场景。许多的系统本身更加适合用传统的增删改查模式,那么就应该用那个模式。CQRS对于所有人来说在思维上都是一个大的跳跃,所以除非你真的清楚CQRS能带给你的好处否则不要轻易尝试。

尤其CQRS应该只在一个系统的特定部分中(DDD中所说的有边界的上下文)使用而非整个系统。以此推而广之,一个系统中的每个具有边界的上下文领域都应该根据其自身特点决定建模方式。

到目前为止,我看到的CQRS带来的益处有两个方面。首先是对复杂性的掌控——一个复杂的领域可能更加适合CQRS。我必须要澄清的是,实际上仍然有很多情况下查询和命令共享数据模型会更简单,这个必须具体问题具体分析。

另一个好处是对高性能的支撑能力。CQRS能够让你将读和写分开,使得单独对读或写进行扩展变的很容易。如果你的系统在读和写两方面有非常大的不同,那么CQRS会很适合。即便不能如此,你也可以针对两个方面各自选择最优的优化方案。一个例子就是对读和写采用不同的数据库读取方案。

如果你的系统不适合使用CQRS,但同时也面临复杂度或者性能的问题,别忘了你可以使用从属数据库(ReportingDatabase)。CQRS中所有的查询都使用不同的数据模型。通过从属数据库你可以继续用主库支撑绝大部分的请求,将对应的更吃力的请求转移到从属数据库上。

目前为止我们还没有足够的CQRS实践经验,无法对其好处和缺点完全了解。所以尽管CQRS是一个我很喜欢的模式,但我不会将它放到第一优先级上。

分享到:
评论
1 楼 fei33423 2014-06-10  
1. 事件溯源 命令模式 术语 最好不要翻译,或者 斜体 带上原文 event source.
2. 增删改查的方式适用于比较复杂的领域 错了, 原文是 CQRS 不是增删改查

相关推荐

    dotnet-一个基于DDD领域驱动设计CQRS命令查询职责分离的netcore框架

    一个基于 DDD 领域驱动设计 CQRS 命令查询职责分离 的 .net core 框架,完全开源。ASP.NET Core 2.1 应用, 包含 DDD、CQRS 和事件回溯。

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

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

    SimpleCQRSExample:.Net 中命令和查询职责分离的简单示例

    简单的 CQRS 示例 .Net 中命令和查询职责分离的简单示例 博客文章

    CQRS:通用命令CQRS [命令和查询责任隔离]

    CQRS:通用命令CQRS [命令和查询责任隔离]

    CQRS读写分离模式的例子

    CQRS读写分离模式的例子

    CQRS介绍 CQRS概述

    简单的说,就是一个系统,从架构上把它拆分为两部分:命令处理(写请求)+查询处理(读请求)。然后读写两边可以用不同的架构实现,以实现CQ两端(即Command Side,简称C端;Query Side,简称Q端)的分别优化。CQRS...

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

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

    cqrsjs:CQRS 模式适用于 javascript

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

    CQRS-Commands-API:使用Web API从CQRS实现命令的示例

    CQRS命令API 使用Web API从CQRS实施命令的示例 依存关系 .NET 5 调解员 内容描述 仅执行命令

    event-sourcing, Meteor的CQRS和事件采购基础架构.zip

    event-sourcing, Meteor的CQRS和事件采购基础架构 用于 Meteor的 CQRS &事件源 这个包提供了构建你的Meteor 应用程序的基础设施,以英镑 ( 命令/查询职责分离) 和英镑事件采购原则为基础。 这样可以使用强大的业务...

    CQRS架构实例

    一个教科书式的基于C#的CQRS架构,对了解领域驱动设计和命令职责分离原则的思想有很大的帮助。

    CQRS 探索之旅

    CQRS 旅程CQRS 旅程CQRS 旅程CQRS 旅程CQRS 旅程CQRS 旅程

    探索CQRS和事件源(微软云)

    4.2.4CQRS命令验证55 4.2.5倒计时定时器和读者模型56 4.3实现细节56 4.3.1订单访问码(记录定位器)57 4.3.2倒计时定时器58 4.3.3使用ASP.NET MVC验证60 4.3.4将改动推送到读者端62 4.3.5重构SeatsAvailability ...

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

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

    cqrs-quarkus-kafka:使用Quarkus和Kafka实现CQRS架构

    关于CQRS-命令查询职责隔离 根据 其核心思想是,您可以使用与用于读取信息的模型不同的模型来更新信息。 在某些情况下,这种分离可能很有价值,但请注意,对于大多数系统,CQRS会增加风险的复杂性。 应用程序 模拟...

    Nette-CQRS-Commands:Nette 框架的简单 CQRS 命令

    ###将命令与 Nette 中的服务连接起来。 此扩展提供了 CQRS 命令的简单实现。 安装: 安装 Nette-CQRS-Commands 的最佳方法是使用 : $ composer require adamstipak/nette-cqrs-commands 用法: 命令示例: ...

    CQRS代码示例

    CQRS的完整分层代码示例,CQRS的完整分层代码示例,CQRS的完整分层代码示例,CQRS的完整分层代码示例,CQRS的完整分层代码示例。

    探索CQRS和事件源

    4.2.4 CQRS命令驗證55 4.2.5 倒計時定時器和讀者模型56 4.3 實現細節56 4.3.1 訂單訪問碼(記錄定位器)57 4.3.2 倒計時定時器58 4.3.3 使用ASP.NET MVC驗證60 4.3.4 將改動推送到讀者端62 4.3.5 重構...

    quarkus-cqrs

    关于CQRS-命令查询职责隔离根据其核心思想是,您可以使用与用于读取信息的模型不同的模型来更新信息。 在某些情况下,这种分离可能很有价值,但请注意,对于大多数系统,CQRS会增加风险的复杂性。应用程序模拟最终...

Global site tag (gtag.js) - Google Analytics