土法炼钢兴趣小组的算法知识备份

【全文检索引擎】生产排障:breaker、refresh、分片、慢查询

文章导航

分类入口
databasestorage
标签入口
#elasticsearch#lucene#troubleshooting#circuit-breaker#refresh#shards#explain#full-text-search

目录

平台工程师最常听到的抱怨是「ES 又红了」:有时是写入被拒绝,有时是搜索超时,有时是 heap 持续高位却查不到明显慢查询。第一反应往往是加机器或调 refresh_interval,但若没把症状对应到 breaker、Segment 数量、mapping 字段数、分片元数据开销 中的哪一层,调参容易南辕北辙。本文用一张 症状→机制 决策树把「感觉不对」翻译成「该看本系列哪一篇、哪个 API」,再展开五类高频故障的检查单。不含未跑的千节点集群数字

本文是「全文检索引擎」系列第 17 篇(共 18 篇)。→ 系列目录

版本锚定:Elasticsearch 8.x Circuit breakerFix common cluster issues;机制结论回链本系列第 7–14 篇。


一、先分清四种「不好」

症状标签 可能机制 优先篇章
写入拒绝 / 429 circuit breaker、translog 压力、磁盘 watermark 12、本节二
搜索慢 / 超时 分片过多、大字段 fetch、聚合 fielddata、DFS 10、11、13、本节五
heap 高 / OOM 段过多、fielddata、聚合超内存 breaker 7–8、14、本节二
结果不对 / 不全 refresh 窗口、软删未 merge、分片路由错误 7–8、12、11

四类可叠加:例如 refresh_interval 过短同时推高 CPU 与段数,表现为 又慢又占内存——决策树先定主因,再合并次要因素。


二、症状 → 机制决策树

flowchart TD
  symptom["Observed symptom?"]

  symptom -->|"write rejected / 429"| writeGate{"breaker type in logs?"}
  writeGate -->|"parent / request"| aggIssue["Aggregation or huge query buffer<br/>见第 14 篇, 调小 size / 用 DV"]
  writeGate -->|"fielddata"| fdIssue["text field used for agg/sort<br/>改 keyword + doc_values"]
  writeGate -->|"no breaker, disk"| diskIssue["disk watermark / flood stage<br/>删索引或扩盘"]

  symptom -->|"heap high steady"| heapGate{"many small segments?"}
  heapGate -->|"yes"| refreshIssue["refresh too frequent or bulk too small<br/>见第 12、7 篇"]
  heapGate -->|"no"| mappingGate{"field count exploding?"}
  mappingGate -->|"yes"| mapIssue["dynamic mapping explosion<br/>见第 14 篇"]
  mappingGate -->|"no"| shardGate{"shard count >> data size?"}

  symptom -->|"search slow"| slowGate{"_search slow log shows fetch?"}
  slowGate -->|"fetch dominates"| fetchIssue["stored fields / _source huge<br/>见第 10 篇, source filtering"]
  slowGate -->|"query dominates"| queryIssue["too many shards or heavy agg<br/>见第 11、13 篇"]
  slowGate -->|"only some queries"| explainPath["run profile + explain<br/>本节五"]

  symptom -->|"missing recent docs"| nrtGate{"refresh_interval?"}
  nrtGate -->|"default 1s ok but still miss"| replicaIssue["routing / wrong index / alias<br/>见第 11 篇"]
  nrtGate -->|"set -1 manual refresh"| visIssue["expected NRT delay<br/>见第 12 篇"]

  shardGate -->|"yes"| shardIssue["shard overhead > query parallelism gain<br/>见第 11 篇, architecture/42"]

图的作用是把排查 分层:heap 高且段很多时,先查 refresh 与 bulk 批次,而不是先调 BM25 参数(第 6 篇)。


三、circuit breaker:JVM 里的硬顶

Elasticsearch 用 circuit breaker 限制单次请求或子系统可申请的堆内存,防止 OOM 拖垮整个节点。官方文档列出的常见类型包括(名称以 8.x Reference 为准):

Breaker 典型触发场景 机制回链
parent 子 breaker 总和逼近上限 全局保险丝
request 单查询聚合桶过多、terms size 过大 第 14 篇聚合
fielddata text 字段排序/聚合(旧路径) 应用 keyword + doc_values
in_flight_requests 并发搜索过多 客户端限流

检查单

  1. 读节点日志中的 CircuitBreakingExceptionbreaker 名称
  2. 对聚合查询检查 sizeshard_size、是否 composite 分页(第 14 篇)。
  3. 禁止对 analyzed text 做聚合;mapping 审查用 _field_caps 或 index mapping API。
  4. 临时缓解 不等于 根因修复:调大 breaker 限额只推迟 OOM(Elastic 文档明确 breaker 目的是保护节点)。
sequenceDiagram
  participant C as Client
  participant N as Data node
  participant CB as Circuit breaker
  C->>N: search with huge terms agg
  N->>CB: estimate heap for buckets
  alt over limit
    CB-->>C: 429 CircuitBreakingException
  else ok
    N-->>C: response
  end

四、refresh 过频:可搜性与段爆炸的交换

refresh 使内存中新 Segment 对搜索可见(第 12 篇), 等价于 fsync 持久化。默认 refresh_interval 为 1s 适合近实时搜索,但在 高写入 场景会导致:

场景 建议方向 风险
日志批量导入 写入期 refresh_interval=-1,结束后恢复 导入期不可搜
搜索 SLA 秒级 保持 1s 或 wait_for 有控刷新 段数上升
只读索引 停止 refresh,force merge 后封存 失去 NRT

症状:merge 线程池队列长、段数监控持续升、查询延迟随写入波动。对照第 8 篇 merge 与第 12 篇三者矩阵,勿用缩短 refresh 来「解决」写入慢——往往适得其反。


五、大字段与 mapping 爆炸

5.1 大字段

5.2 动态 mapping 爆炸

动态模板在 JSON 日志场景下可为每个新键建字段——字段数可达千级,cluster state 与 每个段 的元数据成本上升。第 14 篇已述失效模式;排障时:

  1. GET index/_mapping 看字段数增长曲线。
  2. dynamic: falsestrict、runtime field 替代随意建列。
  3. 区分 搜索字段仅存储字段enabled: false 对象)。

六、分片过多:并行度变负资产

每个分片是一个完整 Lucene 索引,自带:

architecture/42 讲过「shard 过多」的架构陷阱;机制层补充:单分片数据量过小 时,并行收益抵不过固定开销。经验性工程判断(非 benchmark):许多团队以 每分片 tens of GB 级 为规划起点,须按数据量、heap、查询并发 重算——具体数字随版本与硬件变化,本文不给虚假最优 shard 数。

检查


七、慢查询:profile 与 explain

7.1 工具分工

API 回答什么
profile: true 时间花在哪个查询子句、哪个 collector
explain 某文档 BM25 分量(第 6 篇 IDF/TF/norm)
Slow search log 生产长尾样本

教学示例(须在真实集群对 小索引 执行;以下为 DSL 形态,非伪造输出):

GET my-index/_search
{
  "profile": true,
  "query": { "match": { "body": "circuit breaker" } },
  "size": 5
}
GET my-index/_explain/doc-id
{
  "query": { "match": { "body": "circuit breaker" } }
}

读 profile:若 match 子句耗时高,回第 5、9 篇看 postings 与词项频率;若 fetch 高,回第 10 篇 _source;若 knn 高,外链 vector-engine 调参,不在此复述 HNSW。

7.2 与第 13 篇查询路径对照

协调节点时间 = 路由 + 分片并行 query + fetch + reduce。DFS 全局词频(可选)增加一轮往返——高基数字段上 IDF 更准,但 慢查询日志 里会出现额外 dfs 阶段;仅在确有评分偏差时开启。

7.3 translog 与磁盘 watermark

写入拒绝有时 不是 breaker

日志里若无 CircuitBreakingException,查 _cluster/health_cat/allocation 与节点磁盘指标。这与 architecture/42 的容量故事衔接,但 机制层 仍是 Lucene IndexWriter 无法提交 commit。

7.4 bulk 批次与 refresh 联动

现象 可能原因 动作
写入 QPS 低但 CPU 高 过小 bulk + 默认 1s refresh 增大 bulk、临时 -1 refresh
merge 拒绝 / too many segments refresh 过频 + 写入不停 降 refresh、限并发写入
导入后搜索仍慢 未 force merge 且段极多 评估只读索引 merge(第 8 篇代价)

八、常见误解

误解一:circuit breaker 触发说明 ES 坏了,应立刻调大限额。 Breaker 是 保护机制;应缩小聚合、改 mapping 或减并发,而非永久关闭。

误解二:refresh 越快数据越安全。 refresh 只影响 可搜;持久化靠 translog + flush(第 12 篇)。过快 refresh 损害 merge 与 heap。

误解三:慢查询就是 BM25 慢。 大量案例慢在 fetch 大 _sourceterms 聚合分片扇出,profile 一步可区分。

误解四:加副本能缓解写入 breaker。 副本分担读,但 写入仍经主分片;写入拒绝要从 bulk 批次、mapping、磁盘查。

误解五:OpenSearch 与 ES 排障完全不同。 第 16 篇:内核同源;breaker、refresh、段模型检查单 共用


九、开放问题

  1. 统一可观测模板:将 segment 数、refresh 耗时、breaker 触发、慢查询 top-N 钉在同一 Grafana 行,并与 Lucene merge 线程池关联——社区方案多,缺乏与 ES 版本绑定的单一标准。
  2. 向量 + 全文混合索引的资源隔离:第 15 篇;同一节点 kNN 与重聚合争 heap 时,仅靠 breaker 是否足够,尚无公开容量公式。
  3. 自动识别「分片过多 vs 查询写法差」:需结合慢日志与 shard 统计的启发式规则,厂商文档多为手工清单。

十、小结

三句话小结:

  1. 先用 症状→机制决策树 把问题归到写入 breaker、refresh/段、mapping/大字段、分片扇出或 NRT 可见性,再打开对应篇章,而不是统一归咎于「ES 慢」。
  2. circuit breakerrefresh 过频 是 heap 与 CPU 两侧最常见的可修复根因;profile + explain 区分 query 与 fetch 与 BM25 分量。
  3. OpenSearch 与 Elasticsearch 排障机制同构(第 16 篇);日志专属场景另见 observability/08,不在此替代。

选型与系列收束见 第 18 篇


参考资料

  1. Elasticsearch 8.x Reference, Circuit breaker settingsFix common cluster issuesProfile APIExplain API.
  2. 本系列第 7–14 篇机制结论。
  3. architecture/42 搜索架构(分片规划叙事,机制回链)。

返回 系列目录 | 上一篇:OpenSearch 与 Solr | 下一篇:选型与阅读地图

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .