📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

配置项作用 #

cluster.max_shards_per_node 配置项限制集群中每个数据节点允许的最大分片数量。当创建索引或打开索引时,系统会检查操作是否会导致集群超过此限制。此限制在分片创建时应用,防止集群因分片过多而变得不稳定。

配置项类型 #

该配置项为动态配置,可以在运行时通过集群设置 API 进行修改。

默认值 #

1000

是否必需 #

可选配置项(有默认值)

取值范围 #

1 ~ Integer.MAX_VALUE

工作原理 #

分片数量限制在创建索引或打开索引时进行检查:

┌─────────────────────────────────────────────────────────┐
│              创建/打开索引请求                             │
│         (number_of_shards × number_of_replicas)          │
└─────────────────────────────────────────────────────────┘
                        │
                        ▼
                ┌───────┴────────┐
                │                 │
            计算分片数        检查集群状态
                │                 │
                ▼                 ▼
        ┌───────┴────────┐   当前分片数
        │   验证限制      │        +
        │               │   新增分片数
        │ 总分片 ≤ 限制? │        =
        │               │   cluster total
        └───────┬────────┘
                │
        ┌───────┴────────┐
        │                │
      是(允许)       否(拒绝)
        │                │
        ▼                ▼
    创建/打开    ValidationException

计算公式:

集群最大分片数 = max_shards_per_node × 数据节点数量

新增分片数 = number_of_shards × (1 + number_of_replicas)

允许条件: 当前开放分片数 + 新增分片数 ≤ 集群最大分片数

配置格式 #

# 默认配置
cluster.max_shards_per_node: 1000

# 高密度分片场景
cluster.max_shards_per_node: 3000

# 保守配置
cluster.max_shards_per_node: 500

# 动态修改
PUT /_cluster/settings
{
  "persistent": {
    "cluster.max_shards_per_node": 2000
  }
}

使用示例 #

场景 1:检查是否可以创建索引

# 当前状态:
# - 数据节点:3 个
# - max_shards_per_node:1000
# - 已开放分片:2500 个
# - 集群最大分片:3 × 1000 = 3000

# 尝试创建索引(5 个主分片,1 个副本)
PUT /my_index
{
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}

# 新增分片:5 × (1 + 1) = 10
# 验证:2500 + 10 = 2510 ≤ 3000 → 允许

场景 2:超过限制被拒绝

# 当前状态:
# - 数据节点:3 个
# - max_shards_per_node:1000
# - 已开放分片:2995 个

# 尝试创建索引(10 个主分片,1 个副本)
PUT /my_index
{
  "settings": {
    "number_of_shards": 10,
    "number_of_replicas": 1
  }
}

# 新增分片:10 × (1 + 1) = 20
# 验证:2995 + 20 = 3015 > 3000 → 拒绝

# 错误信息:
# ValidationException: this action would add [20] total shards,
# but this cluster currently has [2995]/[3000] maximum shards open

推荐设置建议 #

生产环境建议:根据数据节点数量和硬件配置设置

场景每节点分片数说明
默认1000通用场景
小规模集群500-1000少量数据节点
中等规模1000-2000标准配置
大规模集群2000-3000大量小索引
超大规模3000-5000专业调优

分片数量与性能的关系 #

每节点分片数的影响:

分片数CPU 使用内存开销集群状态性能
< 500稳定优秀
500-1000稳定良好
1000-2000可能不稳定一般
> 2000很高很高容易不稳定较差

分片过多的问题:

  1. 内存开销增加:每个分片占用内存
  2. CPU 上下文切换:管理大量分片消耗 CPU
  3. 集群状态变大:影响集群管理性能
  4. 恢复时间变长:节点故障后恢复时间增加

常见问题 #

问题 1:创建索引时超过限制

ValidationException: this action would add [20] total shards,
but this cluster currently has [2995]/[3000] maximum shards open

解决方案:

  1. 增加限制
