RabbitMQ 高级特性之持久性
1. 简介
在 RabbitMQ 的消息发送流程中,一共有三种消息丢失的情况:
- 生产者给 broker 发送的消息,broker 没有收到
- broker 将消息丢失
- 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. 交换机、队列、消息三者之间持久化的影响
- 当交换机为持久化时,重启服务器,交换机依然存在
- 当交换机为非持久化时,重启服务器,交换机不存在
- 当队列为持久化、队列中的消息为持久化时,重启服务器,队列依然存在,队列中的消息依然存在
- 当队列为持久化、队列中的消息为非持久化时,重启服务器,队列依然存在,队列中的消息不存在
- 当队列为非持久化、队列中的消息为持久化时,重启服务器,队列不存在,队列中的消息不存在
- 当队列为非持久化、队列中的消息为非持久化时,重启服务器,队列不存在,队列中的消息不存在