RabbitMQ进阶_延迟消息

文章目录

  • 一、 死信交换机和延迟消息
    • 1.1、 死信交换机
    • 1.2、 延迟消息
  • 二、 DelayExchange插件
  • 三、 实现时的优化

  在电商的支付业务中,对于一些库存有限的商品,为了更好的用户体验,通常都会在用户下单时立刻扣减商品库存。例如电影院购票、高铁购票,下单后就会锁定座位资源,其他人无法重复购买。但是这样就存在一个问题,假如用户下单后一直不付款,就会一直占有库存资源,导致其他客户无法正常交易,最终导致商户利益受损!因此,电商中通常的做法就是: 对于超过一定时间未支付的订单,应该立刻取消订单并释放占用的库存

  例如,订单支付超时时间为30分钟,则我们应该在用户下单后的第30分钟检查订单支付状态,如果发现未支付,应该立刻取消订单,释放库存。

  但问题来了:如何才能准确的实现在下单后第30分钟去检查支付状态呢?像这种在一段时间以后才执行的任务,我们称之为延迟任务,而要实现延迟任务,最简单的方案就是利用MQ的延迟消息了。在RabbitMQ中实现延迟消息也有两种方案:

  • 死信交换机+TTL
  • 延迟消息插件

一、 死信交换机和延迟消息

1.1、 死信交换机

什么是死信?当一个队列中的消息满足下列情况之一时,可以称为死信(dead letter):

  • 消费者使用basic.rejectbasic.nack声明消费失败,并且消息的requeue参数设置为false。
  • 消息是一个过期消息,超时无人消费。
  • 要投递的队列消息满了,无法投递。

  如果一个队列中的消息已经成为死信,并且这个队列通过dead-letter-exchange属性指定了一个交换机,那么队列中的死信消息就会投递到这个交换机中,而这个交换机就称为死信交换机。而此时假如有队列与死信交换机绑定,则最终死信消息就会被投递到这个队列中。死信交换机有什么作用呢?

  1. 收集那些因处理失败而被拒绝的消息。
  2. 收集那些因队列满了而被拒绝的消息。
  3. 收集因TTL(有效期)到期的消息。

1.2、 延迟消息

在这里插入图片描述
  如上图所示,有一组绑定的交换机(simple.direct)和队列(simple.queue)。但是simple.queue没有消费者监听,而是设定了死信交换机dlx.direct,而队列simple.queue则与死信交换机绑定。

  1. 假如我们现在发送一条消息到simple.direct,并设置消息的有效期为30s。
  2. 消息肯定会被投递到simple.queue之后,由于没有消费者,因此消息无人消费。30s之后,消息的有效期到期,成为死信。
  3. 死信被再次投递到死信交换机dlx.direct
  4. 最终消息被成功路由到dlx.queue,此时有消费者与dlx.queue绑定, 也就能成功消费消息了。但此时已经是30s钟以后了。

也就是说,publisher发送了一条消息,但最终consumer在30s后才收到消息。我们成功实现了延迟消息

二、 DelayExchange插件

  基于死信队列虽然可以实现延迟消息,但是太麻烦了。因此RabbitMQ社区提供了一个延迟消息插件来实现相同的效果。

1.声明延迟交换机(基于注解方式)

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "delay.queue", durable = "true"),exchange = @Exchange(name = "delay.direct", delayed = "true"),key = "delay"
))
public void listenDelayMessage(String msg){log.info("接收到delay.queue的延迟消息:{}", msg);
}

2.发送延迟消息。发送消息时,必须通过x-delay属性设定延迟时间:

@Test
void testPublisherDelayMessage() {// 1.创建消息String message = "hello, delayed message";// 2.发送消息,利用消息后置处理器添加消息头rabbitTemplate.convertAndSend("delay.direct", "delay", message, new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {// 添加延迟消息属性message.getMessageProperties().setDelay(5000);return message;}});
}

  延迟消息插件内部会维护一个本地数据库表,同时使用Elang Timers功能实现计时。如果消息的延迟时间设置较长,可能会导致堆积的延迟消息非常多,会带来较大的CPU开销,同时延迟消息的时间会存在误差。因此,不建议设置延迟时间过长的延迟消息

三、 实现时的优化

