美文网首页ZookeeperJava学习笔记程序员
分布式利器Zookeeper(三)

分布式利器Zookeeper(三)

作者: 张丰哲 | 来源:发表于2017-05-17 07:47 被阅读1142次

    前言

    《分布式利器Zookeeper(一)》

    《分布式利器Zookeeper(二):分布式锁》

    本篇博客是分布式利器Zookeeper系列的最后一篇,涉及的话题是:Zookeeper分布式锁的代码实现、zkclient的使用、Curator框架介绍等。

    Zookeeper分布式锁的代码实现

    在上一篇博客中,从思路上已经分析了Zookeeper如何帮助我们实现分布式锁,我们直接来看代码:

    分布式客户端 获取分布式锁的方法lock:初始化ZK 获取分布式锁的方法lock:创建临时节点与判断最小路径 main测试 运行结果

    需要注意的是,即便监控到了比自己序号小的节点的删除Watcher,也需要再次确认下!

    从结果上,看的很清楚,各个线程有序获得锁。


    zkclient

    zkclient是在zookeeper原生API基础上做了一点封装,简化了ZK的复杂性。

    来看代码:

    基于zkclient的增删改查

    我们观察下zkclient的使用,和以前基于zookeeper的原生API有哪些区别呢?

    第一,原生API需要我们利用CountDownLatch来确保ZK的初始化,现在zkclient帮助我们屏蔽掉了这个细节

    第二,原生API是不可以递归创建节点的,而zkclient可以帮助我们递归创建不存在的父节点,还可以递归删除

    第三,支持序列化操作,上面的代码你大概可以看出一些端倪,就是我们从操作byte[]到操作String了。(事实上,在zkclient中你只需要实现ZkSerializer接口,就可以完成Object到byte[]的转换,虽然如此,但是实际开发中,利用JSON也挺好的!)

    第四,还有最重要的一点就是,zkclient将对节点的操作和对节点的监控分离开了,在原生API中2者是耦合在一起的!从思想上来看,便于理解;从代码上来看,也简洁些(如果写在一起,头都大了);更加方便的是,zkclient替我们完成了重复watch的功能!

    watch订阅机制

    看到没有,是不是有点像MQ的订阅机制,非常好用!【但是也有点不太完美,子节点的数据变更为什么没有监控呢,这有点不符合人性啊!还好有Curator...】

    但是呢,我们知道ZK是有很多应用场景的,比如实现分布式锁,zkclient并没有替我们进行封装,但是Curator框架可以帮助我们做到!

    Curator

    为了更好实现Java操作Zookeeper服务器,后来出现Curator框架,功能非常强大,目前已经是Apache的顶级项目,有很多丰富的特性,比如session超时重连,主从选举,分布式计数器,分布式锁等,非常有利于Zookeeper复杂场景下的开发。

    POM文件:

    pom.xml

    增删改查:

    curator基本的API操作

    Curator框架使用链式编程风格,易读性很强!

    注意,不论是原生的API,还是基于zkclient的API,都是提供的connectTimeout,而Curator提供了sessionTimeout,功能很强大。

    异步回调

    无论是原生的API,还是zkclient,都是支持异步回调的,但是Curator框架在支持异步回调的同时,增加了线程池供我们优化!

    NodeCacheListener PathChildrenCacheListener

    对于Curator而言,为了解决重复Watch的问题,它引入了一种全新的思想:Cache与ZK SERVER比对的机制。不论是原生的API,还是基于ZKCLIENT的,其实它们解决思路都是重复注册!

    思路决定出路!Curator通过事件驱动将客户端的Cache与ZK SERVER的数据比对,就自然而然的解决了重复WATCH的功能!为什么Curator能成为Apache的顶级项目呢,我想大概就是因为它的与众不同的设计思想!

    在Curator中,有2种Listener,一个是监控节点的NodeCacheListener,一个是监控子节点的PathChildrenCacheListener。PathChildernCacheListener可以监控子节点的新增、修改、删除,非常好用!

    好了,到这里,准备结束这个系列了(其实还有一些内容没有涉及,比如Curator的分布式锁、分布式barrier的介绍等,以后有空再分享,暂且保留下,哈哈)!

    相关文章

      网友评论

      • 大悦月:if (zooKeeper.exists(ROOT + "/" + waitPath, true) == null) {
        // 获得锁
        doTask();
        }
        这段代码没看懂啊,我换成下面的代码也是一样么?
        zooKeeper.exists(ROOT + "/" + waitPath, true);
      • 01010100:你上一篇里的思路理的挺好的,不过你这里的实现有点没看懂啊:没有获取到锁时,是通过什么来阻塞当前线程的?
        张丰哲:具体思路在上一篇中,你可以参考下。
        “没有获取到锁时,是通过什么来阻塞当前线程的?” 大概是这样的,如果一个线程没有拿到锁,那么实质上这个线程并不会执行,而是进入了一个watch状态中,一旦拿到锁的线程执行完毕,释放锁后就会触发watch机制,相当于通知下一个线程可以执行了。
      • 685a21d094b4:三篇zk文章都看完了,写得很好,我未接触过zk的也能看懂👍👍

      本文标题:分布式利器Zookeeper(三)

      本文链接:https://www.haomeiwen.com/subject/arpxxxtx.html