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

news/2024/12/27 0:13:55/文章来源:https://www.cnblogs.com/vipstone/p/18305883

使用 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、设计模式、消息队列等模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/744820.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在上传文件到 COS 时同步获取文件信息

本文将介绍如何在上传文件到 COS 时同步获取文件信息,如图片的宽高、格式等。目前,可以通过 COS 上传接口,如 PUT Object、CompleteMultipartUploads 等将文件存储至 COS 存储桶中,我们针对以下三种场景提供上传时同步获取文件信息的方式背景介绍 本文将介绍如何在上传文件…

【C++】cmath

1、头文件 #include <cmath>2、幂函数

SRAM CIM的后续发展之我见

SRAM CIM的后续发展之我见 目前CIM技术已经应用在诸多存储器上,如主流存储器SRAM,DRAM,Flash,以及新型NVM,如RRAM,PCM,FeRAM,MRAM等。其中SRAM CIM是一个进展较快的方向,主要受益于其工艺上的成熟性,与CMOS先进工艺的高度兼容,并且SRAM的高速度也是SRAM CIM性能上的…

springboot+vue前后端分离项目-项目搭建13-树形表

效果一、后端 1. 新建表category 2.新建entity,com/example/demo/entity/Category.java3.新建Mapper,com/example/demo/mapper/CategoryMapper.java 4.新建Controller,com/example/demo/controller/CategoryController.java 主要代码逻辑如下, 封装成List<Category>,…

阶跃星辰启动「繁星计划」开放平台;运动迁移框架 MotionClone 无需训练,一键克隆视频运动丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑的个人观点…

[GXYCTF2019]Ping Ping Ping

[GXYCTF2019]Ping Ping Ping (命令执行绕过总结) 题目来源 收录于:BUUCTF  GXYCTF2019 题目描述提示较为明确,get方法传参127.0.0.1后结果如下比较容易想到联合执行命令,先看有哪些文件尝试直接读取flag.php读取失败,对空格进行了过滤。 题解 以下内容参考文章:htt…

Xdown 多功能多线程并发下载工具

下载地址:https://www.mediafire.com/file/942px42bad7exdf/Xdown%25E4%25B8%258B%25E8%25BD%25BD%25E5%25B7%25A5%25E5%2585%25B7.zip/file Xdown是一款超级强大且免费无广告的Torrent(BT)/磁力链/Aria2/HTTP下载工具。Xdown不光如此还支持BT做种,使用 Xdown下载器让我们跟…

MariaDb安装及登录

一、安装 ​ 及客户端 sudo apt install mariadb-server mariadb-client -y二、链接、测试 mysql -u root -p show databases;三、设置安全策略 sudo mysql_secure_installation四、配置、开启其他客户端访问 ​ 1、配置其他访问:修改配置文件 sudo vi /etc/mysql/mariadb.con…

bundletool工具使用(Android aab包安装)

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣 apk再见了,Android全新App安装格式aabhttps://github.com/google/bundletool https://github.com/google/bundletool/releaseshttps://developer.android.com/studio/command-line/bundletool#generate_apksbundletool工…

「杂文」日常 10

20240716 其实大一下早就结束了,但是一直不知道怎么咋给这篇新博开头 直到刚才:于是就得到了一个唐完了的开头 希望这几天的 noi 不会有人把操作数用 char 读,🙏

【Python】pyppeteer简单使用

爬取百度搜索python的第一页标题import sys sys.path.append("/home/user/.local/lib/python3.9/site-packages") #将包的路径添加到环境变量 import asyncio from pyppeteer import launch from pyppeteer_stealth import stealth #反检测模块,隐藏浏览器特征 imp…