ZooKeeper 入門


0 介紹

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

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

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

ZooKeeper是可以集群復制的,集群間通過Zab(ZooKeeper Atomic Broadcast)協議來保持數據的一致性。

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


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 解壓

解壓到自己想要的目錄即可

1.4 配置

可通過復制conf/zoo_sample.cfg文件,命名為zoo.cfg,然后進行修改。

示例

# 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);
	}

}

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM