Zookeeper 脑裂问题

什么是脑裂?

脑裂(split-brain)就是“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”,如果一个人有多个大脑,并且相互独立的话,那么会导致人体“手舞足蹈”,“不听使唤”。
脑裂通常会出现在集群环境中,比如ElasticSearch、Zookeeper集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如ElasticSearch集群中有Master节点,Zookeeper集群中有Leader节点。
**官方定义:**当一个集群的不同部分在同一时间都认为自己是活动的时候,我们就可以将这个现象称为脑裂症状。通俗的说,就是比如当你的 cluster 里面有两个结点,它们都知道在这个 cluster 里需要选举出一个 master。那么当它们两之间的通信完全没有问题的时候,就会达成共识,选出其中一个作为 master。但是如果它们之间的通信出了问题,那么两个结点都会觉得现在没有 master,所以每个都把自己选举成 master。于是 cluster 里面就会有两个 master。
在脑裂发生时,集群中的每个子集可能都会继续工作,执行读取和写入操作。这可能会导致数据冲突和不一致性。例如,如果一个数据库集群发生脑裂,不同的子集可能会同时接收写入请求,导致数据在不同子集中不同步。当脑裂问题解决后,这些不同的数据可能会导致数据合并困难,进而导致数据损坏或数据丢失。

集群脑裂产生的原因?

一般集群脑裂都是由以下三个原因产生的

  1. 网络分区: 当集群中的节点之间的网络连接出现问题,导致某些节点无法与其他节点通信。例如高可用服务器各节点之间心跳线链路发生故障,高可用服务器上开启了iptables防火墙阻挡了心跳消息传输等等
  2. 节点故障: 集群中的某些节点可能因为硬件故障、操作系统问题或其他原因而失去响应,导致其他节点认为它们已经不再可用。例如网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)因心跳线间连接的设备故障(网卡及交换机)
  3. 通信问题: 由于通信协议、时钟同步等问题,节点可能无法准确地识别其他节点的状态,从而导致混淆。

那么如何判断集群是否发生了脑裂?

在分布式系统中这些都是有监控者来判断判断一个节点是否down 掉的,但是监控者也很难判定其他的节点的状态,唯一一个可靠的途径就是心跳,Zookeeper也是使用心跳来判断客户端是否仍然活着。
整体运转流程如下

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

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

如何解决脑裂问题?

过半机制

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

那zookeeper过半机制中为什么是大于,而不是大于等于?
这是为了减少脑裂的概率,假设现在有一个由6台zkServer所组成的一个集群,部署在了两个机房,每个机房都有3台zkServer,那么如果机房之间的网络断了之后,两个机房内的zkServer还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个Leader。

Quornums机制

即只有集群中超过半数节点投票才能选举出Leader。这样的方式可以确保leader的唯一性,要么选出唯一的一个leader, 要么选举失败。这是zookeeper防止"脑裂"默认采用的方法。
在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,依然没有什么作用。

通过Quorums机制来防止脑裂和假死,当leader挂掉之后,可以重新选举出新的leader节点使整个集群达成一致;当出现假死现象时,通过epoch大小来拒绝旧的leader发起的请求,在前面也已经讲到过,这个时候,重新恢复通信的老的leader节点会进入恢复模式,与新的leader节点做数据同步。不过这个如果旧的leader处理了数据,就会出现数据丢失的情况。

适当的超时设置

ZooKeeper 使用会话(Session)来管理客户端和服务器之间的连接,设置适当的会话超时时间可以减少脑裂的影响。较短的会话超时时间可以更快地检测到节点失效,从而减少不一致性。

采用Redundant communications (冗余通信)方式

集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。

网络配置优化

确保集群中的节点之间的网络连接稳定,避免分区和网络延迟。优化网络配置可以减少网络问题引发的脑裂。

启用磁盘锁

