PS:
ZK基础参见另一篇文章:《ZooKeeper简介、基础知识和主要配置》
使用的协议:
ZAB(zookeeper原子广播),为paxos的一种实现。
Zookeeper提供了三种选择策略:
LeaderElection
AuthFastLeaderElection
FastLeaderElection
这里仅介绍默认的算法:FastLeaderElection。
基础概念
Sid:服务器id;
Zxid:服务器的事务id,数据越新,zxid越大;
epoch:逻辑时钟,在服务端是一个自增序列,每次进入下一轮投票后,就会加1;
server状态:
Looking(选举状态)
Leading(领导者状态,表明当前server是leader)
Following(跟随者状态,表明当前server是Follower)
Observing(观察者状态、表明当前server是Observer)。
每个节点启动的时候都是LOOKING状态,如果这个节点参与选举但最后不是leader,则状态是FOLLOWING,如果不参与选举则是OBSERVING,leader的状态是LEADING。
Zookeeper选举原理,参考文章:
https://www.cnblogs.com/yuyijq/p/4116365.html
https://www.cnblogs.com/scuwangjun/p/9063149.html
zk集群关键特性:投票选leader,某节点要能选举获胜,票数必须大于集群数的一半(大于等于m=n/2+1),换句话说,过半存活,集群才可用。
所以,n=2、3时,m=2,当n=4、5时,m=3。
假设有3个节点,投票数必须大于等于2,然后挂掉1个,此时,还剩两个,过半,所以能选出leader。
如果有2个节点,然后挂掉1个,还剩1个,存活不过半,集群无法提供服务。(zk屏蔽了这种情况,要求集群节点总数必须大于等于3)
为什么?因为选举算法决定的,在代码里面有如下方法:
public boolean containsQuorum(Set<Long> ackSet) { return (ackSet.size() > half); }
假设有4个节点,投票数必须大于等于3,然后挂掉1个,此时,还剩3个,超过半数存活,且最多能投出3票,故能正常服务。但如果继续挂掉一个,就还剩2个了,就无法提供服务了。
所以,4个节点的容错数,和3个节点是一样的。
所以,部署4个节点是浪费,部署3个节点仅仅是为了节约资源。
同理,如果想容错数为2,用5个节点就行了。
为什么3个挂掉一个,还剩两个能选举成功?而4个挂掉2个,还剩两个就不能选举成功了?
我猜是和节点的状态有关,当然还和half变量有关(halt=配置的集群节点数/2,换句话说,和初始配置的集群节点数有挂)。
奇葩问题:如果配置的3个节点,但只启动两个节点,能选举成功吗?如果选举成功之后,再加入第三个节点,会发生什么变化?
Zookeeper观察者:
http://zookeeper.apache.org/doc/r3.5.5/zookeeperObservers.html
https://agapple.iteye.com/blog/1741921
ZK使用总结:
https://www.jianshu.com/p/eec133595c68
Zookeeper存在不稳定原因分析:
https://www.jianshu.com/p/f30ae8e75d6d
阿里巴巴为什么不用 ZooKeeper 做服务发现?:
http://jm.taobao.org/2018/06/13/做服务发现?/
采用zookeeper的EPHEMERAL节点机制实现服务集群的陷阱:
https://yq.aliyun.com/articles/227260
总结:
在粗粒度分布式锁,分布式选主,主备高可用切换等不需要高TPS 支持的场景下有不可替代的作用,而这些需求往往多集中在大数据、离线任务等相关的业务领域,因为大数据领域,讲究分割数据集,并且大部分时间分任务多进程/线程并行处理这些数据集,但是总是有一些点上需要将这些任务和进程统一协调,这时候就是 ZooKeeper 发挥巨大作用的用武之地。
但是在交易场景交易链路上,在主业务数据存取,大规模服务发现、大规模健康监测等方面有天然的短板,应该竭力避免在这些场景下引入 ZooKeeper,在阿里巴巴的生产实践中,应用对ZooKeeper申请使用的时候要进行严格的场景、容量、SLA需求的评估。
所以可以使用 ZooKeeper,但是大数据请向左,而交易则向右,分布式协调向左,服务发现向右。