PUT /_cluster/settings
{
  "persistent": {
    "cluster.max_shards_per_node": 2000
  }
}
  1. 减少分片数
// 使用更少的分片
PUT /my_index
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
  1. 删除不需要的索引
# 删除旧索引
DELETE /old_index_*

# 关闭不用的索引
POST /unused_index/_close

问题 2:集群分片数过多

症状:

  • 集群状态更新缓慢
  • 节点响应变慢
  • 内存使用过高

解决方案:

  1. 清理旧索引
# 使用 ILM 管理索引生命周期
# 自动删除或关闭旧索引
  1. 合并小索引
# 使用 reindex 合并多个小索引
POST /_reindex
{
  "source": {
    "index": "small_index_1"
  },
  "dest": {
    "index": "merged_index"
  }
}
  1. 增加数据节点
# 水平扩展,增加数据节点
# 新节点自动分担分片

动态修改 #

# 临时修改(重启后失效)
PUT /_cluster/settings
{
  "transient": {
    "cluster.max_shards_per_node": 2000
  }
}

# 持久修改(重启后保持)
PUT /_cluster/settings
{
  "persistent": {
    "cluster.max_shards_per_node": 2000
  }
}

# 恢复默认值
PUT /_cluster/settings
{
  "transient": {
    "cluster.max_shards_per_node": null
  }
}

查看当前状态 #

# 查看当前设置
GET /_cluster/settings?flat_settings=true

# 查看集群分片统计
GET /_cat/allocation?v

# 查看每个节点的分片数
GET /_cat/shards?v&h=index,shard,node,prirep,state

# 查看集群健康和分片数
GET /_cluster/health?pretty

# 查看索引统计
GET /_cat/indices?v&h=index,pri,rep,docs.count,store.size

分片规划建议 #

1. 评估分片数量

预期数据大小 / 单分片建议大小 = 分片数

示例:
- 预期数据:100GB
- 单分片建议:20-50GB
- 分片数:100GB / 30GB ≈ 3-4 个分片

2. 分片大小建议

数据总量主分片数单分片大小
< 10GB1< 10GB
10-50GB1-210-30GB
50-100GB2-520-50GB
100-500GB5-1020-50GB
500GB-1TB10-2050-100GB
> 1TB20+50-100GB

3. 时间序列数据规划

// 使用 rollover 管理时间序列索引
PUT /_ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "30d"
          }
        }
      }
    }
  }
}

与分配限制的区别 #

配置项应用时机作用范围配置项
cluster.max_shards_per_node分片创建时整个集群创建限制
cluster.routing.allocation.enable分片分配时分配决策分配控制

注意:

  • cluster.max_shards_per_node创建索引时检查
  • 还有一个分配时的限制,由 ShardsLimitAllocationDecider 控制

监控建议 #

# 持续监控分片数量
GET /_cat/nodes?v&h=name,shards

# 计算每节点分片数
GET /_cat/allocation?v

# 设置告警
# 当每节点分片数 > 80% 限制时告警
# 当集群总开放分片数 > 90% 限制时告警

告警阈值:

指标警告严重
每节点分片数 / 限制> 80%> 95%
集群总开放分片 / 最大值> 85%> 95%

性能优化建议 #

1. 合理设置分片数

// 根据数据量设置分片数
PUT /my_index
{
  "settings": {
    "number_of_shards": 3,      // 根据数据量
    "number_of_replicas": 1     // 根据可用性需求
  }
}

2. 使用 ILM 自动管理

# 设置索引生命周期管理
# 自动删除、关闭旧索引
# 控制集群总分片数

3. 定期清理

# 创建定期清理任务
# 删除过期的日志索引
DELETE /logs-2023-01-*

注意事项 #

  1. 动态更新:此配置为动态配置,可在线修改
  2. 软限制:创建时检查,不是分配时检查
  3. 规划重要:提前规划分片数量,避免频繁调整
  4. 监控必要:建议定期监控分片数量
  5. 平衡考虑:分片数影响性能,需平衡吞吐量和资源消耗