redis实现的分布式锁为啥要设置过期时间?
Redis分布式鎖利用setnx,如果進(jìn)程中的線程成功設(shè)置了setnx,則證明獲取到了鎖,然后執(zhí)行業(yè)務(wù)邏輯代碼,然后釋放鎖。
//試圖獲得鎖 1.if (redisClient.setnx(xx,xx)){ 2. do xxxxx something 3. //釋放鎖 4. redisClient.del(xx) 5.}這種方式有個(gè)問題就是如果第4行之前出現(xiàn)錯(cuò)誤,執(zhí)行不到第4行的話,鎖會(huì)釋放不了,然后鎖死。
于是一個(gè)新的方案出爐:
//試圖獲得鎖 1.if (redisClient.setnx(xx,xx)){ 2. //設(shè)置過期時(shí)間 3. expire xx 5 4. do xxxxx something 5. //釋放鎖 6. redisClient.del(xx) 7.}給鎖設(shè)置過期時(shí)間,這樣一來,即使執(zhí)行不到第6行(釋放鎖的哪一行),等過期時(shí)間到了,也會(huì)自動(dòng)釋放鎖。
然而這個(gè)方案乍一看是那么回事,其實(shí)沒啥卵用,因?yàn)榧渔i和設(shè)置過期時(shí)間不是原子操作,加完鎖后,設(shè)置過期時(shí)間前出現(xiàn)問題,照樣玩完。
于是接下來,很多人想方設(shè)法吧這兩個(gè)操作變成原子操作,先有第三方包,后有官方實(shí)現(xiàn)版本(set ex nx)。
手動(dòng)分割線,以下才是正文,哈哈。
這個(gè)問題確實(shí)是解決了,但是為啥一定要用這種方式解決呢?對于Java來說,直接在finally中釋放鎖不就行了嗎?就像ReentrantLock不就是在finally中釋放鎖的嗎?
其實(shí)這里是不一樣的,ReentranLock加鎖和釋放鎖是在自己的進(jìn)程里面,即使進(jìn)程被kill掉,鎖來不及釋放,下次啟動(dòng)進(jìn)程的時(shí)候,再次獲取鎖就是了。
但是Redis分布式鎖是第三方的東西,程序就是Redis節(jié)點(diǎn)的客戶端,一旦客戶端沒有釋放鎖,服務(wù)端就會(huì)一直持有這個(gè)鎖的,其他進(jìn)程中的線程是獲取不了鎖的。
比如以下這兩種情況(如果只在finally中釋放鎖,不設(shè)置過期時(shí)間):
1.網(wǎng)絡(luò)抖動(dòng)
進(jìn)程A中的一個(gè)線程獲取到了鎖,然后執(zhí)行finally中的釋放鎖的代碼時(shí),由程序到Redis的網(wǎng)絡(luò)不好了,所以釋放鎖失敗。此時(shí)對于redis服務(wù)端來說,它可不知道客戶端曾經(jīng)試圖釋放過鎖,它會(huì)一直把鎖給A,如此一來,其他進(jìn)程的線程再也不能獲取到這個(gè)鎖了。
如果用設(shè)置過期時(shí)間的方式,即使客戶端和服務(wù)端的網(wǎng)絡(luò)不通了,服務(wù)端依然在進(jìn)行時(shí)間的計(jì)算,時(shí)間到了直接把鎖釋放掉,等網(wǎng)絡(luò)通了,不影響獲取鎖。
2.服務(wù)端宕機(jī)
進(jìn)程A獲取到了鎖,Redis服務(wù)器宕機(jī)了,所以鎖沒有釋放。等到Redis再次恢復(fù)的時(shí)候,Redis服務(wù)端還會(huì)保持這這個(gè)鎖給到A,就會(huì)鎖死。
如果是設(shè)置了過期時(shí)間的話,服務(wù)器恢復(fù)后就會(huì)繼續(xù)倒計(jì)時(shí),時(shí)間到了服務(wù)器自動(dòng)把鎖釋放。
說白了,分布式鎖用的是第三方的東西,所以要在第三方設(shè)置,不能只在客戶端保證所的釋放。
one more thing:
其實(shí)用set ex nx雖然加鎖和設(shè)置過期時(shí)間變成了原子性,但是依然會(huì)有問題,因?yàn)橐话銇碚fRedis在生產(chǎn)環(huán)境中并不是單節(jié)點(diǎn)的,而是一個(gè)集群。
那么會(huì)存在這種情況,比如A進(jìn)程中的一個(gè)線程獲取到了鎖,是設(shè)置到了master節(jié)點(diǎn),但是當(dāng)master的數(shù)據(jù)還沒有同步到slaver之前,master死了。此時(shí)從slaver中選舉中來的新master并不知道有這個(gè)鎖,所以新的線程B來獲得鎖,也會(huì)獲取成功。這就造成了兩個(gè)進(jìn)程獲取同一把鎖。
解決這種問題有一個(gè)RedLock算法,留待以后研究。
總結(jié)
以上是生活随笔為你收集整理的redis实现的分布式锁为啥要设置过期时间?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA价格对程序员来说九牛一毛,为啥这
- 下一篇: maya海龟烘焙法线_maya法线烘焙