在jvm同乙個程序內的執行緒
單程序的併發場景,我們可以使用語言和類庫提供的鎖如sychronized和reentranlock,對於部分不是的場景,我們需要使用分布式鎖。
分布式鎖的實現方式
加鎖 setnx(key,1)
當乙個執行緒執行setnx返回1,說明key原本不存在,該執行緒成功得到了鎖,當乙個執行緒執行setnx返回0,說明key已經存在,該執行緒搶鎖失敗。
解鎖 del(key)
當得到鎖的執行緒執行完任務,需要釋放鎖,以便其他執行緒進入,釋放鎖的簡單方式執行del指令。
鎖超時 (key,30)
如果乙個得到鎖的執行緒在執行任務的過程中掛掉,來不及顯式地釋放鎖,這塊資源將會永遠被鎖住,別的執行緒再也別想進來。
if
(setnx
(key,1)
==1)finally
}
setnx和expire
之間不是原子性操作,如果執行完setnx,節點宕機了,那麼鎖就永遠得不到釋放。在redis2.6.12提供了set指令增加了可選引數。set(key,1,30,nx)
del導致誤刪
如果某些原因導致執行緒a執行很慢,過了30秒都還沒有執行完,這時候鎖過期自動釋放,執行緒b得到了鎖,隨後執行緒a執行完任務,執行緒a接著執行del釋放鎖,但這時候b還沒有執行完,執行緒a釋放的是執行緒b加的鎖。
解決方法:在del釋放鎖之前加乙個判斷,驗證當前的鎖是不是自己加的,可以在加鎖的時候那當前執行緒id當做value,並在刪除之前驗證key對應的value是不是自己的執行緒id。
//加鎖
string threadid=thread.
currentthread()
.getid;
set(key,threadid,
30,nx)
;//解鎖
if(threadid.
equals
(redisclient.
get(key)))
出現併發的可能性
雖然我們避免了執行緒a誤刪掉key的情況,但是同一時間有a,b兩個執行緒在訪問**塊,仍然使不完美的。我們可以獲得鎖的執行緒開啟乙個守護執行緒,用來給快要過期的鎖續航。
分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...
redis實現分布式鎖
隨便 系統越來越大,各功能模組除了垂直切割以外,同時也得做集群處理,那麼問題來了,在多執行緒情況下對於資源的競爭就需要乙個統一的訪問限制。以選課系統為例子,集群中各節點對課程可選數量同時操作,這裡就需要同步了,否則會導致最後選到的數量比可選的數量大,這裡我們的分布式鎖就派上用場了。利用redis來實...
redis實現分布式鎖
分布式鎖可以基於很多種方式實現,比如zookeeper redis.不管哪種方式,他的 基本原理是不變的 用乙個狀態值表示鎖,對鎖的占用和釋放通過狀態值來標識。1 使用redis的setnx命令實現分布式鎖 1 實現的原理 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶...