rabbitMq延迟队列实现

什么是延迟队列?RabbitMQ 如何实现延迟队列? 定义:延迟队列是一种特殊的队列,队列中的元素(消息)并不会立即被消费者获取并处理,而是在经过一段指定的延迟时间后,才会被消费者消费。它主要用于需要在特定时间点或经过一定时间间隔后执行的任务场景。// 延迟队列// 延迟交换机// 延迟路由键// 死信队列// 死信交换机// 死信路由键// 创建连接// 设置RabbitMQ服务器地址// 设置RabbitMQ服务器端口// 设置用户名// 设置密码// 初始化队列和交换机// 声明死信交换机。 阅读详情

前言

我们要实现延迟消息队列效果,在rabbtimq中可以通过TTL+死信的方式,把过期消息转移到死信exchange中,然后再死信exchange绑定的队列中去消费完成后期的业务逻辑。
在这里插入图片描述
但是这里有一个前提就是,我们TTL队列中的过期时间都是一样的,如果不一样就会如下图
在这里插入图片描述
因为消息是排队出队的,如果前面的消息TTL时长大于后面的就会一直阻塞出队口,造成队列阻塞,而后面的消息即便是过期了也依然无法出队释放空间。
所以私信只适合统一过期时长的消息依次入队,如果是不同过期时长的消息并且不是过期时间短的排前面就会造成阻塞或者队列爆满,从而影响实际业务和队列性能。
因此根据不同的过期时长需要创建不同的私信队列,从而实现单一死信只处理单一时长过期的消息。但是这样也会造成死信队列创建冗余,业务累赘的问题。

参考:死信队列
https://blog.youkuaiyun.com/zjcjava/article/details/79410137

rabbitMq延迟队列

目前Kakfa,RockMq因为mq协议也没有定义这种队列标准,因此都不支持延迟队列。RabbitMq为了解决这个情况,增加了一个延迟队列插件abbitmq_delayed_message_exchange
在这里插入图片描述
它的工作模式是消息发给延迟消息交换机,交换机Exchange根据消息头中的TTL判断如果消息过期了,它就把消息转发给绑定相应的KEY队列,然后该队列的消费者去做业务逻辑处理。

这里,延迟交换机是一个非阻塞结构的计数器,它会判断每个消息的过期时长,达到过期时长的消除才会触发转发。没有达到的就一直待在交换机中,这样不用关注你的消息过期时长如何多变和前后不一致,都可以通过它来完成。

默认情况下,它是没有安装这个插件的,需要手工安装插件。

安装插件abbitmq_delayed_message_exchange

官网下载
https://www.rabbitmq.com/community-plugins.html

下载相应版本的文件解压后它是以ez格式结尾的文件
rabbitmq_delayed_message_exchange-3.8.0.ez

在安装的环境执行命令

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

完成后,在管理界面可以看到新建exchange时多了一个Type是x-delayed-message类型
在这里插入图片描述
如果在面板中创建延迟消息交换机,如上图,需要加上Arguments参数,而且是必须加,这样,当延迟交换机才知道消息到期后是以哪种类型发给绑定的队列。
在这里插入图片描述

而,队列则普通队列绑定即可,这里就不做演示了。创建完成我们在Exchange选项卡下面向该延迟消息交换机发送一条延迟消息,上图我创建了一个5000毫秒的消息,路由参数Lazy.bill
点击发送,客户端监听该绑定的消息队列,会发现 它不会立刻接受到消息,等一下才会接受到

代码实现


/**
* rabbitmq配置
 * 实现RabbitListenerConfigurer 主要是为了消息类型转换配置实现MappingJackson2MessageConverter 
 *  
 */

@Configuration
public class RabbitConfig implements RabbitListenerConfigurer {


    /**
     * 基础配置
     * @param connectionFactory
     * @return
     */

