持久性
我们在前面说了消息端处理消息时,消息如何不丢失,但是如何保证当 RabbitMQ 服务器停掉之后,生产者发送的消息不丢失呢?
默认情况下,RabbitMQ 退出或者由于某种原因崩溃时,会忽视队列和消息,除非告知他不要这么做
RabbitMQ 的持久化分为三个部分:
- 交换器的持久化
- 队列的持久化
- 消息的持久化
交换机持久化
交换机的持久化,是通过在声明交换机时将 durable 参数置为 true 实现的
- 相当于将交换机的属性在服务器内部保存,当
MQ的服务器发生意外或关闭之后,重启RabbitMQ时不需要重新去建立交换机,交换机会自动建立,相当于一直存在 - 如果交换器不设置持久化,那么在
RabbitMQ服务器重启之后,相关的交换机元数据会丢失,对一个长期使用的交换机来说,建议将其置为持久化的
ExchangeBuilder.topicExchange(Constant.ACK_EXCHANGE_NAME).durable(true).build();
队列持久化
队列的持久化是通过在声明队列时将 durable 参数置为 true 实现的
- 如果队列不设置持久化,那么在
RabbitMQ服务器重启之后,该队列就会被删除掉,此时数据也会丢失(队列没有了,消息也无处可存了) - 队列的持久化能保证该队列本身的元数据不会因异常情况而丢失,但是并不能保证内部存储的消息不会丢失
- 要确保消息不会丢失,需要将消息设置为持久化
咱们前面用的创建队列的方式都是持久化的
QueueBuilder.durable(COnstant.ACK_QUEUE).build();
点进去看源码会发现,该方法默认 durable 是 true
public static QueueBuilder durable() {
return durable(namingStrategy.generateName());
}
private QueueBuilder setDurable() {
this.durable = true;
return this;
}
通过下面代码,可以创建非持久化的队列
QueueBuilder.noDurable(Constant.ACK_QUEUE).build();
消息持久化
消息实现持久化,需要把消息的投递模式 (MessageProperties 中的 deliveryMode)设置为 2,也就是 MessageDeliveryMode.PERSISTENT
public enum MessageDeliveryMode {
NON_PERSISTENT,
PERSISTENT;
设置了队列和消息的持久化,当 RabbitMQ 服务器重启之后,消息依旧存在。
- 如果只设置队列持久化,重启之后消息会丢失
- 如果只设置消息持久化,重启之后队列消息,继而消息也丢失
所以单单设置消息持久化而不设置队列的持久化显得毫无意义
// 非持久化信息
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
// 持久化信息
channel.basicPublish("", QUEUE_NAME,