Appearance
MQ 为什么要用,以及怎么保证消息可靠:解耦、削峰、异步与幂等
消息队列是很多后端项目里“迟早会遇到”的一层能力。
但真正需要它的时候,核心问题往往不是“会不会发消息”,而是:
- 为什么要上 MQ
- 上了之后系统复杂度换来了什么
- 消息丢了、重复了、积压了怎么办
先说结论
MQ 最常见的三个价值:
- 解耦
- 削峰填谷
- 异步处理
而一旦上了 MQ,你就必须额外认真面对四件事:
- 生产端可靠投递
- Broker 存储可靠性
- 消费幂等
- 失败重试与死信处理
一、什么时候真的需要 MQ
1. 解耦
例如下单成功后,要同时做:
- 发优惠券
- 发站内信
- 记操作日志
如果这些动作全同步串起来,订单服务会越来越重。
这时用 MQ 的好处是:
- 主链路只负责把关键业务先走通
- 其他动作异步拆给下游系统
2. 削峰填谷
如果短时间请求量突然上涨,比如秒杀、活动、批量导入,MQ 可以把流量先缓冲起来,避免下游数据库或服务被瞬时打垮。
3. 异步处理
某些操作本来就不适合要求用户同步等待,例如:
- 发邮件
- 发短信
- 导出报表
- 大量非核心统计任务
二、JMS 和 AMQP 到底是什么
很多旧笔记里会把产品、协议、接口混在一起记。
更清晰的理解是:
JMS:Java 平台里的消息服务接口规范AMQP:面向消息中间件的网络协议规范
它们不是同一个维度的东西。
可以这样粗略理解
- JMS 更像 Java 世界里的统一接口约定
- AMQP 更像跨语言通信的协议规范
所以像 RabbitMQ 这类产品,通常会和 AMQP 关联更紧。
三、常见消息模型该怎么理解
如果先从 RabbitMQ 的角度理解,最常见的几种模型可以记成:
- 简单队列
- 工作队列
- 发布订阅
- 路由
- Topic
真正需要记住的不是名字本身,而是它们分别适合什么场景。
1. 工作队列
适合:
- 一个生产者
- 多个消费者竞争消费
典型用途:
- 异步任务分发
- 后台处理队列
2. 发布订阅
适合一条消息要广播给多个下游系统。
例如:
- 一个事件同时通知多个服务
3. 路由 / Topic
适合:
- 根据业务类型、标签、路由键把消息分发给不同消费者
这类模型更适合复杂一些的业务路由场景。
四、上 MQ 之后,系统复杂度为什么会增加
因为你把“同步调用是否成功”的问题,换成了“消息链路是否可靠”的问题。
会新增很多需要思考的点:
- 生产者发出去了没有
- Broker 收到了没有
- 消费者处理成功了没有
- 失败后要不要重试
- 重试多次还不行怎么办
五、消息可靠性最核心的几个问题
1. 生产阶段会不会丢
要考虑:
- 发送失败有没有感知
- 有没有确认机制
- 失败后如何补发
2. 存储阶段会不会丢
要考虑:
- 是否持久化
- Broker 是否高可用
- 故障切换后消息是否还在
3. 消费阶段会不会丢
要考虑:
- 消费成功后何时确认
- 处理失败是否能重试
- 是否会重复投递
真正可靠的设计,一定是把这三段链路分开看。
六、为什么消费幂等特别重要
在 MQ 场景里,“至少一次”往往比“恰好一次”更现实。
这意味着某条消息可能被投递不止一次。
所以消费逻辑要尽量做到:
- 同一消息重复执行,结果仍然正确
常见做法:
- 业务唯一键去重
- 状态机判断
- Redis / 数据库防重记录
很多系统真正做的,不是绝不重复,而是允许重复投递但保证重复消费无害。
七、常见失败处理策略
1. 直接重试
适合短暂性故障,例如:
- 网络抖动
- 下游瞬时不可用
2. 延迟重试
避免失败消息立即再次打爆下游。
3. 死信队列
多次失败后进入死信队列,留给人工排查或补偿处理。
这通常是非常实用的一层保险。
八、消息积压时该怎么排查
如果生产速度持续高于消费速度,就会出现积压。
更实用的排查顺序通常是:
- 看消费端是不是报错或阻塞
- 看下游依赖是不是慢了
- 看单条消息处理是不是太重
- 看消费者并发度和分区 / 队列数量是否合理
不要一看到积压就先扩容,有时候根因只是某个下游接口变慢了。
九、RabbitMQ、RocketMQ、Kafka 怎么粗略理解
先记一个足够实用的印象:
- RabbitMQ:路由灵活,业务消息场景直观
- RocketMQ:业务消息能力较完整,Java 业务系统常见
- Kafka:高吞吐事件流、日志流场景更突出
如果你想看更细的产品对比,可以继续看:
十、什么场景不该一上来就上 MQ
如果只是:
- 一个很简单的单体项目
- 调用链很短
- 异步需求不明显
那先别急着引入 MQ。
因为它带来的不是“免费性能”,而是新的复杂度。
十一、一个更稳妥的使用原则
主链路只放真正关键的同步步骤。
那些可以异步、允许稍后完成、失败可以补偿的事情,再考虑交给 MQ。
这样你才能真正得到 MQ 的收益,而不是只增加维护成本。
一句话总结
MQ 的价值不在“发消息”这件事本身,而在于它帮你重新切分系统责任边界。
但一旦用了 MQ,就一定要把可靠投递、幂等消费、失败重试、死信处理和积压排查一并设计进去。