Redis分佈式鎖的N種姿勢

Redis幾種架構
Redis發展到現在,幾種常見的部署架構有:
  • 單機模式;
  • 主從模式;
  • 哨兵模式;
  • 集羣模式;
我們首先基於這些架構講解Redisson普通分佈式鎖實現,需要注意的是,只有充分了解普通分佈式鎖是如何實現的,才能更好的瞭解Redlock分佈式鎖的實現,因爲Redlock分佈式鎖的實現完全基於普通分佈式鎖。
普通分佈式鎖
Redis普通分佈式鎖原理這個大家基本上都瞭解,本文不打算再過多的介紹,上一篇文章《Redis分佈式鎖最牛逼的實現》也講的很細,並且也說到了幾個重要的注意點。如果你對Redis普通的分佈式鎖還有一些疑問,可以再回顧一下這篇文章。
接下來直接show you the code,畢竟 talk is cheap。
  • redisson版本
本次測試選擇redisson 2.14.1版本。
單機模式
源碼如下:


 

通過代碼可知,經過Redisson的封裝,實現Redis分佈式鎖非常方便,我們再看一下Redis中的value是啥,和前文分析一樣,hash結構,key就是資源名稱,field就是UUID+threadId,value就是重入值,在分佈式鎖時,這個值爲1(Redisson還可以實現重入鎖,那麼這個值就取決於重入次數了):

172.29.1.180:5379> hgetall DISLOCK
1) "01a6d806-d282-4715-9bec-f51b9aa98110:1"
2) "1"

哨兵模式
即sentinel模式,實現代碼和單機模式幾乎一樣,唯一的不同就是Config的構造:
[Java] 純文本查看 複製代碼
1
2
3
4
5
Config config = new Config();
config.useSentinelServers().addSentinelAddress(
"redis://172.29.3.245:26378","redis://172.29.3.245:26379", "redis://172.29.3.245:26380")
.setMasterName("mymaster")
.setPassword("a123456").setDatabase(0);

 

集羣模式
集羣模式構造Config如下:
[Java] 純文本查看 複製代碼
1
2
3
4
5
Config config = new Config();
config.useClusterServers().addNodeAddress(
"redis://172.29.3.245:6375","redis://172.29.3.245:6376", "redis://172.29.3.245:6377",
"redis://172.29.3.245:6378","redis://172.29.3.245:6379", "redis://172.29.3.245:6380")
.setPassword("a123456").setScanInterval(5000);

 

總結
普通分佈式實現非常簡單,無論是那種架構,向Redis通過EVAL命令執行LUA腳本即可。
Redlock分佈式鎖
那麼Redlock分佈式鎖如何實現呢?以單機模式Redis架構爲例,直接看實現代碼:


 

最核心的變化就是RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);,因爲我這裏是以三個節點爲例。
那麼如果是哨兵模式呢?需要搭建3個,或者5個sentinel模式集羣(具體多少個,取決於你)。
那麼如果是集羣模式呢?需要搭建3個,或者5個cluster模式集羣(具體多少個,取決於你)。
實現原理
既然核心變化是使用了RedissonRedLock,那麼我們看一下它的源碼有什麼不同。這個類是RedissonMultiLock的子類,所以調用tryLock方法時,事實上調用了RedissonMultiLock的tryLock方法,精簡源碼如下:


 

很明顯,這段源碼就是上一篇文章《Redlock:Redis分佈式鎖最牛逼的實現》提到的Redlock算法的完全實現。
以sentinel模式架構爲例,如下圖所示,有sentinel-1,sentinel-2,sentinel-3總計3個sentinel模式集羣,如果要獲取分佈式鎖,那麼需要向這3個sentinel集羣通過EVAL命令執行LUA腳本,需要3/2+1=2,即至少2個sentinel集羣響應成功,纔算成功的以Redlock算法獲取到分佈式鎖:


 

Redlock分佈式鎖
問題合集


 

根據上面實現原理的分析,這位同學應該是對Redlock算法實現有一點點誤解,假設我們用5個節點實現Redlock算法的分佈式鎖。那麼要麼是5個redis單實例,要麼是5個sentinel集羣,要麼是5個cluster集羣。而不是一個有5個主節點的cluster集羣,然後向每個節點通過EVAL命令執行LUA腳本嘗試獲取分佈式鎖,如上圖所示。
  • 失效時間如何設置

 

這個問題的場景是,假設設置失效時間10秒,如果由於某些原因導致10秒還沒執行完任務,這時候鎖自動失效,導致其他線程也會拿到分佈式鎖。
這確實是Redis分佈式最大的問題,不管是普通分佈式鎖,還是Redlock算法分佈式鎖,都沒有解決這個問題。也有一些文章提出了對失效時間續租,即延長失效時間,很明顯這又提升了分佈式鎖的複雜度。另外就筆者瞭解,沒有現成的框架有實現,如果有哪位知道,可以告訴我,萬分感謝。
  • redis分佈式鎖的高可用

 

關於Redis分佈式鎖的安全性問題,在分佈式系統專家Martin Kleppmann和Redis的作者antirez之間已經發生過一場爭論。有興趣的同學,搜索"基於Redis的分佈式鎖到底安全嗎"就能得到你想要的答案,需要注意的是,有上下兩篇(這應該就是傳說中的神仙打架吧,哈)。
  • zookeeper or redis

 

沒有絕對的好壞,只有更適合自己的業務。就性能而言,redis很明顯優於zookeeper;就分佈式鎖實現的健壯性而言,zookeeper很明顯優於redis。如何選擇,取決於你的業務!

更多免費技術資料可關注:annalin1203

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章