理论和实践详解RabbitMQ惰性/延迟队列(lazy queues)(带测试样例及分析)

1 缘起

最近在补充RabbitMQ的相关知识,
之前仅学习RabbitMQ的基础使用,集成到SpringBoot中,
只是使用了一些基础功能,如手动ACK、发布确认等,
对于队列的类型并没有深入研究,直接使用默认队列,
再次学习时才发现,RabbitMQ还有很多于我而言的高级功能,
先从Lazy队列开始补充,
分享如下,
这里不单单分享理论知识,同时,给出测试样例,验证lazy队列相关功能,加深理解。

官网地址:https://www.rabbitmq.com/lazy-queues.html

2 Lazy队列

RabbitMQ从3.6.0版本开始,Broker引入了LazyQueues(惰性队列/延迟队列),该队列会即时将存入队列中的数据持久化到磁盘,当需要消费时才将数据加载到内存。
Lazy queues的主要目的之一是让队列支持长队列(百万级消息),实际应用中队列会变得很长的原因:

  • 消费者下线、销毁或者维护中;
  • 进入队列的消息数量激增,生产者生产数据的速度超过消费者消费速度;
  • 消费者消费速度比正常情况低。

默认情况下,发送到RabbitMQ的消息会直接进入内存(外存内存),保证消费者可以快速获取消息,而持久化的消息进入内存的同时会写入到磁盘。
当Broker需要释放内存时,消息会从缓存交换到磁盘,将批量消息从内存交换到磁盘过程中耗时且阻塞队列(无法接收新消息)。虽然近期的RabbitMQ版本有改进交换算法,但是,对于数百万量级的消息交换仍不是很高效。
Lazy queues尝试将消息尽早落盘,换句话说,在内存中的数据会大大减少,但是,增加了磁盘的I/O。

2.1 配置队列模式

RabbitMQ的队列可以配置为默认模式或lazy模式。

  • 推荐使用队列策略,可以运行时修改队列模式;
  • 通过queue.declare参数配置队列模式,新建队列时使用,无法运行时修改;

同时使用策略和队列参数指定队列模式时,队列参数优先级高于策略值,即Policy为Lazy,queue-mode参数为default,此时队列处于非lazy模式。
若在声明队列时通过可选参数配置队列模式,则只能通过删除队列并使用其他不同的参数重新声明来变更队列模式。

2.2 队列策略修改队列模式为lazy(运行时变更)

通过queue-mode配置队列为lazy模式,如下:

  • Linux操作系统
rabbitmqctl set_policy Lazy "^test-lazy-queue-1$" '{"queue-mode":"lazy"}'  --vhost /tutorial --apply-to queues
  • Windows操作系统
rabbitmqctl set_policy Lazy "^test-lazy-queue-1$" "{""queue-mode"":""lazy""}" --vhost /tutorial --apply-to queues

命令参数解析如下表:

序号 参数 描述
1 rabbitmqctl RabbitMQ客户端命令
2 set_policy 设定策略
3 Lazy Lazy标识
4 ^test-lazy-queue-1$ 队列名称,其中^和$可不填
5 queue-mode 队列模式,lazy或者default
6 –vhost 指定vhost
7 –apply-to 应用到某个对象,如queues,作用于队列
  • Windows客户端端操作结果
    如下图所示。
    在这里插入图片描述

  • 配置结果
    通过RabbitMQ自带的监控平台,可以查看队列test-lazy-queue-1的工作模式为lazy,
    如下图所示。其中Policy为Lazy(标识作用),queue-mode为lazy,即队列为lazy模式。
    理论和实践详解RabbitMQ惰性/延迟队列(lazy queues)(带测试样例及分析)_第1张图片

2.3 运行时变更队列模式为非lazy

若队列是通过策略方式配置的工作模式,可以在运行时改变其工作模式,无需删除并重新声明队列。直接修改queue-mode为default即可变更队列模式。

  • Linux操作系统
rabbitmqctl set_policy Lazy "^test-lazy-queue-1$" '{"queue-mode":"default"}'  --vhost /tutorial --apply-to queues
  • Windows操作系统
rabbitmqctl set_policy Lazy "^test-lazy-queue-1$" "{""queue-mode"":""default""}" --vhost /tutorial --apply-to queues
  • Windows客户端变更队列
    test-lazy-queue-1为非lazy模式,如下图所示。
    在这里插入图片描述

  • 变更结果
    通过RabbitMQ监控平台查看,如下图所示,
    由图可知,queue-mode为default,此时队列为非lazy模式,
    而Policy为Lazy标识。
    理论和实践详解RabbitMQ惰性/延迟队列(lazy queues)(带测试样例及分析)_第2张图片

2.4 声明队列时指定为lazy模式

通过配置x-queue-mode参数可在声明队列时指定队列模式,如default和lazy。
不指定x-queue-mode,则默认为default,该模式在RabbitMQ3.60版本的Broker已经支持,截止目前没有革命性改进。
下面通过Java程序实现声明队里时指定x-queue-mode为lazy。

2.4.1 引入依赖


<dependency>
    <groupId>com.rabbitmqgroupId>
    <artifactId>amqp-clientartifactId>
    <version>5.12.0version>
dependency>

2.4.2 测试样例

创建队列test-lazy-queue-3时,通过x-queue-mode指定工作模式。

package com.monkey.java_study.mq.rabbitmq;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * RabbitMQ生产者.
 *
 * @author xindaqi
 * @since 2022-07-27 15:50
 */
public class RabbitMQLazyProvider {
   

    public static void main(String[] args) {
   
        try (Connection connection = RabbitMQConnection.connectionFactoryDefault(); Channel channel = connection.createChannel()) {
   
            String queueName = "test-lazy-queue-3";
            boolean durableFlag = false;
            boolean exclusiveFlag = false;
            boolean autoDeleteFlag = false;
            Map<String, Object> queueMode = new HashMap<>(2);
            // 指定x-queue-mode为lazy
            queueMode.put("x-queue-mode", "lazy");
            // 声明队列
            channel.queueDeclare(queueName, durableFlag, exclusiveFlag, autoDeleteFlag, queueMode);
            String exchangeName = "test-exchange";
            String routingKey = "test-routing-key";
            // 指定exchange和DIRECT方式
            channel.exchangeDeclare(exchangeName, Bui

你可能感兴趣的:(#,消息队列,java-rabbitmq,rabbitmq,java)