JAVA面试题分享二百八十九:什么脑裂?

本文探讨了分布式系统中脑裂问题的解决方案,如ZooKeeper通过奇数节点和Quorums过半机制防止脑裂,Elasticsearch通过手动设置法定候选人数量,以及Redis通过哨兵模式和配置参数限制slave数量来避免数据丢失。
摘要由CSDN通过智能技术生成

目录

step1:回答一下,什么是脑裂问题?

step2:嘚瑟一下,ZooKeeper如何解决脑裂

step3:嘚瑟一下,elasticSearch 如何解决脑裂

step4:再来回答redis 集群的脑裂

哨兵(sentinel)模式下的脑裂

集群(cluster)模式下的脑裂

手动解决问题

自动解决问题

如何解决脑裂?


step1:回答一下,什么是脑裂问题?

在一个高可用集群中,当多个服务器在指定的时间内,由于网络的原因无法互相检测到对方,而各自形成一个新的小规模集群,并且各小集群当中,会选举新的master节点,都对外提供独立的服务,

由于网络断裂的原因,一个高可用集群中,实际上分裂为多个小的集群,这种情况就称为裂脑。

也有的人称之为分区集群,或者大脑垂直分隔,互相接管对方的资源,出现多个Master的情况,都可以称为脑裂。

脑裂(Split-Brain)是一个形象的比喻,好比“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”。

裂脑之后的后果是,可能会导致服务器端的数据不一致,或造成数据的丢失

step2:嘚瑟一下,ZooKeeper如何解决脑裂

安装ZooKeeper之前,需要规划一下节点,ZooKeeper节点数有一个重要的要求:ZooKeeper集群节点数必须是奇数

这个要求,与ZooKeeper 的默认解决脑裂的策略有关系。

对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,

比如,为了高可用,将一个由 6 个节点的  zkServer 集群,部署在了两个机房,具体如下图:

正常情况下,此集群只会有一个 Leader,

并且 集群的Leader节点是集群通过选举的规则所有节点中选出来的,简称为选主。

那么如果机房之间, 发生断网,一个子网是3个节点,

一个大的集群, 被分割为 2个小的集群,每个小的集群各自3个节点,

选举出各自的leader,对外提供服务, 发生脑裂。

zk 如何解决脑裂问题呢?

ZooKeeper选主规则中很重要的一条是:要求“可用节点数量 > 总节点数量/2” 。

这条规则,叫做 Quorums  过半机制。

ZooKeeper集群使用了一种简单的节点数过半机制,确保集群被分裂后,还能否正常工作。

Quorums 直接翻译是 法定人数,就是通过投票的方式来,多数派才能选择 leader。ZooKeeper默认设置的是采用Majority Qunroms的方式来支持Leader选举。

过半机制就是“可用节点数量 > 总节点数量/2”,集群才能选举Leader,才是可用的,才可以对外服务;

为什么要“可用节点数量 > 总节点数量/2”呢?

在上图中,如果机房之间的网络断了之后,两个机房内的 zkServer 还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个 Leader。这就出现了 集群 脑裂(Split-Brain)。

所以,要求 “可用节点数量 > 总节点数量/2”。

但是, 在上面的例子中, 每个IDC机房,每个小的集群各自3个节点,都没有过半, 所以, 每个小集群都选举不了Leader,都不可用,当然,整个集群也不可用用。

从而, ZooKeeper集群节点数必须是基数。

发生断网之后,一定会出现一个大点的子集群和一个小的子集群。

  • 小的集群里边, 选举不了leader,不能提供服务。

  • 由大点的子集群, 选举一个 leader,提供服务。

比如, 集群节点只有 5个,断网之后,3个节点的小集群, 满足过半机制,还可以提供服务。

图片

Quorums  过半机制,就是解决集群的脑裂问题的默认机制。

为啥ZooKeeper集群节点数必须是奇数呢?

从上面的例子可以看到,Quorums  过半机制  在偶数节点的场景下,发生失效,而集群节点数必须是奇数可以规避 这个问题 。

更极端的例子是: 100个节点的集群,如果网络问题导致分为两个部分,50个节点和50个节点,这样整个集群还是不可用的,因为按照Quorums的方式必须51个节点才能保证选出1个Leader。

所以,ZooKeeper集群节点数必须是奇数, 规避Quorums   在偶数场景可能导致的无效问题。

另外,节点数配置成奇数,还有一个好处:集群的容忍度更高, 节省服务器资源

  • 比如3个节点的集群,Quorums = 2, 也就是说:  集群可以容忍1个节点失效,这时候还能选举出1个lead,集群还可用.

  • 比如4个节点的集群,它的Quorums = 3,Quorums要超过3,相当于集群的容忍度还是1,如果2个节点失效,那么整个集群还是无效的,  集群可以容忍的,仍然是1个节点失效,

