單Redis例項實現分布式鎖的正確方法

2021-10-08 07:27:02 字數 1097 閱讀 6398

獲取鎖使用命令:

set resource_name my_random_value nx px 30000
這個命令僅在不存在key的時候才能被執行成功(nx選項),並且這個key有乙個30秒的自動失效時間(px屬性)。這個key的值是「my_random_value」(乙個隨機值),這個值在所有的客戶端必須是唯一的,所有同一key的獲取者(競爭者)這個值都不能一樣。

value的值必須是隨機數主要是為了更安全的釋放鎖,釋放鎖的時候使用指令碼告訴redis:只有key存在並且儲存的值和我指定的值一樣才能告訴我刪除成功。可以通過以下lua指令碼實現:

if redis.call("get",keys[1]) == ar**[1] then

return redis.call("del",keys[1])

else

return 0

end

使用這種方式釋放鎖可以避免刪除別的客戶端獲取成功的鎖。舉個例子:客戶端a取得資源鎖,但是緊接著被乙個其他操作阻塞了,當客戶端a執行完畢其他操作後要釋放鎖時,原來的鎖早已超時並且被redis自動釋放,並且在這期間資源鎖又被客戶端b再次獲取到。如果僅使用del命令將key刪除,那麼這種情況就會把客戶端b的鎖給刪除掉。使用lua指令碼就不會存在這種情況,因為指令碼僅會刪除value等於客戶端a的value的key(value相當於客戶端的乙個簽名)。

這個隨機字串應該怎麼設定?我認為它應該是從/dev/urandom產生的乙個20位元組隨機數,但是我想你可以找到比這種方法代價更小的方法,只要這個數在你的任務中是唯一的就行。例如一種安全可行的方法是使用/dev/urandom作為rc4的種子和源產生乙個偽隨機流;一種更簡單的方法是把以毫秒為單位的unix時間和客戶端id拼接起來,理論上不是完全安全,但是在多數情況下可以滿足需求.

key的失效時間,被稱作「鎖定有效期」。它不僅是key自動失效時間,而且還是乙個客戶端持有鎖多長時間後可以被另外乙個客戶端重新獲得。

截至到目前,我們已經有較好的方法獲取鎖和釋放鎖。基於redis單例項,假設這個單例項總是可用,這種方法已經足夠安全。現在讓我們擴充套件一下,假設redis沒有總是可用的保障。

分布式鎖 使用Redis實現分布式鎖

關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...

redis實現分布式鎖

隨便 系統越來越大,各功能模組除了垂直切割以外,同時也得做集群處理,那麼問題來了,在多執行緒情況下對於資源的競爭就需要乙個統一的訪問限制。以選課系統為例子,集群中各節點對課程可選數量同時操作,這裡就需要同步了,否則會導致最後選到的數量比可選的數量大,這裡我們的分布式鎖就派上用場了。利用redis來實...

redis實現分布式鎖

分布式鎖可以基於很多種方式實現,比如zookeeper redis.不管哪種方式,他的 基本原理是不變的 用乙個狀態值表示鎖,對鎖的占用和釋放通過狀態值來標識。1 使用redis的setnx命令實現分布式鎖 1 實現的原理 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶...