持久化
持久化在前面多次提到,持久化可以提高 RabbitMQ 的可靠性,防止在异常情况(重启、关闭、宕机等)下的数据丢失。
本节针对这个概念做一个总结。RabbitMQ 的持久化分为三个部分:
- 交换器的持久化在声明交换器是将 durable 参数设置为 true 实现,如果不持久化,RabbitMQ 服务重启之后,相关的交换器元数据会丢失(没有这个交换器了),但是 队列和消息不会丢失(分情况是否设置持久化),只是 不能将消息发送到这个交换器了。
- 队列的持久化在声明队列时将 durable 参数设置为 true 实现,如果不持久化,RabbitMQ 服务重启之后,相关的 元数据会丢失,消息也会丢失;
- 消息的持久化但是队列的持久化,并 不能保证消息数据不丢失,要保证消息不丢失,需要将消息的投递模式设置为 2 (BasicProperties 中的 deliveryMode 属性)
注意要点
不是所有的消息都设置持久化,在一些对可靠性要求不是那么高的消息,可以不采用持久化。这样可以提高整体的吞吐量。
交换器、队列、消息都设置为持久化,也有可能丢失,有以下一个方面:
- autoAck :自动确认在业务系统中,自动确认是最容易丢失的,如果处理过程中发生异常,消息可能就丢了。解决方案:改成手动 ack
- 数据刷盘:RabbitMQ 依赖内核的 fsync 函数存盘关于 fsync 函数,自己百度;大概就是数据先写缓存,等待缓存写满,或则内核需要重用缓存时,会将该缓存排入输出队列,进而同步到设备上。服务器突然断电,就有可能导致丢失一部分数据;解决方案:可以使用 RabbitMQ 的镜像队列机制(后面章节会讲解),相当于配置了副本,master 挂掉,会自动切换到 slave 节点,保证了高可用性。
还可以在发送端引 入事物机制 或 发送方确认机制 来保证消息已经正确发送并存储至 RabbitMQ 中。下一章节讲解