Zookeeper之原生連接、數據存儲和事件機制

鑑於前面幾篇博客已經將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 原生操作到這裏就完事了

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