Skip to content

Elasticsearch 集群

Elasticsearch 集群通过节点、分片和副本实现水平扩展和高可用。理解集群结构,是排查搜索慢、索引 red/yellow、分片未分配、磁盘水位和写入抖动的基础。

商业系统里,商品搜索、订单检索、日志检索对集群的要求并不一样:商品搜索更关注查询稳定性和相关性,订单检索更关注权限过滤和时间范围,日志检索更关注写入吞吐、时间滚动索引和磁盘生命周期。

为什么 ES 要拆分片和副本

单台机器的 CPU、内存、磁盘和 IO 都有限。ES 通过主分片把一个索引拆到多台机器上,从而提升容量和并行处理能力;通过副本分片复制数据,提升查询能力和故障恢复能力。

如果没有分片,数据量大了只能垂直扩容;如果没有副本,一个节点故障就可能导致数据不可用。

mermaid
flowchart TD
    A["product_search 索引"] --> B["主分片 P0"]
    A --> C["主分片 P1"]
    A --> D["主分片 P2"]
    B --> E["副本 R0"]
    C --> F["副本 R1"]
    D --> G["副本 R2"]
    E --> H["节点故障时可提升为主分片"]
    F --> H
    G --> H

集群基本结构

mermaid
flowchart TD
    A["Cluster 集群"] --> B["Master eligible 节点"]
    A --> C["Data 节点 1"]
    A --> D["Data 节点 2"]
    A --> E["Data 节点 3"]
    A --> F["Coordinating 节点"]
    F --> G["接收搜索请求并合并结果"]
    C --> H["保存分片并执行查询"]
    D --> H
    E --> H
    B --> I["管理元数据和分片分配"]

一个索引会被拆成多个主分片,每个主分片可以有多个副本分片。主分片和它自己的副本不会分配到同一个节点上,否则节点故障时副本也会一起丢失。

核心概念

概念说明
ClusterES 集群,由多个节点组成
Node一个 ES 实例
Master eligible Node有资格成为主节点,管理集群元数据
Data Node保存数据和执行查询、聚合
Coordinating Node接收请求、分发到分片、合并结果
Index逻辑索引,一类文档集合
Primary Shard主分片,负责写入
Replica Shard副本分片,提高可用性和查询能力
SegmentLucene 不可变索引文件

写入流程

mermaid
flowchart TD
    A["客户端写入文档"] --> B["协调节点接收请求"]
    B --> C["根据 _id 或 routing 计算目标分片"]
    C --> D["主分片写入"]
    D --> E["复制到副本分片"]
    E --> F["达到写入确认条件"]
    F --> G["返回写入结果"]

文档默认根据 _id 路由到某个主分片。主分片写入成功后,再复制到副本分片。

如果商品数据按店铺查询特别多,可以考虑 routing 到店铺维度,但 routing 设计不好会导致热点分片。不要为了“看起来高级”随便加 routing。

查询流程

mermaid
flowchart TD
    A["客户端查询"] --> B["协调节点"]
    B --> C["分发到相关分片"]
    C --> D["各分片本地查询 TopN"]
    D --> E["协调节点合并排序"]
    E --> F["执行 fetch 获取文档"]
    F --> G["返回结果"]

查询会分发到多个分片,协调节点负责合并结果。因此分片过多会增加协调成本。深分页时,每个分片都要返回更多候选结果,协调节点压力会明显升高。

健康状态

状态含义常见原因
Green主分片和副本都正常集群健康
Yellow主分片正常,部分副本未分配单节点副本无法分配、节点不足、磁盘水位
Red部分主分片不可用数据节点故障、磁盘问题、分片损坏

单节点开发环境出现 Yellow 很常见,因为副本不能和主分片放在同一个节点。

分片规划

分片不是越多越好。

过多分片的问题:

  1. 集群元数据变大。
  2. 查询协调成本增加。
  3. 小分片浪费资源。
  4. 恢复和迁移更慢。
  5. JVM 堆内存和文件句柄压力更大。

规划时要考虑:

问题影响
数据总量多大决定索引数量和分片大小
每天增长多少决定是否按天、按月滚动
查询是按时间还是全量决定索引拆分方式
写入吞吐多高决定 refresh、bulk、节点配置
保留多久决定 ILM 生命周期

常见建议:

  1. 商品搜索这类核心索引,分片数量要根据数据量和节点数规划,不要每天滚动。
  2. 日志索引通常按时间滚动,配合 ILM 管理生命周期。
  3. 小数据量不要拆太多分片。
  4. 分片数一旦设置,调整成本较高,要提前评估。

商品搜索和日志索引的区别

对比商品搜索日志检索
数据变化商品频繁改价、上下架、更新销量持续追加写入,较少更新
索引命名product_search_v1product_search_v2app-log-2026.07.01
查询特点关键词、过滤、排序、聚合时间范围、traceId、level、message
生命周期长期保留,重建后切别名按时间保留,过期删除或降级
优化重点相关性、分词、业务排序写入吞吐、磁盘、ILM

不要把日志索引的按天滚动模式照搬到商品搜索,也不要把商品搜索的别名重建模式照搬到海量日志。

常用排查命令

json
GET /_cluster/health
GET /_cat/nodes?v
GET /_cat/indices?v
GET /_cat/shards?v
GET /_cluster/allocation/explain
GET /_nodes/hot_threads

排查顺序:

mermaid
flowchart TD
    A["发现集群异常"] --> B["查看 _cluster/health"]
    B --> C{"状态"}
    C -- "yellow" --> D["查看未分配副本"]
    C -- "red" --> E["查看不可用主分片"]
    D --> F["检查节点数量、磁盘水位、分片规则"]
    E --> F
    F --> G["使用 allocation explain 定位原因"]
    G --> H["处理磁盘、节点、索引或分配规则"]

磁盘水位

ES 会根据磁盘使用率控制分片分配。磁盘水位过高时,分片可能无法分配,甚至索引被设置为只读。

常见处理:

  1. 清理过期索引。
  2. 扩容磁盘或增加节点。
  3. 调整 ILM 策略。
  4. 检查是否有异常大索引。
  5. 检查日志是否无限保留。

典型现象:

现象可能原因
新索引无法分配副本磁盘超过水位线
写入报只读错误flood stage 水位触发保护
集群持续 yellow副本没有合适节点可放
查询和写入都变慢磁盘 IO 压力大

写入性能优化

大量初始化数据或重建索引时,常见做法:

  1. 使用 Bulk 批量写入。
  2. 适当调大 refresh_interval,导入完成后再恢复。
  3. 根据业务可用性临时降低副本数,完成后再恢复。
  4. 控制并发,避免把集群写爆。
  5. 监控 rejected、CPU、磁盘 IO、GC。

Bulk 示例:

json
POST /_bulk
{ "index": { "_index": "product_search", "_id": "1001" } }
{ "id": 1001, "productName": "无线蓝牙耳机", "stockStatus": "IN_STOCK" }
{ "index": { "_index": "product_search", "_id": "1002" } }
{ "id": 1002, "productName": "机械键盘", "stockStatus": "IN_STOCK" }

Bulk 不是越大越好。过大的批次会增加内存压力和失败重试成本,要结合文档大小和集群能力压测。

查询性能排查

mermaid
flowchart TD
    A["查询慢"] --> B["查看慢日志"]
    B --> C["用 profile 分析 DSL"]
    C --> D["检查深分页"]
    D --> E["检查 wildcard、脚本排序、大聚合"]
    E --> F["检查分片数量和分片大小"]
    F --> G["检查 CPU、磁盘、GC、线程池拒绝"]

常见问题:

问题处理
深分页限制页数,使用 search_after
大聚合缩小时间范围,优化字段类型,控制 bucket 数
通配符慢改用分词、ngram 或搜索建议
分片太多合理规划索引,减少小分片
排序慢确认排序字段类型正确,避免脚本排序

常见问题

问题可能原因建议
单节点 yellow副本无处可放开发环境可把副本设为 0
red主分片不可用查节点、磁盘、分片分配
查询变慢分片多、查询复杂、缓存失效看慢日志和查询 DSL
写入变慢refresh 频繁、副本多、磁盘慢调整 refresh、批量写入
分片未分配磁盘水位、节点不足、规则限制allocation explain
重建索引很慢bulk 太小或太大、refresh 频繁批量调优,临时调整 refresh

小结

Elasticsearch 集群学习重点是 Node、Index、Shard、Replica、健康状态、分片规划和排障命令。

生产排障时先看 health,再看 shards 和 allocation explain;查询慢看 slowlog 和 profile;磁盘问题看水位和 ILM。分片规划要克制,过多分片会带来明显管理和查询成本。