Skip to content
消息系统选型与 Kafka 基础 · 第 1 篇 / 共 5 篇
领域数据与中间件
专题Kafka 专题
当前序列消息系统选型与 Kafka 基础
阅读位置第 1 篇 / 共 5 篇当前专题第 1 个序列 / 共 6 个序列

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. 死信队列

多次失败后进入死信队列,留给人工排查或补偿处理。

这通常是非常实用的一层保险。

八、消息积压时该怎么排查

如果生产速度持续高于消费速度,就会出现积压。

更实用的排查顺序通常是:

  1. 看消费端是不是报错或阻塞
  2. 看下游依赖是不是慢了
  3. 看单条消息处理是不是太重
  4. 看消费者并发度和分区 / 队列数量是否合理

不要一看到积压就先扩容,有时候根因只是某个下游接口变慢了。

九、RabbitMQ、RocketMQ、Kafka 怎么粗略理解

先记一个足够实用的印象:

  • RabbitMQ:路由灵活,业务消息场景直观
  • RocketMQ:业务消息能力较完整,Java 业务系统常见
  • Kafka:高吞吐事件流、日志流场景更突出

如果你想看更细的产品对比,可以继续看:

十、什么场景不该一上来就上 MQ

如果只是:

  • 一个很简单的单体项目
  • 调用链很短
  • 异步需求不明显

那先别急着引入 MQ。

因为它带来的不是“免费性能”,而是新的复杂度。

十一、一个更稳妥的使用原则

主链路只放真正关键的同步步骤。

那些可以异步、允许稍后完成、失败可以补偿的事情,再考虑交给 MQ。

这样你才能真正得到 MQ 的收益,而不是只增加维护成本。

一句话总结

MQ 的价值不在“发消息”这件事本身,而在于它帮你重新切分系统责任边界。

但一旦用了 MQ,就一定要把可靠投递、幂等消费、失败重试、死信处理和积压排查一并设计进去。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读RabbitMQ、Kafka、RocketMQ 怎么选适合先理解为什么要用 MQ,再衔接 Kafka 的核心架构、消费组和生产端基础。Kafka 专题 · 消息系统选型与 Kafka 基础同一序列 · 顺着当前主线继续读Kafka 核心架构与消息投递适合先理解为什么要用 MQ,再衔接 Kafka 的核心架构、消费组和生产端基础。Kafka 专题 · 消息系统选型与 Kafka 基础同专题其他序列 · Kafka 投递链路与日志存储机制保留策略和日志压缩适合哪些场景适合把副本机制、acks、批量压缩和日志组织放在一条 Kafka 投递主线上理解。Kafka 专题 · Kafka 投递链路与日志存储机制同专题其他序列 · Kafka 高级投递与消费治理批量发送、压缩和吞吐延迟怎么权衡适合把分区键、批量压缩、位点提交和 ISR 治理放在一起看。Kafka 专题 · Kafka 高级投递与消费治理跨专题关联 · 同场景:基础学习@Conditional 系列注解怎么配合使用适合把自动装配、条件装配、Profile 和循环依赖放回 Spring Boot 启动过程里理解。Spring 专题 · Spring Boot 启动、装配与配置跨专题关联 · 同场景:基础学习迟到数据、侧输出流和补数边界适合把 Savepoint、迟到数据和两阶段提交放在一起看。Flink 专题 · Flink 状态一致性与迟到数据处理
继续阅读消息系统选型与 Kafka 基础当前序列第 1 篇 / 共 5 篇当前专题第 1 个序列 / 共 6 个序列
往前看
上一序列协同控制与分布式锁从第 1 篇开始:Redis 和 ZooKeeper 分布式锁怎么选
往后看
下一篇RabbitMQ、Kafka、RocketMQ 怎么选继续当前序列下一章下一序列Kafka 可靠性与故障治理从第 1 篇开始:Kafka 顺序性、幂等生产者和精确一次

把零散经验整理成可查、可复用、可持续更新的企业级知识门户