Elasticsearch 的分片分配策略(Shard Allocation)是怎样的?
Elasticsearch 的分片分配(Shard Allocation)是将索引的分片(包括主分片和副本分片)分配给集群中节点的过程。这个过程由 Master 节点 负责执行。
分片分配的目标是:负载均衡、高可用性(避免单点故障)以及遵守用户定义的规则。
以下是 Elasticsearch 分片分配策略的核心机制、触发场景及关键配置详解:
1. 什么时候触发分片分配?
分片分配通常在以下几种场景下触发:
- 索引创建时:Master 节点决定主分片放在哪些节点上。
- 节点加入集群时:为了平衡负载,Master 可能会将部分分片从现有节点移动到新节点。
- 节点离开集群(或故障)时:
- Master 会将丢失的主分片对应的副本分片提升为主分片。
- Master 会重新分配缺失的副本分片到其他健康节点,以恢复副本数量。
- 手动执行 Reroute:管理员通过 API 强制移动分片。
- 磁盘空间达到阈值:当节点磁盘不足时,ES 会尝试移走分片。
- 更新副本数:增加
number_of_replicas时,需要分配新的副本。
2. 核心分配原则(Allocation Deciders)
Elasticsearch 内部有一系列“决策者”(Deciders),它们会依次检查每个分片是否可以分配给特定节点。如果任何一个决策者说“不”,分片就不会分配给该节点。
A. 硬性规则(必须遵守)
- 同分片互斥(Same Shard Allocation):
- 规则:同一个分片的主分片(Primary)和副本分片(Replica)绝对不能分配在同一个节点上。
- 目的:防止节点宕机导致数据彻底丢失。
- 版本兼容性:
- 主分片所在的节点版本不能高于副本分片所在的节点版本(主要在滚动升级时起作用)。
B. 资源限制规则
- 磁盘水位线(Disk-based Shard Allocation):
- ES 会根据磁盘使用率决定是否分配分片。
cluster.routing.allocation.disk.watermark.low(默认 85%):超过此值,不再向该节点分配新分片。cluster.routing.allocation.disk.watermark.high(默认 90%):超过此值,开始将该节点上的现有分片迁移走。cluster.routing.allocation.disk.watermark.flood_stage(默认 95%):超过此值,强制将索引设为只读(read-only),防止磁盘被写满。
- 分片数量限制:
cluster.routing.allocation.total_shards_per_node:限制每个节点允许的总分片数。
C. 用户自定义规则(高级策略)
- 分片感知(Shard Allocation Awareness):
- 用于跨机架、跨可用区(Zone)部署。
- 配置
cluster.routing.allocation.awareness.attributes: rack_id,ES 会尽量将主分片和副本分片分配在不同的rack_id上,以防机架断电导致数据不可用。
- 分片过滤(Shard Allocation Filtering):
- 这是实现 冷热数据架构(Hot-Warm Architecture) 的核心。
- 通过给节点打标签(如
node.attr.box_type: hot),然后在索引设置中指定index.routing.allocation.require.box_type: hot,强制该索引的分片只能去热节点。
3. 负载均衡策略(Rebalancing)
当集群状态稳定,且没有违反上述硬性规则时,ES 会尝试通过移动分片来平衡集群负载。
ES 使用一个权重算法来计算节点的负载,主要考虑以下因子(通过 cluster.routing.allocation.balance.* 配置):
index(默认 0.55):每个节点上特定索引的分片数量。ES 试图让同一个索引的分片均匀分布在所有节点。node(默认 0.45):每个节点上的分片总数。ES 试图让所有节点的分片总数大致相等。threshold(默认 1.0):平衡操作的阈值。只有当移动分片带来的优化权重超过这个值时,才会触发移动,避免过于频繁的抖动。
4. 关键配置与运维操作
在生产环境中,我们经常需要调整以下配置来控制分配行为:
A. 全局开关(维护时常用)
当你需要重启节点进行维护时,为了防止 ES 疯狂地重新复制数据(Rebalancing),通常会临时禁用分配:
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.enable": "primaries"
}
}
all(默认): 允许所有分配。primaries: 只允许分配主分片(保证读写,但不恢复副本)。new_primaries: 只允许分配新建索引的主分片。none: 禁止任何分片分配。
维护结束后,记得改回 all。
B. 限流(Throttling)
为了防止分片恢复/迁移占用过多的网络带宽和磁盘 I/O,影响正常业务:
cluster.routing.allocation.node_concurrent_recoveries(默认 2): 允许每个节点同时进行多少个分片的恢复任务。indices.recovery.max_bytes_per_sec(默认 40mb): 限制恢复时的传输速率。
C. 延迟分配(Delayed Allocation)
当节点短暂离线(如重启)时,不希望立即触发副本重建(因为节点马上就回来了)。
PUT /<index_name>/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
这意味着节点掉线 5 分钟内,ES 不会重新分配该节点上的副本,等待其回归。
5. 排查分片未分配问题(Troubleshooting)
如果集群状态变黄(Yellow)或红(Red),说明有分片未分配。最强大的排查工具是 Allocation Explain API。
命令:
GET /_cluster/allocation/explain
返回结果示例分析:
ES 会明确告诉你为什么某个分片处于 UNASSIGNED 状态。常见的理由包括:
CLUSTER_RECOVERED: 集群刚启动,正在恢复中。ALLOCATION_FAILED: 之前的分配尝试失败了(如磁盘坏了)。- Decider 拒绝理由:
DISK_THRESHOLD_DECIDER: 磁盘满了。SAME_SHARD_ALLOCATION_DECIDER: 找不到其他机器放副本(例如只有 1 个节点,却设置了 1 个副本)。FILTER_ALLOCATION_DECIDER: 标签不匹配(如指定了不存在的节点标签)。
总结
Elasticsearch 的分片分配策略是一个多层级的决策过程:
- 安全第一:先确保不违反同分片互斥、磁盘水位等硬性限制。
- 用户规则:遵守冷热分离、机架感知等自定义配置。
- 负载均衡:最后通过算法让分片在节点间分布得尽可能均匀。
理解这个机制对于设计高可用架构(如多 AZ 部署)和解决集群 Yellow/Red 状态至关重要。