zookeeper的脑裂问题

article/2025/9/21 2:21:05

关于集群中的"脑裂"问题,不清楚的可以看这里(https://www.cnblogs.com/kevingrace/p/7205846.html),下面重点说下 Zookeeper 脑裂问题的处理办法。ZooKeeper 是用来协调(同步)分布式进程的服务,提供了一个简单高性能的协调内核,用户可以在此之上构建更多复杂的分布式协调功能。脑裂通常会出现在集群环境中,比如 ElasticSearch、Zookeeper 集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如 ElasticSearch 集群中有 Master 节点,Zookeeper 集群中有 Leader 节点。

一 Zookeeper 集群节点为什么要部署成奇数
zookeeper 容错指的是:当宕掉几个 zookeeper 节点服务器之后,剩下的个数必须大于宕掉的个数,也就是剩下的节点服务数必须大于 n/2,这样 zookeeper 集群才可以继续使用,无论奇偶数都可以选举 leader。例如5台 zookeeper 节点机器最多宕掉 2 台,还可以继续使用,因为剩下 3 台大于 5/2。那么为什么最好为奇数个节点呢?是在以最大容错服务器个数的条件下,会节省资源。比如,最大容错为 2 的情况下,对应的zookeeper 服务数,奇数为5,而偶数为6,也就是6个zookeeper 服务的情况下最多能宕掉2个服务,所以从节约资源的角度看,没必要部署6(偶数)个 zookeeper 服务节点。

zookeeper 集群有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。也就是说如果有 2 个 zookeeper 节点,那么只要有1个zookeeper 节点死了,那么 zookeeper 服务就不能用了,因为1没有过半,所以2个 zookeeper 的死亡容忍度为0;同理,要是有3个 zookeeper,一个死了,还剩下2个正常的,过半了,所以3个 zookeeper 的容忍度为1;同理也可以多列举几个:2->0; 3->1; 4->1; 5->2; 6->2 就会发现一个规律,2n 和 2n-1 的容忍度是一样的,都是 n-1,所以为了更加高效,何必增加那一个不必要的 zookeeper 呢。

根据以上可以得出结论:从资源节省的角度来考虑,zookeeper 集群的节点最好要部署成奇数个!!

二  Zookeeper 集群中的"脑裂"场景说明
对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由 6 台 zkServer 所组成的一个集群,部署在了两个机房:

19249a8bc64cc77f74815514b41716bc.png

 

图1

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

a85a429dda45de0c0caacda8b3c643d5.png

 

图2

这就相当于原本一个集群,被分成了两个集群,出现了两个"大脑",这就是所谓的"脑裂"现象。对于这种情况,其实也可以看出来,原本应该是统一的一个集群对外提供服务的,现在变成了两个集群同时对外提供服务,如果过了一会,断了的网络突然联通了,那么此时就会出现问题了,两个集群刚刚都对外提供服务了,数据该怎么合并,数据冲突怎么解决等等问题。刚刚在说明脑裂场景时有一个前提条件就是没有考虑过半机制,所以实际上 Zookeeper 集群中是不会轻易出现脑裂问题的,原因在于过半机制。

zookeeper 的过半机制:在领导者选举的过程中,如果某台 zkServer 获得了超过半数的选票,则此 zkServer 就可以成为 Leader 了。

举个简单的例子:如果现在集群中有 5 台 zkServer,那么 half=5/2=2,那么也就是说,领导者选举的过程中至少要有三台 zkServer 投了同一个 zkServer,才会符合过半机制,才能选出来一个 Leader。

有个疑问:zookeeper 选举的过程中为什么一定要有一个过半机制验证?因为这样不需要等待所有 zkServer 都投了同一个 zkServer 就可以选举出来一个Leader 了,这样比较快,所以叫快速领导者选举算法。

再来想一个问题,过半机制中为什么是大于,而不是大于等于呢?这就是更脑裂问题有关系了,比如回到上文出现脑裂问题的场景 [如上图1]:

当机房中间的网络断掉之后,机房1内的三台服务器会进行领导者选举,但是此时过半机制的条件是 "节点数 > 3",也就是说至少要4台 zkServer 才能选出来一个  Leader,所以对于机房1来说它不能选出一个 Leader,同样机房2也不能选出一个  Leader,这种情况下整个集群当机房间的网络断掉后,整个集群将没有 Leader。

而如果过半机制的条件是 "节点数 >= 3",那么机房1和机房2都会选出一个Leader,这样就出现了脑裂。这就可以解释为什么过半机制中是大于而不是大于等于,目的就是为了防止脑裂。

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

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

三  Zookeeper 集群"脑裂"问题处理
1.  什么是脑裂?

简单点来说,脑裂 (Split-Brain) 就是比如当你的 cluster 里面有两个节点,它们都知道在这个 cluster 里需要选举出一个 master。那么当它们两个之间的通信完全没有问题的时候,就会达成共识,选出其中一个作为 master。但是如果它们之间的通信出了问题,那么两个结点都会觉得现在没有 master,所以每个都把自己选举成 master,于是 cluster 里面就会有两个 master。

对于 Zookeeper 来说有一个很重要的问题,就是到底是根据一个什么样的情况来判断一个节点死亡 down 掉了。 在分布式系统中这些都是有监控者来判断的,但是监控者也很难判定其他的节点的状态,唯一一个可靠的途径就是心跳,Zookeeper 也是使用心跳来判断客户端是否仍然活着。

使用 ZooKeeper 来做 Leader HA 基本都是同样的方式:每个节点都尝试注册一个象征 leader 的临时节点,其他没有注册成功的则成为 follower,并且通过 watch  机制 (这里有介绍) 监控着leader所创建的临时节点,Zookeeper 通过内部心跳机制来确定 leader 的状态,一旦 leader 出现意外 Zookeeper 能很快获悉并且通知其他的 follower,其他 flower 在之后作出相关反应,这样就完成了一个切换,这种模式也是比较通用的模式,基本大部分都是这样实现的。但是这里面有个很严重的问题,如果注意不到会导致短暂的时间内系统出现脑裂,因为心跳出现超时可能是  leader 挂了,但是也可能是 zookeeper 节点之间网络出现了问题,导致 leader 假死的情况,leader其实并未死掉,但是与 ZooKeeper 之间的网络出现问题导致Zookeeper 认为其挂掉了然后通知其他节点进行切换,这样 follower 中就有一个成为了 leader,但是原本的 leader 并未死掉,这时候 client 也获得 leader 切换的消息,但是仍然会有一些延时,zookeeper 需要通讯需要一个一个通知,这时候整个系统就很混乱可能有一部分 client 已经通知到了连接到新的 leader 上去了,有的 client 仍然连接在老的 leader 上,如果同时有两个 client 需要对 leader 的同一个数据更新,并且刚好这两个 client 此刻分别连接在新老的 leader 上,就会出现很严重问题。

这里做下小总结:假死:由于心跳超时(网络原因导致的)认为 leader 死了,但其实 leader 还存活着。脑裂:由于假死会发起新的 leader 选举,选举出一个新的 leader,但旧的 leader 网络又通了,导致出现了两个 leader ,有的客户端连接到老的 leader,而有的客户端则连接到新的 leader。

2.  zookeeper 脑裂是什么原因导致的?主要原因是 Zookeeper 集群和 Zookeeper client 判断超时并不能做到完全同步,也就是说可能一前一后,如果是集群先于 client 发现,那就会出现上面的情况。同时,在发现并切换后通知各个客户端也有先后快慢。一般出现这种情况的几率很小,需要 leader 节点与 Zookeeper 集群网络断开,但是与其他集群角色之间的网络没有问题,还要满足上面那些情况,但是一旦出现就会引起很严重的后果,数据不一致。

3.  zookeeper 是如何解决"脑裂"问题的?要解决 Split-Brain 脑裂的问题,一般有下面几种种方法:- Quorums (法定人数) 方式: 比如3个节点的集群,Quorums = 2, 也就是说集群可以容忍1个节点失效,这时候还能选举出1个 lead,集群还可用。比如4个节点的集群,它的 Quorums = 3,Quorums 要超过3,相当于集群的容忍度还是1,如果2个节点失效,那么整个集群还是无效的。这是 zookeeper 防止"脑裂"默认采用的方法。- 采用 Redundant communications  (冗余通信)方式:集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。- Fencing (共享资源) 方式:比如能看到共享资源就表示在集群中,能够获得共享资源的锁的就是 Leader,看不到共享资源的,就不在集群中。- 仲裁机制方式。- 启动磁盘锁定方式。

要想避免 zookeeper"脑裂"情况其实也很简单,在 follower 节点切换的时候不在检查到老的 leader 节点出现问题后马上切换,而是在休眠一段足够的时间,确保老的  leader 已经获知变更并且做了相关的 shutdown 清理工作了然后再注册成为  master 就能避免这类问题了,这个休眠时间一般定义为与 zookeeper 定义的超时时间就够了,但是这段时间内系统可能是不可用的,但是相对于数据不一致的后果来说还是值得的。

1) zooKeeper 默认采用了 Quorums 这种方式来防止"脑裂"现象,即只有集群中超过半数节点投票才能选举出 Leader。这样的方式可以确保 leader 的唯一性,要么选出唯一的一个 leader,要么选举失败。在 zookeeper 中 Quorums 有3个作用:

