JavaEE進階——ZooKeeper和Curator

I. 簡介

ZooKeeper是一個分佈式的,提供分佈式應用程序協調服務的一個項目。它是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分佈式同步、組服務等。

工作機制

ZooKeeper從設計模式角度理解:是基於觀察者模式的分佈式服務管理框架,它負責存儲和管理所有節點都關心的數據,然後接受觀察者的註冊,一旦這些數據發生變化,ZooKeeper就會通知已經註冊了的觀察者,觀察者可以相應的做出反應。

ZooKeeper=文件系統+通知機制

所以大多數利用ZooKeeper實現的相關功能,都是基於其存儲數據的機制加上數據監聽的機制。比如利用ZooKeeper給集羣中機器進行編號,服務器的動態上下線,分佈式鎖等等。

特點

ZooKeeper集羣中包含四種角色:

  1. Leader:Leader負責進行投票的發起和決議,既能讀也能寫。
  2. Follower:Follower用於接收客戶端請求並向客戶端返回結果,只能提供讀服務,寫請求需轉發給Leader節點;同時在選主過程中參與投票
  3. Observer:Observer不參與投票過程,也不參與寫操作的“過半寫成功”策略,只同步Leader的狀態。Observer的目的是爲了擴展系統,提高讀取速度。
  4. Client:客戶端,連接ZooKeeper服務器,請求發起方。

如下是一個ZooKeeper集羣示意圖,共有7個服務器,其中1個Leader,4個Follower,2個Observer。

ZooKeeper集羣

集羣有如下特點:

  1. ZooKeeper集羣中只有一個Leader,其他的均爲Learner,包括Follower和Observer;
  2. 集羣中只要有半數以上的節點存活,ZooKeeper就可以正常服務。半數以上特性使得往往集羣節點個數爲奇數;
  3. 全局數據一致。每個Server保存一份相同的數據副本,Client無論連接到哪個Server,數據都是一致的;
  4. 更新請求順序執行。來自同一個Client的更新請求按其發送次序順序執行;
  5. 數據更新原子性。一次數據更新要麼成功,要麼失敗,事務特點。
  6. 實時性。在一定時間範圍內,客戶端能夠讀到最新數據,因爲數據量小,同步快。

數據結構

ZooKeeper的數據模型的結構與Unix文件系統很類似,整體上可以看做是一棵樹,每個節點可以稱作一個ZNode,每一個ZNode默認可以存儲1MB的數據,每個ZNode都可以通過其路徑唯一標識

ZooKeeper的數據結構

應用場景

統一命名服務

分佈式應用中,通常需要有一套完整的命名規則,既能夠產生唯一的名稱又便於人識別和記住。例如:www.baidu.com域名對應的服務器ip地址有很多,域名很容易被識記,ip則很難。那麼可以在ZooKeeper服務器上創建一個www.baidu,com的節點,該節點下可以創建所有ip地址名稱的子節點,這樣就可以統一命名,根據域名得到所有ip。

統一配置管理

分佈式環境下,配置文件的同步往往非常常見。一般情況下,對配置文件的修改希望對集羣中的每一個節點都生效。所以可以將配置文件上傳到ZooKeeper的一個節點中,所有的節點去監聽該節點內容變化,當節點內容變化說明配置文件更新,每個節點讀取新的配置文件並更新狀態。

統一集羣管理

分佈式環境中,實時掌握每個節點狀態是必要的,這樣可以根據節點的狀態變化做出應對策略。ZooKeeper可以實現實時監控節點狀態變化,節點可將自身信息寫入ZooKeeper的某個節點下,監聽這個節點就可以實現對節點信息的監控,獲取實時狀態變化。

服務器動態上下線

分佈式環境中,服務器往往是動態增減的。對於服務的調用方來說,動態的獲悉服務器的上下線顯得十分必要。服務器上線時在ZooKeeper的某個節點下寫入臨時節點數據,調用方則監聽該節點下的數據變化,每當有服務器上下線,調用方就會得知並獲取最新的所有服務器列表。

軟負載均衡

在ZooKeeper中可以記錄每臺服務器的訪問次數,讓訪問次數最少的機器去處理客戶端的請求。

II. 下載安裝

下載地址:https://zookeeper.apache.org/releases.html#download

Docker鏡像地址:https://hub.docker.com/_/zookeeper/

安裝過程:參考zookeeper安裝教程(zookeeper3.4.5爲例)

配置文件zoo.cfg參數含義:

