美文网首页redis
Redisson延迟队列RDelayedQueue的使用

Redisson延迟队列RDelayedQueue的使用

作者: jackcooper | 来源:发表于2019-09-26 16:46 被阅读0次

    在开发中,往往会遇到一些关于延时任务的需求。例如

    1. 生成订单30分钟未支付,则自动取消
    2. 生成订单60秒后,给用户发短信
      对上述的任务,我们给一个专业的名字来形容,那就是延时任务。那么这里就会产生一个问题,这个延时任务和定时任务的区别究竟在哪里呢?一共有如下几点区别:
    • 定时任务有明确的触发时间,延时任务没有
    • 定时任务有执行周期,而延时任务在某事件触发后一段时间内执行,没有执行周期
    • 定时任务一般执行的是批处理操作是多个任务,而延时任务一般是单个任务

    解决方案:

    • 1、JDK的延迟队列
    • 2、时间轮算法--HashedWheelTimer
    • 3、Redisson延迟队列RDelayedQueue

    前俩方案的优缺点:

    • 优点:
      效率高,任务触发时间延迟时间比delayQueue低,代码复杂度比delayQueue低。
    • 缺点:
      (1)服务器重启后,数据全部消失,怕宕机   
      (2)集群扩展相当麻烦   
      (3)因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现OOM异常

    使用Redisson延迟队列RDelayedQueue

    1、 pom.xml

    <!-- JDK 1.8+ compatible -->
    <dependency>
       <groupId>org.redisson</groupId>
       <artifactId>redisson</artifactId>
       <version>3.11.2</version>
    </dependency> 
    
    
    <!-- JDK 1.6+ compatible -->
    <dependency>
       <groupId>org.redisson</groupId>
       <artifactId>redisson</artifactId>
       <version>2.10.4</version>
    </dependency> 
    

    2、队列中要存入的元素实体

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Employer {
        private String name;
        private int age;
        private String wife;
        private Double salary;
        private String putTime;
    
        public void setPutTime() {
            this.putTime = new SimpleDateFormat("hh:mm:ss").format(new Date());
        }
    }
    

    3、生成订单并放进延时队列的类

    package com.redisson;
    
    import org.redisson.Redisson;
    import org.redisson.api.RBlockingQueue;
    import org.redisson.api.RDelayedQueue;
    import org.redisson.api.RedissonClient;
    import org.redisson.config.Config;
    
    import java.util.concurrent.TimeUnit;
    
    public class RedisPutInQueue {
        public static void main(String args[]) {
            Config config = new Config();
            config.useSingleServer().setAddress("redis://127.0.0.1:6379");
            RedissonClient redissonClient = Redisson.create(config);
            RBlockingQueue<Employer> blockingFairQueue = redissonClient.getBlockingQueue("delay_queue");
    
            RDelayedQueue<Employer> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
            for (int i = 0; i < 10; i++) {
                try {
                    //模拟间隔投递消息
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 一分钟以后将消息发送到指定队列
                //相当于1分钟后取消订单
                //延迟队列包含callCdr 1分钟,然后将其传输到blockingFairQueue中
                //在1分钟后就可以在blockingFairQueue 中获取callCdr了
                Employer callCdr = new Employer();
                callCdr.setSalary(345.6);
                callCdr.setPutTime();
                delayedQueue.offer(callCdr, 1, TimeUnit.MINUTES);
                System.out.println("callCdr =================================> " + callCdr);
            }
            //在该对象不再需要的情况下,应该主动销毁。
            // 仅在相关的Redisson对象也需要关闭的时候可以不用主动销毁。
            delayedQueue.destroy();
    
            //redissonClient.shutdown();
        }
    }
    
    

    4、取消订单的操作类

    package com.redisson;
    
    import org.redisson.Redisson;
    import org.redisson.api.RBlockingQueue;
    import org.redisson.api.RDelayedQueue;
    import org.redisson.api.RedissonClient;
    import org.redisson.config.Config;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class RedisOutFromQueue {
        public static void main(String args[]) {
            Config config = new Config();
            config.useSingleServer().setAddress("redis://127.0.0.1:6379");
            RedissonClient redissonClient = Redisson.create(config);
            RBlockingQueue<Employer> blockingFairQueue = redissonClient.getBlockingQueue("delay_queue");
            RDelayedQueue<Employer> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
            while (true) {
                Employer callCdr = null;
                try {
                    callCdr = blockingFairQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("订单取消时间:" + new SimpleDateFormat("hh:mm:ss").format(new Date()) + "==订单生成时间" + callCdr.getPutTime());
            }
        }
    }
    
    

    参考:

    相关文章

      网友评论

        本文标题:Redisson延迟队列RDelayedQueue的使用

        本文链接:https://www.haomeiwen.com/subject/mwknuctx.html