本文用以深度学习ES elasticsearch
所涉及版本为 9.0

理解 ES 到底在解决什么问题

假设需求一个日志系统,每天承载数据量如下:

  • 写入:500GB 日志
  • 查询:数千用户同时搜索
  • 机器:10 台

如果只有一台 ES 实例,他的数据完成流程是

text
1
用户 -> ES -> 磁盘

此时存在问题,

  • 磁盘放不下怎么办?
  • 查询太多,CPU 不够用怎么办?
  • 写入太多,一台机器写盘、合并成为瓶颈
  • 内存不够用怎么办?
  • 节点会坏,数据不能丢,宕机后怎样 Failover?
  • 如果是集群,集群元数据、分片位置、主副本切换需要有人统一管理。

es cluster 本质上就是解决的是:大量文档数据如何被快速写入、快速检索、水平扩展、高可用保存和聚合分析

基于这些 ES 引入了一些角色用于区分不同的功能

角色功能
Cluster一组互联的 Node 被成为集群
Node负责运行实例
Index负责逻辑数据集合
Shard负责横向切分
Replica负责高可用和读扩展
Node Roles负责把不同类型的 Node 隔离开

Cluster Node 和 Shared

Cluster (集群)

Cluster 是一组 Elasticsearch 互联的节点组成的整体,对外表现为一个 es 系统。

一个 ES 集群负责:

  • 维护全局 Cluster State [1]
  • 管理节点和索引元数据 [1]
  • 决定 shard 的分配与迁移 [2]
  • 通过选举 (Voting) 机制完成 Master 选举 [3]
  • 节点故障时重新分配 shard [1]
  • 任意节点都可以接收客户端请求 [4],并利用 Cluster State 将请求路由到正确的 shard,用户访问任意一个可访问的节点,本质上都是在访问这个集群。

Node (节点)

节点 (Node) 就是一个 ES (elasticsearch) 实例,可以部署在一台服务器、容器或 Pod 中。

一个节点可以承担一个或多个角色(小集群),例如:master, data, ingest

通过参数来配置“节点”角色

text
1
2
node.roles: [ master ]
node.roles: [ master, data, ingest ]

Index (索引)

Index 是文档的逻辑集合,类似数据库里的 table,但它不是关系模型,一个 Index 会被拆成若干 primary shard。

例如:

  • app-log-2026.06.11
  • order-search-v1

Shard (分片)

Shard 是 ES 横向扩展的核心。一个 shard 本质上是一个 Lucene index。

为什么要有 shard?

  • 单个 index 太大,一台机器放不下。
  • 查询可以并行打到多个 shard。
  • 数据可以分散到多个 data node。
  • 节点故障时可以用 replica 顶上。

例如

text
1
2
3
index = app-log-2026.06.11
number_of_shards = 3
number_of_replicas = 1

那么他可能的分片为

text
1
2
3
node-1: p0, r1
node-2: p1, r2
node-3: p2, r0

他的核心不是顺序,而是依照这个原则

Elasticsearch will never assign a replica to the same node as the primary shard [5].

text
1
2
3
p0 和 r0 不能在同一个 node
p1 和 r1 不能在同一个 node
p2 和 r2 不能在同一个 node

To protect against hardware failure, Elasticsearch will not assign a replica to the same node as its primary shard. If no other data nodes are available to host the replica, it remains unassigned. [5].

Primary 和 Replica

主分片 (Primary shard)

Primary shard 是主分片,是写入的入口。每条文档根据 routing 规则落到某一个 primary shard。

text
1
client -> coordinating node -> primary shard -> replica shard -> ack

默认 routing 近似理解为:

text
1
2
3
4
5
routing_factor = num_routing_shards / num_primary_shards

shard_num =
    ( hash(_routing) % num_routing_shards )
    / routing_factor

如果“路由分片数量” ≠ “主分片数量”

text
1
2
number_of_shards = 5
number_of_routing_shards = 30

那么

text
1
2
routing_factor = 30 / 5 = 6
shard_num = (hash(_routing) % 30) / 6

最终的落地为 0 - 4

如果 “路由分片数量” = “主分片数量”,例如

text
1
2
number_of_shards = 3
number_of_routing_shards = 3

