天天看點

一文搞懂Zookeeper是幹啥的

1.Zookeeper概述(Zookeeper是什麼、應用場景)

1.Zookeeper是什麼

  1. Zookeeper 是一個開源的分布式協調服務系統 ,主要用來解決分布式叢集中應用系統的一緻性問題和資料管理問題
  2. Zookeeper是1個分布式檔案系統+監聽通知機制
  3. Zookeeper檔案系統中存儲的其實是Znode, Znode 是 Zookeeper 中的節點,可以通過操作檔案系統的方式操作 Zookeeper中的Znode

2.應用場景

常見應用場景:資料釋出/訂閱、命名服務、分布式協調/通知、分布式鎖、分布式隊列

2.1 資料釋出/訂閱

釋出者将資料釋出到Zookeeper的節點上,供訂閱者進行資料訂閱,進而達到動态擷取資料的目的,

實作配置資訊的集中式管理和資料的動态更新。

釋出/訂閱一般有兩種設計模式:推模式和拉模式,服務端主動将資料更新發送給所有訂閱的用戶端稱為

推模式;用戶端主動請求擷取最新資料稱為拉模式.

Zookeeper采用了推拉相結合的模式,用戶端向服務端注冊自己需要關注的節點,一旦該節點資料發生變更,那麼服務端就會向相應的用戶端推送Watcher事件通知,用戶端接收到此通知後,主動到服務端擷取最新的資料。

2.2 命名服務

通過命名服務,用戶端可以根據指定名字來擷取資源的實體,在分布式環境中,上層應用僅僅需要一個全局唯一的名字。

Zookeeper可以實作一套分布式全局唯一ID的配置設定機制

2.3 分布式協調/通知

Zookeeper中特有的Watcher注冊于異步通知機制,能夠很好地實作分布式環境下不同機器,甚至不同系統之間的協調與通知,進而實作對資料變更的實時處理。

通常的做法是不同的用戶端都對Zookeeper上的同一個資料節點進行Watcher注冊,監聽資料節點的變化(包括節點本身和子節點),若資料節點發生變化,那麼所有

訂閱的用戶端都能夠接收到相應的Watcher通知,并作出相應處理。

在絕大多數分布式系統中,系統機器間的通信無外乎 心跳檢測、工作進度彙報和系統排程。

① 心跳檢測,不同機器間需要檢測到彼此是否在正常運作。

Zookeeper基于其臨時節點特性(臨時節點的生存周期是用戶端會話,用戶端若當即後,其臨時節點自然不再存在)

可以讓不同機器都在Zookeeper的1個指定節點下建立臨時子節點,不同的機器之間可以根據這個臨時子節點來判斷對應的用戶端機器是否存活。

② 工作進度彙報,通常任務被分發到不同機器後,需要實時地将自己的任務執行進度彙報給分發系統。

Zookeeper建立1個節點,每個任務用戶端都在這個節點下面建立臨時子節點,這樣不僅可以判斷機器是否存活,

同時各個機器可以将自己的任務執行進度寫到該臨時節點中去,以便中心系統能夠實時擷取任務的執行進度。

③ 系統排程

Zookeeper能夠實作如下系統排程模式:分布式系統由控制台和一些用戶端系統兩部分構成,控制台的職責就是需要将一些指令資訊發送給所有的用戶端,

以控制他們進行相應的業務邏輯,背景管理人員在控制台上做一些操作,實際上就是修改Zookeeper上某些節點的資料,Zookeeper可以把資料變更以時間

通知的形式發送給訂閱用戶端。

2.4 分布式鎖

分布式鎖:控制分布式系統之間同步通路共享資源的方式,可以保證不同系統通路1個或1組資源時的一緻性,主要分為排它鎖和共享鎖。

排它鎖又稱為寫鎖或獨占鎖

若事務T1對資料對象O1加上了排它鎖,那麼在整個加鎖期間,隻允許事務T1對O1進行讀取和更新操作,其他任何事務都不能再對這個資料

對象進行任何類型的操作,直到T1釋放了排它鎖。

① 擷取鎖,在需要擷取排它鎖時,所有用戶端通過調用接口,在/exclusive_lock節點下建立

臨時子節點/exclusive_lock/lock。Zookeeper可以保證隻有一個用戶端能夠建立成功,沒有成

功的用戶端需要注冊/exclusive_lock節點監聽。

② 釋放鎖,當擷取鎖的用戶端當機或者正常完成業務邏輯都會導緻臨時節點的删除,此

