系统采用CQRS,写模型提交订单地址修改后,通过事件异步更新读模型。用户收到“修改成功”提示后立即刷新,却从读模型看到旧地址。既保留异步投影,又改善该用户读己之写体验的合理办法是()。
写入成功时返回可追踪的版本或事件序号,后续查询要求读模型至少达到该水位,可以在不把全系统改成强一致的前提下,为当前会话提供更可控的读己之写体验。
选项分析
错误。异步投影天然可能滞后,口头宣布不会改变数据传播过程。
错误。丢弃查询不保证剩余请求读到新版本,也损害可用性。
正确。版本水位把“至少读到我刚才那次写入”变成可检查条件。
错误。禁止查看是在回避一致性设计,不是解决用户问题。
本题为什么容易错
很多人把“写接口返回成功”理解为所有读副本都已更新。成功通常只证明写模型接受并持久化了命令,读模型何时可见取决于事件投递和投影进度。
简短答案
订单修改成功后立即查询却还是旧值,怎样改善当前用户体验,正确答案是 C(返回写入版本水位,查询时等待或路由到已追上该版本的视图,超时则明确提示同步中)。写入成功时返回可追踪的版本或事件序号,后续查询要求读模型至少达到该水位,可以在不把全系统改成强一致的前提下,为当前会话提供更可控的读己之写体验。
易混淆概念对比表
| 概念 | 本题判断 | 区别要点 | 记忆提示 |
|---|---|---|---|
| 宣布所有读模型天然强一致,不再处理延迟 | 本题干扰项 | 错误。异步投影天然可能滞后,口头宣布不会改变数据传播过程。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 随机删除一部分查询请求,降低读库压力 | 本题干扰项 | 错误。丢弃查询不保证剩余请求读到新版本,也损害可用性。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 返回写入版本水位,查询时等待或路由到已追上该版本的视图,超时则明确提示同步中 | 本题正确答案 | 正确。版本水位把“至少读到我刚才那次写入”变成可检查条件。 | 看到题干核心场景时优先联想到它 |
| 禁止用户修改后再次查看订单 | 本题干扰项 | 错误。禁止查看是在回避一致性设计,不是解决用户问题。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
本题易混淆选项怎么区分
- 宣布所有读模型天然强一致,不再处理延迟:错误。异步投影天然可能滞后,口头宣布不会改变数据传播过程。
- 随机删除一部分查询请求,降低读库压力:错误。丢弃查询不保证剩余请求读到新版本,也损害可用性。
- 禁止用户修改后再次查看订单:错误。禁止查看是在回避一致性设计,不是解决用户问题。
知识点详解
CQRS将命令和查询职责分离,读模型常由事件异步构建,因此可能出现投影延迟。读己之写保证用户至少能看到自己已确认的更新,不等同于要求所有用户和所有副本立即一致。可通过版本水位、会话令牌、短期路由到写侧、轮询投影进度或明确的处理中状态实现。设计还应监控事件积压、处理失败和最大可接受延迟。
备考速记
写成功不等于读模型已追上;带版本水位,至少看见自己刚写的。
CQRS 在版本水位场景中的作用
例如写接口返回订单版本87,查询接口只在读模型版本不小于87时返回最终页面。若两秒内还没追上,可以展示“修改已保存,页面同步中”,而不是悄悄展示旧地址。
同类题怎么考
- 解释CQRS读模型为何出现旧数据。
- 为特定会话选择版本水位、短暂等待或写模型兜底。
CQRS 在系统架构设计师软考中的考法
看到“写成功、立即读旧值、异步读模型”,先判断最终一致性延迟。题目若要求改善当前用户体验,找会话版本、等待水位或临时读写侧,不必把整个系统改为同步双写。
解题思路
题干没有说写失败,而是读模型尚未追上。最稳的判断不是强行否认延迟,而是给这次写入一个版本凭证。用户随后查询时,系统检查读模型是否已经处理到该版本;到了就读,没到就短暂等待、读写模型兜底或提示同步中。C 把一致性要求限定在需要它的会话里。
考点定位
CQRS不必然使用两个数据库;一旦读写存储异步同步,就要显式处理投影延迟和用户对新状态的可见性。
易错提醒
- 接口返回成功却不提供操作ID或版本,前端无法判断同步状态。
- 读模型消费失败没有重试和监控,短暂延迟变成长期不一致。
- 为一个需要读己之写的页面,把所有查询都强制改走主库。
备考提示
- 把命令提交、事件发布、投影更新、查询读取画成四个时刻。
- 区分最终一致、读己之写和全局线性一致,不要把它们当成只有强弱两档。
你可能还想了解
- CQRS为什么会读到旧数据?
- 读己之写和强一致有什么区别?
- 版本水位如何改善读模型延迟?
本文小结
CQRS异步投影会让读模型短暂落后。写入返回版本水位,查询等待或选择已追上该版本的视图,可为当前用户提供读己之写体验。