Zookeeper基本概念
集群角色
- Leader
提供读写服务 - Follower
提供读服务。在Leader不存的时候进行Leader选举。如果接收到客户端的事务操作则转发给Leader。 - Observer
不参与Leader选举,也不参与写操作的“过半写成功”策略。因此Observer可以在不影响写性能的情况下提升集群的读性能。
会话
在客户端和服务端第一次建立TCP连接之后会建立会话。服务器会维护一个客户端会话时间,在这个时间内会话就有效。
数据节点
ZNode
- 持久节点
- 临时节点
版本
每个ZNode都会有一个Stat结构存储三个数据版本
- Version:当前Znode版本
- CVersion:当前Znode子节点的版本
- AVersion:当前ZNode的ACL版本
ZAB协议
Zookeeper Atomic Broadcast : Zookeeper原子消息广播协议
ZAB协议是为分布式协调服务Zoopkeeper专门设计的一种支持崩溃恢复的原子广播协议。
核心
事务请求由Leader服务器处理,其他服务器为Follower服务器,Leader服务器将一个客户端事务请求转换为一个事务Proposal(提议),并将这个Proposal分发给集群中所有的Follower,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader再向所有的Follower服务器分发Commit消息,要求其将前一个Proposal进行提交。
两种基本模式
消息广播
Leader会为每个事务请求生成对应的Proposal来进行广播,Leader会为这个这个Proposal分配一个全局单调递增的唯一ID,即ZXID(事务ID)。Leader还会给每一个Follower分配一个单独的队列,然后将需要广播的事务Proposal放到队列中去,并且根据FIFO进行发送消息。
Follower接收到Proposal之后会以事务日志的方式写入到本地磁盘,然后返回给Leader一个ACK。
Leader接收到超过半数的ACK之后,给所有的Follower发送Commit消息,进行提交。
奔溃恢复
在Leader奔溃之后,选举出的新Leader是急集群中所有机器ZXID最大的。
ZXID是一个64位的数字,低32位是单调递增的计数器,高32位代表Leader周期epoch的编号。
三个阶段
上面的两种基本模式可以细分成三个阶段。
阶段一:发现
选举Leader,准Leader会选取整个集群中包含ZXID最大的Follower所执行的事务集作为初始事务集
阶段二:同步
Leader将初始事务集同步给所有Follower(两阶段提交)
阶段三:广播
Leader将从客户端收到的事务请求生成对应的事务Proposal,并发送给Follower进行同步(两阶段提交)
服务器状态
Looking:Leader选举阶段
Following:Follower服务器和Leader保持同步状态
Leading:Leader服务器作为主进程领导状态
Zookeeper技术内幕
系统模型
节点特性
节点类型
- 持久几点
- 持久顺序节点
- 临时节点
- 临时顺序节点
顺序节点:每个父节点会为它的第一级子节点维护一份顺序,用于记录创建的先后顺序,在创建节点的过程中可以自动为节点加一个数字的后缀(递增,上限是整型的最大值)
版本
每个ZNode都会有一个Stat结构存储三个数据版本
- Version:当前Znode版本
- CVersion:当前Znode子节点的版本
- AVersion:当前ZNode的ACL版本
Version用于乐观锁。
Watch机制
Watch机制主要包括客户端线程、客户端WatchManager和Zookeeper服务器三部分。
客户端在向Zookeeper服务器注册Watcher的同时会将Watch对象存储在客户端的WatchManager中,当Zookeeper触发Watcher事件后,会向客户端发送通知,客户端线程会从WatcherManager中取出对应的Watcher对象来执行回调逻辑。
-
客户端注册
-
服务端处理事件
在对指定的节点进行数据更新的时候,会调用注册时存储的Map,查看需要给哪些客户端发送Watch事件。发送完之后就会把这个客户端信息从Map中删除。所以一次Watch监听是一次性的,如果需要持续监听的话需要客户端反复注册。 -
客户端处理事件回调
Wather事件很简单,只有执行的节点和事件类型,通知转态等,并没有具体的变更内容,需要客户端执行一次查询操作才能获取变更内容。
Leader选举
选举原则
- 每个服务器第一轮投票都是投给自己
- ZXID比较大的优先作为Leader
- 可以变更投票;当收到比自己投票大的ZXID的投票消息的时候,会将自己的投票变更为这个较大ZXID服务器的投票。
- 获取超过半数投票的服务器成为Leader
数据存储
为了提高性能,Zookeeper的数据都是存储在内存中。
为了支持持久化,Zookeeper会把内存里的快照数据持久化到硬盘,可通过配置snapCount来控制,进行了多少次事务日志记录之后进行一个数据快照(不是完全按照这个配置的值来,会有一定的随机性)。
异步线程进行数据快照。
Zoopkeeper典型应用场景
选举Master
**原理:**利用Zookeeper的强一致的特性,在分布式高并发的情况下节点的创建能够保证全局唯一性,即Zookeepr可以保证客户端无法重复创建一个已经存在的节点。那么最终只会有一个客户端创建节点成功,创建成功的客户端成为Master。
创建的节点是临时节点,通过会话维持这个节点。没有创建成功的节点通过Watch机制监听这个节点,当Master宕机了,会话结束,监听的节点再来争夺创建新的几点,创建成功的节点为新的Master。
分布式锁
和选举Master差不多
问题:
-
ZK是CP模型么
-
同一时刻,不同的客户端有可能读取到的数据不一致么?
我理解是有可能的,因为ZAB协议只要求过半数的Follower回复了ACK就返回成功了,所以这个时候读没有ACK的Follower的时候会读到旧数据。
ZK应该不保证强一致性,只保证了在一定时间内达成一致。 -
Leader选举过程中系统是不可用的么?
是不可用的 -
follower是怎么同步Leader数据的,比如新加入集群的Follower
发现,同步,广播
-
ZK有持久化机制么?如果数据全部在内存里,如果全部机器重启了怎么办?
有快照机制