zoukankan      html  css  js  c++  java
  • 利用redis 分布式锁 解决集群环境下多次定时任务执行

    定时任务:

        @Scheduled(cron= "0 39 3 * * *")
        public void getAllUnSignData(){
            //检查任务锁,若其它节点的相同定时任务已经执行,则该节点的任务执行一个空任务,否则设置锁并执行该任务
            String timerName = this.getClass().getName()+Thread.currentThread() .getStackTrace()[1].getMethodName();//当前类名+当前方法名
            if(redisLock.requireLock(timerName,7200)){
                return;
            }
            long startTime = System.currentTimeMillis();
            logger.info("定时任务 UnSignStatistics start-->" + startTime );
            //找出签到异常的学生,保存在表中
            gxyWarnService.saveUnSignWarn();
            long endTime = System.currentTimeMillis();
            logger.info("定时任务 UnSignStatistics end-->" +endTime+ ", execute time: " + (endTime - startTime) + "ms" );
    
    
        }

    用类名+方法名作为key, 去redis 获取锁。

    如果获取到了键值对: (key , 1) ,则说明定时任务已被执行,返回true , 执行if 中的return, 不执行 后面的定时任务。

    如果没有获取到 键值对: (key , 1) ,则说明定时任务没有被执行 。在redis中 设置键值对 (key , 1), (并设置有效期7200秒,这个有效期小于定时任务的周期即可),并返回false 。不执行if 中的return,继续执行后面的定时任务代码。

    @Component
    public class RedisLock {
        //redis中存任务锁的key前缀
        public final static String MOGUDING_TIMER_LOCK_KEY = "com:lock:job:";
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        /**
         * 判断是否有锁。有,返回true;否,返回false,设置一定期效的锁
         * @param lockName
         * @param expire  锁的有效时间长,单位:秒
         * @return
         */
        public boolean requireLock(String lockName,long expire){
            String key = MOGUDING_TIMER_LOCK_KEY+lockName;
            if(redisTemplate.opsForValue().getAndSet(key,"1")==null){   //“1”这里无任何意义
                redisTemplate.expire(key,expire,TimeUnit.SECONDS);
                return false;
            }else {
                return true;
            }
        }
        /**
         * 判断是否有锁。有,返回true;否,返回false,设置一定期效的锁
         * @param lockName
         * @param date  锁的有效时间截止点
         * @return
         */
        public boolean requireLock(String lockName,Date date){
            String key = MOGUDING_TIMER_LOCK_KEY+lockName;
            if(redisTemplate.opsForValue().getAndSet(key,"1")==null){  //“1”这里无任何意义
                redisTemplate.expireAt(key,date);
                return false;
            }else {
                return true;
            }
        }
    }
  • 相关阅读:
    mysql中使用row_number()函数
    Android开发环境的搭建之(二)Android Studio的安装
    Android开发环境的搭建之(一)Java开发环境的安装
    进程与线程
    工作起始之博客搬家
    MapReduce的自制Writable分组输出及组内排序
    map端join和reduce端join的区别
    String.StartsWith 方法
    RPC和心跳机制
    MAPREDUCE中的序列化
  • 原文地址:https://www.cnblogs.com/z360519549/p/11661162.html
Copyright © 2011-2022 走看看