Zookeeper入門(mén)之三-Java客戶端curator的使用

ZK的java客戶端—curator 基本使用

普通的增刪改查實(shí)現(xiàn)--同步接口
 public class CuratorConTest {

    static RetryPolicy policy = new ExponentialBackoffRetry(1000, 3); // 重試3次

    // 創(chuàng)建連接 -- 傳統(tǒng)寫(xiě)法
/*        CuratorFramework zkClient = CuratorFrameworkFactory.newClient("localhost:32770",
                5000,
                3000,
                policy);*/

    // 創(chuàng)建連接-- 流式寫(xiě)法
    static CuratorFramework zkFluentClient = CuratorFrameworkFactory.builder()
            .connectString("localhost:32770")
            .sessionTimeoutMs(5000)
            .connectionTimeoutMs(3000)
            .retryPolicy(policy)
            .namespace("zk-jsy")  // 如果指定了某個(gè)應(yīng)用只能在某一個(gè)節(jié)點(diǎn)下操作配深,
            // 可以指定namespace,這里base表示路徑為/base痊末。記得不能直接用/捏顺,會(huì)報(bào)錯(cuò)柒莉。
            .build();


    public static void main(String[] args) throws Exception {

        // 連接開(kāi)啟
//        zkClient.start();

        zkFluentClient.start();

        // 測(cè)試創(chuàng)建
        CuratorConTest test = new CuratorConTest();
        test.testCreate();

        // 測(cè)試獲取
        test.testGet();

        // 測(cè)試更新
        test.testUpdate();

        // 測(cè)試刪除
        test.testDelete();

//        Thread.sleep(Integer.MAX_VALUE);
    }

    private void testCreate() throws Exception {
        // 1、創(chuàng)建默認(rèn)類(lèi)型節(jié)點(diǎn),書(shū)上說(shuō)默認(rèn)內(nèi)容為空,但是實(shí)際上上我本地的ip地址
        //org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for /zk-jsy/book
        // 是因?yàn)閦ookeeper的版本和curator的版本不兼容導(dǎo)致的部翘,默認(rèn)zk的版本是3.5.1-Alpha搂根,降級(jí)成3.4.8即可
        zkFluentClient.create().forPath("/book1-" + ThreadLocalRandom.current().nextInt());

        // 2珍促、創(chuàng)建有默認(rèn)值的節(jié)點(diǎn)
        zkFluentClient.create().forPath("/book2-" + ThreadLocalRandom.current().nextFloat(), "mytestbook2Create".getBytes());

        // 3、創(chuàng)建臨時(shí)節(jié)點(diǎn)剩愧,斷開(kāi)后會(huì)自動(dòng)清除
        zkFluentClient.create().withMode(CreateMode.EPHEMERAL).
            forPath("/book3-" + ThreadLocalRandom.current().nextInt());

        // 4猪叙、創(chuàng)建臨時(shí)節(jié)點(diǎn),同時(shí)如果父節(jié)點(diǎn)不存在仁卷,也把父節(jié)點(diǎn)創(chuàng)建了穴翩。但是父節(jié)點(diǎn)會(huì)是持久節(jié)點(diǎn)
        zkFluentClient.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL).
            forPath("/test/book4-test" + ThreadLocalRandom.current().nextInt());
    }

    private void testGet() throws Exception {
        String path = "/getData/mydata-" + ThreadLocalRandom.current().nextInt();
        zkFluentClient.create().creatingParentsIfNeeded().forPath(path,
                ("sogetdata" + ThreadLocalRandom.current().nextInt()).getBytes());

        // 1、獲取,注意返回的是bytes
        String value = new String(zkFluentClient.getData().forPath(path));
        System.out.println(value);

        // 2五督、獲取屬性
        Stat stat = new Stat();
        String value11 = new String(zkFluentClient.getData().storingStatIn(stat).forPath(path));
        System.out.println(stat.toString());
        System.out.println(value11);
    }

    private void testUpdate() throws Exception {
        String path = "/updateData/mydata-" + ThreadLocalRandom.current().nextInt();
        zkFluentClient.create().creatingParentsIfNeeded().forPath(path,
                ("toBeUpdate" + ThreadLocalRandom.current().nextInt()).getBytes());
        System.out.println("originData:" + new String(zkFluentClient.getData().forPath(path)));

        // 1藏否、 普通的update,不管version
        Stat stat = zkFluentClient.setData().forPath(path, ("newData" + ThreadLocalRandom.current().nextInt()).getBytes());
        System.out.println("newData:" + new String(zkFluentClient.getData().forPath(path)));

        // 2充包、樂(lè)觀鎖更新副签,可以用來(lái)實(shí)現(xiàn)CAS,如果version不匹配基矮,是無(wú)法更新的
        zkFluentClient.setData().withVersion(stat.getVersion()).forPath(path, ("UpdateByVersion:" + stat.getVersion()).getBytes());
        System.out.println("updateByVersionData:" + new String(zkFluentClient.getData().forPath(path)));

        // 2.1 測(cè)試cas淆储,傳入version=1,而當(dāng)前實(shí)際為2
        zkFluentClient.setData().withVersion(1).forPath(path,"error".getBytes());
        System.out.println("updateByErrorVersionData:" + new String(zkFluentClient.getData().forPath(path)));
        // KeeperErrorCode = BadVersion for /zk-jsy/updateData/mydata--1431282676 返回這個(gè)異常,version不對(duì)
    }

    private void testDelete() throws Exception {

        // 1家浇、普通刪除本砰,但是不能刪除含有葉子節(jié)點(diǎn)的父節(jié)點(diǎn)
        String path = "/book/forDelete" + ThreadLocalRandom.current().nextInt();
        zkFluentClient.create().creatingParentsIfNeeded().forPath(path);
        //Thread.sleep(20000);  // sleep期間可以看到對(duì)應(yīng)的節(jié)點(diǎn)
        zkFluentClient.delete().forPath(path);  // 刪除節(jié)點(diǎn)

        // 2、刪除節(jié)點(diǎn)钢悲,以及遞歸刪除其子節(jié)點(diǎn)点额,如果傳入/,刪除的是 namespace下的根目錄
        zkFluentClient.delete().deletingChildrenIfNeeded().forPath("/book");

        // 3舔株、無(wú)論如何,只要客戶端連接存在还棱,就會(huì)一直重試载慈,直到刪除成功,避免因?yàn)榧哼x主等情況造成數(shù)據(jù)無(wú)法清除
        zkFluentClient.delete().guaranteed().deletingChildrenIfNeeded().forPath("/");
    }
}
創(chuàng)建的異步實(shí)現(xiàn)
/**
 * 異步實(shí)現(xiàn)
 */
