当前位置: 首页 > article >正文

JAVA:利用 RabbitMQ 死信队列实现支付超时场景的技术指南

1、简述

在支付系统中,订单支付的超时自动撤销是一个非常常见的业务场景。通常用户未在规定时间内完成支付,系统会自动取消订单,释放相应的资源。本文将通过利用 RabbitMQ 的 死信队列(Dead Letter Queue, DLQ)来实现支付超时自动撤销功能,并详细讲解如何在 Java 中进行实现。

在这里插入图片描述

2、什么是死信队列?

死信队列是 RabbitMQ 中的一个重要功能,当消息在某个队列中变成“死信”时,可以被发送到另一个特殊的队列,这个队列就是死信队列。消息变成死信的情况有三种:

  • 消息被拒绝(basic.reject 或 basic.nack),并且 requeue=false。
  • 消息的 TTL(Time to Live)过期。
  • 队列达到最大长度,无法再存入新消息。

通过死信队列,我们可以处理一些特殊的业务逻辑,例如订单支付超时自动撤销。

3、实现过程

我们将为每个新创建的支付订单设置一个超时时间(例如 30 分钟),在订单支付的过程中将订单的消息发送到 RabbitMQ。消息在 RabbitMQ 中设置一定的 TTL(生存时间)。如果用户在超时时间内完成支付,消息会被正常处理;如果超时未支付,消息会成为“死信”,被转移到死信队列,从而触发订单撤销的逻辑。

3.1 环境准备

首先,在 pom.xml 中添加 RabbitMQ 相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3.2 RabbitMQ 配置

在 application.yml 中添加 RabbitMQ 的连接配置:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
3.3 配置普通队列和死信队列

我们需要配置两个队列,一个是正常的支付订单队列,另一个是死信队列。

  • 支付订单队列:用于接收支付订单的消息。
  • 死信队列:接收从支付订单队列中转移过来的超时未处理的消息。
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    // 正常交换机
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange("order-exchange");
    }

    // 死信交换机
    @Bean
    public DirectExchange deadLetterExchange() {
        return new DirectExchange("dead-letter-exchange");
    }

    // 正常队列
    @Bean
    public Queue orderQueue() {
        return QueueBuilder.durable("order-queue")
                .withArgument("x-dead-letter-exchange", "dead-letter-exchange") // 绑定死信交换机
                .withArgument("x-dead-letter-routing-key", "dead-letter-routing-key") // 死信路由键
                .withArgument("x-message-ttl", 1800000) // 消息的TTL(30分钟)
                .build();
    }

    // 死信队列
    @Bean
    public Queue deadLetterQueue() {
        return QueueBuilder.durable("dead-letter-queue").build();
    }

    // 绑定正常队列和交换机
    @Bean
    public Binding orderBinding(Queue orderQueue, DirectExchange orderExchange) {
        return BindingBuilder.bind(orderQueue).to(orderExchange).with("order-routing-key");
    }

    // 绑定死信队列和死信交换机
    @Bean
    public Binding deadLetterBinding(Queue deadLetterQueue, DirectExchange deadLetterExchange) {
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with("dead-letter-routing-key");
    }
}
3.4 发送订单支付消息

在订单创建时,我们将消息发送到 RabbitMQ,设置 TTL(超时时间):

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void createOrder(String orderId) {
        // 模拟创建订单的逻辑
        System.out.println("订单创建成功,订单ID:" + orderId);

        // 发送订单消息到RabbitMQ
        rabbitTemplate.convertAndSend("order-exchange", "order-routing-key", orderId);
        System.out.println("订单消息已发送,等待支付超时或支付完成处理...");
    }
}
3.5 监听死信队列,实现超时自动撤销订单

当订单超时未支付,消息将转移到死信队列,我们通过监听死信队列,实现订单撤销逻辑:

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class DeadLetterQueueListener {

    @RabbitListener(queues = "dead-letter-queue")
    public void handleExpiredOrder(String orderId) {
        // 处理超时订单撤销的逻辑
        System.out.println("订单支付超时,自动撤销订单,订单ID:" + orderId);
        // TODO: 更新数据库订单状态为已取消
    }
}

4、总结

通过使用 RabbitMQ 的死信队列,我们可以轻松实现支付超时自动撤销的功能。具体流程如下:

  • 创建订单时,将订单消息发送到 RabbitMQ,并为消息设置 TTL。
  • 如果用户在规定时间内完成支付,系统处理消息,订单正常完成。
  • 如果消息在 TTL 时间内未被处理,消息进入死信队列,触发自动撤销逻辑。

利用 RabbitMQ 死信队列可以确保超时订单得到及时处理,避免资源浪费,同时还能保证系统的高并发处理能力。

这套方案可以扩展应用于任何有类似超时要求的业务场景,如购物车超时、订单确认超时等。


http://www.kler.cn/a/503821.html

相关文章:

  • Java Agent(三)、ASM 操作字节码入门
  • 504 Gateway Timeout:网关超时解决方法
  • 图像模糊度(清晰度)检测 EsFFT 算法详细分析
  • Android SystemUI——基础简介(一)
  • 快速排序介绍
  • Linux下部署Redis(本地部署超详细)
  • 第424场周赛:使数组元素等于零、零数组变换 Ⅰ、零数组变换 Ⅱ、最小化相邻元素的最大差值
  • OJ题目下篇
  • AI赋能下的美颜API与滤镜SDK:从传统到深度学习的进化之路
  • 深入理解 Python 的装饰器
  • Elasticsearch ES|QL 地理空间索引加入纽约犯罪地图
  • 计算机的错误计算(二百一十一)
  • 交互数字人:革新沟通的未来
  • Java Agent(三)、ASM 操作字节码入门
  • 【机器学习】神经网络训练技巧
  • 使用VSCode搭建Ruby on Rails集成开发环境
  • mac intel芯片下载安卓模拟器
  • 【css】浏览器强制设置元素状态(hover|focus……)
  • rclone,云存储备份和迁移的瑞士军刀,千字常文解析,附下载链接和安装操作步骤...
  • MAC AndroidStudio模拟器无网络
  • 新版懒人精灵基础老狼孩插件经典例子板块-视频教程
  • C# 内存篇
  • 《零基础Go语言算法实战》【题目 4-1】返回数组中所有元素的总和
  • 蓝牙BT04-A的使用与相关AT指令
  • AI大模型开发—1、百度的千帆大模型调用(文心一言的底层模型,ENRIE等系列)、API文档目的地
  • 多线程基础系列-多线程初识