MQ
MQ 基础
日期: 2025.9.8
通宵如鬼神哈👻
同步与异步
同步: 顺序执行,下一步依赖上一步完成
- 适用场景: 需即时结果的操作(如登录需先验证验证码)
- 技术实现: OpenFeign、RestTemplate
异步: 消息发送到 Broker 后,发送方无需等待接收方处理
- 适用场景:无需即时结果的操作(如注册后发送短信/邮件)
- 技术实现:MQ、多线程
- 核心流程:消息发送者 → 消息 Broker(中间件) → 消息接收者
- 优势:异步处理、系统解耦、流量削峰
常见 MQ 实现
| 类型 | 特点 |
|---|---|
| RabbitMQ | 轻Topic, 消息由Broker推送给消费者(推模式), 侧重可靠性和幂等性保证 |
| Kafka | 重Topic, 消息由消费者主动拉取(拉模式), 适用于高流量场景(日志,数据挖掘,数据清洗) |
| RocketMQ | 阿里内部用 |
RabbitMQ 核心概念
| 定位 | 作用 | |
|---|---|---|
publisher |
生产者 | 发送消息的应用程序 |
consumer |
消费者 | 消费消息的应用程序 |
queue |
队列 | 存储消息的缓冲区,暂存消息等待消费 |
exchange |
交换机 | 负责路由消息,决定消息投递到哪个队列 |
virtual host |
虚拟主机 | 实现数据隔离 每个虚拟主机有独立的 exchange和queue |
broker |
服务器 | 消息中转站 |
MQ 工作模式
| 模式 | 结构 | 特点 |
|---|---|---|
| 简单模式 | 一产一列一消 | 基础模式,一对一传递 |
| 工作队列 | 一产一列一消 | 消费者之间是竞争关系,配置预取消息实现"能者多劳" |
| Fanout | 一产一交多列多消 | 广播模式,无条件条件群发 |
| Direct | 一产一交多列多消 | 精确匹配RoutingKey群发,只投递到匹配的队列 |
| Topic | 一产一交多列多消 | RoutingKey支持通配符( #匹配0~N个单词,*匹配 1 个单词,单词用.分割) |
MQ 高级特性
日期: 2025.9.9
1. 消息积压
-
原因:消费者消费速度 < 生产者生产速度
-
解决方法:
-
用惰性队列:消息先存磁盘,消费时再加载到内存,缓解队列存储压力
-
修复消费者问题后,临时增加消费者节点,加速消费积压消息,完成后下线新增节点
2. 消息可靠性保障
(1)生产者角度
-
开启重试策略:确保消息能正确到达 MQ,重试耗尽后写入数据库人工处理
-
开启 confirm 机制:保证消息到达交换机
-
开启 return 机制:保证消息从交换机正确路由到队列
(2)持久化操作
- 对交换机、队列、消息进行持久化,确保 MQ 宕机重启后消息不丢失
(3)消费者角度
-
开启自动 ack,设置本地重试策略:重试耗尽后,失败消息路由到错误队列
-
监听错误队列,将消息写入数据库人工处理
3. 消费消息回执(ACK 机制)
-
ack:成功处理,RabbitMQ 删除消息
-
nack:处理失败,RabbitMQ 重新投递
-
reject:处理失败并拒绝,RabbitMQ 删除消息
SpringAMQP 的处理模式
-
none:消息投递后立即删除,不安全(不推荐)
-
manual:手动调用 API 发送 ack/reject,灵活但有业务入侵
-
auto:自动处理
- 业务正常:自动返回 ack
- 业务异常:返回 nack
- 消息处理 / 校验异常(如类型不匹配):返回 reject
4. 消息幂等性(避免重复消费)
-
天生幂等操作:如根据 ID 删除、查询数据(重复执行结果一致)
-
非幂等操作解决方案(推荐 Redis + 唯一 ID):
-
生产者发送消息时携带唯一 ID,并将 ID 写入 Redis(预注册)
-
消费者接收消息后,用 ID 查询 Redis:
-
若不存在:正常消费,完成后删除 Redis 中的 ID
-
若存在:表示已消费,不做处理
(核心:通过 “预注册 ID + 消费后删除” 规避并发冲突)
-
补充:通过业务状态判断(如 “从状态 A 到 B” 需校验当前为 A)
5. 延迟消息
- 核心:利用死信队列和TTL(time-to-live,消息存活时间) 实现,消息过期后进入死信队列,触发延迟处理逻辑
MQ可靠性保障并不是百分百,有可能消费者根本没有收到MQ的消息,那么后续就无法执行了。我们可以主动发起查询去获取最新结果,然后继续完成后续业务操作

浙公网安备 33010602011771号