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可以确保消息在系统崩溃后不会丢失。

相关推荐
Shirley~~1 分钟前
力扣hot100:每日温度
开发语言·javascript·ecmascript
Zww08918 分钟前
idea配置注释模板
java·ide·intellij-idea
Renhao-Wan10 分钟前
Docker 核心原理详解:镜像、容器、Namespace、Cgroups 与 UnionFS
java·后端·docker·容器
Rsun0455117 分钟前
ScheduledExecutorService类作用
java
froginwe1122 分钟前
《WebPages 邮局》
开发语言
小钊(求职中)24 分钟前
算法知识、常用方法总结
java·算法·排序算法·力扣
萧逸才28 分钟前
【learn-claude-code】S07TaskSystem - 任务系统:大目标拆成小任务,持久化到磁盘
java·人工智能·ai
@insist12332 分钟前
网络工程师-广域网与接入网技术(一):核心协议与流量控制
开发语言·网络·网络工程师·软考·软件水平考试
Rsun0455142 分钟前
MessageUtils.message(“user.jcaptcha.expire“)
java
ˇasushiro1 小时前
终端工具配置
开发语言·ios·swift