分散式鎖為什麼要選擇Zookeeper而不是Redis?

宇的季節發表於2021-05-21

在分散式的應用中,為了防止單點故障,保障高可用,通常會採用主從結構,當主節點掛掉後,從節點可以代替主節點提供服務。

Redis通過複製 + sentinel哨兵來實現主從模式。

Zookeeper通過replicated mode複製模式來實現主從模式。

單從結構上看,Redis和Zookeeper都是主從架構,那Zookeeper的優勢是什麼?為什麼要選擇Zookeeper?難道只是因為Zookeeper是目錄結構,Redis是K-V結構嗎?

同步機制的不同

Redis

Redis在給從節點同步資料時,正常情況是增量同步,也就是主節點的資料修改語句(DML)會非同步的同步給從節點。Redis的資料同步沒有保障資料一致性的機制,也就是說,一條DML在主節點執行成功時,不能保障其他從節點成功執行了這條資料,這就會造成一個問題,如果在資料沒有同步到從節點時,主節點掛掉,就會產生資料丟失的情況。

Zookeeper

Zookeeper使用類paxos演算法來保障資料的一致性。簡單的講,當一個DML語句傳送給主節點時,Zookeeper需要保證一半以上的節點接收到資料,才會返回成功。並且當主節點掛掉,從節點重新選舉時,同步到最新的資料的節點會有優先選舉權。

舉個例子:

一個4節點Zookeeper(A、B、C、D),A是主節點,當執行一個create語句成功時,至少有3臺節點執行成功(一半以上),例如A、C、D成功。此時如果A節點掛了,B、C、D進行選舉,由於C、D都執行成功了create語句,B沒有執行,C、D的資料更加新,具有優先選舉權,再根據名稱排序,選擇C做為主節點。在整個選舉過程中,服務不可用,選舉完成後,C節點和A節點資料一致,不會出現丟失的情況。

分散式鎖

要實現分散式鎖,需要滿足一些要求:

  1. 只能有一個服務的一個執行緒能獲取鎖
  2. 一個持有鎖的執行緒掛掉後,鎖應該被釋放,用來給其他執行緒用
  3. 一個持有鎖的執行緒沒執行完,鎖不能釋放
  4. 鎖釋放後,其他等待者可以繼續爭搶
  5. 管理鎖的主節點(Redis或Zookeeper)掛了,重新選舉後,不影響鎖的持有情況

Redis解決方案

問題1、問題2:使用“SET key value EX seconds NX”語句獲取鎖並設定過期時間

問題3:另開一個監控執行緒,監控主執行緒執行情況,用來延長過期時間

問題4:等待執行緒定時檢查鎖的持有情況

問題5:暫無或者解決成本很高,需要自己實現類paxos的演算法

Zookeeper解決方案

通過建立臨時節點可以解決問題1,2,3

watch機制可以解決問題4,並且相比定時檢查,watch可以做到更高實時性

zookeeper的paxos同步機制保障了節點間資料一致性,即使主節點掛掉,也可以保障資料不丟,可以解決問題5

對比可以發現:

Zookeeper的機制可以保證分散式鎖實現業務程式碼簡單,成本低。

Redis如果要解決分散式鎖的問題,對於一些複雜的情況,很難解決,成本較高。

相關文章