在 ZooKeeper 中,磁盘锁(Disk Lock)是一种额外的安全措施,用于防止脑裂问题。磁盘锁可以在主节点选举时帮助确保只有一个节点被选为主节点,从而降低脑裂风险。启用磁盘锁需要进行一些特定的配置和步骤。
以下是启用磁盘锁的一般步骤:

  1. 配置数据目录: 首先,您需要为每个 ZooKeeper 节点配置一个数据目录(dataDir)。数据目录是节点用于存储数据和元数据的位置。确保您的配置文件中已经正确设置了数据目录。
  2. 配置磁盘锁目录: 在 ZooKeeper 配置文件中,设置一个磁盘锁目录(dataLogDir)。这个目录将用于存储磁盘锁的文件。
  3. 启用磁盘锁: 在 ZooKeeper 的配置文件中,设置 syncEnabled 选项为 true。这将启用磁盘锁机制。
  4. 配置自动清理: 您还可以配置自动清理磁盘锁的选项,以便在主节点意外失效时,其他节点能够顺利选出新的主节点。具体配置可能因 ZooKeeper 版本而异,但通常会涉及到设置一些时间间隔。
  5. 重启 ZooKeeper 节点: 在配置文件修改完成后,您需要重启所有的 ZooKeeper 节点,以使配置生效。

磁盘锁的原理是通过将选举过程的相关信息写入磁盘锁文件,其他节点可以检查这些文件以决定是否进行选举。这在一定程度上增加了选举的稳定性,从而降低了脑裂风险。
请注意,虽然启用磁盘锁可以增加系统的稳定性,但它也会引入一些额外的磁盘 I/O 操作,可能会对性能产生一些影响。因此,在启用磁盘锁之前,建议您仔细评估您的系统需求和性能预期。
尽管磁盘锁可以确保选举信息写入磁盘,但如果出现写入延迟或错误,节点之间的信息同步可能会受到影响,可能导致脑裂。

参考文章

HA高可用集群中”脑裂”问题解决 - 运维总结 - 散尽浮华 - 博客园
Zookeeper集群”脑裂”问题 - 运维总结 - 散尽浮华 - 博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java虚拟机(JVM)框架

见:GitHub - eHackyd/Java_JVM: Java虚拟机(JVM)框架的学习笔记

Android studio实现水平进度条

原文 ProgressBar 用于显示某个耗时操作完成的百分比的组件称为进度条。ProgressBar默认产生圆形进度条。 实现效果图: MainActivity import android.os.Bundle; import android.view.View; import android.app.Activity; import android.widget.Button; import…

Python:多变量赋值

相关文章 Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 Python中的赋值语句可以同时对多个变量进行对象绑定(赋值),既可以是多变量链式赋值,也可以是多变量平行赋值&#x…

部署Spring Boot项目

上传jar包 之前在新建Spring Boot项目[1]使用mvn install的方式,已经构建出jar包。 通过scp或rz/sz,将该jar包上传到服务器 执行java -jar hello-0.0.1-SNAPSHOT.jar,发生如下报错: Exception in thread "main" java.lang.Unsuppo…

KubeAdmin方式搭建K8S(1.26.0)

本次安装K8S版本为1.26.0 服务器环境配置 ip描述配置192.168.233.221master节点CPU(2C) 内存(2G) 硬盘(50G)192.168.233.222node1节点CPU(2C) 内存(2G) 硬盘…

(笔记五)利用opencv进行图像几何转换

参考网站:https://docs.opencv.org/4.1.1/da/d6e/tutorial_py_geometric_transformations.html (1)读取原始图像和标记图像 import cv2 as cv import numpy as np from matplotlib import pyplot as pltpath r"D:\data\flower.jpg&qu…

Redis-监听过期key-JAVA实现方案

一、创建监听配置类 RedisListenerConfig。 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.d…

图文详解PhPStudy安装教程

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 官方下载 请在PhPStudy官方网站下载安装文件,官方链接如下:https://m.xp.cn/linux.html;图示如下: 请下载PhPStudy安装文件…

QML与C++的交互操作

