RabbitMQ延迟消息

目录

一、死信交换机

二、延迟消息插件

声明延迟交换机

发送延迟消息


使用场景

在电商的支付业务中,对于一些库存有限的商品,为了更好的用户体验,通常都会在用户下单时立刻扣减商品库存。例如电影院购票、高铁购票,下单后就会锁定座位资源,其他人无法重复购买。

但是这样就存在一个问题,假如用户下单后一直不付款,就会一直占有库存资源,导致其他客户无法正常交易,最终导致商户利益受损!

因此,电商中通常的做法就是:对于超过一定时间未支付的订单,应该立刻取消订单并释放占用的库存

例如,订单支付超时时间为30分钟,则我们应该在用户下单后的第30分钟检查订单支付状态,如果发现未支付,应该立刻取消订单,释放库存。

延迟消息:生产者发送消息时指定一个时间,消费者不会立刻收到消息,而是在指定时间之后才收到消息。

延迟任务:设置在一定时间之后才执行的任务

一、死信交换机

当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):

  • 消费者使用basic.rejectbasic.nack声明消费失败,并且消息的requeue参数设置为false
  • 消息是一个过期消息,超时无人消费
  • 要投递的队列消息满了,无法投递

如果一个队列中的消息已经成为死信,并且这个队列通过**dead-letter-exchange** 属性指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机就称为死信交换机(Dead Letter Exchange)。

死信交换机的作用

  1. 收集那些因处理失败而被拒绝的消息
  2. 收集那些因队列满了而被拒绝的消息
  3. 收集因TTL(有效期)到期的消息

首先创建一个队列绑定死信交换机

创建交换机绑定队列

绑定队列

在创建一组队列和交换机

绑定队列

生产者发送消息

复制代码
 @Test
    public void SendTTLMessage() {
        // 队列名称
        String queueName = "simple.direct";
        // 消息
        Message message = MessageBuilder.withBody("hello".getBytes(StandardCharsets.UTF_8))
                .setExpiration("10000")//单位毫秒
                .build();
        // 发送消息
        rabbitTemplate.convertAndSend(queueName,"hello", message);
    }

消费者接受消息

复制代码
@RabbitListener(queues = "dlx.queue")
    public void listenDlxQueueMessage(Map<String, Object> msg) throws InterruptedException {
        System.out.println("消费者接收到object.queue消息:【" + msg + "】");
    }

十秒钟后消息到死心队列

二、延迟消息插件

基于死信队列虽然可以实现延迟消息,但是太麻烦了。因此RabbitMQ社区提供了一个延迟消息插件来实现相同的效果

官方文档说明: Scheduling Messages with RabbitMQ | RabbitMQ - Blog

插件下载地址: GitHub - rabbitmq/rabbitmq-delayed-message-exchange: Delayed Messaging for RabbitMQ 由于我们安装的MQ是3.8版本,因此这里下载3.8.17版本

因为我们是基于Docker安装,所以需要先查看RabbitMQ的插件目录对应的数据卷。

复制代码
docker volume inspect mq-plugins

插件目录被挂载到了/var/lib/docker/volumes/mq-plugins/_data这个目录,我们上传插件到该目录下

开启插件

复制代码
docker exec -it mq rabbitmq-plugins enable rabbitmq_delayed_message_exchange
声明延迟交换机

基于注解方式:

复制代码
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "delay.queue", durable = "true"),
        exchange = @Exchange(name = "delay.direct", delayed = "true"),
        key = "delay"
))
public void listenDelayMessage(String msg){
    log.info("接收到delay.queue的延迟消息:{}", msg);
}

基于@Bean的方式:

复制代码
package com.itheima.consumer.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class DelayExchangeConfig {

    @Bean
    public DirectExchange delayExchange(){
        return ExchangeBuilder
                .directExchange("delay.direct") // 指定交换机类型和名称
                .delayed() // 设置delay的属性为true
                .durable(true) // 持久化
                .build();
    }

    @Bean
    public Queue delayedQueue(){
        return new Queue("delay.queue");
    }
    
    @Bean
    public Binding delayQueueBinding(){
        return BindingBuilder.bind(delayedQueue()).to(delayExchange()).with("delay");
    }
}
发送延迟消息

发送消息时,必须通过x-delay属性设定延迟时间:

复制代码
@Test
void testPublisherDelayMessage() {
    // 1.创建消息
    String message = "hello, delayed message";
    // 2.发送消息,利用消息后置处理器添加消息头
    rabbitTemplate.convertAndSend("delay.direct", "delay", message, new MessagePostProcessor() {
        @Override
        public Message postProcessMessage(Message message) throws AmqpException {
            // 添加延迟消息属性
            message.getMessageProperties().setDelay(5000);
            return message;
        }
    });
}
相关推荐
凌乱的豆包17 小时前
Spring Cloud Alibaba Nacos 服务注册发现和分布式配置中心
分布式
独隅19 小时前
PyTorch 分布式训练完整指南:策略、实现与模型选型
人工智能·pytorch·分布式
架构师老Y20 小时前
011、消息队列应用:RabbitMQ、Kafka与Celery
python·架构·kafka·rabbitmq·ruby
墨北小七1 天前
小说大模型的分布式训练——张量并行架构设计与实现
分布式
豆豆1 天前
政务服务平台站群一体化解决方案
大数据·分布式·微服务·cms·政务·网站管理系统·站群cms
昵称暂无11 天前
分布式事务难题:Seata框架在微服务中的落地实践
分布式·微服务·架构
都说名字长不会被发现1 天前
分布式场景下的数据竞争问题与解决方案
分布式·乐观锁·悲观锁·redission·redis 分布式锁·数据版本
甘露s1 天前
分布式与可重入性的一些问题
分布式
juniperhan1 天前
Flink 系列第 3 篇:核心概念精讲|分布式缓存 + 重启策略 + 并行度 底层原理 + 代码实战 + 生产规范
大数据·分布式·缓存·flink
想你依然心痛1 天前
HarmonyOS 5.0 IoT开发实战:构建分布式智能设备控制中枢与边缘计算网关
分布式·物联网·harmonyos