Skip to content

Elasticsearch 从零到精通验收清单

这页用来回答:ES 文档是不是只讲了“倒排索引、分词、近实时”几个词,还是能让零基础真正理解搜索系统怎么设计、怎么同步、怎么排查?

学完 Elasticsearch 不能只会说“ES 查询快”。你要能解释为什么快、为什么近实时、为什么写入成功后搜不到、为什么 Mapping 改错要重建、为什么深分页慢、为什么 MySQL 和 ES 会不一致、ES 更新失败后怎么补偿。

最终目标

学完 ES 专栏后,你至少要能做到:

  1. 判断一个业务查询是否适合 ES,而不是所有查询都丢给 ES。
  2. 根据搜索页面设计文档模型和 Mapping,而不是照搬数据库表。
  3. 解释倒排索引、分词、term dictionary、posting list、BM25 的作用。
  4. 解释写入、refresh、segment、translog、flush、merge 的全过程。
  5. 解释 Query Phase、Fetch Phase、分片并行、协调节点合并 TopN。
  6. 解释 textkeywordtermmatchmustfilter 的区别。
  7. 设计 MySQL 到 ES 的同步链路,处理重复、乱序、失败、补偿和重建。
  8. 排查搜不到、搜不准、查询慢、写入慢、yellow/red、磁盘水位和 JVM 压力。
  9. 用别名完成不停机重建索引。
  10. 面试时标准回答在面试页,追问原理能跳回知识点页展开。

总路线

mermaid
flowchart TD
    A["阶段 1<br/>ES 定位和适用场景"] --> B["阶段 2<br/>文档模型和 Mapping"]
    B --> C["阶段 3<br/>倒排索引和分词"]
    C --> D["阶段 4<br/>写入、Refresh、Segment"]
    D --> E["阶段 5<br/>查询 Query / Fetch"]
    E --> F["阶段 6<br/>集群、分片、副本"]
    F --> G["阶段 7<br/>MySQL 同步和一致性"]
    G --> H["阶段 8<br/>性能优化和排查"]
    H --> I["阶段 9<br/>商业场景和面试"]

为什么要这样学?

阶段原因如果跳过
先学定位ES 是搜索视图,不是事务主库拿 ES 做库存、支付判断
再学文档ES 按文档检索,不擅长临时 Join索引照搬数据库表,查询复杂又慢
再学倒排查询快的核心在倒排索引只会说“ES 快”
再学写入近实时、更新成本、refresh 都在这里写入成功搜不到不会解释
再学查询慢查询、深分页、聚合都在查询链路里查询慢只会加机器
再学集群生产一定涉及分片副本和健康状态yellow/red、未分配分片不会处理
再学同步ES 常和 MySQL 搭配数据不一致、更新失败没补偿
最后排查生产问题是多机制叠加搜不到、搜不准、慢查询无证据链

阶段 1:ES 定位和适用场景

ES 是搜索和分析引擎,通常保存面向搜索的冗余视图。

mermaid
flowchart TD
    A["业务数据"] --> B["MySQL / PostgreSQL<br/>事实源"]
    B --> C["消息 / CDC / 任务同步"]
    C --> D["Elasticsearch<br/>搜索视图"]
    D --> E["全文检索、筛选、排序、聚合、高亮"]

适合

场景为什么适合
商品搜索全文检索、筛选、排序、聚合、高亮
订单后台检索多条件、时间范围、手机号、商品名
工单搜索标题、描述、处理人、状态、SLA
日志分析时间范围、traceId、错误码、耗时聚合
搜索建议前缀召回、热度排序
医疗资产检索字段名、表名、标签、批次、机构检索

不适合

不适合原因替代
支付主库缺少关系库强事务MySQL / PostgreSQL
强一致库存判断ES 近实时,可能旧值库存服务 + 数据库事务
高频单字段更新更新本质是删除旧文档再写新文档主库保存事实,ES 异步同步
临时多表 JoinES 文档模型不擅长运行时 Join写入前冗余,或数据库查询
小数据简单条件查询引入 ES 成本高数据库索引即可