集群中最少的节点数用来选举 leader 保证集群可用。

通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据。

假设某个 leader 假死,其余的 followers 选举出了一个新的 leader。这时,旧的leader 复活并且仍然认为自己是 leader,这个时候它向其他 followers 发出写请求也是会被拒绝的。因为每当新 leader 产生时,会生成一个 epoch 标号(标识当前属于那个 leader 的统治时期),这个epoch是递增的,followers 如果确认了新的leader 存在,知道其 epoch,就会拒绝 epoch 小于现任 leader epoch 的所有请求。那有没有 follower 不知道新的 leader 存在呢,有可能,但肯定不是大多数,否则新 leader 无法产生。Zookeeper 的写也遵循 quorum 机制,因此,得不到大多数支持的写是无效的,旧 leader 即使各种认为自己是 leader,依然没有什么作用。

zookeeper 除了可以采用上面默认的 Quorums 方式来避免出现"脑裂",还可以可采用下面的预防措施:2) 添加冗余的心跳线,例如双线条线,尽量减少“裂脑”发生机会。3) 启用磁盘锁。正在服务一方锁住共享磁盘,"裂脑"发生时,让对方完全"抢不走"共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动"解锁",另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在  HA 中设计了"智能"锁。即正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。4) 设置仲裁机制。例如设置参考 IP(如网关 IP),当心跳线完全断开时,2个节点都各自 ping 一下 参考 IP,不通则表明断点就出在本端,不仅"心跳"、还兼对外"服务"的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够 ping 通参考 IP 的一端去起服务。更保险一些,ping 不通参考 IP 的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。
 


