Zookeeper(一) —— 環境搭建

1、概述

集中式 向 分佈式演變,高併發、海量存儲java

應用場景:apache

* 數據發佈、訂閱的兩種方式:推模式、拉模式
* 命名服務
* 分佈式協調/通知(心跳檢測)
* 負載均衡

自增加id和uuid的缺點,前者只能在單表中使用,後者可在分佈式環境使用,但不易於理解、尋找規律api

2、基本概念

一、集羣中的角色:服務器

* Leader
* Follower
* Observer

二、會話併發

客戶端與Zookeeper的鏈接,其鏈接是經過TCP長鏈接,保持會話,客戶端會向Zookeeper端上報心跳。會話也被叫作Session

三、版本負載均衡

版本的做用是進行分佈式鎖控制,鎖分爲兩種,悲觀鎖和樂觀鎖
悲觀鎖適合併發競爭激烈的場景,能避免數據不一致的狀況,上一個事務沒完成,下一個事務不能開始。樂觀鎖的併發控制是,加入版本號,每次讀取記錄時首先會得到版本號,插入數據時,也會將版本號帶到參數中,若更新失敗,說明其餘事務已經修改過數據,會拋出異常給客戶端,讓其進行處理(重試)

version 當前數據內容節點版本號
cversion 當前數據子節點版本號
aversion 當前數據節點ACL變動版本號

四、節點分佈式

服務器(節點)
數據模型中的節點高併發

五、watcher測試

客戶端能夠在zookeeper中註冊watcher,當zookpeer上的內容改變時,會通知客戶端獲取ui

六、ACL權限控制

CREATE 建立子節點的權限
READ 讀取節點數據、子節點列表的權限
WRITE 更新節點數據的權限
DELETE 刪除子節點的權限
ADMIN 設置節點ACL權限

3、環境安裝

一、建立文件夾
/opt 用來安裝本身的應用軟件
/var 用來存放日誌輸出

二、下載zookeeper
wget 下載連接

三、進行配置
(1)修改Zoo.cfg

dataDir 是用來存放數據快照
clientPort 對外提供的端口號,默認2181
server.id=ip:port:port

server.1=ip:port:port
server.2=ip:port:port
server.3=ip:port:port

(2)在/var/zookeeper中建立myid,內容爲id編號,如1

四、啓動

export ZK_HOME = /../zookeeper
export PATH=\(PATH:\)ZK_HOME/bin

Zookeeper/bin zkServer.sh start
telnet ip port(2181)
輸入 stat 查看狀態

4、zk命令

一、啓動客戶端鏈接到服務器
zkCli.sh -server serverip:2181

help

quit

ls /   //列出節點

create  /path content

get /path   //查看數據

set /path conent //設置數據

delete  /path      //刪除一個節點

rmr /a                //遞歸刪除全部節點

5、經過API訪問zk

一、獲取根下的目錄

(1) 導入依賴包

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>

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

(2)測試代碼

fonxian1 對應的是zk服務器的ip地址

@org.junit.Test
public void ls() throws Exception{
    ZooKeeper zk = new ZooKeeper("fonxian1:2181",10000,null);
    List<String> list = zk.getChildren("/",false);
    for(String str:list){
     System.out.println(str);
    }

}

二、遞歸獲取根下全部文件名

@org.junit.Test
    public void lsAll() {
        try {
            ls("/");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void ls(String path) throws Exception {

        ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
        List<String> list = zk.getChildren(path, false);
        if (list == null || list.isEmpty()) {
            return;
        }
        for (String str : list) {
            if ("/".equals(path)) {
                System.out.println(path + str);
                ls(path + str);
            } else {
                System.out.println(path + "/" + str);
                ls(path + "/" + str);
            }

        }

    }

三、添加數據

@org.junit.Test
    public void setData () {

        try{
        ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
        zk.setData("/a","fonxian".getBytes(),2);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

出現版本號錯誤的提示

org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /a

    at org.apache.zookeeper.KeeperException.create(KeeperException.java:115)
    at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
    at org.apache.zookeeper.ZooKeeper.setData(ZooKeeper.java:1327)
    at com.fonxian.ZookeepTest.setData(ZookeepTest.java:47)

緣由是Zookeeper服務器中/a的版本號爲0,將代碼中的版本號設置爲0,便可執行成功

[zk: 127.0.0.1(CONNECTED) 0] get /a
tom
cZxid = 0x200000002
ctime = Sun Mar 18 15:49:45 CST 2018
mZxid = 0x200000002
mtime = Sun Mar 18 15:49:45 CST 2018
pZxid = 0x20000000f
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 3

四、添加臨時節點

create [-s] [-e] path data acl

參數s ,表示序列節點,會在父節點下建立一個10個0+父節點名的節點
參數e,表示臨時節點,臨時節點在會話結束時會被刪除,在leader選舉中扮演重要做用

@Test
    public void setTempData() {

        try {

            ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
            zk.create("/a/t","fonxian".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.EPHEMERAL);
            System.out.println("hello");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

五、使用觀察者

觀察者的做用在於,當數據發生修改,服務器會通知客戶端數據修改,每次註冊,只會通知一次。

@Test
    public void testWatch(){

        try {

            final ZooKeeper zk = new ZooKeeper("fonxian1:2181", 50000, null);

            Watcher w = new Watcher() {

                public void process(WatchedEvent watchedEvent) {
                    try{
                        System.out.println("data change");
                        byte[] newData = zk.getData("/a",this,null);
                        System.out.println("new data = "+new String(newData));
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            } ;

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

            while(true){

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
相關文章
相關標籤/搜索