1 读写分离只解决了一半问题
技术评审 1会上经常有人问:
查询接口性能要求高,写入操作需要严格校验。怎么设计?
标准答案:读写分离。主库写,从库读。
但这只解决了数据库层的问题。应用层呢?
典型的Service代码里,写操作需要严格校验和事务,读操作需要灵活查询和组装。两种完全不同的复杂度,却混在一起。
更糟的是,让AI维护这种代码时,它会混乱。我见过AI在优化查询性能时,把写入的校验逻辑也”优化”掉了。线上数据一致性直接炸了。
这才是CQRS要解决的真问题。
2 CQRS:命令和查询彻底分离
CQRS(Command Query Responsibility Segregation)核心思想:
命令(写)和查询(读)是两种完全不同的责任,用不同的模型处理。
命令模型负责写:接收命令、校验、修改状态、发布事件。 查询模型负责读:从优化的读存储查询、返回投影数据。
两者通过事件同步:命令模型发布事件,查询模型订阅事件更新读存储。
这样做的好处: - 写操作可以专注于业务规则和数据一致性 - 读操作可以针对查询场景优化存储结构(Redis、ES、视图表) - 两边独立演化,互不干扰
3 Actor模型天然适合CQRS
用Actor实现CQRS后,AI生成代码的成功率从不到40%提升到75%以上。为什么?

命令端:每个订单一个Actor
Actor天然提供了命令模型需要的能力: - 状态隔离:每个Actor管理自己的订单状态 - 并发控制:消息串行处理,不需要锁 - 事件发布:Actor可以向EventStream发布事件
关键点:业务逻辑是纯函数,Actor只负责状态管理和消息路由。
查询端:投影Actor订阅事件
查询端用Actor维护不同的投影视图。不同的查询需求可以有不同的投影Actor,各自维护最适合的数据结构。
7 事件溯源:让AI不需要”理解当前状态”
CQRS的自然延伸是事件溯源(Event Sourcing)。这是我认为对AI编程最有价值的架构模式。
传统方式存储”当前状态”:订单表里只有order_id、status、total。问题是:这个订单经历了什么?谁改过状态?为什么是这个金额?答案:不知道,或者需要翻日志。
事件溯源存储”事件流”:OrderCreated、OrderPaid、OrderShipped。完整历史,可重放、回溯、审计。
对AI编程的意义
AI不需要”理解当前状态是什么”——这要追踪所有修改状态的代码。 AI只需要”重放事件历史”——这是纯函数。
def applyEvent(state: OrderState, event: OrderEvent): OrderState = {
event match {
case OrderCreated(id, userId, items) =>
state.copy(orderId = id, userId = userId, items = items, status = Created)
case OrderPaid(_, paymentId, _) =>
state.copy(status = Paid, paymentId = Some(paymentId))
case OrderShipped(_, trackingNo, _) =>
state.copy(status = Shipped, trackingNo = Some(trackingNo))
}
}让AI生成这种纯函数,成功率高达95%。而让AI生成传统的状态修改代码,成功率不到60%。
三个价值: 1. 状态变成可计算的结果(纯函数) 2. 历史可追溯,bug可定位 3. 可以重建任意时间点的状态
8 什么时候不该用CQRS
CQRS不是银弹。见过太多团队盲目使用,把简单问题复杂化。
不适合的场景:
CRUD简单应用 - 增加复杂度,收益不大。用传统MVC就够了。
读写比例接近 - 分离收益有限。先优化查询,不行再考虑CQRS。
强一致性需求 - CQRS是最终一致性,如果业务要求强一致,用数据库事务。
团队经验不足 - 学习曲线陡峭。先从简单模块试点。
项目周期短 - 架构复杂度高。快速交付优先。
判断标准:读写比例 > 10:1,或查询需要复杂聚合(3个以上表join),或写入需要复杂校验(5个以上步骤),才考虑CQRS。
9 复杂度在架构层面被控制
CQRS与Actor模式的结合,构建了”职责分离、状态隔离、事件驱动”的架构。
对AI编程的价值:
- 上下文边界清晰:命令端和查询端完全分离,AI不需要同时理解两边
- 状态变化显式:事件流让状态变化成为可追溯的历史
- 纯函数逻辑:事件应用函数是纯函数,易于生成和测试
- 独立可验证:每个Actor、每个投影都可以独立验证
AI不再是”理解整个系统”,而是”理解一个Actor、一个事件、一个函数”。
我在实际项目中的数据: - AI生成代码成功率:从40%提升到75% - 代码bug率:下降60% - 开发效率:提升3倍
这不是理论,是实战验证过的结果。
9.1 系列回顾
从系列之一到系列之四,完成了一次完整的思考旅程:
- 系列之一:诊断AI编程在面向对象架构下的困境
- 系列之二:深入Actor模式的隔离机制
- 系列之三:引入函数式编程让逻辑可预测
- 系列之四:构建CQRS架构在架构层面控制复杂度
贯穿始终的核心思想:
适合AI编程的架构,不是让AI变得更聪明,而是让问题变得更简单。
Actor模式、函数式编程、CQRS,这些”冷门”的编程范式,恰恰提供了这种”化繁为简”的能力。它们拥有AI编程所需的本质特征:隔离、显式、简单。
在AI编程时代,最古老的智慧,可能是最新的答案。
如果你正在考虑在项目中引入这些模式:
- 从小处开始,选择独立模块试点
- 先理解本质,而不是盲目跟风
- 量化效果,用数据说话
- 持续优化,架构不是一成不变的
- 基于知识和数据做决策
软件工程没有银弹,但有更好的选择。
参考文献 2:
- Greg Young, “CQRS Documents” (2010) - CQRS模式的原始提出者
- Martin Fowler, “CQRS” (2011){width=85%} - https://martinfowler.com/bliki/CQRS.html
- Vaughn Vernon, “Implementing Domain-Driven Design” (2013) - CQRS与DDD结合实践
- Akka Documentation - https://doc.akka.io/
- Event Store Documentation - https://www.eventstore.com/
本系列文章由reddish撰写,遵循”知识优于氛围”理念,所有观点基于软件工程实践与AI编程调研。