http://chatgpt.dhexx.cn/article/jaul8d1d.shtml

相关文章

什么是脑裂问题

所谓脑裂问题就是在多机热备的高可用系统中,当两个结点心跳突然断开,纠纷列为两个独立的个体,由于互相失去联系,都认为对方出现了故障,因此都会争抢对方的资源,这就是脑裂问题 当从节点们发现和主节点连接不…

集群脑裂问题分析

1.什么是集群脑裂 集群的脑裂通常是发生在集群中部分节点之间不可达而引起的(或者因为节点请求压力较大,导致其他节点与该节点的心跳检测不可用)。当上述情况发生时,不同分裂的小集群会自主的选择出master节点,造成原…

Redis中的常见问题(穿透、雪崩、脑裂)

文章目录 1.Redis的缓存穿透2.Redis缓存雪崩的问题3.Redis的脑裂问题 1.Redis的缓存穿透 2.Redis缓存雪崩的问题 3.Redis的脑裂问题 客户端向主服务器写入了数据 但是主服务器还没有来得及同步的情况下 主服务器死了 那么这个时候就会选举新的主服务器 原来的主服务器在一段时间…

脑裂是什么,zk是如何解决脑裂问题的

什么是脑裂 脑裂(split-brain)就是“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”,我们都知道,如果一个人有多个大脑,并且相互独立的话,那么会导致人体“手舞足蹈”,“不听使唤”。 脑裂…

堆叠脑裂

堆叠脑裂 一、什么是堆叠脑裂二、堆叠脑裂的危害三、如何解决堆叠脑裂四、DAD是如何工作的五、DAD恢复机制:六、DAD检测方式:1、 业务口直连检测方式2、Eth-Trunk口代理检测方式3、管理网口检测方式4、堆叠端口检测方式 一、什么是堆叠脑裂 堆叠建立后&…

Redis 的脑裂现象和解决方案

Redis 中的脑裂是什么? 从名字分析,脑裂现象就是大脑裂开了,一个人如果有两个大脑,就出现了两个决策者,此时身体就不知道该听谁的了,势必会造成混乱。 对应到 Redis 上,就是指在主从集群中&am…

Redis脑裂现象及解决方案

Redis脑裂现象及解决方案 什么是Redis的脑裂现象 当Redis主从集群环境出现两个主节点为客户端提供服务,这时客户端请求命令可能会发生数据丢失的情况。 脑裂出现的场景 场景一 主从哨兵集群中如果当发生主从集群切换时,那么一定是超过预设quorum数量…

分布式系统的“脑裂”到底是个什么玩意?

目前大多数项目都在往分布式上发展,一旦系统采用分布式系统,便会引入更多复杂场景和解决方案。比如,当你在系统中使用了Elasticsearch、ZooKeeper集群时,你是否了解过集群的“脑裂”现象?又是否知道它们是如何解决脑裂…

JDBC编程--jdbc基本操作步骤

JDBC即java数据库互连,是java语言和数据库之间独立于数据库的连接标准API,JDBC从根本上来说是一种规范,具体的实现需要依赖于具体数据库生产商提供jar包【驱动】,提供了统一的接口用于访问不同的底层数据库,允许使用ja…

【Java】JDBC连接数据库详细步骤(面试必备)

系列文章目录 本文旨在详细讲解使用JDBC连接数据库的六个步骤 其中第一步注册驱动的讲解链接:JDBC—MySQL以类加载的方式注册驱动(反射)_m0_56164356的博客-CSDN博客 // 1、注册驱动// 2、获取连接// 3、获取数据库操作对象// 4、执行sql语句…

JDBC基本步骤

JDBC编程 JDBC即java数据库互连,是java语言和数据库之间独立于数据库的连接标准API,JDBC从根本上来说是 一种规范,具体的实现需要依赖于具体数据库生产商提供jar包【驱动】,提供了统一的接口用于访问不 同的底层数据库&#xff0…

Java使用JDBC步骤

学习目标: Java使用JDBC步骤 学习内容: 1.为项目导入mysql-jdbc的jar包 2.初始化驱动 3.建立与数据库的连接 4.创建Statement 5.执行SQL语句 6.关闭连接 7.使用try-with-resourced的方式自动关闭连接 知识详解: JAVA使用JDBC步骤&#xff…

JDBC之程序编写步骤

当当当当~~~~欢迎大家阅读,今天我们学习JDBC程序编写步骤 以上是JDBC程序编写步骤的流程图 步骤一:导入java.sql包 步骤二:加载并注册驱动程序 java.sql.Driver 接口:是所有 JDBC 驱动程序需要实现的接口,这个接口是…

JDBC具体的操作步骤

目录 1.加载驱动 Driver 2.获得连接 3.执行指令 4.关闭资源 一: 首先先建立一个包为:com.zking.util 包中建立一个类:DBHelper类//帮助类 使用静态代码块加载驱动 2. 定义连接语句 3. 获得连接方法 : 4. 关闭资源:连接c…

浅谈JDBC,JDBC实现的几大步骤

前言 当我们学完数据库之后总觉得数据库和java之间是没有联系的,但是我们还是要去学数据库是为了什么呐?现在就来了,现在我就来给大家讲讲怎么将数据库和java进行联系,我们也可以用数据库代替以前的IO流来存东西了。 JDBC 概述 …

【JDBC-1】jdbc编程六大步骤

文章目录 jdbc编程步骤1.注册驱动2.获取数据库的连接3.获取数据库操作对象4.执行sql语句5.处理查询结果集6.释放资源 jdbc编程步骤 jdbc编程6步:1.注册驱动2.获取连接3.获取数据库操作对象4.执行sql5.处理查询结果集6.释放资源1.注册驱动 注册驱动的作用&#xff…

如何使用jetty

一直都听说jetty跟Tomcat一样,是一个web容器。之前做项目的时候,也使用过jetty,不过当时jetty是作为一个插件,跟maven集成使用的。那个时候,由于是第一次使用jetty,感觉jetty跟Tomcat并不一样,启…

BAT优秀工具

1、腾讯智图:图片压缩优化平台 地址:智图_图片压缩在线工具_在线制作webp 智图可以帮你把图片压缩到很小,但是还是很清晰!有很多网站限制图片上传的大小,用这个就可以!在线的,很方便&#xff01…

GifCam2.0使用

GifCam2.0使用 有时候我们需要制作一个gif,那么我们可以用GifCam 。 GifCam 是一款能够轻松录制gif的软件,它体积小、免安装。它可以给现有的gif增加帧数。编辑gif图片,如添加文字、删除某些帧、修改特定帧的延迟等。 下载地址:h…

荒野大镖客2-解压即玩

游戏名称:荒野大镖客2发行时间:2019年12月6日游戏详细介绍:https://store.steampowered.com/app/1174180/Red_Dead_Redemption_2/ (STEAM网站)不了解这是什么游戏的可以看一下版本介绍:该版本由EMPRESS小组…