介绍
ZooKeeper是用于分布式高性能协调服务的应用程序。它在一个简单的界面中公开了常见的服务,例如命名,配置管理,同步和组服务。您可以现成使用它来实现共识,组管理,领导者选举和状态协议。
注意事项
- 配置的服务器必须是奇数的,例:3台、5台
- 设置好Java堆的大小,如果机器内存有4G就设置3G,因为系统缓存也需要内存,最好实际测试下,否则后果很严重…
配置
找到安装后ZooKeeper的conf路径,创建一个zoo.cfg文件,配置如下
tickTime
ZooKeeper使用的基本时间单位(毫秒)。它用于做心跳,并且最小会话超时将是tickTime的两倍。
dataDir
存储内存数据库快照的位置,除非另有说明,否则存储数据库更新的事务日志。
如果是集群模式,在此目录创建myid文件,并将服务的ID保存在里面,ID取server.后面的数字。
例:server.1=192.168.1.0:2888:3888,取1为ID。
clientPort
用户客户端连接的端口,结合搜客户端的请求访问。
dataLogDir
Zookeeper 保存日志文件的目录。
选举原理
选举状态
LOOKING: 竞选状态。
FOLLOWING: 随从状态,同步 leader 状态,参与投票。处理非事务请求, 转发事务请求给 Leader。
OBSERVING: 观察状态,同步 leader 状态,不参与投票。
LEADING: 领导者状态。
重要参数
服务器 ID(myid):编号越大在选举算法中权重越大。
事务ID(zxid):值越大说明数据越新,权重越大。
逻辑时钟(epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加。
启动时选举
介绍
每个节点启动的时候都 LOOKING 观望状态,然后进行选举主流程。以三台机器组成的集群为例。第一台服务器 server1启动时,无法进行 leader 选举,当第二台服务器 server2 启动时,两台机器可以相互通信,进入 leader 选举过程。
步骤
- 每台 server 发出一个投票,由于是初始情况,server1 和 server2 都将自己作为 leader 服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch,使用(myid,zxid)表示,此时 server1 投票为(1,0),server2 投票为(2,0),然后将各自投票发送给集群中其他机器。
- 接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
- 分别处理投票。针对每一次投票,服务器都需要将其他服务器的投票和自己的投票进行对比,对比规则如下:
- 优先比较 epoch
- 检查 zxid,zxid 比较大的服务器优先作为 leader
- 如果 zxid 相同,那么就比较 myid,myid 较大的服务器作为 leader 服务器
- 统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2 都统计出集群中有两台机器接受了(2,0)的投票信息,此时已经选出了 server2 为 leader 节点。
- 改变服务器状态。一旦确定了 leader,每个服务器响应更新自己的状态,如果是 follower,那么就变更为 FOLLOWING,如果是 Leader,变更为 LEADING。此时 server3继续启动,直接加入变更自己为 FOLLOWING。
图解
1.下面图中,每个服务器都会发出投票
2.投票后,leader发送心跳,如果跟随者指定时间内没有收到心跳,会开始新一轮的选举。
运行时选举
当集群中 leader 服务器出现宕机或者不可用情况时,余下的非Observer服务器都会将自己的服务器状态变更为LOOKING,整个集群无法对外提供服务,进入新一轮的 leader 选举。
- leader 挂后,其他非 Oberver服务器将自身服务器状态变更为 LOOKING。
- 每个 server 发出一个投票。在运行期间,每个服务器上 zxid 可能不同。
- 处理投票。规则同启动过程。
- 统计投票。与启动过程相同。
- 改变服务器状态。与启动过程相同。
数据一致性(ZAB)
如图片所示,客户端发送一个写的请求后,Leader来协调数据的一致性。
- Leader给每一个Follower发送proposal
- Follower接收到事务Proposal,以事务日志的形式写入磁盘中,并向Leader反馈ACK
- 当Leader接收超过一半Follower的ACK时,广播事务cmmit