Zookeeper總結

概念簡述

  • 分佈式系統協調服務的中間件
  • 能夠基於Zookeeper實現發佈/訂閱、負載均衡、分佈式協調/通知、master選舉、分佈式鎖、分佈式隊列等

簡單說下分佈式系統特色

  • 多臺計算機組成一個總體,一個總體一致對外而且處理同一請求
  • 內部的每臺計算機均可以互相通訊(REST/RPC)
  • 客戶端到服務端的一次請求到響應結束會經歷多臺計算機

特性

  • 順序一致性:客戶端的更新將按發送順序應用
  • 原子性:事務要麼所有成功,要麼所有失敗
  • 單一視圖:客戶端鏈接集羣中的任一Zookeeper節點,數據都是一致的
  • 可靠性:每次對Zookeeper的操做狀態都會保存在服務端,一旦應用了更新,它將從那時起持續到客戶端覆蓋更新
  • 實時性:客戶端能夠讀取到Zookeeper服務端的最新數據

Zookeeper結構模型

Zookeeper的數據保存在內存中。Zookeeper容許分佈式進程經過共享的層次結構命名空間進行相互協調,層次結構命名空間由ZooKeeper中的數據寄存器——Znode組成,Znode相似於文件和目錄。node

  • 樹型結構,相似linux的目錄結構或HTML
  • 每一個Zookeeper節點都有各自的版本號,每當節點數據變化,該節點的版本號會累加
  • 每一個Zookeeper節點存儲的數據不宜過大,幾kb便可
  • 節點能夠設置權限來限制訪問

ZNode(數據節點)結構

每一個ZNode由兩部分組成:linux

  • stat:狀態信息;包括一個數據節點的全部狀態信息,包括事務ID、版本信息和子節點個數等。
  • data:數據內容

node模型,父node會有多個子node服務器

image.png

節點類型

  • 持久節點

    節點建立後就一直存在,直到有刪除操做來主動清除這個節點,不會隨會話失效而消失。session

  • 臨時節點

    節點生命週期和客戶端會話綁定。客戶端會話失效(是會話失效,不是鏈接斷開)時,節點消失。數據結構

  • 順序節點

    不是一種類型,持久和臨時節點都會有順序節點,每一個Zookeeper的父節點會記錄子節點的建立前後順序,在建立的時候自動給子節點的節點名加上一個數字後綴。數字範圍是整型最大值。架構

watch機制

針對每一個節點的增刪改操做,Zookeeper能夠根據watcher事件進行監控,當監控的某個znode發生變化,就會觸發watch事件。Zookeeper的watch都是一次性的,觸發後當即銷燬。併發

Zookeeper的協調機制

其實就是session工做原理負載均衡

  • 客戶端和服務端鏈接會話,每一個會話都會設置一個超時時間
  • 客戶端和服務端經過心跳機制(客戶端向服務端的ping包請求) 保持通訊,心跳session過時,臨時節點則被拋棄

Zookeeper集羣角色

  • leader分佈式

    • 一個Zookeeper集羣同一時間只有一個實際工做的leader,他會維護與Follower和Observer的心跳
    • 執行讀和寫操做
    • 只有leader能執行寫操做,全部寫操做都須要由leader將寫操做廣播給其餘服務器
  • follower性能

    • 響應leader心跳
    • 處理並返回客戶端讀請求,將客戶端寫請求轉發給leader處理
    • 在leader處理寫請求時,參與選舉
  • observer

    • 響應leader心跳
    • 處理並返回客戶端讀請求,放大查詢能力
    • 不參與選舉
要保證leader選舉快,就要保證follower節點可控且儘可能少

可靠性

Zookeeper經過ZAB協議保證數據最終一致性。

Paxos協議

Paxos:https://www.douban.com/note/208430424/(寫得好,就懶得再總結了,直接看)

ZAB協議

Zookeeper經過ZAB(Zookeeper Atomic Broadcast 原子廣播)這個支持崩潰恢復的一致性協議來維護數據一致性。經過這個協議,Zookeeper實現了一種主從模式的架構來保證各個副本之間的數據一致。