    @Bean
    @Primary
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
//        template.setMessageConverter(new Jackson2JsonMessageConverter());
        return template;
    }
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
//        factory.setMessageConverter(new Jackson2JsonMessageConverter());
//        factory.setErrorHandler(new RabbitListenerClassCastFailErrorHandler());
        return factory;
    }


    /**
     * 监听器消费者消息类型转换配置,如果字符串类型这里可以不用配置
     * @return
     */
    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
    }

    @Bean
    MessageHandlerMethodFactory messageHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
        messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter());
        return messageHandlerMethodFactory;
    }

    @Bean
    public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
        return new MappingJackson2MessageConverter();
    }



    /***********延迟队列消息配置*****************/
    public static final String LAZY_EXCHANGE = "Ex.LazyExchange";
    public static final String LAZY_QUEUE = "Qu.LazyQueue";
    public static final String LAZY_KEY = "Lazy.#";
    public static final String LAZY_KEY_BILL = "Lazy.bill";



    @Bean
    public TopicExchange lazyExchange(){
        Map<String, Object> pros = new HashMap<>();
        //设置交换机支持延迟消息推送
        pros.put("x-delayed-type", "direct");
        TopicExchange exchange = new TopicExchange(LAZY_EXCHANGE, true, false,pros);
        exchange.setDelayed(true);
        return exchange;
    }

    @Bean
    public Queue lazyQueue(){
        return new Queue(LAZY_QUEUE, true);
    }

    @Bean
    public Binding lazyBinding(){
        return BindingBuilder.bind(lazyQueue()).to(lazyExchange()).with(LAZY_KEY);
    }



}

消息监听消费端配置



@Slf4j
@Component
public class RabbitmqListener {
 

