背景
專案組已經有個
分布式鎖註解(參考前文《記一次分布式鎖註解化》),但是在設定鎖過期時間時,需要去預估業務耗時時間,如果鎖的過期時間能根據業務執行時間自動調整,那使用的就更方便了。
思路保留原先的可自定義設定過期時間,只有在沒有設定過期時間(過期時間為預設值0)的情況下,才會啟動自動延長。
申請鎖時,設定乙個延長過期時間,定時每隔延長過期時間的三分之一時間就重新設定過期時間(時期時間值為延長過期時間)。
為了防止某次業務由於異常而出現任務持續很久,從而長時間占有了鎖,新增最大延期次數引數。
加鎖用乙個map來儲存需要續期的任務資訊。
在加鎖成功之後將任務資訊放入map,並啟動延遲任務,延遲任務在執行延期動作前先檢查下map裡鎖資料是不是還是被當前任務持有。
每次續期任務完成並且成功之後,就再次啟動延遲任務。
申請鎖復用之前的加鎖方法,把延長過期時間作為加鎖過期時間。
public lock acquireandrenew(string lockkey, string lockvalue, int lockwatchdogtimeout) lock lock = acquire(lockkey, lockvalue, lockwatchdogtimeout); if (!lock.issuccess()) expirationrenewalmap.put(lockkey, new renewlockinfo(lock)); scheduleexpirationrenewal(lockkey, lockvalue, lockwatchdogtimeout, maxrenewtimes, new atomicinteger()); return lock;
定時續期
當前鎖還未被釋放(map裡還有資料),並且當前延期任務執行成功,則繼續下一次任務。
private void scheduleexpirationrenewal(string lockkey, string lockvalue, int lockwatchdogtimeout, int maxrenewtimes, atomicinteger renewtimes):{}] fail!", lockkey, lockvalue); return; } if (maxrenewtimes > 0 && renewtimes.incrementandget() == maxrenewtimes) :{}] override times[{}]!", lockkey, lockvalue, maxrenewtimes); return; } scheduleexpirationrenewal(lockkey, lockvalue, lockwatchdogtimeout, maxrenewtimes, renewtimes); } catch (exception e) :{}] error!", lockkey, lockvalue, e); } }, lockwatchdogtimeout / 3, timeunit.milliseconds); renewlockinfo lockinfo = expirationrenewalmap.get(lockkey); if (lockinfo == null) lockinfo.setrenewscheduledfuture(scheduledfuture);
private boolean renewexpiration(string lockkey, string lockvalue, int lockwatchdogtimeout) if (!lockinfo.getlock().getlockvalue().equals(lockvalue)) list keys = lists.newarraylist(lockkey); list args = lists.newarraylist(lockvalue, string.valueof(lockwatchdogtimeout)); return (long) jedistemplate.evalsha(renewscriptsha, keys, args) > 0;
延期指令碼
public void init() // 放在redis指令碼前面,防止redis刪除失敗,而map沒有清理,從而導致redis無限期續期 try } } catch (exception e) :{}] error!", lock.getlockkey(), lock.getlockvalue(), e); } expirationrenewalmap.remove(lock.getlockkey()); list keys = lists.newarraylist(lock.getlockkey()); list args = lists.newarraylist(lock.getlockvalue()); return (long) jedistemplate.evalsha(releasescriptsha, keys, args) > 0;
註解改造
註解類註解增加兩個引數,並且原先的過期時間引數預設值改為0,即預設啟動自動延期。
@target(value = )
@retention(value = retentionpolicy.runtime)
public @inte***ce dislock else { lock = jedisdistributedlock.acquire(key, value, dislock.expire());
protected boolean ifrenew(dislock dislock){ return dislock.expire() == dislock.default_expire;
Redis(十一) Redis分布式鎖
為什麼需要使用分布式鎖 因為synchronize和lock是乙個jvm中線程級別的鎖。如何應用部署在多台伺服器上 多個jvm 那synchronize和lock就不起作用了。所以需要分布式鎖來保證符合操作的原子性。1 基於資料庫 2 zookeeper分布式鎖 高一致性,效能較差 3 基於redi...
redis續期 Redis學習
過期刪除策略 redis 過期策略及實現原理 mp.weixin.qq.com redis分布式鎖 聊聊redisson的分布式鎖 www.jianshu.com 聊聊分布式鎖 mp.weixin.qq.com redis distlock redis中國使用者組 crug www.redis.cn...
redis分布式鎖
redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...