zookeeper學習02 使用

Allen烽發表於2018-11-13

知識點:
1)zookeeper客戶端的使用
2)zoo.cfg裡面配置資訊的講解
3)zookeeper的一些常見概念模型
4)zookeeper java客戶端的使用

zoo.cfg配置檔案引數分析
tickTime= 2000 zookeeper最小時間單位長度(ms)
initLimit=10 結果是10tickTime follower節點啟動之後與leader節點完成資料同步的時間
syncLimit=5 5
tickTime follower節點與leader節點進行心跳檢測的最大延遲時間
dataDir=/tmp/zookeeper 表示zookeeper伺服器儲存快照檔案的目錄
dataLogDir 表示配置zookeeper事務日誌的儲存日誌 預設指定在dataDir目錄下
clientport 表示客戶端和伺服器建立連線的埠號:2181【預設】

客戶端的操作
先進入客戶端 sh zkCli.sh

zookeeper學習02  使用

看看他有哪些命令

zookeeper學習02  使用
zookeeper中的一些概念 1)資料模型 zookeeper的資料模型和檔案系統類似,每一個節點稱為:znode 是zookeeper中的最小資料單元,每個znode上都可以儲存資料和掛載子節點,從而構成一個層次化的屬性結構。

zookeeper學習02  使用
持久化節點 :節點建立後會一直存在zookeeper伺服器上,直到主動給刪除
持久化有序節點:每個節點都會為他的一級子節點維護一個順序
臨時節點:臨時節點的生命週期和客戶端的會話保持一致,當客戶端會話失效,該節點自動清理
臨時有序節點:臨時節點上多了一個順序性的特性

會話:四種狀態
NOT CONNECTED 未連線
CONNECTING 連線中
CONNECTED 已連線
CLOSED 關閉

watcher
zookeeper 提供了分散式資料釋出/訂閱 ,zookeeper允許客戶端向伺服器註冊一個watcher監聽,當伺服器端的節點觸發指定事件的時候會觸發watcher,服務端會向客戶端傳送一個事件通知
watcher的通知是一次性,一旦觸發一次通知後,該watcher就失效了。
ACL
zookeeper提供了控制節點訪問許可權的功能,用於有效保證zookeeper中資料的安全性,避免誤操作而導致系統出現重大事故。
create/read/write/delete/admin

zookeeper命令
根據上面的說話,zookeeper是基於類似於檔案系統的資料結構
我們先看下它的根

zookeeper學習02  使用
沒有節點的時候我們先建立一個節點
建立節點命令
1) create [-s] [-e] path data acl
-s 代表是否是有序的
-e 代表是否是臨時的
預設是持久化節點
path 代表路徑
data 代表資料
acl 代表許可權

create /lulf 123

zookeeper學習02  使用

我們再來看下這個節點下的是否有值

zookeeper學習02  使用
建立子節點必須要攜帶完整路徑
2)get path [watch]
獲取指定path的資訊

zookeeper學習02  使用

3) set path data [version]
修改節點path對應的data

zookeeper學習02  使用
4) delete path [version]
刪除指定節點
version表示鎖的概念【樂觀鎖】
資料庫中有個version欄位來控制資料行的版本好

zookeeper學習02  使用
stat資訊
節點的狀態資訊
cZxid = 0x100000006 節點被建立時的事務id
ctime = Mon Aug 27 17:05:03 CST 2018 節點被建立時的時間
mZxid = 0x10000000d 節點被最後一次修改的事務id
mtime = Mon Aug 27 18:58:20 CST 2018 節點被最後一次修改的時間
pZxid = 0x100000007 子節點被最後一次修改的事務id
cversion = 1 子節點的版本號
dataVersion = 1 資料版本號
aclVersion = 0 accesscontrol 節點修改許可權
ephemeralOwner = 0x0 建立臨時節點的時候,會有一個sessionid,該值儲存的就是這個id
dataLength = 3 資料長度
numChildren = 1 子節點數

java API的使用 1)匯入jar包

 <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.8</version>
    </dependency>
複製程式碼

2)建立連線

