脑裂通常会出现在集群环境中,比如ElasticSearch、Zookeeper集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如ElasticSearch集群中有Master节点,Zookeeper集群中有Leader节点。

什么是脑裂?

简单点来说,在正常的ZK集群中,只会有一个Leader, 而这个Leader就是整个集群的大脑,脑裂,顾名思义,大脑分裂,即产生了多个Leader。

ZK中脑裂的场景说明

对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由6台 ZK 所组成的一个集群,部署在了两个机房:

OpenStack脑裂 脑裂zookeeper_服务器

正常情况下,此集群只会有一个Leader,那么如果机房之间的网络断了之后,两个机房内的 ZK 还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个Leader。

 

OpenStack脑裂 脑裂zookeeper_zookeeper_02

这就相当于原本一个集群,被分成了两个集群,出现了两个"大脑",这就是所谓的"脑裂"现象。对于这种情况,其实也可以看出来,原本应该是统一的一个集群对外提供服务的,现在变成了两个集群同时对外提供服务,如果过了一会,断了的网络突然联通了,那么此时就会出现问题了,两个集群刚刚都对外提供服务了,数据该怎么合并,数据冲突怎么解决等等问题。

刚刚在说明脑裂场景时有一个前提条件就是没有考虑过半机制,所以实际上Zookeeper集群中是不会轻易出现脑裂问题的,原因在于过半机制。

ZK过半机制为什么是大于,而不是大于等于?

这就跟脑裂问题有关系了,比如回到上文出现脑裂问题的场景 :当机房中间的网络断掉之后,机房1内的三台服务器会进行领导者选举,但是此时过半机制的条件是 "节点数 > 3",也就是说至少要4台zkServer才能选出来一个Leader,所以对于机房1来说它不能选出一个Leader,同样机房2也不能选出一个Leader,这种情况下整个集群当机房间的网络断掉后,整个集群将没有Leader。而如果过半机制的条件是 "节点数 >= 3",那么机房1和机房2都会选出一个Leader,这样就出现了脑裂。这就可以解释为什么过半机制中是大于而不是大于等于,目的就是为了防止脑裂。

如果假设我们现在只有5台机器,也部署在两个机房:

OpenStack脑裂 脑裂zookeeper_集群环境_03

此时过半机制的条件是 "节点数 > 2",也就是至少要3台服务器才能选出一个Leader,此时机房件的网络断开了,对于机房1来说是没有影响的,Leader依然还是Leader,对于机房2来说是选不出来Leader的,此时整个集群中只有一个Leader。因此总结得出,有了过半机制,对于一个 ZK 集群来说,要么没有Leader,要么只有1个Leader,这样 ZK 也就能避免了脑裂问题。