ZAB協議主要包括兩點:

  • 全部寫操做必須經過Leader完成,Leader寫入本地日誌後再複製到全部Follower,observer節點
  • 一旦Leader節點沒法工做,ZAB會自動從Follower節點從新選舉出一個Leader

    ZAB兩階段提交
    好處是保證提交過的數據不會丟失。由於提交過的數據都是半數經過的,即便leader服務器宕機也至少有一半以上的服務器保存有數據。
    • follower/observer節點收到客戶端的寫請求,將寫請求轉發給leader節點(若是是leader節點直接收到寫請求則忽略此步驟)
    • leader節點收到客戶端的寫請求,先將寫請求以Proposal的形式發給follower,等待回覆
    • follower收到proposal後返回ACK給leader
    • leader收到超過半數的ACK回覆(leader節點會默認給本身一個ACK),則發送commit指令給follower和Observer節點
  • follower/observer節點收到後處理寫請求,再回復leader節點

    • leader將處理結果返回客戶端

image.png

##### 消息廣播和崩潰恢復

*   消息廣播
    
    過半服務器和Leader服務器完成數據狀態同步後,就進入消息廣播模式。當一臺遵循ZAB協議的服務器加入集羣,當發現有Leader服務器後,就自動進入數據恢復模式,和Leader服務器進行數據同步,同步完成後再參與到消息廣播去
    
    Leader服務器接收到客戶端的事務請求,會生成對應事務方案,發起一次消息廣播。當從服務器接收到客戶端事務請求,會將請求轉發給Leader服務器
    
