Zookeeper的那些事

Zookeeper的那些事,第1张

Zookeeper的那些事

ZooKeeper是一个开放源码的分布式协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理 *** 作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

分布式应用程序可以基于Zookeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。

Zookeeper保证了如下分布式一致性特性:

  • 顺序一致性
  • 原子性
  • 单一视图
  • 可靠性
  • 实时性(最终一致性)

客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的zookeeper机器来处理。对于写请求,这些请求会同时发给其他zookeeper机器并且达成一致后,请求才会返回成功。因此,随着zookeeper的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。

有序性是zookeeper中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper最新的zxid。


1、Zookeeper 的数据节点
     Znode有两种类型,短暂的(ephemeral)和持久的(persistent)

  • PERSISTENT-持久节点
    除非手动删除,否则节点一直存在于Zookeeper上

  • EPHEMERAL-临时节点
    临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除。

  • PERSISTENT_SEQUENTIAL-持久顺序节点
    基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。

  • EPHEMERAL_SEQUENTIAL-临时顺序节点
    基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。

  • Container nodes--容器节点
    ZK 服务端启动后,会有一个单独的线程去扫描,所有的容器节点,当发现容器节点的子节点数量为 0 时,会自动删除该节点

  • 持久 TTL、持久顺序 TTL
    指带有存活时间,简单来说就是当该节点下面没有子节点的话,超过了 TTL 指定时间后就会被自动删除

2、服务器角色
Leader
事务请求的唯一调度和处理者,保证集群事务处理的顺序性
集群内部各服务的调度者

Follower
处理客户端的非事务请求,转发事务请求给Leader服务器
参与事务请求Proposal的投票
参与Leader选举投票

Observer
3.3.0版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力

处理客户端的非事务请求,转发事务请求给Leader服务器
不参与任何形式的投票

3、Zookeeper四种节点状态
Leader:说明此节点已经是leader节点,处于领导者地位的状态,差不多就是一般集群中的master。但在zookeeper中,只有leader才有写权限,其他节点(FOLLOWING)是没有写权限的,可以读

Looking:选举中,正在寻找leader,即将进入leader选举流程中

Following:跟随者,表示当前集群中的leader已经选举出来了,主要具备以下几个功能点             

                    向leader发送请求(PING消息、REQUEST消息、ACK消息、RevalIDATE消息)

                    接收leader消息并进行处理;

                    接收client发送过来的请求,如果为写请求,会发送给Leader进行投票处理,然后返回client结果。

Observing:Observing和Following差不多,但不参加投票和选举,接受leader选举后的结果
 

4、Zookeeper是如何保证事务的顺序一致性的?
Zookeeper采用了全局递增的事务Id来标识,所有的proposal(提议)都在被提出的时候加上了zxid,zxid实际上是一个64位的数字,高32位是epoch(时期; 纪元; 世; 新时代)用来标识leader周期,如果有新的leader产生出来,epoch会自增,低32位用来递增计数。当新产生proposal的时候,会依据数据库的两阶段过程,首先会向其他的server发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行。

5、Leader选举
Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。

  (1) 服务器初始化启动。

  (2) 服务器运行期间无法和Leader保持连接。

