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

使用 RabbitMQ 和 RocketMQ 的人是幸运的,因为这两个 MQ 自身提供了延迟队列的实现,不像用 Kafka 的同学那么苦逼,还要自己实现延迟队列。当然,这都是题外话,今天咱们重点来聊聊 RabbitMQ 延迟队列的实现原理,以及 RabbitMQ 实现延迟队列的优缺点有哪些?
很多人知道使用 RabbitMQ 是可以实现延迟队列的,但对于 RocketMQ 自身也提供了延迟队列这件事却持有不同态度,这是因为网上有些资料说 RocketMQ 和 Kafka 没有内置延迟队列。其实这种说法是因为,RocketMQ 在早期版本中确实没有内置延迟队列,但在 4.x 就内置了 18 个级别的延迟队列了(最长支持 2 小时的延迟队列),5.x 就支持随机延迟时间的延迟队列了,所以这里需要特殊强调一下。
1.什么是延迟队列?
延迟队列(Delay Queue)是一种特殊类型的队列,它的主要特点是可以让进入队列的元素在指定的延迟时间之后才被取出进行处理。
延迟队列的主要使用场景有以下这些:
- 订单超时处理:在电商系统中,如果用户下单后未在一定时间内支付,订单可能会被自动取消。可以将订单放入延迟队列,在设定的延迟时间(如 30 分钟)后取出处理取消操作。
- 任务重试:当某个任务执行失败时,将其放入延迟队列,等待一段时间(如 5 分钟)后重新执行。
- 消息延迟发送:某些消息不需要立即发送,而是在指定的延迟时间后发送,例如定时提醒消息。
- 缓存过期处理:缓存中的数据可能有一定的有效期,将即将过期的数据放入延迟队列,到期后进行删除或更新操作。
2.延迟任务实现方法
那么延迟队列的实现方式有哪些呢?
延迟队列的实现方式通常有以下几种:
- 基于 JDK 提供的 DelayQueue 来实现:它是内存级别的延迟队列,重启应用之后消息会丢失,并且只支持单机版延迟队列,所以一般不用。
- 基于 MQ 的延迟队列:例如使用 RabbitMQ 来实现延迟队列,他们适合处理动态和临时延迟任务,不像定时任务一样,适合处理正式的、固定的延迟任务。
- 基于定时任务组件实现延迟任务:例如 XXLJob 或 Quartz 等框架来实现延迟任务,他们适合处理固定(执行)频率的延迟任务。
我们通常会使用延迟队列来存储(和实现)延迟消息,所以大部分时候,我们说的延迟队列和延迟消息其实是一回事。
3.使用RabbitMQ实现延迟队列
使用 RabbitMQ 实现延迟队列有以下两种实现方式:
- 通过死信队列实现延迟任务:将正常的消息放到没有消息订阅者的消息队列(消息自然就会过期),等消息过期之后会进入死信队列,通过订阅死信队列消费消息,从而实现延迟队列,如下图所示:

- 通过官方提供的延迟插件实现延迟功能。
早期大部分公司都会采用第一种方式,而随着 RabbitMQ 3.5.7(2015 年底发布)的延迟插件的发布,因为其使用更简单、更方便,所以它现在才是大家普通会采用的,实现延迟队列的方式。
3.1 实现原理分析
使用延迟插件的实现原理是通过创建一个延迟交换机(Delay Exchange),延迟消息首先会把消息投递到延迟交换机,并不是直接将消息投递业务队列(所以不会立即执行),由延迟交换机控制消息在延迟一段时间后,再将消息投递到真正的队列中进行消费,从而实现延迟队列,它的实现流程如下图所示:

