CQRS 是一种体系结构模式,用于分隔用于读取和写入数据的模型。 相关的术语 命令查询分离(CQS) 最初由Bertrand Meyer在他的书 Object-Oriented 软件建设中定义。 基本思路是,可以将系统的操作划分为两个截然不同的类别:
查询。 这些查询返回结果,不会更改系统的状态,并且它们没有副作用。
命令。 这些命令更改系统的状态。
CQS 是一个简单的概念:它是关于同一对象中的方法,即查询或命令。 每个方法都返回状态或改变状态,但不能同时返回两者。 即使是单个存储库模式对象也可以符合 CQS。 CQS 可被视为 CQRS 的基本原则。
指挥和查询责任分离(CQRS) 由格雷格·杨介绍,由乌迪·达汉等人大力推广。 它基于 CQS 原则,但更详细。 它可以被视为基于命令和事件以及异步消息(可选)的模式。 在许多情况下,CQRS 与更高级的场景相关,例如使用不同的物理数据库来进行读取(查询)和写入(更新)操作。 此外,一个不断发展的 CQRS 系统可能会为更新数据库实现 Event-Sourcing (ES), 因此你只会在域模型中存储事件,而不是存储当前状态数据。 但是,本指南中未使用此方法。 本指南使用最简单的 CQRS 方法,该方法只将查询与命令分开。
CQRS 的分离方面是通过将查询操作分组到一个层,将命令操作分组到另一个层来实现的。 每个层都有自己的数据模型(请注意,我们说模型,不一定是不同的数据库),并且是使用自己的模式和技术组合构建的。 更重要的是,这两个层可以位于同一层或微服务中,如本指南中使用的示例(订购微服务)。 或者,可以在不同的微服务或进程中实现它们,以便可以单独优化和横向扩展,而不会影响彼此。
CQRS 的意思是在读写操作中拥有两个对象,而在其他上下文中通常只有一个对象。 有理由拥有非规范化读取数据库,你可以在更高级的 CQRS 文献中了解该数据库。 但是,我们在这里没有使用这种方法,目标是在查询中具有更大的灵活性,而不是限制包含来自 DDD 模式(如聚合)的约束的查询。
此类服务的一个示例是 eShopOnContainers 引用应用程序中的订购微服务。 此服务基于简化的 CQRS 方法实现微服务。 它使用单个数据源或数据库,但两个逻辑模型加上事务域的 DDD 模式,如图 7-2 所示。
图 7-2. 基于 CQRS 和 DDD 的简化版微服务
逻辑“排序”微服务包括其排序数据库,该数据库可以位于同一个 Docker 主机,但不一定必须如此。 在同一 Docker 主机中拥有数据库适用于开发,但不适用于生产环境。
应用程序层可以是 Web API 本身。 此处的重要设计方面是,微服务已根据 CQRS 模式从命令、域模型和事务拆分查询和 ViewModels(尤其是为客户端应用程序创建的数据模型)。 此方法使查询独立于来自 DDD 模式的限制和约束,这些模式仅对事务和更新有意义,如后面的部分所述。
其他资源
- 格雷格·杨 事件源系统中的版本控制 (免费阅读在线电子书)
https://leanpub.com/esversioning/read