zookeeper集群搭建非常简单,准备三台安装好zookeeper服务器,在其zoo.cfg配置中分表添加如下配置
initLimit 10 集群中的follower与leader之间完成初始化同步连接时能容忍的最多心跳数(tickTime的数量)。如果zk集群环境数据量很大,同步数据时间会变长,这种情况下可以适当调大改参数 syncLimit 2 集群中的follower与leader的请求应答时间之间最多能容忍的心跳数
server.1=node1:2881:3881
server.2=node2:2881:3881
server.3=node3:2881:3881
其中1、2、3是服务id,通过在各自的dataDir目录下创建一个名为myid的文件为每一台服务器赋予一个服务器id,myid文件,一行只包含机器id的文本,id必须唯一,数值在1-255之间,
两个端口号 第一个是follower连接leader的端口号 第二个是选举leader的端口号,node1、node2、node3对应三台服务器的ip
配置好后,分别启动三台机器上的zookeeper,一个最小版的集群便搭建完成,可以通过日志看到相关leader和follower的信息,集群中的所有节点都可以提供服务,客户端连接时,连接串可以可以指定多个或者集群全部节点的连接地址,当一个节点不通时,客户端将自动切换到另一个节点。
凡是涉及到集群就必然会出现数据一致性问题,ZAB协议 (原子消息广播协议)就是专门为zookeeper设计的数据一致性协议。为了保证数据一致性,客户端所有的读取在任何节点都可以,写操作只能转发给lead节点去执行。zookeeper集群中写操作流程如下
leader服务器出现崩溃或者网络原因导致与过半的follower失去连接,zk集群就会进入崩溃修复模式,此时集群不可用,所以zookeeper集群是一个CP服务。ZAB协议规定如果一个事物proposal(提议)在一台机器上处理成功,那么所有的机器上都应该被处理成功,确保那些在leader服务器上提交的事物最终被所有服务器都提交,确保丢弃那些只在lead服务器被提出的proposal。
为了满足ZAB的要求,在zookeeper leader选举时就必须保证选举出来的leader服务器拥有集群中所有机器的最高ZXID的事物proposal。
ZXID(事务编号)是一个64位数字,低32位单调递增的计数器,leader每产生一个事物proposal,都会对计数器加1操作,高32位是leader纪元周期的编号,每当选举一个新leader,就会从这个leader服务器中取出最大的事物proposal的zxid,并从zxid中提取出对应的纪元值,在此基础上加1,之后此编号作为新的纪元,并将低32位从0开始重新计数。基于这样的规则可以解决事物proposal丢弃的问题,当一个包含了上一个leader周期内尚未提交的事物proposal的服务器重新加入集群,发现集群中已经存在leader,则follower的身份加入集群,此时leader服务器会根据自己服务器最后提交的事务proposal和follower上proposal比较,发现follower中有上一个leader周期内的事务proposal,leader会要求follower进行一个回退操作,回退到一个已经确实被集群中过半机器提交的最新的事务proposal
zookeeper leader选举时确保选出的leader符合两个要求:选出的leader上有最高的zxid以及过半节点同意,内置算法有:LeaderElection FastLeaderElection AuthFastLeaderElection
选举中的概念:服务器id,事务id,逻辑时钟(发起的投票轮数技术),选举状态 looking(竞选)、following、observing(观察,只同步不选举)、leading。
选举算法的具体步骤:
1、每个服务器都发起投票选举自己位lead,选举信息中包含上面的4个信息
2、其它服务器收到投票邀请后,比较发起者的zxid是否比自己大,大则投一票,相同的话则比较服务器id,比自己大则投一票
3、发起者收到投票反馈后,看投票数是否大于集群半数,大于则胜出称为lead,否则发起下一轮投票
leader选举出来后 需完成follower与新leader的同步,当半数的follower同步完成后,则可以提供服务。同步过程如下:
leader服务器会为每一个follower都准备一个队列,并将那些没有被各follower同步的事物以proposal消息的形式发送到各个follower,并在每一个proposal后跟一个comiit,follower收到消息后将其在本地应用,与leader同步后leader就会真正将该follower加入可用列表,超过半数后就可以提供服务。