其中 Mnesia 可以理解为基于文件存储的数据库。
3.2 优缺点分析
使用死信队列实现延迟任务有个缺点,它不能实现随机延迟任务,每个无消费者的队列上只能设置一个 ttl(消息过期时间),所以只能实现固定过期时间的延迟任务。
使用延迟插件实现延迟任务有以下两个缺点:
- 消息丢失问题:消息在真的被投递到目标消息队列之前,是存放在接收到了这个消息的服务端本地的 Mnesia 里面。也就是说,如果这个时候还没有刷新磁盘,那么消息就会丢失;如果这个节点不可用了,那么消息也同样会丢失。
- 高并发问题:这种实现方式不支持高并发场景,因为它只有一个延迟交换机,当高并发或数据量比较大时执行效率就会比较低。
课后思考
如何解决 RabbitMQ 延迟插件造成的这两个问题?如何实现 Kafka 的延迟队列?
本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。
说说RabbitMQ延迟队列实现原理?的更多相关文章
- RabbitMQ延迟队列
rabbitmq延迟队列 rabbitmq实现延迟队列用了rabbitmq-delayed-message-exchange插件,需要提前安装,并启用. 原理 其原理是通过Exchange来实现延迟功 ...
- C# RabbitMQ延迟队列功能实战项目演练
一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...
- RabbitMQ延迟队列插件安装
RabbitMQ延迟队列插件安装 一.下载插件 下载地址:https://www.rabbitmq.com/community-plugins.html 二.把下载的插件放到指定位置 下载的文件为zi ...
- C#实现rabbitmq 延迟队列功能
最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...
- Spring Boot(十四)RabbitMQ延迟队列
一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...
- rabbitmq延迟队列demo
1. demo详解 1.1 工程结构: 1.2 pom 定义jar包依赖的版本.版本很重要,rabbit依赖spring,两者必须相一致,否则报错: <properties> <sp ...
- Spring RabbitMQ 延迟队列
一.说明 在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制. RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-excha ...
- RabbitMQ 延迟队列,消息延迟推送
目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...
- Spring Boot (26) RabbitMQ延迟队列
延迟消息就是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 延迟队列 订单业务: 在电商/点餐中,都有下单后30分钟内没有付款,就自动取消订单. 短 ...
- RabbitMQ 延迟队列实现订单支付结果异步阶梯性通知
在第三方支付中,例如支付宝.或者微信,对于订单请求,第三方支付系统采用的是消息同步返回.异步通知+主动补偿查询的补偿机制. 由于互联网通信的不可靠性,例如双方网络.服务器.应用等因素的影响,不管是同步 ...
随机推荐
- 智能便捷_AIRIOT智慧充电桩管理解决方案
现如今随着对可持续交通的需求不断增加,电动车市场正在迅速扩大,建设更多更智能的充电桩,并通过管理平台提高充电设施的可用性和效率成为一项重要任务.传统的充电桩管理平台在对充电设施进行管理过程中,存在如下 ...
- mysql 命令行安装方式
一:下载 先到 mysql 官方网站下载:https://dev.mysql.com/downloads/mysql/ 点击直接下载: 解压到目录:D:\mysql-8.0.19-winx64 如图 ...
- 提速15%,PaddleOCRSharp新版v4.3发布
PaddleOCRSharp v4.3版本,已经于5月23日发布.该版本的发布,在不影响识别精度的同时,带来了10%~15%速度的提升. 项目地址:https://gitee.com/raoyutia ...
- 修改linux默认启动界面——从命令行模式转换为图形化模式
从命令行模式转换为图形化模式 首先需要安装对应的图形化安装包 yum groupinstall "GNOME Desktop" "Graphical Administra ...
- ETL工具-nifi干货系列 第十四讲 nifi处理器QueryDatabaseTableRecord查询表数据实战教程
1.处理器QueryDatabaseTableRecord和处理器QueryDatabaseTable比较相似,该组件生成一个 SQL 查询,或者使用用户提供的语句,并执行它以获取所有在指定的最大值列 ...
- #define 用法解法
宏的优点是能整理代码 缺点是宏替换来的代码需要人工解除宏后才能暴漏源代码 改底层时候是需要解一解的 它可以做到main函数中只有一个宏字母 这个宏定义时候,定义成了几个函数的源代码 所以main里面就 ...
- Ton 区块链的官方 类ERC20-Token 智能合约代码-Transfer部分解析
作者:林冠宏 / 指尖下的幽灵.转载者,请: 务必标明出处. 掘金:https://juejin.im/user/1785262612681997 GitHub : https://github.co ...
- vite+vue3+ts+elementPlus前端框架搭建 [三] router路由管理
路由包括动态路由.静态路由两种,本文中以静态路由的方式实现了动态路由. 1. 创建Router 在Src目录下创建router文件夹,并在router文件夹下创建index.ts文件. index.t ...
- MoneyPrinterPlus:AI自动短视频生成工具,详细使用教程
MoneyPrinterPlus是一款使用AI大模型技术,一键批量生成各类短视频,自动批量混剪短视频,自动把视频发布到抖音,快手,小红书,视频号上的轻松赚钱工具. 之前有出过一期基本的介绍,但是后台收 ...
- 使用GET方法访问网站
使用GET方法访问网站 服务器接收get参数 server.py import flask app = flask.Flask(__name__) @app.route('/') def index( ...