zookeeper淺析

概述

ZooKeeper是一個分佈式的,開源的分佈式應用程序協調服務,它包含一個簡單的原語集,屬於Apache的頂級項目,能夠基於它實現服務發現,配置維護,集羣管理和分佈式鎖等。node

架構

zookeeper淺析
經過架構圖咱們看到zookeeper主要有以下四種角色:緩存

  • Leader:處理讀寫請求,處理與Follower的心跳檢測,並以事務的方式處理與Follower和Observer的數據同步
  • Follower:直接處理讀請求,對於寫請求轉發給 Leader,Leader選舉中參與競爭和投票,與Leader維持數據同步
  • Observer:直接處理讀請求,對於寫請求轉發給 Leader,Leader選舉中不參與投票,與Leader維持數據同步
  • Client:請求發起者

概念

  1. znode
    zk中數據都存儲在znode中,一個znode節點能夠包含子znode同時也能夠包含數據,每一個znode都有一個惟一的訪問路徑。znode主要有以下四種類型:
    • PERSISTENT-持久化目錄節點
      客戶端與zookeeper斷開鏈接後,該節點依舊存在
    • PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
      客戶端與zookeeper斷開鏈接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
    • EPHEMERAL-臨時目錄節點
      客戶端與zookeeper斷開鏈接後,該節點被刪除
    • EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
      客戶端與zookeeper斷開鏈接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
  2. session
    session是zookeeper中會話的實例載體,一個session則是指代一個客戶端會話。一個會話必須包含如下幾個基本的屬性:
    • sessionID : 會話的ID,用來惟一標識一個會話,每一次客戶端創建鏈接的時候,zookeeper服務端都會給其分配一個全局惟一的sessionID
    • timeOut:一次會話的超時時間,客戶端在構造zookeeper實例的時候,會配置一個sessionTimeOut參數用於指定會話的超時的時間。zookeeper服務端會按照鏈接的客戶端發來的timeOut參數來計算並肯定超時的時間
    • tickTime:下一次會話超時的時間點,爲了方便zookeeper對會話進行所謂的分桶策略進行管理,同時也能夠實現高效的對會話的一個檢查和清理。tickTime是一個13位的Long類型的數值,通常狀況下這個值接近timeOut,可是並不徹底相等
    • isCloseing:用來標記當前會話是否已經處於被關閉的狀態。若是服務端檢測到當前會話的超時時間已經到了,就會將isCloseing屬性標記爲已經關閉,這樣之後即便再有這個會話的請求訪問也不會被處理
  3. watch
    用戶能夠對一個znode設置watch,當這個znode發生了變化時,例如建立、刪除、數據變動、添加或移除子節點,watch API就會發出通知。可是,zookeeper的 watch有一個缺點,就是這個watch只能被觸發一次,一旦發出了通知,若是還想對這個節點繼續watch,用戶須要從新設置watch。
  4. zxid
    leader 服務器在接收到事務請求後,會爲每一個事務請求生成對應的 proposal 來進行廣播,而且在廣播事務 proposal 以前,leader 服務器會首先爲這個事務 proposal 分配一個全局單調遞增的惟一 ID ,咱們稱之爲zxid。zxid就是zk中的事務編號,是一個8字節的整型數字,一共有64位長度,前32位用來記錄epoch,後32位就是用來計數。每一次寫請求都會增長後32位,每一次leader選舉會增長前32位,每次增長都是+1。
  5. myid
    啓動配置zoo.cfg中有一項 dataDir 指定了數據存放的路徑,在此路徑下新建一個文本文件,命名爲myid, 文本內容就是一個數字,這個數字就是當前節點的myid,用來惟一標識一個節點。
  6. 節點的狀態
    在zab協議中,是經過自身的狀態來區分本身的角色的。在組成zab協議的全部進程啓動的時候,初始化狀態都是 LOOKING 狀態,此時進程組中不存在leader,選舉以後纔有,在進行選舉成功後,就進入消息廣播模式,此時 zookeeper 集羣中的角色狀態就再也不是 LOOKING 狀態。在運行期間各個進程可能出現如下三種狀態之一:
    • LOOING:處在這個狀態時,會進入 Leader 選舉狀態
    • FOLLOWER:Follower 服務器和 Leader 服務器保持同步時的狀態
    • LEADING:Leader 服務器做爲主進程領導者的狀態
  7. prososal
    leader服務器將客戶端事務請求轉化成一個事務prososal

    核心zab協議

    zookeeper分佈式服務可以知足CAP理論中的CP,即能保證一致性和分區容忍性,可是不是保證可用性。像在leader選舉的過程當中,服務是不可用的。而zookeeper是採用zab(Zookeeper Atomic Broadcast)原子消息廣播協議來保證CP。
    zab在工做的過程當中,會有兩種模式的切換:崩潰恢復模式和消息廣播模式。服務器

    • 在進入崩潰恢復模式時 zookeeper集羣會進行 leader 選舉,通常有兩種狀況會發生選舉:
    • 當服務器啓動時期會進行 Leader 選舉。
    • 當服務器運行期 Leader 服務器的出現網絡中斷、崩潰退出、重啓等異常狀況,或者當集羣中半數的服務器與該 Leader 服務器沒法通訊時,進入崩潰恢復模式,開始 Leader 選舉。
    • 選舉出 Leader 服務器後,會進入消息廣播模式,開始接收處理客戶端的請求。
      恢復模式

      崩潰恢復模式下 leader 選舉的過程細節以下:網絡

    • 檢測節點處於 LOOKING 階段,開始選舉 leader
      發起投票時有兩種狀況:
    • 在服務啓動的初始階段,每一個服務器都會投票給本身以(myid,zxid)的信息形式發送,那初始階段沒有 zxid 值,就會發送(myid,0)
    • 在服務器運行期間,每一個服務器上的 zxid 都有值,且 zxid 都不相同,因此就正常發送(myid,zxid)
    • 各節點收到信息後將收到的(myid,zxid)和本身的比較。會比較epoch、寫請求操做數、myid三個字段,依次比較誰大誰就更有資格成爲leader
    • 而後判斷是否有半數的機器投票選出 leader,若是否,在進入新一輪投票,直到選出
    • 選出 leader 後,其餘節點就變成 follower 角色,並向 leader 發送本身服務器的最大 zxid ,leader 服務器收到後會和本身本地的提議緩存隊列進行比較,判斷使用那種策略進行同步
    • 當同步完成,集羣就能夠正常的處理請求了,就進入消息廣播模式了
      消息廣播模式

      主要過程以下:session

    • leader 服務器接收到請求後在進行廣播事務 proposal 以前會爲這個事務分配一個 ZXID,再進行廣播。
    • leader 服務器會爲每一個 follower 服務器都各自分配一個單獨的隊列,而後將須要廣播的事務 proposal 依次放入這些隊列中去,並根據 FIFO 策略進行消息的發送。
    • 每一個follower 服務器在接收到後都會將其以事務日誌的形式寫入到本地磁盤中,而且在成功寫入後返回leader 服務器一個 ACK 響應。
    • 當有超過半數的服務器 ACK 響應後,leader 就會廣播一個 commit 消息給全部的 follower 服務器,follower 接收到後就完成對事務的提交操做。

      應用場景

      發佈訂閱

      做爲配置中心,來存放服務的配置架構

      命名服務

      命名服務是指經過指定的名字來獲取資源或者服務的地址,提供者的信息。簡單來講使用Zookeeper作命名服務就是用路徑做爲名字,路徑上的數據就是其名字指向的實體,例如url地址。併發

      集羣管理

      集羣中的全部節點都註冊到zk中,並添加watch機制。可以實現集羣節點數量,在線狀態,上下線狀態等的自動發現。異步

      分佈式通知/協調

      ZooKeeper 中特有 watcher 註冊與異步通知機制,可以很好的實現分佈式環境下不一樣系統之間的通知與協調,實現對數據變動的實時處理。socket

      master選舉

      利用zooKeeper的一致性,可以保證在分佈式高併發狀況下節點建立的全局惟一性,即:同時有多個客戶端請求建立 /currentMaster 節點,最終必定只有一個客戶端請求可以建立成功。利用這個特性,就能很輕易的在分佈式環境中進行集羣選取了。分佈式

      分佈式鎖

      鎖服務能夠分爲兩類,一個是保持獨佔,另外一個是控制時序。

    • 獨佔
      全部客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。
    • 控制時序
      /distribute_lock節點已預先存在,客戶端在它下面建立臨時有序節點(這個能夠經過節點的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)。zk的父節點(/distribute_lock)維持一份 sequence,保證子節點建立的時序性,從而也造成了每一個客戶端的全局時序。

      分佈式隊列

      隊列方面,簡單地講有兩種,一種是常規的先進先出隊列,另外一種是要等到隊列成員聚齊以後的才統一按序執行。對於第一種先迚先出隊列,和分佈式鎖服務中的控制時序場景基本原理一致,這裏再也不贅述。
      第二種隊列實際上是在 FIFO 隊列的基礎上做了一個加強。一般能夠在 /queue 這個 znode 下預先創建一個/queue/num 節點,而且賦值爲 n(或者直接給/queue 賦值 n),表示隊列大小,以後每次有隊列成員加入後,就判斷下是否已經到達隊列大小,決定是否能夠開始執行了。這種用法的典型場景是,分佈式環境中,一個大任務 Task A,須要在不少子任務完成(或條件就緒)狀況下才能進行。這個時候,凡是其中一個子任務完成(就緒),那麼就去 /taskList 下創建本身的臨時時序節點(CreateMode.EPHEMERAL_SEQUENTIAL),當 /taskList 發現本身下面的子節點知足指定個數,就能夠進行下一步按序進行處理了。

      優缺點

      優勢

    • 高可靠
    • 應用普遍,比較成熟
    • 支持監聽事件
    • API簡單

      缺點

    • 對於每一個 watch 請求,zookeeper 都會打開一個新的 socket 鏈接,這樣 zookeeper 就須要實時管理不少 socket 鏈接,比較複雜

總結

zookeeper是一款成熟的協調服務,應用普遍。

相關文章
相關標籤/搜索