RabbitMQ 高级特性——TTL

在这里插入图片描述

文章目录

  • 前言
  • TTL
    • 设置消息的 TTL
    • 设置队列的 TTL

前言

对于前面讲到的重试机制中,当确认策略为 MANUAL 手动确认的时候,如果消费者出现了程序逻辑错误,那么消息就无法被争取处理,那么就会执行 basicNack 方法,如果我们的 basicNack 方法的第三个参数的值为 true 的话,在只有这一个消费者的情况下,这个消息就会反复重新进入队列并且返回投递给这个消费者,那么在这个队列中的后面的消息就无法被提递给消费者,这样就导致了消息积压,那么如何处理这个问题呢?答案就是为消息或者队列设置 TTL(ime-To-Live)生存时间,当消息或者队列存在一段时间后就会被丢弃或者投递到死信队列中。那么这篇文章将介绍 RabbitMQ 中的 TTL。

TTL

TTL(Time-to-Live)过期时间,RabibtMQ 可以对队列和消息设置 TTL。当消息到达存活时间之后,如果该消息还没有被消费,那么就会被自动处理掉。

就是我们平时购物的时候,如果下单超过 24 消失还没有付款的话,订单就会被自动取消。

设置消息的 TTL

RabbitMQ 有两种设置 TTL 的方法,一是设置队列的 TTL,队列中的所有消息都有相同的过期时间,而就是对消息单独设置 TTL,每条消息的 TTL 可以不同。如果两种方式一起使用,则过期时间为两者的较小值。

先来看看如何对消息设置 TTL。

public static final String TTL_EXCHANGE = "ttl.exchange";
public static final String TTL_QUEUE = "ttl.queue";
@Bean("ttlExchange")
public DirectExchange ttlExchange() {return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).durable(true).build();
}@Bean("ttlQueue")
public Queue ttlQueue() {return QueueBuilder.durable(Constants.TTL_QUEUE).build();
}@Bean("ttlBinding")
public Binding ttlBinding(@Qualifier("ttlQueue") Queue queue,@Qualifier("ttlExchange") DirectExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("ttl");
}
@RequestMapping("/ttl")
public String ttl() {//设置消息的过期时间MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setExpiration("10000");return message;}};rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","rabbitmq ttl",messagePostProcessor);return "消息发送成功";
}

这里消费者的代码我们就不写了,就通过 RabbitMQ 的管理页面观察消息的过期:

在这里插入图片描述

启动之后,并且让生产者生产消息,可以发现队列中已经存在一条消息了,然后等待一段时间再观察会发现刚刚生产的消息已经不存在了:

在这里插入图片描述
这是设置消息的过期时间,那么下面我们来看看如何设置队列的时间。

设置队列的 TTL

设置队列的 TTL 是在我们声明队列的时候设置的,声明队列的时候加入 x-message-ttl 参数实现的,单位是毫秒。

//队列设置TTL的第一种方法
@Bean("ttlQueue")
public Queue ttlQueue() {return QueueBuilder.durable(Constants.TTL_QUEUE).ttl(20*1000).build();
}//队列设置TTL的第二种方法
@Bean("ttlQueue")
public Queue ttlQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-message-ttl",20000);return QueueBuilder.durable(Constants.TTL_QUEUE).withArguments(arguments).build();
}//也可以将map平铺出来
@Bean("ttlQueue")
public Queue ttlQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-message-ttl",20000);return QueueBuilder.durable(Constants.TTL_QUEUE).withArgument("x-message-ttl",20000).build();
}

这里创建两个队列,一个是设置了 TTL 的队列,一个是没有设置 TTL 的对了,然后看两个队列的差别:

@Bean("ttlExchange")
public DirectExchange ttlExchange() {return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).durable(true).build();
}@Bean("ttlQueue")
public Queue ttlQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-message-ttl",20000);return QueueBuilder.durable(Constants.TTL_QUEUE).withArgument("x-message-ttl",20000).build();
}@Bean("normalQueue")
public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).build();
}@Bean("ttlBinding")
public Binding ttlBinding(@Qualifier("ttlQueue") Queue queue,@Qualifier("ttlExchange") DirectExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("ttl");
}@Bean("ttlBinding2")
public Binding ttlBinding2(@Qualifier("normalQueue") Queue queue,@Qualifier("ttlExchange") DirectExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("ttl");
}

在这里插入图片描述
在这里插入图片描述

过一段时间之后再观察:

在这里插入图片描述

