zookeeper入門

zookeeper 簡介

Zookeeper 分佈式服務框架是 Apache Hadoop 的一個子項目,它主要是用來解決分佈式應用中常常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。html

zookeeper 單機使用

訪問http://zookeeper.apache.org/releases.html 並下載最新版本的ZooKeeper,這裏我使用的版本是3.4.8。java

下載完成後解壓縮。進入conf目錄,建立zoo.cfg配置文件(可複製已有的zoo_sample.cfg修改)。node

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
clientPort=2181

說明一下幾個配置項的意義(initLimit和syncLimit暫時先無論,後面有說明):apache

  • tickTime:這個時間是做爲 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每一個 tickTime 時間就會發送一個心跳。
  • dataDir:顧名思義就是 Zookeeper 保存數據的目錄,默認狀況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄裏。
  • clientPort:這個端口就是客戶端鏈接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。

保存配置文件,返回進入bin目錄,雙擊zkService.cmd啓動服務,控制檯看到以下啓動信息:設計模式

...
2017-05-04 16:42:38,924 [myid:] - INFO  [main:ZooKeeperServer@787] - tickTime set to 2000
2017-05-04 16:42:38,924 [myid:] - INFO  [main:ZooKeeperServer@796] - minSessionTimeout set to -1
2017-05-04 16:42:38,925 [myid:] - INFO  [main:ZooKeeperServer@805] - maxSessionTimeout set to -1
2017-05-04 16:42:38,993 [myid:] - INFO  [main:NIOServerCnxnFactory@89] - binding to port 0.0.0.0/0.0.0.0:2181

再雙擊zkCli.cmd啓動客戶端,控制檯顯示以下信息:api

...
WATCHER::
[zk: localhost:2181(CONNECTED) 0]
WatchedEvent state:SyncConnected type:None path:null

ZooKeeper客戶端用於與ZooKeeper服務器進行交互,下面來進行簡單的操做。服務器

建立Znodes

建立具備給定路徑的znode。session

語法數據結構

create /path data

示例:app

create /FirstZnode "myfirstzookeeper-app"
Created /FirstZnode

使用參數能夠指定建立的節點模式CreateMode,CreateMode有下面幾種:

  • PERSISTENT:建立後只要不刪就永久存在

  • EPHEMERAL:會話結束年結點自動被刪除,EPHEMERAL結點不容許有子節點

  • SEQUENTIAL:節點名末尾會自動追加一個10位數的單調遞增的序號,同一個節點的全部子節點序號是單調遞增的

  • PERSISTENT_SEQUENTIAL:結合PERSISTENT和SEQUENTIAL

  • EPHEMERAL_SEQUENTIAL:結合EPHEMERAL和SEQUENTIAL

默認狀況下,全部znode都是持久的。

建立Sequential znode,請添加-s標誌,語法以下

create -s /path data

示例:

[zk: localhost:2181(CONNECTED) 1] create -s  /FirstZnode "second-data"
Created /FirstZnode0000000006

建立Ephemeral Znode,請添加-e標誌,語法以下

create -e /path data

示例:

[zk: localhost:2181(CONNECTED) 2] create -e /SecondZnode "Ephemeral-data"
Created /SecondZnode

當客戶端鏈接丟失時,臨時znode將被刪除。下面咱們會經過退出ZooKeeper客戶端,而後從新打開zkCli來驗證。

獲取數據

獲取znode的數據,包括數據上次修改的時間,修改的位置等其餘相關信息。

語法

get /path

示例:

[zk: localhost:2181(CONNECTED) 3] get /FirstZnode
myfirstzookeeper-app
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x151
mtime = Thu May 04 17:02:34 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 20
numChildren = 0

訪問Sequential znode,必須輸入znode的完整路徑,語法以下

get /path00000000xx

示例:

[zk: localhost:2181(CONNECTED) 4] get /FirstZnode0000000006
second-data
cZxid = 0x152
ctime = Thu May 04 17:10:34 CST 2017
mZxid = 0x152
mtime = Thu May 04 17:10:34 CST 2017
pZxid = 0x152
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0

這裏咱們來驗證Ephemeral Znode。

先獲取一次:

[zk: localhost:2181(CONNECTED) 5] get /SecondZnode
Ephemeral-data
cZxid = 0x153
ctime = Thu May 04 17:13:21 CST 2017
mZxid = 0x153
mtime = Thu May 04 17:13:21 CST 2017
pZxid = 0x153
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x15bd2a018370000
dataLength = 14
numChildren = 0

關閉zkCli命令行窗口,等待40s,重啓客戶端,再次嘗試獲取:

