Sunday面试指南

CQRS 是什么?和数据库读写分离有什么区别?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:CQRS 是什么?

🙋‍♂️ 我:读请求走从库,写请求走主库。

🧑‍💻 面试官:这叫数据库读写分离。如果还是一套模型和接口,怎么体现 CQRS?

🙋‍♂️ 我:CQRS 更关注命令和查询职责分别设计。

🧑‍💻 面试官:一定要两套数据库吗?一定要事件溯源吗?写完后查询没看到新结果,产品怎么办?

CQRS 分的是改变状态与读取信息的模型职责,不只是把 SQL 分到两台数据库服务器。

面试速答(60 秒版)

CQRS 是命令查询职责分离。命令负责改变业务状态并维护规则,查询负责提供读取结果,可以按展示与检索需求设计不同模型。

数据库读写分离主要解决请求路由与存储承载问题,读走副本、写走主库,并不自动意味着使用了不同的业务模型。

CQRS 可以先在同一应用、同一数据库中实现逻辑分离,也可以进一步使用独立读写存储。是否跨库、是否异步同步、是否采用 Event Sourcing,都是额外选择。

当读写需求差异明显时,它可能让各自更易优化;但也会带来模型维护、数据同步和一致性处理成本。简单 CRUD 项目不必为了架构名字强行拆开。

CQRS命令守规则查询面向读取模型不要求必然分库

知识点详解:写入要守规则,读取要方便使用

命令为什么不只是一个 update 接口?

假设一个预约系统需要取消预约。命令表达的是“取消预约”,要检查预约状态、操作权限和是否允许取消,再完成合法的状态变化。

它不是让调用方任意传一组数据库字段,让服务端直接覆盖。命令侧模型要维护业务约束,并报告执行结果。

这里的“命令与查询分离”也不表示 HTTP 命令响应必须空白。响应可以包含命令执行结果,但不要把它和独立读取模型混为同一职责。

查询模型可以按页面组织

一个列表页面可能需要预约信息、用户名称和地点摘要。查询侧可以直接提供页面需要的投影,避免每次按复杂业务对象层级拼装。

读模型可以是普通查询、数据库视图,也可以是预先维护的表或搜索索引。它不一定和写模型具有相同字段和关系。

所以读写分离不只是数据库部署关系,而是在模型上允许两种不同需求分别表达。

为什么可以共用数据库?

最简单的 CQRS 可以只分开处理职责和模型,底层仍使用同一个数据库。查询需要的结果也可以在这个数据库里获得。

进一步拆到独立存储,是为了不同读取形态、容量或技术要求,不是定义里的强制条件。Microsoft CQRS 文档

而主从复制即便用了两台机器,也可能只是同一数据结构的不同副本。机器多了,不代表模型已经分开。

异步读模型为什么会落后?

如果命令先提交写状态,再通过事件更新读投影,两者不是同时完成的。命令已经成功,列表可能仍然显示旧状态。

这是产品需要面对的可见行为。可以让命令响应返回必要结果、界面显示处理中,或等待读投影达到某个版本,再提供符合一致性要求的查询路径。

不能只对用户说一句“最终一致”,却不说明可能多久、失败时怎样发现、关键页面怎样避免错误决策。

同步读投影也有成本,跨存储同步还可能涉及部分失败。选择取决于一致性需求,不是越异步越先进。

命令已经提交时异步读投影仍可能落后

如何判断值得引入?

先确认读写需求是否真的不同:查询是否需要大量组合或专门检索,写模型是否有复杂规则,扩展压力是否集中在读取。

再估算新增投影、同步机制、回填、监控和团队维护成本。可以从一个边界清楚的模块开始,不必让整个系统一次分裂成两套平台。

验证除了查询延迟,还要检查命令规则是否保持,以及同步延迟、重复事件和读模型重建是否可控。

面试官继续追问

CQRS 必须搭配事件溯源吗?

不必。可以继续保存当前状态,通过其他可靠方式更新读模型。事件溯源决定状态的来源,与职责分离不是同一选择。

读模型坏了可以随便删掉重建吗?

要有可信数据来源、重建程序和对用户的影响控制。理论上可重建,不等于生产中无需成本和计划。

查询没有新结果,能重新执行命令吗?

不能默认这样做。查询落后不代表命令失败,盲目重试可能重复产生业务效果,仍要有命令身份和幂等设计。

面试速记卡

  • CQRS:命令与查询的模型职责分别设计。
  • 读写分离:存储路由与副本承载,不自动等于 CQRS。
  • 数据库数量:可以同库,也可进一步分开。
  • 事件溯源:独立选择,不是 CQRS 必选项。
  • 引入依据:真实读写差异,以及能否承担同步与维护成本。

公司面试真题

这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历