首页 > 其他分享 >说说RabbitMQ延迟队列实现原理?

说说RabbitMQ延迟队列实现原理?

时间:2024-07-16 18:41:42浏览次数:15  
标签:队列 RabbitMQ 实现 任务 消息 延迟

使用 RabbitMQ 和 RocketMQ 的人是幸运的,因为这两个 MQ 自身提供了延迟队列的实现,不像用 Kafka 的同学那么苦逼,还要自己实现延迟队列。当然,这都是题外话,今天咱们重点来聊聊 RabbitMQ 延迟队列的实现原理,以及 RabbitMQ 实现延迟队列的优缺点有哪些?

很多人知道使用 RabbitMQ 是可以实现延迟队列的,但对于 RocketMQ 自身也提供了延迟队列这件事却持有不同态度,这是因为网上有些资料说 RocketMQ 和 Kafka 没有内置延迟队列。其实这种说法是因为,RocketMQ 在早期版本中确实没有内置延迟队列,但在 4.x 就内置了 18 个级别的延迟队列了(最长支持 2 小时的延迟队列),5.x 就支持随机延迟时间的延迟队列了,所以这里需要特殊强调一下。

1.什么是延迟队列?

延迟队列(Delay Queue)是一种特殊类型的队列,它的主要特点是可以让进入队列的元素在指定的延迟时间之后才被取出进行处理。

延迟队列的主要使用场景有以下这些:

  1. 订单超时处理:在电商系统中,如果用户下单后未在一定时间内支付,订单可能会被自动取消。可以将订单放入延迟队列,在设定的延迟时间(如 30 分钟)后取出处理取消操作。
  2. 任务重试:当某个任务执行失败时,将其放入延迟队列,等待一段时间(如 5 分钟)后重新执行。
  3. 消息延迟发送:某些消息不需要立即发送,而是在指定的延迟时间后发送,例如定时提醒消息。
  4. 缓存过期处理:缓存中的数据可能有一定的有效期,将即将过期的数据放入延迟队列,到期后进行删除或更新操作。

2.延迟任务实现方法

那么延迟队列的实现方式有哪些呢?

延迟队列的实现方式通常有以下几种:

  1. 基于 JDK 提供的 DelayQueue 来实现:它是内存级别的延迟队列,重启应用之后消息会丢失,并且只支持单机版延迟队列,所以一般不用。
  2. 基于 MQ 的延迟队列:例如使用 RabbitMQ 来实现延迟队列,他们适合处理动态和临时延迟任务,不像定时任务一样,适合处理正式的、固定的延迟任务。
  3. 基于定时任务组件实现延迟任务:例如 XXLJob 或 Quartz 等框架来实现延迟任务,他们适合处理固定(执行)频率的延迟任务。

我们通常会使用延迟队列来存储(和实现)延迟消息,所以大部分时候,我们说的延迟队列和延迟消息其实是一回事。

3.使用RabbitMQ实现延迟队列

使用 RabbitMQ 实现延迟队列有以下两种实现方式:

  1. 通过死信队列实现延迟任务:将正常的消息放到没有消息订阅者的消息队列(消息自然就会过期),等消息过期之后会进入死信队列,通过订阅死信队列消费消息,从而实现延迟队列,如下图所示:

image.png

  1. 通过官方提供的延迟插件实现延迟功能

早期大部分公司都会采用第一种方式,而随着 RabbitMQ 3.5.7(2015 年底发布)的延迟插件的发布,因为其使用更简单、更方便,所以它现在才是大家普通会采用的,实现延迟队列的方式。

3.1 实现原理分析

使用延迟插件的实现原理是通过创建一个延迟交换机(Delay Exchange),延迟消息首先会把消息投递到延迟交换机,并不是直接将消息投递业务队列(所以不会立即执行),由延迟交换机控制消息在延迟一段时间后,再将消息投递到真正的队列中进行消费,从而实现延迟队列,它的实现流程如下图所示:
image.png

其中 Mnesia 可以理解为基于文件存储的数据库。

3.2 优缺点分析

使用死信队列实现延迟任务有个缺点,它不能实现随机延迟任务,每个无消费者的队列上只能设置一个 ttl(消息过期时间),所以只能实现固定过期时间的延迟任务。

使用延迟插件实现延迟任务有以下两个缺点:

  1. 消息丢失问题:消息在真的被投递到目标消息队列之前,是存放在接收到了这个消息的服务端本地的 Mnesia 里面。也就是说,如果这个时候还没有刷新磁盘,那么消息就会丢失;如果这个节点不可用了,那么消息也同样会丢失。
  2. 高并发问题:这种实现方式不支持高并发场景,因为它只有一个延迟交换机,当高并发或数据量比较大时执行效率就会比较低。

