ZooKeeper 入門

0 介紹

官網:http://zookeeper.apache.org/html

ZooKeeper是Hadoop的正式子項目,它是一個針對大型分佈式系統的可靠協調系統,提供的功能包括:配置維護、名字服務、分佈式同步、組服務等。ZooKeeper的目標就是封裝好複雜易出錯的關鍵服務,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。java

ZooKeeper代碼版本中,提供了分佈式獨享鎖、選舉、隊列的接口,代碼在zookeeper-x.x.x\src\recipes。其中分佈鎖和隊列有Java和C兩個版本,選舉只有Java版本。node

ZooKeeper是能夠集羣複製的,集羣間經過Zab(ZooKeeper Atomic Broadcast)協議來保持數據的一致性。apache

原理:http://cailin.iteye.com/blog/2014486/api


1 安裝

1.1 前提

需配置Java運行環境服務器

1.2 下載

http://mirrors.cnnic.cn/apache/zookeeper架構

https://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz分佈式

1.3 解壓

解壓到本身想要的目錄便可ide

1.4 配置

可經過複製conf/zoo_sample.cfg文件,命名爲zoo.cfg,而後進行修改。oop

示例

# ZooKeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每一個 tickTime 時間就會發送一個心跳。
tickTime=2000

# 投票選舉新leader的初始化時間
initLimit=10

# 集羣中的follower服務器與leader服務器之間請求和應答之間能容忍的最多心跳數(tickTime的數量)
syncLimit=5

# 保存數據的目錄
dataDir=D:\\zookeeper\\data
#保存日誌文件的目錄
dataLogDir=D:\\zookeeper\\log

# 客戶端啓動端口
clientPort=2181

1.5 運行

雙擊bin/zkServer.cmd啓動ZooKeeper啓動服務端。

bin\zkCli.cmd -server 127.0.0.1:2181啓動客戶端操做。


2 結構

ZooKeeper的核心相似一個精簡的文件系統,提供一些簡單的操做和一些附件的抽象(例如,znode的排序與watch)。

有4種節點類型

類型 說明
持久節點(PERSISTENT) 節點建立後,就一直存在,直到有刪除操做來主動清除這個節點
持久順序節點(PERSISTENT_SEQUENTIAL) 持久化節點,每一個父節點會爲他的第一級子節點維護一個單調增數
臨時節點(EPHEMERAL) 臨時節點的生命週期和客戶端會話綁定。也就是說,若是客戶端會話失效,那麼這個節點就會自動被清除掉。
臨時順序節點(EPHEMERAL_SEQUENTIAL) 臨時節點,每一個父節點會爲他的第一級子節點維護一個單調增數,可用於實現分佈式鎖

3 經常使用命令

  • help:查看可執行的命令
  • quit:退出客戶端
  • ls:查看某個節點下的數據
  • create:在某個節點下建立子節點
  • delete:刪除子節點
  • rmr:刪除路徑
  • get:獲取節點數據
  • set:設置節點數據

4 在Java中進行使用

導入相應的jar包,這裏使用Maven進行jar包的管理,以下配置

<zookeeper.version>3.4.10</zookeeper.version>
<zkclient.version>0.10</zkclient.version>

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>${zookeeper.version}</version>
</dependency>
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>${zkclient.version}</version>
</dependency>

org.apache.zookeeper.ZooKeeper的使用

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.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZooKeeperTest {
    private static final String ZK_CONNECT_URL = "127.0.0.1:2181";
    private static final int SESSION_TIMEOUT = 3000;
    
    // 這裏直接拋出Exception,實際項目中須要自行捕獲異常
    public static void main(String[] args) throws Exception {
        ZooKeeper zooKeeper = new ZooKeeper(ZK_CONNECT_URL, SESSION_TIMEOUT, null);
        // 設置監聽器
        zooKeeper.register(new ZkWatcher(zooKeeper, "/root"));
        
        // 建立root節點,其包含的數據爲「root data」,設置訪問權限爲全部人都可訪問,建立模式爲持久化節點
        zooKeeper.create("/root", "root data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        
        // 設置節點內容,-1無視版本,若是版本與服務器上版本不一致則拋出異常
        zooKeeper.setData("/root", "new data".getBytes(), -1);
        
        // 獲取節點內容
        Stat stat = new Stat();
        System.out.println(new String(zooKeeper.getData("/root", false, stat)));

        // 建立子節點
        zooKeeper.create("/root/child", "child".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        
        // 刪除節點,必須先刪除子節點才能刪除根節點,否則會報錯
        zooKeeper.delete("/root/child", -1);
        zooKeeper.delete("/root", -1);
    }
    
    // 節點監聽器
    private static class ZkWatcher implements Watcher {
        private ZooKeeper zooKeeper;
        private String path;
        
        public ZkWatcher(ZooKeeper zooKeeper, String path) {
            this.zooKeeper = zooKeeper;
            this.path = path;
        }
        
        @Override
        public void process(WatchedEvent event) {
            System.out.println("watcher:" + event.getType());
            // 因爲Watcher的監聽只能是一次性,因此須要這樣處理,或者改用ZkClient進行實現
            try {
                zooKeeper.exists(path, true);
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

org.I0Itec.zkclient.ZkClient的使用

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;

public class ZkClientTest {
    private static final String ZK_CONNECT_URL = "127.0.0.1:2181";
    private static final String PATH = "/zkclient";
    
    public static void main(String[] args) {
        ZkClient zkClient = new ZkClient(ZK_CONNECT_URL);
        
        zkClient.subscribeDataChanges(PATH, new IZkDataListener() {
            
            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("handleDataDeleted dataPath:" + dataPath);
            }
            
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {
                System.out.println("handleDataChange dataPath:" + dataPath + " data:" + data);
                
            }
        });
        
        // 建立節點
        zkClient.create(PATH, "Hello", CreateMode.PERSISTENT);
        
        // 設置節點數據
        zkClient.writeData(PATH, "new");
        
        // 獲取數據
        System.out.println(zkClient.readData(PATH));
        
        // 建立子節點
        zkClient.create(PATH + "/child", "child", CreateMode.PERSISTENT);
        
        // 獲取子節點信息
        System.out.println(zkClient.getChildren(PATH));
        
        // 刪除節點
        zkClient.delete(PATH + "/child");
        zkClient.delete(PATH);
    }

}

參考資料

  • http://zookeeper.apache.org/
  • http://zookeeper.apache.org/doc/r3.4.10/api/index.html
  • http://zookeeper.apache.org/doc/r3.4.10/zookeeperStarted.html
  • 陳康賢的《大型分佈式網站架構設計與實踐》
相關文章
相關標籤/搜索