*   崩潰恢復
    
    當Leader服務器出現異常狀況,則進入恢復模式,從新選舉Leader服務器,當過半機器和Leader服務器完成數據狀態同步以後,就退出恢復模式。服務器在成爲Leader後,先判斷自身未Commit的消息(是否存在於大多數服務器中從而決定是否要將其Commit
    
*   小結
    
    *   因爲使用主從複製模式,全部寫操做都由Leader主導,而讀操做可經過任意節點完成,所以Zookeeper讀性能好於寫性能,適合讀多寫少的場景;
        
    *   雖然使用主從,同一時間只有一個Leader,但Failover機制保證了集羣不存在單點失敗(SPOF)的問題;
        
    *   ZAB協議保證了Failover(崩潰恢復)過程當中的數據一致性;
        
    *   服務器收到數據後先寫本地文件再進行處理,保證了數據的持久性

Zookeeper選舉

一些概念
  • myid

    每一個Zookeeper服務器的惟一標識。

  • zxid

    事務ID,用於標識一次更新操做的 Proposal ID。爲了保證proposal順序行,zxid必須單調遞增。

    Zookeeper使用一個64位數來表示,高32位是leader的epoch,從1開始,每次選出新的Leader,epoch加一。低32位位該epoch內的序號,每次epoch變化,都將低32位的序號重置。保證了zxid的全局遞增性。

  • 服務器狀態

    LOOKING、FOLLOWING、LEADING、OBSERVING

  • 選票數據結構

    • logicClock:每一個服務器會維護一個自增整數,表示該服務器發起的第幾輪投票
    • state:當前服務器狀態
    • self_id:當前服務器的myid
    • self_zxid:當前服務器保存數據的最大zxid
    • vote_id:被推舉的服務器的myid
    • vote_zxid:被推舉的服務器上所保存的數據的最大zxid
  • 投票流程

    • 自增選舉輪次

      Zookeeper規定全部有效的投票都必須在同一輪次中。每一個服務器在開始新一輪投票是,會先對本身維護的logicClock進行自增

    • 初始化選票

      廣播投票前服務器會現將本身的投票箱清空

    • 發送初始化選票

      每一個服務器最開始都是經過廣播把票投給本身

    • 接收外部選票

      服務器會嘗試從其餘服務器獲取投票,並計入本身的投票箱。

    • 判斷選舉輪次

      • 若是外部投票的logicClock大於本身的,則說明該服務器選舉輪次落後了,服務器會當即清空本身的投票箱並將本身的logicClock更新爲收到的logicClock,再對比本身以前的投票和收到的投票以肯定是否須要變動本身的投票,最終再次將本身的投票廣播出去。
      • 外部投票的logicClock小於本身的,服務器直接忽略,處理下一個投票
      • logicClock相等,選票PK
    • 選票PK

      • 先比較zxid,若收到的票zxid較大,將本身票中的vote_zxid與vote_myid更新爲zxid比較大的;並將收到的票及本身更新後的票放入本身的票箱
      • zxid相同,比較myid,若是收到的票myid大,將vote_myid更新爲較大的並廣播出去,將收到的票及本身更新後的票放入本身的票箱
    • 統計選票

      若是已經肯定有過半服務器承認了本身的投票(也多是更新後的投票),則終止投票,不然繼續接受其餘服務器的投票

    • 更新服務器狀態

      更新服務器狀態爲LEADING或者FOLLOWING

集羣初始化時的選舉

image

Follower崩潰後的選舉

image.png

leader崩潰後的選舉(不想畫圖了。。)
  • 從新選舉出Leader
  • 老Leader恢復後成爲Follower

Zookeeper相關應用:

配置中心

註冊中心

Zookeeper實現分佈式鎖

Zookeeper實現分佈式鎖原理就是Watch機制+臨時順序節點

頭腦風暴
  1. 爭搶鎖,只有一我的能得到鎖?leader節點只有一個,建立leader節點成功的獲取鎖。
  2. 得到鎖的人出問題,死鎖問題?臨時節點(session)
  3. 得到鎖的人成功了,要釋放鎖?主動放棄領導權
  4. 鎖被釋放、刪除,別人怎麼知道的?

    4-1 主動輪詢,心跳?弊端:延遲,壓力

    4-2 watch: 解決延遲問題。 弊端:壓力

    4-3 多個watch同時觸發,負載壓力?順序節點,watch前一個(按序列順序依次watch前一個),最小的得到鎖!成本:一旦最小的釋放了鎖,Zookeeper只給第二個發事件回調,資源消耗壓力小

非公平鎖實現(實現有弊端)
  1. 多個客戶端發起建立leader節點請求,爭搶到的客戶端建立leader節點,得到鎖
  2. 沒有建立成功的客戶端成爲follower節點,併發起一個watch監聽leader節點
  3. 當客戶端釋放鎖時,leader主動放棄領導權,直接刪除leader節點;當leader進程宕機,與Zookeeper之間的session結束,leader節點也會被刪除
  4. 當leader節點被刪除,watch觸發,剩下的客戶端開始競爭建立節點,重複步驟一
  5. 小結

    Zookeeper寫性能不高,若是有上萬個客戶端參與鎖競爭,就會有上萬個寫請求(建立leader節點)發送給Zookeeper,Zookeeper集羣負載壓力過大;

    當釋放鎖,leader主動放棄領導權時,又會觸發watch,須要給每一個客戶端進行通知,負載壓力過大

公平鎖實現
  1. 客戶端都建立/Zookeeperroot/leader節點
  2. 因爲是順序節點,每一個客戶端都能建立成功,每一個客戶端會判斷本身是否是最小序列的節點,是則成爲leader,不是則成爲follower節點
  3. 當客戶端釋放鎖時,leader主動放棄領導權,直接刪除leader節點;當leader進程宕機,與Zookeeper之間的session結束,leader節點也會被刪除
  4. 公平鎖實現時,每一個follower節點只須要wacth比它前一個序列的節點便可。當leader節點被刪除,只有後一個follower節點獲得通知,而後成爲leader節點。
  5. 當leader節點沒有放棄領導權,其中有其它客戶端宕機致使該follower節點不可用時,宕機節點的後一個節點不會直接成爲leader節點,它會判斷本身是否是最小的節點,若是不是,則watch前一個序列節點;若是是,則成爲leader節點。
相關文章
相關標籤/搜索