Skip to content

Elasticsearch

官方文档:Elasticsearch:官方分布式搜索和分析引擎 | Elastic

Elasticsearch 常被简称为 ES。它是构建在 Lucene 之上的分布式搜索和分析引擎,商业系统里常用于商品搜索、订单检索、工单检索、日志分析、搜索建议、聚合筛选和地理位置检索。

推荐阅读顺序:

  1. 核心概念
  2. 从零到生产级掌握
  3. 从零到精通验收清单
  4. 商业场景训练营
  5. 底层原理
  6. 写入、Refresh与Segment全过程
  7. 查询Query与Fetch全过程
  8. 倒排索引、分词与BM25评分
  9. Mapping与查询
  10. 分词
  11. 同步与重建索引
  12. MySQL与ES数据一致性
  13. 集群
  14. 性能优化与排查
  15. 商业搜索场景
  16. 面试题

ES 到底是什么

可以把 ES 理解成三层能力:

层次负责什么初学者怎么理解
Lucene单机倒排索引、分词、评分、段文件真正完成搜索的底层引擎
Elasticsearch 节点REST API、索引管理、查询执行、集群通信把 Lucene 包装成可访问的服务
Elasticsearch 集群节点发现、分片、副本、故障恢复、分布式查询让搜索能扩容、高可用
mermaid
flowchart TD
    A["业务系统"] --> B["Elasticsearch REST API"]
    B --> C["协调节点"]
    C --> D["数据节点 A"]
    C --> E["数据节点 B"]
    C --> F["数据节点 C"]
    D --> G["Lucene 分片和倒排索引"]
    E --> H["Lucene 分片和倒排索引"]
    F --> I["Lucene 分片和倒排索引"]

所以 ES 不是“一个更快的 MySQL”,而是一个围绕倒排索引、文档模型、分布式分片和相关性排序设计的搜索系统。

ES 适合解决什么问题

场景示例ES 提供的能力
商品搜索“无线降噪耳机 300以内”全文检索、过滤、排序、高亮、聚合
后台订单检索状态、时间、手机号后四位、商品名多条件查询、时间范围、精确过滤
工单检索搜标题、描述、处理人、优先级文本检索、权限过滤、按 SLA 排序
日志分析traceId、错误码、接口耗时时间范围检索、聚合统计
搜索建议输入“蓝牙”提示“蓝牙耳机”前缀召回、热度排序
附近门店5km 内有货门店geo_point、距离过滤和排序

ES 不适合解决什么问题

不适合场景原因更合适的方案
支付、记账主库ES 不提供关系型数据库那种强事务模型MySQL、PostgreSQL
强一致扣库存ES 是近实时搜索,不能负责库存最终判断数据库事务、库存服务
复杂运行时 JoinES 是文档模型,不擅长临时多表 Join数据库 Join,或写入前冗余字段
高频单文档精确更新更新本质是删除旧文档再写新文档主库保存事实,ES 保存搜索副本
小数据简单查询引入 ES 会增加部署和同步成本数据库索引即可

项目里最常见的架构是:MySQL 保存主数据,ES 保存搜索视图。业务写入以数据库成功为准,再通过消息、任务或 Binlog 把数据同步到 ES。

写入和搜索流程

写入流程

mermaid
flowchart TD
    A["商品或订单变更"] --> B["业务服务写入 MySQL"]
    B --> C["发送变更消息或写入 Binlog"]
    C --> D["同步服务组装搜索文档"]
    D --> E["写入 Elasticsearch"]
    E --> F["按 Mapping 处理字段"]
    F --> G["text 字段分词"]
    G --> H["建立倒排索引"]
    F --> I["keyword、date、number 建精确索引"]
    H --> J["refresh 后可搜索"]
    I --> J

ES 是近实时搜索系统。文档写入成功后,不一定立刻被搜索到,通常要等 refresh。默认 refresh_interval 常见为 1s,所以业务上要接受短暂延迟。

查询流程

mermaid
flowchart TD
    A["用户输入关键词和筛选条件"] --> B["搜索 API 校验参数"]
    B --> C["组装 Query DSL"]
    C --> D["协调节点接收查询"]
    D --> E["分发到相关分片"]
    E --> F["每个分片本地查询和打分"]
    F --> G["协调节点合并 TopN"]
    G --> H["返回分页、高亮、聚合结果"]

查询慢时不要只怀疑 ES “性能差”。常见原因包括:分片太多、Mapping 不合理、查询 DSL 过重、深分页、聚合范围过大、磁盘水位高、JVM GC 压力大、同步写入过猛。

核心概念速览

概念类比说明
Index一类搜索视图例如 product_searchorder_search
Document一条 JSON 数据一件商品、一个订单、一条日志
Field字段productNamepricestatus
Mapping表结构加索引策略字段类型、是否分词、是否可聚合
Shard分片数据水平拆分单位
Replica副本提高可用性和查询吞吐
Analyzer分词器决定文本如何拆词
Query DSL查询语言描述怎么搜、怎么过滤、怎么排序

知识点目录

页面重点
核心概念文档、字段、Mapping、倒排索引、refresh、segment
从零到生产级掌握搜索视图、文档模型、倒排索引、写入查询、同步一致性、生产排查课程线
从零到精通验收清单用可验证任务串起定位、Mapping、倒排索引、写入查询、同步一致性、排查和面试闭环
商业场景训练营商品搜索文档、Mapping、近实时、查询快、MySQL 同步、ES 更新失败补偿、重建索引和慢查询排查
底层原理ES 为什么快、为什么近实时、写入流程、查询流程、BM25、doc values
写入、Refresh 与 Segment 全过程协调节点、主分片、副本、buffer、translog、refresh、flush、merge、更新删除成本
查询 Query 与 Fetch 全过程Query Phase、Fetch Phase、分片 TopN、深分页、filter、排序聚合高亮成本
倒排索引、分词与 BM25 评分倒排索引结构、Analyzer、text/keyword、BM25、搜不到和搜不准
Mapping 与查询字段类型、text/keywordterm/match、bool、分页、聚合
分词中文分词、索引分词、查询分词、同义词、搜不到排查
同步与重建索引MySQL 到 ES 同步、MQ/CDC、幂等、乱序、补偿、别名切换
MySQL 与 ES 数据一致性双写风险、本地消息表、CDC、幂等、乱序、补偿、对账
集群节点、分片、副本、健康状态、磁盘水位、分片规划
性能优化与排查搜不到、搜不准、查询慢、写入慢、yellow/red、JVM、热点分片
商业搜索场景商品、订单、工单、日志、搜索建议、地理位置和 Java Demo
面试题刷题复习入口,详细原理回到对应知识点页

快速启动 Demo

本地学习可以使用 Docker 快速启动单节点 ES。生产环境不要照搬这个配置。

bash
docker run --name es-dev \
  -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
  docker.elastic.co/elasticsearch/elasticsearch:8.15.0

验证:

bash
curl http://localhost:9200
curl http://localhost:9200/_cluster/health?pretty

如果访问不到,优先检查:

  1. 容器是否启动成功。
  2. 端口 9200 是否被占用。
  3. 本机内存是否足够。
  4. 是否启用了安全认证。

最小 CRUD Demo:商品索引

创建索引:

json
PUT /product_search_demo
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0,
    "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" }
    }
  }
}

写入文档:

json
PUT /product_search_demo/_doc/1001
{
  "id": 1001,
  "productName": "无线蓝牙降噪耳机 Pro",
  "brandName": "SoundMax",
  "categoryName": "耳机",
  "tags": ["蓝牙耳机", "主动降噪", "官方旗舰"],
  "price": 29900,
  "stockStatus": "IN_STOCK",
  "saleCount": 5821,
  "updatedAt": "2026-07-01T10:00:00"
}

查询文档:

json
GET /product_search_demo/_search
{
  "query": {
    "match": {
      "productName": "无线降噪耳机"
    }
  }
}

局部更新:

json
POST /product_search_demo/_update/1001
{
  "doc": {
    "price": 27900,
    "updatedAt": "2026-07-01T12:00:00"
  }
}

删除文档:

json
DELETE /product_search_demo/_doc/1001

这组命令覆盖了学习 ES 最基本的入口:建索引、写文档、查文档、局部更新、删除文档。

商业搜索索引设计思路

商品搜索索引通常包含:

字段类型建议用途
productNametext + keyword商品名全文搜索、高亮、必要时精确匹配
subTitletext卖点辅助召回
brandIdlong品牌过滤
brandNamekeyword品牌聚合展示
categoryIdlong类目过滤
tagskeyword标签过滤、运营加权
pricescaled_float价格范围、排序、聚合
stockStatuskeyword是否有货
saleCountlong销量排序
updatedAtdate同步排查和排序

不要照搬数据库表。ES 文档应该按搜索页面需要来设计,可以冗余品牌名、类目名、标签和统计字段,减少查询时再去 Join。

查询 Demo:商品搜索

json
GET /product_search_demo/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "无线降噪耳机",
            "fields": ["productName^5", "tags^2"]
          }
        }
      ],
      "filter": [
        { "term": { "stockStatus": "IN_STOCK" } },
        { "range": { "price": { "gte": 10000, "lte": 30000 } } }
      ],
      "should": [
        { "term": { "tags": { "value": "官方旗舰", "boost": 2 } } },
        { "range": { "saleCount": { "gte": 1000, "boost": 1.5 } } }
      ]
    }
  },
  "sort": [
    { "_score": "desc" },
    { "saleCount": "desc" },
    { "id": "desc" }
  ],
  "highlight": {
    "fields": {
      "productName": {}
    }
  }
}

productName^5 表示商品名命中权重更高。filter 不参与相关性打分,适合库存、品牌、类目、价格等精确条件。should 不强制命中,但命中后可以提高排序。

使用注意事项

  1. Mapping 一旦设计不当,后期修改成本较高,通常需要重建索引。
  2. 数据库仍然是主数据源,Elasticsearch 是搜索副本。
  3. 写入链路要考虑最终一致性,例如商品改价、上下架后异步同步索引。
  4. 中文搜索要选择合适分词器,并测试同义词、停用词、品牌词和型号词。
  5. 搜索接口要限制分页深度,避免深分页拖垮集群。
  6. 订单、支付、库存判断不能依赖 ES 的搜索结果,必须回到主库或对应业务服务确认。

常见误区

误区正确理解
ES 可以替代 MySQLES 做搜索副本,MySQL 仍保存事实数据
写入成功就一定马上搜到ES 是近实时搜索,受 refresh 影响
分片越多越快分片过多会增加协调和元数据成本
所有字段都用 text精确过滤、排序、聚合字段应使用 keyworddatelong 等类型
搜不到就是 ES 坏了先检查同步、分词、Mapping、查询类型和过滤条件
查询慢只能加机器先看 DSL、分片数量、慢日志、聚合和深分页

本章小结

Elasticsearch 的核心价值是:把业务数据转换成适合搜索的文档视图,通过倒排索引、分词、过滤、打分和聚合,让用户在大量数据中快速找到结果。

学习 ES 的主线不是背命令,而是理解:

  1. 数据为什么要同步到 ES。
  2. 字段为什么要这样建 Mapping。
  3. 查询为什么要区分全文搜索和精确过滤。
  4. 线上问题应该从同步、分词、Mapping、DSL、集群逐层排查。