zookeeper基础知识

来源:互联网 发布:宁夏干部网络培训登录 编辑:程序博客网 时间:2024/06/06 01:03
Zookeeper是什么?
Zookeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务。它被设计为易于编程,使用文件系统目录树作为数据模型。服务端跑在java上,提供java和C的客户端 API
基本概念
集群角色:没有Master/Slave概念,有Leader、Follower、Observer三个角色。Leader服务器为客户端提供
读和写服务。Follower和Observer都能提供读服务,但Observer不参与Leader选举过程。
会话:指客户端和服务器之间的一个TCP连接。
节点:机器节点(集群中的机器),数据节点(Znode数据模型中的数据单元,分为持久节点和临时节点)
版本:version、cversion等
Watcher:可在指定的节点上注册事件,当事件触发的时候,服务器会通知客户端。
ACL:用来进行权限控制。
zookeeper可以用来做什么
集群服务,统一命名服务,分布式配置管理,分布式消息队列,分布式锁,分布式通知协调
等。
配置管理
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。但是当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,而且还可能是动态的话使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。比如我们可以把配置放在数据库里,然后所有需要配置的服务都去这个数据库读取配置。但是,因为很多服务的正常运行都非常依赖这个配置,所以需要这个集中提供配置服务的服务具备很高的可靠性。一般我们可以用一个集群来提供这个配置服务,但是用集群提升可靠性,那如何保证配置在集群中的一致性呢? 这个时候就需要使用一种实现了一致性协议的服务了。Zookeeper就是这种服务,它使用Zab这种一致性协议来提供一致性。现在有很多开源项目使用Zookeeper来维护配置,比如在Hbase中,客户端就是连接一个Zookeeper,获得必要的hbase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列Kafka中,也使用Zookeeper来维护broker的信息。在Alibaba开源的SOA框架Dubbo中也广泛的使用Zookeeper管理一些配置来实现服务治理。


名字服务
名字服务这个就很好理解了。比如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是不能是别域名的。怎么办呢?如果我们每台机器里都备有一份域名到IP地址的映射,这个倒是能解决一部分问题,但是如果域名对应的IP发生变化了又该怎么办呢?于是我们有了DNS这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应的IP是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。


分布式锁
其实在第一篇文章中已经介绍了Zookeeper是一个分布式协调服务。这样我们就可以利用Zookeeper来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即fail over到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫Leader Election(leader选举)。比如HBase的Master就是采用这种机制。但要注意的是分布式锁跟同一个进程的锁还是有区别的,所以使用的时候要比同一个进程里的锁更谨慎的使用。


集群管理
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。还有,比如一个分布式的SOA架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制)。还有开源的Kafka队列就采用了Zookeeper作为Cosnumer的上下线管理。


Zookeeper总体结构

Leader/Follower
ZooKeeper需要在所有的服务(可以理解为服务器)中选举出一个Leader,然后让这个Leader来负责管理集群。此时,集群中的其它服务器则成为此Leader的Follower。并且,当Leader故障的时候,需要ZooKeeper能够快速地在Follower中选举出下一个Leader。
Observer
Observer是zk集群的另一个角色, observer的行为在大多数情况下与follower完全一致, 但是他们不参加选举和投票, 而仅仅接受(observing)选举和投票的结果.
Zookeeper逻辑图如下:


如上图所示,假设搭建了一个5台server的集群,5台机器根据选举算法,选出一个leader,其他节点就是follower。
选举好leader后会和每个server建立长连接
修改操作:当某个节点收到修改操作时,就会将请求转发给leader,leader有处理机制,修改后同步到每一个follower。
zookeeper集群搭建完成就可以启动客户端,客户端可以连接除leader外的所有节点,建立长连接,客户端任何修改信息都会同步到server上,由leader同步到各个节点
选举:当leader挂掉后就会选举一个新的leader,然后再重新建立连接。完成一次选举大概需要200ms。
zookeeper中的概念
ZNode

zookeeper目录树中每一个节点对应一个Znode。每个Znode维护着一个属性结构,它包含着版本号(dataVersion),时间戳(ctime,mtime)等状态信息。ZooKeeper正是使用节点的这些特性来实现它的某些特定功能。每当Znode的数据改变时,他相应的版本号将会增加。每当客户端检索数据时,它将同时检索数据的版本号。并且如果一个客户端执行了某个节点的更新或删除操作,他也必须提供要被操作的数据版本号。如果所提供的数据版本号与实际不匹配,那么这个操作将会失败。
Session
Client与ZooKeeper之间的通信,需要创建一个Session,这个Session会有一个超时时间。因为ZooKeeper集群会把Client的Session信息持久化,所以在Session没超时之前,Client与ZooKeeper Server的连接可以在各个ZooKeeper Server之间透明地移动。
在实际的应用中,如果Client与Server之间的通信足够频繁,Session的维护就不需要其它额外的消息了。否则,ZooKeeper Client会每t/3 ms发一次心跳给Server,如果Client 2t/3 ms没收到来自Server的心跳回应,就会换到一个新的ZooKeeper Server上。这里t是用户配置的Session的超时时间。
Watcher
ZooKeeper支持一种Watch操作,Client可以在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。如果该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。
Zookeeper数据模型
zookeeper文件系统

zookeeper维护一个类似文件系统的数据结构
Zookeeper表现为一个分层的文件系统目录树结构(不同于文件系统的是,节点可以有自己的数据,而文件系统中的目录节点只有子节点)。
由根目录和各个子目录组成,每一个子目录称为znode,znode类似文件夹,但是znode可以存储数据
1) 持久化节点
所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点——不会因为创建该节点的客户端会话失效而消失。
2) 持久化顺序节点
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。
3) 临时节点
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。
4) 临时顺序节点
可以用来实现分布式锁
客户端调用create()方法创建名为“_locknode_/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。
客户端调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,注意,这里不注册任何Watcher。
客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点序号最小,那么就认为这个客户端获得了锁。
如果在步骤3中发现自己并非所有子节点中最小的,说明自己还没有获取到锁。此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时注册事件监听。
之后当这个被关注的节点被移除了,客户端会收到相应的通知。这个时候客户端需要再次调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,确保自己确实是最小的节点了,然后进入步骤3。
节点特性:
节点类型(节点的生命周期):持久节点、临时节点、顺序节点。
状态信息:包含事务ID、创建时间、版本号等信息。
版本:记录节点的修改次数,用来保证分布式数据的原子性操作(悲观锁:一个事务对数据进行处理时,在整个过程
都将数据锁定,其它事务无法对这个数据进行更新,直到这个事务完成;乐观锁:假定多个事务在处理过程中不会彼此影响,所以
在大部分时间不需要加锁)
通知机制
ZooKeeper支持一种Watch操作,Client可以在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。如果该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。需要注意的是,ZooKeeper中的Watcher是一次性的,即触发一次就会被取消,如果想继续Watch的话,需要客户端重新设置Watcher。这个跟epoll里的oneshot模式有点类似。
Watcher:客户端向服务端注册一个Watcher,当服务端指定事件触发时,就会向指定的客户端发送一个事件通知。
Watcher接口、WatchedEvent、回调方法等等。
ZAB协议
ZAB协议(ZooKeeper Atomic Broadcast):是为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议。
ZAB协议包括两种基本模式:崩溃恢复和消息广播。
在消息广播中,Leader服务器会为每一个Follower服务器各自分配一个单独的队列,将需要广播的事务依次放入
这些队列中,并根据FIFO(先进行出)的策略进行消息发送。
崩溃恢复:当Leader服务器出现崩溃或者由于网络原因导致Leader服务器失去与过半Follower的联系,就进入崩溃恢复模式。
进程正常工作时,处于UP状态;进程崩溃时,称为处于DOWN状态。
ZAB协议是整个Zookeeper框架的核心所在,它规定任何时候都需要保证只有一个主进程负责进行消息广播,如果主进程崩溃了
就要选举一个新的主进程,选举机制和消息广播机制是紧密相关。
ZAB与Paxos的联系与区别:
联系:都存在类似于Leader进程的角色,负责协调多个Follower进程的运行;Leader进程都会等待超过半数的Follower做出正确
的反馈后,才会将一个提案进行提交。
区别:设计目标不一样。ZAB用于构建一个高可用的分布式数据主备系统,Paxos用于构建分布式一致性状态机系统。
zk通信
通信协议:Zookeeper基于TCP/IP协议,实现了自己的通信协议来完成客户端与服务器、服务器与服务器之间的网络通信。
对于请求主要包括请求头和请求体,对于响应,主要包含响应头和响应体。