內容簡介:Martin上來就問,咱們要鎖來幹啥呢?2個緣由:對於第1種緣由,咱們對鎖是有必定寬容度的,就算髮生了兩個節點同時工做,對系統的影響也僅僅是多付出了一些計算的成本,沒什麼額外的影響。這個時候 使用對於第2種緣由,對正確性嚴格要求的場景(好比訂單,或者消費),就算使用了 RedLock 算法仍然html
Martin上來就問,咱們要鎖來幹啥呢?2個緣由:redis
對於第1種緣由,咱們對鎖是有必定寬容度的,就算髮生了兩個節點同時工做,對系統的影響也僅僅是多付出了一些計算的成本,沒什麼額外的影響。這個時候 使用 單點的 Redis 就能很好的解決問題,沒有必要使用RedLock,維護那麼多的 Redis 實例,提高系統的維護成本。算法
對於第2種緣由,對正確性嚴格要求的場景(好比訂單,或者消費),就算使用了 RedLock 算法仍然 不能保證鎖的正確性 。編程
咱們分析一下 RedLock 的有啥缺陷吧:安全
做者 Martin 給出這張圖,首先咱們上一講說過,RedLock中,爲了防止死鎖,鎖是具備過時時間的。這個過時時間被 Martin 抓住了小辮子。服務器
這還了得,數據就發生了錯誤。RedLock 只是保證了鎖的高可用性,並無保證鎖的正確性。網絡
這個時候也許你會說,若是 Client 1 在提交任務以前去查詢一下鎖的持有者是不本身就能解決這個問題?架構
答案是否認的,FGC 會發生在任什麼時候候,若是 FGC 發生在查詢以後,同樣會有如上討論的問題。運維
那換一個沒有 GC 的編程語言?異步
答案仍是否認的, FGC 只是形成系統停頓的緣由之一,IO或者網絡的堵塞或波動均可能形成系統停頓。
Martin給出了一個解決的方案:
爲鎖增長一個 token-fencing。
咱們其實能夠理解這個 token-fencing 就是一個樂觀鎖,或者一個 CAS。
Martin 還指出了,RedLock 是一個 嚴重依賴系統時鐘 的分佈式系統。
仍是這個過時時間的小辮子。若是某個 Redis Master的系統時間發生了錯誤,形成了它持有的鎖提早過時被釋放。
這個時候 Martin 又提出了一個至關重要的關於分佈式系統的設計要點:
好的分佈式系統應當是異步的,且不能時間做爲安全保障的。由於在分佈式系統中有會程序暫停,網絡延遲,系統時間錯誤,這些因數都不能影響分佈式系統的安全性,只能影響系統的活性(liveness property)。換句話說,就是在極端狀況下, 分佈式系統頂多在有限的時間內不能給出結果,可是不能給出錯誤的結果 。
因此總結一下 Martin 對 RedLock 的批評:
這個時候感受醍醐灌頂,簡直寫的太好了。
RedLock 的做者,同時也Redis 的做者對 Martin的文章也作了迴應,條理也是至關的清楚。
antirez 看到了 Martin 的文章之後,就寫了一篇文章回應。劇情會不會反轉呢?
antirez 總結了 Martin 對 RedLock的指控:
對於第一個問題:
antirez 洋洋灑灑的寫了不少,仔細看半天,也沒有解決我心中的疑問。回顧一下RedLock 獲取鎖的步驟:
若是,程序在1-3步之間發生了阻塞,RedLock能夠感知到鎖已通過期,沒有問題。
若是,程序在第 4 步以後發生了阻塞?怎麼辦???
答案是,其餘 具備自動釋放鎖的分佈式鎖都沒辦解決這個問題 。
對於第二個質疑:
antirez 認爲,首先在實際的系統中,從兩個方面來看:
對於第1個問題。上文已經提到了,RedLock作了一些微小的工做,可是沒辦法徹底避免。其餘帶有自動釋放的分佈式鎖也沒有辦法。
第2個問題,Martin認爲系統時間的階躍主要來自兩個方面:
對於人爲修改,能說啥呢?人要搞破壞沒辦法避免。
NTP受到一個階躍時鐘更新,對於這個問題,須要經過運維來保證。須要將階躍的時間更新到 服務器 的時候,應當採起小步快跑的方式。屢次修改,每次更新時間儘可能小。
因此嚴格來講確實, RedLock創建在了 Time 是可信的模型上,理論上 Time 也是發生錯誤,可是在現實中,良好的運維和工程一些機制是能夠最大限度的保證 Time 可信。
最後, antirez 還打出了一個暴擊,既然 Martin 提出的系統使用 fecting token 保證數據的順序處理。還須要 RedLock,或者別的分佈式鎖幹啥??
每個系統設計都有本身的側重或者侷限。工程也不是完美的。在現實中工程中不存在完美的解決方案。咱們應當深刻了解其中的原理,瞭解解決方案的優缺點。明白選用方案的侷限性。是否能夠接受方案的侷限帶來的後果。
架構原本就是一門平衡的藝術。
簡單來講,單實例Redis能解決大部分的分佈式鎖需求。Redlock的引入意義不大,若是對可用性要求更高的話,使用其餘方案也許是更好的選擇。