文章目录
-
- [一、共识算法的演进:Zen vs. Coordination](#一、共识算法的演进:Zen vs. Coordination)
-
- [1. Zen Discovery (ES < 7.0)](#1. Zen Discovery (ES < 7.0))
- [2. Cluster Coordination (ES 7.0+)](#2. Cluster Coordination (ES 7.0+))
- [二、Master 选举流程 (Master Election)](#二、Master 选举流程 (Master Election))
-
- [1. 选举时机](#1. 选举时机)
- [2. 7.x+ 选主逻辑图解](#2. 7.x+ 选主逻辑图解)
- 三、元数据管理 (Meta Data Management)
- [四、脑裂问题 (Split Brain) 及其解决方案](#四、脑裂问题 (Split Brain) 及其解决方案)
-
- [1. 经典场景](#1. 经典场景)
- [2. 旧版解决方案 (discovery.zen)](#2. 旧版解决方案 (discovery.zen))
- [3. 新版解决方案 (Cluster Coordination)](#3. 新版解决方案 (Cluster Coordination))
- 总结
Elasticsearch(简称 ES)之所以能处理 PB 级数据并提供毫秒级搜索体验,核心在于其强大的分布式架构 。在分布式系统中,最棘手的问题莫过于"共识"(Consensus):即如何让集群中的几十上百个节点对系统的当前状态(Cluster State)达成一致。
本文将带您深入 ES 的底层,解析其从早期的 Zen Discovery 到现代基于 Raft 变种的 Cluster Coordination 的演进之路。
在深入细节之前,让我们通过一张思维导图总览 ES 分布式架构的核心模块:
ES 分布式架构
一致性与共识
Legacy
基于 Bully 算法
最小主节点数配置
7.x+
基于 Raft 变种
TLA+ 形式化验证
动态投票配置
Master 选举
选举触发时机
选主流程
元数据管理
Cluster State
2PC
脑裂问题
成因: 网络分区
旧版方案: minimum_master_nodes
新版方案: Voting Quorum
一、共识算法的演进:Zen vs. Coordination
Elasticsearch 的版本分水岭在于 7.0。在此之前和之后,其集群协调层的实现逻辑截然不同。
1. Zen Discovery (ES < 7.0)
在早期版本中,ES 使用自研的 Zen Discovery 模块。
- 核心逻辑 :基于改进版的 Bully 算法。
- 特点 :
- 节点通过 Ping 发现彼此。
- 通常选择 Node ID 最小且拥有最新集群状态的节点作为 Master。
- 缺点:虽然简单,但在复杂的网络分区、节点快速重启等边缘场景下,容易出现"反复选主"或"数据不一致"的情况。它属于"Best Effort"(尽力而为)的一致性模型。
2. Cluster Coordination (ES 7.0+)
从 7.0 开始,ES 引入了全新的 Cluster Coordination 子系统。
- 核心逻辑 :基于 Raft 共识算法 的变种。
- 改进点 :
- 形式化验证:ES 团队使用 TLA+ 模型对算法进行了数学验证,保证了正确性。
- 安全性:严格保证数据一致性,解决了旧版本中存在的幽灵节点和数据回滚风险。
- 动态性:不同于标准 Raft 的静态成员列表,ES 允许集群动态伸缩(Dynamic Membership),无需重启集群即可更改投票节点。
| 特性 | Zen Discovery (旧版) | Cluster Coordination (新版) |
|---|---|---|
| 算法基础 | Bully 算法变种 | Raft 算法变种 |
| 一致性强度 | 弱 (Best Effort) | 强 (Safety Guaranteed) |
| 脑裂防护 | 手动配置 minimum_master_nodes |
自动管理 Voting Configuration |
| 配置复杂度 | 高,扩容需手动计算参数 | 低,自动引导 |
二、Master 选举流程 (Master Election)
在 ES 集群中,Master 节点拥有至高无上的权力:它负责维护全局的 Cluster State(包含索引元数据、分片路由表等)。只有 Master 能修改这些状态。
1. 选举时机
当以下情况发生时,会触发选主:
- 集群启动时。
- 当前的 Master 节点挂掉或网络不可达。
- 当前 Master 主动辞职(Step down)。
2. 7.x+ 选主逻辑图解
新版选主流程引入了 Pre-voting (预投票)和 Voting 阶段,确保只有拥有最新数据的节点才能成为 Master。
发现现有 Master
未发现 Master
版本落后
版本最新
是 ( > N/2)
否
节点启动/Master丢失
Ping 其他节点
加入现有集群
发起 Pre-voting
对比 Cluster State 版本
等待其他节点发起选举
成为 Candidate
向 Voting 节点请求投票
获得过半数票?
当选 Master
随机超时后重试
发布新的 Cluster State
广播我是 Master
三、元数据管理 (Meta Data Management)
Master 当选后,最重要的任务就是管理元数据(Cluster State)。这包括:
- Settings: 集群层面的配置。
- Mappings: 索引的字段定义。
- Routing Table: 分片在哪些节点上。
更新流程:两阶段提交
为了保证所有节点对元数据认知一致,ES 采用类似 2PC (Two-Phase Commit) 的机制来发布状态。
Data Node 2 Data Node 1 Master Node Data Node 2 Data Node 1 Master Node 状态变更 (如: 新建索引) Phase 1: Publish Phase 2: Commit / Apply 收到过半数 Ack? ->> YES PublishRequest (ClusterState Diff) PublishRequest (ClusterState Diff) Ack (我已收到并暂存) Ack (我已收到并暂存) Apply State Locally CommitRequest (应用状态) CommitRequest (应用状态) Apply State Apply State
关键点 :ES 为了性能,传输的通常是 Diff(增量差异),而不是全量的 Cluster State。但在新节点加入时,会发送全量数据。
四、脑裂问题 (Split Brain) 及其解决方案
脑裂是指由于网络分区(Network Partition),一个集群被割裂成两个或多个部分,每一部分都选出了自己的 Master,导致数据写入不一致,甚至数据覆盖。
1. 经典场景
假设有 5 个节点(A, B, C, D, E),A 是 Master。网络故障导致 A, B 和 C, D, E 无法通信。
- A, B 认为 C, D, E 挂了,A 继续当 Master。
- C, D, E 认为 A, B 挂了,它们选出 C 当新 Master。
- 结果:两个 Master 同时接受写入,数据彻底混乱。
2. 旧版解决方案 (discovery.zen)
依靠"过半机制"硬性配置。
公式 :minimum_master_nodes = (master_eligible_nodes / 2) + 1
配置示例 (elasticsearch.yml):
yaml
# 假设有 3 个主节点资格的节点
discovery.zen.minimum_master_nodes: 2
- 原理:在上述 5 节点分裂场景中,A, B 只有 2 票,小于 (5/2)+1=3,因此 A 自动降级,无法成为 Master。C, D, E 有 3 票,可以工作。
- 痛点:每次集群扩缩容,管理员必须记得修改这个配置,否则极易出事故。
3. 新版解决方案 (Cluster Coordination)
7.x 之后,移除了 minimum_master_nodes 配置。ES 内部自行维护一个 Voting Configuration(投票配置表)。
-
初始引导 :
集群首次启动时,需显式指定初始的主节点列表:
yaml# 7.x+ 首次启动配置 cluster.initial_master_nodes: ["node-1", "node-2", "node-3"] -
动态维护 :
当节点加入或离开集群时,Master 会自动更新 Voting Configuration。
- 如果节点 A 宕机,Master 可能会将 A 从投票列表中移除(如果配置了自动缩容策略)。
- 即使发生网络分区,只有拥有"当前生效的 Voting Configuration 中过半数节点"的那一部分集群才能选出 Master。
总结
从 Zen Discovery 到 Cluster Coordination 的转变,标志着 Elasticsearch 从一个"易用的搜索引擎"成熟为一个"严谨的分布式数据库"。
生产环境建议:
- 版本选择:尽量使用 ES 7.10+ 或 8.x 版本,享受更强的共识安全性。
- 节点角色分离 :在大型集群中,设置专用的
master-eligible节点(通常 3 个),不存数据,只负责集群协调,避免 GC 导致的假死(False Positive)触发误选主。 - 监控 :密切关注
cluster_state_queue和discovery相关的日志,任何选主事件都应引起运维警惕。