课后思考

如何解决 RabbitMQ 延迟插件造成的这两个问题?如何实现 Kafka 的延迟队列?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

标签:队列,RabbitMQ,实现,任务,消息,延迟
From: https://www.cnblogs.com/vipstone/p/18305883

相关文章

  • 队列
    队列创建宏定义:configSUPPORT_STATIC_ALLOCATION//静态创建QueueHandle_txQueueCreateStatic(UBaseType_tuxQueueLength,UBaseType_tuxItemSize,uint8_t*pucQueueStorageBuffer,StaticQueue_t*pxQueueBuffer);/*Thequeueistobecreatedtoholdamaxi......
  • 使用RocketMQ 实现基于标签过滤的消息队列生产和消费
    在分布式系统中,消息队列(MessageQueue,MQ)是一种常见的通信方式,它能够解耦系统组件,提供异步通信,提升系统的伸缩性和可靠性。ApacheRocketMQ是一款开源的分布式消息中间件,具有高性能、低延迟、高可靠性和高可用性等特点。本文将介绍如何使用ApacheRocketMQ实现基于标签过......
  • RabbitMQ复习
    消息中间件的作用:(1)异步处理(2)应用解耦(3)流量削峰消息中间件的缺点:引入了新的东西,也就增加了新的故障点。比如消息中间件挂了,影响系统的可用性。两种框架:JMS和AMQP最大的区别是JMS是是javaapi,对跨平台的支持较差,但在纯java技术栈内首选。AMQP是跨平台的,序列化方式选json,......
  • Day10(栈与队列) | 150. 逆波兰表达式求值 239. 滑动窗口最大值 347.前 K 个高频元
    150.逆波兰表达式求值给你一个字符串数组tokens,表示一个根据逆波兰表示法表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。注意:有效的算符为'+'、'-'、'*'和'/'。每个操作数(运算对象)都可以是一个整数或者另一个表达式。两个整数之间的除法总是......
  • 代码随想录算法训练营第六十六天 | Bellman_ford 队列优化算法(SPFA)、Bellman_ford之
    Bellman_ford队列优化算法(SPFA)题目链接:https://kamacoder.com/problempage.php?pid=1152文档讲解:https://programmercarl.com/kamacoder/0094.%E5%9F%8E%E5%B8%82%E9%97%B4%E8%B4%A7%E7%89%A9%E8%BF%90%E8%BE%93I-SPFA.html思路Bellman_ford算法每次松弛都是对所......
  • zookeeper+kafka消息队列群集部署
    目录消息队列1:什么是消息队列2:消息队列的特征3:为什么需要消息队列Kafka基础与入门1:kafka基本概念2:kafka角色术语3:kafka拓扑架构4:Topic和partition5:Producer生产机制6:Consumer消费机制zookeeper概念介绍1:zookeeper应用举例2:zookeeper的工作原理是什么?3:zookeeper......
  • RabbitMQ 安装并成功启动后,无法访问http://127.0.0.1:15672/#/
    1.问题描述&解决:安装了最新版RabbitMQ,然后先正常启动也无法访问,然后网上搜呀搜,什么重启服务,使用管理员打开cmd,或者是使用管理员运行下图的RabbitMQservice-start,最后又尝试了rabbitmq-pluginsenablerabbitmq_management这个命令,都无法在火狐浏览器打开http://127.0.0.1:1......
  • 延迟队列
     绑定队列编写监听器@RabbitListener(bindings=@QueueBinding(value=@Queue(MqConstants.Queue.LEARNING_RECORD_QUEUE),exchange=@Exchange(value=MqConstants.Exchange.LEARNING_DELAY_EXCHANGE,type=ExchangeTypes.TOPIC,delayed="true&quo......
  • 【数据结构】线性结构——数组、链表、栈和队列
    目录前言一、数组(Array)1.1优点1.2缺点1.3适用场景二、链表(LinkedList)2.1优点2.2缺点2.3适用场景三、栈(Stack)3.1优点3.2缺点3.3适用场景四、队列(Queue)4.1优点4.2缺点4.3适用场景......
  • 【JavaScript脚本宇宙】解密六大Node.js消息队列库:选对工具,事半功倍
    从Bull到NSQ:探索Node.js消息队列库的全貌前言在现代软件开发中,消息队列是一种常见的通信模式,用于实现异步任务处理、解耦系统组件、以及实现可靠的事件驱动架构。Node.js作为一个流行的后端开发平台,有许多优秀的消息队列库可以供开发者选择和使用。本文将介绍六个流行的No......