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

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

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

3.1 实现原理分析

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

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

3.2 优缺点分析

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

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

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

课后思考

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

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

说说RabbitMQ延迟队列实现原理?的更多相关文章

  1. RabbitMQ延迟队列

    rabbitmq延迟队列 rabbitmq实现延迟队列用了rabbitmq-delayed-message-exchange插件,需要提前安装,并启用. 原理 其原理是通过Exchange来实现延迟功 ...

  2. C# RabbitMQ延迟队列功能实战项目演练

    一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...

  3. RabbitMQ延迟队列插件安装

    RabbitMQ延迟队列插件安装 一.下载插件 下载地址:https://www.rabbitmq.com/community-plugins.html 二.把下载的插件放到指定位置 下载的文件为zi ...

  4. C#实现rabbitmq 延迟队列功能

    最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...

  5. Spring Boot(十四)RabbitMQ延迟队列

    一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...

  6. rabbitmq延迟队列demo

    1. demo详解 1.1 工程结构: 1.2 pom 定义jar包依赖的版本.版本很重要,rabbit依赖spring,两者必须相一致,否则报错: <properties> <sp ...

  7. Spring RabbitMQ 延迟队列

    一.说明 在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制. RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-excha ...

  8. RabbitMQ 延迟队列,消息延迟推送

    目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...

  9. Spring Boot (26) RabbitMQ延迟队列

    延迟消息就是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 延迟队列 订单业务: 在电商/点餐中,都有下单后30分钟内没有付款,就自动取消订单. 短 ...

  10. RabbitMQ 延迟队列实现订单支付结果异步阶梯性通知

    在第三方支付中,例如支付宝.或者微信,对于订单请求,第三方支付系统采用的是消息同步返回.异步通知+主动补偿查询的补偿机制. 由于互联网通信的不可靠性,例如双方网络.服务器.应用等因素的影响,不管是同步 ...

随机推荐

  1. 因为我的一次疏忽而带来的golang1.23新特性

    距离golang 1.23发布还有两个月不到,按照惯例很快要进入1.23的功能冻结期了.在冻结期间不会再添加新功能,已经添加的功能不出大的意外一般也不会被移除.这正好可以让我们提前尝鲜这些即将到来的新 ...

  2. 初识上位机(下):C#读写PLC数据块数据

    大家好,我是Edison. 作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去.这里我用两篇小文带你快速进入上位机开发领域.后续,我会考虑再出一个系列文章一起玩工控上位机. 上一篇 ...

  3. 智能勘探 | AIRIOT智慧油田管理解决方案

      石油勘探和开采地处偏远地区,涉及面广且生产规模大.特殊的作业环境下,使得工作人员作业条件艰苦,仅靠人工值守难度很大,不可避免的遇到一系列硬核挑战: 1.设备维护难度较高: 2.采油厂分布地域广.分 ...

  4. grafana模板参考

    空的,把面板都删除了 { "__inputs": [ { "name": "DS_PROMETHEUS", "label" ...

  5. ClipBord 复制 Html winform

    剪贴板针对不同的数据格式,在组织剪贴板内容时,有不同的格式要求.最简单的是,复制一般的.txt文本内容.使用方法 ClipBord.Clear(); ClipBord.SetText(str); 复制 ...

  6. 代码界的超级英雄:GitHub的奇幻冒险之旅

    GitHub简介 GitHub是一个用于代码托管.版本控制和协作开发的平台.它于2008年2月8日由Chris Wanstrath.PJ Hyett和Tom Preston-Werner创立,目前由微 ...

  7. 关于Zotero组件在office word中的添加

    引言:学姐问我,怎么弄Zotero,在调试过程中遇到的问题及解决方案 Q&A Zotero的安装 找到官网(https://www.zotero.org/)点击download,安装(个人觉得 ...

  8. Windows库链接报错

    问题回溯 今天拿到别人已经编译好的库,发现在链接的时候出现了报错 [9/9 12.7/sec] Linking CXX shared module bin\plugins\AsensingPlugin ...

  9. itest(爱测试)开源接口测试&敏捷测试&极简项目管理 6.6.6 发布,新增接口mock

    (一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock 6合1,又有丰富的统计分析.可按测试包 ...

  10. GeoGebra作圆的切线

    参考文档:<GeoGebra入门教程>唐家军 1. 目的 使用GeoGebra作出过一点的圆的切线. 2. 构造过程 文档种的描述如下: 按照上述构造过程,在输入条形框中依次输入上面的指令 ...