美文网首页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