那么带入公式为 $routing_factor = 1$,那么公式就为上面提到的公式

text
1
shard_num = hash(_routing) % number_of_primary_shards

副本分片 (Replica shard)

Replica shard 是 primary shard 的副本。

  1. 高可用:primary 所在节点挂了,replica 可以提升为新的 primary。
  2. 读扩展:搜索请求可以打到 primary,也可以打到 replica。
  3. 分担查询压力。
  • Replica 不能和对应 primary 放在同一个节点上。
  • 如果只有 1 个 data node,设置 number_of_replicas: 1 会导致集群 yellow,参考主副本部分的引用。
  • Primary shard 数量创建 index 后一般不能直接修改,需要 reindex 或 split/shrink 等方式调整。

节点角色 (Node Roles)

为什么要拆分节点角色?

因为 ES 集群里不同工作负载的瓶颈完全不同,混在一起很容易一个角色负责的瓶颈导致全部拖死。

例如,在小集群内,一个节点可能同时做:

  1. master 管理集群状态。
  2. data 存数据、查数据、写数据。
  3. ingest 做 pipeline 预处理。
  4. coordinating 做请求分发和结果合并。

可用节点角色

角色主要职责存储数据数据
master主节点,管理整个集群
data通用数据节点,存储所有数据、执行查询
data_content内容数据节点,存储普通索引数据
data_hot热数据节点,存储最新、读写频繁的数据
data_warm温数据节点,存储较旧、查询较少的数据
data_cold冷数据节点,存储很少访问的数据
data_frozen冻结数据节点,存储极少访问的数据
ingest摄取节点,数据写入前做预处理
ml机器学习节点,运行异常检测等 ML 任务
remote_cluster_client远程集群客户端,跨集群搜索/复制
transform转换节点,执行 Transform 任务

一个节点既可以承担多个角色,也可以只承担一个角色,只是表现在不同规模的集群,运行方式不一样。

Node 一些常用角色组合

Master-eligible node

Master-eligible node 表示为有资格参与 master 选举的节点,并不等于“当前 master 节点”,ME node 可以参与选举也可能会被选举为 “master” 节点

Any master-eligible node that is not a voting-only node may be elected to become the master node by the master election process. [7]

它大致负责:

  • 参与 master 选举,被选中后成为 elected master。
  • 管理 cluster state。
  • 创建/删除 index。
  • 跟踪节点加入/离开。
  • 决定 shard 分配到哪些节点。
  • 发布 cluster state 到所有节点。

Master node 只负责集群的管理,不负责数据的存储、查询、写入等流程

重点:master 做的是轻量级集群管理动作,但它非常关键。master 节点必须有持久化 path.data,因为里面保存集群元数据。如果集群元数据丢失,即使 data node 上的数据还在,也可能无法读取。

Master nodes must have a path.data directory whose contents persist across restarts, just like data nodes, because this is where the cluster metadata is stored. The cluster metadata describes how to read the data stored on the data nodes, so if it is lost then the data stored on the data nodes cannot be read. [7]

Dedicated master node

专用 master 节点,就是这个节点只负责 Master 相关工作

配置方式

yaml
1
node.roles: [ master ]

Voting-only master-eligible node

Voting-only master-eligible node 只参与 master 选举投票,但 永远不会成为真正的 master

配置方式:

text
1
node.roles: [ master, voting_only ]

只有 master 节点,标注了 voting_only 才是 Voting-only master-eligible node

High availability (HA) clusters

官方推荐 HA 至少要三个 master 节点,至少两个不是 Voting-only 的 Master 节点

High availability (HA) clusters require at least three master-eligible nodes, at least two of which are not voting-only nodes. Such a cluster will be able to elect a master node even if one of the nodes fails.

配置示例

text
1
2
3
4
5
6
7
cluster.name: es-prod
node.name: master-1
node.roles: [ master ]
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
discovery.seed_hosts: ["master-1", "master-2", "master-3"]
cluster.initial_master_nodes: ["master-1", "master-2", "master-3"]

数据节点 (Data Node)

数据节点Data node 保存包含文档的 shards,并处理 CRUD、搜索、聚合等数据相关操作,这些操作会消耗 I/O、内存和 CPU。

配置

text
1
node.roles: [ data ]