package com.lulf.javaapi;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class CreateSessionDemo {

	private final static String CONNECTSTRING = "192.168.48.128:2181,192.168.48.130:2181,"
			+ "192.168.48.131:2181,192.168.48.132:2181";
	private static CountDownLatch countDownLatch=new CountDownLatch(1);
	public static void main(String[] args) throws IOException, InterruptedException {
		ZooKeeper zooKeeper = new ZooKeeper(CONNECTSTRING, 5000, new Watcher() {
			
			@Override
			public void process(WatchedEvent watchedEvent) {
				//如果當前連線狀態是連線成功的,通過計數器去控制
				if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
					countDownLatch.countDown();
					System.out.println(watchedEvent.getState());
				}
			}
		});
		countDownLatch.await();
		System.out.println("test  "+zooKeeper.getState());
	}
}
複製程式碼

3)建立節點

zookeeper學習02  使用

package com.lulf.javaapi;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

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

public class CreateNodeDemo implements Watcher {

	private final static String CONNECTSTRING = "192.168.48.128:2181,192.168.48.130:2181,"
			+ "192.168.48.131:2181,192.168.48.132:2181";
	private static CountDownLatch countDownLatch = new CountDownLatch(1);
	private static ZooKeeper zooKeeper = null;
	private static Stat stat = new Stat();

	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
		zooKeeper = new ZooKeeper(CONNECTSTRING, 5000, new CreateNodeDemo());
		countDownLatch.await();
		System.out.println("test  " + zooKeeper.getState());
		// 建立節點
		String path = "/FXP";
		byte[] data = "1234".getBytes();
		List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE;
		CreateMode createMode = CreateMode.EPHEMERAL;
		String result = zooKeeper.create(path, data, acl, createMode);
		zooKeeper.getData(path, true, stat);// 增加一個watcher
		System.out.println("建立成功  " + result);

		// 修改資料 -1代表不用管他版本號
		zooKeeper.setData(path, "311".getBytes(), -1);

		//刪除節點	
		zooKeeper.delete(path, -1);
		Thread.sleep(2000);
		
		//建立節點和子節點【這邊要注意只有持久化節點才有子節點】
		zooKeeper.create("/LULF", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		TimeUnit.SECONDS.sleep(1);
		zooKeeper.create("/LULF/lulf1-1", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		TimeUnit.SECONDS.sleep(1);
		
		

	}

	@Override
	public void process(WatchedEvent watchedEvent) {
		// 如果當前連線狀態是連線成功的,通過計數器去控制
		if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
			if (Event.EventType.None == watchedEvent.getType() && null == watchedEvent.getType()) {
				countDownLatch.countDown();
				System.out.println(watchedEvent.getState());
			} else if (watchedEvent.getType() == Event.EventType.NodeDataChanged) {
				try {
					System.out.println("路徑 " + watchedEvent.getPath() + "改變後的值 "
							+ zooKeeper.getData(watchedEvent.getPath(), true, new Stat()));
				} catch (KeeperException | InterruptedException e) {
					e.printStackTrace();
				}
			} else if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {

			} else if (watchedEvent.getType() == Event.EventType.NodeCreated) {
				try {
					System.out.println("路徑 " + watchedEvent.getPath() + "節點的值 "
							+ zooKeeper.getData(watchedEvent.getPath(), true, new Stat()));
				} catch (KeeperException | InterruptedException e) {
					e.printStackTrace();
				}
			} else if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
					System.out.println("刪除路徑 " + watchedEvent.getPath());
			}
		}
	}
}
複製程式碼

許可權控制模式
schema:授權物件
ip : 192.168.48.131
digest : username password
world :開放式的許可權控制模式 訪問許可權對所有使用者開放 world:anyone
super :超級使用者 可以對zookeeper上的資料節點進行操作

zookeeper學習02  使用
如上可以對建立節點做多個要求

連線狀態
1)keeperStat:expored
在一定的時間內客戶端沒有收到伺服器的通知,則認為當前的會話已經過期了,
2)disconnected 斷開連線狀態
3)keeperstat.syncConnected 客戶端和伺服器端在某個節點上建立連線,並且完成一次ersion,
zxid的同步
4)keeperstatus.authFailed 授權失敗

NodeCreated 當節點被建立時觸發
NodeChildrenChanged 標識子節點被建立,被刪除,子節點資料發生變化
NodeDataChanged 節點資料發生改變
NodeDeleted 節點被刪除
None 當客戶端和伺服器連線狀態發生變化的時候,事件型別就是None

zkclient
1)引入jar包

<dependency>
      <groupId>com.101tec</groupId>
      <artifactId>zkclient</artifactId>
      <version>0.10</version>
    </dependency>
複製程式碼

2)建立會話

zookeeper學習02  使用

