基於Redis實現分布式鎖

2022-05-27 08:03:11 字數 1835 閱讀 5242

1.setnx

鎖在redis中最簡單的資料結構就是string。最早的時候,上鎖的操作一般使用setnx,這個命令是當:lock不存在的時候set乙個val,或許你還會記得使用expire來增加鎖的過期,解鎖操作就是使用del命令,偽**如下:

if (redis::setnx("my:lock", 1))

這裡其實是有問題的,問題就在於setnx和expire中間如果遇到crash等行為,可能這個lock就不會被釋放了。

2.set

現在官方建議直接使用set來實現鎖。我們可以使用set命令來替代setnx,就是下面這個樣子

if (redis::set("my:lock", 1, "nx", "ex", 10))

上面的**把my:lock設定為1,當且僅當這個lock不存在的時候,設定完成之後設定過期時間為10。

獲取鎖的機制是對了,但是刪除鎖的機制直接使用del是不對的。因為有可能導致誤刪別人的鎖的情況。比如,這個鎖我上了10s,但是我處理的時間比10s更長,到了10s,這個鎖自動過期了,被別人取走了,並且對它重新上鎖了。那麼這個時候,我再呼叫redis::del就是刪除別人建立的鎖了。

官方對解鎖的命令也有建議,建議使用lua指令碼,先進行get,再進行del

主控:

$token = rand(1, 100000);

function lock()

function unlock()

if (lock())

redis分布式鎖核心類:

public

class

redistool

return

false

; }

/*** 釋放分布式鎖

* @param

jedis redis客戶端

* @param

lockkey 鎖

* @param

requestid 請求標識

* @return

是否釋放成功

*/public

static

boolean

releasedistributedlock(jedis jedis, string lockkey, string requestid)

return

false

; }

}

lua引數解釋:

> eval "

return "2

key1 key2 first second

1) "

key1

"2) "

key2

"3) "

first

"4) "

second

"

其他:lua指令碼的原子性:

redis 使用單個 lua 直譯器去執行所有指令碼,並且, redis 也保證指令碼會以原子性(atomic)的方式執行:當某個指令碼正在執行的時候,不會有其他指令碼或 redis 命令被執行。這和使用 multi / exec 包圍的事務很類似。在其他別的客戶端看來,指令碼的效果(effect)要麼是不可見的(not visible),要麼就是已完成的(already completed)。另一方面,這也意味著,執行乙個執行緩慢的指令碼並不是乙個好主意。寫乙個跑得很快很順溜的指令碼並不難,因為指令碼的執行開銷(overhead)非常少,但是當你不得不使用一些跑得比較慢的指令碼時,請小心,因為當這些蝸牛指令碼在慢吞吞地執行的時候,其他客戶端會因為伺服器正忙而無法執行命令。

基於Redis實現分布式鎖

分布式鎖的基本功能 1.同一時刻只能存在乙個鎖 2.需要解決意外死鎖問題,也就是鎖能超時自動釋放 3.支援主動釋放鎖 分布式鎖解決什麼問題 多程序併發執行任務時,需要保證任務的有序性或者唯一性 準備 redis版本 2.6 redis是主從 sentinel模式 為了高可用 原理 redis2.6之...

基於Redis實現分布式鎖

之前專案中使用redis鎖實現秒殺等一些併發業務,在這裡整理一下基於redis實現分布式鎖的簡單入門例項,記錄一下,便於以後檢視 學習。springboot整合redisson分布式鎖 1 簡介 在分布式系統中存在併發場景,為了解決這一問題,基於redis鎖一定程度可以解決這一問題,但是也有缺點,如...

基於redis實現分布式鎖

實現方式 具備條件 確保鎖可用,必須要滿足一下幾個條件 1 互斥性,任意時刻只有乙個使用者能持有鎖 2 不會產生死鎖,假設某個使用者在持有鎖的期間由於服務崩潰或者其他原因沒有主動釋放鎖,也能保證後續其他使用者可以加鎖 3 加鎖和解鎖必須是同一使用者,b使用者無法解除a使用者加的鎖 實現 1 引入je...