Redisson(1)分布式锁——如何解决死锁问题
?Redisson是如何解決死鎖問題的?
普通利用Redis實現(xiàn)分布式鎖的時候,我們可能會為某個鎖指定某個key,當線程獲取鎖并執(zhí)行完業(yè)務(wù)邏輯代碼的時候,將該鎖對應(yīng)的key刪除掉來釋放鎖。
lock->set(key),成功->執(zhí)行業(yè)務(wù),業(yè)務(wù)執(zhí)行完畢->unlock->del(key)。
根據(jù)這種操作和實踐方式,我們可以分為下面兩個場景:
1)業(yè)務(wù)機器宕機
因為我們的業(yè)務(wù)不知道要執(zhí)行多久才能結(jié)束,所以這個key我們一般不會設(shè)置過期時間。這樣如果在執(zhí)行業(yè)務(wù)的過程中,業(yè)務(wù)機器宕機,unlock操作不會執(zhí)行,所以這個鎖不會被釋放,其他機器拿不到鎖,從而形成了死鎖。
Redisson為了解決這種情況,設(shè)定了一個叫做lockWatchdogTimeout的參數(shù),默認為30秒鐘。這樣當業(yè)務(wù)方調(diào)用加鎖操作的時候,
默認的leaseTime是-1,此時看門狗才會生效,不會走if分支,如果leaseTime被人為設(shè)置了值,且不是-1,看門狗不會work。這里會取watch dog的時間作為鎖的持有時間,默認是30s,這個時候即使發(fā)生了宕機現(xiàn)象,因為這個鎖不是永不過期的(宕機之后不不會再續(xù)租),所以30s后就會釋放,不會產(chǎn)生死鎖。
另一方面,它還能解決當鎖內(nèi)邏輯超過30s的時候鎖會失效的問題,因為當leaseTime是-1的時候,會啟動一個定時任務(wù),在業(yè)務(wù)方釋放鎖之前,會一直不停的增加這個鎖的生命周期時間,保證在業(yè)務(wù)執(zhí)行完畢之前,這個鎖一直不會因為redis的超時而被釋放(具體參考:汪~汪~汪~redisson的WatchDog是如何看家護院的?_黑少的技術(shù)盒子-CSDN博客)。
2)Redis宕機
如果Redis宕機,三種情況:
①Redis是單點模式
②Redis是集群模式,master在獲取到一把鎖之后(寫操作成功后),在沒來得及把該鎖同步到slave之前就宕掉,這個時候slave沒有鎖,這把鎖失效了……
③Redis是集群模式,而整個集群都宕機,那么就沒救了……
Redisson的官方文檔里有這段描述(參考:8. Distributed locks and synchronizers · redisson/redisson Wiki · GitHub)
“If Redisson instance which acquired lock crashes then such lock could hang forever in acquired state. To avoid this Redisson maintains lock watchdog, it prolongs lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through?Config.lockWatchdogTimeout?setting.”
這里說的是擁有Redisson的服務(wù)(業(yè)務(wù)服務(wù))宕機造成的影響嗎?如果是,那么和上面說的1)是一個意思。
這里GitHub中文譯文翻譯可能會引起歧義,8. 分布式鎖和同步器 · redisson/redisson Wiki · GitHub
里面翻譯的是:
“大家都知道,如果負責儲存這個分布式鎖的Redisson節(jié)點宕機以后,而且這個鎖正好處于鎖住的狀態(tài)時,這個鎖會出現(xiàn)鎖死的狀態(tài)。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個監(jiān)控鎖的看門狗,它的作用是在Redisson實例被關(guān)閉前,不斷的延長鎖的有效期。默認情況下,看門狗的檢查鎖的超時時間是30秒鐘,也可以通過修改Config.lockWatchdogTimeout來另行指定?!?/p>
這里說“負責儲存這個分布式鎖的Redisson節(jié)點宕機”可能會引起歧義,Redisson應(yīng)該指的是客戶端,而不是Redis服務(wù)實例吧。
如果是要形容Redis有問題而業(yè)務(wù)系統(tǒng)沒問題,應(yīng)該描述為“如果存儲該鎖的Redis節(jié)點宕機,那么這個鎖可能會被無限hang住”。
但是這里為什么會無限hang住,還是要看解鎖的部分是如何操作的,后面也會詳細說明。(這里貌似是因為Redis的訂閱功能,只有當這個鎖釋放的時候,才會觸發(fā)所有訂閱該鎖的其他線程,否則其他線程永遠都獲取不到鎖[如果沒有調(diào)用帶有超時時間獲取鎖的方法的話],從而造成死鎖。這個后面再詳細說,這里說的只是猜測,可能并不準確)。
反之,如果不hang住,鎖因為Redis節(jié)點宕掉而失效,那么其他的線程可以獲取鎖,但是當前的業(yè)務(wù)系統(tǒng)還在處理業(yè)務(wù),并沒有處理完,這里就會有線程安全問題了。
參考:
汪~汪~汪~redisson的WatchDog是如何看家護院的?_黑少的技術(shù)盒子-CSDN博客
8. Distributed locks and synchronizers · redisson/redisson Wiki · GitHub
相關(guān)文檔連接:
Redis官方文檔中文鏈:《Redis官方文檔》用Redis構(gòu)建分布式鎖 | 并發(fā)編程網(wǎng) – ifeve.com
Redisson Github中文鏈接:目錄 · redisson/redisson Wiki · GitHub
Redisson Github文檔:Home · redisson/redisson Wiki · GitHub
Redisson 官方文檔:Redisson: Redis Java client with features of In-Memory Data Grid
其他鏈接:扒開Redisson的小棉襖,Debug深入剖析分布式鎖之可重入鎖No.1_黑少的技術(shù)盒子-CSDN博客,redisson應(yīng)用之分布式對象 | KL博客
掘金
總結(jié)
以上是生活随笔為你收集整理的Redisson(1)分布式锁——如何解决死锁问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单实现 Android 闹钟
- 下一篇: Charles抓取手机APP接口数据使用