使用redis分散式鎖來解決叢集專案的定時任務衝突問題
阿新 • • 發佈:2019-01-07
import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.annotation.Scheduled; public class Test { // @Scheduled(cron="0 */1 * * * ?")//(每隔1分鐘的整數倍) public void closeOrderTask(){ 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 closeOrderTaskV(){ 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){ closeOrder(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("關閉訂單定時任務結束"); } }