zookeeper总结

一、Zookeeper介绍

   分布式协调服务集群的管理者,监视着集群中各个节点的状态,根据节点提交的反馈进行下一步合理操作

二、Zookeeper文件系统

   Zookeeper提供一个多层级的节点命名空间(节点称为znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。

   Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M

zookeeper提供了四种节点类型:

  1. PERSISTENT-持久化目录节点:客户端与zookeeper断开连接后,该节点依旧存在 
  2. PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 
  3. EPHEMERAL-临时目录节点:客户端与zookeeper断开连接后,该节点被删除 
  4. EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

三、Zookeeper通知机制

    client端会对某个znode建立一个watcher事件,当该znode发生变化时,这些client会收到zk的通知,然后client可以根据znode变化来做出业务上的改变等。

四、Zookeeper watch监听机制

Zookeeper机制的特点:
1、Watch事件是一次性触发器,当它从服务器发送给客户端,客户但只会收到一次这样的信息
2、注册Watch监听:getdata() and exists()设置数据监视,getchildren()设置了子数据监视。
3、触发Watch监听: create、delete、setData
4、客户端断开之后重新连接到服务器也是需要一段时间。这就导致了zookeeper客户端不能够接收全部的zookeeper事件,watch事件可能会丢失。Zookeeper只能保证最终的一致性,而无法保证强一致性
5、Watch是轻量级的,其实就是本地JVM的Callback,服务器端只是存了是否有设置了Watcher的布尔类型

五、一致性

      一致性又可以分为强一致性与弱一致性。
     强一致性可以理解为在任意时刻,所有节点中的数据是一样的。同一时间点,你在节点A中获取到key1的值与在节点B中获取到key1的值应该都是一样的。
     弱一致性包含很多种不同的实现,目前分布式系统中广泛实现的是最终一致性。
     所谓最终一致性,就是不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,节点间的数据会最终达到一致状态。

六、Zookeeper原理

   Zookeeper 的核心是原子广播,这个机制保证了各个服务器之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)广播模式(同步)

 1)当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。

 2)一旦leader已经和多数的follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态.广播模式为了保证提议(proposal)被按顺序处理,zk采用了递增的事务id号(zxid)来标识,所有的提议都在被提出的时候加上了zxid,zxid实际上是一个64位的数字,高32位是epoch用来标识leader是否发生改变,如果有新的leader产生出来,epoch会自增,低32位用来递增计数。当新产生提议的时候,会依据数据库的两阶段过程,首先会向其他的server发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行。这个过程保证了事务的顺序一致性。

七、Leader选举

7.1、选举算法如下:3.4.0以后只保留了基于TCP的FastLeaderElection选举算法

  • LeaderElection
  • AuthLeaderElection
  • FastLeaderElection(默认方式,标准的Fast Paxos算法)

7.2 选举时服务器状态

  • LOOKING 不确定Leader状态。该状态下的服务器认为当前集群中没有Leader,会发起Leader选举
  • FOLLOWING 跟随者状态。表明当前服务器角色是Follower,并且它知道Leader是谁
  • LEADING 领导者状态。表明当前服务器角色是Leader,它会维护与Follower间的心跳
  • OBSERVING 观察者状态。表明当前服务器角色是Observer,与Folower唯一的不同在于不参与选举

7.3 Leader选举(以三台服务器组成为例)

      1、Zookeeper集群初始化启动时Leader选举
  (1) 每个Server发出一个投票。ZK1启动,给自己投票,使用(myid, ZXID)来表示,此时ZK1的投票为(1, 0),然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,ZK1的状态一直属于Looking。然后ZK2启动,给自己投票,发送投票(2,0)给其他服务器。 
  (2) 接受来自各个服务器的投票。这个阶段会判断该投票的有效性,包括检查是否是本轮投票、是否来自LOOKING状态的服务器。 
  (3) 处理投票。优先检查ZXID。ZXID比较大的服务器优先作为Leader。如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。对于ZK1和ZK2的投票,ZK2会胜选,ZK1会更新自己的投票(2,0),并发送给ZK2
  (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于ZK1、ZK2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出ZK2作为Leader。 
  (5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。当新的Zookeeper节点ZK3启动时,发现已经有Leader了,不再选举,直接将直接的状态从LOOKING改为FOLLOWING

      2、Zookeeper集群运行期间Leader重新选举(Leader挂掉)

       (1) 变更状态。Leader挂后,余下的非Observer服务器都会将自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。 
  (2) 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定ZK1的ZXID为124,ZK3的ZXID为123;在第一轮投票中,ZK1和ZK3都会投自己,产生投票(1, 124),(3, 123),然后各自将投票发送给集群中所有机器。 
  (3) 接收来自各个服务器的投票。与启动时过程相同。 
  (4) 处理投票。与启动时过程相同,由于ZK1事务ID大,ZK1将会成为Leader。 
  (5) 统计投票。与启动时过程相同。 
  (6) 改变服务器的状态。与启动时过程相同

八、Zookeeper同步流程

选完Leader以后,zk就进入状态同步过程。 
1、leader会为所有follower和observer创建learnerhandler线程用于接收同步数据请求,然后发消息给follower和observer; 
2、follower和abserver收到leader发过来的信息,比较zxid的大小,如果zxid小于leader的zxid,则把节点最大的zxid发送给leader; 
3、leader会将大于该zxid的所有数据同步到该follower,完成同步后通知follower更改uptodate状态; 
5、Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

九、集群说明

      9.1  集群最低3(2N+1)台,保证奇数,主要是为了选举算法。三台允许挂掉一台

      9.2  端口说明:2181:对客户端提供服务    2888:集群通信,leader监听此端口    3888:leader选举 

      9.3  集群角色:

           1)Leader 一个Zookeeper集群同一时间只会有一个实际工作的Leader,它会发起并维护与各Follwer及Observer间的心跳。所有的写操作必须要通过Leader完成再由Leader将写操作广播给其它服务器

           2)Follower 一个Zookeeper集群可能同时存在多个Follower,它会响应Leader的心跳。Follower可直接处理并返回客户端的读请求,同时会将写请求转发给Leader处理,并且负责在Leader处理写请求时对请求进行投票

           3)Observer 角色与Follower类似,但是无投票权

十、应用

    10.1 命名服务(文件系统)

            通过指定的名字来获取资源或者服务的地址,利用zk创建一个全局的路径,即是唯一的路径,这个路径就可以作为一个名字,指向集群中的集群,提供的服务的地址,或者一个远程的对象等等

    10.2 配置管理(文件系统、通知机制)

           将程序的配置信息放在zk的znode下,当znode发生变化时,利用watcher通知给各个客户端,从而更改配置

    10.3 Zookeeper集群管理(文件系统、通知机制)  

          所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 

         对于第一点,当有机器加入时,在指定目录下创建临时目录节点,利用watcher监听。当有机器挂掉时,其所创建的临时目录节点被删除,利用watcher监听
         对于第二点,所有机器在制定目录下创建临时顺序编号目录节点,每次选取编号最小的机器作为master

   10.4 Zookeeper队列管理(文件系统、通知机制)

         两种类型的队列:
        1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。 
        2、队列按照 FIFO 方式进行入队和出队操作。 
         第一类,在约定目录下创建临时目录节点,监听节点数目是否达到我们要求的数目。 
        第二类,在特定的目录下创建PERSISTENT_SEQUENTIAL节点,创建成功时Watcher通知等待的队列,队列删除序列号最小的节点用以消费。此场景下Zookeeper的znode用于消息存储,SEQUENTIAL序列号就是消息的编号,由于创建的节点是持久化的,所以不必担心队列消息的丢失问题

   10.5 Zookeeper分布式锁(文件系统、通知机制)

          锁服务可以分为两类,一个是保持独占,另一个是控制时序。 

        对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。 
         对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便

         获取分布式锁的流程:

  1. 客户端调用createNode方法在locker下创建临时顺序节点
  2. 调用getChildren(“locker”)来获取locker下面的所有子节点,注意此时不用设置任何Watcher。客户端获取到所有的子节点path之后,如果发现自己创建的节点在所有创建的子节点序号最小,那么就认为该客户端获取到了锁
  3. 如果发现自己创建的节点并非locker所有子节点中最小的,则对其调用exist()方法,同时对其注册事件监听器,当监听到这个比自己小的节点被删除时,则再次进行判断自己创建的节点序号是否是最小,是则获取锁,不是则重复以上操作                            

十一、问题总结

11.1 Zookeeper对节点的watch监听通知是永久的吗?

     不是。官方声明:一个Watch事件是一个一次性的触发器,为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,这太消耗性能了。

11.2 机器中为什么会有leader?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要进行leader选举。

 

猜你喜欢

转载自blog.csdn.net/qq_33314107/article/details/81261254
今日推荐