RabbitMQ 高级特性之持久性

发布于:2025-07-04 ⋅ 阅读:(27) ⋅ 点赞:(0)

1. 简介

在 RabbitMQ 的消息发送流程中,一共有三种消息丢失的情况:

  1. 生产者给 broker 发送的消息,broker 没有收到
  2. broker 将消息丢失
  3. broker 给消费者发送消息时消息丢失

对于第一种情况,我们可以使用 RabbitMQ 提供的发布确认模式;

对于第三种情况,我们可以使用 RabbitMQ 的发布确认特性;

对于第二种情况,我们可以使用 RabbitMQ 的持久化特性。

2. 什么是持久化特性

RabbitMQ 的持久化表示的是资源存储在硬盘中,当 RabbitMQ 服务器重启后,设置为持久化的资源不会被释放,除非手动删除,不然不会丢失。

RabbitMQ 的持久化特性分为:

  • 交换机持久化
  • 队列持久化
  • 消息持久化

3. 交换机持久化

在 spring 中,我们声明交换机时,可以为交换机指定是否持久化。

声明持久化交换机:

    //写法一  
    @Bean("persExchange")
    public DirectExchange persExchange() {
        return ExchangeBuilder.directExchange(Constants.PRES_EXCHANGE).build();
    }

    //写法二
    @Bean("persExchange")
    public DirectExchange persExchange() {
        return ExchangeBuilder.directExchange(Constants.PRES_EXCHANGE).durable(true).build();
    }

在写法一中,没有指定 durable 参数,那么默认就会声明一个持久化交换机。

声明非持久化交换机:

    @Bean("notPersExchange")
    public DirectExchange notPersExchange() {
        return ExchangeBuilder.directExchange(Constants.NOT_PERS_EXCHANGE).durable(false).build();
    }

将 durable 参数设置为 false,就会声明一个非持久化交换机。

4. 队列持久化

我们也可以为队列指定是否持久化。

声明持久化队列:

    @Bean("persQueue")
    public Queue persQueue() {
        return QueueBuilder.durable(Constants.PERS_QUEUE).build();
    }

调用 durable 方法即可声明一个持久化队列。

声明非持久化队列:

    @Bean("notPersQueue")
    public Queue notPersQueue() {
        return QueueBuilder.nonDurable(Constants.NOT_PERS_QUEUE).build();
    }

调用 nonDurable 方法即可声明一个持久化队列。

5. 消息持久化

生产者在发送消息时,可以指定该消息是否持久化。

发送持久化消息:

    @RequestMapping("/pres")
    public String pers() {

        String messageInfo = "pres message";

        Message message = new Message(messageInfo.getBytes(StandardCharsets.UTF_8),
                new MessageProperties());

        //设置消息持久化
        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);

        rabbitTemplate.convertAndSend(Constants.PRES_EXCHANGE, Constants.PERS_ROUTINGKEY, message);

        return "持久化消息发送成功";
    }

MessageDeliveryMode 提供了两个参数,分别为 PERSISTENT 和 NON_PERSISTENT,表示持久化和非持久化。

发送非持久化消息:

    @RequestMapping("/nPres")
    public String nPers() {

        String messageInfo = "nPres message";

        Message message = new Message(messageInfo.getBytes(StandardCharsets.UTF_8),
                new MessageProperties());

        //设置消息非持久化
        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);

        rabbitTemplate.convertAndSend(Constants.NOT_PERS_EXCHANGE, Constants.PERS_ROUTINGKEY, message);

        return "非持久化消息发送成功";
    }

6. 交换机、队列、消息三者之间持久化的影响

  • 当交换机为持久化时,重启服务器,交换机依然存在
  • 当交换机为非持久化时,重启服务器,交换机不存在
  • 当队列为持久化、队列中的消息为持久化时,重启服务器,队列依然存在,队列中的消息依然存在
  • 当队列为持久化、队列中的消息为非持久化时,重启服务器,队列依然存在,队列中的消息不存在
  • 当队列为非持久化、队列中的消息为持久化时,重启服务器,队列不存在,队列中的消息不存在
  • 当队列为非持久化、队列中的消息为非持久化时,重启服务器,队列不存在,队列中的消息不存在

网站公告

今日签到

点亮在社区的每一天
去签到