当前位置: 首页 > news >正文

ES节点故障的容错方案

ES节点故障的容错方案

  • 1. es启动加载逻辑
    • 1.1 segment和translg组成和分析
    • 1.2 es节点启动流程
    • 1.3 es集群的初始化和启动过程
  • 2. master高可用
    • 2.1 选主逻辑
      • 2.1.1 过滤选主的节点列表
      • 2.1.2 Bully算法
      • 2.1.2 类Raft协议
      • 2.1.3 元数据合并
    • 2.2 HA切换
  • 3. 分片高可用
    • 3.1 集群分片汇报
    • 3.2 选举主分片
    • 3.4 主分片恢复
    • 3.4 副分片恢复
    • 3.2 分片恢复的一致性
    • 3.2 HA切换逻辑
    • 3.3 如果写入过程中,分片副本节点宕机,会如何处理?
  • 4. 疑问和思考
    • 4.1 如果一个es宕机,运行在es上的shard数据丢失,是否会自动做均衡?
  • 5. 参考文档

本文主要探讨es集群的高可用容错方案和容错能力的探讨。在出现单机故障时相关的容错方案。

更多关于分布式系统的架构思考请参考文档关于常见分布式组件高可用设计原理的理解和思考


1. es启动加载逻辑

1.1 segment和translg组成和分析

可以参考文章ES高可用架构涉及常用功能整理,本文不再赘述。

1.2 es节点启动流程

在这里插入图片描述
更多细节可以参考玩转Elasticsearch源码-一图看懂ES启动流程

1.3 es集群的初始化和启动过程

es集群的启动大致流程如下
在这里插入图片描述
这里的集群启动过程指集群完全重启时的启动过程,期间要经历选举主节点、主分片、数据恢复等重要阶段,理解其中原理和细节,对于解决或避免集群维护过程中可能遇到的脑裂、无主、恢复慢、丢数据等问题有重要作用。

2. master高可用

2.1 选主逻辑

es的master选主逻辑根据版本不同,有不同的调整

  • 7.0版本之前,使用Bully算法
  • 7.0版本以后,使用类Raft协议,基于Raft协议做了调整

2.1.1 过滤选主的节点列表

选举的第一步,就是需要过滤出选参选的活跃master节点列表,并判断活跃的master列表是否满足选举条件。

  1. 通过参数discovery.zen.ping.unicast.hosts 获取初始的master列表,之后需要做2个事情
  • 通过ping机制,获取列表中活跃的master列表
  • 由于人工静态配置的列表可能不全,因此需要跟活跃的初始列表通信,获取集群中能够成为master的所有节点
  1. 判断过滤出来的活跃master列表数量是否满足discovery.zen.minimum_master_nodes要求,如果不满足,说明集群中参选的数量不足,有可能会有脑裂的风险,不能进一步选举。否则无法满足quorum机制

注: 在7.0后版本中,废除了discovery.zen.minimum_master_nodes参数,而是通过类raft算法自行计算

2.1.2 Bully算法

Bully算法的基本原理就是,根据节点的ID大小来判定谁是leader

Bully算法在选举的时候会发送三种消息类型

  • 选举消息 (Election Message: Sent to announce election.)
  • 应答消息(Answer (Alive) Message: Responds to the Election message.)
  • 选举成功消息 (Coordinator (Victory) Message: Sent by winner of the election to announce victory.)

这三种消息类型组成了Bully的基础消息类型,这也是Bully算法选举必须要了解的东西。

分步解释

  • 节点1向节点,节点3发送选举,并且带上自己的序号1
  • 节点2,3接收到消息之后,进行序号比较,发觉自己的序号更大,向节点1返回应答消息Answer (Alive) Message,告知节点1被踢出选主序列(大概是这个意思)
  • 节点2向节点3发送选举请求,节点3找不到更高序号的节点发送选举请求了节点3向节点2返回应答消息,节点3收不到其他节点的应答消息了
  • 节点3被认为是leader,向其他节点发送Coordinator Message,选举成功的请求,将自己是master节点广播到节点1,节点2