所以:

4个节点的集群的容忍度 = 3个节点的集群的容忍度,但是4个节点的集群多了1个节点,相当于浪费了资源。

step3:嘚瑟一下,elasticSearch 如何解决脑裂

ElasticSearch 和  zookeeper集群一样,也存在脑裂问题。

不过,es 集群的leader ,改名字了,叫做 Master 节点,不叫做leader节点, 但是换汤不换药,本质是一样的。

es 集群中,候选主节点(即有资格成为主节点、master 候选人)配置为:

node.master: true
node.data: false

从节点配置为:

node.master: false 
node.data: true

候选主节点参与 master 的选举。

一个高可用的Es集群,候选 master 至少需要3个,保证 master 节点的高可用。

当然,可以更多,但是正式的master的选举,同样遵守  Quorums  过半机制。

只是, ES必须手动设置 法定候选人的数量, 通过以下参数设置:

discovery.zen.minimum_master_nodes

上面的参数值,设置超过所有候选节点一半以上来解决脑裂问题,即设置为 (N/2)+1;

该参数是用于控制选举行为发生的最小集群主节点数量

当备选主节点的个数大于等于该参数的值,且备选主节点中有该参数个节点认为主节点挂了,进行选举。

官方建议为(n/2)+1,n 为候选 master 个数(即有资格成为主节点的节点个数)

step4:再来回答redis 集群的脑裂

包括:

  • 哨兵(sentinel)模式下的脑裂

  • 集群(cluster)模式下的脑裂

哨兵(sentinel)模式下的脑裂

哨兵(sentinel)模式下的脑裂,主要是由于网络分区,导致 master、slave 和 sentinel 三类节点处于不同的网络分区。

此时哨兵无法感知到 master 的存在,会将 slave 提升为 master 节点。

此时就会存在两个 master,就像大脑分裂,那么原来的客户端往继续往旧的 master 写入数据,而新的master 就会丢失这些数据

下面是一个例子:

图片

1个master与3个slave组成的哨兵模式(哨兵独立部署于其它机器),

刚开始时,2个应用服务器server1、server2都连接在master上,

如果master与slave及哨兵之间的网络发生故障,但是哨兵与slave之间通讯正常,

这时3个slave其中1个,经过哨兵投票后,提升为新master,

如果恰好此时server1仍然连接的是旧的master,而server2连接到了新的master上。

脑裂之后,会数据就不一致了,下面有两个例子:

1:基于setNX指令的分布式锁,可能会拿到相同的锁,因为这个锁,处于不同的 mater上边 ;

2:基于incr生成的全局唯一id,也可能出现重复, 因为这个id, 在不同的master上边。

集群(cluster)模式下的脑裂

图片

cluster模式下,这种情况要更复杂,例如集群中有6组分片,每给分片节点都有1主1从,

如果出现网络分区时,各种节点之间的分区组合都有可能。

手动解决问题

在正常情况下,如果master挂了,那么写入就会失败,

如果是手动解决,那么人为会检测master以及slave的网络状况,然后视情况,

如果是master挂了,重启master,

如果是master与slave之间的连接断了,可以调试网络,

这样虽然麻烦,但是是可以保证只有一个master的,所以只要认真负责,不会出现脑裂。

自动解决问题

Redis cluter 内部中有一个故障转移机制,如果一旦发现master挂了,就在slave中选举新的master节点以实现故障自动转移。

问题,就出现在这个自动故障转移上,如果一旦大家监测不到一个master,尽管master还是在正常运行,集群也认为它挂了,会在slave中选举新的master,

而有一部分应用仍然与旧的master交互,当旧的master与新的master重新建立连接,旧的master会同步新的master中的数据,而旧的master中的数据就会丢失。

所以,自动故障转移, 在发生脑裂的之后恢复的时候,会导致老master数据的丢失

如何解决脑裂?

设置每个master限制slave的数量

redis的配置文件中,存在两个参数

min-slaves-to-write 3
min-slaves-max-lag 10
  • 第一个参数表示连接到master的最少slave数量

  • 第二个参数表示slave连接到master的最大延迟时间

按照上面的配置,要求至少3个slave节点,且数据复制和同步的延迟不能超过10秒,否则的话master就会拒绝写请求,

配置了这两个参数之后,如果发生集群脑裂,原先的master节点接收到客户端的写入请求会拒绝,就可以减少数据同步之后的数据丢失。

注意:较新版本的redis.conf文件中的参数变成了

min-replicas-to-write 3
min-replicas-max-lag 10

解决 redis中的异步复制情况下的数据丢失问题,也能使用这两个参数

配置这两个参数之后,如果发生集群脑裂,原先的master节点接收到写入请求就会拒绝,就会减少数据同步之后的数据丢失

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值