RabbitMQ如何保证消息可靠性

本文详细探讨了RabbitMQ中消息可能丢失的原因,以及如何通过生产者重试机制、确认机制、Exchange和Queue的持久化来确保消息可靠性。同时介绍了消费者确认机制、失败重试策略和最佳的失败处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、RabbitMQ消息丢失的可能性

1.1 生产者消息丢失场景

1.2 MQ导致消息丢失

1.3 消费者丢失

2、如何保证生产者消息的可靠性

2.1 生产者重试机制

2.2 生产者确认机制

2.3 实现生产者确认

2.3.1 配置yml开启生产者确认

2.3.2 定义ReturnCallback

2.3.3 定义ConfirmCallback

3、MQ消息可靠性

3.1 Exchange交换机持久化

3.2 Queues队列持久化

3.3 消息的持久化

3.4 LazyQueue

4、消费者的可靠性

4.1 消费者确认机制

4.1.1首先我们来测试一下acknowledge-mode: none不做处理的场景:

4.1.2 测试acknowledge-mode: auto自动处理情况下

4.1.2.1 消费者抛出消息异常

4.1.2.2 消费者抛出业务异常

5、消费者失败重试机制

5.1 消费者失败重试机制

5.2 失败处理策略


1、RabbitMQ消息丢失的可能性

如下图是消息从生产者到消费者的关系图。通过图片我们可以分析,消息从生产者,MQ,消费者这三个环节任一个都有可能丢失。那么下面我们就从这三点进行分析。

1.1 生产者消息丢失场景
  • 生产者发送消息时连接MQ失败

  • 生产发生消息到达MQ后未找到Exchange

  • 生产者发送消息到达MQ的 Exchange 后,未找到合适的 Queue

  • 消息到达MQ后,处理消息的进程发生异常

1.2 MQ导致消息丢失
  • 消息到达MQ,保存到队列后,尚未消费就突然宕机

1.3 消费者丢失
  • 消息接收后尚未处理突然宕机

  • 消息接收后处理过程中抛出异常

综上,我们要解决消息丢失问题,保证MQ的可靠性,就必须从3个方面入手:

  • 确保生产者一定把消息发送到MQ

  • 确保MQ不会将消息弄丢

  • 确保消费者一定要处理消息

2、如何保证生产者消息的可靠性

2.1 生产者重试机制

生产者发送消息时,出现了网络故障,导致与MQ的连接中断。为了解决这个问题,SpringAMQP提供的消息发送时的重试机制。当 RabbitTemplate与MQ连接超时后,多次重试。

我们可以在生产者对应的yml配置中配置:

spring:
rabbitmq:
 connection-timeout: 1s # 设置MQ的连接超时时间
 template:
  retry:
   enabled: true # 开启超时重试机制
   initial-interval: 1000ms # 失败后的初始等待时间
   multiplier: 2 # 失败后下次的等待时长倍数,下次等待时长 = initial-interval *multiplier
   max-attempts: 3 # 最大重试次数

我这边故意把URL地址写错:

spring:
  rabbitmq:
    host: 601.204.203.40

我们可以发现总共重试了3次。如图所示:

但是SpringAMQP提供的重试机制是阻塞式的重试,也就是说多次重试等待的过程中,当前线程是被阻塞的。如果对于业务性能有要求,建议禁用重试机制。

2.2 生产者确认机制

其实一般我们生产者与MQ网络连接比较稳定,所以基本上不用考虑第一种场景。但是还有一些到达MQ之后可能会丢失的场景,比如:

  • 生产者发送的消息到达MQ没有找到Exchange

  • 生产者发送的消息到达MQ找到Exchange,但是没有找到Queue

  • MQ内部处理消息进程异常

基于上面几种情况,RabbitMQ提供了生产者消息确认机制,包括 Publisher Confirm 和 Publisher Return 两种。在开启确认机制的情况下,当生产者发送消息给MQ后,MQ会根据消息处理的情况返回不同的回执。具体主要有以下几种情况:

  • 当消息发送到MQ上,但是路由失败了,会返回会通过Publisher Return返回返回信息。同时会返回ack确认信息,表示投递成功。

  • 当非持久化消息发送到MQ上,并且入队成功,会返回ACK确认信息,表示投递成功。

  • 当持久化消息发送到MQ上,入队成功并且持久化到磁盘,会返回ACK确认信息,表示投递成功。

  • 其它情况都会返回NACK,告知投递失败

其中 ack 和 nack 属于Publisher Confirm机制, ack 是投递成功; nack 是投递失败。而 return 则属于Publisher Return机制。默认情况,这两种都是关闭的,需要通过配置开启。

2.3 实现生产者确认
2.3.1 配置yml开启生产者确认

我们在生产者对应yml配置中加入

spring:
rabbitmq:
 publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型
 publisher-returns: true # 开启publisher return机制

其中publisher-confirm-type一共有三种模式:

  • none :关闭confirm机制

  • simple :同步阻塞等待MQ的回执

  • correlated :MQ异步回调返回回执

一般我们都是开启correlated模式。

2.3.2 定义ReturnCallback

每个 RabbitTemplate 只能配置一个 ReturnCallback,我们可以定义一个配置类统一配置。下面我们在生产者中定义配置类ReturnsCallbackConfig:

package com.chenwen.producer.config;
​
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Configuration;
​
import javax.annotation.PostConstruct;
​
@Slf4j
@AllArgsConstructor
@Configuration
public class ReturnsCallbackConfig {
    private final RabbitTemplate rabbitTemplate;
​
    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returned) {
     
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值