RabbitMQ消息持久化与内存管控


RabbitMQ消息持久化与内存管控。

【MQ中间件】RabbitMQ消息持久化与内存管控

RibbitMQ持久化

持久化就把信息写入到磁盘的过程。

RibbitMQ持久化

消息什么时候需要持久化:

消息本身在publish的时候就要求消息写入磁盘;

内存紧张,需要将部分内存中的消息转移到磁盘;

持久化是为提高rabbitmq消息的可靠性,防止在异常情况(重启,关闭,宕机)下数据的丢失。

rabbitmq持久化分为三个部分: 交换器的持久化、队列的持久化和消息的持久化

交换器的持久化

交换器的持久化是通过声明队列时,将durable参数设置为true实现的。如果交换器不设置持久化,那么rabbitmq服务重启之后,exchange将不复存在,不过消息不会丢失,那么既而发送方rabbitmq producer就无法正常发送消息。建议将交换器设置为持久化。

未持久化exchange

绑定在未持久化exchange上的持久化queue与持久化消息

未持久化exchange重启之后消失

队列的持久化

队列的持久化是通过声明队列时,将durable参数设置为true实现的。如果队列不设置持久化,那么rabbitmq服务重启之后,相关的队列元数据将会丢失,而消息是存储在队列中的,所以队列中的消息也会被丢失。

未持久化队列持久化消息

持久化的消息

未持久化队列重启消息丢失

消息的持久化

队列的持久化只能保证其队列本身的元数据不会被丢失,但是不能保证消息不会被丢失。所以消息本身也需要被持久化,可以在投递消息前设置AMQP.BasicProperties的属性deliveryMode为2即可,spring boot和rabbitmq整合以后,默认消息是会被持久化的。

消息都设置为持久化,但是这样会影响RabbitMQ的性能。因为我们将消息写入到内存的同时还需要将消息写入到磁盘。
对于可靠性要求不是那么高的消息可以不采用持久化处理,以提高整体系统的吞吐量。

总结

将交换器、队列和消息都设置持久化之后就能保证数据不会被丢失吗?当然不是,多个方面

  • 消费者端: 消费者订阅队列将autoAck设置为true,虽然消费者接收到了消息,但是没有来得及处理就宕机了,那数据也会丢失,解决方案就是以为手动确认接收消息,待处理完消息之后,手动删除消息
  • 在rabbitmq服务端,如果消息正确被发送,但是rabbitmq未来得及持久化,没有将数据写入磁盘,服务异常而导致数据丢失,解决方案,可以通过rabbitmq集群的方式实现消息中间件的高可用性

内存限制

内存告警

当内存使用超过配置的阈值或者磁盘剩余空间低于配置的阈值时会暂时阻塞客户端的连接,并停止接收从客户端发来的消息,以避免服务崩溃,客户端与服务端的心跳检测也会失败。当出现内存告警时,可以通过管理命令临时调整内存大小。

rabbitmqctl set_vm_memory_high_watermark <fraction>

fraction为内存阈值,RabbitMQ默认是0.4,表示当RabbitMQ使用的内存超过总内存的40%时,就会产生告警并阻塞所有生产连接。 通过此命令修改的阈值在RabbitMQ重启之后将会失效,通过修改配置文件的方式设置的阈值才会永久有效,但需要重启服务才会生效。

配置文件:RabbitMQ.conf

#相对值,也就是前面的fraction,建议设置在0.4~0.66之间,不要超过0.7
vm_memory_high_watermark.relative=0.4
#绝对值,单位为KB,MB,GB,对应的临时命令是:RabbitMQctl set_vm_memory_high_watermark absolute <value>
#vm_memory_high_watermark.absolute=1GB

阻塞

当出现blocking或blocked话说明到达了阈值和以及高负荷运行了。

内存换页

在某个broker节点触及内存并阻塞生产者之前,他会尝试将队列内存中的消息换页存储到磁盘以释放内存空间。持久化和非持久化的消息都会被转储到磁盘中,其中持久化的消息本身就在磁盘中有一个备份,所以这里会将持久化的消息从内存中清除掉。
默认情况下,在内存达到内存阈值的50%时会进行换页操作。也就是说,在默认的内存阈值40%的情况下,当内存超过0.4*0.5=0.2时会经行换页动作。
内存换页可以通过在配置文件中设置来进行调整。

vm_memory_high_watermark_paging_ratio=0.75

磁盘限制

当磁盘剩余空间低于设置的阈值时,RabbitMQ同样会阻塞生产者,这样可以避免因非持久化的消息持续换页而耗尽磁盘空间导致服务崩溃。
默认情况下,磁盘的阈值是5OM,表示当磁盘剩余空间低于5OM时,会阻塞生产者并停止内存中消息的换页动作。这个阈值的设置可以减小,但不能完全消除因磁盘耗尽而导致崩溃的可能性。比如在两次磁盘空间检测期间内,磁盘空间从大于50M被耗尽到OM。
备注:一个相对谨慎的做法是将磁盘阈值设置为与操作系统所显示的内存大小一致。
通过以下命令可以临时调整磁盘阈值

#设置具体大小,单位为KB/MB/GB
rabbitmqctl set_disk_free_limit <disk_limit>
#设置相对值,建议取值为1.0~2.0(相对于内存的倍数,如内存大小是8c,若为1.0,则表示磁盘剩余8G时阻塞)
rabbitmqctl set_disk_free_limit mem_relative <fraction>

对应的配置文件配置如下:
disk_free_limit.relative=2.0
#disk_free_limit_absolute=50MB

运行时查看生效的配置文件信息

rabbitmq-diagnostics environment

引用

RabbitMQ持久化机制

RabbitMQ – RabbitMQ死信队列及内存监控

RabbitMQ持久化机制


文章作者: WangQingLei
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WangQingLei !
  目录