redis相关知识记录整理
一、分布式鎖的作用:
同一時間只允許一個用戶操作,
一般情況下,我們使用分布式鎖主要有兩個場景:
二、分布式鎖的實現(xiàn)方式
三、redis分布式鎖的問題
(1)鎖超時:
假設(shè)現(xiàn)在我們有兩臺平行的服務(wù) A B,其中 A 服務(wù)在?獲取鎖之后?突然?掛了,那么 B 服務(wù)就永遠(yuǎn)無法獲取到鎖了:
如果在加鎖和釋放鎖之間的邏輯執(zhí)行得太長,以至于超出了鎖的超時限制,也會出現(xiàn)問題。因為這時候第一個線程持有鎖過期了,而臨界區(qū)的邏輯還沒有執(zhí)行完,與此同時第二個線程就提前擁有了這把鎖,導(dǎo)致臨界區(qū)的代碼不能得到嚴(yán)格的串行執(zhí)行。因此Redis 分布式鎖不要用于較長時間的任務(wù)
GC可能引發(fā)的問題:服務(wù) A 獲取了鎖并設(shè)置了超時時間,但是服務(wù) A 出現(xiàn)了 STW 且時間較長,導(dǎo)致了分布式鎖進(jìn)行了超時釋放,在這個期間服務(wù) B 獲取到了鎖,待服務(wù) A STW 結(jié)束之后又恢復(fù)了鎖,這就導(dǎo)致了?服務(wù) A 和服務(wù) B 同時獲取到了鎖,這個時候分布式鎖就不安全了。
(2)單點和多點宕機(jī)問題對分布式鎖的影響:
如果 Redis 采用單機(jī)部署模式也就是單點鎖,那就意味著當(dāng) Redis 故障了,就會導(dǎo)致整個服務(wù)不可用。
而如果采用主從模式部署,我們想象一個這樣的場景:服務(wù) A?申請到一把鎖之后,如果作為主機(jī)的 Redis 宕機(jī)了,那么?服務(wù) B?在申請鎖的時候就會從 從機(jī)那里獲取到這把鎖,從而導(dǎo)致服務(wù)AB同時獲取了鎖,為了解決這個問題,Redis 作者提出了一種?RedLock 紅鎖?的算法?(Redission 同 Jedis)
四、redLock紅鎖
一種基于 Redis 實現(xiàn)分布式鎖的方式。
比原先的單節(jié)點的方法更安全。它可以保證以下特性:
redlock算法:
假設(shè)有5個完全獨立的redis主服務(wù)器,為了獲得鎖,client 會進(jìn)行如下操作
1.獲取當(dāng)前時間戳
2.client嘗試順序的使用相同的key,value申請所有redis服務(wù)的鎖,在獲取鎖的過程中的獲取時間比鎖過期時間timeout短很多,是為了不要過長時間的等待已經(jīng)關(guān)閉的redis服務(wù)。并且試著獲取下一個redis實例。
? ?比如:timeout為5s,設(shè)置獲取鎖最多用1s,所以如果一秒內(nèi)無法獲取鎖,就放棄獲取這個鎖,從而嘗試獲取下個鎖
3.當(dāng) client 在大于等于 3 個 master 上成功申請到鎖的時候,會計算申請鎖消耗了多少時間,這部分消耗的時間采用獲得鎖的當(dāng)下時間戳減去第一步獲得的時間戳得到,如果申請花費的時間小于timeout的時間,那么鎖就真正獲取到了。
4.如果成功獲取鎖,則鎖的真正有效時間是 timeout時間減去申請鎖花費的時間;比如:timeout是5s,獲取所有鎖用了2s,則真正鎖有效時間為3s(其實應(yīng)該再減去時鐘漂移);
5.如果 client 申請分布式鎖失敗了,那么它就會在少部分申請成功鎖的 master 節(jié)點上執(zhí)行釋放鎖的操作,重置狀態(tài)
6.失敗重試:如果一個 client 申請鎖失敗了,那么它需要稍等一會再重試避免多個 client 同時申請鎖的情況,另外就是如果 client 申請鎖失敗了它需要盡快在它曾經(jīng)申請到鎖的 master 上執(zhí)行 unlock 操作,便于其他 client 獲得這把鎖,避免這些鎖過期造成的時間浪費
7.崩潰恢復(fù):如果我們的節(jié)點沒有持久化機(jī)制,client 從 5 個 master 中的 3 個處獲得了鎖,然后其中一個重啟了,這是注意?整個環(huán)境中又出現(xiàn)了 3 個 master 可供另一個 client 申請同一把鎖!?違反了互斥性。
如果我們開啟了 AOF 持久化那么情況會稍微好轉(zhuǎn)一些,因為 Redis 的過期機(jī)制是語義層面實現(xiàn)的,所以在 server 掛了的時候時間依舊在流逝,重啟之后鎖狀態(tài)不會受到污染。但是考慮斷電之后呢,AOF部分命令沒來得及刷回磁盤直接丟失了,除非我們配置刷回策略為 fsnyc = always,但這會損傷性能。
解決這個問題的方法是,當(dāng)一個節(jié)點重啟之后,我們規(guī)定在 max timeout期間它是不可用的(不可以被獲取鎖的),這樣它就不會干擾原本已經(jīng)申請到的鎖,等到它 crash 前的那部分鎖都過期了,環(huán)境不存在歷史鎖了,那么再把這個節(jié)點加進(jìn)來正常工作。
?
總結(jié)
以上是生活随笔為你收集整理的redis相关知识记录整理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360笔试第一题----最强的不一定是最
- 下一篇: 项目难点总结