集群恢复网关与集群索引分布必要性了解
在 Elasticsearch(简称 ES)集群运维中,集群重启恢复、残余索引处理、索引分片分布是保障集群稳定性、数据完整性、读写性能的三大核心基础能力。多数集群故障、数据丢失、分片异常、读写卡顿问题,根源均来自这三个模块的认知不足与配置不当。
本文将聚焦Cluster Gateway 集群恢复网关、Dangling Index 残余索引挂载、Cluster Allocation 集群索引分布三大核心,通俗讲解其核心价值、工作原理、适用场景,并搭配完整实战操作,让读者彻底搞懂「为什么需要、是什么作用、怎么落地操作」。
Cluster Gateway 集群恢复网关实战操作
1.1 核心问题:为什么需要集群恢复网关?
ES 集群所有节点全部重启、机房断电、集群整体宕机后,会面临一个核心问题:集群重启后,如何找回原有集群状态、索引信息、分片分配规则?
如果没有网关机制,集群重启后会初始化全新空集群,所有历史索引、模板、分片配置、集群元数据全部丢失,直接造成业务数据不可用。
而 Cluster Gateway(集群恢复网关)是 ES 内置的集群元数据与持久化恢复模块,是集群整体重启后数据与状态恢复的唯一核心载体,所有生产集群必须依赖该机制实现故障自愈。
1.2 核心作用:网关到底做什么?
ES 默认使用Local Gateway 本地网关,核心职责只有两个,贯穿集群全生命周期:
持久化集群元数据:实时记录集群所有状态,包括索引列表、索引分片配置、副本数、映射模板、集群权限、分片分配记录等,将动态集群状态落地到节点本地磁盘持久化存储,而非仅内存缓存。
集群重启状态恢复:集群整体重启、故障恢复后,新选举的 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)。这是一个非常保守的值,旨在保证业务稳定性,但在急需恢复数据时会显得过慢。
调优建议
- 加快恢复:在业务低峰期或集群急需恢复健康状态时,可以显著调大该值(例如设置为
100mb、200mb甚至500mb),以充分利用内网的高带宽资源。 - 保护业务:如果恢复过程导致业务查询延迟增加,应适当调小该值,为正常业务留出网络资源。
恢复并发操作数:
indices.recovery.max_concurrent_operations,该参数控制在分片恢复过程中,并行发送的操作请求数量(主要指 Lucene 段文件的传输和操作并发度)。
简单来说,它决定了恢复线程在搬运数据时的“并发力度”。数值越大,同一时间内处理的恢复任务片段越多。(起使也是可以理解成就是他的单位指的就是分片)
默认值2。这也是一个相对保守的默认设置,旨在避免过高的 I/O 压力。
调优建议
- 加快恢复:如果节点的 CPU 和磁盘 I/O(特别是 SSD)性能较强,可以将此值调大(例如
4或8),通过提高并发度来加速恢复流程。 - 资源权衡:调大此参数会增加 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 决定「每一个索引的每一个分片,放在哪个节点」,核心价值三点:
保障高可用:强制主分片与副本分片异地部署,避免单节点故障导致数据丢失;
实现负载均衡:均匀分散所有索引分片,避免热点节点,最大化利用集群CPU、磁盘、IO资源;
控制分片调度逻辑:支持自定义机架、机房、节点属性调度,支持分片冻结、强制迁移、禁止分配、恢复分配等精细化管控。
集群索引分片分布核心配置:
# ------------------------------ 分片分布设置 ------------------------------ # 允许索引分片自动分布,默认值 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中直接设置:
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集群索引分片分布平衡配置
#----------------集群分片自动平衡设置----------------# #以下设置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以上的配置也都是可以动态进行设置:
PUT _cluster/settings { "persistent": { "cluster.routing.rebalance.enable": "all", "cluster.routing.allocation.allow_rebalance": "indices_all_active", "cluster.routing.allocation.cluster_concurrent_rebalance": 2 } }启发式分片分布平衡策略设置:
#定义分配在该节点的分片数的因子 阈值=因子*(当前节点的分片数-集群的总分片数/节点数,即每个节点平均分片数) #节点的分片数因子,默认0.45f cluster.routing.allocation.balance.shard: 0.45f #定义分配在该节点某个索引的分片数的因子,阈值=因子*(保存当前节点的某个索引的分片数-每个节点某个索引的平均分片数) #节点索引数分片数因子,默认值0.55f cluster.routing.allocation.balance.index: 0.55f #以上计算的值,若超出此下面的 阀值,则启动自动平衡 cluster.routing.allocation.balance.threshold: 1.0fPUT _cluster/settings { "persistent": { "cluster.routing.allocation.balance.shard": 0.45, "cluster.routing.allocation.balance.index": 0.55, "cluster.routing.allocation.balance.threshold": 1.0 } }这些数据其实很少用到,使用默认的就行了。
物理磁盘感知平衡策略:
# 是否启用磁盘感知平衡策略, 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: 30sPUT _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. 禁止写入、更新、删除,仅允许读和删除操作 | 业务写入直接报错,必须立刻扩容或清理磁盘 |
索引分片分布机架感知配置
#设置自定义机架属性 #节点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_02PUT _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.attributes和cluster.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" } }这组配置的作用是:
- 给节点打上自定义标签
attr01: xyz01 - 通过
exclude规则,让集群分片不分配到指定 IP 的节点,也不分配到带有attr01=xyz01标签的节点 - 常用于节点下线维护,临时排除节点,避免分片分配到目标节点上
上面的配置都是非必要不修改的配置,对于实际开发大家使用默认的数值就可以了。