原文地址html
上週花了點時間研究了 Redis 的做者提的 RedLock 的算法來實現一個分佈式鎖,文章地址。在官方的文檔最下面發現了這樣一句話。redis
Analysis of RedLock
Martin Kleppmann analyzed Redlock here. I disagree with the analysis and posted my reply to his analysis here.算法
忽然以爲事情好像沒有那麼簡單,就點進去看了看。仔細讀了讀文章,發現了一個不得了的世界。因而靜下心來研究了 Martin 對 RedLock 的批評,還有 RedLock 做者 antirez 的反擊。編程
Martin上來就問,咱們要鎖來幹啥呢?兩個緣由:安全
對於第一種緣由,咱們對鎖是有必定寬容度的,就算髮生了兩個節點同時工做,對系統的影響也僅僅是多付出了一些計算的成本,沒什麼額外的影響。這個時候 使用單點的 Redis 就能很好的解決問題,沒有必要使用RedLock,維護那麼多的Redis實例,提高系統的維護成本。服務器
對於第二種緣由,對正確性嚴格要求的場景(好比訂單,或者消費),就算使用了 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 認爲,首先在實際的系統中,從兩個方面來看:
對於第一個問題。上文已經提到了,RedLock作了一些微小的工做,可是沒辦法徹底避免。其餘帶有自動釋放的分佈式鎖也沒有辦法。
第二個問題,Martin認爲系統時間的階躍主要來自兩個方面:
對於人爲修改,能說啥呢?人要搞破壞沒辦法避免。
NTP受到一個階躍時鐘更新,對於這個問題,須要經過運維來保證。須要將階躍的時間更新到服務器的時候,應當採起小步快跑的方式。屢次修改,每次更新時間儘可能小。**
說個題外話,讀到這裏我忽然理解了運維同窗的郵件:
因此嚴格來講確實, RedLock創建在了 Time 是可信的模型上,理論上 Time 也是發生錯誤,可是在現實中,良好的運維和工程一些機制是能夠最大限度的保證 Time 可信。
最後, antirez 還打出了一個暴擊,既然 Martin 提出的系統使用 fecting token 保證數據的順序處理。還須要 RedLock,或者別的分佈式鎖 幹啥??
看完二人的博客來往,感受就是看武俠戲裏面的高手過招,至關得爽快。二人思路清晰,Martin 上來就看到RedLock的死穴,一頓猛打,antirez見招拆招成功化解。
至於二人誰對誰錯?
我以爲,每個系統設計都有本身的側重或者侷限。工程也不是完美的。在現實中工程中不存在完美的解決方案。咱們應當深刻了解其中的原理,瞭解解決方案的優缺點。明白選用方案的侷限性。是否能夠接受方案的侷限帶來的後果。
架構原本就是一門平衡的藝術。
Martin 推薦使用ZooKeeper 實現分佈事務鎖。Zookeeper 和 Redis的鎖有什麼區別? Zookeeper解決了Redis沒有解決的問題了麼?且聽下回分解。