不同工作用不同形状
写入模型负责不变量:订单不能重复支付,库存不能为负。读取模型面向屏幕:带客户名和状态徽章的订单列表。强迫一个模型同时承担两者,往往得到一个查询慢、校验别扭的折中方案。
CQRS 把它们分开。命令处理器加载写模型、校验命令并提交变更;投影器消费变更并更新读表或搜索索引;查询直接读取投影。
POST /orders -> command handler -> write model -> event
|
v
projector -> orders_read
GET /orders -> query handler -> orders_read
一致性必须显式
写存储和读存储分离后,写入后立刻读取可能看不到变更——这是投影延迟,不是缺陷。要按界面逐一决定:跳转到读取写模型的详情页、显示乐观的本地更新,或展示“处理中”直到投影追上。监控延迟,并在超过产品容忍度时告警。
投影需要检查点。重启后从最后处理位置继续,而不是重放全部历史。投影出错时,重建到新表,追平后再切换读取,并保留旧投影以便回滚。
授权与边界
读模型可能把数据暴露给无权查看的用户。要在查询处理器或行级实施授权,不能假设写模型的规则会自动延续。把敏感字段复制进搜索索引,会新增一个数据保留和访问控制面。
何时使用
当读写负载在形状或规模上确实不同,或需要多个投影服务不同消费者时,使用 CQRS。优点是模型聚焦、可独立扩展;代价是最终一致性、数据重复和投影器运维。与单一模型相比,CQRS 增加了管道,只有分离能解决可测量的问题时才值得。