QML旨在通过C 代码轻松扩展。Qt QML模块中的类使QML对象能够从C 加载和操作,QML引擎与Qt元对象系统集成的本质使得C 功能可以直接从QML调用。这允许开发混合应用程序,这些应用程序是通过混合使用QML,JavaScript和C 代码实现的。除了从QML访问…

OpenCV(十五):拷贝图像

在OpenCV中,拷贝图像数据时有两种方式:深拷贝(Deep Copy)和浅拷贝(Shallow Copy)。这两种拷贝方式的主要区别在于是否创建新的图像副本。 浅拷贝(Shallow Copy)是指将图像对象的指针…

Python中的计数器Counter

计数器counter是包含在collections模块中的容器。 什么是容器Container? 容器是容纳对象的对象。它们提供了一种访问所包含对象并对其进行迭代的方法。内置容器的例子有元组、列表和字典。其他内容包含在“collections”模块中。 Counter是dict的子类。因此&#…

WebGIS的一些学习笔记

一、简述计算机网络的Internet 概念、网络类型分类、基本特征和功用是什么 计算机网络的Internet 概念 计算机网络是地理上分散的多台独立自主的计算机遵循约定的通讯协议,通过软、硬件互连以实现交互通信、资源共享、信息交换、协同工作以及在线处理等功能的系统…

LabVIEW液压支架控制系统的使用与各种配置的预测模型的比较分析

LabVIEW液压支架控制系统的使用与各种配置的预测模型的比较分析 模型预测控制在工业中应用广泛。这种方法的优点之一是在求解最优控制问题时能够明确考虑对输入和输出状态施加的约束。控制对象模型用于有限时间范围内最优控制的实时计算。所使用的数学设备允许从具有单输入和单…

12 mysql char/varchar 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 char 类类型的相关数据的存储 …

电子邮件服务器

目录 一、相关知识 二、邮件服务器种类 三、邮件传输协议 四、DNS中的MX记录 五、电子邮件系统工作原理 六、配置文件相关参数 七、邮件服务器配置案例 7.1设置用户别名邮箱 7.2空壳邮件服务器 一、相关知识 1、电子邮箱系统三个组成部分 MUA(telnet):邮…

ATF(TF-A)安全通告 TFV-1 (CVE-2016-10319)

安全之安全(security)博客目录导读 ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-1 (CVE-2016-10319) 二、CVE-2016-10319 一、ATF(TF-A)安全通告 TFV-1 (CVE-2016-10319) Title 错误的固件更新SMC可能导致意外的大数据拷贝到安全内存中CVE ID CVE-2016-10319 Da…

JSX底层渲染机制

JSX底层渲染机制 一,.步骤 1.把我们写的jsx语法编译为虚拟DOM【virtualDOM】 虚拟DOM对象:框架自己内部构建的一套对象体系(对象的相关成员都是React内部绑定的),基于这些属性描述出我们所构建视图中的DOM接的相关特征 1基于ba…

python中如何不修改字符串的前提,使其对大小写字母不敏感

如果你希望在不修改原字符串的基础上实现大小写不敏感的比较,你可以使用内置函数str.casefold(),它会将字符串转换为小写并处理一些特殊字符,使得比较更加严格。下面是如何使用它来实现大小写不敏感的比较: x input() y input()…

通讯软件014——分分钟学会Matrikon HDA Explorer

本文介绍如何使用Matrikon HDA Explorer工具软件进行OPC HDA通讯调试。相关软件可登录网信智汇(wangxinzhihui.com)下载。 1、连接OPC HDA Server数据源“Kepware.KEPServerEX HAD.V6”。 2、添加标签:右键点击“Kepware.KEPServerEX HAD.V6”…

Oracle-day6:over()函数

目录 一、over()开窗函数 二、无参over()的使用 三、over(partition by 列名) 四、over(order by 列名 asc/desc) 五、over(partition by 列名 order by 列名 asc|desc) 六、练习(笔试) 一、over()开窗函数 拓展:数据库的版本 oracle:8i 9i 10g …