public class AsyncCuratorTest {

    static RetryPolicy policy = new ExponentialBackoffRetry(1000, 3); // 重試3次

    // 創(chuàng)建連接-- 流式寫(xiě)法
    static CuratorFramework zkFluentClient = CuratorFrameworkFactory.builder()
            .connectString("localhost:32770")
            .sessionTimeoutMs(5000)
            .connectionTimeoutMs(3000)
            .retryPolicy(policy)
            .namespace("zk-asyncjsy")  // 如果指定了某個(gè)應(yīng)用只能在某一個(gè)節(jié)點(diǎn)下操作,
            // 可以指定namespace珍手,這里base表示路徑為/base办铡。記得不能直接用/,會(huì)報(bào)錯(cuò)琳要。
            .build();

    static CountDownLatch countDownLatch = new CountDownLatch(2); // countDownLatch

    static ExecutorService tp = Executors.newFixedThreadPool(2); // ThreadPool

    public static void main(String[] args) throws Exception {

        String path = "/asyncCreate" + ThreadLocalRandom.current().nextInt();

        zkFluentClient.start();

        // 異步創(chuàng)建 -1
        zkFluentClient.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        System.out.println("Event[code:" + curatorEvent.getResultCode() + ", type:" + curatorEvent.getType());

                        System.out.println("Thread of processResult:" + Thread.currentThread().getName());

                        countDownLatch.countDown();
                    }
                }, tp).forPath(path, "createInfo".getBytes());

        // 異步創(chuàng)建 -2 寡具,會(huì)重復(fù),返回錯(cuò)誤碼
        zkFluentClient.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        System.out.println("Event[code:" + curatorEvent.getResultCode() + ", type:" + curatorEvent.getType());

                        System.out.println("Thread of processResult:" + Thread.currentThread().getName());

                        countDownLatch.countDown();
                    }
                }).forPath(path, "createAgain".getBytes());

        countDownLatch.await();
        tp.shutdown();
    }
}

執(zhí)行結(jié)果如下:

Event[code:0, type:CREATE
Thread of processResult:pool-3-thread-1
Event[code:-110, type:CREATE
Thread of processResult:main-EventThread

注意以下方面:

  1. 第一次異步回調(diào)傳入了 線程池tp稚补,用于在線程池中執(zhí)行對(duì)應(yīng)的回調(diào)童叠,可以從結(jié)果中看到,執(zhí)行的線程并不是Main線程
  2. 第二次異步回調(diào)课幕,并沒(méi)有傳入線程池tp拯钻,所以執(zhí)行操作的是主線程Main
  3. countDownLatch在這里只是為了保證線程執(zhí)行結(jié)束后,可以shutdown線程池
  4. 返回的event.getResultCode如果是0撰豺,表示操作成功,如果是其他值拼余,表示不成功污桦,比如-110,表示數(shù)據(jù)節(jié)點(diǎn)已存在匙监。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凡橱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子亭姥,更是在濱河造成了極大的恐慌稼钩,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件达罗,死亡現(xiàn)場(chǎng)離奇詭異坝撑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)粮揉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)巡李,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扶认,你說(shuō)我怎么就攤上這事侨拦。” “怎么了辐宾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵狱从,是天一觀的道長(zhǎng)膨蛮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)季研,這世上最難降的妖魔是什么敞葛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮训貌,結(jié)果婚禮上制肮,老公的妹妹穿的比我還像新娘。我一直安慰自己递沪,他們只是感情好豺鼻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著款慨,像睡著了一般儒飒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上檩奠,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天桩了,我揣著相機(jī)與錄音,去河邊找鬼埠戳。 笑死井誉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的整胃。 我是一名探鬼主播颗圣,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼屁使!你這毒婦竟也來(lái)了在岂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛮寂,失蹤者是張志新(化名)和其女友劉穎蔽午,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酬蹋,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡及老,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了范抓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片写半。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尉咕,靈堂內(nèi)的尸體忽然破棺而出叠蝇,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布悔捶,位于F島的核電站铃慷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜕该。R本人自食惡果不足惜犁柜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望堂淡。 院中可真熱鬧馋缅,春花似錦、人聲如沸绢淀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)皆的。三九已至覆履,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間费薄,已是汗流浹背硝全。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留楞抡,地道東北人伟众。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像召廷,于是被迫代替她去往敵國(guó)和親赂鲤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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