这是《RocketMQ 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 消息队列的价值不是“把调用改成异步”,而是为业务建立清晰的事件契约、状态流转和故障恢复路径。本章整理常见业务架构模式,以及它们的风险边界。
27.1 事件驱动架构
基本结构:
order service
-> publish OrderCreated
-> inventory / notification / risk consumers
收益:
- 降低服务耦合;
- 支持新增下游而不改上游;
- 削峰填谷;
- 建立业务审计流;
- 支持数据同步和实时分析。
代价:
- 链路可观测性要求高;
- 最终一致;
- 事件治理复杂;
- 重复和乱序必须处理;
- 故障影响可能延迟暴露。
27.2 命令与事件
| 类型 | 语义 | 示例 |
|---|---|---|
| Command | 要求对方执行动作 | CreateOrderCommand |
| Event | 说明事实已经发生 | OrderCreatedEvent |
错误示例:
OrderPaid event -> consumer tells inventory to deduct
更清晰的设计:
OrderPaid event -> inventory service reacts: reserve or deduct stock
事件命名使用过去式,命令命名使用祈使式。
27.3 Outbox 模式
解决本地事务与消息发送一致性:
transaction:
update business table
insert outbox event
relay:
scan outbox
send message
mark sent
要点:
- 业务与事件同事务;
- eventId 全局唯一;
- relay 支持重试;
- 消费端幂等;
- 事件表按时间分区;
- 清理策略与审计要求一致。
RocketMQ 事务消息可以减少扫描延迟,但本地 outbox 仍是可靠审计和补偿基础。
27.4 Saga 模式
分布式长流程用本地事务加补偿:
create order
-> reserve inventory
-> charge payment
-> failure
-> release inventory
-> close order
设计要点:
- 每步有幂等操作;
- 每步有对应补偿;
- 补偿也可能失败;
- 状态机持久化;
- 定时恢复悬挂流程;
- 对外提供流程状态查询;
- 支持人工介入。
RocketMQ 承担步骤事件和补偿事件,不负责自动回滚数据库。
27.5 CQRS 与数据同步
命令侧:
order API -> order DB -> publish event
查询侧:
consumer -> projection table / search index / cache
注意:
- 查询模型最终一致;
- 投影任务必须幂等;
- 事件乱序要按聚合 ID 处理;
- 支持重放;
- 建立版本和快照;
- 提供对账和重建任务。
不要让用户在提交命令后立刻查询旧状态却不给出一致性提示。
27.6 异步任务
模式:
API accepts request
-> persist task
-> send task message
-> worker execute
-> update task status
任务表字段:
| 字段 | 说明 |
|---|---|
| task_id | 唯一 ID |
| type | 任务类型 |
| payload | 输入参数 |
| status | 状态 |
| attempt | 尝试次数 |
| next_retry_at | 下次执行时间 |
| result | 输出或失败原因 |
消息丢失时可由任务表补偿,任务重复时可由 task_id 幂等。
27.7 广播通知
广播消息适合:
- 本地缓存刷新;
- 配置变更通知;
- 在线服务元信息刷新;
- 灰度规则通知。
不适合:
- 数据库唯一记录写入;
- 扣款、扣库存;
- 全局审计事实;
- 必须全部实例确认的强一致流程。
广播消费的新实例可能无法自动获得历史全量消息,通常需要“全量加载 + 增量广播”组合。
27.8 削峰填谷
peak requests
-> enqueue
-> controlled consumers
-> downstream database
关键参数:
- 队列长度;
- 消费并发;
- 请求超时;
- 过期策略;
- 用户反馈;
- 降级策略;
- 死信治理。
削峰不是无限排队。超过业务等待时间后,应拒绝或降级,而不是让用户等待未知结果。
27.9 事件版本管理
事件契约演化:
| 变更 | 兼容性 |
|---|---|
| 新增可选字段 | 向后兼容 |
| 删除字段 | 需迁移期 |
| 修改字段含义 | 不兼容 |
| 枚举新增值 | 消费端需容错 |
| 修改业务键 | 高风险 |
推荐:
eventType + version
eventId
schema registry
consumer tolerance for unknown fields
消费者应允许未知字段,生产者避免重命名字段。
27.10 服务边界
事件平台治理:
- Topic 命名规范;
- 事件 schema 注册;
- 生产者和消费者授权;
- SLA 和 lag 告警;
- 死信治理;
- 事件文档;
- 兼容性测试;
- 数据脱敏;
- 生命周期管理;
- 归属团队。
示例命名:
order.order-created.v1
risk.payment-checked.v1
user.profile-updated.v2
本章小结
业务架构模式的核心是明确事实、命令、状态和补偿。Outbox 保证生产可靠,Saga 处理长流程,CQRS 支撑查询模型,异步任务通过任务表兜底。RocketMQ 提供传输、重试、死信和事务能力,但业务正确性仍依赖契约、幂等、状态机和对账。
思考题
- Command 和 Event 的命名有什么区别?
- Outbox 与事务消息如何组合?
- Saga 补偿失败怎么办?
- CQRS 查询模型如何重放重建?
- 哪些场景不适合广播消息?