zookeeper
zookeeper简介
分布式的协调服务,主要用户解决分布式系统中多个进程之间的同步限制,防止出现脏读;
应用场景
- 统一命名服务
ip映射域名
- 统一配置管理
znode存储配置消息
- 统一集群管理
znode存储集群节点的实时状态
- 服务动态上下线
创建临时节点用户服务动态上下线
- 软负载均衡
znode存储服务器的访问次数,
- 分布式锁
特点
- zk:一个领导者多个跟随者组成的集群
- 集群中只要有半个以上节点存活,zk集群就能正常的提供服务,所以部署zk集群时的节点数量都是奇数
- 全局数据一致,每个节点保存相同一份的数据副本
- 更新请求顺序执行。来自同一个client的更行请求按其发送顺序依次执行
- 数据更新原子性,要么成功要么失败
- 实时性,在一定范围内,client都能读到最新的数据
数据结构
zk数据模型结构类似unix文件的文件系统,整体类型一个树,每一个节点称为znode,每个znode默认存储1mb的数据,每个znode都能通过路径进行唯一标识

配置参数
名称 | 数据类型 | 含义 |
---|---|---|
tickTime | num | 心跳时长,单位毫秒 |
initLimit | num | 领导者和跟随者初始连接时能容忍的最多心跳数据( |
tickTime的数量) | ||
syncLimit | num | 领导者和跟随者通讯时长,如果超过这个配置的时间,则去除该跟随者 |
dataDir | String | 保存zk的数据的本地地址 |
dataLogDir | String | 存储顺序日志,缺省值为 |
dataDir的值 | ||
clinetPort | num | zk的端口 |
集群
选举机制
选举算法FastLeaderElection
术语介绍
myid
每个zk服务器,都需要再数据文件夹下创建一个名为myid的文件,该文件包含整合zk集群下的唯一的整数id,且该整数id必须和配置文件中的的hostnam必须一致(server点后面的id即为myid),myid越大再选举中的权重越大
server.1:zoo1:2888:3888
zxid
类似为RDBMS中的事务id,用于标识一个更新操作的proposal ID。为了保证顺序性,该zxid必须单调递增。
因此zk使用一个64位数来表示
高32位是Leader的epoch,从1开始,每次选举出新的Leader,epoch加一
低32位为该epoch内的序号,每次epoch变化都会将低32位的序号重置,这样来保证zkid的全局递增性
zj节点状态
一个ZK节点可能处于以下4种状态之一,在源码中以QuorumPeer#ServerState枚举来定义。
- LOOKING:不确定Leader的“寻找”状态,即当前节点认为集群中没有Leader,进而发起选举;
- LEADING:“领导”状态,即当前节点就是Leader,并维护与Follower和Observer的通信,当节点属于Leader时,负责写操作;
- FOLLOWING:“跟随”状态,即当前节点是Follower,且正在保持与Leader的通信,当节点属于Follower时只负责读请求;
- OBSERVING:“观察”状态,即当前节点是Observer,且正在保持与Leader的通信,但是不参与Leader选举,也不参与集群写操作时的投票。
选票数据结构
- logicClock
用来标识该服务发起的第几轮投票
- state
服务器状态
self_id
当前服务的myid
zelf_zxid
当前服务器上保存的最大zxid
- vote_id
被选举的服务器myid
- vore_zxid
被选举的服务器上所保存的最大的zxid
投票流程
自增选举流程
zk规定所有有效的投票必须在用一个轮次中,每个服务器在开启新一轮投票时,都会先自增自己维护的logicCLock
初始话投票
每个服务器在广播自己的选票前,会将自己的投票箱清空,该投票箱保存了所受到的选票。
例:服务器2投票给服务器3,服务器3投票给服务器1,则服务器1的投票箱为(2,3),(3,1),(1,1)。票箱只会记录每一个投票者的最后一票,如投票者更新自己的选票,则其它服务器收到给新选票会在自己票箱中更新该服务器的选票
发送初始化选票
每台服务器最开始都会通过广播把票投给自己
接收外部投票
服务器会先尝试给其他服务器获取选票,并记入自身的投票箱内。如果无法获取任务外部的投票,则会确认自己是否与集群这种其他服务器保持者有效连接,如果是则重新发送自己的投票;如果否,则马上与之创建连接
判断选举轮次
收到外部投票时,首次会根据投票信息中所包含的logicClock来进行不做的处理
- 外部投票的logicClock大于自身的logicClock
说明此次选举的轮次小于其他服务器的选举轮次,此时立即清空自身的票箱和更新自身的logicClock为新收到的logicClock,然后再对比自己之前的投票与收到的选票以确定是否需要变更自己的投票,最终再次将自己的选票广播出去
- 外部投票的logicClock小于自身的logicClock
忽略该投票
- 外部投票的logicClock等于自身的logicClock
进行选票pk
选票pk
选票pk基于(self_id,self_zxid)与(vote_id,vote_id)的对比