Redis--SpringBoot Redis实现延时队列

Redis--SpringBoot Redis实现延时队列_第1张图片

第一步:pom.xml

        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

第二步:application.yml

server:
  port: 8081
  servlet:
    context-path: /

spring:
  # redis非关系型数据库
  redis:
    host: 服务器ip
    port: 6379
    password: 密码
    jedis:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1
        # 连接池中的最大空闲连接
        max-idle: 500
        # 连接池中的最小空闲连接
        min-idle: 0
    lettuce:
        shutdown-timeout: 0

第三步:DelayTask延时任务模型

/**
 * @Author ben
 * @Description 延时任务模型
 * @Date 上午10:59 2022/3/4
 **/
@Data
public class DelayTask {
    /**
     * 消息id
     */
    private String id;
    /**
     * 任务名称
     */
    private String taskName;
    /**
     * 具体任务内容
     */
    private T msg;
}

第四步:RedisDelayQueue延时队列

/**
 * @Author ben
 * @Description redis延时队列
 * @Date 上午11:05 2022/3/4
 **/
public class RedisDelayQueue {
    /**
     * 延迟队列名称
     */
    private String delayQueueName = "delayQueue";


    private RedisTemplate redisTemplate;

    // 传入redis客户端操作
    public RedisDelayQueue(RedisTemplate redisTemplate, String delayQueueName)
    {
        this.redisTemplate = redisTemplate;
        this.delayQueueName = delayQueueName;
    }
    /**
     * 设置延迟消息
     */
    public boolean setDelayTasks(T msg, long delayTime) {
        DelayTask delayTask = new DelayTask<>();
        delayTask.setId(UUID.randomUUID().toString());
        delayTask.setMsg(msg);
        Boolean addResult = redisTemplate.opsForZSet().add(delayQueueName, JSONObject.toJSONString(delayTask), System.currentTimeMillis() + delayTime);
        if(addResult)
        {
            System.out.println("添加任务成功!"+JSONObject.toJSONString(delayTask)+"当前时间为"+ LocalDateTime.now());
            return true;
        }
        return false;
    }
    /**
     * 监听延迟消息
     */
    public void listenDelayLoop() {
        System.out.println("线程名称:"+ Thread.currentThread().getName());
        System.out.println("线程id:"+ Thread.currentThread().getId());
        while (true) {
            // 获取一个到点的消息
            Set set = redisTemplate.opsForZSet().rangeByScore(delayQueueName, 0, System.currentTimeMillis(), 0, 1);

            // 如果没有,就等等
            if (set.isEmpty()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 继续执行
                continue;
            }
            // 获取具体消息的key
            String it = set.iterator().next();
            // 删除成功
            if (redisTemplate.opsForZSet().remove(delayQueueName, it) > 0) {
                // 拿到任务
                DelayTask delayTask = JSONObject.parseObject(it, DelayTask.class);
                // 后续处理
                System.out.println("消息到期;"+delayTask.getMsg().toString()+",到期时间为"+ DateUtil.formatAsDatetime(new Date()));
            }
        }
    }
}

第五步:CustomerThread 消费者线程

/**
 * @Classname CustomerThread
 * @Description 消费者线程
 * @Date 2022/3/4 23:38
 * @Created ben
 */
public class CustomerThread extends Thread {
    private RedisTemplate redisTemplate;
    public CustomerThread(RedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }
    @Override
    public void run(){
        RedisDelayQueue queue = new RedisDelayQueue(redisTemplate,"下单未付款,1min后自动取消!");
        queue.listenDelayLoop();
    }
}

第六步:RedisController延时任务入口

/**
 * @Classname RedisController
 * @Description redis延时任务入口
 * @Date 2022/3/4 22:41
 * @Created ben
 */
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisTemplate redisTemplate;
    public boolean customerThread = false;

    @RequestMapping("/createDelayTasks")
    public CommonResult createDelayTasks(@RequestParam(value = "orderNumber") String orderNumber){
        String msg = "订单号:" + orderNumber + ",下单时间:"+ DateUtil.formatAsDatetime(new Date());
        RedisDelayQueue queue = new RedisDelayQueue(redisTemplate,"下单未付款,1min后自动取消!");
        boolean result = queue.setDelayTasks(msg, 60000);
        if (!customerThread){
            customerThread = true;
            CustomerThread thread = new CustomerThread(redisTemplate);
            thread.start();
        }
        if (result){
            return new CommonResult(true,"下单成功,未付款,1min后自动取消订单!");
        }
        return new CommonResult(false,"下单失败!");
    }

}

第七步:CommonResult公共返回对象

/**
 * @Author ben
 * @Description 公共返回对象
 * @Date 上午11:40 2022/1/14
 **/
@Data
public class CommonResult implements Serializable {
    private boolean isucceed;
    private T data;
    public CommonResult(boolean isucceed,T data) {
        this.isucceed = isucceed;
        this.data = data;
    }
    public CommonResult(){

    }
}

第八步:install

  • install后的jar包,就在项目路径的target下.

Redis--SpringBoot Redis实现延时队列_第2张图片

第九步:部署服务器,并启动项目

  • 部署此处省略,可参考(51条消息) 服务器--阿里轻量应用服务器部署springboot项目_卷神一代的博客-CSDN博客_轻量应用服务器部署springboothttps://blog.csdn.net/weixin_51110874/article/details/122469932?spm=1001.2014.3001.5501

第十步:访问url,并测试

  • ip:端口号/redis/createDelayTasks?orderNumber=1
  • Redis--SpringBoot Redis实现延时队列_第3张图片

你可能感兴趣的:(Java,Redis,redis,spring,boot)