在部署架构中,数据节点还可以细分为多层,可用角色有 data_content,data_hot, data_warm, data_cold, data_frozen 一个数据节点可以属于多个角色。

协调节点 (Coordinating node)

任何节点接收到客户端请求后,都会临时扮演 coordinating node。仅负责协调的节点就相当于负载均衡

Essentially, coordinating only nodes behave as smart load balancers. [9]

配置

text
1
node.roles: [ ]

协调节点就是剥夺了 master 和 data node 的能力仅剩下的功能 (Coordinating),这个节点基本上只做三件事:路由请求;处理搜索 ;分发批量写入。但官方不建议配置太多协调节点到集群中,太多的协调节点会给集群带来额外的负担。

Adding too many coordinating only nodes to a cluster can increase the burden on the entire cluster because the elected master node must await acknowledgement of cluster state updates from every node! The benefit of coordinating only nodes should not be overstated — data nodes can happily serve the same purpose. [9]

什么时候需要配置协调节点

  • 查询入口很多;
  • 聚合查询重;
  • bulk 写入量大;
  • 不希望业务客户端直接打 data 节点;
  • 需要统一入口做负载均衡。

Ingest 节点

Ingest 节点负责在文档写入 index 前执行预处理 pipeline

配置

text
1
node.roles: [ ingest ]

例如原始数据是

text
1
2
3
{
  "message": "2026-07-09 12:00:01 ERROR user login failed from 1.2.3.4"
}

我想写入ES前加工成

text
1
2
3
4
5
6
{
  "@timestamp": "2026-07-09T12:00:01Z",
  "level": "ERROR",
  "event": "user login failed",
  "client_ip": "1.2.3.4"
}

文档先进入 ingest pipeline,经过多个 processor 加工后,再写入目标 index。

A New Way To Ingest - Part 2 | Elastic Blog

图:ingest pipeline
Source:https://www.elastic.co/blog/new-way-to-ingest-part-2

用户在选型时,根据 processor 做的操作类型,以及这些操作需要多少资源, 有时候可以考虑搞专用 ingest 节点。 这些节点只负责 ingest 预处理这一件事。

数据节点分层

数据分层是指 Elasticsearch data node 的分层,在 ES8 之后,data node 不只是一个 角色 (data),还可以按数据冷热分层,用不同 storage tier 在性能、成本、可访问性之间做平衡;hot 适合频繁访问,frozen 适合很少查询的数据,根据用途拆成:

角色用途
data通用数据节点 (Generic data node),万能角色可以承担所有专用 data tier 的职责。
data_content内容型数据节点 (Content data node),这种节点的特点为:
不是明显的时间序列数据
不会因为变老就一定降级到慢盘
需要长期保存,无论新旧,都希望查询快
data_hot热数据节点 (Hot data node) prefer 时间序列,常用于日志,metrics,trace,订单等
data_warm温数据节点 (Warm data node), 最近几周,偶尔查,性能要求低于 hot
data_cold冷数据节点 (Cold data node),本地不需要普通副本来保证可靠性;节点故障后可以从 snapshot repository 恢复,因此可以节省本地磁盘,但索引是只读的。
data_frozen冻结数据节点 (Frozen data node),依赖 snapshot repository,因为查询时有时要从 snapshot 仓库拉数据,所以通常比 cold tier 更慢。

总结:

  • data_content: 业务内容数据,不按时间自然变冷。

  • data_hot: 最新时间序列数据,写入高,查询高,最快机器。

  • data_warm: 最近一段时间的旧数据,查询少一些,机器可以便宜点。

  • data_cold: 老数据,偶尔查,重点省存储。

  • data_frozen: 归档数据,极少查,依赖 snapshot,最省但最慢。

  • data: 万能数据角色,不细分冷热。

elasticsearch cluster

图:Data tiers
Source:https://www.elastic.co/blog/elasticsearch-data-architecture-tools-improved-analysis-storage

Reference

[1] Cluster state

[2] Shard allocation, relocation, and recovery

[3] Voting configurations

[4] Node roles

[5] Red or yellow cluster health status

[6] How to route docs of same _routing key in Elasticsearch into multiple shard?

[7] Master-eligible node

[8] Voting-only master-eligible node

[9] Coordinating only node