大聪明教你学Java | 深入浅出聊 RabbitMQ 中的死信队列和延迟队列

2024-01-28 09:20

本文主要是介绍大聪明教你学Java | 深入浅出聊 RabbitMQ 中的死信队列和延迟队列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。
🍊支持作者: 点赞👍、关注💖、留言💌~

今天大明白在用 RabbitMQ 的时候又被难住了 👇

大明白:兄弟,RabbitMQ 你用过不?😥
大聪明:那必须用过啊,你这是又被什么问题给难住了 🤔
大明白:我用 RabbitMQ 的时候就是发个消息到消费者就结束了,今天才知道还有死信队列和延迟队列呢,这都是啥玩意啊😭
大聪明:哈哈哈哈哈哈哈哈,小问题,不要慌~ 正好今天没啥事,听我给你娓娓道来…

RabbitMQ 中的死信队列

在了解死信队列之前,我们先来看看什么是死信👇

死信,顾名思义就是无法被消费的消息。一般来说,生产者将消息投递到某个节点或者直接投递到某个队列里,消费者从队列中取出消息进行消费,但有时候由于特定的原因导致队列中的某些消息无法被消费,这些无法被消费的消息如果没有后续的处理,那么就变成了死信,有死信自然就有了死信队列,即 DLX(Dead Letter Exchanges )。

在死信的概念中,我们可以看到这么一个关键词“特定的原因”,我们再一起看看这个特定的原因具体指得的什么:

  • 消息 TTL (Time to live的简称,即过期时间)过期
  • 队列达到最大长度(队列满了,无法再将新消息添加数据到队列中)
  • 消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false

我们可以参考下面的流程图来理解消息被投递到死信队列的过程 👇
在这里插入图片描述

其实死信队列并没有什么独特的地方,它不过是绑定在死信交换机上的普通队列,而死信交换机也只是一个普通的交换机,不过是用来专门处理死信的交换机。死信消息的生命周期也并不复杂:

  1. 业务消息被投入业务队列
  2. 消费者正常消费业务队列的消息,但是由于处理过程中发生异常,于是进行了 basic.reject 或 basic.nack 操作
  3. 被 basic.reject 或 basic.nack 的消息由 RabbitMQ 投递到死信交换机中
  4. 死信交换机将消息投入相应的死信队列
  5. 死信队列的消费者消费死信消息

我们了解了死信队列的基本概念,可能有些小伙伴就会产生疑问了:既然死信队列中的消息都是死信,那它有什么用呢?成了死信直接删掉不就行了吗🤨

其实死信消息是 RabbitMQ 为我们做的一层保证。当然了,我们也可以不使用死信队列,而是在消息消费异常时,将消息主动投递到另一个交换机中。比如从死信队列拉取消息,然后发送邮件、短信等方式来通知开发人员关注;或者将消息重新投递到一个队列然后设置过期时间,来进行延时消费。一般用在较为重要的业务队列中,确保未被正确消费的消息不被丢弃,一般发生消费异常可能的原因主要由于消息信息本身存在错误导致处理异常,处理过程中参数校验异常,或者因网络波动导致的查询异常等等。当发生异常时,当然不能每次通过日志来获取原消息,然后让运维帮忙重新投递消息。此时就可以通过配置死信队列的方式来解决这个问题,我们可以让未正确处理的消息暂存到另一个队列中,待后续排查清楚问题后,编写相应的处理代码来处理死信消息。这样的处理方式是不是就比手工投递消息要好太多了😉

RabbitMQ 中的延迟队列

延迟队列存储的对象是对应的延迟消息。所谓“延迟消息” 是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。在 RabbitMQ 中并没有直接给我们提供延迟队列的功能,我们可以通过 “过期时间 + 死信队列” 的方式来实现延迟队列。如下图所示:

在这里插入图片描述
延迟队列的应用场景就非常多了,比如:

  • 用户在商城下单,此时库存减一;若30分钟未支付,则取消该订单,将商品库存加一(即订单30分钟未支付,系统自动超时关闭)
  • 账单 24 小时未确认,就发送提醒消息

在这里我们可以延伸出来一个问题:我们在实现订单30分钟未支付,系统自动超时关闭的时候,为什么选择延迟队列呢?有没有其他的实现方案呢?👇

答案是肯定的,一定是存在其他实现方案的,下面我们就对这些方案做一个对比:

🍊 方案一:基于任务调度实现(也就是利用定时任务轮询数据库实现)。估计没人会选择这种实现方式,它的弊端太明显了,效率非常低,也非常消耗服务器性能。

🍊 方案二:…

🍊 方案三:…

嘿嘿,这里我先卖个关子,欲知后事如何,且听下回分解👋

小结

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●’◡’●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

你在被打击时,记起你的珍贵,抵抗恶意;
你在迷茫时,坚信你的珍贵,抛开蜚语;
爱你所爱 行你所行 听从你心 无问东西

这篇关于大聪明教你学Java | 深入浅出聊 RabbitMQ 中的死信队列和延迟队列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/653189

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("