redis分布式鎖演變過程

2021-10-09 12:29:20 字數 1899 閱讀 1524

最近研究了下redis分布式鎖,分享下演變過程,怎麼一步步實現抗高併發的分布式鎖

@override

public string seckill()

else

return goodscount >=0?

"恭喜你,搶到商品"

:"抱歉,您沒搶到"

;}

這段**,單執行緒情況下,無任何問題,一旦涉及到多執行緒,就涉及到先後順序,得先查詢redis獲取庫存,然後減庫存,將剩餘庫存存入redis,這段操作需要原子執行才行

毫無疑問synchronized 和 reentrantlock在集群環境下是不可行的,這裡不做贅述

**變成了這樣

string goodsid =

"666666"

; string lockkey =

"lockkey"

; boolean lock = redistemplate.

opsforvalue()

.setifabsent

(lockkey,

"***");

if(lock)

else

redistemplate.

delete

(lockkey)

;return goodscount >=0?

"恭喜你,搶到商品"

:"抱歉,您沒搶到";}

else

增加了獲取鎖和刪除鎖的過程,如果獲取到了鎖,執行秒殺操作,獲取不到鎖,繼續執行獲取鎖的操作;

但是這樣寫出現了個問題,如果來不及執行刪除鎖的**,拋異常或者服務宕機了,那麼其他執行緒永遠獲取不到鎖,變成了死鎖了,於是下面開始改進:

將setnx加上過期時間

boolean lock = redistemplate.opsforvalue().setifabsent(lockkey, 「***」,30, timeunit.seconds);

這樣就算服務宕機了,也能釋放鎖,不至於造成死鎖。

但是又引發出來了新的問題,有2個執行緒,執行緒一需要10s執行完成,執行緒二需要35秒執行完成,執行緒二30秒**沒執行完,這時候執行緒一執行完成刪除了鎖,這時候會有新的執行緒獲取到鎖,執行緒二執行完成後,又刪除了別人的鎖,於是開始下面的演變

@override

public string seckill() else

return goodscount >= 0 ? "恭喜你,搶到商品" : "抱歉,您沒搶到";

}finally

}}else

這樣還有個問題,執行時間還是個問題,**執行時間不一致,無法保證所有請求在30秒或者指定時間內執行完成,還是存在刪除別人鎖的情況,目的就是在**沒有執行完成時不要刪除鎖,**執行完成才刪除鎖,改進方法就是鎖續期,專門開啟乙個執行緒,每隔10秒,(1/3的時間)檢查鎖是否還存在,如果存在,就將時間續期為30秒

timeout task = commandexecutor.getconnectionmanager().newtimeout(new timertask() 

if (future.getnow())

}});

}}, internallockleasetime / 3, timeunit.milliseconds);

if (expirationrenewalmap.putifabsent(getentryname(), new expirationentry(threadid, task)) != null)

先查詢是否是自己的鎖,然後再刪除鎖也要是原子執行

至此,redis分布式鎖算比較完整的了,redis官方給我們最好了這一套,可以直接使用redisson

redis分布式鎖

redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...

Redis分布式鎖

分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...

redis分布式鎖

使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...