天天看點

Zookeeper詳細使用解析!分布式架構中的協調服務架構最佳選型實踐Zookeeper概念Zookeeper實作分布式鎖Zookeeper的資料模型Zookeeper基本操作Zookeeper事件通知Zookeeper的一緻性Zookeeper應用場景基于Docker建立Zookeeper

Zookeeper概念

  • Zookeeper是分布式協調服務,用于管理大型主機,在分布式環境中協調和管理服務是很複雜的過程,Zookeeper通過簡單的架構和API解決了這個問題

Zookeeper實作分布式鎖

分布式鎖三要素:
加鎖
解鎖
鎖逾時           
  • Zookeeper資料結構類似樹結構,由節點Znode組成
  • Znode分為四種類型:
    • 持久節點(PERSISTENT): 預設節點類型,建立節點的用戶端與Zookeeper斷開連接配接後,節點依舊存在
    • 持久節點順序節點(PERSISTENT_SEQUENTIAL): 持久節點順序節點就是在建立持久節點時,Zookeeper根據建立節點的時間順序給節點進行編号
    • 臨時節點(EPHEMERAL): 建立節點的用戶端與Zookeeper斷開連接配接後,臨時節點會被删除
    • 臨時節點順序節點(EPHEMERAL_SEQUENTIAL): 臨時節點順序節點就是在建立臨時節點時,Zookeeper根據建立節點的時間順序給節點進行編号
    • 應用Zookeeper的臨時順序節點,實作分布式鎖

Zookeeper與Redis分布式鎖比較:

分布式鎖 Zookeeper Redis
優點

1.有封裝好的架構,容易實作

2.有等待鎖隊列,提升搶鎖的效率

Set和Del指令性能高
缺點 添加和删除節點性能低

1.實作複雜,需要考慮原子性,誤删,鎖逾時問題

2.沒有等待鎖的隊列,隻能用戶端自旋來等鎖,效率低

Zookeeper的資料模型

  • 類似資料結構中的樹,檔案系統中的目錄
  • Zookeeper的資料存儲基于節點Znode
  • Znode的引用方式是路徑引用,每一個Znode節點擁有唯一的路徑

Znode中的元素

  • data: Znode存儲的資料資訊
  • ACL: 記錄Znode的通路權限,即哪些程序和IP可以通路本節點
  • stat: Znode的各種中繼資料(資料的資料)
  • child: 目前節點的子節點引用

Zookeeper的應用場景是讀多寫少的應用場景:Znode不用來存儲大規模的業務資料,用于存儲少量的狀态和配置資訊(Znode存儲資料不能超過1MB)

Zookeeper基本操作

  • 建立節點:create
  • 删除節點:delete
  • 判斷節點是否存在:exists
  • 獲得一個節點的資料:getData
  • 設定一個節點的資料:setData
  • 擷取節點下的所有子節點:getChildren

exists,getData,getChildren屬于讀操作,Zookeeper用戶端在請求讀操作時,可以選擇是否設定watch

Zookeeper事件通知

  • Watch可以了解成注冊在特定Znode上的觸發器
  • 當Znode發生改變的時候,調用create,delete,setData方法,将會觸發Znode上注冊的對應事件,請求的Watch的用戶端會接收到異步通知
  • Zookeeper事件通知的互動過程:
    • 用戶端調用getData方法,watch的參數是true,服務端接收到請求,傳回節點資料,在對應的Hash表中插入被Watch的Znode路徑以及Watcher清單
    • 當被Watch的Znode删除,服務端會查找Hash表,找到該Znode對應的所有Watcher,異步通知用戶端,并且删除Hash表中對應的key-value

Zookeeper的一緻性

  • Zookeeper Service叢集是一主多從結構
  • 在更新資料時,首先更新到主伺服器,再同步到從伺服器
  • 在讀資料時,直接讀取任意節點
  • 采用ZAB協定,為了保證主從節點資料的一緻性

