Redis 分佈式鎖在平常工做中常常用到,面試中也是高頻問題,本身在看的時候,發現對於 Redlock 理解有些誤差,主要是 Redlock 是在單實例(單集羣)仍是多實例(多集羣)下實現的。查資料的時候發現有這個問題的毫不止我一個,甚至不少人理解都是錯的還寫博客告訴別人。固然若是你已經知道了,看看我走過的彎路或許也會有些收穫。面試
在介紹 Redlock 以前,先看下通常狀況下的實現方式。redis
加鎖:算法
SET resource_name my_random_value NX PX 30000
複製代碼
解鎖:緩存
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
複製代碼
這是一段 lua 腳本,意思是:當 key 存在而且值剛好等於給定的值時,才刪除 keybash
這裏有幾個須要注意的點dom
若是是面試,當你說出是如何實現的,面試官可能就會問這種實現有什麼問題。異步
首先若是是單節點,節點一掛,鎖就沒了,等節點再重啓,別的客戶端就能夠獲取到鎖,也就是兩個客戶端都有鎖了,這就有問題了。分佈式
能夠添加一個 slave 節點,當 master 節點掛了能夠切換到 slave,可是還會有問題,由於 Redis 默認是異步進行主從同步的,好比如下場景:lua
如何解決這種問題呢,Redis 官網有一種算法實現,Redlock。spa
加鎖的過程
問題就在於,對於 N 個實例的理解,我最開始覺得能夠是集羣中的多個 master 節點,可是問題就來了,如何在同一個集羣中多個 master 設置相同的 key。
走了不少彎路,最後發現是多個實例(多集羣),也就是這些實例之間並無任何關係,這樣也能夠理解爲何能夠在每一個實例設置相同的 key 以及爲何控制多數加鎖成功的判斷須要放在客戶端了。可是在實際場景中就不大可能會使用,由於實現 Redlock 最少須要三個節點,生產環境基本都是集羣,也就是爲了加鎖就須要至少鏈接 3 個集羣。什麼狀況下一個服務會連多個 Redis 集羣呢,多級緩存?每一個 Redis 是不一樣業務的緩存?我還沒了解過。
若是這是面試官期待的基於 Redis 分佈式加鎖解決方案,我以爲這個面試官可能也理解的有點問題。
走彎路的時候也瞭解了很多新的知識
幫助中對於 -c
是這麼描述的
Enable cluster mode (follow -ASK and -MOVED redirections).
複製代碼
雖說是啓用集羣模式,但並非服務端分單機模式仍是集羣模式,只是加了 -c
會自動進行重定向。
開始沒加 -c
去請求一個不在本節點存儲的 key ,會返回重定向信息,而若是加上,會自動進行重定向。
集羣狀況下,key 屬於哪一個哈希槽是在客戶端計算的仍是服務端?
服務端確定是有的,若是隻在客戶端進行,那就至關於加了一層查詢路由,一致性須要由這一層保證,而在服務端沒有任何保證,這確定是不對的。並且像上面給出的重定向信息,說明服務端確定是計算過的。
客戶端通常也會有,只是看成緩存,每次直接選擇存放 key 的節點,而不須要頻繁的進行重定向。
通常若是是集羣的話,最開始客戶端就會創建整個集羣的拓撲,獲取每一個節點保存那些槽位,可是後續若是節點和槽位的映射關係變化了,具體的刷新策略就看每一個客戶端的實現了。