Redis分布式鎖

2021-10-24 10:45:16 字數 2610 閱讀 3788

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不存在。如給定的...