zookeeper之原生API和zkClient的API

1 ZK的原生API

1.1 java操作原生API

1.1.1 引入依賴

使用java操作zookeeper,引入maven座標

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

1.1.2 創建會話

創建會話方法:客戶端通過創建一個zookeeper實例來鏈接zookeeper服務器
Zookeeper提供了4個構造方法,根據所提供的參數不同
參數說明如下:

  • connectString:連接服務器列表,如果有多個則用分隔
  • sessionTimeout:心跳檢測時間週期(毫秒
  • wather:事件處理通知器
  • canBeReadOnly:標識當前會話是否支持只讀
  • sessionId和sessionPassword:提供連接zookeepersession和密碼,通過這兩個確定唯一一臺客戶端,目的可以提供重複會話

注意zookeeper客戶端和服務器端會話的建立是一個異步過程,也就是說在程序中,我們程序方法在處理完客戶端初始化後立即返回(也就是說程序往下執行代碼,這樣,大多數情況下我們並沒有真正構建一個可用會話,在會話的生命週期處於CONNECTING時纔算真正建立完畢,所以我們需要使用多線程中學習的一個小工具類)

public class ZooKeeperDemo{
	//zk 連接地址
	private static final String CONNECT_ADDR="192.168.126.130:2181";
	//session 超時時間
	private static final Integer SESSION_OUTTIME=5000;
	//阻塞程序執行,用於等待zookeeper連接成功,發送成功信號
	private static CountDownLatch countDown = new CountDownLatch(1);
	public static void main(String[] args) throws Exception{
		//zk 連接
		ZooKeeper zk = new ZooKeeper(CONNECT_ADDR,SESSION_OUTTIME,new Watcher(){
			@Override
			public void process(WatchedEvent event){				
					Event.KeeperState state = event.getState();
					Event.EventType type = event.getType();
					//如果建立了安全連接
					if(Event.KeeperState.SyncConnected==state){
						if(Event.EventType.None==type){
							//如果連接建立成功,則發送信號
							countDown.countDown();
							System.out.println("zk 建立連接");
						}
					}			
			}
		});
		//進行阻塞
		countDown.await();
		System.out.println("zk 執行了");
		//關閉會話
		zk.close();
	}
}

1.1.3 節點的CRUD

1.1.3.1 創建節點

創建節點方法:create
有兩種創建節點的方法:同步異步創建節點方式
同步方式:

  • 參數1,節點路徑(名稱):/nodeName(不允許遞歸創建節點,也就是說在父節點不存在的情況下,不允許創建子節點)
  • 參數2,節點內容: 要求類型是字節數組
  • 參數3,節點權限:使用Ids.OPEN_ACL_UNSAFE開發權限即可。(這個參數一般在權限沒有太高要求的場景下,沒必要關注)
  • 參數4,節點類型:創建節點的類型:CreateMode.*,提供以下幾種節點類型:
    PERSISENT:持久節點
    PERSISENT_SEQUENTIAL:持久順序節點
    EPHEMERAL:臨時節點
    EPHEMERAL_SEQUENTIAL:臨時順序節點
    CONTAINER:容器節點,用於LeaderLock等特殊用途,當容器節點不存在任何子節點時,容器將成爲服務器在將來某個時候刪除的候選節點
    PERSISTENT_WITH_TTL:帶TTLtime-to-live,存活時間)的永久節點,節點在TTL時間之內沒有得到更新並且沒有孩子節點,就會被自動刪除
    PERSISTENT_SEQUENTIAL_WITH_TTL:帶TTLtime-to-live,存活時間)和單調遞增序號的永久節點,節點在TTL時間之內沒有得到更新並且沒有孩子節點,就會被自動刪除
//創建父節點,此處的zk是上一步的會話產生的
String ret = zk.create("/testRoot","testRoot".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISENT);
System.out.println(ret);

注意:臨時節點效率很高,主要用來作爲分佈式鎖

異步方式:(在同步方式參數基礎上增加倆參數)

  • 參數5,註冊一個異步回調函數,要實現AsynCallBack.VoidCallBack接口,重寫processResult(int rc,String path,Obejct ctx,String name)方法,當節點創建完畢後執行此方法
    rc:爲服務端響應碼,0表示調用成功,-4表示端口連接,-110表示指定節點存在,-112表示會話已經過期
    path:接口調用時傳入API的數據節點的路徑參數
    ctx:爲調用接口傳入APIctx的值
    name:實際在服務器端創建節點的名稱
  • 參數6,傳遞給回調函數的參數,一般爲上下文(context)信息
