CQRS 入门
读写分离、投影;与 ES 搜索对照。
30 分钟
CQRS 入门
CQRS(Command Query Responsibility Segregation) 把 写(Command) 与 读(Query) 模型分开:写侧保业务不变式;读侧为查询 优化结构(投影、缓存、搜索引擎)。常与事件驱动、Kafka 消费链配合。
学习目标
- 区分 Command 与 Query 的职责
- 理解读模型投影与最终一致
- 对照 ip-event-driven 与搜索场景
动机:读写需求分裂
写:创建订单 — 强一致、事务、规则复杂
读:订单列表 / 报表 / 全文搜索 — 多表 JOIN、高 QPS、可略滞后
同一 MySQL 表既服务写又服务复杂读,索引与锁竞争互相拖累。
CQRS 拓扑
Commands Events
Client ─────────► [Write Model] ─────────► [Kafka]
order-svc / MySQL │
▼
[Projection Workers]
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
[Read DB: MySQL] [Redis 缓存] [Elasticsearch]
▲
Client ─── Queries ──────┘
(BFF / GraphQL / REST)
写路径仍 sb-transaction;读路径订阅 kafka-consumer 更新投影。
投影(Projection)直觉
OrderCreated 事件 → Worker 插入 order_list_view(冗余 userName、courseTitle,免 JOIN)。
| 读模型 | 来源事件 | 用途 |
|---|---|---|
| 用户订单列表 | OrderCreated, OrderPaid | App 列表页 |
| 销售报表 | OrderPaid | Admin BI |
| 搜索索引 | CourseUpdated | ES 全文 |
滞后通常 毫秒~秒;UI 可提示「处理中」或读写分离路由。
与 API 组合 / BFF
- ip-api-composition 可改为 只查读模型,减少扇出
- gql-nplus1 问题在 CQRS 读库上 Often 已扁平化
不必上 Event Sourcing(存全量事件为唯一真相);CQRS 可只用 MySQL 双表/双库。