RabbitMQ的持久化设置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RabbitMQ的持久化设置相关的知识,希望对你有一定的参考价值。

参考技术A “持久化”可以提高RabbitMQ的可靠性,以防在异常情况(重启、关闭、宕机等)下的数据丢失。RabbitMQ的持久化分为三个部分:交换器的持久化、队列的持久化和消息的持久化。

交换器的持久化是通过在声明队列是将durable参数设置为true实现的。如果交换器不设置持久化,那么在RabbitMQ服务器重启之后,相关的交换器元数据会丢失,不过消息不会丢失,只是不能将消息发送到这个交换器中了。对于一个长期使用的交换器来说,建议将其设置为持久化的。

队列的持久化是通过在声明队列时将durable参数设置为true实现的。如果队列不设置持久化,那么在RabbitMQ服务重启之后,相关队列的元数据会丢失,此时数据也会丢失。争所谓“皮之不存,毛将焉附”,队列都没有了,消息有能存在哪里呢?

队列的持久化能保证其本身的元数据不会因异常情况而丢失,但是不能保证内部所存储的消息不会丢失。要确保消息不会丢失,需要将其设置为持久化。通过将消息的投递模式(BasicProperties中的deliveryMode属性)设置为2即可实现消息的持久化。

设置了队列和消息的持久化,当RabbitMQ服务重启之后,消息依旧存在。单单只设置队列持久化,重启之后消息会丢失,单单只设置了消息的持久化,重启之后队列消失,继而消息也丢失。单单设置消息持久化而不设置队列的持久化显得毫无意义。

将交换器、队列、消息都设置了持久化之后就能百分之百保证数据不丢失了吗?答案是否定的。

首先从消费者来说,如果在订阅消费队列时将autoAck参数设置为true,那么当消费者接收到相关消息之后,还没来得及处理就宕机了,这样也算数据丢失。这种情况很好解决,将autoAck参数设置为false,并进行手动确认。

其次,在持久化的消息正确存入RabbitMQ之后,还需要一段时间(虽然很短,但是不可忽视)才能存入磁盘之中。RabbitMQ并不会为每条消息都进行同步存盘(调用内核的fsync方法)的处理,可能仅仅保存在操作系统缓存之中而不是物理磁盘之中。如果在这段时间内RabbitMQ服务节点发生了宕机、重启等异常情况,消息保存还没来得及落盘,那么这些消息将会丢失。

这个问题怎么解决呢?这里可以引入RabbitMQ的镜像队列机制,相当于配置了副本,如果主节点(master)在此特殊时间内挂掉,可以自动切换到从节点(slave),这样有效地保证了高可用性,除非整个集群都挂掉。虽然这样也不能完全保证RabbitMQ消息不丢失,但是配置了镜像队列要比没有配置镜像队列的可靠性要高很多,在实际生产环境中的关键业务队列一般都会设置镜像队列。

还可以在发送端引入事务机制或者发送方确认机制来保证消息已经正确地发送并存储至RabbitMQ中,前提还要保证在调用channel.basicPublish方法的时候交换器能够将消息正确路由到相应的队列之中。

以上是关于RabbitMQ的持久化设置的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 之持久化

RabbitMQ持久化

.Net RabbitMQ实战指南——进阶

RabbitMQ进阶

RabbitMQ进阶

RabbitMQ概要图