Elasticsearch 面试八股文(50题)
title: Elasticsearch 面试八股文(50 题)
date: 2026-06-09 14:30:00
tags:
- 面试
- Elasticsearch
- 搜索
- 分布式
categories: 面试八股文
Elasticsearch 面试八股文(50 题)
📚 面试高频:本文覆盖 Elasticsearch 核心知识点,从基础概念到高级优化,帮你系统掌握 ES 面试要点。
🎯 面试加分:每个问题都包含深度解析和面试加分回答,让你在面试中脱颖而出。
⚡ 快速掌握:所有问题都附有通俗易懂的解释和实战经验分享。
📖 学习指南
🎯 学习目标:通过本文,你将系统掌握 Elasticsearch 的核心概念、搜索原理、分布式架构和性能优化技巧,能够自信地应对任何 Elasticsearch 相关的面试问题。
适合人群
- 🔰 初学者:想系统学习 Elasticsearch 的开发者
- 🚀 有经验者:想深入理解 ES 原理的高级开发者
- 💼 面试准备者:想刷 Elasticsearch 面试题的求职者
学习建议
- 先理解概念,再深入原理:先搞懂”是什么”,再搞懂”为什么”
- 结合实战场景:不要死记硬背,要理解实际应用场景
- 动手实践:在自己电脑上安装 ES,执行本文的示例代码
- 反复复习:面试前一周,每天复习 10 个问题
学习时间估算
- ⏱️ 快速复习(只看一句话总结):2 小时
- 📚 系统学习(看深度解析):1-2 天
- 💪 深入理解(研究源码):1 周+
🗺️ 知识图谱
mindmap
root((Elasticsearch))
基础概念
Lucene
倒排索引
近实时搜索
数据模型
索引 Index
文档 Document
字段 Field
映射 Mapping
分布式架构
分片 Shard
副本 Replica
节点 Node
集群 Cluster
搜索功能
全文搜索
结构化搜索
聚合搜索
地理位置搜索
性能优化
写入优化
读取优化
硬件选择
JVM 调优
实战应用
电商搜索
日志分析
监控系统
⚠️ 常见陷阱与误区
陷阱 1:对 text 字段使用 term 查询
❌ 错误示例:
1 | |
✅ 正确做法:
- 如果要精确匹配,使用
keyword类型字段 - 如果要全文搜索,使用
match查询
陷阱 2:动态映射导致类型推断错误
❌ 错误示例:
1 | |
✅ 正确做法:
- 总是使用静态映射(手动定义 mapping)
- 禁用动态映射:
"dynamic": false
陷阱 3:主分片数量不能修改
❌ 错误认知:
- 以为可以动态修改主分片数量
✅ 正确认知:
- 主分片数量在索引创建后不能修改(因为路由公式
shard = hash(_routing) % number_of_primary_shards) - 如果需要修改,只能重建索引
陷阱 4:From/Size 分页不适合深分页
❌ 错误做法:
1 | |
✅ 正确做法:
- 浅分页(前 1000 条):使用
from/size - 深分页(导出数据):使用
scroll - 深分页(实时分页):使用
search_after
陷阱 5:忽略副本分片的重要性
❌ 错误做法:
- 为了节省磁盘空间,禁用副本分片
✅ 正确做法:
- 生产环境至少设置 1 个副本
- 副本分片提供高可用(主分片故障时,副本分片可以提升为主分片)
- 副本分片可以提高读取吞吐量(读取请求可以负载均衡到副本分片)
💡 面试技巧
技巧 1:结构化回答
不要只回答”是什么”,要按照以下结构回答:
- 一句话总结(概念)
- 深度解析(原理、实现、优缺点)
- 面试加分回答(实际项目经验、源码理解、行业最佳实践)
示例:
面试官:什么是倒排索引?
你:
- 一句话总结:倒排索引是 ES 的核心数据结构,通过词项(Term)→ 文档列表(Posting List)的映射,实现快速全文搜索。
- 深度解析:倒排索引包括词项字典(Term Dictionary)和倒排列表(Posting List),词项字典用 FST 压缩存储,倒排列表用 Roaring Bitmap 压缩存储。
- 面试加分回答:我在实际项目中,曾经因为倒排索引占用太多内存,导致查询性能下降。后来通过禁用不需要搜索的字段的索引,减少了倒排索引的大小,查询性能提升了 30%。
技巧 2:结合实战场景
不要只背概念,要结合实际项目经验回答。
示例:
面试官:如何优化 ES 的写入性能?
你:
- 禁用刷新和副本(批量导入时)
- 使用 Bulk API(批量写入)
- 增加刷新间隔(降低刷新频率)
- 使用 SSD(提高 I/O 性能)
我在上一家公司,每天需要将 1000 万条日志导入 ES。最初直接单条写入,导入需要 2 小时。后来我使用了 Bulk API(批量大小 5MB),并临时禁用刷新和副本,导入时间缩短到 20 分钟,性能提升了 6 倍。
技巧 3:引导到你会的方向
如果遇到不会的问题,不要慌,可以引导到你会的方向。
示例:
面试官:ES 的 Translog 是什么?
你:(如果你不熟悉 Translog,可以引导到你会的方向)
我对 Translog 了解不深,但我知道 ES 的写入流程是:先写入内存缓冲区,然后定期刷新到文件系统缓存,最后刷写到磁盘。为了保证数据不丢失,ES 会使用 Translog 记录所有写操作。我更熟悉的是 ES 的分布式架构和搜索原理…
技巧 4:展示学习能力和技术热情
面试官不仅考察你的知识储备,还考察你的学习能力和技术热情。
示例:
面试官:你如何保持对 ES 的学习?
你:
- 阅读官方文档(每周至少阅读 1 个模块)
- 阅读源码(我已经阅读了 Lucene 的倒排索引实现)
- 参与社区(在 Elasticsearch 中文社区回答问题)
- 实践项目(自己搭建了一个日志分析系统,使用 ELK Stack)
📋 目录
- 第一部分:Elasticsearch 基础(Q1-Q10)
- 第二部分:Elasticsearch 索引和映射(Q11-Q20)
- 第三部分:Elasticsearch 搜索(Q21-Q30)
- 第四部分:Elasticsearch 集群和分布式(Q31-Q40)
- 第五部分:Elasticsearch 性能优化(Q41-Q50)
🎯 面试高频问题与答题思路
高频问题 1:设计一个电商搜索系统
答题思路:
- 数据建模:商品数据如何存储(使用非规范化数据,将商品信息、库存信息、价格信息存储在同一文档中)
- 分词器选择:中文分词器(使用 IK Analyzer)
- 搜索类型:全文搜索(使用
match查询)、过滤搜索(使用filter查询) - 排序:按评分排序、按销量排序、按价格排序
- 分页:使用
search_after实现无限滚动分页 - 性能优化:增加副本、使用文件系统缓存、使用 filter 查询
高频问题 2:如何优化 ES 的写入性能?
答题思路:
- 禁用刷新和副本(批量导入时)
- 使用 Bulk API(批量写入)
- 增加刷新间隔(降低刷新频率)
- 使用 SSD(提高 I/O 性能)
- 优化 mapping(禁用不需要搜索的字段)
高频问题 3:ES 集群状态是红色,如何排查?
答题思路:
- 查看集群健康状态:
GET /_cluster/health - 查看未分配的分片:
GET /_cat/shards?h=index,shard,prirep,state,unassigned.reason - 查看节点状态:
GET /_cat/nodes - 查看日志:
tail -f logs/elasticsearch.log - 解决方案:如果是节点故障,下线故障节点,恢复副本分片
第一部分:Elasticsearch 基础(Q1-Q10)
Q1:什么是 Elasticsearch?它和 Solr 的区别是什么?
一句话总结:Elasticsearch 是一个分布式搜索和分析引擎,基于 Lucene 构建,擅长全文搜索、结构化搜索、分析。
深度解析:
Elasticsearch 的核心概念:
- 倒排索引(Inverted Index):ES 的核心,通过词项(Term)快速查找文档
- 近实时搜索(NRT):文档索引后,默认可在 1 秒内被搜索到
- 分布式架构:天然支持水平扩展
ES vs Solr:
| 对比项 | Elasticsearch | Solr |
|---|---|---|
| 分布式 | 天然分布式,易于扩展 | 需要 Zookeeper 协调 |
| 近实时 | 支持(1 秒延迟) | 支持(但配置复杂) |
| 社区 | 活跃,生态丰富 | 较成熟,但社区增长慢 |
| REST API | 原生支持 | 需要额外配置 |
| 大数据 | 适合(可处理 PB 级数据) | 适合(但扩展性不如 ES) |
面试加分回答:
- 可以讲讲 ES 的使用场景(日志分析、全文搜索、安全分析)
- 可以讲讲 ELK Stack(Elasticsearch + Logstash + Kibana)
- 可以讲讲实际项目中的应用(比如商品搜索、日志检索)
Q2:Elasticsearch 的核心概念有哪些?
一句话总结:ES 的核心概念包括:索引(Index)、类型(Type)、文档(Document)、字段(Field)、映射(Mapping)、分片(Shard)、副本(Replica)。
深度解析:
ES 的数据模型:
- 索引(Index):相当于关系型数据库的数据库
- 类型(Type):相当于表(ES 7.x 已废弃,一个索引只能有一个类型
_doc) - 文档(Document):相当于行
- 字段(Field):相当于列
ES 的分布式模型:
- 分片(Shard):索引的水平拆分,每个分片是一个独立的 Lucene 索引
- 主分片(Primary Shard):原始数据,负责处理写请求
- 副本分片(Replica Shard):备份数据,负责处理读请求,提供高可用
示例:
1 | |
面试加分回答:
- 可以讲讲分片数量为什么不能修改(因为路由公式
shard = hash(_routing) % number_of_primary_shards) - 可以讲讲如何规划分片数量(根据数据量和硬件资源)
- 可以讲讲实际项目中的分片策略(比如按时间滚动索引)
Q3:Elasticsearch 的倒排索引(Inverted Index)是什么?
一句话总结:倒排索引是 ES 的核心数据结构,通过词项(Term)→ 文档列表(Posting List) 的映射,实现快速全文搜索。
深度解析:
正排索引 vs 倒排索引:
- 正排索引(比如数据库索引):通过 ID → 内容 查找
- 倒排索引:通过 词项 → 文档 ID 列表 查找
倒排索引的组成:
- 词项字典(Term Dictionary):存储所有词项,按字典序排列(用 FST,有限状态转换机 压缩存储,用很小的内存前缀共享大量词项,支持快速前缀/范围查找)
- 倒排列表(Posting List):存储包含该词项的文档 ID 列表,以及词频、位置等信息(用增量编码(delta encoding)+ Frame of Reference(FOR)位压缩存储,并附带**跳表(Skip List)**加速文档 ID 的跳跃查找)
示例:
1 | |
倒排索引 vs 正排(doc values)的分工(面试常问,容易和上面的”正排索引”名词混淆):
- 倒排索引:负责”词 → 文档“的检索,即全文搜索、词项匹配走的是它
- 正排(doc values):ES 为 text 之外的字段默认额外维护一份”文档 → 字段值“的列式存储(doc values),专门服务于排序、聚合、脚本计算这类需要按文档遍历字段值的场景;倒排索引结构上不适合做这类操作,所以两者是互补关系,不是替代关系
text字段默认不生成 doc values(因为分词后的词项排序意义不大),所以 text 字段不能直接排序/聚合,需要用keyword类型或fielddata(不推荐,占堆内存)
flowchart LR
D1["文档1: I love Elasticsearch"]
D2["文档2: Elasticsearch is fast"]
D3["文档3: I love fast search"]
D1 --> T["分词 Analyzer"]
D2 --> T
D3 --> T
T --> TD["词项字典 Term Dictionary(FST 压缩,按字典序)"]
TD -->|"I"| P1["Posting List: [doc1, doc3]"]
TD -->|"love"| P2["Posting List: [doc1, doc3]"]
TD -->|"elasticsearch"| P3["Posting List: [doc1, doc2]"]
TD -->|"fast"| P4["Posting List: [doc2, doc3]"]
P1 --> SK["每个 Posting List 内: 文档ID 增量编码 + 跳表加速遍历"]
P2 --> SK
P3 --> SK
P4 --> SK
面试加分回答:
- 可以讲讲 FST(Finite State Transducer) 如何压缩词项字典
- 可以讲讲倒排列表如何用 Frame of Reference + 跳表 压缩和加速遍历(注意:Roaring Bitmap 在 Lucene/ES 中主要用于缓存的 filter 结果位图等场景,不是倒排列表本身的主要压缩方式,面试时不要说反)
- 可以讲讲实际项目中的优化(比如禁用不需要检索字段的索引,用
"index": false;给不需要排序聚合的字段关闭 doc_values,用"doc_values": false)
Q4:Elasticsearch 的文档 CRUD 操作有哪些?
一句话总结:ES 的文档 CRUD 操作包括:索引(Index)、创建(Create)、读取(Get)、更新(Update)、删除(Delete)。
深度解析:
CRUD 操作示例:
1 | |
面试加分回答:
- 可以讲讲 Index vs Create 的区别(
PUT /_create/如果 ID 已存在则报错,POST /_doc/或PUT /_doc/会覆盖) - 可以讲讲 Update 的内部原理(先获取文档,修改,再索引)
- 可以讲讲实际项目中的最佳实践(比如使用 Bulk API 批量操作)
Q5:Elasticsearch 的搜索类型有哪些?
一句话总结:ES 的搜索类型包括:全文搜索、结构化搜索、聚合搜索、地理位置搜索。
深度解析:
1. 全文搜索:
1 | |
2. 结构化搜索:
1 | |
3. 聚合搜索:
1 | |
4. 地理位置搜索:
1 | |
面试加分回答:
- 可以讲讲 Match vs Term 的区别(
match会分词,term不会分词) - 可以讲讲 聚合的性能优化(比如
size: 0不返回文档,只返回聚合结果) - 可以讲讲实际项目中的应用(比如商品搜索、用户画像分析)
Q6:Elasticsearch 的 mapping(映射)是什么?
一句话总结:Mapping 是 ES 的数据模式定义,定义了文档的字段类型、分词器、是否索引等属性。
深度解析:
Mapping 的类型:
- 动态映射(Dynamic Mapping):ES 自动推断字段类型(不推荐,因为可能推断错误)
- 静态映射(Explicit Mapping):手动定义字段类型(推荐)
字段类型:
- text:用于全文搜索(会分词)
- keyword:用于结构化搜索(不会分词)
- integer、long、float、double:数值类型
- date:日期类型
- boolean:布尔类型
- geo_point:地理位置类型
示例:
1 | |
多字段(Multi-field):同一个字段经常既要能全文搜索、又要能精确匹配/排序/聚合,这时用 fields 给它挂一个 .keyword 子字段,两份倒排+正排各存一份,互不影响:
1 | |
面试加分回答:
- 可以讲讲 text vs keyword 的区别(
text会分词,用于全文搜索;keyword不会分词,用于精确匹配) - 可以讲讲 多字段(multi-field):一个字段用
text做全文搜索,同时用.keyword子字段做精确匹配/排序/聚合,是搜索场景里最常见的字段设计 - 可以讲讲 动态映射的风险(比如数字被推断为
long,导致无法精确匹配) - 可以讲讲实际项目中的最佳实践(建议使用静态映射)
Q7:Elasticsearch 的分词器(Analyzer)是什么?
一句话总结:分词器是 ES 用于处理文本字段的组件,包括:字符过滤器(Character Filter)、分词器(Tokenizer)、词项过滤器(Token Filter)。
深度解析:
分词器的组成:
- 字符过滤器:预处理文本(比如去除 HTML 标签)
- 分词器:将文本切分成词项(比如按空格分词)
- 词项过滤器:后处理词项(比如转小写、去除停用词、添加同义词)
内置分词器:
- Standard Analyzer:默认分词器,按词切分,转小写
- Simple Analyzer:按非字母字符切分,转小写
- Whitespace Analyzer:按空格切分
- IK Analyzer:中文分词器(需要单独安装插件,ES 官方不内置)
IK 分词器的两种模式(面试高频细节,容易混):
- ik_max_word:最细粒度拆分,穷举所有可能的词语组合。比如”中华人民共和国”会拆成”中华人民共和国/中华人民/中华/华人/人民共和国/人民/共和国/共和/国”等。通常用于 index time(建索引时),让文档能被尽量多的词命中,召回率更高
- ik_smart:最粗粒度拆分,只切出最可能的一种组合,比如”中华人民共和国”只切成”中华人民共和国”。通常用于 search time(查询时),避免查询词被拆得过细导致检索结果发散、精度下降
Index Time 分词 vs Search Time 分词(面试常问,很多人分不清):
- Index Time(索引时):文档写入时,
analyzer(或未单独配置时的search_analyzer/analyzer)对字段内容分词,生成写入倒排索引的词项——这一步决定了”这份文档能被哪些词命中” - Search Time(查询时):查询语句(如
match的查询文本)也要经过分词,才能拿分词后的词项去匹配倒排索引——这一步决定了”这次查询会用哪些词去查” - 默认情况下
analyzer同时作用于 index time 和 search time;如果需要不同策略,可以单独指定search_analyzer,最典型的场景就是索引时用ik_max_word提高召回,搜索时用ik_smart提高精度:
1 | |
示例:
1 | |
面试加分回答:
- 可以讲讲 如何选择合适的分词器(英文用
standard,中文用ik_max_word) - 可以讲讲 如何自定义分词器(比如添加同义词过滤器)
- 可以讲讲实际项目中的优化(比如禁用不必要的词项过滤器)
Q8:Elasticsearch 的评分机制(Scoring)是什么?
一句话总结:ES 使用 BM25 算法计算文档的相关性评分(_score),评分越高,排序越靠前。
深度解析:
BM25 算法:
- 是 TF-IDF 的改进版,ES 5.0 版本起默认相关性算法从经典的 TF-IDF(Classic Similarity)切换为 BM25(在此之前,ES 2.x 及更早版本默认用的是 TF-IDF)
- 考虑词频(TF) 和 逆文档频率(IDF)
- 会对词频做饱和处理:词出现次数越多贡献越大,但增速递减,不会线性无限加分(避免高频词/关键词堆砌主导评分)
评分公式(简化版,忽略多词项求和):
1 | |
BM25 的两个可调参数(面试高频,容易被追问):
- k1(默认
1.2):控制词频饱和度。k1 越大,词频对评分的影响越持久(饱和得越慢);k1 越小,词频很快就饱和,重复出现的词边际收益迅速下降 - b(默认
0.75):控制字段长度归一化的强度。b=1 表示完全按字段长度归一化(长文档会被压低分数);b=0 表示完全不考虑字段长度 - 可以在 mapping 里给字段自定义 similarity 来调这两个参数:
1 | |
如何关闭算分:不需要相关性排序、只需要”是否匹配”的场景(比如权限过滤、状态过滤),应该把条件放进 filter context(bool.filter、constant_score 的 filter)而不是 must——filter context 下不计算 _score(统一记为 1),且结果可以被缓存,比 query context 更快。
示例:
1 | |
面试加分回答:
- 可以讲讲 query context vs filter context(
filter不算分、可缓存,权限过滤这类”是否满足条件”的场景应该用filter) - 可以讲讲 如何自定义评分(使用
function_score查询) - 可以讲讲 如何影响评分(比如给新发布的文档加权)
- 可以讲讲实际项目中的优化:比如在 KNN 向量召回后,用
rescore对召回窗口内的候选做 BM25 二次重打分——这是”重打分”而不是”融合两个独立排行榜”(RRF),细节见后面的向量检索小节
Q9:Elasticsearch 的分布式架构是什么?
一句话总结:ES 是分布式系统,通过分片(Shard) 实现水平扩展,通过副本(Replica) 实现高可用。
深度解析:
ES 的节点类型:
- 主节点(Master Node):负责集群管理(创建/删除索引、跟踪节点状态)
- 数据节点(Data Node):负责存储数据和执行搜索
- 协调节点(Coordinating Node):负责接收客户端请求,路由到正确的节点,合并结果
- 预处理节点(Ingest Node):负责文档预处理(比如解析附件)
ES 的写入流程:
- 客户端发送写请求到协调节点
- 协调节点根据 文档 ID 或 路由值 计算目标主分片
- 协调节点将请求转发到主分片所在节点
- 主分片写入成功后,并行转发到所有副本分片
- 所有副本分片写入成功后,返回成功给客户端
ES 的查询流程(Query Then Fetch):搜索默认分两个阶段,为的是避免”每个分片都把完整文档传给协调节点再排序”造成的巨大网络和内存开销:
- Query 阶段:协调节点把查询广播给相关分片(主或副本二选一),每个分片在本地执行查询并打分,只返回轻量的
doc_id + score(并不返回完整文档),协调节点收集所有分片的结果后做全局排序,截出最终需要的from~from+size那一段 - Fetch 阶段:协调节点只向排序后确实要返回的那几条结果所在的分片,按需请求这些
doc_id对应的完整文档内容,取回后拼装成最终响应
sequenceDiagram
participant C as 客户端
participant Co as 协调节点
participant S1 as 分片1
participant S2 as 分片2
participant S3 as 分片3
C->>Co: 发起搜索请求
Note over Co,S3: Query 阶段
Co->>S1: 转发查询
Co->>S2: 转发查询
Co->>S3: 转发查询
S1-->>Co: 返回本地 Top-N 的 doc_id + score
S2-->>Co: 返回本地 Top-N 的 doc_id + score
S3-->>Co: 返回本地 Top-N 的 doc_id + score
Co->>Co: 合并所有分片结果并全局排序,截取 from~size
Note over Co,S3: Fetch 阶段
Co->>S1: 按 doc_id 请求完整文档
Co->>S3: 按 doc_id 请求完整文档
S1-->>Co: 返回完整文档内容
S3-->>Co: 返回完整文档内容
Co-->>C: 返回最终结果
- 这也是为什么深分页代价大:
from+size越大,每个分片在 Query 阶段都要在本地排出from+size条,协调节点要合并分片数 ×(from+size)条结果再排序,from 越大开销越大
面试加分回答:
- 可以讲讲 如何规划节点角色(小规模集群可以混合部署,大规模集群应该分离角色)
- 可以讲讲 为什么要 Query Then Fetch 两阶段(避免每个分片把完整文档都传回协调节点,Query 阶段只传轻量的 doc_id+score,只有最终会返回的那几条才在 Fetch 阶段取完整内容)
- 可以讲讲 如何避免脑裂问题(ES 7.0 之前用
discovery.zen.minimum_master_nodes手动配置候选主节点法定人数;ES 7.0 起该参数已被移除,改为集群内置的选主机制/**投票配置(voting configuration)**自动管理,不再需要手动设置) - 可以讲讲实际项目中的部署方案(比如 3 个主节点 + 多个数据节点)
Q10:Elasticsearch 的近实时搜索(NRT)是什么?
一句话总结:ES 的近实时搜索是指文档索引后,默认可在 1 秒 内被搜索到(不是实时,但接近实时)。
深度解析:
为什么不是实时?
- Lucene 的**段(Segment)**一旦写完就是不可变的(Immutable)
- 新写入的文档首先进入内存缓冲区(In-memory Indexing Buffer),此时还不可搜索
- 默认每隔 1 秒执行一次 刷新(Refresh):把缓冲区中的文档写成一个新的、驻留在文件系统缓存(File System Cache)里的 Lucene 段(这一步很轻量,不需要 fsync 到磁盘)
- 只有 refresh 完成、段对外可见之后,这批文档才能被搜索到——“近实时”这个说法的来源正是这个默认 1 秒的 refresh 间隔,而不是数据已经落盘
数据不丢失靠的是 Translog(事务日志),不是 refresh:
- refresh 只是让内存里的数据变得可搜索,并不保证持久化——如果这时候进程崩溃、缓冲区里的数据会丢
- 所以每次写操作在写入内存缓冲区的同时,也会追加写入 translog(默认每个请求都 fsync,
index.translog.durability可调为async定期 fsync 以换取更高吞吐) - 节点重启恢复时,ES 会重放 translog 中尚未落盘的操作,从而保证不丢数据——refresh 保证”近实时可搜索”,translog 保证”数据不丢失”,两者各管一段,不要混为一谈
刷新(Refresh)vs 刷写(Flush)vs 段合并(Merge):
- 刷新(Refresh):内存缓冲区 → 生成新的、可搜索的 Lucene 段(轻量级,默认 1 秒一次,不保证持久化到磁盘,也不清空 translog)
- 刷写(Flush):把文件系统缓存中的段
fsync到磁盘,生成新的 commit point,并清空/截断已经落盘的 translog(重量级,保证持久化;默认由 translog 大小/时间等条件触发,也可手动调用) - 段合并(Merge):refresh 越频繁,小段越多,查询要遍历的段也越多,删除的文档也需要靠合并才能真正清理;ES 后台会定期把多个小段合并成更大的段,同时物理删除标记为已删除的文档,减少段数量、提升查询效率(这一步会消耗 CPU 和 IO,是写入性能调优时经常要控制的点)
flowchart LR
W["写请求"] --> B["内存缓冲区 In-memory Buffer(尚不可搜索)"]
W --> TL["Translog(追加写,默认每请求 fsync)"]
B -->|"默认每 1s,refresh"| SEG["新 Segment 生成,进入文件系统缓存(此时可被搜索——近实时的由来)"]
SEG -->|"持续写入产生更多小 Segment"| MERGE["Segment Merge:合并小段、物理清理已删除文档"]
TL -->|"节点重启时重放,保证数据不丢"| RECOVER["崩溃恢复"]
SEG -->|"达到阈值/定期,flush"| FLUSH["fsync 到磁盘 + 生成新 Commit Point"]
FLUSH -->|"已落盘的操作可以清空"| TL
示例:
1 | |
面试加分回答:
- 可以讲讲 如何优化刷新间隔(提高写入性能 vs 提高搜索实时性)
- 可以讲讲 refresh、flush、translog、merge 各自解决什么问题(refresh 管可搜索性,translog 管不丢数据,flush 管持久化,merge 管段数量和查询效率),这是这道题最容易被追问混淆的地方
- 可以讲讲实际项目中的调优(比如批量导入时临时禁用刷新、调大 translog flush 阈值以降低 IO)
第二部分:Elasticsearch 索引和映射(Q11-Q20)
Q11:Elasticsearch 的索引模板(Index Template)是什么?
一句话总结:索引模板是 ES 的自动应用 mapping 和 settings 的机制,当创建新索引时,如果匹配模板模式,则自动应用模板中的配置。
深度解析:
索引模板的组成:
- 索引模式(Index Pattern):匹配哪些索引(比如
log-*) - Mapping:字段类型定义
- Settings:索引设置(比如分片数量、刷新间隔)
- 别名(Alias):索引别名
示例:
1 | |
面试加分回答:
- 可以讲讲 索引模板的使用场景(比如日志索引、时间序列索引)
- 可以讲讲 如何滚动索引(使用
Rollover API) - 可以讲讲实际项目中的应用(比如按天创建日志索引)
Q12:Elasticsearch 的别名(Alias)是什么?
一句话总结:别名是 ES 的索引昵称,可以通过别名访问多个索引,实现零停机时间重建索引。
深度解析:
别名的好处:
- 简化查询:可以通过一个别名查询多个索引
- 零停机时间重建索引:先创建新索引,然后切换别名
- 过滤别名:可以给别名添加过滤器,实现多租户
示例:
1 | |
面试加分回答:
- 可以讲讲 别名的实现原理(别名是保存在集群状态中的)
- 可以讲讲 如何使用别名实现零停机时间重建索引
- 可以讲讲实际项目中的应用(比如版本化索引)
Q13:Elasticsearch 的动态映射(Dynamic Mapping)有什么问题?
一句话总结:动态映射是 ES 自动推断字段类型的机制,但可能推断错误,导致搜索结果不符合预期。
深度解析:
动态映射的问题:
- 数字被推断为 long:比如
"123"被推断为long,导致无法精确匹配 - 日期被推断为 text:比如
"2024-01-01"被推断为text,导致无法按日期范围搜索` - 新字段自动加入 mapping:可能导致 mapping 爆炸(比如动态生成成千上万个字段)
解决方案:
- 使用静态映射(推荐)
- 禁用动态映射:
"dynamic": false - 严格动态映射:
"dynamic": "strict"(不允许新字段)
示例:
1 | |
面试加分回答:
- 可以讲讲 为什么应该禁用动态映射
- 可以讲讲 如何修复错误的 mapping(重建索引)
- 可以讲讲实际项目中的最佳实践(** always 使用静态映射**)
Q14:Elasticsearch 的嵌套对象(Nested Object)是什么?
一句话总结:嵌套对象是 ES 的复杂数据类型,用于数组中的对象,保持对象的独立性,避免数组扁平化问题。
深度解析:
数组扁平化问题:
1 | |
嵌套对象解决方案:
1 | |
面试加分回答:
- 可以讲讲 nested vs object 的区别(
object类型会扁平化,nested类型保持独立性) - 可以讲讲 nested 的性能问题(嵌套查询较慢,因为需要加载整个嵌套文档)
- 可以讲讲实际项目中的应用(比如订单中的商品列表)
Q15:Elasticsearch 的父子关系(Parent-Child Relationship)是什么?
一句话总结:父子关系是 ES 的关联数据模型,用于一对多关系,父文档和子文档是独立的文档,但可以联合查询。
深度解析:
父子关系 vs 嵌套对象:
| 对比项 | 父子关系 | 嵌套对象 |
|---|---|---|
| 数据存储 | 父文档和子文档是独立的文档 | 嵌套对象是父文档的一部分 |
| 更新 | 可以独立更新子文档 | 必须更新整个父文档 |
| 查询 | 支持父子联合查询 | 只支持嵌套查询 |
| 性能 | 较慢(需要 Join) | 较快 |
示例:
1 | |
面试加分回答:
- 可以讲讲 父子关系的性能问题(Join 操作较慢)
- 可以讲讲 父子关系的使用场景(比如问答系统、评论系统)
- 可以讲讲实际项目中的替代方案(比如非规范化数据,将父子数据放在同一个文档中)
Q16:Elasticsearch 的索引生命周期管理(ILM)是什么?
一句话总结:ILM 是 ES 的自动化索引管理功能,可以自动执行滚动、收缩、强制合并、删除等操作,适用于时间序列数据(比如日志)。
深度解析:
ILM 的阶段:
- Hot 阶段:索引正在被频繁写入和查询
- Warm 阶段:索引不再写入,但偶尔查询
- Cold 阶段:索引很少查询,可以存储在便宜的硬件上
- Delete 阶段:索引可以被删除
示例:
1 | |
面试加分回答:
- 可以讲讲 ILM 的使用场景(比如日志索引、指标索引)
- 可以讲讲 如何监控 ILM 的执行(使用
GET /_ilm/status) - 可以讲讲实际项目中的应用(比如按天创建日志索引,自动删除 90 天前的索引)
Q17:Elasticsearch 的索引设置(Index Settings)有哪些重要的?
一句话总结:索引设置是 ES 的索引级别配置,包括:分片数量、刷新间隔、写入限流、合并策略等。
深度解析:
重要的索引设置:
- number_of_shards:主分片数量(不能修改)
- number_of_replicas:副本分片数量(可以动态修改)
- refresh_interval:刷新间隔(默认 1 秒)
- index.translog.flush_threshold_size:刷写阈值(默认 512MB)
- index.merge.scheduler.max_thread_count:合并线程数
示例:
1 | |
面试加分回答:
- 可以讲讲 如何优化写入性能(增大刷新间隔、禁用副本、使用 Bulk API)
- 可以讲讲 如何优化查询性能(增加副本、使用文件系统缓存、优化 mapping)
- 可以讲讲实际项目中的调优经验(比如批量导入时临时禁用刷新)
Q18:Elasticsearch 的 mapping 优化技巧有哪些?
一句话总结:Mapping 优化技巧包括:禁用不需要搜索的字段、使用 keyword 类型、启用 doc_values、禁用 _source 等。
深度解析:
Mapping 优化技巧:
- 禁用不需要搜索的字段:
"index": false - 使用 keyword 类型:用于精确匹配(比 text 类型快)
- 启用 doc_values:用于排序和聚合(默认启用)
- 禁用 _source:如果不获取原始文档,可以禁用(节省磁盘空间)
- 使用常量关键字(constant_keyword):如果字段值固定,可以使用(节省存储空间)
示例:
1 | |
面试加分回答:
- 可以讲讲 如何减少索引大小(禁用不需要的功能)
- 可以讲讲 如何优化聚合性能(启用 doc_values)
- 可以讲讲实际项目中的优化经验(比如只为需要的字段启用索引)
Q19:Elasticsearch 的索引重建(Reindex)是什么?
一句话总结:索引重建是将旧索引的数据复制到新索引的操作,用于修改 mapping、增加分片数量、拆分索引等场景。
深度解析:
为什么需要重建索引?
- Mapping 错误(比如字段类型推断错误)
- 需要修改分片数量(主分片数量不能修改,只能重建索引)
- 需要优化索引结构(比如启用/doc_values、禁用 _source)
重建索引的步骤:
- 创建新索引(正确的 mapping 和 settings)
- 使用 Reindex API 复制数据
- 等待重建完成
- 切换别名(实现零停机时间)
示例:
1 | |
面试加分回答:
- 可以讲讲 如何加速重建索引(使用
slices参数并行重建) - 可以讲讲 如何避免重建索引时的性能问题(限制重建速度)
- 可以讲讲实际项目中的经验(比如提前规划 mapping,避免重建索引)
Q20:Elasticsearch 的索引拆分(Split)是什么?
一句话总结:索引拆分是 ES 的增加主分片数量的操作,但有限制(新分片数量必须是原分片数量的倍数)。
深度解析:
为什么需要拆分索引?
- 主分片数量不能修改(因为路由公式)
- 但如果索引的设置
index.number_of_routing_shards大于index.number_of_shards,则可以拆分`
拆分的限制:
- 新分片数量必须是原分片数量的倍数
- 原索引必须只读(不能写入)
示例:
1 | |
面试加分回答:
- 可以讲讲 拆分索引的使用场景(比如数据量增长,需要增加分片数量)
- 可以讲讲 拆分索引的限制(必须是倍数)
- 可以讲讲实际项目中的替代方案(比如按时间滚动索引,而不是拆分索引)
第三部分:Elasticsearch 搜索(Q21-Q30)
Q21:Elasticsearch 的 Match 查询和 Term 查询的区别是什么?
一句话总结:match 查询会分词,用于全文搜索;term 查询不会分词,用于精确匹配。
深度解析:
Match 查询:
- 会对查询字符串进行分词
- 然后对每个词项进行搜索
- 最后合并结果(默认是 OR 关系)
Term 查询:
- 不会对查询字符串进行分词
- 直接精确匹配倒排索引中的词项**
示例:
1 | |
面试加分回答:
- 可以讲讲 Match vs Term 的区别(
match会分词,term不会分词) - 可以讲讲 如何选择合适的查询类型(全文搜索用
match,精确匹配用term) - 可以讲讲实际项目中的常见错误(比如对
text字段使用term查询)
Q22:Elasticsearch 的 Bool 查询是什么?
一句话总结:bool 查询是 ES 的复合查询,可以组合多个查询条件,包括:must、should、must_not、filter。
深度解析:
Bool 查询的子句:
- must:必须匹配,会贡献评分
- should:可以匹配,会贡献评分(但可以通过
minimum_should_match控制至少匹配几个) - must_not:必须不匹配
- filter:必须匹配,但不会贡献评分(会使用缓存,性能更高)
示例:
1 | |
面试加分回答:
- 可以讲讲 filter vs must 的区别(
filter不贡献评分,会使用缓存) - 可以讲讲 如何优化 bool 查询的性能(将不需要评分的条件放在
filter中) - 可以讲讲实际项目中的复杂查询案例(比如电商搜索)
Q23:Elasticsearch 的聚合(Aggregation)是什么?
一句话总结:聚合是 ES 的分析功能,类似于 SQL 的 GROUP BY 和聚合函数,包括:指标聚合、桶聚合、管道聚合。
深度解析:
聚合的类型:
- 指标聚合(Metric Aggregation):计算指标(比如
sum、avg、max、min、cardinality) - 桶聚合(Bucket Aggregation):将文档分组(比如
terms、range、histogram) - 管道聚合(Pipeline Aggregation):对聚合结果进行二次计算(比如
avg_bucket、max_bucket)
示例:
1 | |
terms 聚合的精度问题(面试高频,很多人不知道):
terms聚合默认是分片级近似计算:每个分片先各自算出本分片 Top-N 的 buckets,再汇总到协调节点合并——不是把所有分片的全量数据拉到协调节点精确统计,所以分布式场景下terms聚合的计数可能不精确- 返回结果里的
doc_count_error_upper_bound(该次聚合可能的最大计数误差)和sum_other_doc_count(没有进入返回 buckets 的其它文档数)就是用来暴露这个误差的 - 典型场景:某个词项在大多数分片里排不进前几名、但在个别分片里数量不小,如果每个分片只上报 Top-N,这个词项可能被漏掉或算少
- 缓解方式:调大
shard_size(每个分片参与预聚合的候选桶数,默认是size的一个放大值),用更大的候选集换更高精度,但会增加内存和网络开销;如果字段基数不大,也可以考虑不分片聚合或用cardinality(基于 HyperLogLog++ 近似算法,本身也是近似值,不追求精确去重计数时用它换性能)
面试加分回答:
- 可以讲讲
terms聚合为什么不精确(分片级近似 Top-N,doc_count_error_upper_bound就是用来衡量误差的)、如何用shard_size提高精度 - 可以讲讲 聚合的性能优化(比如
size: 0、使用execution_hint) - 可以讲讲 聚合的内存限制(比如
circuit_breaker) - 可以讲讲实际项目中的应用(比如用户画像分析、日志统计分析)
Q24:Elasticsearch 的排序(Sorting)是什么?
一句话总结:排序是 ES 的自定义文档顺序的功能,可以按字段值、评分、地理距离排序。
深度解析:
排序的类型:
- 按字段值排序:比如按价格、日期排序
- 按评分排序:按
_score排序(默认) - 按地理距离排序:按距离指定坐标的远近排序**
示例:
1 | |
面试加分回答:
- 可以讲讲 排序的性能问题(排序需要加载字段值,会消耗内存)
- 可以讲讲 如何优化排序性能(启用
doc_values、使用unmapped_type) - 可以讲讲实际项目中的需求(比如多维度排序,先按评分排序,再按时间排序)
Q25:Elasticsearch 的分页(Pagination)是什么?
一句话总结:分页是 ES 的限制返回结果数量的功能,包括:From/Size、Scroll、Search After。
深度解析:
分页的类型:
- From/Size:浅分页(适合前 1000 条左右结果,ES 默认限制
from + size不超过index.max_result_window,默认 10000) - Scroll:深分页,但已不推荐用于”用户实时翻页”场景,官方定位是给导出大量数据 / reindex 这类一次性批量遍历用的——它会保持一个快照视图,长时间占用资源,且不支持”跳页”
- Search After(配合 Point in Time,推荐):深分页首选方案,无状态、代价与
from/size无关,只能”翻下一页”不能跳页,适合无限滚动等实时分页场景
From/Size 的问题:
- 比如
from: 990, size: 10,ES 需要从每个分片获取 1000 条结果,然后在协调节点合并排序,最后返回第 990-1000 条 - 性能很差(占用大量内存和 CPU)
示例:
1 | |
面试加分回答:
- 可以讲讲 为什么 From/Size 不适合深分页(每个分片都要在本地排出
from+size条,from 越大协调节点要合并排序的数据量越大,是 Query Then Fetch 两阶段查询里 Query 阶段的开销) - 可以讲讲 Scroll vs Search After 的区别(
scroll保持时间点快照,适合一次性导出数据;search_after无状态、只能往后翻页,是当前官方推荐的深分页/实时分页方案,通常配合 Point in Time 使用以获得稳定的一致性视图) - 可以讲讲实际项目中的分页方案(比如无限滚动分页,使用
search_after+ PIT)
Q26:Elasticsearch 的高亮(Highlighting)是什么?
一句话总结:高亮是 ES 的在搜索结果中标记关键词的功能,通常用于全文搜索。
深度解析:
高亮的类型:
- unified:默认高亮器,适用于大多数场景
- plain:传统高亮器,适用于小片段**
- fvh(Fast Vector Highlighter):快速向量高亮器,适用于大文档**
示例:
1 | |
面试加分回答:
- 可以讲讲 高亮的性能问题(高亮需要重新分析文本,会消耗 CPU)
- 可以讲讲 如何优化高亮性能(使用
fvh,提前存储词项向量) - 可以讲讲实际项目中的优化(比如禁用高亮
_score以提高性能)
Q27:Elasticsearch 的建议器(Suggester)是什么?
一句话总结:建议器是 ES 的搜索建议功能,包括:Term Suggester、Phrase Suggester、Completion Suggester。
深度解析:
建议器的类型:
- Term Suggester:拼写纠正(比如输入 “elasticserch”,建议 “elasticsearch”)
- Phrase Suggester:短语建议(基于 Term Suggester,但考虑词组)
- Completion Suggester:自动补全(输入 “ela”,建议 “elasticsearch”)
示例:
1 | |
面试加分回答:
- 可以讲讲 建议器的使用场景(比如搜索框的自动补全、拼写纠正)
- 可以讲讲 如何优化建议器的性能(使用
completion类型,存储在内存中) - 可以讲讲实际项目中的应用(比如电商搜索的自动补全)
Q28:Elasticsearch 的地理位置搜索(Geo Search)是什么?
一句话总结:地理位置搜索是 ES 的基于地理位置的搜索功能,包括:地理距离查询、地理边界查询、地理聚合。
深度解析:
地理位置字段类型:
- geo_point:一个点(经纬度)
- geo_shape:一个形状(圆形、多边形等)
地理位置查询:
- geo_distance:查询距离指定坐标一定范围内的文档
- geo_bounding_box:查询在指定矩形范围内的文档
- geo_polygon:查询在指定多边形范围内的文档**
示例:
1 | |
面试加分回答:
- 可以讲讲 地理位置搜索的使用场景(比如附近的商家、配送范围)
- 可以讲讲 如何优化地理位置搜索的性能(使用
geo_point类型,启用doc_values) - 可以讲讲实际项目中的应用(比如外卖平台的附近商家搜索)
Q29:Elasticsearch 的多索引搜索(Multi-Index Search)是什么?
一句话总结:多索引搜索是 ES 的同时搜索多个索引的功能,可以通过索引模式、别名实现。
深度解析:
多索引搜索的方式:
- 指定多个索引:
GET /index1,index2/_search - 使用索引模式:
GET /log-*/_search - 使用别名:
GET /logs/_search(别名可以指向多个索引)
示例:
1 | |
面试加分回答:
- 可以讲讲 多索引搜索的使用场景(比如日志索引、时间序列索引)
- 可以讲讲 如何优化多索引搜索的性能(使用别名、限制搜索的索引数量)
- 可以讲讲实际项目中的最佳实践(总是使用别名)
Q30:Elasticsearch 的批量操作(Bulk API)是什么?
一句话总结:Bulk API 是 ES 的批量执行多个操作的功能,可以显著提高写入性能。
深度解析:
Bulk API 的操作类型:
- index:索引文档(如果已存在则覆盖)
- create:创建文档(如果已存在则报错)
- update:更新文档(部分更新)
- delete:删除文档**
Bulk API 的格式:
1 | |
示例:
1 | |
面试加分回答:
- 可以讲讲 Bulk API 的性能优化(批量大小控制在 5-15MB)
- 可以讲讲 Bulk API 的错误处理(某个操作失败不会影响其他操作)
- 可以讲讲实际项目中的应用(比如批量导入数据、批量更新数据)
第四部分:Elasticsearch 集群和分布式(Q31-Q40)
Q31:Elasticsearch 的集群健康状态(Cluster Health)有哪些?
一句话总结:ES 的集群健康状态包括:绿色(Green)、黄色(Yellow)、红色(Red)。
深度解析:
集群健康状态:
- 绿色(Green):所有主分片和副本分片都可用
- 黄色(Yellow):所有主分片可用,但有些副本分片不可用
- 红色(Red):有些主分片不可用
查看集群健康状态:
1 | |
面试加分回答:
- 可以讲讲 为什么集群状态是黄色(因为副本分片没有地方分配,比如只有一个节点)
- 可以讲讲 如何处理红色状态(找到不可用主分片的原因,可能是节点故障)
- 可以讲讲实际项目中的监控(比如使用 Watcher 监控集群健康状态)
Q32:Elasticsearch 的节点发现(Node Discovery)是什么?
一句话总结:节点发现是 ES 的节点加入集群的机制,包括:Zen Discovery(ES 7.x 之前)和 Coordinator(ES 7.x 之后)。
深度解析:
Zen Discovery(ES 7.x 之前):
- 使用 单播(Unicast) 或 多播(Multicast) 发现节点
- 需要配置
discovery.zen.ping.unicast.hosts - 需要配置
discovery.zen.minimum_master_nodes(防止脑裂)
Coordinator(ES 7.x 之后):
- 使用 Coordinator 节点 管理集群状态
- 自动发现节点(不需要手动配置)
- 防止脑裂(内部实现)
示例:
1 | |
面试加分回答:
- 可以讲讲 为什么 ES 7.x 废弃了 zen discovery(容易配置错误,导致脑裂)
- 可以讲讲 如何避免脑裂问题
- 可以讲讲实际项目中的部署方案(比如 3 个 Coordinator 节点)
Q33:Elasticsearch 的主节点选举(Master Election)是什么?
一句话总结:主节点选举是 ES 的选举主节点的机制,保证集群有唯一的主节点管理集群状态。
深度解析:
主节点选举的流程:
- 节点启动:节点尝试加入集群(或形成集群)
- 选举临时主节点:从候选主节点中选举一个作为临时主节点
- 投票:候选主节点向临时主节点投票
- 选举成功:如果临时主节点获得 超过半数 的候选主节点投票,则成为正式主节点
- 选举失败:如果没有候选主节点获得超过半数投票,则重新选举
防止脑裂:
- minimum_master_nodes:最少候选主节点数量(ES 7.x 之前)
- 公式:
minimum_master_nodes = (候选主节点数量 / 2) + 1
示例:
1 | |
面试加分回答:
- 可以讲讲 主节点选举的原理(类似 Raft 协议)
- 可以讲讲 为什么需要超过半数投票(防止脑裂)
- 可以讲讲实际项目中的部署方案(比如 3 个候选主节点)
Q34:Elasticsearch 的分片分配(Shard Allocation)是什么?
一句话总结:分片分配是 ES 的将分片分配到节点的机制,包括:主分片分配、副本分片分配、再平衡。
深度解析:
分片分配的阶段:
- 主分片分配:当索引创建时,主分片分配到哪些节点
- 副本分片分配:当主分片分配完成后,副本分片分配到哪些节点(不能和主分片在同一个节点)
- 再平衡:当节点加入或离开时,重新分配分片(保持平衡)
分片分配的策略:
- Same Shard Policy:不要让主分片和副本分片在同一个节点
- Awareness Policy:按机房、机架分配分片(提高容灾能力)
- Filter Policy:允许/禁止将分片分配到某些节点**
示例:
1 | |
面试加分回答:
- 可以讲讲 如何优化分片分配(按机房分配、控制每个节点的分片数量)
- 可以讲讲 如何手动迁移分片(使用
cluster rerouteAPI) - 可以讲讲实际项目中的经验(比如避免单个节点分配过多分片)
Q35:Elasticsearch 的写入一致性(Write Consistency)是什么?
一句话总结:写入一致性是 ES 的控制写入操作需要多少副本分片可用的机制,包括:all、quorum、one。
深度解析:
写入一致性的级别:
- all:所有副本分片都可用(最强一致性)
- quorum:大部分副本分片可用(默认,公式是
(主分片数量 + 副本分片数量) / 2 + 1) - one:只要主分片可用(最弱一致性)
示例:
1 | |
面试加分回答:
- 可以讲讲 写入一致性和可用性的权衡(
all一致性最强,但可用性最差) - 可以讲讲 如何保证数据不丢失(设置
wait_for_active_shards=all) - 可以讲讲实际项目中的配置(比如金融场景用
all,日志场景用one)
Q36:Elasticsearch 的读取一致性(Read Consistency)是什么?
一句话总结:读取一致性是 ES 的控制读取操作从哪个分片读取的机制,包括:all、quorum、one。
深度解析:
读取一致性的级别:
- all:从所有分片读取(最慢,但结果最准确)
- quorum:从大部分分片读取
- one:从单个分片读取(最快,但结果可能不准确)
ES 的实际实现:
- ES 没有 读取一致性级别(和 Cassandra 不同)
- ES 的读取请求会自动路由到相关分片(主分片或副本分片)
- 但可以通过 preference 参数控制读取哪个分片
示例:
1 | |
面试加分回答:
- 可以讲讲 ES 为什么没有读取一致性级别(因为 ES 是近实时搜索,主分片和副本分片可能有延迟)
- 可以讲讲 如何保证读取结果准确(使用
preference=_primary) - 可以讲讲实际项目中的配置(比如提高缓存命中率,使用
preference=session_id)
Q37:Elasticsearch 的集群扩容(Cluster Scaling)是什么?
一句话总结:集群扩容是 ES 的增加节点的操作,可以提高容量和提高性能。
深度解析:
扩容的方式:
- 增加数据节点:提高容量和读取性能
- 增加协调节点:提高请求路由性能
- 增加预处理节点:提高文档预处理性能**
扩容的限制:
- 主分片数量不能修改(如果容量不够,需要重建索引)
- 但可以增加副本分片数量(提高读取性能)
示例:
1 | |
面试加分回答:
- 可以讲讲 如何规划集群规模(根据数据量、写入 QPS、读取 QPS)
- 可以讲讲 如何避免扩容时的性能问题(控制分片分配速率)
- 可以讲讲实际项目中的扩容方案(比如滚动扩容,逐个重启节点)
Q38:Elasticsearch 的集群缩容(Cluster Shrink)是什么?
一句话总结:集群缩容是 ES 的减少节点的操作,通常用于下线故障节点或降低硬件成本。
深度解析:
缩容的步骤:
- 迁移分片:将待下线节点上的分片迁移到其他节点
- 等待集群状态变为绿色:确保所有分片都有副本
- 下线节点:关闭待下线节点
示例:
1 | |
面试加分回答:
- 可以讲讲 如何安全下线节点(先迁移分片,再下线)
- 可以讲讲 如何避免缩容时的数据丢失(确保副本分片可用)
- 可以讲讲实际项目中的缩容方案(比如滚动缩容,逐个下线节点)
Q39:Elasticsearch 的跨集群搜索(Cross-Cluster Search)是什么?
一句话总结:跨集群搜索是 ES 的搜索多个集群的功能,适用于多数据中心、冷热分离场景。
深度解析:
跨集群搜索的配置:
- 配置远程集群:在本地集群中配置远程集群的连接信息
- 搜索远程集群:使用
集群别名:前缀搜索远程集群
示例:
1 | |
面试加分回答:
- 可以讲讲 跨集群搜索的使用场景(比如多数据中心、冷热分离)
- 可以讲讲 如何优化跨集群搜索的性能(使用 CCR(Cross-Cluster Replication) 复制数据到本地集群)
- 可以讲讲实际项目中的应用(比如搜索历史数据,从远程集群搜索)
Q40:Elasticsearch 的跨集群复制(CCR - Cross-Cluster Replication)是什么?
一句话总结:跨集群复制是 ES 的复制索引到远程集群的功能,适用于灾备、就近读取场景。
深度解析:
CCR 的使用场景:
- 灾备:将索引复制到远程集群,防止数据中心故障
- 就近读取:将索引复制到多个数据中心,提高读取性能
- 数据本地化:将全局索引复制到本地集群,减少跨数据中心延迟**
示例:
1 | |
面试加分回答:
- 可以讲讲 CCR 和跨集群搜索的区别(CCR 是复制数据,跨集群搜索是远程搜索)
- 可以讲讲 如何优化 CCR 的性能(使用自动跟随模式,自动复制新索引)
- 可以讲讲实际项目中的应用(比如灾备方案,将索引复制到远程集群)
第五部分:Elasticsearch 性能优化(Q41-Q50)
Q41:Elasticsearch 的写入性能优化有哪些?
一句话总结:写入性能优化包括:禁用刷新、禁用副本、使用 Bulk API、增加刷新间隔、使用 SSD。
深度解析:
写入性能优化技巧:
- 禁用刷新:
index.refresh_interval: -1(批量导入完成后恢复) - 禁用副本:
index.number_of_replicas: 0(批量导入完成后恢复) - 使用 Bulk API:批量写入(批量大小控制在 5-15MB)
- 增加刷新间隔:
index.refresh_interval: 30s(降低刷新频率) - 使用 SSD:SSD 的随机 I/O 性能远好于机械硬盘**
示例:
1 | |
面试加分回答:
- 可以讲讲 如何平衡写入性能和搜索实时性(根据业务需求调整
refresh_interval) - 可以讲讲 如何使用 Bulk API 的最佳实践(控制批量大小、并行写入)
- 可以讲讲实际项目中的优化经验(比如日志导入,禁用刷新和副本)
Q42:Elasticsearch 的读取性能优化有哪些?
一句话总结:读取性能优化包括:增加副本、使用文件系统缓存、优化 mapping、使用 filter 查询、避免深度分页。
深度解析:
读取性能优化技巧:
- 增加副本:提高读取吞吐量(但需要更多硬件资源)
- 使用文件系统缓存:Linux 会自动缓存文件(需要足够的内存)
- 优化 mapping:禁用不需要搜索的字段、使用 keyword 类型
- 使用 filter 查询:filter 查询不贡献评分,会使用缓存
- 避免深度分页:使用
search_after代替from/size
示例:
1 | |
面试加分回答:
- 可以讲讲 如何优化聚合性能(使用
doc_values、控制聚合数量) - 可以讲讲 如何优化排序性能(使用
doc_values) - 可以讲讲实际项目中的优化经验(比如为热数据增加副本)
Q43:Elasticsearch 的硬件选择有哪些建议?
一句话总结:ES 的硬件选择建议:CPU 不需要太强(主要瓶颈在 I/O 和内存)、内存要足够(文件系统缓存)、使用 SSD(提高 I/O 性能)、网络要快(分布式系统)。
深度解析:
硬件选择建议:
- CPU:2-8 核(不需要太强,ES 主要瓶颈在 I/O 和内存)
- 内存:64GB-128GB(一半给 ES,一半给文件系统缓存)
- 磁盘:SSD(提高 I/O 性能,尤其是写入性能)
- 网络:千兆网卡或万兆网卡(分布式系统,节点间通信频繁)
示例:
1 | |
面试加分回答:
- 可以讲讲 为什么 JVM 堆内存不要超过 32GB(因为 JVM 的压缩指针机制,超过 32GB 后效率下降)
- 可以讲讲 如何监控硬件资源使用率(使用
node.statsAPI) - 可以讲讲实际项目中的硬件选择经验(比如热数据用 SSD,冷数据用机械硬盘)
Q44:Elasticsearch 的 JVM 堆内存优化有哪些?
一句话总结:JVM 堆内存优化包括:设置合适的堆内存大小、避免频繁 Full GC、使用 G1GC。
深度解析:
JVM 堆内存优化技巧:
- 设置合适的堆内存大小:
Xms和Xmx设置为相同值(避免动态调整) - 不要超过 32GB:因为 JVM 的压缩指针机制,超过 32GB 后效率下降
- 使用 G1GC:ES 默认使用 G1GC(适合大堆内存)
示例:
1 | |
面试加分回答:
- 可以讲讲 如何监控 JVM 堆内存使用率(使用
node.statsAPI 或 Kibana) - 可以讲讲 如何避免频繁 Full GC(增加堆内存、优化查询)
- 可以讲讲实际项目中的调优案例(比如解决 OOM 问题)
Q45:Elasticsearch 的索引性能监控有哪些指标?
一句话总结:索引性能监控指标包括:索引速率、索引延迟、索引拒绝次数、合并速率、刷写速率。
深度解析:
索引性能监控指标:
- 索引速率(Index Rate):每秒索引多少文档
- 索引延迟(Index Latency):索引一个文档需要多少时间
- 索引拒绝次数(Index Rejected):线程池拒绝次数(如果很高,说明写入过载)
- 合并速率(Merge Rate):每秒合并多少文档
- 刷写速率(Flush Rate):每秒刷写多少次**
示例:
1 | |
面试加分回答:
- 可以讲讲 如何判断写入过载(索引拒绝次数 > 0)
- 可以讲讲 如何优化写入性能(增加线程池大小、优化 mapping)
- 可以讲讲实际项目中的监控方案(比如使用 Prometheus + Grafana 监控 ES 指标)
Q46:Elasticsearch 的搜索性能监控有哪些指标?
一句话总结:搜索性能监控指标包括:搜索速率、搜索延迟、搜索拒绝次数、缓存命中率、内存使用率。
深度解析:
搜索性能监控指标:
- 搜索速率(Search Rate):每秒执行多少次搜索
- 搜索延迟(Search Latency):搜索需要多少时间
- 搜索拒绝次数(Search Rejected):线程池拒绝次数(如果很高,说明搜索过载)
- 缓存命中率(Cache Hit Rate):filter 查询缓存命中率
- 内存使用率(Memory Usage):JVM 堆内存使用率**
示例:
1 | |
面试加分回答:
- 可以讲讲 如何判断搜索过载(搜索拒绝次数 > 0)
- 可以讲讲 如何优化搜索性能(增加副本、使用 filter 查询、优化 mapping)
- 可以讲讲实际项目中的监控方案(比如使用 Elastic APM 监控搜索性能)
Q47:Elasticsearch 的常见性能问题有哪些?
一句话总结:常见性能问题包括:写入过载、搜索过载、内存不足、磁盘 I/O 瓶颈、网络延迟。
深度解析:
常见性能问题及解决方案:
- 写入过载:索引拒绝次数 > 0 → 增加数据节点、优化 mapping、使用 Bulk API
- 搜索过载:搜索拒绝次数 > 0 → 增加数据节点、增加副本、优化查询
- 内存不足:JVM 堆内存使用率 > 75% → 增加堆内存、优化查询、增加节点
- 磁盘 I/O 瓶颈:磁盘 I/O 使用率 > 80% → 使用 SSD、增加节点**
- 网络延迟:节点间通信延迟高 → 使用万兆网卡、将节点部署在同一个机房**
面试加分回答:
- 可以讲讲 如何排查性能问题(使用
node.statsAPI、查看日志) - 可以讲讲 如何优化性能(硬件升级、配置调优、查询优化)
- 可以讲讲实际项目中的性能问题案例(比如解决写入拒绝问题)
Q48:Elasticsearch 的数据建模最佳实践有哪些?
一句话总结:数据建模最佳实践包括:避免过度嵌套、使用非规范化数据、合理使用父子关系、控制字段数量。
深度解析:
数据建模最佳实践:
- 避免过度嵌套:嵌套查询较慢,如果嵌套层级很深,性能会很差
- 使用非规范化数据:将关联数据存储在同一文档中(提高查询性能)
- 合理使用父子关系:父子关系查询较慢,如果不需要独立更新子文档,使用嵌套对象或非规范化数据
- 控制字段数量:字段数量过多会导致 mapping 爆炸,影响性能**
示例:
1 | |
面试加分回答:
- 可以讲讲 如何选择合适的关联数据模型(嵌套对象 vs 父子关系 vs 非规范化数据)
- 可以讲讲 如何避免 mapping 爆炸(禁用动态映射、使用
nested类型) - 可以讲讲实际项目中的数据建模案例(比如电商搜索的数据建模)
Q49:Elasticsearch 的备份和恢复(Snapshot and Restore)是什么?
一句话总结:备份和恢复是 ES 的数据备份功能,可以将索引备份到远程仓库(比如 HDFS、S3),然后恢复。
深度解析:
备份和恢复的步骤:
- 创建快照仓库:配置远程仓库(比如 HDFS、S3)
- 创建快照:备份索引
- 恢复快照:恢复索引**
示例:
1 | |
面试加分回答:
- 可以讲讲 备份和恢复的使用场景(比如数据迁移、灾难恢复)
- 可以讲讲 如何自动化备份(使用 Watcher 定时创建快照)
- 可以讲讲实际项目中的备份方案(比如每天备份一次,保留最近 7 天的快照)
Q50:Elasticsearch 的安全机制(Security)有哪些?
一句话总结:ES 的安全机制包括:身份认证、权限控制、传输加密、审计日志。
深度解析:
ES 的安全功能(需要安装 X-Pack 插件):
- 身份认证:使用 Realm(比如 Native Realm、LDAP Realm)
- 权限控制:使用 Role 和 User
- 传输加密:使用 TLS/SSL 加密节点间通信
- 审计日志:记录用户操作**
示例:
1 | |
面试加分回答:
- 可以讲讲 为什么需要启用安全机制(防止未授权访问、保护敏感数据)
- 可以讲讲 如何集成 LDAP/AD(使用 LDAP Realm)
- 可以讲讲实际项目中的安全方案(比如启用身份认证和权限控制)
🎯 加餐:向量检索与 KNN + BM25 rescore 混合检索
这一节是我在项目里真正用到的部分,也是简历上写了向量检索之后最容易被面试官深挖的地方,务必吃透——尤其是要分清楚 rescore(重打分) 和 RRF(倒数排名融合) 是两种完全不同的混合检索思路,不要在面试里说混。
Q51:Elasticsearch 的 dense_vector 和 kNN 搜索是什么?
一句话总结:dense_vector 是 ES 用来存储向量的字段类型,kNN 搜索基于 HNSW(分层可导航小世界图) 做近似最近邻检索,用向量相似度而不是关键词匹配来召回文档。
深度解析:
dense_vector 字段定义:
1 | |
kNN 搜索请求(近似最近邻):
1 | |
num_candidates 与 k 的关系(面试常问):
num_candidates必须 ≥ k:它是 HNSW 图在单个分片内部探索、比较的候选数量,最终只从这些候选里选出 Top-k 返回给协调节点做全局合并num_candidates越大,越接近精确(brute-force)最近邻的召回效果,但查询延迟和 CPU 开销也越大;越小则越快,但可能漏掉真正的近邻(这就是”近似”最近邻的近似之处)- 经验做法:
num_candidates取k的几倍到十几倍(比如 k=10 时 num_candidates 取 50~100),根据召回率要求和延迟预算去调
Q52:KnowFlow 如何把 KNN 与 BM25 结合,并守住权限边界?
HybridSearchService.permissionSearchRequest 在同一 ES 请求中设置顶层 knn 与文本 query。ES 会按 OR 合并两路候选,随后对窗口内结果执行 BM25 rescore:原始分数权重 0.2,重排查询权重 1.0。这属于分数加权重排,不是 RRF。RRF 需要对独立排行榜按名次计算 Σ1/(k+rank)。
权限过滤必须同时放进 knn.filter 和文本 query.bool.filter。只在文本分支过滤,向量分支仍可能召回无权访问的文档。当前源码为两路复用同一条件:本人文档、公开文档、所属组织文档至少满足一个。新增的 3 项请求结构回归测试通过;真实 ES 集成验证仍待完成。
topK × 30 是 KNN 候选窗口配置,不等于准确率或召回率的实测提升。项目缺少可复核的检索评测集,因此面试时应讲清机制与风险,不报检索效果百分比。
追问:为什么不能只在返回结果后过滤? 这样可能得到不足 topK 条结果,也不能避免无权文档参与向量候选与评分。应在每条召回路径进入候选池前加权限条件。
追问:如何验证? 除请求结构单测,还应在真实 ES 索引中放入本人、公开、同组织和其他私有文档,分别使用只命中向量或只命中文本的查询,断言其他私有文档永不出现。衡量排序收益需要独立标注集与 Recall@K/MRR 等指标。
💪 实战演练(真实面试场景)
🎯 面试技巧:面试时遇到 Elasticsearch 问题,不要只背概念,要结合实际项目经验回答。
场景 1:请你设计一个电商搜索系统?
回答思路:
- 数据建模:商品数据如何存储(使用非规范化数据,将商品信息、库存信息、价格信息存储在同一文档中)
- 分词器选择:中文分词器(使用 IK Analyzer)
- 搜索类型:全文搜索(使用
match查询)、过滤搜索(使用filter查询) - 排序:按评分排序、按销量排序、按价格排序
- 分页:使用
search_after实现无限滚动分页** - 性能优化:增加副本、使用文件系统缓存、使用 filter 查询**
场景 2:如何优化 ES 的写入性能?
回答思路:
- 禁用刷新和副本(批量导入时)
- 使用 Bulk API(批量写入)
- 增加刷新间隔(降低刷新频率)
- 使用 SSD(提高 I/O 性能)
- 优化 mapping(禁用不需要搜索的字段)
场景 3:ES 集群状态是红色,如何排查?
回答思路:
- 查看集群健康状态:
GET /_cluster/health - 查看未分配的分片:
GET /_cat/shards?h=index,shard,prirep,state,unassigned.reason - 查看节点状态:
GET /_cat/nodes - 查看日志:
tail -f logs/elasticsearch.log - 解决方案:如果是节点故障,下线故障节点,恢复副本分片**
📚 扩展学习资源**
📖 持续学习:Elasticsearch 发展很快,要保持学习状态。
官方资源
书籍推荐
- 《Elasticsearch 实战》(Elasticsearch in Action)
- 《Elasticsearch 权威指南》(旧版,但基础概念讲得好)
博客推荐
🚀 学习路径总结
第一阶段:基础概念(1-2 天)
- 理解 Lucene 和倒排索引
- 理解 ES 的核心概念(索引、文档、字段、映射)
- 理解 ES 的分布式架构(分片、副本、节点、集群)
- 掌握文档 CRUD 操作
第二阶段:搜索功能(2-3 天)
- 掌握全文搜索(Match 查询)
- 掌握结构化搜索(Term 查询、Range 查询)
- 掌握布尔查询(Bool 查询)
- 掌握聚合搜索(指标聚合、桶聚合)
- 掌握排序和分页
第三阶段:分布式架构(2-3 天)
- 理解节点发现和主节点选举
- 理解分片分配和再平衡
- 理解写入一致性和读取一致性
- 掌握集群扩容和缩容
第四阶段:性能优化(2-3 天)
- 掌握写入性能优化
- 掌握读取性能优化
- 掌握硬件选择和 JVM 调优
- 掌握性能监控和故障排查
第五阶段:实战应用(1 周+)
- 搭建一个 ES 集群
- 实现一个电商搜索系统
- 实现一个日志分析系统
- 阅读 ES 源码(可选)
第六阶段:面试准备(1 周)
- 刷完本文的 50 个问题
- 复习数据结构和算法
- 准备项目经验和面试答案
- 模拟面试
🎓 扩展学习资源
官方资源
书籍推荐
- 《Elasticsearch 实战》(Elasticsearch in Action)
- 《Elasticsearch 权威指南》(旧版,但基础概念讲得好)
博客推荐
视频教程
- Elasticsearch 入门到精通(B站)
- Elasticsearch 核心原理(Elastic 官方 Webinar)
实战项目
💪 最后的鼓励
恭喜你!如果你认真学完了上面的 50 个问题,那么你已经掌握了 Elasticsearch 的核心知识。
下一步建议:
- 动手实践:搭建一个 ES 集群,创建索引,执行搜索
- 阅读源码:如果你对 ES 的实现原理感兴趣,可以阅读 Lucene 源码
- 参与社区:在 Elasticsearch 中文社区回答问题,加深理解
- 准备面试:刷 LeetCode 数据库题目,复习 ES 知识
最后的最后:
- 面试不仅考察知识,还考察思维能力和沟通能力
- 回答问题时,要逻辑清晰、深入浅出
- 遇到不会的问题,不要慌,可以引导到你会的方向
祝你面试顺利!🎉
💡 提示:本文档会持续更新,如果你发现错误或想补充内容,欢迎提 Issue!
🎉 总结
恭喜你!如果你认真学完了上面的 50 个问题,那么你已经掌握了 Elasticsearch 的核心知识。
下一步建议:
- 动手实践:搭建一个 ES 集群,创建索引,执行搜索
- 阅读源码:如果你对 ES 的实现原理感兴趣,可以阅读 Lucene 源码
- 参与社区:在 Elasticsearch 中文社区回答问题,加深理解
- 准备面试:刷 LeetCode 数据库题目,复习 ES 知识**
最后的最后:
- 面试不仅考察知识,还考察思维能力和沟通能力
- 回答问题时,要逻辑清晰、深入浅出
- 遇到不会的问题,不要慌,可以引导到你会的方向
祝你面试顺利!🎉
💡 提示:本文档会持续更新,如果你发现错误或想补充内容,欢迎提 Issue!