简介:集群倾斜与 Shard 数量的关系
Elasticsearch 集群倾斜(Cluster Skew)是指集群中的数据分片(Shard)在数据节点上分布不均匀,导致部分节点负载过高,而其他节点资源闲置。这不仅浪费了硬件资源,还会影响查询和写入的性能。
解决集群倾斜的方法有很多,但最基础且关键的一步,就是在创建索引时,设置一个合理的分片数量 (number_of_shards)。
如果主分片数量设置不当(特别是数量太少),可能导致以下问题:
1. 数据分布不均: 如果分片数量少于数据节点数量,部分节点将永远无法参与到该索引的负载均衡中,导致天然的倾斜。
2. 分片过大: 如果数据量持续增长,分片过大(超过推荐的 50GB)会增加恢复时间、降低搜索效率。
实用操作:计算最佳分片数量
合理的分片数量不是随意设置的,它取决于两个关键因素:数据总量和数据节点数量。
第一步:确定集群和数据预估
假设我们有一个包含 5 个数据节点(Data Node)的集群,并且我们预期要创建的索引总数据量在未来一段时间内会增长到 500GB。
第二步:确定目标分片大小
Elasticsearch 官方推荐的单个分片最佳大小在 10GB 到 50GB 之间。我们选取一个中间值,目标设定为 40GB/Primary Shard。
第三步:计算所需的主分片数量
主分片数量 (P) = 预估数据总量 / 目标分片大小
P = 500 GB / 40 GB/shard = 12.5
由于分片数量必须是整数,我们向上取整,得到 13 个主分片。
第四步:调整以适配节点数量
虽然 13 个主分片可以保证分片大小合理,但为了更好地利用 5 个数据节点,我们需要确保分片数量能够均匀分配。13 / 5 = 2.6,分片分配是相对均匀的。
关键原则: 主分片数量 N 应该等于或略大于数据节点数量 M,且最好是 M 的整数倍,以确保每个节点至少承载一个主分片。
如果我们将主分片数量设置为 15 (5的3倍),则 15 / 5 = 3,每个节点恰好分配到 3 个主分片(理想情况),实现了完美的负载均衡。
结论:我们选择 15 个主分片 (number_of_shards: 15)。
代码实战:创建具有优化 Shard 数量的索引
在确定了主分片数量后,我们可以在创建索引时设置该参数。我们同时设置副本数量为 1 (number_of_replicas: 1),这意味着总共有 15 (Primary) + 15 (Replica) = 30 个 Shard。
示例:使用 Index Template 创建索引模板
为了避免每次手动设置,推荐使用索引模板(Index Template)来配置所有新建索引的默认设置。
PUT /_index_template/optimized_logs_template
{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": 15,
"number_of_replicas": 1,
"index.routing.allocation.total_shards_per_node": 6
},
"mappings": {
"properties": {
"timestamp": {
"type": "date"
}
}
}
},
"priority": 500
}
参数说明
| 参数 | 解释 | 作用 |
|---|---|---|
| number_of_shards | 15 (主分片数量) | 确保分片大小适中,且能被 5 个节点均匀分配 (15/5=3),解决负载倾斜问题。 |
| number_of_replicas | 1 (副本数量) | 提供高可用性,但不直接影响分配均衡性。 |
| total_shards_per_node | 6 (可选,但推荐) | 限制单个节点上该索引最大可承载的总分片数 (Primary + Replica)。这里设置 6 是因为 15/5=3,Primary+Replica=2*3=6。这进一步防止了单个节点超载。 |
通过这种方式,当数据写入 **logs-*** 索引时,Elasticsearch 将创建 15 个主分片,并根据集群的节点数量(5个)均匀地将这 30 个分片(15P + 15R)分布在所有节点上,从而从根本上解决了因分片数量设置不当导致的集群倾斜问题。
汤不热吧