時,所有在/exclusive_lock節點上注冊監聽的用戶端都會收到通知,可以重新發起分布式鎖獲

取。

共享鎖又稱為讀鎖

若事務T1對資料對 象O1加上共享鎖,那麼目前事務隻能對O1進行讀取操作,其他事務也隻能對這個資料對象加共享鎖,直到該資料對象上的所有共享鎖都被釋放。在需要擷取共享鎖時,所有用戶端都會到/shared_lock下面建立一個臨時順序節點

2.5 分布式隊列

分布式環境下,我們同樣需要一個類似單程序隊列的元件,用來實作跨程序、跨主機、跨網絡的資料共享和資料傳遞,這就是我們的分布式隊列。

① 資料入隊,在一個節點下建立有序子節點,節點中設定需要入隊的資料,完成資料的入隊操作。

② 資料出隊,取出該節點下的所有子節點,如果數量不為0,取出一個子節點,并将子節點删除。

2.Zookeeper的架構元件、元件關系、原理

Zookeeper是1個分布式檔案系統和監聽通知機制

1.Zookeeper的叢集架構

Zookeeper叢集是一個基于主從架構的高可用叢集

Zookeeper叢集中三種角色:Leader、Follower、Observer

  1. Leader Zookeeper叢集同一時間隻會有一個實際工作的Leader,它會發起并維護與各Follwer及Observer間的心跳。

    所有的寫操作必須要通過Leader完成再由Leader将寫操作廣播給其它伺服器。

  2. Follower Zookeeper叢集可能同時存在多個Follower,它會響應Leader的心跳。

    Follower可直接處理并傳回用戶端的讀請求,同時會将寫請求轉發給Leader處理,并且負責在Leader處理寫請求時對請求進行投票。

  3. Observer 角色與Follower類似,但是無投票權

2.Zookeeper的選舉機制

Leader選舉是保證分布式資料一緻性的關鍵所在。當Zookeeper叢集中的一台伺服器出現以下兩種情況之一時,需要進入Leader選舉。

伺服器啟動時期的Leader選舉,伺服器運作時期的Leader選舉

2.1選舉過程

① 每個Server發出1個投票

由于是初始情況,Server1和Server2都會将自己作為Leader伺服器來進行投票,每次投票會包含所推舉的伺服器的myid和ZXID,使用(myid, ZXID)來表示,

此時Server1的投票為(1, 0),Server2的投票為(2, 0),然後各自将這個投票發給叢集中其他機器

② 接受來自各個伺服器的投票

③ 處理投票

針對每一個投票,伺服器都需要将别人的投票和自己的投票進行PK,PK規則如下

· 優先檢查ZXID。ZXID比較大的伺服器優先作為Leader。

· 如果ZXID相同,那麼就比較myid。myid較大的伺服器作為Leader伺服器。

對于Server1而言,它的投票是(1, 0),接收Server2的投票為(2, 0),首先會比較兩者的ZXID,均為0,再比較myid,此時Server2的myid最大,

于是更新自己的投票為(2, 0),然後重新投票,對于Server2而言,其無須更新自己的投票,隻是再次向叢集中所有機器發出上一次投票資訊即可。

④ 統計投票

⑤ 改變伺服器狀态

3.zookeeper的資料模型(檔案系統)

ZooKeeper 是分布式檔案系統的資料模型,每1個節點稱為Znode,Znode儲存資料和子節點清單

ZooKeeper 保證 Znode 通路的原子性, 不會出現部分 ZK 節點更新成功, 部分 ZK 節點更新失敗的問題

3.1 Znode 的特點

  1. Znode 兼具檔案和目錄兩種特點,既可以儲存資料,也可以有下級節點
  2. Znode 通過路徑引用,如果通路 Znode , 需要使用路徑的形式, 例如 /test1/test11
  3. Znode 存儲資料大小有限制,** 最大隻能為 1M **
  4. Znode 是由三個部分構成 stat、data、children

    stat : 狀态, Znode的權限資訊, 版本等

    data : 資料, 每個Znode都是可以攜帶資料的, 無論是否有子節點

    children : 子節點清單

3.2 Znode 的類型

Znode 有兩種,分别為臨時節點和永久節點

Znode 序列化的特性

建立的時候指定的話,該 Znode 的名字後面會自動追加一個不斷增加的序列号。

序列号對于此節點的父節點來說是唯一的,這樣便會記錄每個子節點建立的先後順序。它的格式為“%10d”(10 位數字,沒有數值的數位用 0 補充,

例如“0000000001”)。

