redis实现定期关单

在SpringBoot项目中,实现订单超过24小时过期并自动关单,常见有以下几种方案,我会逐一说明,并给出推荐实现:

✅ 推荐方案:使用 延迟队列(DelayQueue) 或 消息队列(如RabbitMQ延迟消息)

方案1:使用 Redis + 延迟队列(Redisson延迟队列)

优点: 高性能、易扩展、适合分布式系统
实现步骤:
  1. 引入Redisson依赖:
xml
复制
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.4</version>
</dependency>
 
  1. 下单时,将订单ID加入延迟队列,延迟时间为24小时:
java
复制
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue("orderDelayQueue");
delayedQueue.offer(orderId, 24, TimeUnit.HOURS);
 
  1. 启动一个监听线程,消费延迟队列:
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 到期后消息被转移到这里,供消费者使用

🔍 工作流程简述

  1. 写入延迟消息:
    • 消息被写入一个 ZSET,score 是到期时间戳。
    • 例如:ZADD orderDelayQueue 1695720000 "order:123"
  2. 后台调度线程:
    • Redisson 启动一个后台线程,定期轮询这个 ZSET
    • 如果某个消息的 score(时间) <= 当前时间,就把它从 ZSET 中移除,并推入目标 LIST(即你传入的 RBlockingDeque)。
  3. 消费者读取:
    • 消费者通过 blockingDeque.take()LIST 中阻塞读取消息。

❌ 不是 LinkedHashSet

  • LinkedHashSet 是 Java 中的数据结构,Redis 中没有这个结构。
  • Redis 的 ZSET 是跳表 + 哈希表实现,支持按 score 排序,非常适合做延迟队列。

✅ 总结一句话

Redisson 的延迟队列底层是用 Redis 的 ZSET(SortedSet)+ LIST 实现的,不是 LinkedHashSet。

如果你对 Redisson 的源码感兴趣,我可以给你指一下具体类名和逻辑路径。


posted @ 2025-09-25 16:39  人在代码在  阅读(18)  评论(0)    收藏  举报