验收问题:

  1. 为什么 ES 不能替代 MySQL?
  2. 为什么详情页关键状态通常要回源主库?
  3. 为什么 ES 适合搜索,不适合强一致交易?

阶段 2:文档模型和 Mapping

ES 不是把数据库每张表建成一个索引,而是按搜索页面设计文档。

mermaid
flowchart TD
    A["搜索页面需要展示和筛选什么"] --> B["确定搜索文档字段"]
    B --> C["冗余品牌、类目、标签、状态"]
    C --> D["设计 Mapping"]
    D --> E["按字段用途选择 text / keyword / date / number"]

商品搜索文档 Demo

json
PUT /product_search_v1
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "1s"
  },
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "id": { "type": "long" },
      "productName": {
        "type": "text",
        "analyzer": "standard",
        "fields": {
          "keyword": { "type": "keyword", "ignore_above": 256 }
        }
      },
      "brandName": { "type": "keyword" },
      "categoryName": { "type": "keyword" },
      "tags": { "type": "keyword" },
      "price": { "type": "scaled_float", "scaling_factor": 100 },
      "stockStatus": { "type": "keyword" },
      "saleCount": { "type": "long" },
      "updatedAt": { "type": "date" }
    }
  }
}

字段类型验收

字段用途推荐类型原因
全文检索text会分词,用于 match 查询
精确过滤keyword不分词,用于 term/filter
排序聚合keyword、数值、日期有 doc values
金额scaled_float 或 long 分避免浮点误差
时间date范围查询和排序
描述大字段可关闭部分索引或只用于展示避免索引膨胀

验收问题:

  1. textkeyword 区别是什么?
  2. 为什么 Mapping 改错通常要重建索引?
  3. 为什么生产建议显式 Mapping 和 dynamic: strict
  4. 为什么聚合排序字段不要直接用 text

阶段 3:倒排索引和分词

倒排索引是“词 -> 文档”的映射。

mermaid
flowchart TD
    A["文档:无线蓝牙降噪耳机"] --> B["Analyzer 分词"]
    B --> C["无线"]
    B --> D["蓝牙"]
    B --> E["降噪"]
    B --> F["耳机"]
    C --> G["Posting List: doc1, doc8"]
    D --> H["Posting List: doc1, doc3"]
    E --> I["Posting List: doc1, doc9"]

查询时不再逐行扫描商品名,而是按词找到候选文档,再合并、评分、排序。

为什么 ES 查询快

机制作用
term dictionary快速定位词
posting list找到包含该词的文档
skip list / bitset加速跳跃和过滤
BM25根据词频、逆文档频率、字段长度评分
doc values支撑排序和聚合
分片并行多个分片同时查,协调节点合并

但 ES 不是任何查询都快。深分页、大聚合、脚本排序、前缀通配、大 _source、分片过多都可能很慢。

term 和 match

查询是否分析查询词适合
term不分析keyword、ID、状态、枚举
match分析text 全文检索

验收问题:

  1. 为什么 termtext 整句话可能搜不到?
  2. 索引分词和查询分词为什么必须配合?
  3. BM25 为什么会影响排序?
  4. 为什么同义词改动后可能要重建或重开索引?

详细看:倒排索引、分词与 BM25 评分

阶段 4:写入、Refresh、Segment

ES 写入成功不等于立刻可搜索。

mermaid
flowchart TD
    A["客户端写入文档"] --> B["协调节点路由到主分片"]
    B --> C["主分片写入内存 buffer"]
    C --> D["写 translog"]
    D --> E["复制到副本分片"]
    E --> F["返回写入成功"]
    C --> G["refresh 生成可搜索 segment"]
    G --> H["查询可以搜到新文档"]

refresh、flush、merge

机制做什么解决什么
refresh内存 buffer 生成可搜索 segment让新文档能被搜索
flushLucene commit,裁剪 translog崩溃恢复边界
merge小 segment 合并成大 segment清理删除标记、减少查询开销

更新为什么成本高

Lucene segment 不可变,更新不是原地修改:

mermaid
flowchart TD
    A["更新文档"] --> B["旧文档打删除标记"]
    B --> C["写入新版本文档"]
    C --> D["refresh 后新版本可见"]
    D --> E["merge 时清理旧版本"]

所以高频更新字段,比如库存实时扣减,不适合把 ES 当最终判断来源。

验收问题:

  1. 为什么 ES 叫近实时搜索?
  2. 写入成功但搜不到,第一步判断什么?
  3. refresh_interval 调小有什么代价?
  4. update 为什么不是原地修改?

详细看:写入、Refresh 与 Segment 全过程

阶段 5:查询 Query / Fetch

ES 分布式查询通常分 Query Phase 和 Fetch Phase。

mermaid
flowchart TD
    A["客户端搜索请求"] --> B["协调节点"]
    B --> C["分发到相关分片"]
    C --> D["各分片 Query Phase<br/>召回、过滤、评分、排序 TopN"]
    D --> E["协调节点合并全局 TopN"]
    E --> F["Fetch Phase<br/>拉取 _source、高亮、返回字段"]
    F --> G["返回结果"]

Query 慢和 Fetch 慢

慢的位置常见原因
Query 慢候选集大、wildcard、script、深分页、大聚合、分片多
Fetch 慢_source 大、高亮重、返回字段多、inner_hits

深分页为什么慢

from + size 很大时,每个分片都要取大量候选结果,协调节点合并后再丢弃前面的。

text
from = 100000
size = 20
5 个分片各自可能要准备 100020 条候选
协调节点合并后丢掉前 100000 条

优化方向:

  1. 限制最大页数。
  2. 使用 search_after
  3. 使用 PIT 保持分页视图。
  4. 改成按时间、ID、业务游标翻页。

详细看:查询 Query 与 Fetch 全过程

阶段 6:集群、分片、副本

分片是容量和并行查询单位,副本是高可用和查询吞吐保障。

mermaid
flowchart TD
    A["Index"] --> B["Primary Shard 0"]
    A --> C["Primary Shard 1"]
    A --> D["Primary Shard 2"]
    B --> E["Replica 0"]
    C --> F["Replica 1"]
    D --> G["Replica 2"]

分片不是越多越好

分片过少分片过多
单分片太大,迁移恢复慢元数据、文件句柄、协调成本高
并行度不足每次查询扇出过大
扩容不灵活小分片太多浪费资源

yellow / red

状态含义处理
green主分片和副本都正常正常
yellow主分片正常,部分副本未分配查节点数、磁盘水位、分配规则
red部分主分片不可用优先恢复主分片和数据

详细看:集群

阶段 7:MySQL 同步和一致性

商业系统常见架构:MySQL 是事实源,ES 是搜索视图。

mermaid
flowchart TD
    A["业务写 MySQL"] --> B["事务提交"]
    B --> C["发送 MQ 或产生 Binlog"]
    C --> D["同步服务消费事件"]
    D --> E["按 ID 回查 MySQL 最新快照"]
    E --> F["组装 ES 文档"]
    F --> G["upsert 到 ES"]
    G --> H{"是否成功"}
    H -- "成功" --> I["记录同步成功"]
    H -- "失败" --> J["重试、死信、补偿"]

为什么消息里常只放 ID

  1. 消息更小。
  2. 避免旧消息携带旧字段覆盖新数据。
  3. 搜索文档可能来自多张表,消费端需要组装最新快照。
  4. 失败重试时仍能拿到主库最新状态。

ES 更新失败怎么办

失败类型处理
网络超时幂等重试,不能假定失败或成功
ES 线程池拒绝退避重试,降低并发
磁盘只读处理磁盘水位,解除只读后重放
Mapping 冲突修正数据或 Mapping,必要时重建索引
文档太大拆字段、清理无用字段
多次失败死信、告警、人工修复、补偿扫描

不能因为 ES 更新失败就回滚 MySQL 主事务。主库已经成功时,应让搜索视图通过重试、死信、补偿、对账最终追上。

详细看:MySQL 与 ES 数据一致性

阶段 8:性能优化和排查

搜不到排查

mermaid
flowchart TD
    A["用户搜不到"] --> B["查 MySQL 是否有数据"]
    B --> C{"主库有吗"}
    C -- "没有" --> D["业务数据本身不存在"]
    C -- "有" --> E["按 ID 查 ES"]
    E --> F{"ES 有文档吗"}
    F -- "没有" --> G["查同步链路、MQ、CDC、死信"]
    F -- "有" --> H["查 Mapping、分词、DSL、filter、权限"]

查询慢排查

证据看什么
最终 DSL是否有深分页、wildcard、script、大聚合
slowlogQuery 慢还是 Fetch 慢
profile慢在哪个 query、哪个分片
_source返回字段是否过大
分片数是否过多、是否热点分片
thread poolsearch/write rejected
JVMheap、GC、circuit breaker
磁盘水位、IO、只读块

搜不准排查

  1. _analyze 看索引分词和查询分词。
  2. _explain 看评分原因。
  3. 检查 mustshouldfilter 是否设计合理。
  4. 检查字段 boost、业务排序、销量/时间权重。
  5. 检查同义词、停用词、品牌词、型号词。

详细看:性能优化与排查

阶段 9:商业场景验收

商品搜索

必须做到:

  1. 文档按页面设计,不照搬商品表。
  2. 商品名 text + keyword 子字段。
  3. 品牌、类目、状态用 keyword filter。
  4. 价格、销量、更新时间用于排序和聚合。
  5. 下单价格和库存回源主库或商品服务校验。

订单检索

必须做到:

  1. 租户、用户权限、时间范围必须服务端强制 filter。
  2. 手机号、订单号、状态用精确查询。
  3. 商品名、备注可全文检索。
  4. 列表稳定排序,避免深分页。
  5. 订单详情和支付状态以主库为准。

医疗数据采集与资产平台

必须做到:

  1. MySQL 保存采集批次、资产、字段、血缘、治理结果。
  2. ES 保存面向检索的资产搜索文档。
  3. 文档冗余表名、字段名、中文名、标签、机构、批次、状态。
  4. 通过 MQ/CDC 同步,失败进死信和补偿。
  5. 查询侧统一加租户、机构、权限 filter。

面试闭环

高频问题标准回答深入原理
ES 是什么ES 面试ES 总览
ES 为什么快ES 面试倒排索引与 BM25
ES 为什么近实时ES 面试写入 Refresh 与 Segment
text 和 keywordES 面试Mapping 与查询
term 和 matchES 面试倒排索引与 BM25
Query / FetchES 面试查询 Query 与 Fetch
MySQL 与 ES 一致性ES 面试MySQL 与 ES 一致性
ES 更新失败怎么办ES 面试MySQL 与 ES 一致性
查询慢怎么排查ES 面试性能优化与排查

最终验收题

问题合格标准
ES 能否替代 MySQL能说清事实源和搜索视图区别
文档模型怎么设计能按搜索页面冗余字段
Mapping 怎么设计能区分 text、keyword、date、number
ES 为什么快能讲 term dictionary、posting list、filter、doc values
为什么近实时能讲 buffer、translog、refresh、segment
更新为什么成本高能讲删除标记、新文档、merge
深分页为什么慢能讲各分片 TopN 和协调节点丢弃
MySQL 如何同步 ES能讲 MQ/CDC、回查主库、幂等、补偿
ES 更新失败怎么办能讲重试、死信、告警、补偿、重建
查询慢怎么排查能按 DSL、slowlog、profile、分片、JVM、磁盘排查

本章小结

真正学会 ES,不是会背“倒排索引”和“近实时”,而是能把搜索业务建模、Mapping、分词、倒排索引、写入 refresh、查询 query/fetch、分片副本、MySQL 同步、重建索引、性能排查串成闭环。

如果某个问题讲不清,就回到对应知识点页看流程图、Demo 和商业场景。ES 的难点不是 API,而是搜索视图设计、最终一致性和生产排查证据链。