什么是分布式鎖?
分布式鎖是控制分布式系統或不同系統之間共同訪問共享資源的一種鎖實作,如果不同的系統或同一個系統的不同主機之間共享了某個資源時,往往需要互斥來防止彼此干擾來保證一致性,
分布式鎖需要具備哪些條件?
- 互斥性:在任意一個時刻,只有一個客戶端持有鎖,
- 無死鎖:即便持有鎖的客戶端崩潰或者其他意外事件,鎖仍然可以被獲取,
- 容錯:只要大部分Redis節點都活著,客戶端就可以獲取和釋放鎖,
場景
以前大學照著網上的專案視頻做商城的時候,用到Redis,不過基本上都是用來當快取,但是實際上的應用遠不止快取,所以今天分享一個分布式鎖的場景和應用,
在逛商城的時候進行購物支付,基本都是分布式系統,那么用戶支付的時候就要上鎖,保證不能多執行緒操作,Redis分布式鎖就差不多是這么一個位置:

從業務的角度考慮是非常合理的,它保證了查詢及插入資料整個流程的原子性,防止查到臟資料,使得支付流程是一個串行化操作,
接下來就來講一個Redis分布式鎖的一個知識點,
為什么要使用分布式鎖?
在實際專案中見過分布式鎖后,就不難理解為什么要用分布式鎖了,總的來說就是分布式系統要訪問共享資源,為了避免并發訪問資源帶來的錯誤,我們為共享資源添加一把鎖,讓各個訪問互斥,保證并發訪問的安全性,這就是使用分布式鎖的原因,
Redis中分布式鎖的實作
命令格式:
SETNX key value
將key的值設為value,當且僅當key不存在,若給定的key已經存在,則SETNX不做任何動作,SETNX是SET if Not eXists的簡寫,
回傳值:
回傳整數,具體為
- 1,當key的值被設定
- 0,當key的值沒被設定
Redis中使用分布式鎖很簡單,只要使用setnx指令對某個key上鎖就行:
setnx lock test //上鎖
del lock test //解鎖
當然我們還可以在上鎖之后使用expire指令給鎖設定過期時間,
假如我們的程式不使用指令解鎖,靠redis設定時間過期來解鎖,貌似會出問題,假如我們的服務行程在執行setnx之后和執行expire指令之前掛掉了,那么這個鎖豈不是永遠都不會被釋放?
沒錯,這確實是個問題,當時人們在Redis的開源社區提出一堆解決方案專門來解決這個問題,可實作方式都極為復雜,后來Redis的作者在Redis2.8版本中假如了set指令的擴展引數,使得setnx指令和expire指令能夠同時執行,具體使用像下面一樣:
set lock test ex 5 nx
ex:設定鍵的過期時間
nx:只在鍵不存在的時候,才對鍵進行設定操作
從此以后,Redis成為了分布式鎖的寵兒,
集群Redis的分布式鎖
在Redis的分布式環境中,Redis 的作者提供了RedLock 的演算法來實作一個分布式鎖,
加鎖
獲取當前Unix時間,以毫秒為單位,
依次嘗試從N個實體,使用相同的key和隨機值獲取鎖,在步驟2,當向Redis設定鎖時,客戶端應該設定一個網路連接和回應超時時間,這個超時時間應該小于鎖的失效時間,例如你的鎖自動失效時間為10秒,則超時時間應該在5-50毫秒之間,這樣可以避免服務器端Redis已經掛掉的情況下,客戶端還在死死地等待回應結果,如果服務器端沒有在規定時間內回應,客戶端應該盡快嘗試另外一個Redis實體,
客戶端使用當前時間減去開始獲取鎖時間(步驟1記錄的時間)就得到獲取鎖使用的時間,當且僅當從大多數(這里是3個節點)的Redis節點都取到鎖,并且使用的時間小于鎖失效時間時,鎖才算獲取成功,
如果取到了鎖,key的真正有效時間等于有效時間減去獲取鎖所使用的時間(步驟3計算的結果),
如果因為某些原因,獲取鎖失敗(沒有在至少N/2+1個Redis實體取到鎖或者取鎖時間已經超過了有效時間),客戶端應該在所有的Redis實體上進行解鎖(即便某些Redis實體根本就沒有加鎖成功),
解鎖
向所有的Redis實體發送釋放鎖命令即可,不用關心之前有沒有從Redis實體成功獲取到鎖.
總結
這次對Redis分布式鎖的探索算是加深了自己對Redis的理解,但是Redis的用處遠遠不止快取和分布式鎖,后面慢慢摸索吧,
參考:
1、還不知道 Redis 分布式鎖的背后原理?還不趕快學習一下
2、基于Redis(setnx)實作分布式鎖
3、使用Redis SETNX 命令實作分布式鎖
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/160267.html
標籤:其他
上一篇:常用RGB顏色表
