ElasticSearch 分片数规划与计算
🎯 核心结论(先记住)
ElasticSearch 分片数一旦创建就不能修改,所以分片规划的核心目标是:
单个 Primary Shard 的最终大小控制在 20–50GB 之间(日志类更偏 20–30GB)
分片路由算法:
shard = hash(_routing) % primary_shards
- 决定数据存入哪个主分片
- 改分片数 = 全量重建索引
- ES 没有 “在线拆分主分片” 的能力(只能 shrink 减少)
👉 所以:分片数 = 建索引前必须想清楚的事情
通过对路由值进行哈希计算并取模,保证数据均匀分布在主分片中。这也是为何索引创建后主分片数量不能直接更改的原因。
详细解释:
- shard:计算出的目标主分片(Primary Shard)的索引号。
- hash(_routing):对 _routing 值计算哈希值(通常默认为文档的 _id)。这是将文档哈希为一个确定的数字。
- %:取模运算符,即整除后的余数。
- primary_shards:当前索引的主分片总数量。
工作流程与关键点:
- 确定位置:当写入或查询文档时,ES 会根据 _routing 计算出对应的 shard 编号。
- 数据均匀化:利用哈希函数的随机性,确保文档均匀地分布在所有主分片上。
- 不可修改性:因为分片数是公式的除数,如果后续修改了主分片数量(如 primary_shards 从 3 变为 4),原有的 hash(_routing) 结果取模后的数值就会改变,导致之前的文档“消失”(因为查找时计算出了错误的分片位置)。
举例:如果有 3 个主分片(P0, P1, P2),_routing 为 id1,假设 hash(“id1”) 的结果为 (10),则 10 % 3 = 1。该文档将存储在 P1 上。
在规划前,你至少要知道这 4 个数:
| 参数 | 含义 |
|---|---|
| D | 每天数据量(GB/day) |
| T | 索引保留周期(天) |
| R | 副本数(replica) |
| S | 单 shard 目标大小(GB) |
⭐ 分片数计算公式
Primary Shards = ⌈ ( D × T ) / S ⌉
副本不参与计算 primary shard 数量。
条件
- 每天日志:100 GB
- 索引周期:1 天(daily index)
- shard 目标:25 GB
计算
Primary Shards = 100 / 25 = 4
结论
"number_of_shards": 4,
"number_of_replicas": 1
👉 最终磁盘:
100GB × (1 + 1) = 200GB
条件
- 每天日志:200 GB
- Hot 数据保留:7 天
- shard 目标:30 GB
Primary Shards = (200 × 7) / 30 ≈ 47
⚠️ 不建议单索引 47 shard
👉 正确做法:
- 使用 daily index + rollover
- 每天一个索引,每个索引 7 shard
条件
- 当前数据量:300 GB
- 未来一年预计增长到:1 TB
- shard 目标:40 GB
Primary Shards = 1000 / 40 = 25
👉 创建索引时:
number_of_shards = 24 或 25
❌ 错误做法
1 个索引,100+ shard
✅ 正确做法
daily index + rollover + ILM
示例
"rollover": {
"max_size": "30gb",
"max_age": "1d"
}
好处:
- 分片数自动控制
- shard 永远不超大
- 方便冷热分离
| 场景 | shard 大小 |
|---|---|
| 高频写入日志 | 20–30 GB |
| 普通日志 | 30–40 GB |
| 搜索型业务 | 30–50 GB |
| 冷数据 | 50–100 GB |
经验值:
< 20 shard / GB heap
例如:
- 32GB heap -> ~600 shard(含 replica)
| shard 太多 | shard 太大 |
|---|---|
| 集群状态臃肿 | 查询慢 |
| 内存浪费 | merge 压力大 |
| GC 频繁 | 恢复慢 |
👉 宁可稍微大一点,也不要太多
规划时 至少预留 30%–50% 冗余:
预计一年后 1TB -> 按 1.3TB 规划
- 控制 shard 大小
- 不再关心“单索引分片数”
- 重建索引(代价高)
POST index/_shrink/index_shrinked
ElasticSearch 的主分片数一旦创建就不能修改,所以我在前期会根据 每天数据量 × 保留周期 ÷ 单 shard 目标大小 来计算。
实践中我会把单 shard 控制在 20–50GB, 日志系统用 daily index + rollover + ILM, 同时预留 30% 的增长空间,避免后期重建索引。