如何理解微服务架构中的CQRS

602 阅读3分钟

在上一篇文章—如何实现微服务间的异步通信中中,我们讨论了通过消息代理来实现微服务间通信的总体思路。在本篇文章,我将会阐述微服务架构的一种特定模式—CQRS命令与查询职责分离)。

img

问题描述

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

Standard Architecture

但是,在复杂应用中情况不会这么琐碎。每一个操作都可能涉及大量的环节和约束。

例如

  • :为了消除数据冗余并强制约束,数据库会以标准化的方式构建。:复杂的读查询涉及大量影响性能的 joins/unions/aggregations(连接/联合/聚合) 操作。
  • :需要通过建立索引来提升查询性能。:每次操作都会触发索引的更新。
  • 读/写的表示方式可能不同,进而产生额外的逻辑。
  • 对同一数据的并行操作可能会导致数据争用。
  • 数据库的负载可能会导致性能降低。

CQRS

上述问题可以通过CQRS命令与查询职责分离)来解决。

CQRS (Command Query Responsibility Segregation)

上图包含两个服务—酒店管理服务酒店查询服务(事实上,如果需要,可能会有多个不同的数据库独立的查询服务)。不同服务间数据应该完全同步。开发者通常会使用一些消息代理工具(例如 Kafka)来同步数据。在这些服务中数据格式各不相同。

酒店管理服务负责增/改/删操作,每一种操作都可以用一个指令描述。

  • 发起/批准/驳回 一个酒店创建请求。
  • 向系统中 添加/更新 酒店房间。
  • 修改酒店房间价格。
  • 预订指定时间段的酒店房间。
  • 请求附加服务。
  • 请求 发表/通过/驳回 评论。
  • 取消预订。

酒店查询服务负责向用户展示酒店和房间的列表。

  • 列出一个城市中所有或可预定的酒店房间。
  • 在地图上展示所有酒店(依据地理坐标过滤)。
  • 向用户展示可用的筛选条件。
  • 依据指定筛选条件筛选酒店房间(例如为很多人展示两个酒店房间而不是一间)。

显然,服务的责任各不相同。并且不同服务的性能要求也有差异,用户通常在决定预订房间之前会先浏览大量选项,使得这个系统中操作的数量大大高于操作。因此这些服务的容量会有所不同。

酒店管理服务可以使用RDBMS关系型数据库),例如MySQLPosgreSQL做数据存储,RDBMS的特性可以保证数据安全。

考虑到NoSQL非关系型数据库)执行搜索查询时拥有更强大的能力,如非规范化,地理定位支持,索引,水平扩容等,酒店查询服务可以基于NoSQL 解决方案实现,例如MongoDBElasticsearch

CQRS的优势

  • 责任分割
  • 读写服务的容量缩放互相独立
  • 适合读写操作的数据存储和模式
  • 简单高效的查询

CQRS的劣势

  • 复杂性
  • 最终一致性

总结

本文探讨了CQRS模式。值得一提的是这种模式在复杂系统中有其必要性。因此为了避免不必要的复杂性,你需要慎重考虑是否在你的系统中采用CQRS