当前位置: 首页 > news >正文

RabbitMQ--延迟队列--使用/原理

原文网址:RabbitMQ--延迟队列--使用/原理_IT利刃出鞘的博客-CSDN博客

简介

        本文介绍RabbitMQ的延迟队列的用法。

        本内容也是Java后端面试中常见的问题。

概述

        延迟队列用来存放延迟消息。延迟消息:指当消息被发送以后,不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

        在AMQP协议中,或者RabbitMQ本身没有直接支持延迟队列的功能,但是有两种方案来实现:

  • 方案1:采用rabbitmq-delayed-message-exchange 插件实现。(RabbitMQ 3.6.x开始支持)
    • 推荐。原因:它解决了死信队列的消息投递问题:在第一条消息成为死信之前,后面的消息即使过期也不会投递为死信。
  • 方案2:通过前面所介绍的DLX和TTL模拟出延迟队列的功能。
    • 不推荐。原因:死信队列的设计目的是为了存储没有被正常消费的消息,便于排查和重新投递。死信队列没有对投递时间做出保证,在第一条消息成为死信之前,后面的消息即使过期也不会投递为死信。

        在图1-2中,不仅展示的是死信队列的用法,也是延迟队列的用法,对于queue.dlx这个死信队列来说,同样可以看作延迟队列。假设一个应用中需要将每条消息都设置为10秒的延迟,
生产者通过exchange.normal这个交换器将发送的消息存储在queue.normal这个队列中。消费者订阅的并非是queue.normal这个队列,而是queue.dlx这个队列。当消息从queue.normal这个队列中过期之后被存入queue.dlx这个队列中,消费者就恰巧消费到了延迟10秒的这条消息。

        在真实应用中,对于延迟队列可以根据延迟时间的长短分为多个等级,一般分为5秒、10秒、30秒、1分钟、5分钟、10分钟、30分钟、1小时这几个维度,当然也可以再细化一下。

        以下图(图2-1)为例进行说明。为简化,只设置5秒、10秒、30秒、1分钟这四个等级。根据需求的不同,生产者发送消息的时候通过设置不同的路由键,将消息发送到与交换器绑定的不同的队列中。这里队列也分别配置了DLX和相应的死信队列,当相应的消息过期时,就会转存到相应的死信队列(即延迟队列)中,这样消费者根据业务自身的情况,分别选择不同延迟等级的延迟队列进行消费。

图2-1

使用场景

延迟队列的使用场景有很多,比如:

  • 用户下订单场景:用户下单后有30分钟的时间支付,若30分钟内没有支付,则将这个订单取消。
    • 方案:用户下单后将取消订单的消息发送到延迟队列,延迟时间设置为30分钟。取消订单这个消息的订阅者程序在30分钟后收到消息,判断该订单的状态是否为已支付,若还没支付,则将该订单状态设置为:已取消。
  • 定时遥控场景:用户想用手机远程遥控家里的智能设备在指定的时间工作。
    • 方案:假设用户想要的操作是:开启热水器。首先,将开启热水器这个消息发送到延迟队列,延迟时间设置到用户想要的时间到现在时间的差值。开启热水器这个消息的订阅者程序在指定时间收到消息,再将指令推送到智能设备。

        需要注意的是,延迟队列的消息是不能取消的,解决方案是:在消费消息的时候判断这个消息对应的业务的当前状态。例如:对于取消订单来说,收到消息时,读取这个消息所对应的数据库信息,如果已经是已付款状态了,就不进行任何操作了,如果是未支付状态,则改为已取消。

其他网址

《RabbitMQ实战指南》=> 4.4 延迟队列

相关文章:

  • Linux基础 - Web服务基础
  • 高新技术企业认定八大条件、八大领域、四项指标
  • 异常练习题(Java)
  • 那些惊艳一时的 CSS 属性
  • ipv6地址概述——深入讲解ipv6地址
  • 这才是Git的正确学习方式
  • Linux 命令(204)—— ss 命令
  • 第十四届蓝桥杯模拟赛 第二期题解
  • [激光原理与应用-29]:典型激光器 -1- 固体激光器
  • Redis常见问题
  • 【毕业设计】1-基于单片机的城市轨道交通列车超速防护系统_里程表设计(原理图+PCB+源码+仿真工程+答辩论文)
  • 【数据结构】堆和优先级队列
  • 关于如何找环形链表的入环点
  • 下班路上捡了一部手机,我用8年开发知识主动找到了失主
  • 【Linux系统】第三篇:Linux中软件包管理器yum的使用
  • 深入了解以太坊
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • Gradle 5.0 正式版发布
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • PAT A1120
  • SQL 难点解决:记录的引用
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 机器学习中为什么要做归一化normalization
  • 解析 Webpack中import、require、按需加载的执行过程
  • 前端性能优化--懒加载和预加载
  • 深度学习在携程攻略社区的应用
  • # 安徽锐锋科技IDMS系统简介
  • #Z2294. 打印树的直径
  • (14)Hive调优——合并小文件
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)用.Net的File控件上传文件的解决方案
  • (转)重识new
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • ..回顾17,展望18
  • .“空心村”成因分析及解决对策122344
  • .Net core 6.0 升8.0
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net framework 4.0中如何 输出 form 的name属性。
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET 发展历程
  • .NET开源项目介绍及资源推荐:数据持久层
  • @vue/cli 3.x+引入jQuery
  • [Android]一个简单使用Handler做Timer的例子
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [Angular 基础] - 数据绑定(databinding)
  • [bzoj1038][ZJOI2008]瞭望塔
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [CERC2017]Cumulative Code
  • [EULAR文摘] 脊柱放射学持续进展是否显著影响关节功能
  • [flask]http请求//获取请求体数据