官網: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
需配置Java運行環境服務器
http://mirrors.cnnic.cn/apache/zookeeper架構
https://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz分佈式
解壓到本身想要的目錄便可ide
可經過複製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
雙擊bin/zkServer.cmd
啓動ZooKeeper啓動服務端。
bin\zkCli.cmd -server 127.0.0.1:2181
啓動客戶端操做。
ZooKeeper的核心相似一個精簡的文件系統,提供一些簡單的操做和一些附件的抽象(例如,znode的排序與watch)。
有4種節點類型
類型 | 說明 |
---|---|
持久節點(PERSISTENT) | 節點建立後,就一直存在,直到有刪除操做來主動清除這個節點 |
持久順序節點(PERSISTENT_SEQUENTIAL) | 持久化節點,每一個父節點會爲他的第一級子節點維護一個單調增數 |
臨時節點(EPHEMERAL) | 臨時節點的生命週期和客戶端會話綁定。也就是說,若是客戶端會話失效,那麼這個節點就會自動被清除掉。 |
臨時順序節點(EPHEMERAL_SEQUENTIAL) | 臨時節點,每一個父節點會爲他的第一級子節點維護一個單調增數,可用於實現分佈式鎖 |
導入相應的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); } }