ZAB協定

  • ZAB(Zookeeper Automic Broadcast): 解決Zookeeper叢集崩潰恢複,主從資料同步問題
  • ZAB三種節點狀态:
    • Looking:選舉狀态
    • Following:Following節點(從節點)所處的狀态
    • Leading:Leading(主節點)所處的狀态
  • 最大ZXID: 節點本地的最新事務編号,包含epoch和計數兩部分

ZAB叢集崩潰恢複

  • 當Zookeeper的主節點伺服器當機後,叢集就會進行崩潰恢複,分成三個階段:
    • Leader election(選舉階段):
      • 叢集中的節點處于Looking狀态,各自向其它節點發起投票,投票當中包含自己伺服器的ID和最新事務ID(ZXID)
      • 節點用自身的ZXID和其它節點收到的ZXID作比較,如果發現其它節點的ZXID比自身大,即資料比自己新,就重新發起投票,投票給目前已知最大ZXID所屬節點
      • 每次投票後,伺服器都會統計投票數量,判斷是否某個節點得到半數以上的投票,這樣的節點将會成為準Leader,狀态變為Leading,其它節點狀态變為Following
    • Discovery(發現階段):
      • 在從節點發現最新的ZXID和事務日志,目的是為了防止在意外情況,選舉産生多個Leader
      • Leader接收所有Follower發送的最新的epoch值,Leader從中選出最大的epoch,基于此值+1,生成新的epoch分發給各個Follower
      • 各個Follower接收到最新的epoch,傳回ACK(響應碼)給Leader,帶上各自最大的ZXID和曆史事務日志,Leader選出最大的ZXID,并更新自身曆史日志
    • Synchronization(同步階段):
      • 将Leader收集得到的最新曆史事務日志,同步給叢集中的所有Follower,隻有當半數Follower同步成功,這個準Leader才能成為正式Leader.叢集崩潰恢複正式完成

ZAB主從資料同步

  • Broadcast

Zookeeper正常情況下更新資料的時候,由Leader廣播到所有的Follower:

  • 用戶端發出寫入資料請求給任意的Follower
  • Follower把寫入資料請求轉發給Leader
  • Leader采取二階段送出方式:(先保留送出日志,再送出資料)先發送Propose廣播給Follower
  • Follower接收到Propose消息,寫入日志成功後,傳回ACK消息給Leader
  • Leader接收到半數以上的ACK消息,傳回成功給用戶端,并且廣播commit請求給Follower
資料一緻性:
強一緻性
弱一緻性
順序一緻性:Zookeeper,依靠事務ID和版本号,保證資料的更新和讀取是有序的           

Zookeeper應用場景

  • 分布式鎖: 應用Zookeeper的臨時順序節點,實作分布式鎖
  • 服務注冊與發現: 利用Znode和Watcher,實作分布式服務注冊與發現,如Dubbo
  • 共享配置和狀态資訊: Redis的分布式解決方案Codls,利用Zookeeper存放資料路由表和codls-proxy節點元資訊,同時colds-config發起的指令都會通過Zookeeper同步到各個存活的codls-proxy
  • 高可用實作: Kafka,HBase,Hadoop都依靠Zookeeper同步節點資訊,實作高可用

基于Docker建立Zookeeper

1.建立docker-compose.yml
zoo:
    image: zookeeper
    restart: always
    hostname: zoo
    ports:
        - 2181:2181
    environment:
        - ZOO_MY_ID: 1
        - ZOO_SERVER: server.1(id)=zoo(IP):2888:3888
2.執行docker-compose up -d           

Zookeeper三種工作模式

  • 單機模式: 存在單點故障
  • 叢集模式: 在多台伺服器上部署Zookeeper叢集
  • 僞叢集模式: 在同一台伺服器上運作多個Zookeeper執行個體,仍然有單點故障問題,其中配置的端口号要錯開

Zookeeper三種端口号

  • 2181: 用戶端連接配接Zookeeper叢集使用的監聽端口号
  • 3888: 選舉Leader使用
  • 2888: 叢集内機器通訊使用(Leader和Follower之間資料同步使用的端口号,Leader監聽此端口)

繼續閱讀