
2.2 Elasticsearch-分片与副本:容量规划公式 〈Shard = 节点数 × 1.5~3〉
——把“拍脑袋”变成“拍键盘”
一、为什么是 1.5~3
Elasticsearch 的写入、查询、恢复三大链路最终都会落到 Lucene 段(segment)的磁盘 I/O 上。
- 写入链路:每个 shard 独享一个 Lucene writer,writer 的 flush、merge 线程池是单线程顺序写,shard 数太少会把 CPU 与磁盘“饿死”;太多又会把 merge 调度器“撑爆”。
- 查询链路:每个 shard 都是一个独立的 searcher,search 阶段需要把 query 广播到全部 shard,结果再汇总;shard 数越多,协调节点序列化/反并发的成本越高。
- 恢复链路:集群重启或节点掉线时,Master 需要把 unassigned shard 重新分配到存活节点,shard 数越多,分配耗时与元数据压力越大。
社区通过 10 年生产血泪史,把“总 shard 数 / 节点数”收敛到 1.5~3 这个“甜蜜区间”:
- <1.5:磁盘 I/O 与 CPU 用不满,扩容等于白加机器;
-
3:Full-Cluster Restart 时 Master 发布 30 k+ 元数据分片,ZK 队列打满,选主超时 90 s 直接脑裂。
二、公式的三条前置假设
- 单 shard 大小 ≤ 50 GB(Lucene 合并段上限,>50 GB 3-way merge 会踩 512 MB write buffer 导致 long-GC)。
- 单节点堆内存 ≤ 32 GB(压缩 OOP 临界点,>32 GB 对象指针膨胀 1.5×,Full GC 耗时翻倍)。
- 副本数 replicas=1(默认高可用配置;若 replicas=2 把结果 ×1.5 即可)。
三、推导过程(可跳过)
设:
- D = 业务原始数据量(GB)
- C = 压缩比(日志 1:5、搜索 1:1.2、Metrics 1:10)
- G = 单 shard 目标大小(GB),取 30~50 GB
- N = 数据节点数
- P = 主分片数
- R = 副本数
则:
总存储 = D / C × (1+R)
总 shard 数 = P × (1+R)
单节点 shard 数 = P × (1+R) / N
把“单节点 shard 数”代入甜蜜区间 1.5~3:
1.5 ≤ P × (1+R) / N ≤ 3
⇒ P ≈ N × (1.5~3) / (1+R)
当 R=1 时,P ≈ N × (0.75~1.5)。
又因为单 shard 大小 G = 总存储 / P,于是:
G = D / C × (1+R) / P
= D / C × 2 / (N × (0.75~1.5))
= (D / C) / N × (1.3~2.7)
把 G 控制在 30~50 GB,即可反解 N:
N ≥ (D / C) / 50 × 1.3
N ≤ (D / C) / 30 × 2.7
一句话版本:
“先按 1.5~3 倍节点数算出主分片,再用‘单 shard ≤ 50 GB’校验节点数够不够,不够就加机器,别硬砍 shard。”
四、三步落地法
Step1 量体:用 _cat/indices?v 把过去 30 天索引的 store.size、docs.count、segment.memory 拉出来,算平均单文档大小与压缩比。
Step2 裁衣:
① 把未来 90 天数据量 D90 按压缩比折算成物理尺寸;
② 取 G=40 GB(保守值),得主分片数 P = ceil(D90 / 40);
③ 按公式反推节点数 N = ceil(P / 1.2)(取 1.2 是给自己留 20 % buffer,防止突增)。
Step3 留余:
- 冷热分离场景:热节点承担 70 % 查询流量,按 1.5 倍 shard 密度部署;冷节点只跑 30 % 慢查询,可压到 3 倍密度。
- 超大索引(>1 TB)强制拆多索引:用 Rollover + ILM,让单个物理索引的 shard 数继续落在 1.5~3 区间,而不是一个索引 500 shard。
五、踩坑案例
案例 A:
日志集群 6 节点,每天 600 GB 原始日志,压缩比 1:5,保存 7 天。
D = 600 × 7 / 5 = 840 GB
P = ceil(840 / 40) = 21
N = ceil(21 / 1.2) = 18 → 节点数不足,直接加到 18 台太疼。
优化:
- replicas 从 1 降到 0(日志可丢),P = ceil(840 / 40) = 21,N = ceil(21 / 1.2) = 18 → 仍然不够。
- 把热数据缩为 3 天,冷数据 4 天,冷热分开:热 2 节点 × 1.5 = 3 shard,冷 4 节点 × 3 = 12 shard,合计 15 shard,6 节点即可扛住。
案例 B:
搜索集群 3 节点,商品索引 500 GB,压缩比 1:1.2,replicas=1。
D = 500 × 2 / 1.2 ≈ 833 GB
P = ceil(833 / 40) = 21
N = ceil(21 / 1.2) = 18 → 只有 3 节点,硬件预算不足。
优化:
- 单 shard 放大到 80 GB(搜索场景 merge 压力小),P = ceil(833 / 80) = 11
- N = ceil(11 / 1.2) = 9 → 还是不够。
- 最终拆成 3 个索引,每个 3 shard,查询端用 alias 合并,3 节点 × 3 = 9 shard,刚好踩线。
六、一句话总结
“节点数 × 1.5~3”不是玄学,而是把 Lucene 的段合并、GC、恢复三大瓶颈压到硬件可接受范围内的经验系数;
先按数据量算出 shard,再用公式校验节点,而不是先拍脑袋定 6 台机器,再去纠结“为什么查询延迟飙到 3 秒”。
更多技术文章见公众号: 大城市小农民

被折叠的 条评论
为什么被折叠?



