使用redis分布式鎖來解決集群項目的定時任務沖突問題


//    @Scheduled(cron="0 */1 * * * ?")//(每隔1分鍾的整數倍)
    public void closeOrderTaskV2(){
        System.out.println("關閉訂單定時任務啟動");
        long lockTimeout = 5000;//鎖存在的時間 這個時間根據具體業務處理時間來設置
        
        Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
        if(setnxResult != null && setnxResult.intValue() == 1){//如果返回值是1,代表設置成功,獲取鎖。假設程序執行到這里,此時關掉服務器 那么這里有可能出現死鎖的問題
            RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死鎖(這里的鎖有效期,與上面的lockTimeout值必須統一)
            System.out.println("-----------業務方法開始---------");
            System.out.println("執行業務方法");
            System.out.println("-----------業務方法結束---------");
            RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);//業務方法執行完之后 手動將鎖撤銷
        }else{
            System.out.println("未獲得分布式鎖,鎖名是:"+Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }
        System.out.println("關閉訂單定時任務結束");
    }

    @Scheduled(cron="0 */1 * * * ?")//(每隔1分鍾的整數倍)
    public void closeOrderTaskV3(){
        System.out.println("關閉訂單定時任務啟動");
        long lockTimeout = 5000;//鎖存在的時間 這個時間根據具體業務處理時間來設置
        Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
        if(setnxResult != null && setnxResult.intValue() == 1){
            RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死鎖(這里的鎖有效期,與上面的lockTimeout值必須統一)
            System.out.println("-----------業務方法開始---------");
            System.out.println("執行業務方法");
            System.out.println("-----------業務方法結束---------");
            RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }else{
            //未獲取到鎖,那么繼續判斷,判斷時間戳與當前時間對比,看是否可以重置並獲取到鎖
            String lockValueStr = RedisShardedPoolUtil.get(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
            if(lockValueStr ==null||lockValueStr != null && System.currentTimeMillis() > Long.parseLong(lockValueStr)){//這種到老鎖存在但是已經超時的情況一般是上面遇到的死鎖情況
                //設置新鎖 並獲取老鎖的值,getset是一個原子性的方法
                String getSetResult = RedisShardedPoolUtil.getSet(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
                if(getSetResult == null || (getSetResult != null && StringUtils.equals(lockValueStr,getSetResult))){//老鎖消失 或者老鎖過期並且老鎖未被其他進程操作的情況下 有權利獲取鎖
                    //真正獲取到鎖
                    RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死鎖
                    System.out.println("-----------業務方法開始---------");
                    System.out.println("執行業務方法");
                    System.out.println("-----------業務方法結束---------");
                    RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                }else{
                    System.out.println("沒有獲取到分布式鎖");
                }
            }else{
                System.out.println("沒有獲取到分布式鎖");
            }
        }
        System.out.println("關閉訂單定時任務結束");
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM