MQ

MQ 基础

日期: 2025.9.8

通宵如鬼神哈👻

同步与异步

同步: 顺序执行,下一步依赖上一步完成

  • 适用场景: 需即时结果的操作(如登录需先验证验证码)
  • 技术实现: OpenFeign、RestTemplate

异步: 消息发送到 Broker 后,发送方无需等待接收方处理

  • 适用场景:无需即时结果的操作(如注册后发送短信/邮件)
  • 技术实现:MQ、多线程
  • 核心流程:消息发送者 → 消息 Broker(中间件) → 消息接收者
  • 优势:异步处理、系统解耦、流量削峰

常见 MQ 实现

类型 特点
RabbitMQ 轻Topic,
消息由Broker推送给消费者(推模式),
侧重可靠性和幂等性保证
Kafka 重Topic,
消息由消费者主动拉取(拉模式),
适用于高流量场景(日志,数据挖掘,数据清洗)
RocketMQ 阿里内部用

RabbitMQ 核心概念

定位 作用
publisher 生产者 发送消息的应用程序
consumer 消费者 消费消息的应用程序
queue 队列 存储消息的缓冲区,暂存消息等待消费
exchange 交换机 负责路由消息,决定消息投递到哪个队列
virtual host 虚拟主机 实现数据隔离
每个虚拟主机有独立的exchangequeue
broker 服务器 消息中转站

MQ 工作模式

模式 结构 特点
简单模式 一产一列一消 基础模式,一对一传递
工作队列 一产一列一消 消费者之间是竞争关系,配置预取消息实现"能者多劳"
Fanout 一产一交多列多消 广播模式,无条件条件群发
Direct 一产一交多列多消 精确匹配RoutingKey群发,只投递到匹配的队列
Topic 一产一交多列多消 RoutingKey支持通配符
(#匹配0~N个单词,*匹配 1 个单词,单词用.分割)

MQ 高级特性

日期: 2025.9.9

1. 消息积压

  • 原因:消费者消费速度 < 生产者生产速度

  • 解决方法

  1. 惰性队列:消息先存磁盘,消费时再加载到内存,缓解队列存储压力

  2. 修复消费者问题后,临时增加消费者节点,加速消费积压消息,完成后下线新增节点

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):

  1. 生产者发送消息时携带唯一 ID,并将 ID 写入 Redis(预注册)

  2. 消费者接收消息后,用 ID 查询 Redis:

  • 若不存在:正常消费,完成后删除 Redis 中的 ID

  • 若存在:表示已消费,不做处理

    (核心:通过 “预注册 ID + 消费后删除” 规避并发冲突)

  • 补充:通过业务状态判断(如 “从状态 A 到 B” 需校验当前为 A)

5. 延迟消息

  • 核心:利用死信队列TTL(time-to-live,消息存活时间) 实现,消息过期后进入死信队列,触发延迟处理逻辑

MQ可靠性保障并不是百分百,有可能消费者根本没有收到MQ的消息,那么后续就无法执行了。我们可以主动发起查询去获取最新结果,然后继续完成后续业务操作

posted @ 2025-09-09 21:34  Breezy_space  阅读(17)  评论(0)    收藏  举报