RabbitMQ重试机制

RabbitMQ 重试机制:Auto 与 Manual 消费模式

在 RabbitMQ 消费端,消息消费失败后的重试策略 直接影响系统的可靠性。Spring AMQP 提供了两种消费模式:Auto 模式(自动确认)Manual 模式(手动确认)

本文详细对比两种模式的差异,重点分析 deliveryTag 的变化规律


一、核心区别:Tag 的变化

模式 重试时 Tag 变化 原因
Auto 模式 Tag 保持不变 内部重试,同一条消息
Manual 模式(入队) Tag 持续增加 重新入队 = 新消息,产生新 Tag

关键理解

  • Auto 模式重试是同一条消息在内部重试,Tag 不变
  • Manual 模式 basicNack(requeue=true)消息重新入队,相当于新消息,Tag 递增

二、Auto 模式(自动确认)

2.1 配置

yaml 复制代码
spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: auto
        retry:
          enabled: true
          max-attempts: 3          # 最大重试次数
          initial-interval: 1000   # 首次重试间隔(毫秒)
          multiplier: 2            # 间隔倍数

2.2 Tag 变化示例

复制代码
消息到达(Tag=1)→ 消费失败 → 重试(Tag=1)→ 消费失败 → 重试(Tag=1)→ 消费成功
       ↑                      ↑                    ↑
       Tag=1                  Tag=1                Tag=1
       同一条消息             同一条消息           同一条消息

2.3 代码示例

java 复制代码
@RabbitListener(queues = "test-queue")
public void onMessage(String message) {
    System.out.println("收到消息: " + message);
    // 消费失败,自动重试
    // Tag 保持不变,始终是同一条消息
    throw new RuntimeException("消费失败");
}

2.4 Auto 模式特点

特点 说明
Tag 不变 重试时 Tag 保持不变,始终是同一条消息
内部重试 Spring 内部处理,不经过队列
自动入队 重试次数耗尽后,消息重新入队
简单易用 代码简洁,无需手动管理

三、Manual 模式(手动确认)

3.1 配置

yaml 复制代码
spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: manual
        prefetch: 1

3.2 Tag 变化示例(入队)

复制代码
消息到达(Tag=1)→ 消费失败 → basicNack(requeue=true) → 重新入队
                                                              ↓
消息到达(Tag=2)← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← 
       ↑
       Tag=2(新消息)

3.3 代码示例

java 复制代码
@RabbitListener(queues = "test-queue")
public void onMessage(Message message, Channel channel) throws IOException {
    long deliveryTag = message.getMessageProperties().getDeliveryTag();
    System.out.println("当前 Tag: " + deliveryTag);
    
    try {
        // 业务处理...
        channel.basicAck(deliveryTag, false);
    } catch (Exception e) {
        // 重新入队:Tag 会增加(变成新消息)
        channel.basicNack(deliveryTag, false, true);  // requeue=true
    }
}

3.4 Manual 模式三种响应方式

方法 requeue 参数 Tag 变化 说明
basicAck - 消息删除 确认消费
basicNack(requeue=true) true Tag +1 重新入队,变成新消息
basicNack(requeue=false) false 消息删除 丢弃或进入死信队列

四、Tag 变化对比

4.1 完整对比表

场景 Auto 模式 Manual 模式(入队)
首次消费 Tag=1 Tag=1
第1次重试 Tag=1(不变) Tag=2(+1)
第2次重试 Tag=1(不变) Tag=3(+1)
第3次重试 Tag=1(不变) Tag=4(+1)
消息本质 同一条消息 每次都是新消息

4.2 流程对比图

Auto 模式(Tag 不变)

复制代码
                    ┌─────────────────────────────────┐
                    │           内部重试               │
                    │    Tag=1 → Tag=1 → Tag=1        │
                    │         (同一条消息)            │
消息(Tag=1)→ 消费 → 失败 → 重试 → 失败 → 重试 → 成功/入队

Manual 模式(Tag 递增)

复制代码
消息(Tag=1)→ 消费 → 失败 → basicNack(requeue=true)
                                    ↓
                            重新入队(新消息)
                                    ↓
消息(Tag=2)→ 消费 → 失败 → basicNack(requeue=true)
                                    ↓
                            重新入队(新消息)
                                    ↓
消息(Tag=3)→ 消费 → 成功 → basicAck

五、为什么 Tag 会变化?

5.1 Auto 模式原理

复制代码
消费者 ← → Spring 内部队列(内存)
          ↓
     失败后内部重试
          ↓
     Tag 不变(同一条消息)

Auto 模式的重试发生在 Spring 内部,消息从未离开过消费者,所以 Tag 保持不变。

5.2 Manual 模式原理

复制代码
消费者 ← → RabbitMQ Broker
          ↓
     basicNack(requeue=true)
          ↓
     消息回到 Broker 队列
          ↓
     重新投递(新消息,新 Tag)

Manual 模式 basicNack(requeue=true) 是将消息重新放回 Broker,RabbitMQ 会将其视为新消息,分配新的 deliveryTag。


六、注意事项

  1. Manual 入队会导致 Tag 递增 :每次 basicNack(requeue=true) 都会产生新 Tag,可能影响依赖 Tag 的业务逻辑。

  2. Auto 重试是内部机制:Spring 内部重试不经过 Broker,Tag 不变,但重试次数有限。

  3. 幂等性:无论哪种模式,都要保证消费逻辑的幂等性。

  4. 死信队列:Manual 不入队时,建议配置死信队列,避免消息丢失。

  5. 性能:Auto 模式性能高于 Manual 模式。

相关推荐
学者猫头鹰6 小时前
分布式事务实战教程
java·分布式
笨蛋不要掉眼泪8 小时前
RabbitMQ消息队列:MQ的可靠性
分布式·rabbitmq·java-rabbitmq
zcmodeltech12 小时前
农业教学实训沙盘物联网控制系统设计:基于STM32与Modbus RTU的“感知-控制-实训”一体化方案
分布式·stm32·嵌入式硬件·物联网
ACP广源盛1392462567315 小时前
GSV6155@ACP# Type-C 视频信号转换芯片:技术架构、工程痛点适配与落地场景分析
大数据·c语言·开发语言·人工智能·分布式·嵌入式硬件·架构
平行侠16 小时前
校园分布式智算与模型对攻赛(DormMesh Clash)可行性分析
人工智能·分布式
笨蛋不要掉眼泪2 天前
RabbitMQ消息队列:发送者的可靠性
java·分布式·rabbitmq
AAA@峥2 天前
Ceph 分布式文件系统 CephFS 实战指南
运维·分布式·ceph
cyadyx2 天前
RabbitMQ 使用说明文档
分布式·rabbitmq
布鲁飞丝2 天前
kafka 副本集设置和理解
分布式·kafka
songgz2 天前
ZenithVM:从虚拟机到分布式操作系统内核
jvm·分布式·vm