RabbitMQ 高级特性——TTL

news2024/11/18 9:20:10

在这里插入图片描述

文章目录

  • 前言
  • 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() {
        @Override
        public 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.coloradmin.cn/o/2178609.html

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

相关文章

黑马头条day7-app端文章搜索

今天的内容也只是跑了一下 对于具体的实现掌握的很差 仔细看 es 在微服务学的es使用基本忘光了 这里用起来一点都熟悉 重学&#xff01;&#xff01;&#xff01; kafka异步 文章自动构建索引的时候用到了‘’ mongoDB 用来存储用户的搜索记录 遗忘&#xff08;拦截器 j…

【有啥问啥】In-Context Learning(上下文学习):深入解析与应用实践

In-Context Learning&#xff08;上下文学习&#xff09;&#xff1a;深入解析与应用实践 引言 在人工智能与机器学习的浪潮中&#xff0c;In-Context Learning&#xff08;上下文学习&#xff09;作为一种新兴的学习范式&#xff0c;正逐渐崭露头角。与传统的机器学习模型不…

第四届机器人、自动化与智能控制国际会议(ICRAIC 2024)征稿

第四届机器人、自动化与智能控制国际会议&#xff08;ICRAIC 2024&#xff09;由湖南第一师范学院主办&#xff0c;南京师范大学、山东女子学院、爱迩思出版社&#xff08;ELSP&#xff09;协办。 大会将专注于机器人、数字化、自动化、人工智能等技术的开发和融合&#xff0c…

Go实现RabbitMQ 死信队列、优化

死信队列是什么&#xff1f; 如何配置死信队列&#xff1f; go实现死信队列 go使用发布订阅模式改造批量发送消息 【教学内容】 1. 死信队列是什么&#xff1f; 注意&#xff1a;业务队列与死信交换机的绑定是在构建业务队列时&#xff0c;通过参数&#xff08;x-dead-le…

计算机网络基础--认识协议

目录 前言 一、IP地址与端口 二、网络协议 1.网络体系结构框架 2.网络字节序 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 计算机网络涉及非常广泛&#xff0c;这篇文章主要对计算机网络有个认识 提示&#xff1a;以下是本篇文章正文内容&#x…

SNMP和Syslog有啥区别

在网络管理的世界中&#xff0c;SNMP&#xff08;简单网络管理协议&#xff09;和 Syslog&#xff08;系统日志&#xff09;是两种关键技术&#xff0c;它们分别在监控和管理网络设备方面发挥着重要作用。选择合适的工具对于确保网络的高效运行、优化性能和增强安全性至关重要。…

【易上手快捷开发新框架技术】nicegui组件button用法庖丁解牛深度解读源代码IDE运行和调试通过截图为证

传奇开心果微博文系列 前言一、button 组件基本用法1. 最基本用法示例2. 创建带图标按钮 二、button按钮组件样式定制1. 按钮的尺寸调整2. 改变颜色示例3. 按钮的自定义字体大小4. 圆角形状示例5. 自定义边框6. 添加阴影7. 复合按钮8. 浮动按钮9. 可扩展浮动操作按钮QFAB10. 按…

OpenCV视频I/O(14)创建和写入视频文件的类:VideoWriter介绍

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 视频写入器类。 该类提供了用于写入视频文件或图像序列的 C API。 cv::VideoWriter 类是 OpenCV 库中用于创建和写入视频文件的一个类。它提供了…

echarts实现3D柱状图(视觉层面)根据博主改编

https://blog.csdn.net/weixin_57798646/article/details/131067725 这是原贴 在这个基础上我需要实现 一根柱子 代码如下 <!DOCTYPE html> <html lang"en" style"height: 100%"><head><meta charset"utf8"> </hea…

【中间件学习】Nginx快速入门(为了配置一个项目)

-----------------------------本文章借鉴遇见狂神说--------------------------- 一、一个产品出现瓶颈&#xff1f;&#xff1f; 在一个产品刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#xff0c;所以在低并发的情况下&#xff0c;一个jar包启动应该就够…

Anaconda虚拟环境默认路径在C盘怎么更改

笔者已经新建好了虚拟环境并且安装了对应库&#xff0c;输入conda env list查询发现虚拟环境竟然安装到了C盘(&#xff61;•́︿•̀&#xff61;)&#xff0c;为避免下一次创建虚拟环境出错&#xff0c;笔者现在修改默认路径置D盘&#xff08;软件安装盘&#xff09; 参考两…

SSH连接Vscode

1.安装扩展包ssh 2-1.获取ssh登录命令 输入连接命令 2-2.获取虚拟机秘钥给vscode 查看远程主机的信息 打开工作目录 打开远程终端 3.RSA免密登录 打开power shell输入命令,获取秘钥 添加公钥到虚拟机 名字会自动更新&#xff0c;下一次进入虚拟机就不需要输入密码了

使用apipost工具导入通过swag生成的golang接口文档步骤

1.通过swag init 生成docs接口文档 见使用swag init --parseDependency生成api文档报错解决办法 2.导入操作 ok,操作完成

数据结构双链表和循环链表

目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表&#xff0c;就是尾节点的指针域指向头节点使整个链表形成一个循环&#xff0c;这就弥补了以前单链表无法在后面某个节点找到前面的节点&#xff0c;可以从任意一个节点找到目标节点…

Windows11安装Docker Desktop教程

目录 一.安装前置步骤 ▐ 开启虚拟化 ▐ 安装WSL2 ▐ 安装Linux环境 二.Windows上安装Docker 一.安装前置步骤 ▐ 开启虚拟化 首先确保虚拟化的开启&#xff0c;打开任务管理器后查看&#xff1a; 确保图中的虚拟化是已启用&#xff0c;没有开启的需要通过BIOS进行开启&…

vmware 操作系统安装

下面选择你要装入的iso镜像 下面选择要装入的磁盘&#xff0c;建议别装c盘. 之后等待安装即可。

k8s架构,从clusterIP到光电半导体,再从clusterIP到企业管理

clusterIP作为k8s中的服务&#xff0c; 也是其他三个服务的基础 ~]$ kubectl create service clusterip externalname loadbalancer nodeport 客户端的流量到service service分发给pod&#xff0c;pod由控制器自动部署&#xff0c;自动维护 那么问题是service的可用…

MySQL-MySQL访问

文章目录 前言一、使用步骤1.MYSQL *mysql_init(MYSQL *mysql);2.MYSQL *mysql_real_connectint mysql_query(MYSQL *mysql, const char *q);MYSQL_RES *mysql_store_result(MYSQL *mysql);my_ulonglong mysql_num_rows(MYSQL_RES *res);unsigned int mysql_num_fields(MYSQL_R…

秋招内推2025--招联金融

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

CRC循环校验的功能

CRC (Cyclic Redundancy Check&#xff0c;循环冗余校验) 是一种常用的错误检测码&#xff0c;用于检测数据传输或存储过程中发生的错误。它通过在数据末尾添加一个校验码&#xff08;CRC码&#xff09;来实现。接收方通过同样的算法计算接收数据的CRC码&#xff0c;并将结果与…