redis实现定期关单
在SpringBoot项目中,实现订单超过24小时过期并自动关单,常见有以下几种方案,我会逐一说明,并给出推荐实现:
✅ 推荐方案:使用 延迟队列(DelayQueue) 或 消息队列(如RabbitMQ延迟消息)
方案1:使用 Redis + 延迟队列(Redisson延迟队列)
优点: 高性能、易扩展、适合分布式系统
实现步骤:
实现步骤:
-
引入Redisson依赖:
xml
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.4</version>
</dependency>
-
下单时,将订单ID加入延迟队列,延迟时间为24小时:
java
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue("orderDelayQueue");
delayedQueue.offer(orderId, 24, TimeUnit.HOURS);
-
启动一个监听线程,消费延迟队列:
java
RQueue<String> queue = redissonClient.getQueue("orderDelayQueue");
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(queue);
new Thread(() -> {
while (true) {
try {
String orderId = queue.take(); // 阻塞等待过期订单
// 查询订单状态,如果未支付,则关单
Order order = orderService.getById(orderId);
if (order != null && "UNPAID".equals(order.getStatus())) {
orderService.closeOrder(orderId);
log.info("订单已关闭:{}", orderId);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}).start();
Redisson 的
RDelayedQueue 并不是用 LinkedHashSet 实现的,它的底层数据结构是 Redis 的 List + SortedSet(ZSET) 组合实现的。✅ 底层实现原理(Redisson 延迟队列)
Redisson 的延迟队列(
RDelayedQueue)是基于以下两个核心 Redis 数据结构实现的:表格
| 组件 | Redis 数据结构 | 作用 |
|---|---|---|
| 延迟队列 | ZSET(有序集合) |
按时间戳排序,存储延迟消息 |
| 目标队列 | LIST |
到期后消息被转移到这里,供消费者使用 |
🔍 工作流程简述
-
写入延迟消息:
-
消息被写入一个
ZSET,score 是到期时间戳。 -
例如:
ZADD orderDelayQueue 1695720000 "order:123"
-
-
后台调度线程:
-
Redisson 启动一个后台线程,定期轮询这个
ZSET。 -
如果某个消息的 score(时间) <= 当前时间,就把它从
ZSET中移除,并推入目标LIST(即你传入的RBlockingDeque)。
-
-
消费者读取:
-
消费者通过
blockingDeque.take()从LIST中阻塞读取消息。
-
❌ 不是 LinkedHashSet
-
LinkedHashSet 是 Java 中的数据结构,Redis 中没有这个结构。
-
Redis 的
ZSET是跳表 + 哈希表实现,支持按 score 排序,非常适合做延迟队列。
✅ 总结一句话
Redisson 的延迟队列底层是用 Redis 的 ZSET(SortedSet)+ LIST 实现的,不是 LinkedHashSet。
如果你对 Redisson 的源码感兴趣,我可以给你指一下具体类名和逻辑路径。

浙公网安备 33010602011771号