第一种情况,服务器启动时期的Leader选举

  若进行Leader选举,则至少需要两台机器,这里选取3台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是进入Leader选举过程。选举过程如下

  (1) 初始化时候,每个服务将投票给自己。每个Server发出一个投票。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。

  (2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。

  (3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下

    · 优先检查ZXID。ZXID比较大的服务器优先作为Leader。

    · 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。

  对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0,再比较myid,此时Server2的myid最大,于是Server2

  (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。

  (5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING

第二种选举跟第一种相同


5、Zookeeper 的数据模型
     (1)、层次化的目录结构,命名符合常规文件系统规范
     (2)、每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
  (3)、节点Znode可以包含数据和子节点,但是EPHEMERAL类型的节点不能有子节点
  (4)、Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本
  (5)、客户端应用可以在节点上设置监视器
  (6)、节点不支持部分读写,而是一次性完整读写

 

6、Zookeeper 的读写机制

  (1)、 Zookeeper是一个由多个server组成的集群
  (2)、 一个leader,多个follower
  (3)、 每个server保存一份数据副本
  (4)、 全局数据一致
  (5)、 分布式读写
  (6)、 更新请求转发,由leader实施

 

    

7、Zookeeper工作原理

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

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

   状态同步保证了leader和server具有相同的系统状态

  (2)、这时候当一个server加入zookeeper服务中,它会在恢复模式下启动,发现leader,并和leader进行状态同步。待到同步结束,它也参与消息广播。Zookeeper服务一直维持在Broadcast状态,直到leader崩溃了或者leader失去了大部分的followers支持。

   广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。

  实现中zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch。低32位是个递增计数。

8、Zookeeper节点数据 *** 作流程
     

  • 1.Client向Follower发出写请求
  • 2.Follower节点将请求转发给Leader
  • 3.Leader将数据写入到本节点,并将数据发送到所有的Follower节点
  • 4.等待Follower节点返回
  • 5.当Leader接收到一半以上节点(包含自己)返回写成功的信息之后,返回写入成功消息给原来的Follower
  • 6.原来的Follower返回写入成功消息给Client

     

9、zookeeper中watcher的使用及原理------事件监听机制
watcher的概念
zookeeper提供了数据的发布订阅功能,多个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容发生变化,节点下的子节点列表发生变化)会实时,主动通知订阅者;
zookeeper采用watcher机制实现了发布/订阅功能.该机制在被订阅者对象发生变化的时候会异步的通知客户端,因此客户端不必在watcher注册后轮询阻塞,从而减轻客户端的压力.


在进入watcher之前我们先试想在应用服务器集群中可能存在的两个问题:

(1)、因为集群中有很多机器,当某个通用的配置发生变化后,怎么让自动的让所有服务器的配置统一生效?
(2)、当集群中某个节点宕机,如何让集群中的其他节点知道?
为了解决这两个问题,zookeeper引入了watcher机制来实现发布/订阅功能,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态发生变化时,会通知所有订阅者。
 

watcher基本原理
zookeeper中实现watcher需要有三个部分,如下图所示:
分别是zookeeper服务端、客户端以及客户端的watchManager。

如图所示,客户端向zk注册watcher的同时,会将客户端的watcher对象存储在客户端的WatchManager中;zk服务器触发watch事件后,会向客户端发送通知,客户端线程从watchManager中取出对应watcher执行

 

Watcher特性 特性说明一次性Watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册客户端顺序回调Watcher回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态。一个Watcher回调逻辑不应该太多,以免影响别的watcher执行轻量级WatchEvent是最小的通信单元,结构上只包含通知状态、事件类型和节点路径,并不会告诉数据节点变化前后的具体内容;时效性Watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知;


 

10、zookeeper分布式锁原理
一个ZooKeeper分布式锁,首先需要创建一个父节点,尽量是持久节点(PERSISTENT类型),然后每个要获得锁的线程,都在这个节点下创建个临时顺序节点(ZNode)。由于ZK节点,是按照创建的次序,依次递增的。

为了确保公平,可以简单的规定:编号最小的那个节点,表示获得了锁。所以,每个线程在尝试占用锁之前,首先判断自己是排号是不是当前最小,如果是,则获取锁。

同样,释放锁的时候,就需要删除创建的Znode。创建成功后,如果不是排号最小的节点,就处于等待通知的状态。等谁的通知呢?不需要其他人,只需要等前一个Znode
的通知就可以了。前一个Znode删除的时候,会触发Znode事件,当前节点能监听到删除事件,就是轮到了自己占有锁的时候。第一个通知第二个、第二个通知第三个,击鼓传花似的依次向后


11、zookeeper负载均衡策略
服务器负载均衡有三大基本Feature:负载均衡算法,健康检查和会话保持
(1)、负载均衡算法

一般来说负载均衡设备都会默认支持多种负载均衡分发策略,例如:

Ø  轮询(RoundRobin)将请求顺序循环地发到每个服务器。当其中某个服务器发生故障,AX就把其从顺序循环队列中拿出,不参加下一次的轮询,直到其恢复正常。

Ø  比率(Ratio):给每个服务器分配一个加权值为比例,根椐这个比例,把用户的请求分配到每个服务器。当其中某个服务器发生故障,AX就把其从服务器队列中拿出,不参加下一次的用户请求的分配,直到其恢复正常。

Ø  优先权(Priority):给所有服务器分组,给每个组定义优先权,将用户的请求分配给优先级最高的服务器组(在同一组内,采用预先设定的轮询或比率算法,分配用户的请求);当最高优先级中所有服务器或者指定数量的服务器出现故障,AX将把请求送给次优先级的服务器组。这种方式,实际为用户提供一种热备份的方式。

Ø  最少连接数(LeastConnection):AX会记录当前每台服务器或者服务端口上的连接数,新的连接将传递给连接数最少的服务器。当其中某个服务器发生故障,AX就把其从服务器队列中拿出,不参加下一次的用户请求的分配,直到其恢复正常。

Ø  最快响应时间(Fast Reponse time):新的连接传递给那些响应最快的服务器。当其中某个服务器发生故障,AX就把其从服务器队列中拿出,不参加下一次的用户请求的分配,直到其恢复正常。

以上为通用的负载均衡算法,还有一些算法根据不同的需求也可能会用到,例如:

Ø  哈希算法( hash):  将客户端的源地址,端口进行哈希运算,根据运算的结果转发给一台服务器进行处理,当其中某个服务器发生故障,就把其从服务器队列中拿出,不参加下一次的用户请求的分配,直到其恢复正常。

Ø  基于策略的负载均衡:针对不同的数据流设置导向规则,用户可自行编辑流量分配策略,利用这些策略对通过的数据流实施导向控制。

Ø  基于数据包的内容分发:例如判断HTTP的URL,如果URL中带有.jpg的扩展名,就把数据包转发到指定的服务器。 


(2)、健康检查
健康检查用于检查服务器开放的各种服务的可用状态。负载均衡设备一般会配置各种健康检查方法,例如Ping,TCP,UDP,HTTP,FTP,DNS等。Ping属于第三层的健康检查,用于检查服务器IP的连通性,而TCP/UDP属于第四层的健康检查,用于检查服务端口的UP/DOWN,如果要检查的更准确,就要用到基于7层的健康检查,创建健康检查时可以设定检查的间隔时间和尝试次数,例如设定间隔时间为5秒,尝试次数为3,那么负载均衡设备每隔5秒发起一次健康检查,如果检查失败,则尝试3次,如果3次都检查失败,则把该服务标记为DOWN,然后服务器仍然会每隔5秒对DOWN的服务器进行检查,当某个时刻发现该服务器健康检查又成功了,则把该服务器重新标记为UP。

(3)、会话保持
会话保持用于保持会话的连续性和一致性,由于服务器之间很难做到实时同步用户访问信息,这就要求把用户的前后访问会话保持到一台服务器上来处理。举个例子,用户访问一个电子商务网站,如果用户登录时是由第一台服务器来处理的,但用户购买商品的动作却由第二台服务器来处理,第二台服务器由于不知道用户信息,所以本次购买就不会成功。这种情况就需要会话保持,把用户的 *** 作都通过第一台服务器来处理才能成功。


 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5688976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存