get /SecondZnode
Node does not exist: /SecondZnode

能夠看到臨時znode已經不存在了,而永久節點是存在的:

[zk: localhost:2181(CONNECTED) 1] get /FirstZnode
myfirstzookeeper-app
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x151
mtime = Thu May 04 17:02:34 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 20
numChildren = 0

這裏說一下,客戶端鏈接斷了以後,ZK不會立刻移除臨時數據,只有當SESSIONEXPIRED以後,纔會把這個會話創建的臨時數據移除。

而SESSIONEXPIRED是取決於客戶端和服務端兩方面的。

zk server端timeout參數:

  • tickTime:zk的心跳間隔(heartbeat interval),也是session timeout基本單位,單位爲微妙。
  • minSessionTimeout: 最小超時時間,zk設置的默認值爲2*tickTime。
  • maxSessionTimeout:最大超時時間,zk設置的默認值爲20*tickTime。

咱們配置文件的tickTime爲2000,因此這裏服務端最大超時時間爲20*2000ms = 40s。

zk client端timeout參數:這裏cmd命令行不清楚怎麼設置,可是應該也有默認的值,不過默認值也不知道= =!。

查看zookeeper源碼可知,服務端拿到客戶端的超時時間後,是會作一些判斷的,客戶端超時時間實際限制在{2*tickeTime, 20*tickTime}範圍內。假設客戶端設置了timeout爲100s,實際40s就已經超時了;相似若是客戶端設置timeout爲1s,也要等到4s才超時。

回到咱們的測試,創建臨時節點,若是關閉客戶端後馬上(4s內)鏈接上,臨時節點仍然存在,而等待40s後session必定過時,臨時節點就被刪除了。

設置數據

設置指定znode的數據。

語法

set /path data-updated

示例:

[zk: localhost:2181(CONNECTED) 4] set /FirstZnode "myfirstzookeeper-app1.1"
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x15d
mtime = Thu May 04 17:46:18 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 0

查看結果:

[zk: localhost:2181(CONNECTED) 5] get /FirstZnode
myfirstzookeeper-app1.1
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x15d
mtime = Thu May 04 17:46:18 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 0

設置監聽

當指定的znode或znode的子數據更改時,watch會顯示通知。

語法

get /path [watch] 1

示例:

[zk: localhost:2181(CONNECTED) 6] get /FirstZnode 1
myfirstzookeeper-app1.1
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x15d
mtime = Thu May 04 17:46:18 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 0

設置了監聽的節點被修改後,輸出會稍微不一樣,帶有watch信息

[zk: localhost:2181(CONNECTED) 7] set /FirstZnode "myfirstzookeeper-app1.2"

WATCHER::
cZxid = 0x151
WatchedEvent state:SyncConnected type:NodeDataChanged path:/FirstZnode

ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x15e
mtime = Thu May 04 17:52:14 CST 2017
pZxid = 0x151
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 0

建立子節點

建立子節點相似於建立新的znode。惟一的區別是子節點znode的路徑包含了父路徑。

語法

create /parentpath/childpath data

示例:

[zk: localhost:2181(CONNECTED) 8] create /FirstZnode/Child1 "firstchildren"
Created /FirstZnode/Child1
[zk: localhost:2181(CONNECTED) 9] create /FirstZnode/Child2 "secondchildren"
Created /FirstZnode/Child2

查看子節點

查看znode全部的子節點。

語法

ls /path

示例:

[zk: localhost:2181(CONNECTED) 10] ls /FirstZnode
[Child2, Child1]

查看根目錄下全部節點:

[zk: localhost:2181(CONNECTED) 11] ls /
[dubbo, FirstZnode0000000006, zookeeper, FirstZnode]

檢查狀態

查看指定znode的元數據。包含詳細信息,如時間戳,版本號,ACL,數據長度和子節點znode。

語法

stat /path

示例:

[zk: localhost:2181(CONNECTED) 12] stat /FirstZnode
cZxid = 0x151
ctime = Thu May 04 17:02:34 CST 2017
mZxid = 0x15e
mtime = Thu May 04 17:52:14 CST 2017
pZxid = 0x160
cversion = 2
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 2

刪除節點

刪除指定的znode及其全部子節點。

語法

rmr /path

示例:

[zk: localhost:2181(CONNECTED) 13] rmr /FirstZnode
[zk: localhost:2181(CONNECTED) 14] get /FirstZnode
Node does not exist: /FirstZnode

還有一種刪除,只能刪除沒有子節點的節點,語法:

delete /path

示例:

