,zk的应用主要是针对三类:,在学Java API之前,我们先来了解一下zookeeper的常用命令。,连接zookeeper server。,获取帮助help。,,连接远程节点。,关闭连接。,,显示集群。,创建一个znode。,删除znode节点。,显示一个节点的状态。,查看路径子节点。,命令语法:ls [-s] [-w] [-R] path。,获取指定路径下的数据。,设置或者更新路径数据。,设置ACL。,ZooKeeper内置了一些权限控制方案,可以用以下方案为每个节点设置权限:,同步数据集群间数据。,查看命令执行历史。,退出客户端。,zookeeper客户端和服务器会话的建立是一个异步的过程,也就是说在程序中,程序方法在处理完客户端初始化后立即返回(即程序继续往下执行代码,这样,在大多数情况下并没有真正的构建好一个可用会话,在会话的生命周期处于“CONNECTED”时才算真正的建立完毕,所以需要使用到多线程中的一个工具类CountDownLatch)。,参数说明:,注意,整个创建会话的过程是异步的,构造方法会在初始化连接后即返回,并不代表真正建立好了一个会话,此时会话处于”CONNECTING”状态。当会话真正创建起来后,服务器会发送事件通知给客户端,只有客户端获取到这个通知后,会话才真正建立。,提供了两套创建节点的方法,同步和异步创建节点方式。,path:节点路径(名称):/nodeName。不允许递归创建节点,在父节点不存在的情况下,不允许创建子节点。,data[]:节点内容:要求类型是字节数组,也就是说不支持序列话方式,如果需要实现序列化,可使用java相关序列化框架,如Hessian,Kryo。,acl:节点权限:使用Ids.OPEN_ACL_UNSAFE开放权限即可。,createMode:节点类型:创建节点的类型,CreateMode.*,提供了如下所示的四种节点类型:,异步方式(在同步方法参数的基础上增加两个参数):,cb:回调方法:注册一个异步回调方法,要实现。
AsynCallBack.StringCallBack接口,重写processResult(int rc, String path, Object ctx, String name)方法,当节点创建完成后执行此方法。,ctx:传递给回调方法的参数,一般为上下文(Context)信息。,,修改节点数据。,同步或异步删除节点数据。,节点查询。,判断节点是否存在。,zookeeper有watch事件,是一次性触发的。当watch监视的数据发生变化时,通知在创建zookeeper是设置了Watcher的客户端。Watcher类监视的事件类型和状态类型如下所示:,事件类型(znode节点相关):,状态类型(客户端实例相关):,Watcher的特性:一次性、客户端串行执行、轻量。,ACL(Access Control List),Zookeeper作为一个分布式协调框架,其内部存储的都是一些关乎分布式系统运行时状态的元数据,尤其是涉及到一些分布式锁、Master选举和协调等应用场景。我们需要有效的保障Zookeeper中的数据安全,Zookeeper提供了一套完善的ACL权限控制机制来保障数据的安全。,Zookeeper提供了三种模式,权限模式、授权对象、权限:,权限模式:Scheme,开发人员经常使用如下四种权限模式:,权限对象:指的是权限赋予给用户或者一个指定的实体,例如IP地址或机器等。在不同的模式下,授权对象是不同的。这种模式和授权对象一一对应。,权限:权限就是指那些通过权限检测后可以被允许执行的操作,在Zookeeper中,对数据的操作权限分为以下五大类:,自定义用户权限。,acl之ip权限。,Curator是netflix公司开源的一套zookeeper客户端,目前是Apache的顶级项目。与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量。Curator解决了很多zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册wathcer和NodeExistsException 异常等。,引包:,zookeeper原生支持通过注册watcher来进行事件监听,但是其使用不是特别方便,需要开发人员自己反复注册watcher,比较繁琐。,Curator引入Cache来实现对zookeeper服务端事务的监听。Cache是Curator中对事件监听的包装,其对事件的监听其实可以近似看作是一个本地缓存视图和远程Zookeeper视图的对比过程。同时,Curator能够自动为开发人员处理反复注册监听,从而大大简化原生api开发的繁琐过程。,NodeCache:,NodeCache可以监听指定的节点,注册监听器后,节点的变化会通知相应的监听器。,Path Cache:,Path Cache 用来监听ZNode的子节点事件,包括added、updateed、removed,Path Cache会同步子节点的状态,产生的事件会传递给注册的PathChildrenCacheListener。,TreeCache:,Path Cache和Node Cache的“合体”,监视路径下的创建、更新、删除事件,并缓存路径下所有孩子结点的数据。,可重入锁Shared Reentrant Lock。,Shared意味着锁是全局可见的, 客户端都可以请求锁。Reentrant和JDK的ReentrantLock类似, 意味着同一个客户端在拥有锁的同时,可以多次获取,不会被阻塞。它是由类InterProcessMutex来实现。它的构造函数为:,不可重入锁Shared Lock。,使用InterProcessSemaphoreMutex,调用方法类似,区别在于该锁是不可重入的,在同一个线程中不可重入。,可重入读写锁Shared Reentrant Read Write Lock 类似JDK的ReentrantReadWriteLock. 一个读写锁管理一对相关的锁。一个负责读操作,另外一个负责写操作。读操作在写锁没被使用时可同时由多个进程使用,而写锁使用时不允许读 (阻塞)。此锁是可重入的。一个拥有写锁的线程可重入读锁,但是读锁却不能进入写锁。这也意味着写锁可以降级成读锁, 比如请求写锁 —>读锁 —->释放写锁。从读锁升级成写锁是不成的。主要由两个类实现:,信号量Shared Semaphore 一个计数的信号量类似JDK的Semaphore。JDK中Semaphore维护的一组许可(permits),而Cubator中称之为租约(Lease)。注意,所有的实例必须使用相同的numberOfLeases值。调用acquire会返回一个租约对象。客户端必须在finally中close这些租约对象,否则这些租约会丢失掉。但是, 但是,如果客户端session由于某种原因比如crash丢掉, 那么这些客户端持有的租约会自动close, 这样其它客户端可以继续使用这些租约。租约还可以通过下面的方式返还:,多锁对象Multi Shared Lock Multi Shared Lock是一个锁的容器。当调用acquire, 所有的锁都会被acquire,如果请求失败,所有的锁都会被release。同样调用release时所有的锁都被release(失败被忽略)。基本上,它就是组锁的代表,在它上面的请求释放操作都会传递给它包含的所有的锁。主要涉及两个类:,它的构造函数需要包含的锁的集合,或者一组ZooKeeper的path。,代码演示:,DistributedBarrier构造函数中barrierPath参数用来确定一个栅栏,只要barrierPath参数相同(路径相同)就是同一个栅栏。通常情况下栅栏的使用如下:,双栅栏Double Barrier 双栅栏允许客户端在计算的开始和结束时同步。当足够的进程加入到双栅栏时,进程开始计算,当计算完成时,离开栅栏。双栅栏类是DistributedDoubleBarrier DistributedDoubleBarrier类实现了双栅栏的功能。它的构造函数如下:,memberQty是成员数量,当enter方法被调用时,成员被阻塞,直到所有的成员都调用了enter。当leave方法被调用时,它也阻塞调用线程,直到所有的成员都调用了leave。 注意:参数memberQty的值只是一个阈值,而不是一个限制值。当等待栅栏的数量大于或等于这个值栅栏就会打开! 与栅栏(DistributedBarrier)一样,双栅栏的barrierPath参数也是用来确定是否是同一个栅栏的,双栅栏的使用情况如下:,利用ZooKeeper可以实现一个集群共享的计数器。只要使用相同的path就可以得到最新的计数器值, 这是由ZooKeeper的一致性保证的。Curator有两个计数器, 一个是用int来计数,一个用long来计数。,1)SharedCount 这个类使用int类型来计数。主要涉及三个类。,2)DistributedAtomicLong 除了计数的范围比SharedCount大了之外, 它首先尝试使用乐观锁的方式设置计数器, 如果不成功(比如期间计数器已经被其它client更新了), 它使用InterProcessMutex方式来更新计数值。此计数器有一系列的操作:,你必须检查返回结果的succeeded(), 它代表此操作是否成功。如果操作成功, preValue()代表操作前的值, postValue()代表操作后的值。,curator提供了两种方式,分别是Leader Latch和Leader Election。,随机从候选者中选出一台作为leader,选中之后除非调用close()释放leadship,否则其他的后选择无法成为leader。,通过LeaderSelectorListener可以对领导权进行控制, 在适当的时候释放领导权,这样每个节点都有可能获得领导权。而LeaderLatch则一直持有leadership, 除非调用close方法,否则它不会释放领导权。,至此Zookeeper的应用大体讲完了,在这里多说一句,技术的API不用去背,背也是背不住的,多使用就好了。
© 版权声明
文章版权归作者所有,未经允许请勿转载。