一、当Elasticsearch集群开始"长胖"时
想象你的Elasticsearch集群就像个正在发育的青少年,突然某天业务量暴增,原本的3个节点撑不住了。你赶紧加了2台新服务器,但很快发现:新节点像个局外人一样站着发呆,数据全挤在老节点上,搜索性能反而更差了。
这就是典型的数据均衡问题——新增节点后,Elasticsearch不会自动把存量数据重新分配。就像搬家时把所有家具堆在新客厅门口,反而让整个房子更乱了。
// 技术栈:Elasticsearch 7.x
// 查看当前分片分布情况(会显示所有分片集中在老节点)
GET _cat/shards?v&h=index,shard,prirep,node&s=node
/* 输出示例:
index shard prirep node
logs-2023 0 p node-old-1
logs-2023 1 p node-old-2
logs-2023 2 p node-old-1
...(新节点node-new-1/node-new-2完全没出现)
*/
二、让数据流动起来的三种药方
方案1:开启自动平衡(适合小规模集群)
就像给房间装个自动扫地机器人,Elasticsearch自带平衡机制,但默认配置比较保守:
// 动态启用所有平衡策略(生产环境建议逐个开启)
PUT _cluster/settings
{
"persistent": {
"cluster.routing.rebalance.enable": "all",
"cluster.routing.allocation.balance.shard": "0.7", // 分片平衡因子(默认0.45)
"cluster.routing.allocation.balance.index": "0.6" // 索引平衡因子(默认0.55)
}
}
/* 注意:
1. 值越接近1表示越激进
2. 白天业务高峰时慎用,可能引发性能波动
*/
方案2:手动迁移分片(精准控制但费劲)
好比亲自搬家具,可以精确控制每个分片的位置:
// 将特定索引的分片迁移到新节点
POST _cluster/reroute
{
"commands": [
{
"move": {
"index": "order_logs",
"shard": 0,
"from_node": "node-old-1",
"to_node": "node-new-1"
}
}
]
}
// 配合过滤API先找出热点分片
GET _cat/shards?v&h=index,node,store&s=store:desc
方案3:滚动重启老节点(核武器方案)
这是最彻底的方法——通过临时"踢掉"老节点迫使数据迁移:
# 技术栈:Elasticsearch + Shell
# 1. 先禁用分配(防止自动恢复)
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "none"
}
}
# 2. 逐台重启老节点(建议间隔10分钟)
ssh node-old-1 "systemctl restart elasticsearch"
# 3. 重新启用分配
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "all"
}
}
三、那些年我们踩过的坑
去年给某电商平台扩容时就翻车了。当时直接调整了cluster.routing.allocation.node_concurrent_recoveries(默认2),想加快平衡速度:
PUT _cluster/settings
{
"persistent": {
"node_concurrent_recoveries": 8 // 暴力提高到8
}
}
结果导致:
- 网络带宽打满,正常查询超时
- 大量文件描述符耗尽
- 最终触发了保护机制自动停止迁移
血泪建议:
- 每次调整参数后用
GET _nodes/stats/thread_pool监控bulk/search线程池队列 - 遵循"小步快跑"原则,每次参数调整幅度不超过50%
- 优先迁移冷数据索引(通过
_ilm/policy打标签)
四、预防胜于治疗的日常保健
其实最好的扩容是"无感扩容"。我们给某物流系统设计的方案就很有意思:
// 技术栈:Elasticsearch 8.x
// 在索引模板预配置自动均衡策略
PUT _index_template/logs_template
{
"index_patterns": ["*_logs"],
"template": {
"settings": {
"number_of_shards": 10,
"number_of_replicas": 1,
"routing.allocation.total_shards_per_node": 3 // 每个节点最多放3个主分片
}
}
}
/* 效果:
1. 新索引自动均匀分布
2. 配合ILM自动滚动创建新索引
3. 历史数据通过CCR跨集群复制逐步迁移
*/
长期建议:
- 使用
_cat/allocation?v每周检查磁盘使用差异 - 为热节点配置更高规格的硬件(比如NVMe SSD)
- 重要索引单独配置
routing.allocation.require属性
五、总结:扩容不是终点而是起点
经过多次实战我们发现,Elasticsearch的数据均衡本质是空间换时间的艺术。就像整理衣柜,与其等塞爆时手忙脚乱,不如:
- 提前规划好分片数量(建议单个分片30-50GB)
- 用
index.routing_partition_size控制写入热点 - 善用
_cluster/allocation/explain诊断分配失败原因
记住,一个健康的集群应该像交响乐团——每个节点都有活干,但谁都不该过度劳累。下次扩容时,不妨先喝杯咖啡,把本文的步骤再过一遍。
评论