大聪明教你学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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听