Zookeeper脑裂问题以及为什么推荐奇数节点讲解

Zookeeper的选举算法

在zookeeper中,每一个节点都会有一个zxid和一个myid。其中zxid代表事务ID,而myid代表这个节点的ID。那么什么是事务ID呢,我们可以简单理解每一次操作,这个事务ID就会加1.比如添加数据,删除数据等。那么也就是说,zxid越大,代表这个节点的数据版本越新。也就是权重更高。而当zxid一样的情况下,myid越大权重越高,myid就是我们在配置文件中配置的id

举个栗子

假设有这样三个zk节点,经过选举,由于zxid是一样的,而节点3的myid最大为3,所以选中节点3为leaderZookeeper脑裂问题以及为什么推荐奇数节点讲解_第1张图片
假设有下面这样三个zk节点,经过选举,由于节点2的zxid最大为89,所以选中节点2为leader.
Zookeeper脑裂问题以及为什么推荐奇数节点讲解_第2张图片

为什么zk建议节点数量为奇数台

我们清楚zk的选举算法,下面来说说为什么zk建议的节点数量为奇数台。
这是因为zk里面有个限制,就是集群中存活的节点数必须要超过总节点数的半数才能继续提供服务,那么这是什么意思呢?
比方数我们有3台服务器的时候,其中一台坏了,存活节点为2,2>3/2.所以能继续提供服务,而当集群中两台出现故障,存活数就为1了,1<3/2,所以就不能对外提供服务了。
而当我们集群中有4台服务器,坏了1台,存活数为3,3>4/2.所以能继续提供服务,而当两台出现故障,存活数就为2. 2=4/2。zk中规定的是必须要大于半数,所以就不能提供服务了。
那么也就是说,集群中3台和4台你的容灾能力是一样的,都只能坏一台。那么你为什么要多装一台呢浪费资源呢?当然,如果是为了查询效率多装一台,其实也未尝不可的。
那么我们再说说,为什么zk要有集群中存活的节点数必须要超过总节点数的半数才能继续提供服务,这个规定呢?其中最主要的问题,是为了避免脑裂。

为什么ZK规定集群中存活的节点数必须要超过总节点数的半数才能继续提供服务?

现在很多公司为了容灾,机房都是分开部署,可能一个在上海,一个在昆明,我们设想一个场景,比如有两个机房,上海的机房有3台服务器,昆明的机房有2台服务器,这5台服务器构成了一个集群,一个leader,4个follow。
Zookeeper脑裂问题以及为什么推荐奇数节点讲解_第3张图片
如果当有一天电缆被挖怀了,上海的机房和昆明的机房没法连通了,会存在什么情况呢?
Zookeeper脑裂问题以及为什么推荐奇数节点讲解_第4张图片
情况一:原来的leader是在上海的服务器
我们假设原来的leader是在上海的服务器,那么昆明的两台服务器由于电缆被挖断,无法与leader建立连接,那么昆明的两台服务器就会认为主节点挂了,开始选举leader,2台服务器会把票投给其中的一台,2<5/2,不满足集群中存活的节点数必须要超过总节点数的半数才能继续提供服务的规定,所以昆明的机房是不能继续提供服务的。上海机房的存活数量为3台,组成了一个只有3个节点的小集群,3>5/2,所以上海的机房能继续提供服务。

情况而:原来的leader是在昆明的服务器
我们假设原来的leader是在昆明的服务器,那么上海的机房由于和leader断开,上海的机房会开始重新选举leader,上海机房的存活数量为3台,组成了一个只有3个节点的小集群,3>5/2,所以上海的机房能继续提供服务。昆明只剩下两台服务器,不满足集群中存活的节点数必须要超过总节点数的半数才能继续提供服务的规定,昆明机房是不能继续提供服务。

也就是说,即使出现两个机房网络通信断开的情况,ZK由于集群中存活的节点数必须要超过总节点数的半数才能继续提供服务这个规定,也只会有一个leader对外服务,不会出现各个机房分选出自己的leader的情况,这样就避免了脑裂(多个主节点)的问题

我们设想一下如果没有集群中存活的节点数必须要超过总节点数的半数才能继续提供服务这个规定,当出现故障的时候就可能会存在多个leader,就会造成数据不一致,各个机房自己玩自己的,而这是很致命的。

那么为什么一定要是超过半数,不能是等于半数呢?
我们还是以上面的图来说,如果上海和昆明各有3台服务器,总数是6台服务器。两个机房网络断开的时候,如果是等于半数,就会分选出各自的leader,出现脑裂的问题。

总结

ZK为了避免脑裂的问题,给出了一个规定:集群中存活的节点数必须要超过总节点数的半数才能继续提供服务,而正是由于这个规定,导致集群中n台和n+1台你的容灾能力是一样的(n为奇数),都只能坏一台。

你可能感兴趣的:(Zookeeper,zookeeper选举算法,zookeeper,脑裂,zookeeper脑裂问题)