消息模型与投递语义
用途:明确“消息会不会重复/丢失/乱序”,并据此设计消费方
模型
「模型」小节链接- Topic:一类消息的逻辑名称。
- MessageQueue(队列):Topic 的分片,是并行与顺序的单位。
- Tag:二级过滤(
TagA || TagB),Broker 侧按 hash 粗过滤 + 客户端精过滤,避免为每个子类建 Topic。 - Key:业务检索键(订单号),用于消息查询与去重排查。
- 消费者组:同一组内实例分摊队列(集群模式);不同组各自独立消费全量(广播语义由多组实现)。
- 位点(offset):组维度的消费进度,集群模式由 Broker 持久化。
投递语义
「投递语义」小节链接RocketMQ 提供至少一次(at-least-once),不提供恰好一次:
| 现象 | 成因 |
|---|---|
| 重复 | 消费超时重投、Broker 主从切换、生产者重试、位点提交失败 |
| 乱序 | 多队列并行、重试打乱顺序、生产者未指定同一队列 |
| 丢失 | 异步刷盘 + 异步复制下宕机、Topic 自动创建配置错误、消费端吞异常 |
结论:消费方必须幂等(见“幂等与去重”),并把“重复”当作正常事件设计。
发送方式与可靠性
「发送方式与可靠性」小节链接| 方式 | 适用 | 注意 |
|---|---|---|
| 同步发送 | 需要确认结果(业务事件) | 设超时与重试次数;重试可能产生重复 |
| 异步发送 | 高吞吐、允许稍后确认 | 回调线程不要做重活 |
| 单向发送 | 日志/指标类可丢数据 | 不保证到达 |
| 批量发送 | 同 Topic 大量小消息 | 受单批大小限制 |
可靠性配置组合:同步发送 + 重试(多 Broker)+ 同步刷盘/同步复制 + 事务消息或本地消息表 + 消费幂等 + 对账。
顺序语义
「顺序语义」小节链接只有同一队列内有序。要保证业务实体有序,生产者需按业务键选择队列(MessageQueueSelector,如 hash(orderId) % queueNum),且该队列不能并发消费(消费锁/单线程)。顺序消息与吞吐互斥,务必只在真正需要的场景使用。
消息大小与内容
「消息大小与内容」小节链接- 单消息体上限默认 4MB,但实践应远小于此(建议 KB 级):大消息放大存储、网络与重试成本。
- 传“事件 + 关键标识”,不要传完整快照;订阅方按需回查详情(避免结构耦合与体积膨胀)。
- 敏感数据不进消息体(消息会被复制、索引、保留多日)。
常见误区
「常见误区」小节链接| 误区 | 修正 |
|---|---|
| 认为 MQ 保证不重复 | 至少一次,重复是常态 |
| 用广播模式做集群消费 | 广播位点在本地,实例重启会重放或漏消费 |
| Tag 数量当枚举无限扩展 | Tag 过滤能力有限,分类多时拆 Topic 或用属性过滤(SQL92) |
| 消息体塞大对象 | 改为事件 + 回查 |
| 全局顺序(所有消息单队列) | 吞吐归零,业务上通常也不需要 |
延伸阅读
「延伸阅读」小节链接- Apache RocketMQ 官方文档:Concept、Producer/Consumer 配置
- Martin Kleppmann《数据密集型应用系统设计》第 11 章(消息系统的投递保证)