[zk: localhost:2181(CONNECTED) 17] create /myZnode "mydata"
Created /myZnode
[zk: localhost:2181(CONNECTED) 18] create /myZnode/child1 "child1data"
Created /myZnode/child1
[zk: localhost:2181(CONNECTED) 19] delete /myZnode
Node not empty: /myZnode
[zk: localhost:2181(CONNECTED) 20] delete /myZnode/child1
[zk: localhost:2181(CONNECTED) 21] delete /myZnode
[zk: localhost:2181(CONNECTED) 22] get /myZnode
Node does not exist: /myZnode

zookeeper 數據模型

簡單使用了zookeeper以後,咱們發現其數據模型有些像操做系統的文件結構,結構以下圖所示
zookeeper數據模型

  1. 每一個節點在zookeeper中叫作znode,而且其有一個惟一的路徑標識,如/Server1節點的標識就爲/NameService/Server1。
  2. znode能夠有子znode,而且znode裏能夠存數據,可是EPHEMERAL類型的節點不能有子節點。
  3. znode中的數據能夠有多個版本,好比某一個路徑下存有多個數據版本,那麼查詢這個路徑下的數據就須要帶上版本。
  4. znode能夠是臨時節點,一旦建立這個znode的客戶端與服務器失去聯繫,這個znode也將自動刪除。zookeeper的客戶端和服務器通訊採用長鏈接方式,每一個客戶端和服務器經過心跳來保持鏈接,這個鏈接狀態稱爲session,若是這個session失效,臨時znode也就刪除了。
  5. znode的目錄名能夠自動編號,如sznode0000000001已經存在,再建立sznode的話,將會自動命名爲sznode0000000002。
  6. znode能夠被監控,包括這個目錄節點中存儲的數據的修改,子節點目錄的變化等,一旦變化能夠通知設置監控的客戶端,這個功能是zookeeper對於應用最重要的特性,經過這個特性能夠實現的功能包括配置的集中管理,集羣管理,分佈式鎖等等。

Zookeeper API

Znode是ZooKeeper核心組件,ZooKeeper API提供了方法來操縱znode。

客戶端遵循如下步驟來與ZooKeeper進行清晰和乾淨的交互:

  • 鏈接到ZooKeeper服務。ZooKeeper服務爲客戶端分配會話ID。
  • 按期向服務器發送心跳。不然,ZooKeeper將設定會話ID過時,客戶端須要從新鏈接。
  • 只要會話ID處於活動狀態,就能夠獲取/設置znode。
  • 全部任務完成後,斷開與ZooKeeper服務的鏈接。 若是客戶端長時間不活動,則ZooKeeper服務將自動斷開客戶端。

示例:

import java.io.IOException;
import java.util.List;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 * Test Zookeeper
 *
 * @author tenny.peng
 */
public class TestZookeeper {

