文章三:Elasticsearch 集群恢复和索引分布

集群恢复网关与集群索引分布必要性了解

在 Elasticsearch(简称 ES)集群运维中,集群重启恢复、残余索引处理、索引分片分布是保障集群稳定性、数据完整性、读写性能的三大核心基础能力。多数集群故障、数据丢失、分片异常、读写卡顿问题,根源均来自这三个模块的认知不足与配置不当。

本文将聚焦 Cluster Gateway 集群恢复网关Dangling Index 残余索引挂载Cluster Allocation 集群索引分布 三大核心,通俗讲解其核心价值、工作原理、适用场景,并搭配完整实战操作,让读者彻底搞懂「为什么需要、是什么作用、怎么落地操作」。

Cluster Gateway 集群恢复网关实战操作

1.1 核心问题:为什么需要集群恢复网关?

ES 集群所有节点全部重启、机房断电、集群整体宕机后,会面临一个核心问题:集群重启后,如何找回原有集群状态、索引信息、分片分配规则?

如果没有网关机制,集群重启后会初始化全新空集群,所有历史索引、模板、分片配置、集群元数据全部丢失,直接造成业务数据不可用。

而 Cluster Gateway(集群恢复网关)是 ES 内置的集群元数据与持久化恢复模块,是集群整体重启后数据与状态恢复的唯一核心载体,所有生产集群必须依赖该机制实现故障自愈。

1.2 核心作用:网关到底做什么?

ES 默认使用 Local Gateway 本地网关,核心职责只有两个,贯穿集群全生命周期:

  1. 持久化集群元数据:实时记录集群所有状态,包括索引列表、索引分片配置、副本数、映射模板、集群权限、分片分配记录等,将动态集群状态落地到节点本地磁盘持久化存储,而非仅内存缓存。

  2. 集群重启状态恢复:集群整体重启、故障恢复后,新选举的 Master 节点会读取各节点磁盘中持久化的网关数据,还原完整集群状态、索引结构、分片分布,保证集群重启后数据不丢失、配置不重置。

简单总结:Gateway 是 ES 集群的"记忆硬盘",保存集群所有历史状态,保证集群断电重启后不失忆、不丢数据

1.3 核心原理与关键特性

  1. 持久化机制:集群元数据发生变更(新建/删除索引、修改分片配置、调整模板)时,网关会同步落地到磁盘,而非异步缓存,保证数据可靠性。

  2. 恢复触发机制:集群重启后,不会立即恢复数据,而是等待指定数量节点上线后,再统一触发分片恢复与状态同步,避免节点未完全启动导致的分片错乱、数据丢失问题。

  3. 生效范围:仅针对全集群重启生效,单节点重启、局部故障不会触发网关恢复逻辑。

1.4 核心配置参数(生产必备)

所有网关配置为静态配置,需写入所有主候选节点的 elasticsearch.yml,重启生效,核心参数如下:

  • gateway.expected_nodes:集群预期在线节点数,达到该数量后启动集群恢复,生产建议配置集群总节点数,避免节点未齐全就恢复导致分片异常。

  • gateway.recover_after_nodes:最小恢复节点数,满足该节点数即可触发恢复,防止少数节点启动后提前恢复引发数据不一致。

  • gateway.recover_after_time:等待恢复超时时间,若节点数未达标,超时后强制触发恢复,保障集群不会一直阻塞。

1.5 集群恢复网关实战操作

步骤1:配置网关恢复规则

以 3 节点集群为例,修改所有主节点配置文件:

复制代码
# 集群网关恢复配置
gateway.expected_nodes: 3          # 预期3个节点全部上线
gateway.recover_after_nodes: 2    # 至少2个节点上线即可启动恢复
gateway.recover_after_time: 5m    # 最长等待5分钟,超时强制恢复

步骤2:全集群重启模拟故障

依次停止所有 ES 节点,模拟机房断电、全集群宕机场景,之后逐一启动所有节点。

步骤3:验证集群恢复状态

查询集群健康状态,确认集群恢复正常、索引全部存在:

复制代码
# 查看集群健康
GET _cat/health?v

# 查看所有恢复的索引
GET _cat/indices?v

# 查看分片恢复进度
GET _cat/recovery?v

#查看集群的健康程度
GET _cluster/health

步骤4:核心现象验证

节点刚启动时,集群状态为 yellow/red,等待达标后自动恢复为 green,所有历史索引、分片配置完全保留,证明网关恢复生效。

1.6 Elasticsearch 索引恢复速度调优参数详解

我们在进行索引设置的时候可以通过参数调优加快索引恢复的速度,下面为大家展示两个参数:

恢复网络带宽限制:

indices.recovery.max_bytes_per_sec,该参数用于限制单个节点在进行分片恢复(Recovery)时的最大网络传输速率

Elasticsearch 为了防止数据恢复过程(通常涉及大量的磁盘读取和网络传输)占满整个集群的带宽,从而影响正常的搜索和写入业务,默认对此进行了严格的限速。

默认值,40mb(即每秒 40MB)。这是一个非常保守的值,旨在保证业务稳定性,但在急需恢复数据时会显得过慢。

调优建议
  • 加快恢复 :在业务低峰期或集群急需恢复健康状态时,可以显著调大该值(例如设置为 100mb200mb 甚至 500mb),以充分利用内网的高带宽资源。
  • 保护业务:如果恢复过程导致业务查询延迟增加,应适当调小该值,为正常业务留出网络资源。

恢复并发操作数:

indices.recovery.max_concurrent_operations,该参数控制在分片恢复过程中,并行发送的操作请求数量 (主要指 Lucene 段文件的传输和操作并发度)。

简单来说,它决定了恢复线程在搬运数据时的"并发力度"。数值越大,同一时间内处理的恢复任务片段越多。(起使也是可以理解成就是他的单位指的就是分片)

默认值2。这也是一个相对保守的默认设置,旨在避免过高的 I/O 压力。

调优建议
  • 加快恢复 :如果节点的 CPU 和磁盘 I/O(特别是 SSD)性能较强,可以将此值调大(例如 48),通过提高并发度来加速恢复流程。

  • 资源权衡:调大此参数会增加 CPU 和磁盘 I/O 的负载。如果节点负载已经很高,盲目调大可能会导致节点响应变慢甚至不稳定。

    PUT /_cluster/settings
    {
    "transient": {
    "indices.recovery.max_concurrent_operations": 2,
    "indices.recovery.max_bytes_per_sec": "40mb"
    }
    }

indices.recovery.max_concurrent_operations 在100个节点内,设置成8就已经很足够了,

indices.recovery.max_bytes_per_sec"设置成40mb的倍数,在200MB之内就可以了

Dangling Index 静态索引挂载实战操作

核心问题:什么是残余索引?为什么需要处理?

在 ES 集群运维中,残余索引的产生分为常规故障场景和集群迁移场景,覆盖日常故障和集群迭代两大核心运维场景。

  • 节点离线故障 数据节点长时间脱离集群,期间集群内索引被删除、分片重新分配;节点重新上线后,本地留存的老旧数据无法被集群识别,形成残余索引。

  • 旧集群数据迁移 老旧集群停止下线,业务数据需要迁移复用。将旧集群磁盘索引文件迁移至全新空集群,新集群无对应元数据,原有数据自动判定为残余索引,可通过挂载恢复数据

残余索引挂载与清理实战操作

前置步骤:

在废弃集群的数据copy到当前的集群的文件中,之后通过执行下面的命令可以找到和将索引数据进行挂载。

拷贝文件过程中为了方式文件损坏,最好两个es集群都停机。

步骤1:查询集群残余索引

通过 API 查看集群识别到的所有悬空残余索引:

GET _dangling

返回结果会展示残余索引名称、UUID、分片数、所在节点、创建时间等核心信息,用于判断是否需要恢复。

步骤2:场景1:挂载恢复有效残余索引

若确认该残余索引是误删的有效数据,执行挂载操作,将其重新纳入集群管理:

# 挂载残余索引,替换为实际索引UUID

POST _dangling/<索引UUID>?accept_data_loss=true

参数说明:accept_data_loss=true 表示确认接受本次手动挂载,规避数据版本冲突风险,生产操作需确认数据有效性。

步骤3:场景2:清理无效残余索引

若残余索引为过期冗余数据,直接删除清理脏数据:

# 删除无效残余索引

DELETE _dangling/<索引UUID>

步骤4:验证操作结果

重新查询残余索引列表,确认无残留;查看集群索引列表,挂载的索引正常展示、分片正常分配。

Cluster Allocation 集群索引分布实战操作

核心问题:为什么需要索引分布调度?

ES 的性能、可用性、容灾能力,完全依赖主副分片的分布规则。如果无调度规则,会出现严重问题:

  • 主副分片分配在同一节点,单节点故障直接导致索引数据丢失、读写异常;

  • 分片集中在少数节点,节点负载不均,出现热点节点,引发查询卡顿、写入超时;

  • 新增节点后分片无法自动均衡,集群资源利用率极低;

  • 机房、机架同机房分片集中,机房故障整体数据不可用。

Cluster Allocation(集群分片分配/索引分布)就是 ES 的分片调度核心机制,用于管控所有索引主副分片的分配位置、均衡规则、故障迁移逻辑。

核心作用

简单来说,Allocation 决定「每一个索引的每一个分片,放在哪个节点」,核心价值三点:

  1. 保障高可用:强制主分片与副本分片异地部署,避免单节点故障导致数据丢失;

  2. 实现负载均衡:均匀分散所有索引分片,避免热点节点,最大化利用集群CPU、磁盘、IO资源;

  3. 控制分片调度逻辑:支持自定义机架、机房、节点属性调度,支持分片冻结、强制迁移、禁止分配、恢复分配等精细化管控。

集群索引分片分布核心配置:

java 复制代码
# ------------------------------ 分片分布设置 ------------------------------
# 允许索引分片自动分布,默认值
cluster.routing.allocation.enable: all
# 仅允许索引主分片分配
cluster.routing.allocation.enable: primaries
# 仅允许新创建的主分片分配
cluster.routing.allocation.enable: new_primaries
# 禁止集群分片自动分布
cluster.routing.allocation.enable: none

# ------------------------------ 分片分布移进移出 ------------------------------
# 分片分布移进移出节点并发限制,默认2
cluster.routing.allocation.node_concurrent_recoveries: 2
# 分片分布移进节点并发限制,默认2
cluster.routing.allocation.node_concurrent_incoming_recoveries: 2
# 分片分布移出节点并发限制,默认2
cluster.routing.allocation.node_concurrent_outgoing_recoveries: 2
# 节点主分片恢复并发控制,默认4
cluster.routing.allocation.node_initial_primaries_recoveries: 4

# ------------------------------ 限制相同分片分布在同一节点 ------------------------------
# 限制相同分片分布在同一节点 true/false,默认false=不限制
cluster.routing.allocation.same_shard.host: false

上面的配置都是动态的配置,我们可以在dvl tool中直接设置:

java 复制代码
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": "all",
    "cluster.routing.allocation.node_concurrent_recoveries": 2,
    "cluster.routing.allocation.node_concurrent_incoming_recoveries": 2,
    "cluster.routing.allocation.node_concurrent_outgoing_recoveries": 2,
    "cluster.routing.allocation.node_initial_primaries_recoveries": 4,
    "cluster.routing.allocation.same_shard.host": false
  }
}

在 ES 分片恢复并发参数配置中,node_concurrent_recoveries 管控单节点分片恢复总并发上限,incoming 与 outgoing 分别约束分片迁入、迁出的单向并发数量,配置时遵循逐级约束逻辑,若将总并发设置为 6,迁入迁出并发均配置为 2,单向阈值会优先限制迁移规模,节点实际最多仅能同时完成 2 个迁入、2 个迁出任务,无法触达总并发上限,参数配置失去扩容意义,日常调优需保证总并发数值不低于单向并发数值,才能让整体配额规则正常生效。

Cluster Rebalance集群索引分片分布平衡配置

java 复制代码
#----------------集群分片自动平衡设置----------------#
#以下设置4选1
#容许所有分片自动感知平衡,默认
cluster.routing.rebalance.enable: all
#容许主分片自动感知平衡分布
cluster.routing.rebalance.enable: primaries
#容许副本分片感知平衡分布
cluster.routing.rebalance.enable: replicas
#禁止所有分片自动感知平衡
cluster.routing.rebalance.enable: none

#----------------集群分片分布自动平衡策略设置----------------#
##以下设置3选1
#一直容许所有分片分布自动平衡
cluster.routing.allocation.allow_rebalance: always
#仅容许主分片 并且是 在线能提供服务的,比如关闭的索引分片就不在此范围
cluster.routing.allocation.allow_rebalance: indices_primaries_active
#容许所有分片,包括主分片与副本分片,默认值
cluster.routing.allocation.allow_rebalance: indices_all_active

#集群分片分布自动平衡并发现,集群层面限制,默认2
cluster.routing.allocation.cluster_concurrent_rebalance: 2

以上的配置也都是可以动态进行设置:

java 复制代码
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.rebalance.enable": "all",
    "cluster.routing.allocation.allow_rebalance": "indices_all_active",
    "cluster.routing.allocation.cluster_concurrent_rebalance": 2
  }
}

启发式分片分布平衡策略设置:

java 复制代码
#定义分配在该节点的分片数的因子 阈值=因子*(当前节点的分片数-集群的总分片数/节点数,即每个节点平均分片数)
#节点的分片数因子,默认0.45f
cluster.routing.allocation.balance.shard: 0.45f

#定义分配在该节点某个索引的分片数的因子,阈值=因子*(保存当前节点的某个索引的分片数-每个节点某个索引的平均分片数)
#节点索引数分片数因子,默认值0.55f
cluster.routing.allocation.balance.index: 0.55f

#以上计算的值,若超出此下面的 阀值,则启动自动平衡
cluster.routing.allocation.balance.threshold: 1.0f
java 复制代码
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.balance.shard": 0.45,
    "cluster.routing.allocation.balance.index": 0.55,
    "cluster.routing.allocation.balance.threshold": 1.0
  }
}

这些数据其实很少用到,使用默认的就行了。

物理磁盘感知平衡策略:

java 复制代码
# 是否启用磁盘感知平衡策略, true/false, 默认true=启用
cluster.routing.allocation.disk.threshold_enabled: true

# 磁盘空间限制, 低水位线, 默认值85%, 磁盘高于85%就不再分配新的分片数据
# 此值设置, 可以是固定值, 如10GB, 也可以是百分比
cluster.routing.allocation.disk.watermark.low: 85%

# 磁盘空间限制, 高水位线, 默认90%, 超过此值, 分片数据不再分配到此节点
# 此值设置, 可以是固定值, 如10GB, 也可以是百分比
cluster.routing.allocation.disk.watermark.high: 90%

# 是否容许单节点集群启用此配置, 默认true
cluster.routing.allocation.disk.watermark.enable_for_single_data_node: true

# 磁盘空间限制, 洪水水位线, 超过此值, 磁盘所在索引, 不再接受数据写入, 仅只读
# 此值设置, 可以是固定值, 如10GB, 也可以是百分比
cluster.routing.allocation.disk.watermark.flood_stage: 95%

# 数据超过空间限制后, 是否启用自动平衡机制, 允许所有分片自动移出, 默认true
cluster.routing.allocation.disk.include_relocations: true

# 磁盘空间检查间隔, 默认30s
cluster.info.update.interval: 30s
java 复制代码
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.threshold_enabled": true,
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.enable_for_single_data_node": true,
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%",
    "cluster.routing.allocation.disk.include_relocations": true,
    "cluster.info.update.interval": "30s"
  }
}
水位线 默认值 触发行为 业务影响
低水位线(low) 85% 1. 新分片(包括新建索引、副本分配、恢复的分片)不再分配到该节点2. 已存在的分片读写不受影响 几乎无感知,只是不再 "增重"
高水位线(high) 90% 1. 不接收新分片2. 已有的分片会被自动迁移到其他磁盘充足的节点 会有少量分片迁移 IO,但业务读写基本不受影响
洪水水位线(flood_stage) 95% 1. 节点上的所有索引会被强制设置为 read_only_allow_delete 只读模式2. 禁止写入、更新、删除,仅允许读和删除操作 业务写入直接报错,必须立刻扩容或清理磁盘

索引分片分布机架感知配置

java 复制代码
#设置自定义机架属性
#节点1
node.attr.rack_id: rack_01
#节点2
node.attr.rack_id: rack_02

#集群感知属性名称: rack_id
cluster.routing.allocation.awareness.attributes: rack_id
#机架感知范围, 此处: rack_01,rack_02
cluster.routing.allocation.awareness.force.rack_id.values: rack_01,rack_02
复制代码
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.awareness.attributes": "rack_id",
    "cluster.routing.allocation.awareness.force.rack_id.values": "rack_01,rack_02"
  }
}

说明:

  • node.attr.rack_id 是节点级配置,需要写在每个节点的 elasticsearch.yml 中,不能通过集群 DSL 修改。
  • 只有 cluster.routing.allocation.awareness.attributescluster.routing.allocation.awareness.force.rack_id.values 这两个配置支持通过 _cluster/settings 动态修改。

索引分片分布过滤

复制代码
# ES自定义属性
node.attr.attr01: xyz01

# 案例设置,数据分布不包含其中一个IP节点
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.exclude._ip": "192.168.86.102",
    "cluster.routing.allocation.exclude.attr01": "xyz01"
  }
}

这组配置的作用是:

  1. 给节点打上自定义标签 attr01: xyz01
  2. 通过 exclude 规则,让集群分片不分配到指定 IP 的节点 ,也不分配到带有 attr01=xyz01 标签的节点
  3. 常用于节点下线维护,临时排除节点,避免分片分配到目标节点上

上面的配置都是非必要不修改的配置,对于实际开发大家使用默认的数值就可以了。

相关推荐
CDYXY16 小时前
2026年4月成都卡布灯箱源头口碑深度调研与避坑指南
大数据·人工智能
奋斗的小乌龟21 小时前
动态创建Agent02
java
ZFSS21 小时前
Localization Translate API 集成与使用指南
java·服务器·数据库·人工智能·mysql·ai编程
摇滚侠21 小时前
Java 零基础全套教程,集合框架,笔记 153-163
java·开发语言·笔记
nannan123221 小时前
后端技术栈梳理
java
鹧鸪云光伏21 小时前
微电网容量规划软件:光储设备配置一站式解决方案
大数据·储能·光伏·储能设计方案
扫地的小何尚21 小时前
NVIDIA Vera Rubin 平台如何解决 Agentic AI 的 Scale-up 难题
大数据·人工智能·机器学习
kekekka1 天前
重塑品牌增长逻辑:专业媒体发稿服务如何让每一分预算产生长效复利?
大数据·搜索引擎·媒体
hj2862511 天前
Linux 磁盘管理 + 文件系统 + LVM 笔记整理
linux·运维