ES 系列 #06:ES 集群与分片配置最佳实践

发布于 2026-05-26 10:25 👁 7 次阅读
#elasticsearch#best-practice#cluster#shards#configuration

从硬件选型、节点角色划分、分片策略、JVM 参数四个维度梳理 ES 集群配置最佳实践,重点解决"分片数该设多少"这个高频问题。


目录

章节 说明
硬件选型 磁盘、内存、CPU 的选择建议
节点角色划分 Master、Data、协调节点的隔离原则
分片数量规划 分片大小公式与规范
分片过多的代价 过多分片引起的扩展性问题
关键索引配置 refresh、translog、segment 合并
集群级别参数 重要的 cluster settings

硬件选型

磁盘

场景 推荐磁盘 说明
查询延迟敏感 SSD / NVMe SSD 查询速度比 SATA 快 5-10 倍
查询要求一般 SATA 成本低,适合冷数据
数据节点 单机 500G 以上 保证足够的存储空间
协调节点 200G 足矣 协调节点不存数据,只做路由和聚合

ES 最大的性能瓶颈往往是磁盘 I/O,优先解决磁盘问题。

内存

推荐配置:
  物理内存 >= 16G
  JVM Heap = 机器内存的 50%,但不超过 32G
  内存 : 磁盘 ≈ 1 : 10(经验比例)

示例:
  32G 内存 + 320G SSD → JVM 16G,OS Cache 16G,磁盘 320G

为什么 Heap 不超过 32 GB?

JVM 在 Heap ≤ 32 GB 时会启用指针压缩(Compressed OOPs),每个对象指针从 8 字节压缩为 4 字节,内存利用率更高。超过 32 GB 后指针压缩失效,反而会使实际可用内存变少。

CPU


节点角色划分

es node roles

节点类型 职责 数量建议
Master 节点 管理集群状态(索引创建/删除、分片分配) 固定 3 个,不随数据增长扩展
Data 节点 存储数据,执行查询和写入 按数据量和负载横向扩展
协调节点 路由请求、汇聚结果,不存数据 按查询并发量配置

核心原则:Master 节点与 Data 节点必须隔离,防止数据节点因负载过高导致 Master 不可用,进而引发整个集群崩溃。

# Master 节点配置
node.master: true
node.data: false

# Data 节点配置
node.master: false
node.data: true

分片数量规划

es shard sizing guide

官方推荐规则

1. 单个分片大小:10 GB ~ 50 GB(推荐 10-30 GB)
2. 每 GB Heap 内存对应的分片数 ≤ 20 个
3. 单节点最大分片数(cluster.max_shards_per_node)默认 1000
4. 集群合理的总分片数控制在 3000 以内(不超过 6000)

分片数计算公式

主分片数 = ceil(索引总大小 / 目标单分片大小)

示例:
  预计索引大小 120 GB,目标单分片 30 GB
  → 主分片数 = ceil(120/30) = 4 个主分片

验证:
  节点内存 32G → JVM Heap 16G
  每 GB Heap 最多 20 个分片 → 16G × 20 = 320 个分片上限
  4 个主分片 + 4 个副本 = 8 个分片,远小于 320,合理

分片大小规范

规范 数值
单个分片推荐大小 10-30 GB
单个分片最大上限 50 GB
单索引 size < 1 GB 时,主分片数 ≤ 5(推荐)
单节点数据量上限 2 TB
单集群索引数量 ≤ 1000(推荐)
单集群总分片数 ≤ 6000(推荐),合理值 ≤ 3000

分片均衡配置

防止某些节点分片过多导致流量不均:

PUT /my_index/_settings
{
  "index.routing.allocation.total_shards_per_node": 2
}

分片过多的代价

当集群总分片数过大时(如 6 万+),会出现以下问题:

问题 说明
创建索引耗时长 6 万分片时创建新索引耗时超过 5 秒
pending task 堆积 Master 处理状态变更任务积压,集群被打爆
节点数受限 扩容节点时分片重分配耗时极长
集群资源碎片化 运维成本高,难以管理
重启效率低下 分片重新分配和恢复时间大幅增加
监控统计接口慢 _cat/shards 等接口导致 Master 内存堆积

根本原因:每个分片对应一个 Lucene 实例,每个 Lucene 实例都占用文件句柄、JVM 内存和 CPU,分片数过多相当于同时运行数千个 Lucene 进程。


关键索引配置

Refresh 间隔

# 实时性要求不高时,延长 refresh 间隔,减少 segment 产生频率
PUT /my_index/_settings
{
  "index.refresh_interval": "30s"
}

Translog 异步

PUT /my_index/_settings
{
  "index.translog.durability": "async",
  "index.translog.sync_interval": "5s"
}

定期强制合并只读索引

# 历史不再写入的索引,强制合并为 1 个 segment
POST /my_index/_forcemerge?max_num_segments=1

索引排序(加速特定查询)

PUT /my_index
{
  "settings": {
    "index.sort.field": "createTime",
    "index.sort.order": "desc"
  }
}

对按 createTime 降序排列的查询,命中后可以提前终止扫描(Early Termination),大幅降低查询延迟。


集群级别参数

# elasticsearch.yml

# JVM Heap(设置为机器内存的 50%,不超过 32G)
-Xms16g
-Xmx16g

# 允许每个节点的最大分片数(默认 1000)
cluster.max_shards_per_node: 1000

# 索引 buffer(写入密集型集群可适当调大)
indices.memory.index_buffer_size: 15%

# 段合并速度(SSD 可调高)
indices.store.throttle.max_bytes_per_sec: 100mb

预热文件系统缓存

PUT /my_index/_settings
{
  "index.store.preload": ["nvd", "dvd"]
}
文件类型 含义
nvd norms(相关度评分数据)
dvd doc values(列式存储)
vec, vex 向量数据和 HNSW 图(向量索引专用)

参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。

发表评论