RabbitMQ 延迟队列,消息延迟推送

本文介绍了RabbitMQ如何实现消息延迟推送,包括应用场景如淘宝七天自动确认收货、12306购票支付确认,以及对比传统解决方案如Redis、数据库轮询和JVM DelayQueue的不足。重点讲解了从RabbitMQ 3.6.x版本开始提供的延迟队列插件的使用,包括创建交换机和队列、设置延迟时间以及消费端的处理。并展示了6秒后成功接收延迟消息的测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用场景#

目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如:

  • 淘宝七天自动确认收货。在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将款打给商家,这个过程持续七天,就是使用了消息中间件的延迟推送功能。
  • 12306 购票支付确认页面。我们在选好票点击确定跳转的页面中往往都会有倒计时,代表着 30 分钟内订单不确认的话将会自动取消订单。其实在下订单那一刻开始购票业务系统就会发送一个延时消息给订单系统,延时30分钟,告诉订单系统订单未完成,如果我们在30分钟内完成了订单,则可以通过逻辑代码判断来忽略掉收到的消息。

在上面两种场景中,如果我们使用下面两种传统解决方案无疑大大降低了系统的整体性能和吞吐量:

  • 使用 redis 给订单设置过期时间,最后通过判断 redis 中是否还有该订单来决定订单是否已经完成。这种解决方案相较于消息的延迟推送性能较低,因为我们知道 redis 都是存储于内存中,我们遇到恶意下单或者刷单的将会给内存带来巨大压力。
  • 使用传统的数据库轮询来判断数据库表中订单的状态,这无疑增加了IO次数,性能极低。
### 如何使用 RabbitMQ 实现延迟队列用于订单支付超时处理 #### 定义延迟队列的概念及其重要性 延迟队列是一种特殊的消息队列,能够按照设定的时间间隔发送消息给消费者。对于电商系统而言,在用户下单之后如果未能及时完成支付,则可以通过延迟队列机制自动取消这些未付款项并释放对应的资源。 #### 构建基于 Spring Boot 和 RabbitMQ 的解决方案框架 为了实现这一功能,可以采用Spring Boot集成RabbitMQ的方式构建应用服务端逻辑[^2]: ```java @Configuration public class RabbitConfig { @Bean public Queue orderDelayQueue() { Map<String, Object> args = new HashMap<>(); // 设置死信交换机 args.put("x-dead-letter-exchange", "dlx.exchange"); // 设置死信路由键 args.put("x-dead-letter-routing-key", "order.cancel"); // 设置TTL时间为10分钟(毫秒单位) args.put("x-message-ttl", 600_000); return new Queue("order.delay.queue", true, false, false, args); } } ``` 上述配置定义了一个具有特定属性的队列`order.delay.queue`,其中包含了指向死信交换机的信息以及消息存活时间(TTL)。当一条消息在这个队列里超过了指定时限后就会被转发至关联的死信交换机,并通过预设好的路由键传递给目标处理器。 #### 处理订单创建与过期事件 每当有新的订单生成时,应该立即将其详情封装成JSON字符串形式并通过AMQP协议推送到之前建立起来的延迟队列中等待进一步处理;而一旦收到由死信交换机转交过来的数据包则意味着对应的商品预订已经逾期失效,此时应当立即采取措施撤销交易记录并向客户发出通知邮件提醒尽快重新尝试购买操作[^3]。 ```java @Service @Slf4j public class OrderService { private final AmqpTemplate amqpTemplate; @Autowired public OrderService(AmqpTemplate amqpTemplate) { this.amqpTemplate = amqpTemplate; } /** * 创建新订单并将之加入到延迟队列中 */ public void createOrder(OrderInfo info){ String jsonStr= JSON.toJSONString(info); log.info("New order created:{}",jsonStr); amqpTemplate.convertAndSend("order.delay.queue","",jsonStr); // ...其余业务流程... } /** * 接收来自死信交换机的通知并对相应订单做标记为已关闭状态 */ @RabbitListener(queues="order.dlx.queue") public void handleExpiredOrders(String msgBody){ OrderInfo expiredOrder = JSON.parseObject(msgBody, OrderInfo.class); log.warn("Handling expired order:[{}]",expiredOrder.getId()); cancelUnpaidOrder(expiredOrder); } private void cancelUnpaidOrder(OrderInfo order){ // 更新数据库中的订单状态字段为'closed' // 同步更新库存数量 // 发送电子邮件告知顾客订单已被取消 } } ``` 此部分展示了两个主要方法:一个是用来接收前端传来的参数组合成完整的订单实例对象后再调用RabbitMQ客户端API将其存入临时存储空间内静候时机触发后续动作;另一个则是监听专门为此目的设立的主题订阅者所接收到的内容进而执行必要的清理工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello_world!

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值