RabbitMQ高级特性--延迟消息实现

rabbitmq专栏
代码地址:码云

1. 什么是延迟队列?

延时队列,首先,它是一种队列,队列意味着内部的元素是有序的,元素出队和入队是有方向性的,元素从一端进入,从另一端取出。

其次,延时队列,最重要的特性就体现在它的延时属性上,跟普通的队列不一样的是,普通队列中的元素总是等着希望被早点取出处理,而延时队列中的元素则是希望被在指定时间得到取出和处理,所以延时队列中的元素是都是带时间属性的,通常来说是需要被处理的消息或者任务。

简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列

2. 延迟队列使用场景

那么什么时候需要用延时队列呢?考虑一下以下场景:

  • 订单在十分钟之内未支付则自动取消。

  • 新创建的店铺,如果在十天内都没有上传过商品,则自动发送消息提醒。

  • 账单在一周内未支付,则自动结算。

  • 用户注册成功后,如果三天内没有登陆则进行短信提醒。

  • 用户发起退款,如果三天内没有得到处理则通知相关运营人员。

  • 预定会议后,需要在预定的时间点前十分钟通知各个与会人员参加会议。

3. 延迟队列的实现方式

3.1 利用TTL+死信队列

生产者生产一条延时消息,根据需要延时时间的不同,利用不同的routingkey将消息路由到不同的延时队列,每个队列都设置了不同的TTL属性,并绑定在同一个死信交换机中,消息过期后,根据routingkey的不同,又会被路由到不同的死信队列中,消费者只需要监听对应的死信队列进行处理即可

在这里插入图片描述
这种方式的弊端,无法做到通用性,每搞一个新的延迟任务,都要去实现一个实现的TTL+死信队列,比较麻烦;

3.2 利用RabbitMQ插件实现

安装一个插件即可:Community Plugins

下载rabbitmq_delayed_message_exchange插件,然后解压放置到RabbitMQ的插件目录。

接下来,进入RabbitMQ的安装目录下的sbin目录,执行下面命令让该插件生效,然后重启RabbitMQ。

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

下面详细操作一下:

3.2.1 容器挂载

本地创建一个rabbitmq目录:
在这里插入图片描述
执行下面命令:

docker run -it --rm --name rabbitmq5 -v /home/docker/rabbitmq/:/root/data/   -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin  -p 5672:5672 -p 15672:15672    rabbitmq:3-management
3.2.2 上传插件

插件下载地址: rabbitmq-delayed-message-exchange插件下载

然后直接通过finalshell上传rabbitmq_delayed_message_exchange插件到/home/docker/rabbitmq, 插件会自动同步到容器里的/root/data目录里面
在这里插入图片描述
在这里插入图片描述

3.2.3 复制到RabbitMQ的插件目录
cp /root/data/rabbitmq_delayed_message_exchange-3.8.0.ez /plugins

在这里插入图片描述

3.2.4 使插件生效

接下来,进入RabbitMQ的安装目录下的sbin目录,执行下面命令让该插件生效,然后重启RabbitMQ。

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

执行上面这个命令的时候有个报错说是版本不支持,又换了个rabbitmq_delayed_message_exchange-3.9.0.ez的,然后执行成功,如下图:

在这里插入图片描述
然后通过 docker restart + 容器id 重启即可。

4. 代码实现

4.1 RabbitMQConfig配置

	/**
     * delayedDirect交换机名称
     */
    public static final String DELAYED_DIRECT_EXCHANGE="delayedDirectExchange";

    /**
     * delayed direct队列名称
     */
    public static final String DELAYED_DIRECT_QUEUE="delayedDirectQueue";

    /**
     * delayed_direct路由Key
     */
    public static final String DELAYED_DIRECT_ROUTINGKEY="delayed_directRoutingKey";

    /**
     * 定义一个delayed direct交换机
     * @return
     */
    @Bean
    public CustomExchange delayedDirectExchange(){
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(DELAYED_DIRECT_EXCHANGE,"x-delayed-message", true, false, args);

    }

    /**
     * 定义一个DELAYED direct队列
     * @return
     */
    @Bean
    public Queue delayedDirectQueue(){
        return new Queue(DELAYED_DIRECT_QUEUE);
    }

    /**
     * 定义一个队列和交换机的绑定
     * @return
     */
    @Bean
    public Binding delayedDirectBinding(){
        return BindingBuilder.bind(delayedDirectQueue()).to(delayedDirectExchange()).with(DELAYED_DIRECT_ROUTINGKEY).noargs();
    }

4.2 producer

在这里插入图片描述
启动类:
在这里插入图片描述

4.3 consumer

在这里插入图片描述
另外,把手动签收注释掉,让它自动签收消息:
在这里插入图片描述

4.4 启动服务,测试

在这里插入图片描述

在这里插入图片描述
测试成功!

参考视频:https://www.bilibili.com/video/BV13K4y1H7Zh?p=19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值