redlock算法及其問題

背景

redlock算法是爲了解決什麼問題呢?html

在單redis實例實現分佈式鎖時,可能會出現線程A設置完鎖後,master掛掉,slave提高爲master,由於異步複製的特性,線程A設置的鎖丟失了,這時候線程B設置鎖也可以成功,致使線程A和B同時擁有鎖redis

而後redis做者提出了redlock算法算法

算法描述

  1. 得到當前時間(ms)安全

  2. 首先設置一個鎖有效時間valid_time,也就是超過這個時間後鎖自動釋放,使用相同的key和value對全部redis實例進行設置,每次連接redis實例時設置一個小於valid_time的超時時間,好比valid_time時10s,那超時時間能夠設置成50ms,若是這個實例不行,那麼換下一個設置網絡

  3. 計算獲取鎖總共佔用的時間,再加上時鐘偏移,若是這個總時間小於valid_time,而且成功設置鎖的實例數>= N/2 + 1,那麼加鎖成功異步

  4. 若是加鎖成功了,那麼這個鎖的有效時間就是valid_time - 獲取鎖佔用的時間 - 時鐘偏移分佈式

  5. 若是加鎖失敗,解鎖全部實例(每一個redis實例都運行del key)線程

問題

好了,算法看完了,給個人感受就是,好像更不靠譜了,由於引入了一個不靠譜的時間,時間誤差在分佈式系統中應該是很容易出現的吧,在鎖有效時間裏雖然減去了時鐘偏移,可是應該減多少合適呢,要是這個值設置很差,很容易出現問題htm

先不提這個,咱們回顧一下單redis實例的問題,主從切換時可能會有兩個線程佔有鎖,那麼redlock有沒有這個問題呢get

假設咱們有5個redis實例a,b,c,d,e,線程A分別加鎖,而後a,b,c加鎖成功,由於網絡分區問題,d,e失敗。同時,線程B也加鎖,由於網絡分區問題,a,b加鎖失敗,可是d,e加鎖成功。這時候,顯然線程A會得到鎖,可是若是這時候c的master掛了,而後切換成了slave,slave中沒有A加鎖的信息,恰巧這時線程B對c加鎖的命令到了,那線程B就會加鎖成功,這時候,線程A和B都給三個節點加鎖成功了,他們同時擁有鎖。因此我認爲redlock仍然沒有解決這個問題,只是讓這個問題更不容易發生了,這裏若是我想錯的話歡迎指正

另外,redis做者也對這個算法進行了分析,建議對鎖互斥的安全性要求高的應用不要使用這個算法,分析了GC停頓,page fault,clock jump等等對時間產生的影響,能夠參考http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

相關文章
相關標籤/搜索