队列懒加载
RabbitMQ从3.6.0 版本开始,RabbitMQ引入了懒加载队列的概念
RAM内存警报
默认情况下,RabbitMQ会时实时监控该服务使用内存的情况,当使用的内存超过服务所在计算机的总RAM内存的40%时,就会触发内存警报,此时RabbitMQ就会阻塞所有正在推送消息的连接直到内存警报解除。 出现内存警报时, RabbitMQ会将消息尽量的移出到硬盘上来解决RAM内存占用过多问题。 你可以通过修改配置文件来更改默认的阀值,默认是0.4,即 40%
vm_memory_high_watermark.relative = 0.4
当然,你也可以设置一个绝对的值,单位是:byte
vm_memory_high_watermark.absolute = 1073741824
内存阀值也可以在broker运行期间通过命令行设置进行更改:
rabbitmqctl set_vm_memory_high_watermark [fraction]:设置相对值rabbitmqctl set_vm_memory_high_watermark absolute [memory_limit]:设置绝对值
如果想要立刻解决内存警报,全局停止所有的消息传送,那么可以设置内存阀值为 0
rabbitmqctl set_vm_memory_high_watermark 0
缩减RAM占用
为了解决RAM内存占用过多的问题,RabbitMQ在内存占用达到上述设置的内存阀值的50%的时候,就会开始将消息内容从队列中移出到硬盘保存的工作 (持久化消息在接收的时候就已经保存到硬盘,此时会清除持久化消息在RAM内存中的副本)。 这个阀值也可以配置文件修改,默认值是0.5:
vm_memory_high_watermark_paging_ratio = 0.75
该值也可以设置为一个大于 1 的数值,这时该值就不会起作用
设置队列懒加载
队列有两种形式:默认模式 default 和懒加载模式 lazy。默认模式下,当队列收到消息的时候会将消息存放到RAM内存中 (如果是持久化队列,则会在磁盘和内存中各有一份) ,这就保证了消息最快的被分发到消费者。懒加载模式下,队列会试图尽可能早的将消息从RAM移出到磁盘中,这样就会释放了RAM内存,带来的代价就是I/O的开销。 队列的懒加载模式可以通过两种形式设置
使用
policy设置, 可以通过命令行,也可以通过WEB UI页面进行操作rabbitmqctl set_policy Lazy "^lazy-queue$" '{"queue-mode":"lazy"}' --apply-to queues通过队列参数设置
x-queue-modeMap<String, Object> args = new HashMap<>(); args.put("x-queue-mode", "lazy"); channel.queueDeclare("myqueue", false, false, false, args);
运行时队列模式切换
- 当一个队列从
default模式切换到lazy模式时,该队列会将所有存在RAM中的消息移出到磁盘上,与此同时,该队列将不会接收任何新的推送消息,直到模式转换操作完成,所有的操作才能正常进行 - 当一个队列从
lazy模式切换到default模式时,相当于重启服务后的队列恢复操作,该队列中将会把最多 16384 条消息加载到内存中
关于延迟队列的一些说明
- 当将节点内存使用率保持在较低的优先级,并且可以接受较高的磁盘I/O和磁盘使用率时,可以考虑使用延迟队列
- 当一个RabbitMQ节点正在运行并且正常操作的情况下,延迟队列会保证除了正在传送中的信息,其他的信息都会存放在磁盘上
- 如果一个RabbitMQ节点所在的主机不能充分提供需要的内存和磁盘空间,那么该节点是无法正常启动的
- 如果一个RabbitMQ节点受内存限制,或者在该主机上又很多的延迟队列,那么这将会规划容量很重要的考虑因素
- 当一个RabbitMQ节点启动时,所有的队列(包括延迟队列)将会最多将队列中 16384 条消息加载到内存中