一、前言 / 背景介绍

订单超时自动取消是电商/外卖系统中的常见需求;最近在学习黑马的RabbitMQ课程,突然想起来苍穹外卖里也有外卖订单超时自动取消的功能,但是它使用的是SpringTask,我试试拿来练个手去用RabbitMQ结合Redis来实现此功能。

 二、技术选型与架构设计

1. 技术栈

Spring Boot
RabbitMQ
Redis
MySQL
WebSocket(可选,用于状态推送)

2. 整体架构图

  三、RabbitMQ 延迟队列的实现原理

1. RabbitMQ 的延迟机制原理 

使用 TTL(Time-To-Live)设置消息过期时间;
配置死信交换机(Dead Letter Exchange, DLX)和死信队列(DLQ);
消息过期后自动转发到 DLQ; 

 2. 队列配置示例(Config 类)

@Bean
public DirectExchange orderDelayExchange() {
    return new DirectExchange("order.delay.exchange");
}

@Bean
public CustomExchange deadLetterExchange() {
    return new CustomExchange("dead.letter.exchange");
}

@Bean
public Queue delayQueue() {
    return QueueBuilder.durable("order.delay.queue")
        .withArgument("x-dead-letter-exchange", "dead.letter.exchange")
        .withArgument("x-message-ttl", 60000) // 设置 TTL 为 60s
        .build();
}

 四、订单超时自动取消逻辑实现

1. 用户下单后发送延迟消息 

构建 OrderMessageDTO;
使用 RabbitTemplate 发送到延迟队列;
示例代码片段: 

OrderMessageDTO message = OrderMessageDTO.builder()
    .orderId(order.getId())
    .orderNumber(order.getNumber())
    .build();

rabbitTemplate.convertAndSend("order.delay.exchange", "order.create", message);

 2. 消费者监听死信队列处理订单

 监听 dead.letter.queue;
查询订单状态;
判断是否已被支付或接单(通过 Redis 缓存);
如果未处理,则执行取消订单逻辑;
主动 ACK 消息防止堆积;

五、Redis 标记机制优化消息处理 

1. 为什么需要 Redis?

 避免重复消费;
在支付成功、接单、拒单等操作中主动标记订单为已处理;
消费者根据 Redis 中是否存在标记决定是否跳过处理;

 2. 示例:Redis 标记方法

@Autowired
private StringRedisTemplate redisTemplate;

private final String ORDER_PROCESSED_KEY_PREFIX = "order:processed:";

public void markOrderAsProcessed(Long orderId) {
    redisTemplate.opsForValue().set(ORDER_PROCESSED_KEY_PREFIX + orderId, "1", 1, TimeUnit.DAYS);
}

 3. 消费者中判断逻辑

String key = ORDER_PROCESSED_KEY_PREFIX + orderMessageDTO.getOrderId();
if ("1".equals(redisTemplate.opsForValue().get(key))) {
    channel.basicAck(tag, false); // 已处理,直接确认
    return;
}

 

 六、订单状态变更场景下的处理

场景 处理方式
支付成功 调用 markOrderAsProcessed() 方法
商家接单 调用 cleanupOrderMessage() 方法
拒单 同上,标记订单为已处理
后台取消订单 同上

 七、WebSocket 实时推送订单状态变化(可选扩展)

 结合 WebSocket 向商家端或用户端推送订单状态变更;
示例:支付成功后推送“新订单提醒”;
提升用户体验,增强系统交互性;

 

八、遇到的问题与解决方案

问题 解决方案
消息未确认导致堆积 手动调用 basicAck
死信队列消息重复消费 Redis 标记机制
接单后仍触发取消 Redis 清除消息机制不完善
RabbitMQ 配置错误导致找不到 Exchange 检查交换机、队列声明逻辑
LocalDateTime 序列化异常 添加 Jackson JSR310 模块支持

 

总结:

 RabbitMQ 与 Redis 的组合有效实现了订单生命周期管理;
异步处理提升系统响应速度;
Redis 缓存避免重复消费和业务冲突;
消息队列提高了系统的可维护性和可扩展性 

八、附录 

GitHub 项目地址:sky-take-out: 根据苍穹外卖来练练手,https://gitee.com/he-xingyou/sky-take-out 

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