參數 含義
tickTime 心跳間隔,單位是毫秒,系統默認是2000毫秒,也就是間隔兩秒心跳一次。 客戶端與服務器或者服務器與服務器之間維持心跳,也就是每個tickTime時間就會發送一次心跳。
initLimit Follower與Leader之間初始連接時能容忍的最多心跳數,默認情況下FL的會話時長是2·tickTime
syncLimit Leader發送心跳包給Follower開始到收到Follower響應這段時間最多能容忍的心跳數
dataDir 該目錄用來存放myid信息, 事務日誌存儲路徑等
clientPort 客戶端和服務端連接的端口
server.A=B:C:D A是指myid,B是指該節點的ip地址或者主機名稱,C是指集羣中所有節點和Leader交換信息的端口,D是選舉時服務器相互通信的端口

如果想要指定的節點是Observer節點,在zoo.cfg下額外配置:

peerType=observer
server.A=B:C:D:observer 

III. 內部原理

選舉機制

選舉特點

  1. 半數機制:集羣中超過半數以上的機器存活,集羣即可用。
  2. ZooKeeper雖然沒有指定Leader和Follower,但是ZooKeeper工作時,只有一個節點是Leader,其他則是Follower和Observer,Leader是通過內部選舉機制產生的。

選舉過程

節點類型

節點類型 含義
PERSISTENT 持久化節點
PERSISTENT_SEQUENTIAL 順序自動編號持久化節點,這種節點會根據當前已存在的節點數自動加1
EPHEMERAL 臨時節點, 客戶端Session超時這類節點就會被自動刪除
EPHEMERAL_SEQUENTIAL 臨時自動編號節點

Stat結構體

Stat: 各種元數據,比如事務ID、版本號、時間戳、大小等

  • czxid - 創建該節點的事務 zxid(每次修改ZooKeeper狀態會收到一個zxid形式的時間戳,代表事務ID)
  • ctime - znode 被創建的毫秒數(從1970年開始)
  • mzxid - znode 最後更新的事務 zxid
  • mtime - znode 最後修改的毫秒數
  • pZxid - znode 最後更新的子節點 zxid
  • cversion - znode 子節點變化號,znode 子節點修改次數
  • dataversion - znode 數據變化號
  • aclVersion - znode 訪問控制列表的變化號
  • ephemeralOwner - 如果是臨時節點,這個是znode擁有者的session id。如果不是臨時節點則是0
  • dataLength - znode 的數據長度
  • numChildren - znode 子節點數量

監聽器原理

監聽器原理詳解

  1. 在Zookeeper的API操作中,客戶端的main方法會創建一個主線程;

  2. 在主線程中創建Zookeeper客戶端 (zkClient),這時會創建兩個線程:

    • connet線程負責網絡通信連接,連接服務器;
    • Listener線程負責監聽;
  3. 客戶端通過connet線程連接服務器,將監聽事件註冊到ZooKeeper中(圖中getChildren("/" , true) ," / "表示監聽的是根目錄,true表示監聽,不監聽用false);

  4. 在Zookeeper的註冊監聽列表中將需要註冊的監聽事件添加到列表中,圖中/path表示哪個目錄被客戶端監聽了;

  5. 一旦被監聽的目錄下,數據或路徑發生了改變,Zookeeper就會將這個消息發送給Listener線程;

  6. Listener線程內部調用process方法,採取相應的措施。

監聽器原理圖解

常見的監聽類別

  1. 監聽某節點下目錄路徑的變化:ls path [watch]
  2. 監聽某節點的數據內容的變化:get path [watch]

寫數據流程

寫數據流程

IV. ZooKeeper實戰

客戶端命令行操作

啓動客戶端命令:bin/zkCli.sh

命令基本語法 含義
help 顯示所有操作命令
ls path [watch] 查看當前節點所包含的所有子節點,可選watch表示監聽節點下目錄的變化
ls2 path [watch 查看當前節點數據,並能看到更新次數等數據
get path [watch] 獲得節點的值,可選watch表示監聽該節點數據內容的變化
stat path 查看節點狀態
create [-s] [-e] path data acl 創建節點, -s指定是否自動編號,-e指定順序還是臨時節點。若不指定,則表示持久或非自動編號節點;acl用來進行權限控制,那些人或那些ip可以訪問該節點
set path data [version] 更改節點信息, data就是要更新的新內容,version 表示數據版本
delete path [version] 刪除節點。 若刪除節點存在子節點,那麼無法刪除該節點,必須先刪除子節點,再刪除父節點。
rmr 遞歸刪除節點

原生客戶端API

Maven依賴

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>x.x.x</version>
</dependency>

API操作

Curator API

Curator是Netflix公司開源的一套zookeeper客戶端框架,解決了很多Zookeeper客戶端非常底層的細節開發工作,包括連接重連、反覆註冊Watcher,分佈式鎖和NodeExistsException異常等等。

Maven依賴

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>x.x.x</version>
</dependency>

API操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章