1、zk为什么设置奇数节点n?
zk容错+节省资源:zk选举master时的原则是存活的节点必须大于n/2节点。当有三台服务器存活是容错为1,四台服务器存活容错也是1,再最大容错的情况下,节省资源。再者多一台服务器计算和操作变得复杂耗时。
2、服务器选举leader实现
启动服务器时选举:
1)每个服务器都会选举自己进行投票,投票时包含自己的myid和zxid(事务ID),并且把投票内容发送给其他服务器。
2)接收各个服务器的投票信息。检查是否有效,并且状态为looking的本轮投票。
3)服务器把自己投票与其他服务器投票信息进行比对。zxid比较大的作为leader,相同再比较myid,比较大的作为leader。
4)每次投票后服务器都会记录下来,判断是否超过一半服务器收到相同信息,超过就开始选举。
5)选举之后更改服务器状态。follower状态更改为following,leader就更新状态为leading。
运行时选举(leader挂掉之后,服务不对外开发):
1)更改服务器状态为looking。非observer服务器状态都会改变,开始选举。
2)后续与启动时一致。
3、脑裂问题:网络通信故障后出现多个leader。
心跳机制来判断节点的存活状态解决这个问题。也带来了假死问题。
leader假死,重新选举后又活了过来。
ooKeeper每个节点都尝试注册一个象征master的临时节点,其他没有注册成功的则成为slaver,并且通过watch机制监控着master所创建的临时节点,Zookeeper通过内部心跳机制来确定master的状态,一旦master出现意外Zookeeper能很快获悉并且通知其他的slaver,其他slaver在之后作出相关反应。这样就完成了一个切换。
这种模式也是比较通用的模式,基本大部分都是这样实现的,但是这里面有个很严重的问题,如果注意不到会导致短暂的时间内系统出现脑裂,因为心跳出现超时可能是master挂了,但是也可能是master,zookeeper之间网络出现了问题,也同样可能导致。这种情况就是假死,master并未死掉,但是与ZooKeeper之间的网络出现问题导致Zookeeper认为其挂掉了然后通知其他节点进行切换,这样slaver中就有一个成为了master,但是原本的master并未死掉,这时候client也获得master切换的消息,但是仍然会有一些延时,zookeeper需要通讯需要一个一个通知,这时候整个系统就很混乱可能有一部分client已经通知到了连接到新的master上去了,有的client仍然连接在老的master上如果同时有两个client需要对master的同一个数据更新并且刚好这两个client此刻分别连接在新老的master上,就会出现很严重问题。
Zookeeper的解决方案
要解决Split-Brain的问题,一般有3种方式:
Quorums(ˈkwôrəm 法定人数) :比如3个节点的集群,Quorums = 2, 也就是说集群可以容忍1个节点失效,这时候还能选举出1个lead,集群还可用。比如4个节点的集群,它的Quorums = 3,Quorums要超过3,相当于集群的容忍度还是1,如果2个节点失效,那么整个集群还是无效的
Redundant communications:冗余通信的方式,集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。
Fencing, 共享资源的方式:比如能看到共享资源就表示在集群中,能够获得共享资源的锁的就是Leader,看不到共享资源的,就不在集群中。
ZooKeeper默认采用了Quorums这种方式,即只有集群中超过半数节点投票才能选举出Leader。这样的方式可以确保leader的唯一性,要么选出唯一的一个leader,要么选举失败。在ZooKeeper中Quorums有2个作用:
集群中最少的节点数用来选举Leader保证集群可用:通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据。
假设某个leader假死,其余的followers选举出了一个新的leader。这时,旧的leader复活并且仍然认为自己是leader,这个时候它向其他followers发出写请求也是会被拒绝的。因为每当新leader产生时,会生成一个epoch,这个epoch是递增的,followers如果确认了新的leader存在,知道其epoch,就会拒绝epoch小于现任leader epoch的所有请求。那有没有follower不知道新的leader存在呢,有可能,但肯定不是大多数,否则新leader无法产生。Zookeeper的写也遵循quorum机制,因此,得不到大多数支持的写是无效的,旧leader即使各种认为自己是leader,依然没有什么作用。