
这是一个关于 Elasticsearch 核心原理与常见面试问题的全面总结。内容分为两大部分:核心原理剖析 和 常见面试问题与解答。
Part 1:Elasticsearch 核心原理剖析
要真正掌握 Elasticsearch,必须理解其内部的几个核心设计思想。
1. 核心概念与架构
-
集群、节点、分片、副本
-
集群: 一个或多个节点的集合,共同持有全部数据,提供联合索引和搜索能力。
-
节点: 一个运行中的 ES 实例,是集群的一部分。节点有多种角色(主节点、数据节点、协调节点、摄取节点等)。
-
索引 : 一类文档的集合(类似关系型数据库中的 Database)。
-
分片 : 索引可以被分成多个部分,每个部分就是一个分片。分片是 ES 实现水平扩展和分布式搜索的基石。索引创建时指定分片数,后续不可更改(除非重建索引)。
-
主分片: 数据的原始分片。
-
副本分片 : 主分片的拷贝,提供高可用性 (主分片挂掉,副本可提升为主)和提升读性能(搜索可以在所有副本上并行执行)。
-
-
-
文档 & 映射
-
文档 : ES 中的基本数据单元,是一个 JSON 对象(类似关系型数据库中的 Row)。
-
映射 : 定义索引中文档的字段及其类型、分词器等(类似关系型数据库中的 Schema )。
keyword
类型用于精确匹配(如排序、聚合、Term查询),text
类型用于全文检索(会被分词)。
-
2. 倒排索引
这是 ES 实现高速全文检索的根本数据结构。
-
正排索引: 像一本书的目录,通过标题(文档ID)找到内容。
-
倒排索引: 像一本书末尾的索引,通过关键词找到出现在哪些页码(文档ID)。
-
组成:
-
Term Dictionary: 对所有文档进行分词后得到的所有不重复的单词(Term)的集合。
-
Posting List: 对于每个 Term,记录包含它的所有文档的 ID 列表,以及在该文档中出现的位置、频率等信息。
-
举例 :
文档1:I love elasticsearch
文档2:I love coding
单词 | 文档ID |
---|---|
I | [1, 2] |
love | [1, 2] |
elasticsearch | [1] |
coding | [2] |
当搜索 love
时,直接查找倒排索引,立即得到文档 [1, 2]
。
优化 :Term Dictionary 很大,无法全部装入内存。ES 使用 FST 和 Skip List 等技术进行压缩和快速查找。
3. 写入流程 (Write Process)
-
协调节点: 客户端请求发送到任意节点,该节点成为协调节点。
-
路由计算 : 协调节点根据文档
_id
和路由规则(默认是_id
)计算文档应该存储在哪个主分片上:shard = hash(_routing) % number_of_primary_shards
。 -
转发请求 : 协调节点将写入请求转发到该主分片所在的主数据节点。
-
写入主分片: 主数据节点执行以下操作:
-
生成
_id
(如果未提供)。 -
验证映射和字段。
-
将数据写入 Translog (事务日志,用于崩溃恢复)和 Memory Buffer(内存缓冲区)。
-
此时数据还不可被搜索。
-
-
返回响应: 主分片写入成功后,协调节点返回结果给客户端(可配置为等待不同级别的确认)。
-
Refresh : 默认每 1 秒,Memory Buffer 中的数据会被写入到一个新的 Segment 文件中(在文件系统缓存中,未刷盘),并清空 Buffer。这个过程叫做 Refresh 。Refresh 后,新写入的文档才可以被搜索到。因此 ES 是 近实时 的。
-
Flush : 默认每 30 分钟,或 Translog 达到一定大小时,会执行一次 Flush:
-
将文件系统缓存中的所有 Segment 刷到磁盘。
-
清空 Translog,创建一个新的提交点。
-
4. 搜索流程 (Search Process)
-
查询阶段:
-
分发: 协调节点将搜索请求广播到索引的所有分片(主分片或副本分片)。
-
执行: 每个分片在本地执行查询(使用倒排索引),得到一个本地优先级队列(包含排序后的前 N 个文档 ID 和分数)。
-
返回: 每个分片将各自的队列结果返回给协调节点。
-
-
取回阶段:
-
合并排序: 协调节点合并所有分片的结果,进行全局排序,得到最终正确的 Top N 文档 ID 列表。
-
取回文档 : 协调节点根据文档 ID,向相关分片发送
GET
请求,获取文档的原始数据。 -
返回结果: 协调节点将完整的搜索结果返回给客户端。
-
5. 段合并
由于频繁的 Refresh 会产生大量小的 Segment 文件,搜索时需要遍历所有 Segment,效率低下。
ES 会在后台定期将多个小的、未删除的 Segment 合并成一个更大的 Segment,并物理删除标记为删除的文档。这个过程是 I/O 和 CPU 密集型的,但对提升搜索性能至关重要。
Part 2:常见面试问题与解答
基础概念类
-
Elasticsearch 是什么?主要应用场景?
- 答 : 一个基于 Lucene 构建的分布式、RESTful 的开源搜索和分析引擎。核心场景:全文检索 、日志处理与分析 (ELK Stack)、实时数据分析 、应用性能监控。
-
Elasticsearch 和 MySQL 的区别?
特性 Elasticsearch MySQL 目的 搜索、分析、日志 事务、关系型数据存储 数据结构 无 Schema(灵活,但有映射) 严格 Schema 查询语言 JSON DSL SQL 事务 不支持 ACID 支持 ACID 扩展性 天生的分布式,易水平扩展 垂直扩展或分库分表较复杂 -
解释一下倒排索引,为什么它快?
- 答: 如上文原理所述。它快是因为:1) 直接通过关键词定位文档,避免了全表扫描;2) 数据结构经过高度优化(FST压缩、跳表等);3) 可以高效地进行布尔运算(AND/OR/NOT)。
-
Text 和 Keyword 类型的区别?
-
答:
-
Text
: 用于全文搜索。会被分词器拆分成多个词项,然后建立倒排索引。不用于排序和聚合。 -
Keyword
: 用于精确值匹配。整个字符串作为一个完整的词项存入索引。常用于过滤、排序、聚合。
-
-
集群与分布式类
-
如何设计分片数和副本数?
-
答: 这是一个权衡问题。
-
主分片数 : 一旦设置,不可修改。建议:
-
单个分片大小建议在 10GB - 50GB 之间。
-
考虑数据增长,预留一定空间。
-
分片过多会导致集群管理开销增大;过少则无法充分利用节点资源。
-
-
副本数: 可以随时动态调整。
-
至少设置为
1
,以保证高可用。 -
读多写少的场景可以增加副本数(如从
1
改为2
)来提升搜索吞吐量。 -
副本数越多,写入性能会有一定下降(因为需要同步到更多副本)。
-
-
-
-
描述一下 Elasticsearch 的写入流程?为什么是近实时的?
- 答 : 参考上文核心原理。近实时 的原因在于数据从写入到可被搜索,中间有一个默认 1秒 的 Refresh 间隔。数据首先进入内存缓冲区,只有经过 Refresh 生成 Segment 后才能在搜索时被访问到。
-
描述一下 Elasticsearch 的搜索流程?
- 答: 参考上文的"查询阶段"和"取回阶段"。
-
Master 节点、Data 节点、Coordinating 节点的作用和区别?
-
答:
-
主节点 : 负责集群层面的轻量级操作,如创建/删除索引、跟踪节点状态、决定分片分配。不处理用户请求,数据压力小 。生产环境应配置专用主节点 (
node.master: true, node.data: false
)。 -
数据节点 : 存储数据,执行数据的增、删、改、查和聚合操作。CPU、内存、I/O 密集型 (
node.master: false, node.data: true
)。 -
协调节点 : 所有节点默认都是协调节点。负责接收客户端请求,将请求路由到正确的分片,并聚合结果。在大集群中,可以设置专用协调节点 (
node.master: false, node.data: false
)来分担数据节点的压力。
-
-
性能与优化类
-
如何优化 Elasticsearch 的搜索性能?
-
答:
-
硬件: 使用 SSD;保证足够内存(让文件系统缓存缓存更多的 Segment)。
-
映射设计 : 避免不必要的字段;合理使用
keyword
和text
。 -
查询优化 : 避免深度分页(使用
search_after
);使用 Filter 上下文(可缓存);避免通配符前缀查询。 -
索引设计 : 基于时间的数据使用滚动索引;合理设置分片大小和数量。
-
冷热架构: 将新/热数据放在 SSD 节点,旧/冷数据移到 HDD 节点。
-
-
-
如何优化 Elasticsearch 的写入性能?
-
答:
-
使用批量请求。
-
增加
refresh_interval
(如设置为30s
),减少 Refresh 次数。 -
在批量导入大量数据时,可以暂时禁用副本 (
"number_of_replicas": 0
),导入完成后再恢复。 -
使用自动生成的
_id
。ES 为自定义_id
需要一次额外的查找来确认其唯一性。 -
确保硬件 I/O 性能。
-
-
-
什么是深分页?为什么有问题?如何解决?
-
答 :
from 10000, size 10
这类查询就是深分页。问题在于协调节点需要从每个分片获取10000+10
条数据,然后在内存中合并排序,最后再取第 10000 到 10010 条。开销极大,容易导致 OOM。 -
解决方案:
-
避免: redesign 产品需求,如改为无限滚动。
-
search_after
: 使用上一页的结果来帮助检索下一页,性能极好。 -
Scroll API: 用于离线导出大量数据,非实时。
-
-
-
你如何监控 Elasticsearch 集群的健康状态?
-
答:
-
API :
_cluster/health
(查看状态 green/yellow/red)、_nodes/stats
(节点资源使用情况)、_cat
API(简洁的概览信息)。 -
监控指标: 集群状态、分片数、节点数、CPU/内存/磁盘使用率、索引/搜索速率和延迟、GC 情况。
-
工具: Kibana Monitoring、Prometheus + Grafana、Cerbero、ElasticHQ。
-
-
希望这份详细的总结能帮助你深入理解 Elasticsearch 并为面试做好充分准备!