//此處的 -1是跳過版本限制 dataVersion ,在刪除時如果傳入的版本號不是-1 與現有版本號一致,那麼可以刪除
zk.delete("/testRoot",-1,new AsynCallBack.VoidCallBack(){
	@Override
	public void processResult(int rc,String path,Object ctx){
		System.out.println(rc);
		System.out.println(path);
		System.out.println(ctx);	
	}
},"a");

1.1.3.2 修改節點

//此處的-1 也是跳過版本號的檢查
zk.setData("/testRoot","modify data root".getBytes(),-1);

1.1.3.3 判斷是否存在

判斷節點是否存在

//  參數一:路徑,參數二:是否watch監聽
zk.exists("/testRoot",false);

1.1.3.4 獲取節點值

byte[] data = zk.getData("/testRoot", false, null);
System.out.println(new String(data));
System.out.println(zk.getChildren("/testRoot", false));

1.1.3.5 刪除節點

//刪除節點
zk.delete("/testRoot/children", -1);
System.out.println(zk.exists("/testRoot/children", false));

2 zkClient的API

2.1 引入pom依賴

<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>

2.2 操作客戶端

2.2.1 創建客戶端

/** zookeeper地址 */
	static final String CONNECT_ADDR = "192.168.1.171:2181,192.168.1.172:2181,192.168.1.173:2181";
	/** session超時時間 */
	static final int SESSION_OUTTIME = 5000;//ms 
		
	public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 5000);
		
	}

2.2.2 增加和刪除節點

可以遞歸增加和刪除節點

創建節點時,那個true是否創建父節點

//1. create and delete方法 
		zkc.createEphemeral("/temp");
		//第二個參數createParents==true,表示父節點不存在時創建父節點(遞歸創建)
		zkc.createPersistent("/super/c1", true);
		Thread.sleep(10000);
		zkc.delete("/temp");
		zkc.deleteRecursive("/super");

2.2.3 讀取節點

//2. 設置path和data 並且讀取子節點和每個節點的內容
	zkc.createPersistent("/super", "1234");
	zkc.createPersistent("/super/c1", "c1內容");
	zkc.createPersistent("/super/c2", "c2內容");
	List<String> list = zkc.getChildren("/super");
	for(String p : list){
		System.out.println(p);
		String rp = "/super/" + p;
		//此處的readData是原生API
			String data = zkc.readData(rp);
			System.out.println("節點爲:" + rp + ",內容爲: " + data);
	}

2.2.4 判斷是否存在

		//3. 更新和判斷節點是否存在
		zkc.writeData("/super/c1", "新內容");
		System.out.println(zkc.readData("/super/c1"));
		System.out.println(zkc.exists("/super/c1"));

2.3 zkClinet不需要watcher

zkClient不用watcherwatcher參數,也就是說我們開發人員無需關心反覆註冊Watcher的問題,zkclient給我們提供了一套監聽方式,可以使用監聽節點的方式進行操作,剔除了繁瑣的反覆watcher操作,簡化了代碼的複雜程度

2.3.1 subscribeChildChanges方法

只監聽父子節點的新增和刪除,但是節點變化不監聽

  • 參數一:path路徑
  • 參數二:實現了IZkChildListener接口的類
public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 5000);		
		//對父節點添加監聽子節點變化。
		zkc.subscribeChildChanges("/super", new IZkChildListener() {
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println("parentPath: " + parentPath);
				System.out.println("currentChilds: " + currentChilds);
			}
		});
		Thread.sleep(3000);		
		zkc.createPersistent("/super");
		Thread.sleep(1000);		
		zkc.createPersistent("/super" + "/" + "c1", "c1內容");
		Thread.sleep(1000);		
		zkc.createPersistent("/super" + "/" + "c2", "c2內容");
		Thread.sleep(1000);		
		zkc.delete("/super/c2");
		Thread.sleep(1000);			
		zkc.deleteRecursive("/super");
		Thread.sleep(Integer.MAX_VALUE);
	}

在這裏插入圖片描述

2.3.2 subscribeDataChanges方法

主要監聽節點的刪除和改變

public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 5000);		
		zkc.createPersistent("/super", "1234");		
		//對父節點添加監聽子節點變化。
		zkc.subscribeDataChanges("/super", new IZkDataListener() {
			@Override
			public void handleDataDeleted(String path) throws Exception {
				System.out.println("刪除的節點爲:" + path);
			}			
			@Override
			public void handleDataChange(String path, Object data) throws Exception {
				System.out.println("變更的節點爲:" + path + ", 變更內容爲:" + data);
			}
		});		
		Thread.sleep(3000);
		zkc.writeData("/super", "456", -1);
		Thread.sleep(1000);

		zkc.delete("/super");
		Thread.sleep(Integer.MAX_VALUE);
	}

在這裏插入圖片描述

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