RabbitMQ + Redis 实现:苍穹外卖中的超时订单自动取消功能
RabbitMQ 与 Redis 的组合有效实现了订单生命周期管理;异步处理提升系统响应速度;Redis 缓存避免重复消费和业务冲突;消息队列提高了系统的可维护性和可扩展性。
一、前言 / 背景介绍
订单超时自动取消是电商/外卖系统中的常见需求;最近在学习黑马的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
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)