Elasticsearch 底层原理系列(六):集群架构与节点角色
2020-11-29·6 分钟阅读
前言
Elasticsearch 的分布式能力是其核心优势之一。理解集群架构和节点角色,对于部署高可用、高性能的 ES 集群至关重要。
本章将深入解析 ES 集群的节点角色、职责划分以及集群状态管理机制。
技术亮点
| 技术点 | 难度 | 面试价值 | 本文覆盖 |
|---|---|---|---|
| 节点角色分类 | ⭐⭐⭐ | 高频考点 | ✅ |
| Master 选举 | ⭐⭐⭐⭐ | 高频考点 | ✅ |
| 集群状态管理 | ⭐⭐⭐⭐ | 进阶考点 | ✅ |
| 节点配置最佳实践 | ⭐⭐⭐ | 实战价值 | ✅ |
面试考点
- Elasticsearch 有哪些节点角色?各自的职责是什么?
- Master 节点是如何选举的?
- 集群状态包含哪些信息?如何同步?
- 生产环境应该如何配置节点角色?
节点角色概览
节点角色分类
┌─────────────────────────────────────────────────────────────────────────┐
│ ES 节点角色分类 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Master- │ 集群管理:创建/删除索引、节点加入/离开 │ │
│ │ │ Eligible │ 不存储数据,轻量级 │ │
│ │ │ Node │ │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Data Node │ 存储数据、执行搜索和聚合 │ │
│ │ │ │ CPU/内存/IO 密集型 │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Coordinating │ 请求路由、结果聚合 │ │
│ │ │ Node │ 智能负载均衡器 │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Ingest Node │ 预处理管道:数据转换、富化 │ │
│ │ │ │ 类似 Logstash 的轻量级处理 │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ ML Node │ 机器学习任务:异常检测、预测 │ │
│ │ │ │ 需要较多内存 │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
节点角色配置
# elasticsearch.yml 配置示例
# Master-eligible 节点(可被选为 Master)
node.roles: [ master ]
# Data 节点(存储数据)
node.roles: [ data ]
# Coordinating 节点(仅协调)
node.roles: [ ]
# 组合角色
node.roles: [ master, data ] # 同时是 Master 和 Data 节点
node.roles: [ data, ingest ] # Data 节点 + Ingest 功能
Master 节点详解
Master 节点职责
┌─────────────────────────────────────────────────────────────────────────┐
│ Master 节点职责 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 核心职责:集群级别的元数据管理 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 集群状态管理 │ │
│ │ • 维护集群元数据(索引、映射、别名等) │ │
│ │ • 发布集群状态变更到所有节点 │ │
│ │ │ │
│ │ 2. 索引管理 │ │
│ │ • 创建/删除索引 │ │
│ │ • 索引设置更新 │ │
│ │ • 分片分配决策 │ │
│ │ │ │
│ │ 3. 节点管理 │ │
│ │ • 新节点加入集群 │ │
│ │ • 节点离开检测 │ │
│ │ • 故障节点处理 │ │
│ │ │ │
│ │ 4. 分片分配 │ │
│ │ • 决定分片在哪个节点上 │ │
│ │ • 分片重新平衡 │ │
│ │ • 副本创建 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 重要:Master 节点不存储实际数据,不参与搜索和聚合 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Master 选举
┌─────────────────────────────────────────────────────────────────────────┐
│ Master 选举流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ES 7.x+ 使用改进的选举算法(类似 Raft): │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 选举触发条件: │ │
│ │ • 集群启动 │ │
│ │ • 当前 Master 失效 │ │
│ │ │ │
│ │ 选举流程: │ │
│ │ │ │
│ │ Step 1: 发现阶段 │ │
│ │ ┌───────────────────────────────────────────────────────────┐ │ │
│ │ │ 节点相互发现,通过配置的 seed_hosts 或单播发现 │ │ │
│ │ │ │ │ │
│ │ │ Node A ◄──────────────► Node B ◄──────────────► Node C │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ └─────────────────────────┴─────────────────────────┘ │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 2: 投票阶段 │ │
│ │ ┌───────────────────────────────────────────────────────────┐ │ │
│ │ │ 每个 Master-eligible 节点投票给排序最前的候选者 │ │ │
│ │ │ │ │ │
│ │ │ 排序依据:cluster_state_version + node_id │ │ │
│ │ │ │ │ │
│ │ │ Node A (version=5, id=1) ◄─── 投票 │ │ │
│ │ │ Node B (version=5, id=2) │ │ │
│ │ │ Node C (version=5, id=3) ◄─── 投票 │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 3: 胜出条件 │ │
│ │ ┌───────────────────────────────────────────────────────────┐ │ │
│ │ │ 获得超过半数投票(N/2 + 1) │ │ │
│ │ │ │ │ │
│ │ │ 3 个节点需要 2 票胜出 │ │ │
│ │ │ 5 个节点需要 3 票胜出 │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Step 4: 就任 │ │
│ │ ┌───────────────────────────────────────────────────────────┐ │ │
│ │ │ 胜出节点成为新 Master │ │ │
│ │ │ 发布最新的集群状态到所有节点 │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
避免脑裂
┌─────────────────────────────────────────────────────────────────────────┐
│ 避免脑裂配置 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 脑裂问题:网络分区导致多个节点都认为自己是 Master │
│ │
│ ES 7.x+ 自动计算 minimum_master_nodes = master_eligible_nodes / 2 + 1 │
│ │
│ 示例: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 正常集群(5 个 Master-eligible 节点): │ │
│ │ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ M1 │ │ M2 │ │ M3 │ │ M4 │ │ M5 │ │ │
│ │ │Master│ │ │ │ │ │ │ │ │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │ │
│ │ │ 网络分区 │ │
│ │ ▼ │ │
│ │ 分区 A(3 节点): 分区 B(2 节点): │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ M1 │ │ M2 │ │ M3 │ │ M4 │ │ M5 │ │ │
│ │ │Master│ │ │ │ │ │ 无Master│ │ │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │
│ │ 分区 A 有 3 票(≥ 3),可以选出 Master │ │
│ │ 分区 B 只有 2 票(< 3),无法选出 Master │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 最佳实践:生产环境至少 3 个 Master-eligible 节点 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Data 节点详解
Data 节点职责
┌─────────────────────────────────────────────────────────────────────────┐
│ Data 节点职责 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 核心职责:存储数据、执行查询 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 数据存储 │ │
│ │ • 存储分片数据(主分片和副本分片) │ │
│ │ • 管理索引文件 │ │
│ │ • 执行 Segment 合并 │ │
│ │ │ │
│ │ 2. 查询执行 │ │
│ │ • 执行搜索请求 │ │
│ │ • 执行聚合计算 │ │
│ │ • 返回结果给协调节点 │ │
│ │ │ │
│ │ 3. 写入处理 │ │
│ │ • 接收写入请求 │ │
│ │ • 构建倒排索引 │ │
│ │ • 同步到副本 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 资源特点: │
│ • CPU 密集:查询和聚合计算 │
│ • 内存密集:缓存、FST、Field Data │
│ • IO 密集:磁盘读写 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Data 节点细分
┌─────────────────────────────────────────────────────────────────────────┐
│ Data 节点细分(ES 7.x+) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ data_content: 内容数据节点 │ │
│ │ • 存储常规数据 │ │
│ │ • 适合非时序数据 │ │
│ │ │ │
│ │ data_hot: 热数据节点 │ │
│ │ • 存储最新、最常访问的数据 │ │
│ │ • 需要高性能存储(SSD) │ │
│ │ │ │
│ │ data_warm: 温数据节点 │ │
│ │ • 存储较旧、访问较少的数据 │ │
│ │ • 可以用较便宜的存储 │ │
│ │ │ │
│ │ data_cold: 冷数据节点 │ │
│ │ • 存储很少访问的历史数据 │ │
│ │ • 可以用廉价大容量存储 │ │
│ │ │ │
│ │ data_frozen: 冻结数据节点 │ │
│ │ • 存储极冷数据 │ │
│ │ • 数据可能存储在 S3 等对象存储 │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ 配置示例: │
│ node.roles: [ data_hot ] │
│ node.roles: [ data_warm ] │
│ node.roles: [ data_hot, data_warm ] │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Coordinating 节点详解
Coordinating 节点职责
┌─────────────────────────────────────────────────────────────────────────┐
│ Coordinating 节点职责 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 核心职责:请求路由、结果聚合 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 查询请求处理流程: │ │
│ │ │ │
│ │ 1. 接收客户端请求 │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ Client ──► Coordinating Node │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ │ │ │
│ │ 2. 解析请求 │ │
│ │ • 解析 Query DSL │ │
│ │ • 确定涉及的索引和分片 │ │
│ │ │ │
│ │ 3. 路由请求 │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ ┌─────┐ │ │ │
│ │ │ │ D1 │ │ │ │
│ │ │ ┌───►└─────┘◄───┐ │ │ │
│ │ │ │ │ │ │ │
│ │ │ ┌──┴──┐ ┌──┴──┐ │ │ │
│ │ │ │ CN │ │ D2 │ │ │ │
│ │ │ └──┬──┘ └─────┘ │ │ │
│ │ │ │ │ │ │ │
│ │ │ └───►┌─────┐◄─┘ │ │ │
│ │ │ │ D3 │ │ │ │
│ │ │ └─────┘ │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ │ │ │
│ │ 4. 聚合结果 │ │
│ │ • 合并各分片返回的结果 │ │
│ │ • 全局排序 │ │
│ │ • 分页处理 │ │
│ │ │ │
│ │ 5. 返回客户端 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 优势: │
│ • 减轻 Data 节点负担 │
│ • 集中处理请求路由 │
│ • 智能负载均衡 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
集群状态管理
集群状态内容
┌─────────────────────────────────────────────────────────────────────────┐
│ 集群状态内容 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Cluster State 包含: │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 集群级别信息 │ │
│ │ • cluster_name: 集群名称 │ │
│ │ • cluster_uuid: 集群唯一标识 │ │
│ │ • version: 状态版本号 │ │
│ │ │ │
│ │ 2. 节点信息 │ │
│ │ • nodes: 所有节点列表 │ │
│ │ • 每个节点的角色、地址、属性 │ │
│ │ │ │
│ │ 3. 索引元数据 │ │
│ │ • mappings: 字段映射 │ │
│ │ • settings: 索引设置 │ │
│ │ • aliases: 索引别名 │ │
│ │ │ │
│ │ 4. 分片路由表 │ │
│ │ • routing_table: 分片分布信息 │ │
│ │ • 哪个分片在哪个节点上 │ │
│ │ • 主分片和副本分片的位置 │ │
│ │ │ │
│ │ 5. 集群设置 │ │
│ │ • persistent: 持久化设置 │ │
│ │ • transient: 临时设置 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 查看集群状态:GET /_cluster/state │
│ │
└─────────────────────────────────────────────────────────────────────────┘
状态同步机制
┌─────────────────────────────────────────────────────────────────────────┐
│ 状态同步机制 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Master 发布状态变更流程: │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. Master 接收状态变更请求 │ │
│ │ (如创建索引、更新设置等) │ │
│ │ │ │
│ │ 2. Master 更新本地状态 │ │
│ │ version++ │ │
│ │ │ │
│ │ 3. 发布到所有节点 │ │
│ │ ┌───────────────────────────────────────────────────────┐ │ │
│ │ │ Master │ │ │
│ │ │ │ │ │ │
│ │ │ ┌───────────────┼───────────────┐ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ ▼ ▼ ▼ │ │ │
│ │ │ Node 1 Node 2 Node 3 │ │ │
│ │ │ (Ack) (Ack) (Ack) │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ └───────────────┴───────────────┘ │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ 等待多数确认 │ │ │
│ │ └───────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ 4. 收到多数确认后提交 │ │
│ │ 发送 commit 消息给所有节点 │ │
│ │ │ │
│ │ 5. 所有节点应用新状态 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 这是一种类似两阶段提交的协议,保证一致性 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
生产环境最佳实践
节点角色配置建议
┌─────────────────────────────────────────────────────────────────────────┐
│ 生产环境节点配置建议 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 小型集群(< 10 节点): │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 所有节点:master + data │ │
│ │ node.roles: [ master, data ] │ │
│ │ │ │
│ │ 优点:配置简单 │ │
│ │ 缺点:Master 负担较重 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 中型集群(10-50 节点): │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 3 个专用 Master 节点: │ │
│ │ node.roles: [ master ] │ │
│ │ │ │
│ │ 其余为 Data 节点: │ │
│ │ node.roles: [ data ] │ │
│ │ │ │
│ │ 可选:专用 Coordinating 节点 │ │
│ │ node.roles: [ ] │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 大型集群(> 50 节点): │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 3-5 个专用 Master 节点 │ │
│ │ 多个专用 Coordinating 节点 │ │
│ │ 多个 Data 节点(按热度分层:hot/warm/cold) │ │
│ │ 可选:专用 Ingest 节点 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Master 节点配置建议
# Master 节点专用配置
node.roles: [ master ]
# 避免超时导致重新选举
discovery.zen.ping_timeout: 5s
# 堆内存不宜过大(Master 轻量级)
-Xms4g
-Xmx4g
Data 节点配置建议
# Data 节点配置
node.roles: [ data ]
# 堆内存约为物理内存的 50%,最大 31GB
-Xms16g
-Xmx16g
# 关闭交换分区
bootstrap.memory_lock: true
总结
本章深入解析了 ES 集群架构和节点角色:
| 节点角色 | 职责 | 资源特点 |
|---|---|---|
| Master | 集群管理、状态同步 | CPU/内存轻量 |
| Data | 存储数据、执行查询 | CPU/内存/IO 密集 |
| Coordinating | 请求路由、结果聚合 | CPU/网络密集 |
| Ingest | 数据预处理 | CPU 密集 |
| ML | 机器学习任务 | 内存密集 |
核心要点:
- Master 选举:需要多数节点投票胜出
- 避免脑裂:至少 3 个 Master-eligible 节点
- 角色分离:生产环境建议专用 Master 节点
- 分层存储:hot/warm/cold 架构优化成本
参考资料
下一章预告
下一章将探讨 分片与路由机制,包括:
- 分片路由算法
- 自定义路由
- 分片数量规划
相关文章
Elasticsearch 底层原理系列(七):分片与路由机制
2020-12-13·5 分钟阅读
深入解析 Elasticsearch 分片路由机制,包括路由算法、自定义路由、分片数量规划、以及分片重平衡策略。
Elasticsearch 底层原理系列(一):架构概述
2020-10-06·5 分钟阅读
深入理解 Elasticsearch 整体架构设计,包括核心概念、分层架构、Lucene 与 ES 的关系,以及分布式搜索的基本原理。
Elasticsearch 底层原理系列(九):生产实践与性能调优
2020-12-31·6 分钟阅读
深入解析 Elasticsearch 生产环境最佳实践,包括硬件选型、JVM 调优、索引设计、性能监控与调优、常见问题排查。