从如上算法的介绍中,可以得知,

  • bully算法有点是简单,能够选出leader很容易。
  • bully算法有很多缺陷,最大的问题还是master假死后不能重新触发选主和难以规避脑裂问题

因此es给bully算增加了限制,以规避bully算法的原生问题。

  • 设置最少得节点参选数量discovery.zen.minimum_master_nodes
  • 至少满足(n+1)/2选票,才能成为leader

这也是为什么在7.0版本,选举算法切换为raft的重要原因。

2.1.2 类Raft协议

raft协议经常接触,可以参考 ETCD高可用架构涉及常用功能整理,不在介绍。

相比于Raft算法,Es的选主算法有如下不同

  • 初始为 Candidate状态
  • 允许多次投票,也就是每个有投票资格的节点可以投多票
  • 候选人可以有投票的机会
  • 可能会产生多个主节点,举例来说,如果node1,node2,node3进行选主

如果node1当选leader,但是node2发来了投票要求,那么node1无条件退出leader状态,node2选为主节点,但是node3也发来了投票要求,那么node2退出leader状态,node3当选主节点。

说明白了,就是保证最后当选的leader为主leader

2.1.3 元数据合并

无论是bully算法还是类raft协议,并不考虑当前节点的数据是否最新,而是在完成选举出leader后进行数据合并中完成数据的一致性问题。

原因是客户端在es的副本写入数据过程中,并不会通知master节点,因此master节点并不知道哪个节点的元数据最新,而是通过后续node节点的数据汇报进行完善,在这一点上跟hdfs的nn类似。

这跟etcd、zk有本质区别,因为etcd、zk的leader节点也是数据节点,所有的数据写入是从leader完成,follower进行同步,因此能够感知谁的数据最新。而es的master节点和node节点是拆分的,因此无法实现这一点,因此只能是类raft协议。

因此在完成leader选举后,需要进行元数据合并

  • 其他的master角色节点(没有选举成为master)发送自身的元数据给master
  • node节点上报自身元数据给master
  • master完成元数据合并后,广播到其他的节点经合并

2.2 HA切换

当探测到节点离开事件时,必须判断当前节点数是否过半。如果达不到半数以上,则放弃Master身份,重新加入集群。如果不这么做,则设想以下情况:假设5台机器组成的集群产生网络分区,2台一组,3台一组,产生分区前,Master位于2台中的一个,此时3台一组的节点会重新并成功选取Master,产生双主,俗称脑裂。(节点失效检测)

在这里插入图片描述

节点失效检测会监控节点是否离线,然后处理其中的异常。失效检测是选主流程之后不可或缺的步骤,不执行失效检测可能会产生脑裂(双主或多主)。

3. 分片高可用

3.1 集群分片汇报

完成master选主后,需要重建集群的shard路由表,该工作全部都是master完成

  • 最开始时,Master不知道主分片在哪,它向集群的所有其他节点询问,让其他节点把[website][0]分片的元信息发过来。
  • Master 收到所有返回后,它就有了这个 shard 的信息,然后根据某种策略选一个分片作为主分片。

是不是效率有些低?这种询问量=shard 数×节点数。所以说我们最好控制shard的总规模别太大。

3.2 选举主分片

构建完所有的分片信息,现在考虑把哪个分片作为主分片。

  • ES 5.x以下的版本,通过对比shard级元信息的版本号来决定。

但是有问题: 在多副本的情况下,考虑到如果只有一个 shard 信息汇报上来,则它一定会被选为主分片,但也许数据不是最新的,版本号比它大的那个shard所在节点还没启动。因此可能会数据丢失。

在解决这个问题的时候,ES 5.x开始实施一种新的策略:给每个 shard 都设置一个 UUID,然后在元信息中记录哪个shard是最新的(ES是先写主分片,再由主分片节点转发请求去写副分片,所以主分片所在节点肯定是最新的,如果它转发失败了,则要求Master删除那个节点,所以可以识别哪个分片最新)

如果集群设置了:禁止分配分片,集群仍会强制分配主分片。