设置30分钟后检测订单支付状态实现起来非常简单,但是存在两个问题:

  • 如果并发较高,30分钟可能堆积消息过多,对MQ压力很大。
  • 大多数订单在下单后1分钟内就会支付,但是却需要再MQ内等待30分钟,浪费资源。

在这里插入图片描述
  如上图所示,客户下单到交易服务模块,交易服务会发送延迟消息到MQ,延迟时间到,接收MQ的消息,检查这笔订单客户是否已支付,如果未支付,需要取消。但是考虑到上述问题,可以将一个30分钟的大延迟拆分为数个时间较短的小延迟,正常来说,大部分订单在下单后的短时间内都会完成支付,这样随着时间的流动,因未支付而要发MQ的延迟消息越来越少,从而提高性能。

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

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

相关文章

解决calico 报错: error getting IP from IPAM: resource already exists

问题描述&#xff1a; Pod启动&#xff0c;一直creating状态&#xff0c;describe显示 error getting IP from IPAM: resource already exists&#xff0c;分配的IP地址被占用。 解决办法 这个IP真的被占用了&#xff0c;可以用 kubectl get po -A -owide | grep <ip>…

How to install Node.js and NPM on CentOS

How to install Node.js and NPM on CentOS Download Node.js 菜鸟教程-Node.js 安装配置 Introduction Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and…

PHP 正则验证A-Z且排除某字母

都已经找到这里来了&#xff0c;相信已经尝试很多办法了&#xff0c;那么我们直接上答案 关键正则&#xff1a;(?!.*[IO]) //验证5到6个大写字母且排除I和O if (preg_match(/^(?!.*[IO])[A-Z\d]{5,6}$/u, AAAAM)) {echo "匹配成功"; } else {echo "匹配失败…

今日指数项目集成SpringSecurity

项目集成SpringSecurity ​ 在第一章我们是基于SpringSecurity、JWT技术实现前后端无状态化认证授权&#xff0c;而我们当前的项目是前后端分离的架构&#xff0c;同样也可借助Security框架和Jwt实现前后端的无状态认证授权操作&#xff1b; 1、项目自定义认证过滤器 1.1 依…

特斯拉Robotaxi发布会2024:自动驾驶未来的开端

引言 2024年10月&#xff0c;特斯拉在洛杉矶举行了一场引发全球科技界高度关注的发布会&#xff0c;主题为“We Robot”。这场发布会展示了特斯拉的最新自动驾驶技术&#xff0c;包括无人驾驶出租车Cybercab和无人驾驶厢式货车Robovan&#xff0c;并且还展示了人形机器人Optim…

D43【python 接口自动化学习】- python基础之函数

day43 装饰器&#xff08;上&#xff09; 学习日期&#xff1a;20241020 学习目标&#xff1a;函数&#xfe63;- 56 装饰器&#xff1a;函数嵌套的定义与调用的区别 学习笔记&#xff1a; 变量作用域 变量读取顺序&#xff1a;local-》enclosed-》global-》builtin # 变量…

owasp top 10漏洞原理与防御技术(原理和对应防御技术)

OWASP&#xff08;Open Web Application Security Project&#xff09;每年发布的Top 10 Web应用程序安全风险&#xff0c;是对开发人员、项目经理和组织的一个重要指南。这些风险代表了最常见且具有严重影响的安全漏洞。 1. 注入 原理 注入漏洞是指当攻击者将恶意代码插入应…

Unity-Shader-Tags

shader中可以通过tag指定渲染方式&#xff0c;光照方式等&#xff0c;是与系统对话的窗口 一、Queue&#xff1a; 用于定义渲染的顺序&#xff0c;根据值的大小确定层级的渲染顺序&#xff0c;用户也可以自定义值的大小。 1、Background&#xff1a;1000 2、Geometry&#…

c语言经典100例

1.字符串转为数字 #include <stdio.h>int strToInt(char *s) {int num0;int sign1;int step1;if (*s -){sign -1;s;}while (*s > 0&&*s < 9){num num*10(*s-0);step 10;s;}return num*sign; }int main() {char a[10] "-1234";char *s a ;pr…

法律文书审查专项使用大模型实现

审查合同,起诉书,劳动合同,等等一系列文书都可以采用大模型实现。 愿我们终有重逢之时,而你还记得我们曾经讨论的话题。 QQ group 868373192 QQ second group 277356808 我们可以通过设计更详细的prompt工程来对合同中的每一句进行分析,并判断其是否符合法律法规。对于…

【存储设备专栏 2.8 -- linux 下挂载命令 mount 与 gio mount】

> 请阅读【嵌入式及芯片开发学必备专栏】< 文章目录 mount 命令步骤卸载&#xff08;可选&#xff09; gio mountgio mount -d 详细介绍用法示例示例 1: 挂载 U 盘示例 2: 查看挂载的设备示例 3: 卸载设备 注意事项总结 mount 命令 要将插入到 Linux 系统的 U 盘&#x…

数据库知识点整理

DDL DDL-数据库操作 show databases ------------ 查看所有数据库 select database(); ----------查看当前数据库 create database 数据库名&#xff1b;---- 创建数据库 use 数据库名&#xff1b; --------------使用数据库 drop database 数据库名&#xff1b;--…

自由学习记录(11)

Surface Effector 2D Platform Effector 2D 向上跳跃穿过天花板的功能 平台效应器不用变Trigger&#xff0c;因为本来就是要有碰撞的 use one way grouping是让所有相关联的碰撞器都可以单面跳墙 默认不勾选&#xff0c;左右两边没有摩擦力和弹力&#xff0c;要自己先设置sid…

练习题 - Scrapy爬虫框架 Selectors 数据选择器

在学习Scrapy时,数据选择器(Selectors)是一个重要的概念,它让我们能够从抓取的网页中提取出需要的数据。通过使用XPath和CSS选择器,开发者可以准确地定位网页中的元素,提取文本、属性和节点等内容。熟悉这些选择器的用法,不仅能够提高爬虫的效率,还能帮助更好地理解网页…

poisson过程——随机模拟(Python和R实现)

Python实现 exponential()使用&#xff0c;自动poisson过程实现。 import numpy as np import matplotlib.pyplot as plt# Parameters lambda_rate 5 # rate parameter (events per time unit) T 10 # total time# Generate Poisson process times np.random.exponential(…

使用Redis进行在线人数统计时,有哪些性能优化技巧?

在使用Redis进行在线人数统计时&#xff0c;性能优化非常关键&#xff0c;以下是一些有效的性能优化技巧&#xff1a; 选择合适的数据结构&#xff1a; 使用有序集合&#xff08;ZSet&#xff09;可以同时存储在线用户的名单以及用户的上线时间&#xff0c;适用于需要聚合操作的…

数组的初始化,参数传递,和求和

在自己做的这个C语言解释器中&#xff0c;数组的使用非常简便。下面小程序是一个例子。演示了数组的初始化&#xff0c;参数传递&#xff0c; 和求和。 all[] { WA12,OR8,CA54, ID4, MT4, WY3, NV6, UT6, AZ11, CO10, NM5, ND3,SD3,NE4, KS6, OK7,TX40, MN10, WI10,IA6, MO10,…

SpringBoot+MyBatis+MySQL项目基础搭建

一、新建项目 1.1 新建springboot项目 新建项目 选择SpringBoot&#xff0c;填写基本信息&#xff0c;主要是JDK版本和项目构建方式&#xff0c;此处以JDK17和Maven举例。 1.2 引入依赖 选择SpringBoot版本&#xff0c;勾选Lombok&#xff0c;Spring Web&#xff0c;MyBa…

Keepalived:高可用性的守护神

Keepalived:高可用性的守护神 在现代企业IT系统中,高可用性是确保业务连续性和服务质量的关键要素。系统面对硬件故障、软件错误、人为失误或自然灾害时,依然能保持正常运行,这样的能力对于企业来说至关重要。为此,业界开发了一系列高可用性解决方案,其中Keepalived以其…

数据结构与算法:高级数据结构与实际应用

目录 14.1 跳表 14.2 Trie树 14.3 B树与 B树 14.4 其他高级数据结构 总结 数据结构与算法&#xff1a;高级数据结构与实际应用 本章将探讨一些高级数据结构&#xff0c;这些数据结构在提高数据存取效率和解决复杂问题上起到重要作用。这些高级数据结构包括跳表&#xff0…