设置队列的过期时间和设置消息的过期时间的区别

设置队列TTL属性的方法,一旦消息过期,就会从队列中删除。

设置消息TTL的方法,即使消息过期,也不会马上从队列中删除,而是在即将投递到消费者之前进行判定的。

为什么这两种方法处理的方式不一样?

因为设置队列过期时间,队列中已过期的消息肯定在队列头部(假设是按照时间顺序入队的),RabbitMQ只要定期从队头开始扫描是否有过期的消息即可。

而设置消息TTL的方式,每条消息的过期时间不同,如果要删除所有过期消息需要扫描整个队列,这样效率较低。因此,RabbitMQ选择等到此消息即将被消费时再判定是否过期,如果过期再进行删除即可。跟 Redis 中的惰性删除是一个道理。这种方式避免了不必要的全队列扫描,提高了效率。

注意:这里的“即将投递到消费者之前”通常指的是在消息被发送到消费者之前,RabbitMQ会检查该消息是否已过期。如果消息已过期,RabbitMQ会将其删除,不会将其发送给消费者。这种机制确保了消费者不会接收到过期的消息。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java 网络编程和多线程

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;Java 目录 &#x1f449;&#x1f3fb;实现客户端和服务端交互1. 基本概念2. 常用类3. 简单示例客户端代码服务器代码 4. 注意事项 &#x1f449;&#x1f3…

文献阅读——电力系统安全域边界通用搜索模型与近似方法

文章标题 DOI&#xff1a;10.13334/j.0258-8013.pcsee.190884 ©2020 Chin.Soc.for Elec.Eng. 4411 文章编号&#xff1a;0258-8013 (2020) 14-4411-19 中图分类号&#xff1a;TM 74 电力系统安全域边界通用搜索模型与近似方法 姜涛&#xff0c;李晓辉&#xff0c;李雪*&a…

一站式大语言模型API调用:快速上手教程

智匠MindCraft是一个强大的AI工具及开发平台&#xff0c;支持多种大语言模型和多模态AI模型。本文将详细介绍如何通过API调用智匠MindCraft中的大语言模型&#xff0c;帮助开发者快速上手。 注册与登录 访问智匠MindCraft官网&#xff0c;注册并登录账号。 进入开发者平台&…

常见字符函数和字符串函数(下)

1. strncpy 函数的使用 将源的前 number 个字符复制到目标。如果在复制 num 个字符之前找到源 C 字符串的末尾&#xff08;由 null 字符表示&#xff09;&#xff0c;则目标将填充零&#xff0c;直到写入总数 num 个字符为止。如果 source 长于 num&#xff0c;则不会在 destin…

《向量数据库指南》——非结构化数据迁徙战:向量数据库的挑战与突破

在深入探讨非结构化数据在向量数据库间迁移所面临的挑战时,我们不得不正视这一领域所独有的复杂性与特殊性。随着人工智能、大数据技术的迅猛发展,向量数据库作为处理高维、非结构化数据的核心工具,其重要性日益凸显。然而,与成熟的关系型数据库迁移相比,向量数据库之间的…

扫盲接口测试,有些知识是需要了解和掌握的(建议收藏)

扫盲内容&#xff1a; 1.什么是接口&#xff1f; 2.接口都有哪些类型&#xff1f; 3.接口的本质是什么&#xff1f; 4.什么是接口测试&#xff1f; 5.问什么要做接口测试&#xff1f; 6.怎样做接口测试&#xff1f; 7.接口测测试点是什么&#xff1f; 8.接口测试都要掌…

02-指针代码示例

视频地址&#xff1a; 数组作为函数参数_哔哩哔哩_bilibili 指针是一个变量,用来存放其他变量的地址. 一、语法角度说: 需要用整形变量的指针,去存储一个整形变量的地址. 二、代码部分: (一) 1.指针赋值 int main(int argc, const char* argv[]) {int a;int* p;//这里要…

王道-操作系统

3 下列说法正确的是_____ 答案:A 解析: A 正确。如链接文件可以顺序存取,但不能随机存取。连续文件可随机存取,也可顺序存取。 B 错误。一个 FCB 就是一个文件目录项。在引入索引节点后,每个文件的目录项只保留文件名和指向该文件对应的索引节点指针,而索引节点的有关信息…

AD导出gerber文件(光绘文件)

第一步&#xff1a; 英寸 2:5 勾选你想显示的层 默认默认 第二步&#xff1a; 第三步&#xff1a; 默认