    /**
     * 延迟队列消息处理
     * @param msg
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = "Qu.LazyQueue")
    @RabbitHandler
    public void onLazyMessage(Message msg, Channel channel) throws IOException {
        long deliveryTag = msg.getMessageProperties().getDeliveryTag();
        channel.basicAck(deliveryTag, true);
        log.info("lazy receive ================================================");
        log.info("lazy receive ={}" + new String(msg.getBody()));
    }



}

延迟消息发送


@Resources
RabbitTemplate rabbitTemplate;

//confirmCallback returnCallback 代码省略,请参照上一篇
    public void sendLazy(BillInfo  billInfo ){
        rabbitTemplate.setMandatory(true);
//        rabbitTemplate.setConfirmCallback(confirmCallback);
//        rabbitTemplate.setReturnCallback(returnCallback);
        //id + 时间戳 全局唯一
        CorrelationData correlationData = new CorrelationData("12345678909"+new Date());

        String  msgJson = JSON.toJSONString(billInfo);
        //发送消息时指定 header 延迟时间
        rabbitTemplate.convertAndSend(RabbitConfig.LAZY_EXCHANGE, RabbitConfig.LAZY_KEY_BILL, msgJson,
                new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        //设置消息持久化,过期时长6000,这里可以根据业务类型自定义每个消息不同的过期时长,比如根据租赁合同结束时间配置不同的过期时长
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                        message.getMessageProperties().setDelay(6000);
                        return message;
                    }
                }, correlationData);
    }
SpringBoot整合RabbitMQ实现消息延迟队列 Slf4j@Data@Builder/*** 商户订单号*//*** 支付宝订单号*/@Slf4j@Component@Autowired//为true,则交换机处理消息到路由失败,则会返回给生产者 配置文件指定,则这里不需指定//开启强制消息投递(mandatory为设置为true),但消息未被路由至任何一个queue,则回退一条消息});log.info("===============延时队列生产消息===================="); 阅读详情

相关推荐

海康威视门禁考勤设备数据对接实战:从被动推送到主动拉取

本文深入探讨了海康威视门禁考勤设备数据对接的两种核心方案:HTTP推送与SDK主动拉取。文章对比了两种方式的适用场景、技术实现与优缺点,为开发者提供了从设备配置、代码编写到工程化部署的完整实战指南,帮助读者根据项目规模、网络环境及数据稳定性要求,做出最合适的技术选型。

weixin_29284657的博客 661

RabbitMQ实战教程(三) : 工作队列

RabbitMQ实战教程(三) : 工作队列 1. 工作队列 简单队列不足 : 不支持多个消费者 即一个生产者可以对应多个消费者同时消费,相比简单队列支持多消费者 . 因为实际工作中,生产者服务一般都是很简单的业务逻辑处理之后就发送到队列,消费者接收到队列的消息之后,进行复杂的业务逻辑处理,所以一般都是多个消费者进行处理.如是是一个消费者进行处理,那么队列会积压很多消息. 工作队列分为两...

makesailing的博客 635

Python实战:5分钟搞定固定翼无人机三自由度仿真(附完整代码)

本文提供了一个基于Python的固定翼无人机三自由度仿真快速实现方案。通过面向对象设计,封装了核心运动学模型,并对比了欧拉法与龙格-库塔法两种积分方法。文章附有完整实例代码,帮助算法工程师和研究人员在5分钟内搭建轻量级仿真环境,用于快速验证控制律、路径规划等核心算法逻辑。

docker7nomad的博客 747

RabbitMQ高阶使用队列实现

目录 1 从打车开始说起 1.1 需要解决的问题 1.1.1 打车排队 2 排队人数 2.1 需求 2.1.1 需求分析 2.2 实现方案 2.2.1 MySQL 2.2.1.1 入队 2.2.1.2 获取进度 2.2.1.3 遇到问题 2.2.3 Redis Zset 2.3 排队人数架构介绍 2.4 数据结构 2.4.2 zset结构 2.4.1 雪花算法 2.5 功能实现 2.5.1 派单 2.5.2 获取排队情况 2.6 演示 2.6.1 派单 2.6.2 排队情况查询

赵广陆 2384

国土变更调查中六类拓扑错误的成因分析与高效修复实践

本文深入分析了国土变更调查中六类拓扑错误的成因,包括边界不一致和不规则图形等常见问题,并提出了高效的自动化修复实践。通过智能咬合算法、引力-斥力平衡模型等核心技术,显著提升了修复效率,节省人工质检时间70%。文章还分享了实战中的避坑指南和黄金法则,为相关从业人员提供了宝贵经验。

weixin_29202213的博客 359

告别Qweb!用ReportBro在Odoo 13-19版本中5步搞定动态报表

本文介绍了如何在Odoo 13-19版本中使用ReportBro替代Qweb快速实现动态报表设计。通过5步集成指南,包括环境准备、前端集成、后端服务搭建等,展示了ReportBro在可视化设计、即时预览和多格式输出(PDF/XLSX)方面的优势,显著提升开发效率和报表灵活性。

mac99的博客 799

RabbitMQ学习==》消息队列

文章目录工作队列1、消息确认2、消息持久化3、任务调度公平化4、完整示例代码产生任务:任务调度及工作者: 工作队列 ​ 创建工作队列,用于多个工作人员之间分配耗时的任务 1、消息确认 为了确保消息永远不会丢失,RabbitMQ 支持 消息确认。消费者发回一个确认,告诉 RabbitMQ 一个特定的消息已经被接收、处理并且 RabbitMQ 可以自由地删除它。 如果消费者在没有发送 ack 的情况下死亡(其通道关闭、连接关闭或 TCP 连接丢失),RabbitMQ 将理解消息未完全处理并将重新排队。 默认情况

weixin_42250577的博客 1801

基于Python的高考志愿辅助填报系统

在实际应用中,系统需要处理更复杂的数据,包括更多的高校和专业信息、更详细的录取规则、以及用户的历史选择等。系统需要提供用户友好的界面,让考生输入自己的信息和偏好,然后通过后端的模型计算出推荐的志愿列表。此外,系统还应该提供一些个性化的服务,如根据考生的输入动态调整推荐策略、保存用户的填报历史和偏好等。特征可能包括考生的分数、所在省份、文理科类别、专业偏好、高校的地理位置、排名、专业的就业前景等。3. **推荐逻辑**:根据用户的分数和专业偏好,结合历史录取数据,使用简单的算法来推荐可能录取的高校和专业。

coder_wwwdy的博客 1976

【RabbitMq04】延迟队列

一、延迟队列理解 1、延迟队列概念 延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列,就是死信队列中,TTL消息过期的一种 举例 如死信队列文章中所讲,消费者1启动后,在rabbitmq控制台生成正常队列和死信队列后就又关闭了,然后开启生产者给消费者1发送消息,因为消费者1中设置了TTL消息过期机制,所以等了10秒种消息就自动进入到死信队列了,消息被消费者2接

weixin_40964170的博客 2776

Matplotlib之bar3d画3D柱状图

3D柱状图通常用于展示数据集中不同分类项的数据大小或数量。与普通的柱状图相比,3D柱状图更适合展示数据的三个维度 3D 柱状图 按行/列涂颜色 柱加阴影、描黑边 自定义座标轴名、刻度标签、范围

我走的每一步都算数 1120

专为AI打造的浏览器:内存占用仅为Chrome的1/9、比Chrome快11倍(Docker部署教程,支持飞牛nas等服务器部署)

🚀 专为AI打造的无头浏览器来了! 用Zig从零构建,内存仅Chrome的1/9,速度快11倍,原生CDP协议支持Docker部署,适合爬虫、自动化测试和AI代理应用。✨

XiaoqiangClub的博客 730

RabbitMQ-6-队列

死信队列 概念 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理 解,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息 进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有 后续的处理,就变成了死信,有死信自然就有了死信队列。 应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息 消费发生异常时,将消息投入死

qq_44633875的博客 554

在 SAP BTP ABAP 环境中构建多租户应用:从架构到实战

ABAP多租户应用架构解析 本文详细介绍了SAP BTP中ABAP环境的多租户应用架构,重点阐述了其核心组件及协作机制。在云原生SaaS模式下,多租户架构使多个客户能共享同一套ABAP平台,同时保持数据和配置隔离。架构包含三层:平台与子账户层、多租户应用与平台服务层(含Approuter、ABAP Solution service、XSUAA等核心组件)、ABAP系统与租户层。文章深入分析了各组件功能,包括Approuter的路由机制、ABAP Solution service的自动资源调度、XSUAA的安

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 214

RabbitMQ 实现延迟队列的两种方式

文章目录1. 用插件1.1 安装插件1.2 消息收发2. DLX 实现延迟队列2.1 延迟队列实现思路2.2 案例3. 小结 定时任务各种各样,常见的定时任务例如日志备份,我们可能在每天凌晨 3 点去备份,这种固定时间的定时任务我们一般采用 cron 表达式就能轻松的实现,还有一些比较特殊的定时任务,向大家看电影中的定时炸弹,3分钟后爆炸,这种定时任务就不太好用 cron 去描述,因为开始时间不确定,我们开发中有的时候也会遇到类似的需求,例如: 在电商项目中,当我们下单之后,一般需要 20 分钟之内或者

江南一点雨的专栏 1万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

RabbitMQ实现延迟队列

死信交换机、延迟队列插件① 声明死信交换机并编写监听方法② 声明延迟队列和对应的交换机,在声明队列时配置ttl属性③ 发送消息时,设置超时时间(实际上延迟队列的ttl和消息的超时时间至少有一个设置了就行)① 声明一个交换机,设置 delayed属性为true② 发送消息时,添加 x-delay头,值为超时时间。

后端 2027

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

rabbitMQ实现延迟队列

自定义的交换机是一种新的交换类型(CustomExchange),这种类型消息支持延迟投递机制消息传递之后不会立即投递到目标队列当中,而是存储在mnesia(一个分布式数据系统)表当中,当到达投递时间之后,才会投递到目标队列当中。//声明目标队列//声明基于插件实现的交换机}*///基于插件实现的交换机,必须是CustomExchange类型,标识这是一个延时类型的交换机/*

2301_78149288的博客 2362

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【RabbitMQ | 第四篇】基于RabbitMQ实现延迟队列

RabbitMQ系列第四篇介绍了延迟队列的定义(存储延迟消息的队列)、两种实现延迟队列的方法(基于DLX、以及基于插件),重点为基于DLX和TTL方法,核心思路为为普通消息队列根据binding key绑定指定的死信交换机,再为死信交换机绑定一个死信队列,以及使用消费者监听死信队列;最后消息发送者发送消息即可

踢桃的成长之路 3297

RabbitMQ如何实现延迟队列

rabbitmq实现延迟队列的方法

weixin_44273388的博客 9069

rabbitmq 实现延迟队列的两种方式

转载请注明出处 ps: 文章里面延迟队列=延时队列 什么是延迟队列 延迟队列存储的对象肯定是对应的延时消息,所谓”延时消息”是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费。 场景一:在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行一场处理。这是就可以使用延时队列将订单信

u014308482的博客 7万+

Rabbitmq实现延迟队列

在RabbitMQ中实现延迟队列(延时队列)可以有几种方案,其中常用的是通过死信队列(Dead Letter Queue,DLX)和rabbitmq_delayed_message_exchange插件来实现。以下是这两种方案的介绍以及注意事项。

qq_37638125的博客 966

rabbitmq实现延迟队列

rabbitmq实现延迟队列 延迟队列串存储的对象是对应的延迟消息。rabbitmq本身没有支持延迟队列的功能,通过DLX(死信队列)+TTL消息模拟延迟队列 延迟消息是指消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到消息并消费 延迟队列场景 订单系统中,如果用户下单30分钟内没有进行支付,就需要自动将这些订单设置为失效 支付结果通知,为1分钟,5分钟,10分...

面朝大海,春暖花开 991

如何用RabbitMQ实现延迟队列

TTL+死信队列和延迟队列插件两种方案

zwx900102的博客 1750

rabbitMq实现延迟队列

4 具体的实现rabbitmq本身是没有延迟发送的功能,但是我们通过消息的TTL(Time To Live)来实现,所谓TTL就是指消息的存活时间,RabbitMQ可以对队列和消息分别设置TTL。对队列设置就是队列没有消费者连着的保留时间,也可以对每一个单独的消息做单独的设置。超过了这个时间,我们认为这个消息就死了,称之为。如果队列设置了,消息也设置了,那么会取小的。所以一个消息如果被路由到不同的队列中,这个消息死亡的时间有可能不一样(不同的队列设置)。

2501_90223162的博客 1009

Hyperf框架实现Rabbitmq延迟队列

Hyperf框架实现Rabbitmq延迟队列 Hyperf框架官方支持了Amqp,但是只是具备了基础发消息和接受消息。对于我们经常使用的延迟队列却不支持,这让人感到痛苦。 设计延迟队列 由于Rabbitmq默认没有支持延迟队列,需要使用官方的TTL和死信队列来实现我们的延迟队列功能. 实现原理: 1、rabbitmq 可以针对 Queue和Message 设置 x-message-ttl 来控制消息的生存时间,如果超时,消息变为 dead letter 2、rabbitmq 的queue 可以配置

Zsd 5024

RabbitMQ实现延迟队列的两种方式

使用RabbitMQ实现延迟队列的两种方式 TTL + DLX 使用延迟插件 Linux安装RabbitMQ 首先创建用于连接RabbitMQ的Connection package com.dfyang.rabbitmq; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; ...

dh554112075的博客 1万+

基于RabbitMQ实现延迟队列

延迟队列是一种用来存放需要在指定时间之后或之前被处理的元素的队列。队列中的每个元素都指定了一个延迟时间,该时间表示元素应该在何时被取出并处理。在延迟时间到达之前,元素会保持在队列中,不会被消费者立即消费。

屹奕的博客 1500
上一篇: 多环境配置redission
下一篇: Feign动态设置header
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值