    public static void main(String[] args) {
        try {
            // 建立一個Zookeeper實例。param1:目標服務器地址和端口;param2:Session超時時間;param3:節點變化時的回調方法。
            ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 500000, new Watcher() {
                // 監控全部被觸發的事件
                public void process(WatchedEvent event) {
                    // dosomething
                    System.out.println("監聽事件: " + event.toString());
                }
            });

            // 建立一個節點。param1:節點路徑;param2:節點數據;param3:權限控制;這裏表示全部人均可以操做;param4:節點類型,這裏爲永久。
            zk.create("/FirstZnode", "my first zookeeper app".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

            // 查看一個節點是否存在。param1:znode路徑;param2:是否監測(watch)查看的節點,重載方法:可傳入自定義watch。
            Stat stat = zk.exists("/FirstZnode", true);
            System.out.println("version: " + stat.getVersion());

            // 獲取一個節點的數據。param1:znode路徑;param2:是否監測(watch),重載方法:可傳入自定義watch;param3:znode的元數據。
            byte[] b = zk.getData("/FirstZnode", true, stat);
            String data = new String(b);
            System.out.println(data);

            // 修改一個節點的數據。param1:znode路徑;param2:節點數據;param3:znode當前的版本號,-1無視被修改的數據版本,直接改掉。每當數據更改時,ZooKeeper會更新znode的版本號。
            zk.setData("/FirstZnode", "my first zookeeper app1.1".getBytes(), stat.getVersion());
            stat = zk.exists("/FirstZnode", true);
            System.out.println("version: " + stat.getVersion());
            b = zk.getData("/FirstZnode", true, stat);
            data = new String(b);
            System.out.println(data);

            // 建立子節點,和建立節點同樣。
            zk.create("/FirstZnode/child1", "child1 data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            zk.create("/FirstZnode/child2", "child2 data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

            // 獲取子節點。param1:znode路徑;param2:是否監測(watch),重載方法:可傳入自定義watch。
            List<String> children = zk.getChildren("/FirstZnode", true);
            for (int i = 0; i < children.size(); i++) {
                System.out.println(children.get(i));
            }

            // 刪除節點,若有子節點必須先刪除子節點。param1:znode路徑;param2:znode的當前版本,-1的話直接刪除,無視版本。
            zk.delete("/FirstZnode/child1", -1);
            zk.delete("/FirstZnode/child2", -1);
            zk.delete("/FirstZnode", -1);

            // 關閉session
            zk.close();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

結果:

監聽事件: WatchedEvent state:SyncConnected type:None path:null
version: 0
my first zookeeper app
監聽事件: WatchedEvent state:SyncConnected type:NodeDataChanged path:/FirstZnode
version: 1
my first zookeeper app1.1
child2
child1
監聽事件: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/FirstZnode
監聽事件: WatchedEvent state:SyncConnected type:NodeDeleted path:/FirstZnode

zookeeper 集羣

Zookeeper 不只能夠單機提供服務,同時也支持多機組成集羣來提供服務。實際上 Zookeeper 還支持另一種僞集羣的方式,也就是能夠在一臺物理機上運行多個 Zookeeper 實例。

下面介紹僞集羣模式的安裝和配置:

  1. 新建一個總文件夾zookeeperCluster用於存放集羣;
  2. zookeeperCluster文件夾下創建三個文件夾server1,server2,server3;
  3. 每一個server裏面新建一個data文件夾和一個log文件夾,並複製一份單機的zookeeper的文件夾;
  4. 每一個server/data下新建一個myid文件並寫入一個數字,server1就寫1,server2寫2,server3寫3。Zookeeper 啓動時會讀取這個文件,拿到裏面的數據與 zoo.cfg 裏面的配置信息比較從而判斷當前 server 究竟是哪一個 server。
  5. 進入各個server/zookeeper/conf目錄,編輯zoo.cfg。因爲是在一臺機器上部署多個server,每一個server要用不一樣的clientPort,好比server1是2181,server2是2182,server3是2183,dataDir和dataLogDir也要修改爲相應路徑。
tickTime=2000
initLimit=10
syncLimit=4
dataDir=D:/devsoft/zookeeperCluster/server1/data
dataLogDir=D:/devsoft/zookeeperCluster/server1/log
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
  1. 分別啓動三個server/zookeeper/bin/zkServer.cmd。

說明一下集羣的幾個配置參數

  • initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶鏈接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集羣中鏈接到 Leader 的 Follower 服務器)初始化鏈接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper 服務器尚未收到客戶端的返回信息,那麼代表這個客戶端鏈接失敗。總的時間長度就是 10*2000=20 秒。
  • syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 4*2000=8 秒。
  • server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集羣中的 Leader 服務器交換信息的端口;D 表示的是萬一集羣中的 Leader 服務器掛了,須要一個端口來從新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通訊的端口。若是是僞集羣的配置方式,因爲 B 都是同樣,因此不一樣的 Zookeeper 實例通訊端口號不能同樣,因此要給它們分配不一樣的端口號。

啓動第一個server,這時會報大量錯誤。

2017-05-06 17:26:12,366 [myid:1] - INFO  [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:218
1:FastLeaderElection@852] - Notification time out: 800

不要緊,由於如今集羣只起了1臺server,zookeeper服務器端起來會根據zoo.cfg的服務器列表發起選舉leader的請求,由於連不上其餘機器而報錯。
咱們再起第二個zookeeper服務,leader將會被選出,從而一致性服務開始可使用,這是由於3臺機器只要有2臺可用就能夠選出leader而且對外提供服務(2n+1臺機器,能夠容n臺機器掛掉)。

2017-05-06 17:26:39,573 [myid:2] - INFO  [WorkerSender[myid=2]:QuorumPeer$Quorum
Server@149] - Resolved hostname: 127.0.0.1 to address: /127.0.0.1

再啓動最後一個zookeeper服務。

2017-05-06 17:27:11,071 [myid:3] - INFO  [QuorumPeer[myid=3]/0:0:0:0:0:0:0:0:218
3:FileTxnSnapLog@240] - Snapshotting: 0x700000000 to D:\devsoft\zookeeperCluster
\server3\data\version-2\snapshot.700000000

開啓一個客戶端zkCli.cmd,能夠看到成功鏈接集羣中的master。

2017-05-06 17:27:11,071 [myid:3] - INFO  [QuorumPeer[myid=3]/0:0:0:0:0:0:0:0:218
3:FileTxnSnapLog@240] - Snapshotting: 0x700000000 to D:\devsoft\zookeeperCluster
\server3\data\version-2\snapshot.700000000

而後客戶端就能夠像以前單機同樣進行各類操做。

ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 1] create /testZnode "testdata"
Created /testZnode
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper, testZnode]
[zk: localhost:2181(CONNECTED) 3] delete /testZnode
[zk: localhost:2181(CONNECTED) 4] ls /
[zookeeper]

ZooKeeper 典型的應用場景

Zookeeper 從設計模式角度來看,是一個基於觀察者模式設計的分佈式服務管理框架,它負責存儲和管理你們都關心的數據,而後接受觀察者的註冊,一旦這些數據的狀態發生變化,Zookeeper 就將負責通知已經在 Zookeeper 上註冊的那些觀察者作出相應的反應,從而實現集羣中相似 Master/Slave 管理模式。

下面詳細介紹這些典型的應用場景。

配置管理(Configuration Management)

配置的管理在分佈式應用環境中很常見,例如同一個應用系統須要多臺 PC Server 運行,可是它們運行的應用系統的某些配置項是相同的,若是要修改這些相同的配置項,那麼就必須同時修改每臺運行這個應用系統的 PC Server,這樣很是麻煩並且容易出錯。

像這樣的配置信息徹底能夠交給 Zookeeper 來管理,將配置信息保存在 Zookeeper 的某個目錄節點中,而後將全部須要修改的應用機器監控配置信息的狀態,一旦配置信息發生變化,每臺應用機器就會收到 Zookeeper 的通知,而後從 Zookeeper 獲取新的配置信息應用到系統中。

好比將APP1的全部配置配置到/APP1 znode下,APP1全部機器一啓動就對/APP1這個節點進行監控,而且實現回調方法Watcher,那麼在zookeeper上/APP1 znode節點下數據發生變化的時候,每一個機器都會收到通知,Watcher方法將會被執行,那麼應用再取下數據便可。
配置管理結構圖

集羣管理(Group Membership)

Zookeeper 可以很容易的實現集羣管理的功能,若有多臺 Server 組成一個服務集羣,那麼必需要一個「總管」知道當前集羣中每臺機器的服務狀態,一旦有機器不能提供服務,集羣中其它集羣必須知道,從而作出調整從新分配服務策略。一樣當增長集羣的服務能力時,就會增長一臺或多臺 Server,一樣也必須讓「總管」知道。

Zookeeper 不只可以幫你維護當前的集羣中機器的服務狀態,並且可以幫你選出一個「總管」,讓這個總管來管理集羣,這就是 Zookeeper 的另外一個功能 Leader Election。

它們的實現方式都是在 Zookeeper 上建立一個 EPHEMERAL 類型的目錄節點,而後每一個 Server 在它們建立目錄節點的父目錄節點上調用 getChildren(String path, boolean watch) 方法並設置 watch 爲 true,因爲是 EPHEMERAL 目錄節點,當建立它的 Server 死去,這個目錄節點也隨之被刪除,因此 Children 將會變化,這時 getChildren上的 Watch 將會被調用,因此其它 Server 就知道已經有某臺 Server 死去了。新增 Server 也是一樣的原理。

Zookeeper 如何實現 Leader Election,也就是選出一個 Master Server。和前面的同樣每臺 Server 建立一個 EPHEMERAL 目錄節點,不一樣的是它仍是一個 SEQUENTIAL 目錄節點,因此它是個 EPHEMERAL_SEQUENTIAL 目錄節點。之因此它是 EPHEMERAL_SEQUENTIAL 目錄節點,是由於咱們能夠給每臺 Server 編號,咱們能夠選擇當前是最小編號的 Server 爲 Master,假如這個最小編號的 Server 死去,因爲是 EPHEMERAL 節點,死去的 Server 對應的節點也被刪除,因此當前的節點列表中又出現一個最小編號的節點,咱們就選擇這個節點爲當前 Master。這樣就實現了動態選擇 Master,避免了傳統意義上單 Master 容易出現單點故障的問題。
集羣管理結構圖

總結

經過命令行和API使用了zookeeper的基本功能。Zoopkeeper 提供了一套很好的分佈式集羣管理的機制,即基於層次型的目錄樹的數據結構,並對樹中的節點進行有效管理,從而能夠設計出多種多樣的分佈式的數據管理模型。

參考連接:http://www.w3cschool.cn/zookeeper/      http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html      https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/

相關文章
相關標籤/搜索