队列懒加载

队列懒加载

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-mode

    Map<String, Object> args = new HashMap<>();
    args.put("x-queue-mode", "lazy");
    channel.queueDeclare("myqueue", false, false, false, args);
    

运行时队列模式切换

  • 当一个队列从 default 模式切换到 lazy 模式时,该队列会将所有存在RAM中的消息移出到磁盘上,与此同时,该队列将不会接收任何新的推送消息,直到模式转换操作完成,所有的操作才能正常进行
  • 当一个队列从 lazy 模式切换到 default 模式时,相当于重启服务后的队列恢复操作,该队列中将会把最多 16384 条消息加载到内存中

关于延迟队列的一些说明

  1. 当将节点内存使用率保持在较低的优先级,并且可以接受较高的磁盘I/O和磁盘使用率时,可以考虑使用延迟队列
  2. 当一个RabbitMQ节点正在运行并且正常操作的情况下,延迟队列会保证除了正在传送中的信息,其他的信息都会存放在磁盘上
  3. 如果一个RabbitMQ节点所在的主机不能充分提供需要的内存和磁盘空间,那么该节点是无法正常启动的
  4. 如果一个RabbitMQ节点受内存限制,或者在该主机上又很多的延迟队列,那么这将会规划容量很重要的考虑因素
  5. 当一个RabbitMQ节点启动时,所有的队列(包括延迟队列)将会最多将队列中 16384 条消息加载到内存中