你真的了解什么是CQRS吗?

Posted 系统工程实验室

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的了解什么是CQRS吗?相关的知识,希望对你有一定的参考价值。

CQRS本身并不是一种架构风格,和最终一致性/消息/读写分离/事件溯源/DDD等没有必然的联系。CQRS只是一种非常简单的模式(pattern),它的最大优势是CQRS给我们带来更多的架构属性选择

CQRS 本质

CQRS 全称 Command and Query Responsibility Segregation,即命令和查询职责分离。CQRS 模式的应用非常简单,如下图所示

假设我们的服务为 CustomerService,在非CQRS模式下同时包含了查询和更新服务接口:

//  根据id查询消费者
Customer GetCustomer(CustomerId)
// 根据姓名查询消费者
CustomerSet GetCustomersWithName(Name)
// 创建消费者
void CreateCustomer(Customer)
// 编辑消费者详情
void EditCustomerDetails(CustomerDetails)

应用CQRS模式之后的CustomerWriteService被拆分成了两个接口,分别承担查询和更新操作:

void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

CustomerReadService

Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)

以上这种简单的分离就是CQRS模式的全部了,是不是非常简单?确实,单纯的看,CQRS的确就是这么简单。另外,从上述的示例我们还可看出CQRS的一个特点:

  • 查询职责值获取数据,返回查询数据,但不改变数据状态

  • 命令职责改变数据状态,不返回任何数据

是否严格遵循上述约定存在争议,像栈这种数据结构显然是不符合如上约定的。"出栈" 操作同时改变栈状态和返回数据。

CQRS最大优势就是基于这种职责分离能带给我们更多的架构属性选择。

  1. “读” 和 “写” 两侧进行独立部署以获取更好的伸缩性

  2. “读” 和 “写” 两侧独立架构设计

  3. “读” 和 “写” 两侧进行独立数据模型设计

基于CQRS,我们可以衍生出更多的架构属性,结合实际的业务场景,进行差异化的架构设计。

CQRS 和 消息模式

CQRS和消息模式没有必然联系,落地CQRS 并不一定需要使用消息模式。

如果我们采用了CQRS模式,但是命令和查询两侧底层所依赖的数据模型并未分离,而是基于共享的数据存储和数据模型,命令和查询之间不需要额外的交互,命令侧的数据更新对查询侧实时可见。在这种架构模式下,两侧基于共享的数据已经天然的集成在一起,不需要额外机制进行通信,自然也无需引入消息了。如果我们采用CQRS模式,并且命令和查询两侧进行了数据模型的分离,二者各自依赖独立的数据模型。同时,数据存储也分开部署。命令侧负责数据的更新,而查询侧只负责数据的查询,如何将数据的更新及时同步到查询侧是需要解决的问题。在这种架构模式下,使用消息模式作为两侧的通信机制是个不错的选择,当然,这并不是唯一的选项。

CQRS 和 ES(Event Sourcing, 事件溯源)

ES 并不是一个新的概念,在最早的金融系统中就已经应用。要了解ES,我们需要先看看传统的数据存储。在传统应用中,数据库例如mysql(假设存储介质是数据库,)中存储的始终是数据的最新的状态。例如我们对某条用户的信息进行了多次的修改或编辑,然后保存将数据存储到数据库中。无论何时,数据库中都会记录最后的、最新的用户状态。我们只要根据id或其他信息查询数据库中相应的记录就能获取该用户的最新信息。这是应用中典型的数据存储特点。

当然,我们可以基于特定的数据模型设计以保存数据的更改记录。

这种数据存储模式的特点是简单,不需要额外的维护复杂的设计,我们能够非常容易的获取最新的用户信息。但是不幸的是,我们丢失了历史信息,包括用户的意图信息。而这些信息则有助于我们进行数据回滚、用户行为分析以及开发过程中的调试等等。

在ES模式下,数据库中存储的不在是数据最新状态,而是数据的变更记录,更官方的说法是 “事件(Event)”。数据库中存储的数据变化的事件流。我们基于事件流可以对最新状态进行重建,同时也可以便捷的重现任何历史节点数据。ES需要解决大量事件的存储和高效的实例重建问题,后续单独的文章再介绍ES。

CQRS 和 Eventual Consistency(最终一致性)

最终一致性也常常在服务之间引入,最终一致性的目的是为了提高扩展性和可用性。CQRS和最终一致性同样没有必然的联系。往往采用CQRS后,查询和命令两侧会采用独立的数据模型,在这种架构模式下,命令侧的数据变化后及时同步到查询侧,两侧数据并非实时,在一定的延时后两侧数据最终达成一致。

以上是关于你真的了解什么是CQRS吗?的主要内容,如果未能解决你的问题,请参考以下文章

你真的了解低代码平台吗?

什么是类加载,又有哪些类加载器你真的了解吗?

CRUD玩的这么溜,你知道CQRS吗?

Python是什么?你真的了解Python吗?

04-字典集合,你真的了解吗

你真的了解方法吗?