Elasticsearch 是如何进行选主节点(Master Election)的?
Elasticsearch 的选主(Master Election)机制在 7.x 版本前后发生了重大的变化。
简单来说:
- 7.0 及以后:使用基于 Raft 的共识算法(Raft-inspired),更加严谨、安全,自动处理脑裂问题。
- 7.0 以前:使用 Zen Discovery 模块,基于类似 Bully 算法的定制机制,需要手动配置
minimum_master_nodes来防止脑裂。
以下是详细的流程解析,重点介绍目前主流的 7.x+ 版本机制。
一、 Elasticsearch 7.x 及更高版本(现代机制)
从 ES 7.0 开始,引入了新的集群协调子系统(Cluster Coordination),其选主算法深受 Raft 共识算法 的启发。
1. 核心概念
- Master-eligible Node(候选主节点):配置了
node.master: true的节点。只有这些节点有资格参与竞选和投票。 - Voting Configuration(投票配置):这是 ES 7.x 动态维护的一组节点列表,只有在这个列表里的节点才有投票权。ES 会自动维护这个列表以确保集群的高可用性。
- Quorum(法定人数/多数派):选主必须获得 Voting Configuration 中 超过半数 节点的投票。
- Term(任期):一个递增的整数计数器。每次选举都会增加 Term,用于区分新旧 Master,防止僵尸节点(旧 Master)干扰集群。
2. 选主流程步骤
第一步:触发选举
当集群启动,或者当前的 Master 节点挂掉(其他节点在 cluster.fault_detection.leader_check 失败),或者当前 Master 主动辞职时,选举开始。
第二步:候选人(Candidate)发起竞选
某个 Master-eligible 节点发现没有 Master,它会:
- 将自己的 Term 加 1。
- 将自己转换为 Candidate 状态。
- 给自己投一票。
- 向其他 Master-eligible 节点发送
RequestVote请求。
第三步:节点投票(Voting)
收到投票请求的节点会根据以下规则决定是否投票给该 Candidate:
- Term 检查:Candidate 的 Term 必须大于等于当前节点的 Term。
- 状态新鲜度:Candidate 拥有的 Cluster State(集群状态) 版本必须足够新(至少不落后于投票节点)。这保证了新 Master 拥有最新的元数据。
- 未重复投票:在当前 Term 内,投票节点还没有投给其他人。
第四步:当选(Winning)
如果 Candidate 收到了来自 Voting Configuration 中过半数 节点的投票,它就当选为 Master。
第五步:发布集群状态
新 Master 会发布一个新的 Cluster State,并向全集群广播。一旦该状态被多数派确认(Committed),选举正式完成,集群恢复服务。
3. 如何防止脑裂(Split Brain)?
在 7.x 中,你不再需要配置 minimum_master_nodes。ES 通过 Voting Configuration 自动管理多数派。如果集群分裂成两部分,只有包含“多数派”的那一部分能选出 Master,另一部分因为票数不足无法选主,从而自动进入阻塞状态,避免数据不一致。
注意:在 7.x 集群第一次启动时,必须在配置中设置
cluster.initial_master_nodes,明确指定哪些节点参与首次选举(Bootstrapping)。启动后该配置即可忽略。
二、 Elasticsearch 7.0 以前版本(Zen Discovery)
如果你还在维护 ES 5.x 或 6.x,机制完全不同。使用的是 Zen Discovery。
1. 核心逻辑
它采用了一种类似 Bully 算法 的变体:
- 节点通过 Ping 发现彼此。
- 节点根据 Node ID 进行排序。
- 通常 ID 最小(或根据具体规则排序最优)的节点会被选为 Master。
2. 致命弱点与脑裂
旧版算法最大的问题是无法自动准确判断“多数派”。
- 场景:假设有 3 个节点(A, B, C),网络断开,A 单独一组,B 和 C 一组。
- 结果:A 觉得自己是 Master,B 和 C 选出 B 做 Master。此时集群有两个 Master,即“脑裂”。两个 Master 同时写入数据,导致数据损坏或丢失。
3. 解决方案
必须在 elasticsearch.yml 中手动硬编码配置:
discovery.zen.minimum_master_nodes: N/2 + 1
例如 3 个主节点,必须配置为 2。如果配置错误,极易发生数据事故。
三、 总结对比
| 特性 | 7.x 及以后 (Cluster Coordination) | 7.0 以前 (Zen Discovery) |
|---|---|---|
| 算法基础 | Raft-inspired (强一致性共识) | Bully 变体 (基于排序) |
| 脑裂保护 | 自动 (通过 Voting Configuration) | 手动 (需配置 minimum_master_nodes) |
| 选主速度 | 非常快 (通常几秒内) | 较慢 (Ping 周期可能较长) |
| 首次启动 | 需配置 cluster.initial_master_nodes |
自动发现 |
| 安全性 | 极高 (检查 Cluster State 新鲜度) | 一般 (可能选出状态落后的节点) |
结论
ES 的选主是为了维护 Cluster State(集群状态) 的唯一性和一致性。
- 现代 ES 通过 Raft 机制,要求多数派同意且数据最新的节点才能当选,从算法层面根除了脑裂问题。
- 旧版 ES 依赖人为配置的数学公式来规避风险。