"cluster.routing.allocation.enable": "none"

因此,在设置了上述选项的情况下,集群重启后的状态为Yellow,而非Red。

3.4 主分片恢复

由于每次写操作都会记录事务日志(translog),事务日志中记录了哪种操作,以及相关的数据。因此将最后一次提交(一次提交就是一次 fsync 刷盘的过程)之后的 translog中进行重放,建立索引,如此完成主分片的recovery。

3.4 副分片恢复

副分片的恢复是比较复杂的,在ES的版本迭代中,副分片恢复策略有过不少调整。副分片需要恢复成与主分片一致,同时,恢复期间允许新的索引操作。在目前的6.0版本中,恢复分成两阶段执行:

  • 阶段1
  1. 在主分片所在节点,获取translog保留锁,从获取保留锁开始,会保留translog不受其刷盘清空的影响
  2. 调用接口把shard做快照,这是已经刷磁盘中的分片数据,把这些shard数据复制到副本节点。
  3. 在阶段1完毕前,会向副分片节点发送告知对方启动engine,在阶段2开始之前,副分片就可以正常处理写请求了。

针对当前的分片数据做checkpoint,并送给副分片恢复,耗时长,但是并不影响新的数据写入(写的数据写入到新的translog中,并且在快照期间不会translog不会被清理)

  • 阶段2
  1. translog做快照,这个快照里包含从阶段1开始,到执行translog快照期间的新增索引
  2. 将这些translog发送到副分片所在节点进行重放。

涉及的数据量少,所以耗时短。

由于需要支持恢复期间的新增写操作(让ES的可用性更强),这两个阶段中需要重点关注以下几个问题:

es的分片恢复根据版本不同,有不同的调整

  • 6.0版本之前,副本分片数据全部来自主分片,需要从主分片同步
  • 6.0版本以后,副本分片数据先从本地的translog加载,在从主分片同步,环节主分片压力,是一个分片恢复的提升。

3.2 分片恢复的一致性

恢复时,因为主副分片恢复时间不一致,主分片先进行Recovery,然后副分片才能基于主分片进行Recovery,所以主分片可以工作之后,副分片可能还在恢复中,此时主分片会向副分片发送写请求,因此恢复reply与主分片可能会同时(或者不按发生顺序)对同一个doc进行操作。ES中通过doc的版本号解决这个问题,当收到一个版本号低于doc当前版本号的操作时,会放弃本次操作。对于特定的doc,只有最新一次操作生效。

3.2 HA切换逻辑

当主分片不可用时,es就会重新进行选举,把最新的副本分片提高到主分片的地位,由master进行检测和分片选主,并在分片完成选主后,触发分片的数据恢复逻辑。

3.3 如果写入过程中,分片副本节点宕机,会如何处理?

如果正在写入过程时,副本分片宕机或者出现异常,master会从shard分片中剔除该分片,继续执行写入。

  • 如果分片副本标记写入成功的节点数量,满足要求(具体等待多少副本取决于wait_for_active_shards的配置值),本次写入即可标记成功,并返回给客户端
  • 如果分片副本标记写入成功的节点数量,不满足要求(具体等待多少副本取决于wait_for_active_shards的配置值),本次写入即可标记失败,并返回给客户端,客户端来决定是否重试。

4. 疑问和思考

4.1 如果一个es宕机,运行在es上的shard数据丢失,是否会自动做均衡?

取决于是否配置自动分配参数cluster.routing.allocation.enable,默认是all,表示能够自动触发分配。

  • all:表示能够自动分配分片,如果节点宕机,节点上的涉及的分片副本会自动迁移到其他的节点上,从而满足副本要求(配置了节点标签,不满足分配条件的除外)
  • none: 不触发自动分配,通过在节点主动维护时使用。在进行节点维护时,如果希望临时关闭自动分配,可以使用如下方式
curl -XPUT http://127.0.0.1:9200/_cluster/settings -d '{"transient" : {"cluster.routing.allocation.enable" : "none"}
}'

是否配置主动触发分配,有利有弊,主要原因是自动分配不能识别难以识别业务高峰期,会占用磁盘io和网络带宽。并且如果只是短时间维护节点,触发分配后,机器维护完成,又要重新触发恢复分配,恢复时间较长,因此根据实际情况调整。

个人建议

  • 如果能够清楚的知道节点维护的时间和周期(比如1-2h),可以临时关闭自动分配(恢复时间快)
  • 如果不可预估节点维护的时间或者维护周期过长,不建议关闭自动分配(数据的安全重要度高)

5. 参考文档

  • ElasticSearch——详细看看ES集群的启动流程
  • ElasticSearch-新老选主算法对比

相关文章:

ES节点故障的容错方案

ES节点故障的容错方案 1. es启动加载逻辑1.1 segment和translg组成和分析1.2 es节点启动流程1.3 es集群的初始化和启动过程 2. master高可用2.1 选主逻辑2.1.1 过滤选主的节点列表2.1.2 Bully算法2.1.2 类Raft协议2.1.3 元数据合并 2.2 HA切换 3. 分片高可用3.1 集群分片汇报3.…...

【Flink】FlinkSQL实现数据从Kafka到MySQL

简介 未来Flink通用化,代码可能就会转换为sql进行执行,大数据开发工程师研发Flink会基于各个公司的大数据平台或者通用的大数据平台,去提交FlinkSQL实现任务,学习Flinksql势在必行。 本博客在sql-client中模拟大数据平台的sql编辑器执行FlinkSQL,使用Flink实现数据从Kafka传…...

Unity GC

本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com 简略版本 在 Unity 中,垃圾回收(Garbage Collection,GC)采用的是基于标记-清除(Mark and Sweep)算法的自动内存管理机制。 基于标记-清…...

Vue源码系列讲解——变化侦测篇【下】(Array的变化侦测)

目录 1. 前言 2. 在哪里收集依赖 3. 使Array型数据可观测 3.1 思路分析 3.2 数组方法拦截器 3.3 使用拦截器 4. 再谈依赖收集 4.1 把依赖收集到哪里 4.2 如何收集依赖 4.3 如何通知依赖 5. 深度侦测 6. 数组新增元素的侦测 7. 不足之处 8. 总结 1. 前言 上一篇文…...

【机器学习笔记】贝叶斯学习

贝叶斯学习 文章目录 贝叶斯学习1 贝叶斯学习背景2 贝叶斯定理3 最大后验假设MAP(Max A Posterior)4 极大似然假设ML(Maximum Likelihood)5 朴素贝叶斯NB6 最小描述长度MDL 1 贝叶斯学习背景 试图发现两件事情的关系(因果关系,先决条件&结论&#x…...

ElasticSearch之倒排索引

写在前面 本文看下es的倒排索引相关内容。 1:正排索引和倒排索引 正排索引就是通过文档id找文档内容,而倒排索引就是通过文档内容找文档id,如下图: 2:倒排索引原理 假定我们有如下的数据: 为了建立倒…...

win11安装mysql8.3.0压缩包版 240206

mysql社区版安装包版windows安装包下载地址 在系统环境变量path无点.的情况下 powershell 可以 .\ 或 ./ 开头表示当前文件夹cmd 可以直接命令或.\开头, 不能./开头 所以 .\ 在cmd和powershell中通用 步骤 在解压目录 .\mysqld --initialize-insecure root无密码初始化.\m…...

数据库索引与优化:深入了解索引的种类、使用与优化

数据库索引与优化:深入了解索引的种类、使用与优化 索引的种类 数据库索引是提高查询速度的重要手段之一,主要分为以下几种类型: 主键索引(Primary Key Index): 唯一标识表中的每一行数据,保…...

React 错误边界组件 react-error-boundary 源码解析

文章目录 捕获错误 hook创建错误边界组件 Provider定义错误边界组件定义边界组件状态捕捉错误渲染备份组件重置组件通过 useHook 控制边界组件 捕获错误 hook getDerivedStateFromError 返回值会作为组件的 state 用于展示错误时的内容 componentDidCatch 创建错误边界组件 P…...

分享66个相册特效,总有一款适合您

分享66个相册特效,总有一款适合您 66个相册特效下载链接:https://pan.baidu.com/s/1jqctaho4sL_iGSNExhWB6A?pwd8888 提取码:8888 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不…...

chagpt的原理详解

GPT(Generative Pre-trained Transformer)是一种基于Transformer架构的生成式预训练模型。GPT-3是其中的第三代,由OpenAI开发。下面是GPT的基本原理: Transformer架构: GPT基于Transformer架构,该架构由Att…...

dockerfile 详细讲解

当编写 Dockerfile 时,你需要考虑你的应用程序所需的环境和依赖项,并将其描述为一系列指令。下面是一个简单的示例,演示如何编写一个用于部署基于 Node.js 的网站的 Dockerfile: Dockerfile # 使用官方 Node.js 镜像作为基础镜像…...

跟着pink老师前端入门教程-day23

苏宁网首页案例制作 设置视口标签以及引入初始化样式 <meta name"viewport" content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0"> <link rel"stylesheet" href"css/normaliz…...

JRT监听程序

本次设计避免以往设计缺陷&#xff0c;老的主要为了保持兼容性&#xff0c;在用的设计就不好调了。 首先&#xff0c;接口抽象时候就不在给参数放仪器ID和处理类了&#xff0c;直接放仪器配置实体&#xff0c;接口实现想用什么属性就用什么属性&#xff0c;避免老方式要扩参数时…...

MCU+SFU视频会议一体化,视频监控,指挥调度(AR远程协助)媒体中心解决方案。

视频互动应用已经是政务和协同办公必备系统&#xff0c;早期的分模块&#xff0c;分散的视频应该不能满足业务需要&#xff0c;需要把视频监控&#xff0c;会议&#xff0c;录存一体把视频资源整合起来&#xff0c;根据客户需求&#xff0c;需要能够多方视频互动&#xff0c;直…...

1184. 欧拉回路(欧拉回路,模板题)

活动 - AcWing 给定一张图&#xff0c;请你找出欧拉回路&#xff0c;即在图中找一个环使得每条边都在环上出现恰好一次。 输入格式 第一行包含一个整数 t&#xff0c;t∈{1,2}&#xff0c;如果 t1&#xff0c;表示所给图为无向图&#xff0c;如果 t2&#xff0c;表示所给图为…...

学习 Redis 基础数据结构,不讲虚的。

学习 Redis 基础数据结构&#xff0c;不讲虚的。 一个群友给我发消息&#xff0c;“该学的都学了&#xff0c;怎么就找不到心意的工作&#xff0c;太难了”。 很多在近期找过工作的同学一定都知道了&#xff0c;背诵八股文已经不是找工作的绝对王牌。企业最终要的是可以创造价…...

Android 11 webview webrtc无法使用问题

问题&#xff1a;Android 11 webview 调用webrtc无法使用, 看logcat日志会报如下错误 [ERROR:address_tracker_linux.cc(245)] Could not send NETLINK request: Permission denied (13) 查了下相关的网络权限都有配置了还是不行&#xff0c;还是报这个权限问题 原因&#xff1…...

嵌入式单片机中晶振的工作原理

晶振在单片机中是必不可少的元器件&#xff0c;只要用到CPU的地方就必定有晶振的存在&#xff0c;那么晶振是如何工作的呢&#xff1f; 什么是晶振 晶振一般指晶体振荡器&#xff0c;晶体振荡器是指从一块石英晶体上按一定方位角切下的薄片&#xff0c;简称为晶片。 石英晶体谐…...

AWS配置内网EC2服务器上网【图形化配置】

第一种方法&#xff1a;创建EC2选择启用分配公网ip 1. 创建vpc 2. 创建子网 3. 创建互联网网关 创建互联网网关 创建互联网网关 &#xff0c;设置名称即可 然后给网关附加到新建的vpc即可 4. 给新建子网添加路由规则&#xff0c;添加新建的互联网网关然后点击保存更改 5. 新建…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...