CodeWalk

Redis延迟队列实现与Redisson RDelayedQueue

作者:Yahuda · 2026-05-30 12:55

如何使用Redis实现延迟队列?请介绍ZSet实现延迟队列的方案(Score作为执行时间戳),以及Redisson的RDelayedQueue的原理。和RocketMQ的延迟消息相比有什么优缺点?

回答

Yahuda

ZSet实现延迟队列

// 生产者:添加任务,score为执行时间戳
redisTemplate.opsForZSet().add("delay_queue", taskJson, executeTime);

// 消费者:轮询获取到期的任务
while (true) {
    Set<String> tasks = redisTemplate.opsForZSet()
        .rangeByScore("delay_queue", 0, System.currentTimeMillis(), 0, 1);
    if (tasks != null && !tasks.isEmpty()) {
        String task = tasks.iterator().next();
        // 原子性移除(避免多个消费者重复消费)
        Long removed = redisTemplate.opsForZSet().remove("delay_queue", task);
        if (removed > 0) {
            // 执行业务逻辑
            process(task);
        }
    }
    // 短暂休眠,避免空转
    Thread.sleep(100);
}

Redisson RDelayedQueue

  • 封装了上述ZSet实现,提供便捷API
  • 使用RQueue作为目标队列,RDelayedQueue监听
  • 元素到期时自动从RDelayedQueue转移到目标RQueue
RQueue<String> queue = redisson.getQueue("my_queue");
RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(queue);
delayedQueue.offer("task1", 10, TimeUnit.SECONDS); // 10秒后入队
// 从queue中poll消费
String task = queue.poll();

Redis延迟队列 vs RocketMQ延迟消息

对比Redis(ZSet/Redisson)RocketMQ
精度依赖轮询间隔,秒级毫秒级
可靠性消息可能丢失(宕机)持久化,可靠
延迟等级任意时间固定18个等级(1s/5s/10s/30s/1m...)
海量消息内存限制,容量有限磁盘存储,量大
实现复杂度简单复杂(需部署RocketMQ集群)
适用场景小规模、轻量需求大规模、高可靠性需求

总结:小规模轻量需求用Redis延迟队列(如订单30分钟未支付取消);大规模高可靠用RocketMQ。