图解ZooKeeper的典型应用场景

zookeeper在不少框架中都有应用,例如:Dubbo,Hadoop,Kafka等,但典型的用法也就几种,掌握了这几种用法,再看zookeeper在相关框架中的应用就很轻松,下一篇文章将会详细介绍zookeeper在dubbo中的使用,以便有一个更深入的了解node

本文参考了《从Paxos到ZooKeeper》,鉴于本文的定位是一篇科普性质的文章,所以对于一些诸如共享锁和分布式队列的具体实现没有进行更详细的描述,实际工做中须要实现时能够参考这本书redis

zookeeper的数据模型和文件系统相似,每个节点称为znode,是zookeeper中的最小数据单元,每个znode上能够报存数据和挂载子节点,从而构成一个层次化的属性结构算法

能够建立以下四种节点(znode)sql

   1.持久节点:节点建立后会一直存在zookeeper服务器上,直到主动删除数据库

   2.持久顺序节点:每一个节点都会为它的一级子节点维护一个顺序服务器

   3.临时节点:临时节点的生命周期和客户端的会话保持一致。当客户端会话失效,该节点自动清理数据结构

   4.临时顺序节点:在临时节点上多了一个顺序的特性架构

简单演示一下经常使用的命令并发

-s : 建立顺序节点负载均衡

-e : 建立临时节点

path : 路径

data : 数据

acl : 权限

create默认建立的是持久节点

 

执行完上述命令后,数据结构以下所示

这里简单说一下顺序节点的特性。每次建立顺序节点时,zk都会在路径后面自动添加上10位的数字(计数器),例如 < path >0000000001,< path >0000000002,……这个计数器能够保证在同一个父节点下是惟一的。在zk内部使用了4个字节的有符号整形来表示这个计数器,也就是说当计数器的大小超过2147483647时,将会发生溢出,每次在父节点下建立一个顺序节点时,大小加1,如上图的3到4

zookeeper提供了分布式数据发布/订阅,容许客户端向服务端注册一个watcher监听,当服务端的一些指定事件触发了这个watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。

简单举几个watcher的事件类型

 

基础知识讲解完毕,下面正式分享zookeeper的做用

1.数据发布/订阅

数据发布/订阅(Publish/Subscribe)系统,即所谓的配置中心,顾明思义就是发布者将数据发布到zookeeper的一个或一系列的节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。

zookeeper采用推拉结合的方式来实现发布订阅系统:客户端向服务端注册本身须要关注的节点,一旦该节点的数据发生变动,那么服务端就会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知以后,须要主动到服务端获取最新的数据。

程序老是须要配置的,若是程序分散部署在多台机器上,要这个改变配置就变得困难。好吧,如今把这些配置所有放到zookeeper上去,保存在zookeeper的某个目录节点中,而后全部相关应用程序对这个目录节点进行监控,一旦配置信息发生变化,每一个应用程序就会收到zookeeper的通知,而后从zookeeper中获取新的配置信息应用到系统中就好

2.负载均衡

每台服务端在启动时都会去zookeeper的servers节点下注册临时节点(注册临时节点是由于,当服务不可用时,这个临时节点会消失,客户端也就不会请求这个服务端),每台客户端在启动时都会去servers节点下取得全部可用的工做服务器列表,并经过必定的负载均衡算法计算得出应该将请求发到哪一个服务器上

3.生成分布式惟一ID

在过去的单库单表型系统中,一般可使用数据库字段自带的auto_increment属性来自动为每条记录生成一个惟一的ID。可是分库分表后,就没法在依靠数据库的auto_increment属性来惟一标识一条记录了。此时咱们就能够用zookeeper在分布式环境下生成全局惟一ID。作法以下:每次要生成一个新Id时,建立一个持久顺序节点,建立操做返回的节点序号,即为新Id,而后把比本身节点小的删除便可。

4.Master选举

Master选举是一个在分布式系统中很是常见的应用场景。在分布式系统中,Master每每用来协调系统中的其余系统单元,具备对分布式系统状态变动的决定权。例如,在一些读写分离的应用场景用,客户端的写请求每每是由Master来处理的,而在另外一些场景中, Master则经常负负责处理一下复杂的逻辑,并将处理结果同步给集群中其余系统单元。Master选举能够说是zookeeper最典型的应用场景了

利用zookeeper的强一致性,可以很好地保证在分布式高并发状况下节点的建立必定能保证全局惟一性,即zookeeper将会保证客户端没法重复建立一个已经存在的数据节点。也就是说,若是同时有多个客户端请求建立同一个节点,那么最终必定只有一个客户端可以建立成功。利用这个特性,就很容易在分布式环境中进行Master选举

客户端集群往zookeeper上建立一个/master临时节点。在这个过程当中,只有一个客户端可以成功建立这个节点,那么这个客户端就成了master。同时其余没有在zookeeper上成功建立节点的客户端,都会在节点/master上注册一个变动的watcher,用于监控当前的master机器是否存活,一旦发现当前的master挂了,那么其他的客户端将会从新进行master选举

5.分布式锁

在同一个JVM中,为了保证对一个资源的有序访问,如往文件中写数据,能够用synchronized或者ReentrantLock来实现对资源的互斥访问,若是2个程序在不一样的JVM中,而且都要往同一个文件中写数据,如何保证互斥访问呢?这时就须要用到分布式锁了

目前分布式锁的主流实现方式有两种

   1.利用redis setnex(key value) key不存在返回0,key存在返回1

   2.zookeeper实现排他锁,共享锁(读锁)

这里只简单介绍一下排他锁的实现方式

实现原理和master选举相似,全部客户端在/exclusive_lock节点下建立临时子节点/exclusive_lock/lock,zookeeper会保证在全部的客户端中,最终只有一个客户端可以建立成功,那么就认为该客户端获取了锁,其余没有获取到锁的客户端就须要到/exclusive_lock节点看上注册一个子节点变动的watcher监听,以便实时监听到lock节点的变动状况

释放锁的状况有以下两种

   1.当前获取锁的客户端发生宕机,那么zookeeper上的这个临时节点就会被删除

   2.正常执行完业务逻辑后,客户端会主动将本身建立的临时节点删除

整个排他锁的获取和释放流程能够用以下图表示

6.分布式队列

以下图,建立/queue做为一个队列,而后每建立一个顺序节点,视为一条消息(节点存储的数据即为消息内容),生产者每次建立一个新节点,作为消息发送,消费者监听queue的子节点变化(或定时轮询),每次取最小节点当作消费消息,处理完后,删除该节点。至关于实现了一个FIFO(先进先出)的队列。注:zookeeper强调的是CP(一致性),而非专为高并发、高性能场景设计的,若是在高并发,qps很高的状况下,分布式队列需酌情考虑。

欢迎工做一到五年的Java工程师朋友们加入Java填坑之路:860113  481 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!  

相关文章
相关标签/搜索