Zookeeper簡單使用


zookeeper命令行操作

  • 運行 zkCli.sh –server <ip>進(jìn)入命令行工具
  • 使用 ls 命令來查看當(dāng)前 ZooKeeper 中所包含的內(nèi)容:
    • ls /
  • 創(chuàng)建一個新的 znode 月幌,使用 create /zk myData 。這個命令創(chuàng)建了一個新的 znode 節(jié)點“ zk ”以及與它關(guān)聯(lián)的字符串:
    • create /zk "myData"
  • 我們運行 get 命令來確認(rèn) znode 是否包含我們所創(chuàng)建的字符串:
    • get /zk
  • 監(jiān)聽這個節(jié)點的變化,當(dāng)另外一個客戶端改變/zk時,它會打出下面的
    • get /zk watch

WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk

  • 下面我們通過 set 命令來對 zk 所關(guān)聯(lián)的字符串進(jìn)行設(shè)置:
    • set /zk "zsl"
  • 下面我們將剛才創(chuàng)建的 znode 刪除:
    • delete /zk
  • 刪除節(jié)點:
    • rmr /zk

zookeeper-api應(yīng)用

功能 描述
create 在本地目錄樹中創(chuàng)建一個節(jié)點
delete 刪除一個節(jié)點
exists 測試本地是否存在目標(biāo)節(jié)點
get/set data 從目標(biāo)節(jié)點上讀取 / 寫數(shù)據(jù)
get/set ACL 獲取 / 設(shè)置目標(biāo)節(jié)點訪問控制列表信息
get children 檢索一個子節(jié)點上的列表
sync 等待要被傳送的數(shù)據(jù)

demo代碼

import java.io.IOException;
import java.util.List;

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.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

public class SimpleZkClient {

    private static final String connectString = "192.168.127.61:2181,192.168.127.62:2181,192.168.127.63:2181";
    private static final int sessionTimeout = 2000;

    ZooKeeper zkClient = null;

    @Before
    public void init() throws Exception {
        zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                // 收到事件通知后的回調(diào)函數(shù)(應(yīng)該是我們自己的事件處理邏輯)
                System.out.println(event.getType() + "---" + event.getPath());
                try {
                    zkClient.getChildren("/", true);
                } catch (Exception e) {
                }
            }
        });

    }

    /**
     * 數(shù)據(jù)的增刪改查
     * 
     * @throws InterruptedException
     * @throws KeeperException
     */

    // 創(chuàng)建數(shù)據(jù)節(jié)點到zk中
    public void testCreate() throws KeeperException, InterruptedException {
        // 參數(shù)1:要創(chuàng)建的節(jié)點的路徑 參數(shù)2:節(jié)點大數(shù)據(jù) 參數(shù)3:節(jié)點的權(quán)限 參數(shù)4:節(jié)點的類型
        String nodeCreated = zkClient.create("/eclipse", "hellozk".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        //上傳的數(shù)據(jù)可以是任何類型矢空,但都要轉(zhuǎn)成byte[]
    }

    //判斷znode是否存在
    @Test   
    public void testExist() throws Exception{
        Stat stat = zkClient.exists("/eclipse", false);
        System.out.println(stat==null?"not exist":"exist");
        
        
    }
    
    // 獲取子節(jié)點
    @Test
    public void getChildren() throws Exception {
        List<String> children = zkClient.getChildren("/", true);
        for (String child : children) {
            System.out.println(child);
        }
        Thread.sleep(Long.MAX_VALUE);
    }

    //獲取znode的數(shù)據(jù)
    @Test
    public void getData() throws Exception {
        
        byte[] data = zkClient.getData("/eclipse", false, null);
        System.out.println(new String(data));
        
    }
    
    //刪除znode
    @Test
    public void deleteZnode() throws Exception {
        
        //參數(shù)2:指定要刪除的版本霍弹,-1表示刪除所有版本
        zkClient.delete("/eclipse", -1);
        
        
    }
    //刪除znode
    @Test
    public void setData() throws Exception {
        
        zkClient.setData("/app1", "imissyou angelababy".getBytes(), -1);
        
        byte[] data = zkClient.getData("/app1", false, null);
        System.out.println(new String(data));
        
    }
    
    
}

