news 2026/7/15 18:09:31

CQRS的两种设计方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CQRS的两种设计方式

明整理:CQRS 到底有哪几种常见设计方式,以及在实际项目中该如何选择。

版本 1:Event Sourcing + CQRS(最常见的讨论版本)

上面这张图是最常见的 Event Sourcing + CQRS 架构,流程大致如下:

  1. Client 发送 Command 请求到 Command Service。
  2. Command Service 执行 Aggregate(聚合根)业务逻辑,产生 Domain Event,并写入 Event Store。
  3. 同时将 Domain Event 发布到 Event Bus。
  4. Query Service 订阅 Event Bus 并接收 Domain Event。
  5. Query Service 将变更同步到查询侧数据库(Read Model DB)。

下面先看 Event Sourcing(ES)的优缺点。

最开始只有 Event Sourcing

Event Sourcing 严格来说是在 DDD 圈子里被大规模推广的,其核心概念是:

数据库只存 Domain Event,而不是传统的 Domain State(领域对象当前状态)。

因为在 DDD 中,Aggregate 的变化会产生 Domain Event,所以理论上只保留事件流也可以重建最终状态。

这样做的好处通常有:

  1. 有所有事件的存档,意味着可以恢复到任一时间点下的状态。
  2. 因为有整个状态的变更历史记录,有利于排查问题。
  3. 一定程度上减少状态与事件“双写不一致”问题。若采用状态存储,需要确保状态持久化与事件发布在同一事务边界内;而 Event Sourcing 天然以事件为事实来源。
  4. 可以降低并发写冲突复杂度。事件通常是追加写,不是原地更新(但仍需要处理 duplicate event 和幂等)。

PS:第 3 点在非 Event Sourcing 架构里也可以通过 transactional outbox(发件箱模式)来解决。

为什么这里会出现 CQRS?

因为每次查询都从事件流重放来恢复状态,读取成本高,所以才需要 CQRS。

在大多数业务系统里,Query 次数远大于 Command。纯 ES 的“写优化”并不能直接满足查询性能诉求,因此通常要引入读模型(Read Model),也就是 CQRS 中的 Query 模式。

这个版本有什么问题?

  • Write Service 不直接保存对象最终状态,某些“先读再写”的业务判断会变复杂,且会遇到读写延迟。
  • 存储与运维成本较高(事件量膨胀、回放成本、快照策略、归档策略等)。
  • 事件模型演进困难:当事件结构变化时,历史事件兼容、重放逻辑、Query 侧投影都要一起考虑。
  • 数据同步是最终一致性,不是强一致性。
  • 事务边界与失败补偿设计复杂(发布失败、重复消费、顺序保证、幂等处理等)。

版本 2:读写分离(更常见的工程化 CQRS)

我认为这才是 CQRS 在工程实践中的主流形态:将模型拆分为两套职责。

  • Write:用 DDD 处理业务规则、状态变更与持久化。
  • Query:围绕 UI 与报表需求,做高性能、可定制查询。

Write 与 Query 分开的原因在于:

Aggregate Model 并不天然适合查询场景:查询成本高,且字段结构不一定匹配前端展示需求。

这种设计方式的常见好处:

  • 职责边界清晰:哪些是 Command、哪些是 Query 一目了然,能显著减少在查询流程里“顺手改数据”的问题。
  • 模型解耦:不会为了查询便利去污染 Aggregate 模型,符合单一职责原则。
  • 支持物理隔离与异构存储:例如写入 MySQL、同步到 PostgreSQL 或 Elasticsearch 做查询。

我在项目里通常采用这种方式。很多开发者也有类似实践,例如 Amichai Mantinband 在视频 Understand Clean Architecture in 7 Minutes 中提到的设计,本质上也是在 Application 层做命令与查询分离。

小结

实际项目中,大多数团队会优先落地“读写分离版 CQRS”,而不是“Event Sourcing + CQRS 全家桶”。

Event Sourcing + CQRS 并非不能用,但它更适合这些场景:

  • 对审计追踪、可回放、时点恢复有强需求。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 21:00:21

基于SpringBoot的学生选课系统设计与实现

摘 要 随着高校办学规模扩大与学分制全面推行,课程种类不断增加,学生选课需求日趋多元。传统人工登记与线下选课模式流程繁琐、数据处理缓慢,易出现信息误差与课程冲突问题,难以适配智慧校园建设节奏,在此背景下&…

作者头像 李华
网站建设 2026/7/13 5:15:18

计算机毕业设计之电影购票推荐网站的设计与实现

随着信息化时代的到来,网络系统都趋向于智能化、系统化,电影购票推荐网站也不例外,但目前国内的有些电影院仍都使用人工管理,电影院规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化…

作者头像 李华
网站建设 2026/7/13 5:15:20

YOLO轻量化与部署优化- 第80篇:模型压缩与部署的综合优化指南

一、引言 在深度学习模型从实验室走向实际应用的过程中,模型压缩与部署优化是不可或缺的关键环节。YOLOv8作为当前最先进的目标检测算法,虽然在精度上取得了优异表现,但其较大的计算量和参数量给资源受限的部署环境带来了巨大挑战。如何在保证精度的前提下,尽可能地压缩模…

作者头像 李华
网站建设 2026/7/13 5:15:20

记一次 .NET 某注塑模具系统 CPU爆高分析

讲故事前些天有位朋友在微信上找到我,说他们的系统出现了CPU爆高,找不到原因,让我帮忙看一下,dump也拿出来了,接下来上windbg分析。二:CPU爆高分析1. 真的爆高吗dump的分析第一原则就是相信数据&#xff0c…

作者头像 李华
网站建设 2026/7/13 5:16:34

Docker--认识Docker网络

Network NamespaceNetwork Namespace 是Linux用于实现网络虚拟化的重要功能,他能创建多个隔离的网络空间,每个独立网络空间内的防火墙、网卡、路由表、邻居表、协议栈都是独立的。不管是虚拟机还是容器,当运行在独立的命名空间时,…

作者头像 李华
网站建设 2026/7/13 5:15:19

FMEA×控制计划×PPAP自动联动,这才是研发管理的天花板-全星研发项目管理APQP软件系统#APQP #PLM #汽车电子 #芯片研发 #新能源 #项目管理软件

FMEA控制计划PPAP自动联动,这才是研发管理的天花板-全星研发项目管理APQP软件系统 做汽车部件、芯片、新能源、新材料的研发人,是不是有这种感觉:通用PLM用起来各种别扭🤯 文档管得了,流程控不住;BOM看得见…

作者头像 李华