ElasticsearchNotes

第 23 章:分片与集群架构

zjc 于 2026-01-23 发布

这是《Elasticsearch 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Elasticsearch 是分布式系统,但这不意味着“加节点就一定快”。真正决定集群能力和稳定性的,是节点角色、分片数量、分片大小、副本、分配策略和查询扇出。

本章从架构视角拆解 Elasticsearch 集群。

23.1 集群组成

一个最小生产集群通常包含:

flowchart TB
    C[Client] --> L[Load Balancer]
    L --> N1[Coordinating Node]
    N1 --> D1[Data Node 1]
    N1 --> D2[Data Node 2]
    N1 --> D3[Data Node 3]
    M1[Master-eligible 1] -. cluster state .-> N1
    M2[Master-eligible 2] -. vote .-> M1
    M3[Master-eligible 3] -. vote .-> M1

集群状态由 master 节点维护,包括索引、分片、节点、别名、模板和分配信息。cluster state 越大,发布和同步成本越高,这是“不要创建几十万小索引”的重要原因。

23.2 节点角色

查看节点:

GET /_cat/nodes?v&h=name,node.role,master,heap.percent,ram.percent,cpu,load_average,disk.used_percent

常见角色:

角色 配置 职责
master-eligible node.master: true 参与选主,维护集群状态
data node.data: true 存储分片,执行读写
data_hot node.attr.data: hot 承接高频写入和查询
data_warm node.attr.data: warm 承接较旧、低频查询
data_cold node.attr.data: cold 承接冷数据
data_content 内容数据层 常规业务索引
ingest node.ingest: true 执行 ingest pipeline
coordinating only 所有 master/data/ingest 为 false 接收请求、分发归并
machine learning node.ml: true 机器学习作业

节点角色不是越多越好。小集群可以混合部署,大集群应分离 master、data 和 coordinating,避免 master 被重查询或重写入拖垮。

23.3 Master 与选主

master-eligible 节点通过投票选出 active master。为了避免脑裂,必须满足:

master-eligible 数量 >= 2 * 失败节点数 + 1

常见选择:

节点数 最多容忍失败数 说明
1 0 无高可用,仅开发环境
2 0 一台失败就可能无法选出 master
3 1 生产最小推荐
5 2 大集群常用

master 做的事:

master 不直接执行搜索,但集群状态过大会影响所有节点。应避免:

查看当前 master:

GET /_cluster/state/master_node

查看未选举原因:

GET /_cluster/health?explain=true

23.4 分片与路由

创建索引时必须认真设置 number_of_shards,主分片数一旦创建不能直接修改:

PUT orders-v4
{
  "settings": {
    "number_of_shards": 6,
    "number_of_replicas": 1
  }
}

文档路由公式:

shard = hash(routing) % number_of_primary_shards

默认 routing 是文档 _id。这意味着:

  1. 主分片数改变后,同一文档会路由到不同分片;
  2. 不能通过 update setting 直接修改主分片数;
  3. 需要变更主分片数时,只能 reindex 到新索引;
  4. 自定义 routing 可以让同一类文档落同一分片,但可能造成数据倾斜。

23.4.1 分片不是越多越好

分片多的好处:

分片多的代价:

经验边界:

23.4.2 副本

副本解决高可用和读吞吐:

PUT orders-v4/_settings
{
  "number_of_replicas": 2
}

含义:

副本不是备份。节点损坏后副本能参与恢复,但误删除索引、错误脚本和逻辑损坏仍会同步到副本。真正的备份依赖 snapshot。

23.5 分片分配

分片分配由 master 决定。常见影响因素:

因素 说明
节点在线状态 节点离线后分片需要重新分配
磁盘水位 低磁盘水位可能阻止分配和写入
副本数 副本必须与主分片不同节点
allocation filtering 按节点属性迁移分片
awareness 机架或区域感知
shard balancing 节点间分片数量和磁盘均衡
recovery 限流 恢复速度受网络和磁盘限流控制

查看未分配原因:

GET /_cluster/allocation/explain

查看分片:

GET /_cat/shards/orders-v4?v&h=index,shard,prirep,state,docs,store,node,unassigned.reason

23.5.1 磁盘水印

常见默认值:

水位 默认 行为
low 85% 不再向该节点分配新分片
high 90% 尝试迁移该节点分片
flood_stage 95% 索引标记 read-only,阻止写入
PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%"
  }
}

如果触发 flood stage,需要先清理空间或扩容,再手动解除 read-only:

PUT /_all/_settings
{
  "index.blocks.read_only_allow_delete": null
}

解除锁只是止血,不是治理。根因通常是分片过多、保留期过长、副本过多或容量规划不足。

23.6 集群健康

GET /_cluster/health?wait_for_status=yellow&timeout=10s
状态 含义
green 主分片和副本都正常
yellow 主分片正常,至少一个副本未分配
red 至少一个主分片不可用

查看具体问题:

GET /_cat/indices?v&health=red
GET /_cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason
GET /_cluster/allocation/explain

yellow 不一定立刻影响查询,但表示高可用受损。red 则表示部分数据不可读写,应按索引和分片定位。

23.7 冷热架构

日志和指标类数据常用冷热分层:

node.attr.data: hot
node.roles: [data_hot]
node.attr.data: warm
node.roles: [data_warm]

索引模板可以指定层:

PUT _component_template/logs-allocate
{
  "template": {
    "settings": {
      "index.routing.allocation.include._tier_preference": "data_hot"
    }
  }
}

Hot 节点:

Warm 节点:

Cold 节点:

分层的关键是数据时间边界清晰,并且 ILM 能自动 rollover 和迁移。

23.8 查询扇出

一次搜索请求默认会路由到每个涉及索引的每个分片,每个分片再选择一个主或副本副本执行。

6 个索引 x 10 主分片 x 1 副本 = 60 个目标分片

查询扇出过大时:

治理方式:

23.9 扩容方式

Elasticsearch 扩容分两类:

23.9.1 增加副本

适合读压力大、数据量不变的场景。副本增加会提高磁盘占用和写入成本。

23.9.2 增加数据节点

适合磁盘或 CPU 压力大。已有主分片数不变,但集群会重新平衡分片。

如果主分片数太少,例如只有 1 个,增加节点无法让写入并行拆分,只能通过 reindex 新建更多分片。

扩容步骤:

  1. 确认瓶颈是磁盘、CPU、页缓存、IO 还是查询扇出;
  2. 预估新节点后的分片分布;
  3. 调整 allocation 限流,避免恢复打满网络;
  4. 低峰加入节点;
  5. 观察恢复速度、磁盘水位和查询延迟;
  6. 确认未出现新热点节点。

临时禁用分配:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": "none"
  }
}

恢复分配:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": null
  }
}

23.10 架构设计检查清单

本章小结

分片架构决定了 Elasticsearch 的容量上限和故障行为。主分片数一旦确定就难以修改,分片过多会放大查询扇出和集群状态成本,分片过少又会限制并行度和恢复能力。生产设计要从数据增长、查询模式、副本目标和运维成本四方面同时评估。

思考题

  1. 为什么主分片数不能通过设置直接修改?
  2. 3 个 master-eligible 节点和 2 个节点有什么本质差别?
  3. yellow 和 red 分别代表什么风险?
  4. 什么情况下增加副本有效,什么情况下应该 reindex?
  5. 查询 30 天日志很慢,分片架构上有哪些可能原因?