1.什么是zookeeper

英文文献来自官网,中文用google翻译

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them, which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.


ZooKeeper是一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。所有这些类型的服务都以分布式应用程序的某种形式使用。每次实施它们都需要做很多工作来修复不可避免的错误和竞争条件。由于难以实现这些类型的服务,应用程序最初通常会吝啬它们,这使得它们在变化的情况下变得脆弱并且难以管理。即使正确完成,这些服务的不同实现也会在部署应用程序时导致管理复杂性。

Zookeeper 是一个开源的分布式的,为分布式应用提供协调服务的 Apache 项目

zookeeper从设计模式角度来理解,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经 在Zookeeper上注册的那些观察者做出相应的反应,从而实现集群中类似Master/Slave管理模式
设计目标(特点)

  • Zookeeper:一个领导者(leader),多个跟随者(follower)组成的集群

  • Leader 负责进行投票的发起和决议,更新系统状态。

  • Follower 用于接收客户请求并向客户端返回结果,在选举 Leader 过程中参与投票。

  • 集群中只要有半数以上节点存活, Zookeeper 集群就能正常服务。

  • 全局数据一致:每个 server 保存一份相同的数据副本, client 无论连接到哪个 server,数据都是一致的。

  • 更新请求顺序进行,来自同一个 client 的更新请求按其发送顺序依次执行。

  • 数据更新原子性,一次数据更新要么成功,要么失败。

  • 实时性,在一定时间范围内, client 能读到最新数据

zookeeper的数据结构

ZooKeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一棵树,每个节点称做一个 ZNode。每一个 ZNode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过其路径唯一标识。

2.Zookeeper的选举机制

半数机制(Paxos 协议):集群中半数以上机器存活,集群可用。所以 zookeeper适合装在奇数台机器上。

2.1 我们为什么要选举leader

zookeeper的选举就是在有奇数台服务器的集群中选取一个leader,用来指挥整个集群.那么我们为什么要选举出来一个leader呢?
服务器接到请求做出回应不就行了吗??? 我从网上搜到了这么一个总结

集群本身有很多种类,如tomcat集群,集群里面每一台机器是对等的,所以其自身不存在leader之说。
另外一类,如fastDfs,其依赖于独特的HASH算法,建立文件名和路径之间的映射关系,写操作都是通过namenode分发到各台datanode之上,算法保证了文件名的独一无二,也不存在leader的说法。还有memcache集群,集群里面的机器之间彼此无心跳,通过一致性hash尽可能将key值的存储分散化,降低单一memcahe服务器down机的影响。
还有一类是主从复制,主节点负责写,从节点负责读,提高读的性能。从节点定期通过心跳与主节点沟通,一旦主节点挂掉了,从节点马上接手主节点的任务。应该来讲,zookeeper集群是最接近这一种的。
对于分布式应用,难以避免出现网络的抖动。比如,主节点暂时失去响应,如瞬时负载过高,网络拥塞或者其他原因导致主节点暂时失去响应,超过响应超时时间,这个时候从节点启动,承担起leader的职责,但是原先的主节点又恢复了服务。这个时候,如果没有选举机制(不能仅仅自己宣告自己是leader,还要广而告之,让其他服务器或者客户端知道自己是leader),有可能会存在两个leader节点,导致集群发生混乱。

我使用zookeeper的原因是实现hdfs的高可用,属于主从复制类的集群.主节点负责写,从节点负责读,提高读的性能。从节点定期通过心跳与主节点沟通,一旦主节点挂掉了,从节点马上接手主节点的任务

2.2 选举的流程图

2.3在集群启动时的选举

假设有五台服务器组成的 zookeeper 集群,它们的 myid 从 1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动.
  (1) 每个Server发出一个投票。Server1到Server5都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0)…Server5的投票为(5, 0)然后各自将这个投票发给集群中其他机器。
  (2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
  (3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下
    · 优先检查ZXID。ZXID比较大的服务器优先作为Leader。
    · 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。
  (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息.
  (5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。

过程就可以理解成1启动,投给自己,集群内机器数量没有过半,状态looking–>2启动,加入集群,重新投票,1和2都投给2,集群内机器数量没有过半,状态looking–>Server3启动,此刻他发现Server1和2的ZXID和自己相等,再去比较myid,自己最大,他就为自己投票,同样server1和2也会把票投给他.这时满足了leader的条件,server3就成为了leader,3的状态为leading,1和2变为following–>当4,5启动后,因为已经有了leader,4,5会自动成为follower

2.4服务器运行时期的Leader选举

在Zookeeper运行期间,Leader与非Leader服务器各司其职,即便当有非Leader服务器宕机或新加入,此时也不会影响Leader,但是一旦Leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮Leader选举,其过程和启动时期的Leader选举过程基本一致。
  假设正在运行的有Server1、Server2、Server3三台服务器,当前Leader是Server2,若某一时刻Leader挂了,此时便开始Leader选举。选举过程如下

(1) 变更状态。Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。

(2) 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的ZXID为123,Server3的ZXID为122;在第一轮投票中,Server1和Server3都会投自己,产生投票(1, 123),(3, 122),然后各自将投票发送给集群中所有机器。

(3) 接收来自各个服务器的投票。与启动时过程相同。

(4) 处理投票。与启动时过程相同,此时,Server1将会成为Leader。

(5) 统计投票。与启动时过程相同。

(6) 改变服务器的状态。与启动时过程相同。

因为原leader挂掉时,集群中仍在有半数以上的服务器在运行,所以集群依然正常运行.


注:参考了很多零散的资料,如果总结的有错误请指出.

愿你我出走半生,归来仍是少年