Zookeeper的監(jiān)聽器工作機制

  • 監(jiān)聽器是一個接口楣铁,我們的代碼中可以實現(xiàn)Wather這個接口,實現(xiàn)其中的process方法,方法中即我們自己的業(yè)務(wù)邏輯
  • 監(jiān)聽器的注冊是在獲取數(shù)據(jù)的操作中實現(xiàn):
    • getData(path,watch?)監(jiān)聽的事件是:節(jié)點數(shù)據(jù)變化事件
    • getChildren(path,watch?)監(jiān)聽的事件是:節(jié)點下的子節(jié)點增減變化事件

分布式共享鎖的簡單實現(xiàn)

import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class DistributedClientLock {
    

    // 會話超時
    private static final int SESSION_TIMEOUT = 2000;
    // zookeeper集群地址
    private String hosts = "mini1:2181,mini2:2181,mini3:2181";
    private String groupNode = "locks";
    private String subNode = "sub";
    private boolean haveLock = false;

    private ZooKeeper zk;
    // 記錄自己創(chuàng)建的子節(jié)點路徑
    private volatile String thisPath;

    /**
     * 連接zookeeper
     */
    public void connectZookeeper() throws Exception {
        zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {
            public void process(WatchedEvent event) {
                try {

                    // 判斷事件類型房交,此處只處理子節(jié)點變化事件
                    if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals("/" + groupNode)) {
                        //獲取子節(jié)點帜篇,并對父節(jié)點進(jìn)行監(jiān)聽
                        List<String> childrenNodes = zk.getChildren("/" + groupNode, true);
                        String thisNode = thisPath.substring(("/" + groupNode + "/").length());
                        // 去比較是否自己是最小id
                        Collections.sort(childrenNodes);
                        if (childrenNodes.indexOf(thisNode) == 0) {
                            //訪問共享資源處理業(yè)務(wù)糙捺,并且在處理完成之后刪除鎖
                            doSomething();
                            
                            //重新注冊一把新的鎖
                            thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                                    CreateMode.EPHEMERAL_SEQUENTIAL);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        // 1、程序一進(jìn)來就先注冊一把鎖到zk上
        thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL_SEQUENTIAL);

        // wait一小會笙隙,便于觀察
        Thread.sleep(new Random().nextInt(1000));

        // 從zk的鎖父目錄下洪灯,獲取所有子節(jié)點,并且注冊對父節(jié)點的監(jiān)聽
        List<String> childrenNodes = zk.getChildren("/" + groupNode, true);

        //如果爭搶資源的程序就只有自己竟痰,則可以直接去訪問共享資源 
        if (childrenNodes.size() == 1) {
            doSomething();
            thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
                    CreateMode.EPHEMERAL_SEQUENTIAL);
        }
    }

    /**
     * 處理業(yè)務(wù)邏輯签钩,并且在最后釋放鎖
     */
    private void doSomething() throws Exception {
        try {
            System.out.println("gain lock: " + thisPath);
            Thread.sleep(2000);
            // do something
        } finally {
            System.out.println("finished: " + thisPath);
            //釋放鎖
            zk.delete(this.thisPath, -1);
        }
    }

    public static void main(String[] args) throws Exception {
        DistributedClientLock dl = new DistributedClientLock();
        dl.connectZookeeper();
        Thread.sleep(Long.MAX_VALUE);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掏呼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铅檩,更是在濱河造成了極大的恐慌憎夷,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昧旨,死亡現(xiàn)場離奇詭異拾给,居然都是意外死亡,警方通過查閱死者的電腦和手機臼予,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門鸣戴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人粘拾,你說我怎么就攤上這事窄锅。” “怎么了缰雇?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵入偷,是天一觀的道長。 經(jīng)常有香客問我械哟,道長疏之,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任暇咆,我火速辦了婚禮锋爪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘爸业。我一直安慰自己其骄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布扯旷。 她就那樣靜靜地躺著拯爽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钧忽。 梳的紋絲不亂的頭發(fā)上毯炮,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音耸黑,去河邊找鬼桃煎。 笑死,一個胖子當(dāng)著我的面吹牛崎坊,可吹牛的內(nèi)容都是我干的备禀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼奈揍,長吁一口氣:“原來是場噩夢啊……” “哼曲尸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起男翰,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤另患,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蛾绎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昆箕,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年租冠,在試婚紗的時候發(fā)現(xiàn)自己被綠了鹏倘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡顽爹,死狀恐怖纤泵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情镜粤,我是刑警寧澤捏题,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站肉渴,受9級特大地震影響公荧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜同规,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一循狰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧券勺,春花似錦绪钥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盗扒,卻和暖如春跪楞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侣灶。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工甸祭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褥影。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓池户,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子校焦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容