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 模式。

相关推荐
wuqingshun3141591 小时前
RabbitMQ 中消息什么时候会进入死信交换机?
分布式·rabbitmq
hdsoft_huge2 小时前
SpringBoot系列12:整合RabbitMQ消息队列,异步解耦、死信队列完整业务案例
spring boot·rabbitmq·java-rabbitmq
ClickHouseDB3 小时前
推出 ClickHouse Cloud 中的多阶段分布式查询执行
分布式·clickhouse
BD_Marathon11 小时前
spark.sql报错
大数据·分布式·spark
长不胖的路人甲20 小时前
RabbitMQ 死信队列 DLQ
分布式·rabbitmq
可乐ea20 小时前
【Redis八股|第8篇】Redis 分布式锁原理与 Redisson 使用
数据库·redis·分布式·面试题·redis八股
逸Y 仙X1 天前
Spark部署
大数据·分布式·spark
BD_Marathon1 天前
什么是Spark
大数据·分布式·spark
xian_wwq1 天前
【学习笔记】分布式推理:TP / PP / EP / CP 并行策略详解(20/35)
笔记·分布式·学习·ai