鑑於前面幾篇博客已經將zookeeper單機和集羣搭建完成,現在我們來了解下如何使用代碼操作zookeeper
本文是建立連接和數據存儲
直接開始乾貨:
首先pom文件引入zookeeper依賴,我裝的版本是3.6.0 大家根據情況來定。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
碼來~~~~
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 11:28 上午
* @Version: 1.0
*/
public class ZookeeperClient {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
//這裏綁定zookeeper服務器除了 observe 都要寫上 因爲可能出現任何一臺機器成爲leader 4000是心跳
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
// watcher 的概念建議請看下面
@Override
public void process(WatchedEvent watchedEvent) {
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服務端的響應事件,連接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
//添加節點 ACL:ZooDefs.Ids.OPEN_ACL_UNSAFE權限控制 open是任何人都可以訪問,PERSISTENT節點類型爲持久化
zooKeeper.create("/zk-persis-liaryank","0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
Thread.sleep(1000);
Stat stat=new Stat();
//得到當前節點的值 stat是當前節點的值 也就是自己創建的/zk-persis-liaryank的值
byte[] bytes=zooKeeper.getData("/zk-persis-liaryank",null,stat);
System.out.println(new String(bytes));
//修改節點值 Version這裏是屬於樂觀鎖
zooKeeper.setData("/zk-persis-liaryank","1".getBytes(),stat.getVersion());
//得到當前節點的值
byte[] bytes1=zooKeeper.getData("/zk-persis-liaryank",null,stat);
System.out.println(new String(bytes1));
//zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("關閉連接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
}
運行結果
服務器端查看 stat就是下面圖中的數據,都可以獲取到,可以自行打印輸出下
已經將0 改爲了1
再試試刪除
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 11:28 上午
* @Version: 1.0
*/
public class ZookeeperClient {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服務端的響應事件,連接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
Stat stat=new Stat();
//得到當前節點的值
byte[] bytes=zooKeeper.getData("/zk-persis-liaryank",null,stat);
zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("關閉連接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
運行結果
你可以將刪除直接寫到上邊一起執行一下 加點打印輸出就可以看到完整的增刪改查效果了。
ok現在我們來講事件機制
講事件機制前先補充一下watcher
Watcher 監聽機制是 Zookeeper 中非常重要的特性,我們 基於 zookeeper 上創建的節點,可以對這些節點綁定監聽 事件,比如可以監聽節點數據變更、節點刪除、子節點狀 態變更等事件,通過這個事件機制,可以基於 zookeeper 實現分佈式鎖、集羣管理等功能.
watcher 特性:當數據發生變化的時候, zookeeper 會產 生一個 watcher 事件,並且會發送到客戶端。但是客戶端 只會收到一次通知。如果後續這個節點再次發生變化,那 麼之前設置 watcher 的客戶端不會再次收到消息。 (watcher 是一次性的操作)。 可以通過循環監聽去達到 永久監聽效果.
註冊事件機制: 通過這三個操作來綁定事件 :getData、Exists、getChildren
觸發事件: 凡是事務類型的操作,都會觸發監聽事件。 create /delete /setData
watcher 事件類型
None (-1), 客戶端鏈接狀態發生變化的時候,會收到 none 的事件
NodeCreated (1), 創建節點的事件。 比如zk-persis-liaryank時
NodeDeleted (2), 刪除節點事件。
NodeDataChanged (3), 節點數據發生變更時。
NodeChildrenChanged (4); 子節點被創建、被刪除、會 發生事件觸發
碼來~~~
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 3:19 下午
* @Version: 1.0
*/
public class WatcherDemo {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("全局默認事件:"+watchedEvent.getType());
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服務端的響應事件,連接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
zooKeeper.create("/zk-persis-liaryank","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//這裏通過exits綁定事件
Stat stat = zooKeeper.exists("/zk-persis-liaryank", new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent.getType()+"==>"+watchedEvent.getPath());
try {
//再一次綁定事件,相當於永久註冊監聽 這裏設置的true 是全局的watch
zooKeeper.exists(watchedEvent.getPath(),true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//修改事務類型的操作來出發監聽事件
stat=zooKeeper.setData("/zk-persis-liaryank","2".getBytes(),stat.getVersion());
Thread.sleep(1000);
//然後刪除
zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
//修改的時候讓該內容進入只讀狀態
System.in.read();
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("關閉連接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
}
運行結果如下
ok 原生操作到這裏就完事了