zookeeper浅析

概念

从设计模式角度来看,Zookeeper是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应。
Zookeeper使用主从复制模式,所有的写操作都要由Leader主导完成,而读操作可通过任意节点完成,因此Zookeeper读性能远好于写性能,更适合读多写少的场景。

组成

Leader:一个Zookeeper集群同一时间只会有一个实际工作的Leader,它会发起并维护与各Follwer及Observer间的心跳。所有的写操作必须要通过Leader完成再由Leader将写操作广播给其它服务器。
Follower:一个Zookeeper集群可能同时存在多个Follower,它会响应Leader的心跳。Follower可直接处理并返回客户端的读请求,同时会将写请求转发给Leader处理,并且负责在Leader处理写请求时对请求进行投票。
Observer: 角色与Follower类似,但是无投票权。(若增加Follower会增加了ZAB协议中投票过程的压力)

特性

顺序一致性:客户端发起的更新会按发送顺序被应用到 ZooKeeper 上(ZXID保证)。
原子性:更新要么成功,要么失败,不会出现部分更新。
单一性 :无论客户端连接哪个server,都不会看到比当前视图更老的视图。保证单一视图,可在读操作前使用 sync 方法。
可靠性:一旦数据更新成功,将一直保持,直到新的更新。
及时性:客户端会在一个确定的时间内得到最新的数据。

原子广播(ZAB)

写操作

根据ZAB协议,所有的写操作都必须通过Leader完成,Leader写入本地日志后再复制到所有的Follower节点。
二段提交:Leader第一步将消息提议发给Follower,当收到超过一半的Follower的Ack后,认为所有的Follower都收到了提议,第二步向所有Follower发送Commit信息。
通过Leader进行写操作:
二阶段提交——写Leader
通过Follower/Observer进行写操作:
二阶段提交——写Follower/Observer

选举

一旦Leader节点无法工作,ZAB协议能够自动从Follower节点中重新选出一个合适的替代者,即新的Leader,该过程即为领导选举。

myid:每个ZkServer在集群中的唯一id
zxid:每次更新操作都会单调递增,一共64位,高32位是leader的epoch,低32位是该epoch内事务的序号,每次epoch变化,低32位会重置;当低32位溢出时也会出发epoch++的变化。
  1. 选举优先选择zxid最大的,当zxid相等选择myid最大的。
  2. 如果已经确定有过半服务器认可了自己的投票则终止投票。
  3. 投票终止后,服务器开始更新自身状态。若过半的票投给了自己,则将自己的服务器状态更新为LEADING,否则将自己的状态更新为FOLLOWING。
  4. 重新选举后ZAB协议需要保证数据同步。Follower会将自己zxid信息发给Leader,Leader将其与自己zxid做对比,将同步信息(可能是新增可能是删除)发给对应的follower。当收到半数的follower同步Ack后就可以正式提供服务了。

一篇文章带你走近zookeeper

Watch机制

主动推送:Watch被触发时,由 zk服务器主动将更新推送给客户端,而不需要客户端轮询。
一次性:数据变化时,Watch 只会被触发一次。如果客户端想得到后续更新的通知,必须要在 Watch 被触发后重新注册一个 Watch。
可见性:如果一个客户端在读请求中附带 Watch,Watch 被触发的同时再次读取数据,客户端在得到 Watch 消息之前肯定不可能看到更新后的数据。换句话说,更新通知先于更新结果。
顺序性:如果多个更新触发了多个 Watch ,那 Watch 被触发的顺序与更新顺序一致。

配置管理

程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好.

集群管理

所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除。 新机器加入也是类似,所有机器收到通知:新兄弟目录加入.对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。

分布式锁

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

连接超时问题

在session timeout时间内重连成功

1.client连上时立刻收到事件type=session_event(-1),state=connected_state(3),不需要重新注册watcher,已创建的节点仍在存在;
2.重连后client把已有的watch信息全部收集起来发给服务端,服务端会把这些信息和自己的信息做比对,如果有不同会发送给客户端事件。以免心跳超时后,会话没有超时时,因为不是同一个TCP连接导致信息丢失。

超过session timeout时间后重连成功

客户端连上立刻收到事件type=session_event(-1),state=session_expired_state(-112),此时需要重新注册watcher,原有创建的节点被删除,需要重新创建一个客户端实例和重新注册监听器。若确认能连上(如稍后成功创建了一个节点),客户端又会收到事件type=session_event(-1),state=connected_state(3)。

一直重连不成功

客户端不会收到任何事件。

相关链接ZK 网络故障应对法

SessionTimeOut设置

SessionTimeOut是client和server协商的结果,并不是单纯地在client端配置。
1.client的recv_timeout随握手协议一起发给server

在这里插入图片描述
2.client的SessionTimeOut时间实际是经过服务端下发之后的,并不一定是最先设置的
在这里插入图片描述

配置文件配置了maxSessionTimeOut和minSessionTimeOut

最终SessionTimeOut,必须在minSessionTimeOut和maxSessionTimeOut区间里,如果跨越上下界,则以跨越的上届或下界为准。

配置文件没有配置maxSessionTimeOut和minSessionTimeOut

maxSessionTimeout没配置则 maxSessionTimeOut设置为 20 * tickTime

minSessionTimeOut没配置则 minSessionTimeOut设置为 2 * tickTime

默认配置中tickTime为2秒,SessionTimeOut的合法范围为 4秒~40秒;如果tickTime也没配置,那么tickTime缺省为3秒。

相关链接笃行杂记之Zookeeper SessionTimeOut分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值