一、什么是zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
简单来说,zookeeper = 文件系统 + 监听通知机制
二、文件系统
zookeeper有着与linux类似的文件系统,区别是,linux的目录就是目录,文件就是文件。而zookeeper中只有一个znode概念,本身可以做为“文件”存储一定的数据,又可以做为“目录”存在。
/* +---+ |/ | +-+-+ | | +------+ +--|config| | +--+---+ | | +-----+ | +-----|ip | | | +-----+ | | +-----+ | +-----|port | | +-----+ | | +------+ +--|apps | +--+---+ | +-----+ +-----|app1 | | +-----+ | +-----+ +-----|app2 | +-----+ */
znode共分为四种:
1、PERSISTENT-持久化目录节点
此节点在客户端与zookeeper断开连接之后,依然存在,需要主动删除。
2、PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点
同样地,此类节点也是需要主动删除,不会随着客户端的断开连接而删除。与PERSISTENT不同的是,zookeeper会给此类节点进行编号。如:app0000003362。0000003362为zookeeper给的编号,自动递增。
3、EPHEMERAL-临时目录节点
与PERSISTENT不同的是,此类节点会在客户端与zookeeper断开连接之后被删除。
4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点
与PERSISTENT_SEQUENTIAL类似拥有zookeeper的自动编号,区别是会在客户端与zookeeper断开连接之后被删除。
值得注意的是,同路径下,同名znode只能被创建一次。且每个znode最多只可以存储1M数据。
三、监听通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
四、 实际应用
基于文件系统与监听通知机制,zookeeper有诸多应用场景。
1、命名服务(基于文件系统)
名称在所有计算机系统中起着重要的作用,它们用来共享资源,唯一标识实体,指向位置等。命名的对象可以有多种类型,而且可被一些不同的服务来访问。命名服务器可根据给定的名字来进行资源或对象的地址定位,并获取有关的属性信息。(百度百科)
简单来说,就是通过名字来获取对应资源/服务地址。利用znode的唯一性,可以创建一个全局节点,将对应的信息记录在znode中。需要使用对应资源的服务直接获取此节点的信息即可。
2、配置管理(基于文件系统与监听通知机制)
服务有自己的配置,而同一个服务可多点部署。如果采用配置文件的形式,在修改配置的时候,需要同步文件至所有机器,再通知程度动态加载,或者直接重启。若存在这种情况,整个后台存在一份共享配置(路由信息等),而在一次修改中,只需要同步到某个服务(扩容、增加下游节点等)。长久之后,会出现不同服务的配置不同的情况(虽然对于他们自己所使用的部门是最新的)。此时可以通过配置中心来解决此类问题,所有配置都从配置中心中读取,统一管理。
自己实现配置中心毕竟是有代价。而利用zookeeper,完全可以实现配置中心的功能。将对应信息存储到对应的znode中,服务只需要监听自己关心的配置(znode)。一旦znode发生变化,利用watcher通知所有监听此znode的客户端(对于zookeeper而言,服务是他的客户端),从而更新配置。
3、集群管理(基于文件系统与监听通知机制)
当一个服务部署成集群的时候,就会有两个问题:机器的加入与退出,master的选举。可以在zookeeper里创建一个持久化znode A,然后让本集群所有的服务在A下创建临时znode B,需要知道此集群的服务监听A。当新机器加入时,创建新的B,旧机器离开(宕机、缩容等)时,自动删除B。不管是创建,还是删除,A都发生了变化,利用watcher通知所有监听者。于是大家都知道本集群的情况了。
对于master选举,同样也可以在zookeeper里创建一个持久化znode C,而后所有服务在C里创建临时顺序编号目录节点。每次选择编号最大或者最小的做为master。由于临时顺序编号目录节点的编号是自增的,若选择最大的做为master,当有新机器加入时,新机器就会成为master。而选择最小编号做为master,只要其不退出(znode没删),就不会产生切换master的情况,对数据来说是最安全的。
4、分布式锁(基于文件系统与监听通知机制)
有一个程序,有两个线程,都对相同变量进行100w次++操作。未加锁的情况下,得到的结果并不是200w。同样,在一个集群中,如果同时修改相同资源,也会出现相互覆盖的情况。此时,需要使用到分布式锁来处理此类问题。要开始修改此资源之前,先获取锁。获取成功之后才可以进行修改操作。由于zookeeper中,znode的唯一性,可以利用它来实现分布式锁服务。需要获取锁时,在指定路径下创建znode(非自动编号),需要释放时,删除此znode。若创建失败,则认为当前已有其它服务抢到了锁。
若创建的是非自动编号的znode,会有一个问题。每次都是集群中所有服务竞争同一把锁,会出现一个服务抢到多次,而其它服务一次都不成功的情况。此时可以将其修改为自动编号的znode,并监听对应父znode。每次需要锁时,创建一个自动编号的znode。若自己创建的znode在所有znode中编号最小,则认为自己抢到了锁。解锁(删除znode)之后,又会通知整个集群。这样不仅实现了分布式锁,而且人人有份,有序进行。
五、参考链接
https://blog.csdn.net/u010963948/article/details/83381757
https://www.cnblogs.com/lfs2640666960/p/11104838.html
https://blog.csdn.net/java_66666/article/details/81015302
https://blog.csdn.net/chunqiu3351/article/details/100762270
https://www.jianshu.com/p/d4fb16fafc2e
来源:https://www.cnblogs.com/chinxi/p/12640059.html