如何避免RabbitMQ消息丢失?

简介: 本文探讨了RabbitMQ中如何避免消息丢失的问题。在默认情况下,RabbitMQ并不保证消息的持久性,但提供了多种机制来确保消息的可靠传输与处理。文章分析了消息可能丢失的关键环节,并介绍了相应的保证机制:发布者确认交换机已接收消息、确认队列接收消息、队列及消息的持久化,以及消费者成功处理消息后的确认。通过Java代码示例展示了如何在实际应用中实现这些机制。最终,确保了消息在从生产到消费的整个流程中的可靠性。

前言

面试经常会被问到“怎么避免RabbitMQ消息不丢失”。首先需要明确的是,RabbitMQ在默认情况并不会保证消息的不丢失。不过RabbitMQ提供了一些机制,可以有效的避免消息在传输和处理过程中不丢失。

可能导致消息丢失的环节

先通过RabbitMQ的架构模型看一下消息的处理过程:

  1. 发布者和RabbitMQ建立连接发送消息至交换机。
  2. 交换机和队列绑定,将消息路由到队列中。
  3. 消费者和RabbitMQ建立连接指定某个队列的消息进行消费。

在这过程中以下几个环节可能会丢失消息:

  1. 发布者到交换机环节。
  2. 交换机到队列环节。
  3. 队列到消费者环节。

如下图

RabbitMQ的保证机制

很显然,在这样的处理过程中,要保证消息不丢失需要做到以下几点:

  1. 发布者需确认交换机接收到消息。
  2. 发布者需确认队列接收到消息。
  3. 保证队列及其中的数据持久化。
  4. 确保消费者的成功消费。

如何做到以上几点?

RabbitMQ为了适应各个场景的使用,以上的功能需要开发者按照定义自行设置。

Java代码示例

下面以Java为例,看一下在代码中如何进行相关设置。

确认Exchange接收到消息

在构建channel时添加确认机制,通过确认机制可以得知Exchange是否接收到消息,当消息未发送至Exchange时可以进行补偿措施。

java

代码解读

复制代码

 channel.addConfirmListener((sequenceNumber, multiple) -> {
            System.out.println("消息成功发送到交换机");
        }, (sequenceNumber, multiple) -> {
            System.err.println("消息未发送到交换机,补偿操作。");
        });

确认Queue接收到消息

  1. 构建channel时添加return机制,通过return机制可以得知Queue是否接收到消息,当消息未路由至Queue时可以进行补偿措施。

java

代码解读

复制代码

channel.addReturnListener((replyCode, replyText, exchange, routingKey, basicProperties, body) -> {
            System.err.format("消息 %s 未路由到指定队列: %s, replyText: %s,replyCode: %d%n", body, routingKey, replyText, replyCode);
        });
  1. 发布消息时设置消息mandatory为true,开启return机制。

java

代码解读

复制代码

 channel.basicPublish("", "",true, "", "");

保证Queue及其数据持久化

  1. 声明队列时设置队列持久化。默认情况下,通过channel.queueDeclare声明的队列是非持久的,这意味着如果RabbitMQ服务器重启,该队列所有未处理的消息都会丢失。

java

代码解读

复制代码

 //构建队列,queueDeclare("队列名称","是否持久化队列","是否只允许一个队列消费","长时间未使用是否删除","其他参数")
  channel.queueDeclare("", true, false, false, null);
  1. 还需要确保发布的消息也是持久化的,deliveryMode值为2意味着消息持久化。

java

代码解读

复制代码

//设置消息持久化
AMQP.BasicProperties basicProperties = new AMQP.BasicProperties.Builder().deliveryMode(2).build();
channel.basicPublish("", "",true, basicProperties, "");     

确定消费者的成功消费

当消息持久化至队列时,RabbitMQ已经保证了消息的可靠投递。

但是,为确保消费者的成功消费,消费端的确认机制通常被设置为手动确认模式,当消费者成功消费后向RabbitMQ发送确认信号,RabbitMQ才会从队列中删除该消息。

java

代码解读

复制代码

DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            //消息处理后手动ACK
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
        };
// ack为false
channel.basicConsume("", false, deliverCallback, consumerTag -> {
});

总结

消息不丢失对于消息中间件来说是至关重要的,RabbitMQ通过消息的持久化、生产者确认、消费者确认等机制,有效地确保了消息的可靠性,避免了消息的丢失。


转载来源:https://juejin.cn/post/7347251816616919090

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
7月前
|
消息中间件 Java Spring
【经典问题】RabbitMQ如何确保消息的不丢失?
【1月更文挑战第25天】【经典问题】RabbitMQ如何确保消息的不丢失?
|
消息中间件 数据库
RabbitMQ消息的重复消费问题如何解决的
RabbitMQ消息的重复消费问题如何解决的
1681 0
|
消息中间件 NoSQL Java
【RabbitMQ】RabbitMQ如何做到保证消息100%不丢失?
【RabbitMQ】RabbitMQ如何做到保证消息100%不丢失?
489 0
|
1月前
|
消息中间件
使用RabbitMQ如何保证消息不丢失 ?
RabbitMQ通过发布者确认、回执机制、消息持久化及消费者确认等方案,确保消息从发送到接收的每个环节都能有效防止丢失。即便如此,特殊情况下仍可能丢失,如系统故障等。为此,可设计消息状态表,记录消息ID、内容、交换机、路由键、发送时间和签收状态等,结合定时任务检查并重发未签收消息,以进一步提升消息传输的可靠性。
53 1
|
7月前
|
消息中间件 存储 程序员
RabbitMQ消息丢失的场景,如何保证消息不丢失?(详细讲解,一文看懂)
RabbitMQ消息丢失的场景,如何保证消息不丢失?(详细讲解,一文看懂)
344 0
RabbitMQ消息丢失的场景,如何保证消息不丢失?(详细讲解,一文看懂)
|
7月前
|
消息中间件 存储 程序员
四、RabbitMQ如何保证消息丢失
四、RabbitMQ如何保证消息丢失
73 0
|
消息中间件
rabbitmq重复确认导致消息丢失
rabbitmq重复确认导致消息丢失
|
消息中间件 存储 运维
优雅地处理RabbitMQ中的消息丢失
优雅地处理RabbitMQ中的消息丢失
103 0
|
Java Spring
RabbitMQ-如何保证消息不丢失
RabbitMQ-如何保证消息不丢失
100 0
|
消息中间件
RabbitMQ消息的重复消费问题如何解决的?
RabbitMQ消息的重复消费问题是在分布式系统中常见的一个挑战,解决该问题可以采取以下几种策略:
795 0