Redis基礎知識(學習筆記3--Redlock)

东山絮柳仔發表於2024-06-14

討論的問題:Redis 主從架構鎖失效(丟失)

1.背景描述

當主節點掛掉時,從節點會取而代之,但是客戶端卻沒有明顯感知。比如,原先第一個客戶端在主節點中成功申請了一把鎖,但是這把鎖還沒來得及同步到從節點,主節點突然掛掉了,然後從節點變成了主節點,這個新的主節點內部沒有這個鎖,所以當另一個客戶端傳送請求加鎖時,立即就批准了。這樣就會導致系統中同樣一把鎖被兩個客戶端同時持有,不安全性由此產生。

問題示意圖如下:

即使在Sentinel叢集下,此問題依然存在。

此問題在主從failover時才會發生,並且持續時間會很短,很多時候,對業務無明顯影響。

2. Redlock方案 Redlock實現原理

Redlock方案,需要多個Redis示例,這些示例之間相互獨立,沒有主從關係。通很多分散式演算法一樣,Redlock也使用“大多數機制”。

3.redlock-py----Realock演算法

import redlock
addrs = [{
"host" : "localhost",
"port" : 6379,
"db" : 0
}, {
"host" : "localhost",
"port" : 6479,
"db" : 0
}, {
"host" : "localhost",
"port" : 6579,
"db" : 0
}]
dlm = redlock.Redlock(addrs)
sucess = dlm.lock("user-lck", 5000)
if sucess:
  print 'lock sucess'
  dlm.unlock('user-lck')
else:
  print 'lock failed'

加鎖時,它會向過半節點傳送set(key, value, nx=True, ex=xxx) 指令,只要過半節點set成功,就認為加鎖成功。釋放鎖時,需要向所有節點傳送del指令。

生產過程,還需要考慮出錯重試、時鐘漂移等細節問題。

4.壞處

(1)需要多臺Redis例項;

(2)因為Redlock需要向多個節點進行讀寫,意味著其相比單例項Redis的效能會下降。

特別是,當某一個節點掛掉,其成功寫入的返回時間明顯加大了。這是要特別消失程式對寫入redis超時時間的設定。(即redis還在寫入,但是redis客戶端已經認為寫入超時了)。

(3)極端情況,Redis故障或重啟,可能導致鎖丟失。

例如,Redis例項 其將資料fsync到磁碟的策略為【appendfsync everysec 即每秒fsync一次】,即在故障時,可能會丟失1秒鐘資料。

此時有A例項;B例項;C例項。

client請求,將資料寫入到了A例項和B例項了,C未寫入,並且A已經fsync磁碟了,B尚未fsync到磁碟。但是很不巧,B故障了,或重啟了,那麼B的資料丟失了。

這個時候,如果有新的請求,那麼B和C可能接收-設定同樣的key,這時候,對B而言,就像前面的key沒有出現過一樣,它忘記了。此時就可能出現“超賣”的問題。

當然,在【appendfsync always: 每次有新命令追加到AOF檔案時,就執行一次fsync】,就不會出現重啟,丟命令了。但是安全程式碼的成本就是慢和高消耗。

學習參閱宣告

《Redis深度歷險--核心原理與應用實踐》

相關文章