4. 分片分配与再平衡故障诊断
分片分配是 Elasticsearch 集群把索引的每个分片落到某个数据节点上的过程,它由主节点(master)统一决策,数据节点只负责执行。当集群出现黄色或红色状态时,绝大多数情况并不是数据丢失,而是某些分片找不到合适的落点。理解“为什么没分配”和“为什么反复搬动”,是分片运维的核心能力。
一、分片未分配的常见原因
主节点在分配分片时会依次检查一系列条件,任何一条不满足都会导致分片停留在 UNASSIGNED 状态。常见原因可以归为几类:
- 节点数量不足:副本分片要求与主分片不在同一节点,若数据节点数少于
主分片数 + 1,副本永远无法分配,集群长期黄色。 - 磁盘水位线触发:节点磁盘使用率超过低水位线后,Elasticsearch 不再向该节点分配新分片;超过高水位线后,会主动把分片迁出。
- 分配过滤规则:
index.routing.allocation.include/exclude/require或节点属性(如node.attr.zone)把分片限制到了不存在的节点上。 - 节点离线或恢复延迟:节点宕机后,主节点默认等待
index.unassigned.node_left.delayed_timeout(默认 1m)才重新分配,期间分片显示未分配。 - 分片数超过节点承载上限:
cluster.max_shards_per_node或index.routing.allocation.total_shards_per_node限制被突破。 - 主分片缺失:主分片所在节点数据损坏且无副本,需要
allocate_stale_primary或reroute手动干预。
诊断的第一步永远是查看未分配原因,而不是盲目重试:
GET _cluster/allocation/explain
{
"index": "logs-2024.06",
"shard": 0,
"primary": false
}
返回结果中的 unassigned_info.reason 会直接给出 NODE_LEFT、ALLOCATION_FAILED、CLUSTER_RECOVERED 等根因,explanation 字段则逐节点说明“为什么这个节点也不行”,这是定位问题最有效的入口。
二、分配决策日志解读
主节点日志中与分配相关的关键行通常包含 ClusterApplierService、AllocationService 和 GatewayAllocator 等类名。典型日志如下:
[AllocationService] failed to allocate [logs-2024.06][2] on node [node-3],
reason [NO(disk watermark [90%] exceeded on node-3)]
解读要点:方括号中的分片标识说明是哪个索引的哪个分片;on node 指出候选节点;reason 给出拒绝原因。若日志反复出现 shard has exceeded the maximum number of retries,说明分配尝试次数已达上限,需要手动 POST _cluster/reroute?retry_failed=true 重置重试计数。
三、再平衡阈值调优
再平衡由三个阈值控制,它们决定“节点间分片数量差多少才触发搬动”:
| 参数 | 默认值 | 作用 |
|---|---|---|
cluster.routing.allocation.balance.shard | 0.45 | 分片数量均衡权重 |
cluster.routing.allocation.balance.index | 0.55 | 每索引分片均衡权重 |
cluster.routing.allocation.balance.threshold | 1.0 | 触发再平衡的最小权重差 |
当集群节点数多、分片数少时,默认阈值可能导致频繁小幅搬动,增加恢复压力。此时可适当调大 threshold(如 1.5~2.0),让集群容忍更大的不均衡,减少无谓迁移。反之,若希望更均匀,可调小该值,但要接受更高的网络与 IO 开销。调优后建议用 GET _cat/allocation?v 观察各节点 shards 列的差值是否收敛到可接受范围。
四、磁盘水位线触发场景与恢复
磁盘水位线是生产环境最常见的分配阻塞源。默认三档:低水位线 85%、高水位线 90%、洪水水位线 95%。触发逻辑如下:
恢复操作按优先级排列:
- 清理磁盘:删除过期索引、执行
POST /index/_forcemerge?only_expunge_deletes=true回收被删除文档空间,或迁移冷数据到对象存储。 - 临时放宽水位线:在紧急情况下可动态调整,例如
PUT _cluster/settings {"transient":{"cluster.routing.allocation.disk.watermark.low":"90%","cluster.routing.allocation.disk.watermark.high":"95%"}},但必须同步扩容,否则只是推迟问题。 - 扩容数据节点:新增节点后,主节点会自动把分片迁往新节点,观察
_cat/recovery确认迁移完成。 - 手动重路由:当自动分配失败时,用
POST _cluster/reroute指定move或allocate_replica,并配合retry_failed=true清除失败计数。
GET _cat/allocation?v 查看 disk.percent 列。index.blocks.read_only_allow_delete)。即使磁盘清理后,该块也不会自动解除,需要手动执行 PUT /index/_settings {"index.blocks.read_only_allow_delete": null}。综合来看,分片分配故障的诊断路径是:先用 _cluster/allocation/explain 拿到根因,再对照水位线、过滤规则、节点数量三类条件逐一排除,最后通过清理、扩容或重路由恢复。再平衡阈值调优属于预防性手段,应在集群稳定期小步调整并持续观察,而不是在故障中临时大改。