zookeeper學習02  使用

它的watcher怎麼做呢?

zookeeper學習02  使用

curator
Curator本身是Netfilx公司開源的zookeeper客戶端
curator提供了各種應用場景的實現封裝

curator-framework 提供了fluent風格的api
curator-replice 提供了實現封裝
1)建立seesion
ExponentialBackoffRetry 衰減重試 減少系統負擔 間隔時間 充實次數
RetryNTimes 指定最大重試次數
ReteyOneTime 僅僅重試一次
RetryUnitilElapsed 一直重試知道規定的時間

zookeeper學習02  使用
倆種創立連線的風格

zookeeper學習02  使用
2)增刪改

zookeeper學習02  使用

3)非同步操作及事務處理 Collection transresult=curatorFramework.inTransaction().create().forPath("/trans", "111".getBytes()).and().setData() .forPath("/lll", "555".getBytes()).and().commit();

package com.lulf.curator;

import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

public class CuratorOperationDemo {
	public static void main(String[] args) throws Exception {
		CuratorFramework curatorFramework = CuratorClientUtils.getInstance();
		System.out.println("連線成功。。。。");
		// 建立節點
		curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT)
				.forPath("/curator/curator1-1/curator1-1-1", "123445".getBytes());
		// 刪除節點 預設情況下,version是-1
		curatorFramework.delete().deletingChildrenIfNeeded().forPath("/curator");
		// 獲取資料
		Stat stat = new Stat();
		byte[] bs = curatorFramework.getData().storingStatIn(stat).forPath("/curator");
		String result = new String(bs);
		// 更新
		Stat stat1 = curatorFramework.setData().forPath("/curator", "312".getBytes());

		// 非同步操作
		ExecutorService service = Executors.newFixedThreadPool(1);
		curatorFramework.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT)
				.inBackground(new BackgroundCallback() {
					@Override
					public void processResult(CuratorFramework arg0, CuratorEvent arg1) throws Exception {
						System.out.println(Thread.currentThread().getName() + "-->" + arg1.getResultCode());
					}
				}, service).forPath("/Allen", "allen".getBytes());
		// 事務【curator獨有的】
		Collection<CuratorTransactionResult> transresult=curatorFramework.inTransaction().create().forPath("/trans", "111".getBytes()).and().setData()
				.forPath("/lll", "555".getBytes()).and().commit();
		
		System.out.println("success");

	}

}
複製程式碼

4)事件處理

package com.lulf.curator;

import java.util.concurrent.TimeUnit;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.zookeeper.CreateMode;

public class CuratorEventDemo {
	public static void main(String[] args) throws Exception {
		CuratorFramework curatorFramework = CuratorClientUtils.getInstance();
		//System.out.println("連線成功。。。");
		// curator事件處理
		// 三種watcher來做節點監聽
		// pathcache 監視一個路徑下子節點的建立,刪除節點,資料更新
		// NodeCache 監視一個節點的建立,更新,刪除
		// TreeCache pathcache和nodecache的結合(監視路徑下的建立更新和刪除事件),
		// 快取路徑下所有子節點的資料
		
		//node變化NodeCache
//		NodeCache cache = new NodeCache(curatorFramework, "/lulf", false);
//		cache.start(true);
//		cache.getListenable()
//				.addListener(() -> System.out.println("節點資料發生變化" + new String(cache.getCurrentData().getData())));
//		curatorFramework.setData().forPath("/lulf", "gbcq".getBytes());
	
		
		//pathcache
		PathChildrenCache cache2=new PathChildrenCache(curatorFramework, "/event", false);
		cache2.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
		cache2.getListenable().addListener((curatorFramework1,PathChildrenCacheEvent)->{
			switch (PathChildrenCacheEvent.getType()) {
			case CHILD_ADDED:
				System.out.println("增加子節點");
				break;
            case CHILD_REMOVED:
            	System.out.println("刪除子節點");
				break; 
            case CHILD_UPDATED:
            	System.out.println("更新子節點");
				break; 
			default:
				break;
			}
		});
		curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event", "1".getBytes());
		TimeUnit.SECONDS.sleep(1);
		curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath("/event/event1", "1.1".getBytes());
		TimeUnit.SECONDS.sleep(1);
		curatorFramework.setData().forPath("/event/event1", "1.2".getBytes());
		curatorFramework.delete().forPath("/event/event1");
		System.in.read();
	}
}
複製程式碼

相關文章