分片数量规划的核心原则
Elasticsearch的索引分片(Shard)策略直接决定集群的写入性能、查询效率和资源利用率。分片规划遵循几个核心原则:
分片大小建议在30GB-50GB之间:每个分片本质上是一个Lucene索引,分片过大会导致恢复时间漫长(一个50GB分片在正常网络下恢复约需10-15分钟),合并操作消耗大量I/O。分片过小则浪费资源——每个分片需要独立的文件句柄、内存缓冲区和段合并线程,集群分片总数过多会显著增加主节点内存压力。
每个节点分片数不超过20个/GB堆内存:一个30GB堆内存的数据节点最多承载约600个分片。超出此限制后,主节点在集群状态同步时会出现延迟,写入延迟也会上升。
副本分片数根据可用性和读负载设定:1个副本满足基本的可用性要求(单节点故障不丢数据),读QPS高的场景可以加到2-3个副本,通过分片间负载均衡提升查询吞吐。
索引模板与ILM生命周期管理
日志、指标类时序数据适合使用索引生命周期管理(ILM),自动完成从热到温到冷到删除的流转:
# 索引模板定义
PUT _index_template/logs_template
{
"index_patterns": ["app-logs-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "logs-policy",
"index.lifecycle.rollover_alias": "app-logs",
"index.lifecycle.rollover_age": "1d",
"index.lifecycle.rollover_size": "50gb"
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" },
"service": { "type": "keyword" }
}
}
}
}
# ILM策略
PUT _ilm/policy/logs-policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_primary_shard_size": "50gb"
},
"set_priority": { "priority": 100 }
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 },
"allocate": {
"require": { "data": "warm" }
},
"set_priority": { "priority": 50 }
}
},
"cold": {
"min_age": "30d",
"actions": {
"freeze": {},
"allocate": {
"require": { "data": "cold" }
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
ILM流转逻辑:热阶段每日rollover生成新索引,主分片大小超过50GB或超过1天触发;温阶段7天后收缩分片数到1并强制合并段,降低存储和内存占用;冷阶段30天后冻结索引,查询时再解冻;删除阶段90天后自动清除。
集群容量规划的计算模型
容量规划的核心输入是每日写入量和查询QPS,输出是节点数量和硬件规格。
存储容量计算:
# 日写入量估算
每日原始数据 = 日均文档数 x 单文档平均大小
# 例:1亿文档/天 x 1KB/文档 = 100GB/天
# ES存储开销 = 原始数据 x (1 + 副本数) x 压缩系数 x 索引开销
# 副本数=1, 压缩率约0.5(倒排+docvalue+stored_fields), 索引开销约1.1
总存储 = 100GB x (1+1) x 0.5 x 1.1 = 110GB/天
# 30天存储 = 110GB x 30 = 3.3TB
# 3节点集群, 每节点约 3.3TB/3 = 1.1TB 数据盘
写入吞吐计算:
# 目标写入速率
# 1亿文档/天 = 约1160 docs/s
# 单分片写入能力约5000-8000 docs/s (bulk 5MB batch)
# 3个主分片可承载 15000-24000 docs/s, 满足需求
# 堆内存需求
# 每个分片的FieldData Cache约500MB, 查询缓存约200MB
# 3分片x(500+200)MB x 2(含副本) = 4.2GB
# JVM堆设置 = 系统内存50%, 不超过31GB(指针压缩阈值)
查询吞吐计算:单分片查询能力取决于查询复杂度和缓存命中率。简单过滤查询QPS可达5000+,复杂聚合查询可能只有50-100。通过增加副本分片数线性提升读QPS(每个副本都能独立服务查询)。
分片再平衡与路由优化
集群扩容或节点故障后,分片会自动再平衡。再平衡策略通过cluster-level设置控制:
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.balance.shard": 0.4,
"cluster.routing.allocation.balance.index": 0.3,
"cluster.routing.allocation.balance.disk": 0.3,
"cluster.routing.allocation.disk.threshold_enabled": true,
"cluster.routing.allocation.disk.watermark.low": "85%",
"cluster.routing.allocation.disk.watermark.high": "90%"
}
}
自定义路由:默认路由使用文档ID哈希,相关文档分散到不同分片。如果查询经常按某个维度过滤(如user_id),可以使用自定义路由将同一用户的数据路由到同一分片,查询时指定routing参数避免全分片扫描:
# 写入时指定路由
PUT orders/_doc/order1?routing=user123
{ "user_id": "user123", "amount": 100 }
# 查询时指定路由,只搜索目标分片
GET orders/_search?routing=user123
{
"query": { "term": { "user_id": "user123" } }
}
分片优先级:在节点故障恢复时,通过index.priority控制索引恢复顺序。核心业务索引设高优先级,确保先恢复:
PUT critical-index/_settings
{ "index.priority": 100 }
这种细粒度的分片管理能力让Elasticsearch集群在面对TB级数据和千级QPS时依然保持可预期的性能表现。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/elasticsearch-suo-yin-fen-pian-ce-lyue-yu-ji-qun-rong-liang/