Redisson使用延时队列

发布时间 2023-10-12 22:33:11作者: 乐之者v

延时队列

在开发中,有时需要使用延时队列。

比如,订单15分钟内未支付自动取消。

jdk延时队列

如果使用 jdk自带的延时队列,那么服务器挂了或者重启时,延时队列里的数据就会失效,可用性比较差。

Redisson延时队列

可以使用Redisson的延时队列。

Redisson的配置,详情见:https://blog.csdn.net/sinat_32502451/article/details/133799192

在延时队列中添加任务

    public void addDelayQueue(String orderId) {
        RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque("orderQueue");
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        //在延时队列中添加任务,5秒后生效
        delayedQueue.offer(orderId, 5, TimeUnit.SECONDS);
        log.info("addDelayQueue orderId:" + orderId);
    }

取出延时队列中的任务

取出延时队列中的任务,如果延时队列中没有任务,会阻塞,直到队列中添加了任务。

public void takeDelayQueue() {
	    log.info("DelayQueue take start.");
        RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque("orderQueue");
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        while (true) {
            String orderId = null;
            try {
            	//取出延时队列中的任务,如果延时队列中没有任务,会阻塞,直到队列中添加了任务。
                orderId = blockingDeque.take();
            } catch (Exception e) {
                log.error("blockingDeque.take error.", e);
            }

            if (orderId != null) {
                log.info("DelayQueue get orderId:" + orderId);
                //实际情况不需要break,此处为了方便调试
                break;
            }

        }
    }

日志:

调用 takeDelayQueue()方法,不断在延时队列中拉取数据,由于队列中没有数据,所以会先阻塞。

接着调用 addDelayQueue()方法,往队列中添加数据,观察日志,可以发现 5秒后,取到队列中的数据。

[2023-10-12 21:30:49.536]  INFO  c.c.m.c.controller.DelayQueueController  [line: 63] DelayQueue take start.
[2023-10-12 21:30:54.725]  INFO  c.c.m.c.controller.DelayQueueController  [line: 54] addDelayQueue orderId:12345
[2023-10-12 21:30:59.821]  INFO  c.c.m.c.controller.DelayQueueController  [line: 72] DelayQueue get orderId:12345

参考资料:

https://blog.csdn.net/sinat_32502451/article/details/133799192