每日OJ_牛客_NC95数组中的最长连续子序列_排序+模拟_C++_Java

目录 牛客_NC95数组中的最长连续子序列_排序和模拟 题目解析 C代码 Java代码 牛客_NC95数组中的最长连续子序列_排序模拟 数组中的最长连续子序列_牛客题霸_牛客网 题目解析 排序 模拟。但是要注意处理数字相同的情况&#xff0c;还要注意去重。 排序后使用一个变量cou…

【预备理论知识——1】深度学习:概率论概述

简单地说&#xff0c;机器学习就是做出预测。 概率论 掷骰子 假设我们掷骰子&#xff0c;想知道看到1的几率有多大&#xff0c;而不是看到另一个数字。 如果骰子是公平的&#xff0c;那么所有六个结果{1,…, 6}都有相同的可能发生&#xff0c; 因此我们可以说 1 发生的概率为1…

软件设计(实验三):经典软件体系结构风格(二)

实验目的&#xff1a; 本实验旨在帮助学生理解和实现两种常见的软件体系结构风格&#xff1a;事件的隐式调用软件体系结构、层次软件体系结构。通过编写具体的代码&#xff0c;学生将能够掌握这两种风格的基本原理&#xff0c;并能够评估它们在不同场景下的适用性和优劣。 基…

string类的使用(上)

目录 1.string类的概念 2.string的构造函数&#xff08;实现初始化&#xff09; 3.对string类容量获取和操作 4.string类对象的访问和遍历 4.1operator[] 4.2begin和end 4.3 rbegin 和 rend 4.4迭代器分类 4.5范围for&#xff08;自动实现遍历&#xff09; 5.string类…

http请求过程 part-2

http请求过程 http应用层 实体 实体分为实体首部和实体主体&#xff0c;实体首部是用来描述主体的 实体部分是可选的&#xff0c;它被用来运送请求或者响应的数据 传输层-TCP HTTP连接是建立在TCP连接的基础上 以流形式通过一条已经打开的TCP连接&#xff0c;按顺序进行…

next 从入门到精通

next 从入门到精通 相关链接 演示地址 演示地址 源码地址 源码地址 获取更多 获取更多 hello 大家好&#xff0c;我是 数擎科技&#xff0c;今天来跟大家聊聊 Next.js 如果你遇到任何问题&#xff0c;欢迎联系我 m-xiaozhicloud 什么是 Next.js Next.js 是一个基于 Reac…

27 C 语言标准库 <stdio.h> 中的两个字符串函数:sprintf、sscanf,不同编码方式的中文字符长度

目录 1 sprintf 1.1 函数原型 1.2 功能说明 1.3 案例演示 1.4 注意事项 2 sscanf 2.1 函数原型 2.2 功能说明 2.3 案例演示 2.4 使用 %s 解析字符串的易错点 2.4.1 空白符问题 2.4.2 顺序问题 2.4.3 中文字符长度问题 2.5 注意事项 1 sprintf 1.1 函数原型 spri…

求恰好为k 的区间数量(滑动窗口进阶版)

前言&#xff1a;之前做的滑动窗口都是可以直接一遍过&#xff0c;然后每次右边确定了以后&#xff0c;左边不断缩小寻找最优解 但是这个题目呢我们不仅要保证我们的辅音字母的个数恰好为k&#xff0c;其他元音字母的个数只要每个都出现了就行&#xff0c;这个就导致我们不能用…

【IEEE PDF eXpress】格式不对

目录 一、问题二、解决方法 一、问题 word的文档&#xff0c;用IEEE PDF eXpress网站生成pdf后&#xff0c;提交论文出现错误&#xff1a; Document validation failed due to the following errors: Content exceeds IEEE template margins for its format (Page 1:Bottom).…

Java_TestNg

TestNg 前言支持特性 使用步骤1.引入库 常用注解Test注解BeforeSuite AfterSuiteAfterClass BeforeClassAfterTest BeforeTestAfterGroups BeforeGroupsBeforeMethod AfterMethodDataProviderFactoryListenersPatameters断言相等 不相等true/falsenull / !nullequals / !equals…

Leetcode 887. 鸡蛋掉落

1.题目基本信息 1.1.题目描述 给你 k 枚相同的鸡蛋&#xff0c;并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f &#xff0c;满足 0 < f < n &#xff0c;任何从 高于 f 的楼层落下的鸡蛋都会碎&#xff0c;从 f 楼层或比它低的楼层落下的鸡蛋都…