今天記錄一下redis實現分布式鎖,寫這個話題我猶豫了很久,因為這個實現雖然很容易,但是有很多細節需要注意,一不小心就死鎖,但是仔細一想好像也沒幾個人看我的文章,就當給自己做個筆記吧!大佬們要是發現那兒思路有問題,期待你能指出來哦,在生產環境下最好用redisson,別傻傻的自己實現了
在單機下我們的多執行緒爭搶資源是很好解決的,無非就是加鎖,reentrantlock,synchronized等等都行,但是在多執行緒的情況下,他們已經不是同乙個jvm了,他們是不可能在自己的jvm鎖到同乙個物件的,如圖:所以,在分布式系統中我們需要的是這樣乙個架構:這兒的中介軟體我們今天就是用的redis,後面可能會再寫一下zookeeper實現分布式鎖
我們只需要知道的幾個很簡單的redis命令:set示例: set name xiaoz ex 5 nx 解釋: 設定name欄位的值為xiaoz,失效時間為5秒,如果不存在這個key的話expire示例: expire name 5 解釋: 設定name欄位的超時時間為5秒
del示例: del name 解釋: 刪除name欄位
假設現在兩台機器一共8個執行緒都在爭搶鎖
加鎖
那麼他們怎麼才能算搶到鎖呢?
redis發揮作用了,set加上nx引數能保證只有一次set操作能成功,為什麼呢?我們暫且可以將redis理解為單執行緒,所以進來的8個操作是排好隊的,聽大佬們說好像redis並不完全都是單執行緒,這兒等我了解後再記錄吧。(小本本記上)
set lock 只有自己知道的乙個值,可以是隨機數 ex 5 nx
既然只有乙個操作能成功的話,那不就不用擔心資源爭搶的問題了,不就實現了分布式加鎖了嗎?
網上很多方案是用setnx加expire,其實這兒會有一點問題,因為他不是原子性的,如果在setnx之後剛好宕機了,那麼這個鎖就沒有失效時間了,造成死鎖,當然,這兒可以用lua指令碼操作,lua指令碼是具備原子性的解鎖解鎖直接使用del將lock這個鍵刪除不就解鎖了嗎,不過要注意的是,我們需要判斷一下這個鎖是不是自己的,怎麼判度就是去對比value,這個value只有自己知道,如果一樣就刪除,那麼需要先判斷一下,那麼又出現了原子問題,這兒我們可以使用lua指令碼實現,因為之前說過lua指令碼是具備原子性的
if redis.call('get',keys[1]) == ar**[1] then
return redis.call('del',keys[1])
else
return 0
end
分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...
redis實現分布式鎖
隨便 系統越來越大,各功能模組除了垂直切割以外,同時也得做集群處理,那麼問題來了,在多執行緒情況下對於資源的競爭就需要乙個統一的訪問限制。以選課系統為例子,集群中各節點對課程可選數量同時操作,這裡就需要同步了,否則會導致最後選到的數量比可選的數量大,這裡我們的分布式鎖就派上用場了。利用redis來實...
redis實現分布式鎖
分布式鎖可以基於很多種方式實現,比如zookeeper redis.不管哪種方式,他的 基本原理是不變的 用乙個狀態值表示鎖,對鎖的占用和釋放通過狀態值來標識。1 使用redis的setnx命令實現分布式鎖 1 實現的原理 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶...