上一篇【第46篇】Elasticsearch分布式文档更新原理——局部更新与并发处理下一篇【第48篇】Elasticsearch分析器体系摘要Elasticsearch的集群形成是分布式架构中最基础也最容易被忽视的一环。一个节点的启动并不会自动组成集群——它需要经过节点发现、引导配置和Master选举三个精确编排的阶段。本文从discovery.seed_hosts种子地址配置开始详解单播发现的两阶段探测过程种子探测对等交换进而分析cluster.initial_master_nodes在首次启动时的特殊作用。随后深入Master选举的核心投票配置Voting Configuration、Quorum法定人数和类Raft共识算法并重点解析Elasticsearch如何通过投票机制替代了旧版的minimum_master_nodes来防止脑裂Split-Brain问题。最后介绍集群状态同步、节点故障的自动恢复流程以及green/yellow/red三种健康状态的含义并通过实战案例模拟节点故障与自动恢复全过程。关键词Elasticsearch集群形成、Master选举、脑裂预防、节点发现、集群状态。一、集群形成的三个阶段Elasticsearch集群的诞生不是瞬间完成的而是经历了三个精确编排的阶段节点启动 → 集群形成三阶段 ┌─────────────────────────────────────────────────────┐ │ 阶段一节点发现Discovery │ │ - 通过种子地址列表找到集群中的其他节点 │ │ - 两阶段探测种子探测 → 对等交换 │ │ - 重复探测直到发现Master或获取足够候选节点 │ └────────────────────────┬────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 阶段二集群引导Bootstrap │ │ - 首次启动时确定参与首次选举的候选Master列表 │ │ - 已有集群直接加入Master身份不存在时触发重选 │ └────────────────────────┬────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 阶段三Master选举Election │ │ - 基于Quorum投票的共识算法 │ │ - 获得多数票的节点成为Master │ │ - 落选节点自动成为数据节点或按角色配置运行 │ └─────────────────────────────────────────────────────┘这三个阶段环环相扣没有节点发现就无法知道集群中有哪些节点没有引导配置首次启动时就不知道该选谁当Master没有选举机制就没有统一的集群管理者。理解这个过程是排查集群启动问题的关键基础。二、节点发现机制2.1 种子地址配置节点要加入集群首先需要知道去哪里找其他节点。Elasticsearch通过discovery.seed_hosts配置种子地址列表# elasticsearch.yml 配置示例discovery.seed_hosts:-192.168.1.10-192.168.1.11-192.168.1.12:9300-es-node-1.internal-es-node-2.internal:9301种子地址支持的格式格式示例端口说明IP:端口192.168.1.10:93009300明确指定传输端口IP192.168.1.10默认端口使用transport.profiles.default.port主机名es-node-1.internal默认端口DNS解析后使用默认端口IPv6[::1]:93009300IPv6必须用方括号括起注意这里使用的是9300端口Transport传输协议而非9200端口HTTP REST API。节点之间的所有内部通信都通过Transport协议进行。2.2 两阶段探测过程节点发现不是简单地连接种子地址就结束了而是一个迭代式的探测过程第一阶段种子地址探测新启动的Node5种子列表: [Node1, Node2] Node5 Node1 Node2 │ │ │ │ ① 连接Node1:9300 │ │ │─────────────────────────│ │ │ │ │ │ ② 节点信息交换 │ │ │─────────────────────────│ │ │ │ │ │ Node5获知: │ │ │ Node1是候选Master │ │ │ Node1知道的节点: │ │ │ [Node1, Node3, Node4] │ │ │ │ │ │ ③ 连接Node2:9300 │ │ │─────────────────────────────────────────────────────│ │ │ │ │ ④ 节点信息交换 │ │─────────────────────────────────────────────────────│ │ │ │ │ Node5获知: │ │ Node2知道的节点: │ │ [Node2, Node3, Node4] │第二阶段对等交换Node5发现新节点后继续探测并对等交换 Node5 Node3 Node4 │ │ │ │ ⑤ 连接Node3:9300 │ │ │─────────────────────────│ │ │ ⑥ 交换彼此已知的节点列表 │ │ │─────────────────────────│ │ │ │ │ │ Node5: 我知道 [N1,N2,N3] │ │ Node3: 我知道 [N1,N2,N3,N4] │ │ │ │ │ ⑦ 连接Node4:9300 │ │ │─────────────────────────────────────────────────────│ │ ⑧ 最终Node5已知: │ │ [Node1, Node2, Node3, Node4] ✓ │这个过程持续进行直到发现已选定的Master节点 → 直接加入集群发现足够的候选Master节点 → 触发选举超时 → 在discovery.find_peers_interval默认1秒后重试2.3 单播发现 vs 广播发现Elasticsearch使用**单播发现Unicast Discovery**而非传统的广播发现对比维度单播Elasticsearch采用广播传统方案工作方式指定种子节点列表逐个连接子网内广播自动发现跨子网支持只要种子地址可达不支持广播仅限同一子网云环境完美支持通常不可用安全性更安全明确的白名单任何节点可加入网络开销精确探测广播风暴风险历史背景Elasticsearch 5.0之前使用过multicast多播/广播发现机制节点通过向239.0.0.1:54328发送UDP广播来自动发现同网段内的其他节点。但由于安全隐患任何节点都能加入集群和云环境不兼容的问题multicast在5.0版本中被正式废弃全面转向单播发现。2.4 发现相关配置参数# 节点发现相关配置discovery.seed_hosts:-es-node-1.internal# 种子地址列表discovery.seed_providers:file# 7.x新增从文件读取种子地址# 高级参数一般无需修改discovery.find_peers_interval:1s# 探测间隔discovery.request_peers_timeout:30s# 每轮探测超时discovery.seed_providers是7.x引入的新特性可以从外部文件动态加载种子地址特别适合Docker/Kubernetes等容器化部署场景# 从文件读取种子地址适合动态环境discovery.seed_providers:file三、集群引导配置3.1 首次启动的特殊性当启动一个全新的Elasticsearch集群没有任何数据时需要解决先有Master还是先有集群的问题。Elasticsearch通过cluster.initial_master_nodes配置来解决这个问题# 首次启动全新集群时配置cluster.initial_master_nodes:-es-node-1-es-node-2-es-node-3这些配置的节点名称必须与各节点的node.name值完全一致# es-node-1 上的配置node.name:es-node-1cluster.initial_master_nodes:-es-node-1-es-node-2-es-node-3# es-node-2 上的配置node.name:es-node-2cluster.initial_master_nodes:-es-node-1-es-node-2-es-node-33.2 引导流程首次集群启动流程 ① 所有节点启动读取 cluster.initial_master_nodes 配置 ② 各节点通过seed_hosts完成节点发现互相确认身份 ③ 候选Master节点列表确定来自initial_master_nodes ④ 发起首次Master选举 ⑤ 选举产生Master后initial_master_nodes配置不再生效 ⑥ 后续节点加入直接使用已建立的集群状态 重要 - cluster.initial_master_nodes 仅在首次启动时使用 - 已加入集群的节点不应再设置此配置 - 集群稳定运行后可以移除此配置3.3 生产环境注意事项# ✓ 正确三节点集群的完整发现配置# Elasticsearch 7.x 推荐配置discovery.seed_hosts:-es-node-1.internal-es-node-2.internal-es-node-3.internalcluster.initial_master_nodes:-es-node-1-es-node-2-es-node-3关键原则cluster.initial_master_nodes应包含所有候选Master节点discovery.seed_hosts应包含所有候选Master节点的地址首次启动完成后可注释掉cluster.initial_master_nodes配置常见错误忘记在首次启动后移除cluster.initial_master_nodes当集群重启时如果某些节点不在列表中会导致集群无法正常选举。建议首次启动成功并确认集群状态green后从配置中移除此项。3.4 Docker环境下的集群引导在Docker环境中节点IP可能动态变化这时可以使用Docker内部DNS或特殊配置# Docker Compose环境下network.host:0.0.0.0discovery.type:single-node# 单节点模式开发/测试用# Docker Swarm / K8s 多节点discovery.seed_hosts:-es-node-1-es-node-2-es-node-3cluster.initial_master_nodes:-es-node-1-es-node-2-es-node-3四、Master选举机制4.1 投票配置Voting ConfigurationElasticsearch 7.x使用了基于**投票配置Voting Configuration**的选举机制这是对旧版minimum_master_nodes配置的重大改进。投票配置定义了当前集群中哪些节点有投票权以及需要多少票才能选出MasterVoting Configuration {voter-1, voter-2, voter-3, ..., voter-N} 选举条件候选人获得的票数 N/2过半数即Quorum 示例 3个投票节点 → 需要 2 票 → N/2 1 2 5个投票节点 → 需要 3 票 → N/2 1 3 7个投票节点 → 需要 4 票 → N/2 1 44.2 Master选举过程Elasticsearch的Master选举算法基于Raft一致性算法的核心思想做了适当的工程简化Master选举流程类Raft共识算法 ┌─────────────────────────────────────────────┐ │ 触发选举条件 │ │ - 集群首次启动 │ │ - 当前Master宕机被检测到(List down) │ │ - 当前Master与多数节点失联(Network Partition) │ └────────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ ① 候选节点增加自己的term任期号 │ │ ② 向其他投票节点发送选举请求(VoteRequest) │ │ ③ 接收节点判断 │ │ - 自己是否已经投票给了更高term的候选人 │ │ - 候选人的日志是否至少和自己一样新 │ │ (日志比较term更大优先 → index更大次之) │ │ ④ 如果条件满足投出赞成票 │ └────────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ ⑤ 候选人收到多数票Quorum后成为Master │ │ ⑥ 新Master向所有节点广播集群状态 │ │ ⑦ 落选节点收到新集群状态 → 确认新Master │ │ ⑧ 集群进入稳定运行状态 │ └─────────────────────────────────────────────┘选举的关键细节任期号Term每次选举递增用于区分不同轮次的选举。如果一个节点收到了更高term的选举请求即使之前已经投了票也可以改投给新term的候选人。日志新旧比较优先比较term号谁存储的集群状态更新term相同时比较状态版本号谁的cluster state version更大。这保证了当选的Master一定拥有最新的集群状态。超时机制如果一个候选人在election.timeout默认500ms到10s之间的随机值内未获得足够票数则放弃本轮选举等待随机时间后发起新一轮。4.3 Master节点的职责Master节点一旦当选承担以下核心职责职责说明集群状态管理维护并广播cluster state到所有节点索引管理创建/删除索引、分配分片节点管理跟踪节点加入/离开决定分片分配分片重分配节点故障后触发分片恢复和重新平衡元数据变更处理Mapping变更、模板创建等重要理解Master节点不参与文档的读写路径。当一个客户端发起搜索请求时请求会由协调节点可以是任意节点直接路由到相关分片所在的节点Master节点完全不参与数据读写。这意味着Master节点的负载相对较轻但也意味着Master宕机不会影响正在进行中的读写操作只要已有分片还在。数据节点与Master节点的分离在大型集群中建议使用专用Master节点node.master: true, node.data: false避免Master节点因数据处理压力影响集群管理能力。# 专用Master节点配置推荐3个组成高可用的Master选举组node.master:truenode.data:falsenode.ingest:falsenode.ml:false# 专用数据节点配置node.master:falsenode.data:truenode.ingest:true4.4 节点角色一览节点角色配置职责资源需求Master-eligiblenode.master: true参与Master选举、存储集群状态中等CPU、低内存Datanode.data: true存储分片数据、执行CRUD操作高磁盘I/O、高内存Coordinating默认所有节点转发请求、合并结果中等CPU、中等内存Ingestnode.ingest: true执行Ingest Pipeline预处理中等CPUMachine Learningnode.ml: true运行机器学习作业高CPU、高内存五、防止脑裂Split-Brain5.1 什么是脑裂脑裂是指集群因为网络分区被分裂为两个或多个子集群每个子集群都选举了自己的Master导致数据被两个Master同时修改造成数据不一致。脑裂场景 原始集群: [Master(Node1), Node2, Node3, Node4, Node5] │ ┌────────┴────────┐ 网络中断 网络中断 │ │ ┌───────────┴───┐ ┌───────┴───────────┐ │ 集群A (2节点) │ │ 集群B (3节点) │ │ [Node1, Node2] │ │ [Node3, Node4, │ │ Node1重新当选 │ │ Node5] │ │ 认为Node3-5挂了 │ │ Node3当选Master │ └───────────────┘ │ 认为Node1-2挂了 │ └───────────────────┘ 结果两个Master同时接受写入 → 数据冲突5.2 投票机制的防脑裂原理Elasticsearch 7.x的投票配置自动保证了一个任期只能有一个Master假设5节点集群网络分区为 [Node1,Node2] 和 [Node3,Node4,Node5] 集群A (2节点): - 候选: Node1 - 可获得的票数: 2 (只有Node1和Node2) - 需要票数: 3 (5/2 1 3) - 结果: 无法获得多数票无法当选 ❌ - 集群A拒绝接受写入yellow状态或red状态 集群B (3节点): - 候选: Node3 - 可获得的票数: 3 (Node3, Node4, Node5) - 需要票数: 3 (5/2 1 3) - 结果: 达到Quorum当选新Master ✓ - 集群B继续正常工作 结论只有多数派能选出Master少数派自动拒绝写入避免数据分裂。5.3 minimum_master_nodes vs Voting Configuration对比维度旧版minimum_master_nodes新版Voting Configuration配置方式手动配置N/21自动加入所有Master候选节点动态变更需要手动更新自动追踪节点变化出错风险配置错误导致脑裂自动计算零配置适用版本Elasticsearch 6.x及更早Elasticsearch 7.0典型错误忘记更新导致新节点无法加入不存在教训在旧版Elasticsearch中minimum_master_nodes是最容易出错的配置之一。很多生产事故都是因为运维人员添加新节点后忘记更新这个值导致两个子集群都能选出Master。7.0之后的自动投票机制彻底消除了这个隐患。5.4 手动排除节点投票voting_config_exclusions在某些运维场景下如节点维护你可能需要手动将某个节点从投票配置中排除// 将节点从投票配置中排除节点维护前使用POST/_cluster/voting_config_exclusions/es-node-3// 按节点属性排除适合批量操作POST/_cluster/voting_config_exclusions/node_name:es-node-3,node_name:es-node-4// 等待排除生效并确认安全后关闭节点// 维护完成后添加排除节点回集群DELETE/_cluster/voting_config_exclusions典型使用场景当需要滚动升级或维护包含Master候选节点的服务器时先排除投票再下线避免影响选举Quorum。六、集群状态同步与故障恢复6.1 集群状态Cluster State集群状态是Elasticsearch最重要的元数据结构Master节点负责维护它并向所有节点广播。集群状态包含所有节点的信息名称、IP、角色、状态所有索引的元数据Mapping、Settings、Alias分片的路由表哪个分片在哪个节点上索引模板、Ingest Pipeline等全局配置集群状态同步机制 Master ──(广播Cluster State)── Node1 │ (接收应用) ├───────────────────────── Node2 │ (接收应用) ├───────────────────────── Node3 │ (接收应用) └───────────────────────── ... 同步特点 - 增量更新只传输变化的元数据 - 两阶段提交先发送状态 → 各节点确认 → 提交 - 版本号标识每次变更version16.2 节点故障与自动恢复节点故障恢复流程 Master检测到Node3宕机 │ ▼ ┌─────────────────────┐ │ ① 标记Node3为不可用 │ │ ② 等待超时确认 │ │ (默认3次ping超时) │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ ③ 提升副本分片为主分片 │ │ Node3的Shard0主分片 → │ │ 提升Node1上的Shard0副本│ │ 为新主分片 │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ ④ 重新分配副本分片 │ │ 在其他健康节点上创建 │ │ 新的副本分片 │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ ⑤ 数据均衡可选 │ │ 检查集群是否需要 │ │ 重新平衡分片分布 │ └─────────────────────┘// 查看集群恢复状态GET/_cat/recovery?vactive_onlytrue// 查看分片分配情况GET/_cat/shards?v// 查看未分配的分片及原因GET/_cat/shards?vhindex,shard,prirep,state,unassigned.reason6.3 集群健康状态Green/Yellow/RedGET/_cluster/health// 返回{cluster_name:my-es-cluster,status:green,number_of_nodes:5,active_primary_shards:20,active_shards:40,unassigned_shards:0}状态含义主分片副本分片影响Green一切正常全部分配全部分配无影响Yellow副本未分配全部分配部分未分配数据安全读写可用但有丢失风险Red主分片未分配部分未分配部分未分配部分数据不可读写需立即处理健康状态诊断流程Green → 集群正常运行无需操作 Yellow → 检查未分配副本分片的原因 - 节点数量不足单节点集群天然Yellow - 磁盘空间不足达到水位线 - 分片分配被手动禁用 Red → 紧急处理 - 检查宕机节点能否恢复 - 无法恢复时使用 reroute API 重新分配 - 极端情况下分配空的Primary分片数据丢失// 诊断Yellow状态查看未分配原因GET/_cluster/allocation/explain{index:shop,shard:0,primary:false}// 手动重新路由高级操作谨慎使用POST/_cluster/reroute{commands:[{allocate_stale_primary:{index:shop,shard:0,node:es-node-2,accept_data_loss:true}}]}七、实战案例模拟集群节点故障与自动恢复7.1 环境准备假设我们有一个3节点的Elasticsearch集群并创建了一个测试索引// 创建测试索引1个主分片 1个副本PUT/fault_test{settings:{number_of_shards:1,number_of_replicas:1}}// 写入测试数据POST/fault_test/_bulk{index:{_id:1}}{title:Elasticsearch集群管理实战,content:本文介绍ES集群的故障恢复}{index:{_id:2}}{title:分布式系统设计原则,content:高可用是分布式系统的核心目标}{index:{_id:3}}{title:Elasticsearch性能调优,content:索引和搜索性能的优化方法}7.2 查看初始状态// 查看集群健康状态GET/_cluster/health?pretty// 查看分片分布GET/_cat/shards/fault_test?v// 预期输出3节点1分片1副本// index shard prirep state docs store ip node// fault_test 0 p STARTED 3 10kb 192.168.1.10 es-node-1// fault_test 0 r STARTED 3 10kb 192.168.1.11 es-node-27.3 模拟节点故障# 模拟Node2宕机Kill Elasticsearch进程# Linux:kill-9$(pgrep-fnode.namees-node-2)# 或直接停止Elasticsearch服务systemctl stop elasticsearch# 如果是Node27.4 观察集群自动恢复// 等待几秒后查看集群状态会短暂Yellow后恢复GreenGET/_cluster/health?pretty// {// status: green,// relocating_shards: 0,// initializing_shards: 0,// unassigned_shards: 0// }// 查看分片迁移结果GET/_cat/shards/fault_test?v// index shard prirep state docs store ip node// fault_test 0 p STARTED 3 10kb 192.168.1.10 es-node-1// fault_test 0 r STARTED 3 10kb 192.168.1.12 es-node-3 ← 副本已迁移到Node3// 查看集群恢复过程的详细信息GET/_cat/recovery/fault_test?v// 可以看到副本分片从Node1复制到Node3的完整过程// source_node → target_node, bytes_start → bytes_end, time7.5 模拟Master节点故障# 假设Node1是当前Master停止Node1kill-9$(pgrep-fnode.namees-node-1)// 查看集群状态变化GET/_cluster/health?pretty// 集群会经历短暂的Yellow因为Node1上的主分片需要转移// 然后Node2或Node3被选为新Master// 副本被提升为主分片新副本被创建// 最终恢复到Green状态// 查看当前MasterGET/_cat/master?v// 查看新的分片分布GET/_cat/shards/fault_test?v7.6 恢复故障节点# 重启Node1systemctl start elasticsearch// 等待Node1重新加入集群GET/_cat/nodes?v// Node1会自动加入集群并接收新分配的分片// 查看集群最终状态GET/_cluster/health?pretty// status应该恢复为green7.7 故障恢复过程中的关键API// 实时监控集群状态变化每5秒GET/_cluster/health?wait_for_statusgreentimeout60s// 该请求会阻塞等待直到集群变为green或超时// 查看节点详细信息GET/_nodes/stats?filter_pathnodes.*.name,nodes.*.os.*,nodes.*.process.*// 查看分片分配的解释GET/_cluster/allocation/explain?pretty// 查看集群.pending_tasksMaster队列积压GET/_cluster/pending_tasks八、总结与最佳实践核心要点回顾集群形成经历发现→引导→选举三阶段节点通过种子地址发现其他节点首次启动时通过cluster.initial_master_nodes引导之后通过Quorum投票选举Master。投票配置是防脑裂的核心机制只有获得超过半数投票节点支持的候选者才能当选Master这保证了在任何网络分区场景下最多只有一个Master存在。Master节点负责集群状态中枢维护集群全局元数据并增量广播到所有节点任何索引创建、分片分配、节点变更都由Master协调。Green/Yellow/Red状态是集群健康的风向标Yellow表示副本异常但不影响读写Red表示主分片异常需要紧急处理。最佳实践清单实践建议详细说明Master候选节点为奇数3/5/7个保证Quorum计算的确定性分离Master与Data角色大集群使用专用Master节点node.master:true, node.data:false种子地址覆盖所有候选Masterdiscovery.seed_hosts至少包含所有Master候选节点首次启动后移除initial_master_nodes正常运行后注释掉此配置避免加节点时的混淆监控集群健康状态设置对Yellow和Red状态的告警Yellow超过5分钟即需关注避免单节点集群单节点天然Yellow且无容错能力生产至少3节点合理的ping超时配置避免网络抖动导致的误判Master下线维护前排除投票使用voting_config_exclusions排除维护节点的投票权分片恢复限速节点恢复后大量分片迁移可能压垮集群合理设置recovery限速定期演练故障恢复在测试环境模拟节点故障验证自动恢复流程是否符合预期集群规模推荐节点数量Master候选节点副本数容忍故障节点3311531273~51~22~3103~5专用1~2视配置而定上一篇【第46篇】Elasticsearch分布式文档更新原理——局部更新与并发处理下一篇【第48篇】Elasticsearch分析器体系