目录
正在加载目录…

ES 集群与分片配置最佳实践

发布于 2026-05-26 10:25 · 最后编辑于 2026-07-31 15:52 · 字数 1,390 👁 101 次阅读

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

目录

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

硬件选型

磁盘

场景推荐磁盘说明
查询延迟敏感SSD / NVMeSSD 查询速度比 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

  • 数据节点需要遍历分片并做聚合,CPU 性能影响查询速度,建议 8 核以上
  • 写入性能对 CPU 较为敏感,高 QPS 写入业务需要更好的 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"]
}
文件类型含义
nvdnorms(相关度评分数据)
dvddoc values(列式存储)
vec, vex向量数据和 HNSW 图(向量索引专用)

参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。
登录注册 后才能发表评论