Znode 四種類型分别對應

PERSISTENT:永久節點

EPHEMERAL:臨時節點

PERSISTENT_SEQUENTIAL:永久節點、序列化

EPHEMERAL_SEQUENTIAL:臨時節點、序列化

4.Zookeeper的Watcher機制(監聽通知機制)

監聽通知機制

  • 類似于資料庫中的觸發器, 對某個Znode設定 Watcher , 當Znode發生變化的時候, WatchManager 會調用對應的 Watcher
  • 當Znode發生删除, 修改, 建立, 子節點修改的時候, 對應的 Watcher 會得到通知

Watcher 的特點

  1. 一次性觸發一個 Watcher 隻會被觸發一次, 如果需要繼續監聽, 則需要再次添加Watcher
  2. 事件封裝: Watcher 得到的事件是被封裝過的, 包括三個内容 keeperState, eventType, path

3.Zookeeper叢集安裝、配置部署

1.叢集規劃和安裝配置

伺服器IP 主機名 myid
192.168.174.100 node01 1
192.168.174.110 node02 2
192.168.174.120 node0 3
1.下載下傳安裝包解壓
  cd /export/software
  tar -zxvf zookeeper-3.4.9.tar.gz -C ../servers/
  
  2. 修改配置檔案 zoo.cfg
  cd /export/servers/zookeeper-3.4.9/conf/
  cp zoo_sample.cfg zoo.cfg  #複制配置檔案
  mkdir -p /export/servers/zookeeper-3.4.9/zkdatas/  #建立儲存資料的檔案夾
  
  vim zoo.cfg  #修改zoo.cfg
  # 設定儲存資料的檔案夾
  dataDir=/export/servers/zookeeper-3.4.9/zkdatas
  # 保留多少個快照
  autopurge.snapRetainCount=3
  # 日志多少小時清理一次
  autopurge.purgeInterval=1
  # 叢集中伺服器位址
  server.1=node01:2888:3888
  server.2=node02:2888:3888
  server.3=node03:2888:3888
  
  3. 添加myid配置
  # node01機器zkdatas文下建立1個檔案,檔案名為myid ,檔案内容為1
  echo 1 > /export/servers/zookeeper-3.4.9/zkdatas/myid
  
  4. 安裝包分發并修改myid的值
  scp -r /export/servers/zookeeper-3.4.9/ node02:/export/servers/
  scp -r /export/servers/zookeeper-3.4.9/ node03:/export/servers/
  echo 2 > /export/servers/zookeeper-3.4.9/zkdatas/myid
  echo 3 > /export/servers/zookeeper-3.4.9/zkdatas/myid
  
  5. 三台機器啟動zookeeper服務
  # 啟動zk
  bin/zkServer.sh start
  # 檢視zk狀态
  bin/zkServer.sh status
           

4.Zookeeper的API使用

1.Zookeeper的Shell 用戶端操作

1. 登入Zookeeper用戶端
 bin/zkCli.sh -server node01:2181
 
 2. 操作執行個體
 ls /  # 列出Path下的所有Znode
 
 # 建立Znode,-s 指定是順序節點-e 指定是臨時節點
 create [-s] [-e] path data acl 
 
 create /hello world  # 建立永久節點
 
 create -e /abc 123  # 建立臨時節點
 
 create -s /zhangsan boy # 建立永久序列化節點
 
 # 修改節點資料
 set /hello zookeeper
 
 # 删除節點, 如果要删除的節點有子Znode則無法删除
 delete /hello
 # 删除節點, 如果有子Znode則遞歸删除
 rmr /abc
 
 # 列出曆史記錄
 histroy
           

檢視Znode資訊

Znode 都包含了一系列的屬性,通過指令 get,可以獲得節點的屬性

2.Zookeeper的Java API操作

Zookeeper的JavaAPI使用的是一套zookeeper用戶端架構Curator(屬于Apache軟體)

Curator包含了幾個包:

  1. curator-framework:對zookeeper的底層api的一些封裝
  2. curator-recipes:封裝了一些進階特性,如:Cache事件監聽、選舉、分布式鎖、分布式計數器等
# 建立maven java工程,導入jar包
 <dependency>
 <groupId>org.apache.curator</groupId>
 <artifactId>curator-framework</artifactId>
 <version>2.12.0</version>
 </dependency>

 <dependency>
 <groupId>org.apache.curator</groupId>
 <artifactId>curator-recipes</artifactId>
 <version>2.12.0</version>
 </dependency>

           

繼續閱讀