- 原文地址:How To Understand CQRS In Microservices Architecture
- 原文作者:Oleksii
- 译文出自:掘金翻译计划
在上一篇文章—如何实现微服务间的异步通信中中,我们讨论了通过消息代理来实现微服务间通信的总体思路。在本篇文章,我将会阐述微服务架构的一种特定模式—CQRS(命令与查询职责分离)。

问题描述
软件应用普遍需要数据库来负责读和写操作。通常,应用会实现一些非常简单的CRUD操作,存储一些数据并对其进行读取。

但是,在复杂应用中情况不会这么琐碎。每一个读和写操作都可能涉及大量的环节和约束。
例如
- 写:为了消除数据冗余并强制约束,数据库会以标准化的方式构建。读:复杂的读查询涉及大量影响性能的 joins/unions/aggregations(连接/联合/聚合) 操作。
- 读:需要通过建立索引来提升查询性能。写:每次写操作都会触发索引的更新。
- 读/写的表示方式可能不同,进而产生额外的逻辑。
- 对同一数据的并行操作可能会导致数据争用。
- 数据库的负载可能会导致性能降低。
CQRS
上述问题可以通过CQRS(命令与查询职责分离)来解决。

上图包含两个服务—酒店管理服务和酒店查询服务(事实上,如果需要,可能会有多个不同的数据库独立的查询服务)。不同服务间数据应该完全同步。开发者通常会使用一些消息代理工具(例如 Kafka)来同步数据。在这些服务中数据格式各不相同。
酒店管理服务负责增/改/删操作,每一种操作都可以用一个指令描述。
- 发起/批准/驳回 一个酒店创建请求。
- 向系统中 添加/更新 酒店房间。
- 修改酒店房间价格。
- 预订指定时间段的酒店房间。
- 请求附加服务。
- 请求 发表/通过/驳回 评论。
- 取消预订。
酒店查询服务负责向用户展示酒店和房间的列表。
- 列出一个城市中所有或可预定的酒店房间。
- 在地图上展示所有酒店(依据地理坐标过滤)。
- 向用户展示可用的筛选条件。
- 依据指定筛选条件筛选酒店房间(例如为很多人展示两个酒店房间而不是一间)。
显然,服务的责任各不相同。并且不同服务的性能要求也有差异,用户通常在决定预订房间之前会先浏览大量选项,使得这个系统中读操作的数量大大高于写操作。因此这些服务的容量会有所不同。
酒店管理服务可以使用RDBMS(关系型数据库),例如MySQL和PosgreSQL做数据存储,RDBMS的特性可以保证数据安全。
考虑到NoSQL(非关系型数据库)执行搜索查询时拥有更强大的能力,如非规范化,地理定位支持,索引,水平扩容等,酒店查询服务可以基于NoSQL 解决方案实现,例如MongoDB和Elasticsearch 。
CQRS的优势
- 责任分割
- 读写服务的容量缩放互相独立
- 适合读写操作的数据存储和模式
- 简单高效的查询
CQRS的劣势
- 复杂性
- 最终一致性
总结
本文探讨了CQRS模式。值得一提的是这种模式在复杂系统中有其必要性。因此为了避免不必要的复杂性,你需要慎重考虑是否在你的系统中采用CQRS。