redis 鎖主要利用 redis 的 setnx 命令。
偽**如下:
if
(setnx
(key,1)
==1)finally
}
原子性問題
setnx成功之後,將要設定鎖超時時間的時候,伺服器掛掉、重啟、網路故障等原因,導致expire命令沒有執行,鎖變成死鎖。
可以通過lua**來實現原子性問題
eval "if (redis.call('setnx',keys[1],ar**[1]) < 1) then return 0; end; redis.call('expire',keys[1],tonumber(ar**[2])); return 1;"
1 key value 100
鎖誤解除
執行緒a設定的鎖的時間超時釋放之後,執行緒a仍未執行完畢,正在執行執行緒b的過程中,a解鎖了執行緒b加的鎖
解決辦法:在value上加上當前執行緒加鎖的標識,解鎖的時候,校驗標識。
// 加鎖
string uuid = uuid.
randomuuid()
.tostring()
.replaceall
("-",""
);set key uuid nx ex 30
// 解鎖
if(redis.
call
('get'
, keys[1]
)== ar**[1]
)then
return redis.
call
('del'
, keys[1]
)else
return
0end
超時解鎖導致併發
不可重入
當執行緒在持有鎖的情況下再次請求加鎖,如果乙個鎖支援乙個執行緒多次加鎖,那麼這個鎖就是可重入的。
redission 加鎖示例:
// 如果 lock_key 不存在
if(redis.
call
('exists'
, keys[1]
)==0)
then
// 設定 lock_key 執行緒標識 1 進行加鎖
redis.
call
('hset'
, keys[1]
, ar**[2]
,1);
// 設定過期時間
redis.
call
('pexpire'
, keys[1]
, ar**[1]
);return
nil;
end;
// 如果 lock_key 存在且執行緒標識是當前欲加鎖的執行緒標識
if(redis.
call
('hexists'
, keys[1]
, ar**[2]
)==1)
// 自增
then redis.
call
('hincrby'
, keys[1]
, ar**[2]
,1);
// 重置過期時間
redis.
call
('pexpire'
, keys[1]
, ar**[1]
);return
nil;
end;
// 如果加鎖失敗,返回鎖剩餘時間
return redis.
call
('pttl'
, keys[1]
);
無法等待鎖釋放
如果客戶端需要等待鎖釋放的話,可以通過
集群下的主備切換
redis主從部署模式下,鎖在主節點加鎖成功,命令還未同步到從節點,這個時候主節點掛了,導致資料不一致問題,從而導致併發執行。
集群下的腦裂問題
當出現腦裂問題的時候,有兩個master節點,不同的客戶端連線不同的 master 節點時,兩個客戶端可以同時擁有同一把鎖。
加鎖機制,可重入加鎖機制
lua指令碼保證這段複雜業務邏輯執行的原子性。
釋放鎖機制
每次釋放鎖,次數-1。如果發現加鎖次數是0了,說明這個客戶端已經不再持有鎖了,此時就會用del命令,從redis裡刪除這個key。
鎖互斥機制
加鎖的時候,傳入標識這個客戶端的id,通常用uuid來表示
watch dog自動延期機制
客戶端一旦加鎖成功,就會啟動乙個watch dog看門狗,他是乙個後台執行緒,會每隔10秒檢查一下,如果客戶端還持有鎖key,那麼就會不斷的延長鎖key的生存時間。
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不存在。如給定的...