Appearance
Elasticsearch 是什么?
大家好,这篇我们来聊 Elasticsearch,后面简称 ES。
很多同学第一次接触 ES,容易把它当成一个“更快的数据库”。这个理解只对了一半。ES 确实能存 JSON 文档,也能通过 HTTP API 查询数据,但它真正擅长的是搜索和分析,尤其是全文检索、组合过滤、聚合统计和相关性排序。
ES 适合解决什么问题?
我们先看几个典型场景:
- 电商里搜索“苹果手机 256G”,要能搜到标题、品牌、类目、标签里相关的商品。
- 日志平台里按服务名、错误码、时间范围过滤,再对错误数量做聚合统计。
- 内容系统里按关键词召回文章,并根据时间、标签权重、点击量重新排序。
- 地图或门店系统里按城市、距离、营业状态筛选结果。
这些需求的共同点是:查询条件多,字段类型多,经常既要“过滤”,又要“排序”,还要算“相关度”。这就是 ES 发光的地方。
但 ES 不适合作为强事务数据库使用。它不提供 MySQL 那样的多行事务能力,也不适合频繁地对同一批数据做复杂关联更新。如果数据源来自业务库,常见做法是 MySQL 负责交易事实,ES 负责搜索视图。
ES 的核心概念
ES 里有几个概念经常一起出现:
- Index:索引,可以类比 MySQL 的一张表,但更准确地说,它是一批相同业务文档的逻辑集合。
- Document:文档,一条 JSON 数据,是 ES 存储和检索的基本单位。
- Field:字段,文档里的属性,比如 title、price、publishTime。
- Mapping:字段定义,描述字段类型、是否分词、使用什么分词器等。
- Shard:分片,一个索引会被拆成多个分片,分散存到不同节点上。
- Replica:副本分片,用于高可用和分担读请求。
- Node:节点,一个 ES 进程。
- Cluster:集群,由多个节点组成。
举个例子,一个 articles 索引可能有 3 个主分片,每个主分片有 1 个副本。写入一篇文章时,ES 会根据 _id 或 _routing 计算它属于哪个主分片,然后写入该主分片,再复制到副本分片。
为什么 ES 搜文本快?
MySQL 常见索引结构是 B+ 树。它适合按照字段值从左到右定位,比如 id = 10、age between 18 and 30、name like 'abc%'。
但是全文检索的问题不一样。假设有三篇文章:
text
doc1: 我喜欢学习 Elasticsearch
doc2: Elasticsearch 适合做全文搜索
doc3: MySQL 适合做事务存储如果用户搜索 Elasticsearch 搜索,我们希望快速知道哪些文档包含这些词。倒排索引的思路是反过来建索引:
text
Elasticsearch -> doc1, doc2
搜索 -> doc2
MySQL -> doc3这样查询某个词时,不需要逐篇扫描文章,只要先找到词典里的 term,再拿到包含这个 term 的文档列表。这个“term 到 document”的映射,就是倒排索引的核心。
分词决定能不能搜到
倒排索引里记录的是分词后的 term,不一定是原始句子。
比如字段 title 的值是:
text
中华人民共和国国歌如果使用标准分词器处理中文,效果可能比较粗糙;如果使用 IK 分词器,可能得到:
text
中华人民共和国、中华人民、中华、人民、共和国、国歌因此,搜索能不能命中,和字段使用什么 analyzer 有直接关系。写入时怎么分词,查询时怎么分词,两边要能对得上。
text 和 keyword 的区别
ES 里字符串字段最常见的是两种类型:
- text:会分词,适合全文检索,比如标题、正文、简介。
- keyword:不分词,适合精确匹配、排序、聚合,比如状态、标签、用户 ID、订单号。
比如 author = "金十期货":
- 如果是 text 字段,可能会被分成多个词,适合 match 查询。
- 如果是 keyword 字段,会作为一个整体保存,适合 term 查询。
很多业务字段会使用多字段设计:
json
PUT /articles
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" }
}
}
}
}
}这样 title 可以做全文检索,title.keyword 可以做精确匹配、排序或聚合。
ES 为什么是分布式的?
单机 Lucene 已经能完成倒排索引和搜索,但单机容量、性能和可用性都有限。ES 在 Lucene 之上加了一层分布式能力:
- 一个索引可以拆成多个主分片,分布到多个节点。
- 每个主分片可以有副本分片,节点宕机后副本可以提升为主分片。
- 查询可以发到任意节点,由协调节点把请求转发到相关分片,再合并结果。
- 集群会维护索引元数据、分片分配、节点状态等信息。
在 ES 集群里,请求进入的节点叫协调节点。协调节点不一定保存目标数据,但它会负责路由请求、收集分片结果、排序分页,最后把结果返回给客户端。
集群健康状态怎么看?
ES 常见的集群健康状态有三种:
- green:主分片和副本分片都正常分配。
- yellow:主分片正常,但至少有副本分片没有分配。
- red:至少有主分片没有分配,部分数据不可用。
查看健康状态:
http
GET /_cluster/health查看节点和分片:
http
GET /_cat/nodes?v
GET /_cat/shards?v
GET /_cat/indices?vyellow 不一定代表数据不可读,比如单节点集群设置了 1 个副本,副本无法分配到另一个节点,就会是 yellow。但 red 要认真处理,因为它说明有主分片不可用。
ES 和 MySQL 怎么分工?
常见架构是:
text
业务写入 -> MySQL -> binlog / MQ / 同步任务 -> Elasticsearch -> 搜索接口MySQL 保存权威数据,负责事务、约束、精确更新;ES 保存搜索视图,负责快速检索和聚合。
这样做有一个重要前提:ES 里的数据通常是“最终一致”的。也就是说,业务库更新后,ES 可能稍晚一点才同步完成。对于搜索场景,这种延迟通常可以接受;对于支付、库存、账户余额这类强一致场景,就不应该依赖 ES 作为判断依据。
小结
ES 的核心可以用一句话概括:它把 JSON 文档按 Mapping 和 Analyzer 处理成 Lucene 索引,再通过分片和副本提供分布式搜索能力。
学习 ES 不要一开始就陷在 API 细节里,先把这条主线抓住:
- Mapping 决定字段怎么存。
- Analyzer 决定文本怎么分词。
- 倒排索引决定搜索为什么快。
- Shard 和 Replica 决定 ES 怎么扩展和高可用。
- Query DSL 决定业务查询怎么表达。
后面我们再继续拆 ES 的写入、读取、Mapping 和查询细节。