目录
一、引言
上一章节我们提到,直接使用延迟插件,创建一个延迟指定时间的消息(如10分钟),并不是最好的解决方案,因为假如我们的订单是在5分钟支付的,那么剩余的5分钟时间,RabbitMQ中延迟消息时钟还是一直占用着资源。如果有大量的延迟消息,那么对于服务来说压力是很大的,同时会耗费庞大昂贵的资源。因此,本章节我们就来近一步对延迟插件的消息进行优化。
我们通过下面的流程图来做近一步分析:
1. 用户下单完成后,发送15分钟延迟消息,在15分钟后接收消息,检查支付状态:
2. 已支付:更新订单状态为已支付
3. 未支付:更新订单状态为关闭订单,恢复商品库存
常规延迟插件消息使用的弊端总结:
1. 设置30分钟后检测订单支付状态实现起来非常简单,但是存在两个问题:
2. 如果并发较高,30分钟可能堆积消息过多,对MQ压力很大
3. 大多数订单在下单后1分钟内就会支付,但是却需要在MQ内等待30分钟,浪费资源
二、优化方案
如下图所示,我们可以将10分钟甚至30分钟拆分成多份零散的较短的时间。
消息初次发送的延迟时间设定为10s,10s过后如果订单还是未支付状态,我们判断延迟时间数组里还有没有剩余延迟时间,如果有则继续发送延迟消息,时间设定为数组中的第二个时间10s,直到订单支付成功终止循环,或是最后一份时间消耗完依然未支付,我们取消订单。
三、核心代码实现
3.1. 生产者代码
package com.example.publisher;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.cor