Java高频面试题:RabbitMQ如何实现消息的持久化?

大家好,我是锋哥。今天分享关于【Java高频面试题:RabbitMQ如何实现消息的持久化?】**面试题。**希望对大家有帮助;

Java高频面试题:RabbitMQ如何实现消息的持久化?

在 RabbitMQ 中,消息持久化的目的是确保在服务器宕机或重启后,消息不会丢失。要实现消息持久化,需要同时设置队列持久化消息持久化

1. 队列持久化(Durable Queue)

队列持久化确保队列在RabbitMQ重启后仍然存在。

2. 消息持久化(Persistent Message)

消息持久化保证消息被持久化到磁盘,即使 RabbitMQ 宕机或重启,消息也不会丢失。

Java 代码实现 RabbitMQ 消息持久化

假设你已经引入了 rabbitmq-client 的 Maven 依赖:

复制代码
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.13.0</version>
</dependency>

1. 创建持久化队列和持久化消息

生产者代码
复制代码
import com.rabbitmq.client.*;

public class PersistentProducer {
    private final static String QUEUE_NAME = "task_queue";

    public static void main(String[] argv) throws Exception {
        // 创建连接和频道
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection(); 
             Channel channel = connection.createChannel()) {

            // 声明持久化队列
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);

            // 创建持久化消息
            String message = "Hello World!";
            channel.basicPublish("", QUEUE_NAME, 
                                 new AMQP.BasicProperties.Builder()
                                     .deliveryMode(2)  // 2表示持久化消息
                                     .build(), 
                                 message.getBytes());

            System.out.println("Sent: " + message);
        }
    }
}
消费者代码
复制代码
import com.rabbitmq.client.*;

public class PersistentConsumer {
    private final static String QUEUE_NAME = "task_queue";

    public static void main(String[] argv) throws Exception {
        // 创建连接和频道
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection(); 
             Channel channel = connection.createChannel()) {

            // 声明持久化队列
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);

            // 创建消费者
            System.out.println(" [*] Waiting for messages. To exit press Ctrl+C");

            // 自动确认消息
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println(" [x] Received: " + message);
            };

            channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
        }
    }
}

解释

生产者代码
  1. 队列声明 :使用 channel.queueDeclare(QUEUE_NAME, true, false, false, null),其中 true 表示队列是持久化的。
  2. 消息发布 :通过 channel.basicPublish 发布消息时,设置 deliveryMode=2 来确保消息是持久化的。deliveryMode=2 表示消息会写入磁盘,deliveryMode=1 则是非持久化消息(默认)。
消费者代码
  1. 队列声明 :消费端同样需要声明队列为持久化的,channel.queueDeclare(QUEUE_NAME, true, false, false, null)
  2. 消息消费 :通过 channel.basicConsume 来消费消息,RabbitMQ会确保消息持久化,且不会丢失。

2. 其他相关设置

消费者确认(ACK)

消息的持久化保证了消息不丢失,但消费者需要正确地确认消息(ack)。如果你希望RabbitMQ等待消费者确认消息,可以通过设置 autoAck 参数为 false 来实现手动确认。

复制代码
// 启用手动确认
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });

然后,在消息处理完成后,使用 channel.basicAck 手动确认:

复制代码
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);

如果你不确认消息,RabbitMQ会将未确认的消息重新放回队列。


3. 最后总结下

  1. 队列持久化 :在声明队列时,设置 durable=true
  2. 消息持久化 :在发布消息时,设置 deliveryMode=2
  3. 手动确认 :如果你需要确认消息的消费,设置 autoAck=false,并手动调用 channel.basicAck

通过这种方式,RabbitMQ可以确保消息在系统崩溃后不会丢失。

相关推荐
崇山峻岭之间2 小时前
matlab的高频注入
开发语言·matlab
溪海莘2 小时前
如何使用uv创建并管理一个新的空白的python项目?
开发语言·python·uv
吾诺2 小时前
GO 快速升级Go版本
开发语言·redis·golang
爱打代码的小林2 小时前
用 LangChain 解析大模型输出
java·python·langchain·大模型
YMWM_2 小时前
conda特定环境打包
开发语言·conda·php
_日拱一卒2 小时前
LeetCode(力扣):只出现一次的数字
java·数据结构·算法
小箌2 小时前
JavaWeb_02
java·数据库·maven·mybatis
gxy1990262 小时前
【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
java·spring boot·spring
阿杰真不会敲代码2 小时前
Elasticsearch 入门到实战:安装 + CRUD + 查询
java·大数据·elasticsearch·搜索引擎