Elasticsearch 面试八股文(50题)


title: Elasticsearch 面试八股文(50 题)
date: 2026-06-09 14:30:00
tags:
- 面试
- Elasticsearch
- 搜索
- 分布式
categories: 面试八股文

Elasticsearch 面试八股文(50 题)

📚 面试高频:本文覆盖 Elasticsearch 核心知识点,从基础概念到高级优化,帮你系统掌握 ES 面试要点。

🎯 面试加分:每个问题都包含深度解析和面试加分回答,让你在面试中脱颖而出。

快速掌握:所有问题都附有通俗易懂的解释和实战经验分享。


📖 学习指南

🎯 学习目标:通过本文,你将系统掌握 Elasticsearch 的核心概念、搜索原理、分布式架构和性能优化技巧,能够自信地应对任何 Elasticsearch 相关的面试问题。

适合人群

  • 🔰 初学者:想系统学习 Elasticsearch 的开发者
  • 🚀 有经验者:想深入理解 ES 原理的高级开发者
  • 💼 面试准备者:想刷 Elasticsearch 面试题的求职者

学习建议

  1. 先理解概念,再深入原理:先搞懂”是什么”,再搞懂”为什么”
  2. 结合实战场景:不要死记硬背,要理解实际应用场景
  3. 动手实践:在自己电脑上安装 ES,执行本文的示例代码
  4. 反复复习:面试前一周,每天复习 10 个问题

学习时间估算

  • ⏱️ 快速复习(只看一句话总结):2 小时
  • 📚 系统学习(看深度解析):1-2 天
  • 💪 深入理解(研究源码):1 周+

🗺️ 知识图谱

mindmap
  root((Elasticsearch))
    基础概念
      Lucene
      倒排索引
      近实时搜索
    数据模型
      索引 Index
      文档 Document
      字段 Field
      映射 Mapping
    分布式架构
      分片 Shard
      副本 Replica
      节点 Node
      集群 Cluster
    搜索功能
      全文搜索
      结构化搜索
      聚合搜索
      地理位置搜索
    性能优化
      写入优化
      读取优化
      硬件选择
      JVM 调优
    实战应用
      电商搜索
      日志分析
      监控系统

⚠️ 常见陷阱与误区

陷阱 1:对 text 字段使用 term 查询

错误示例

1
2
3
4
5
6
7
8
GET /my_index/_search
{
"query": {
"term": {
"title": "Elasticsearch 实战" # title 是 text 类型,已经被分词了
}
}
}

正确做法

  • 如果要精确匹配,使用 keyword 类型字段
  • 如果要全文搜索,使用 match 查询

陷阱 2:动态映射导致类型推断错误

错误示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 动态映射可能将 "123" 推断为 long 类型
POST /my_index/_doc
{
"price": "123"
}

# 然后无法精确匹配
GET /my_index/_search
{
"query": {
"term": {
"price": "123" # 无法匹配,因为 price 是 long 类型
}
}
}

正确做法

  • 总是使用静态映射(手动定义 mapping)
  • 禁用动态映射:"dynamic": false

陷阱 3:主分片数量不能修改

错误认知

  • 以为可以动态修改主分片数量

正确认知

  • 主分片数量在索引创建后不能修改(因为路由公式 shard = hash(_routing) % number_of_primary_shards
  • 如果需要修改,只能重建索引

陷阱 4:From/Size 分页不适合深分页

错误做法

1
2
3
4
5
6
# 如果 from=10000,ES 需要从每个分片获取 10010 条结果,性能很差
GET /my_index/_search
{
"from": 10000,
"size": 10
}

正确做法

  • 浅分页(前 1000 条):使用 from/size
  • 深分页(导出数据):使用 scroll
  • 深分页(实时分页):使用 search_after

陷阱 5:忽略副本分片的重要性

错误做法

  • 为了节省磁盘空间,禁用副本分片

正确做法

  • 生产环境至少设置 1 个副本
  • 副本分片提供高可用(主分片故障时,副本分片可以提升为主分片)
  • 副本分片可以提高读取吞吐量(读取请求可以负载均衡到副本分片)

💡 面试技巧

技巧 1:结构化回答

不要只回答”是什么”,要按照以下结构回答:

  1. 一句话总结(概念)
  2. 深度解析(原理、实现、优缺点)
  3. 面试加分回答(实际项目经验、源码理解、行业最佳实践)

示例

面试官:什么是倒排索引?

  1. 一句话总结:倒排索引是 ES 的核心数据结构,通过词项(Term)→ 文档列表(Posting List)的映射,实现快速全文搜索。
  2. 深度解析:倒排索引包括词项字典(Term Dictionary)和倒排列表(Posting List),词项字典用 FST 压缩存储,倒排列表用 Roaring Bitmap 压缩存储。
  3. 面试加分回答:我在实际项目中,曾经因为倒排索引占用太多内存,导致查询性能下降。后来通过禁用不需要搜索的字段的索引,减少了倒排索引的大小,查询性能提升了 30%。

技巧 2:结合实战场景

不要只背概念,要结合实际项目经验回答。

示例

面试官:如何优化 ES 的写入性能?

  1. 禁用刷新和副本(批量导入时)
  2. 使用 Bulk API(批量写入)
  3. 增加刷新间隔(降低刷新频率)
  4. 使用 SSD(提高 I/O 性能)

我在上一家公司,每天需要将 1000 万条日志导入 ES。最初直接单条写入,导入需要 2 小时。后来我使用了 Bulk API(批量大小 5MB),并临时禁用刷新和副本,导入时间缩短到 20 分钟,性能提升了 6 倍。

技巧 3:引导到你会的方向

如果遇到不会的问题,不要慌,可以引导到你会的方向。

示例

面试官:ES 的 Translog 是什么?

:(如果你不熟悉 Translog,可以引导到你会的方向)
我对 Translog 了解不深,但我知道 ES 的写入流程是:先写入内存缓冲区,然后定期刷新到文件系统缓存,最后刷写到磁盘。为了保证数据不丢失,ES 会使用 Translog 记录所有写操作。我更熟悉的是 ES 的分布式架构和搜索原理…

技巧 4:展示学习能力和技术热情

面试官不仅考察你的知识储备,还考察你的学习能力和技术热情。

示例

面试官:你如何保持对 ES 的学习?

  1. 阅读官方文档(每周至少阅读 1 个模块)
  2. 阅读源码(我已经阅读了 Lucene 的倒排索引实现)
  3. 参与社区(在 Elasticsearch 中文社区回答问题)
  4. 实践项目(自己搭建了一个日志分析系统,使用 ELK Stack)

📋 目录


🎯 面试高频问题与答题思路

高频问题 1:设计一个电商搜索系统

答题思路

  1. 数据建模:商品数据如何存储(使用非规范化数据,将商品信息、库存信息、价格信息存储在同一文档中)
  2. 分词器选择:中文分词器(使用 IK Analyzer)
  3. 搜索类型:全文搜索(使用 match 查询)、过滤搜索(使用 filter 查询)
  4. 排序:按评分排序、按销量排序、按价格排序
  5. 分页:使用 search_after 实现无限滚动分页
  6. 性能优化:增加副本、使用文件系统缓存、使用 filter 查询

高频问题 2:如何优化 ES 的写入性能?

答题思路

  1. 禁用刷新和副本(批量导入时)
  2. 使用 Bulk API(批量写入)
  3. 增加刷新间隔(降低刷新频率)
  4. 使用 SSD(提高 I/O 性能)
  5. 优化 mapping(禁用不需要搜索的字段)

高频问题 3:ES 集群状态是红色,如何排查?

答题思路

  1. 查看集群健康状态GET /_cluster/health
  2. 查看未分配的分片GET /_cat/shards?h=index,shard,prirep,state,unassigned.reason
  3. 查看节点状态GET /_cat/nodes
  4. 查看日志tail -f logs/elasticsearch.log
  5. 解决方案:如果是节点故障,下线故障节点,恢复副本分片

第一部分: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
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看索引的设置
GET /my_index/_settings

# 返回:
{
"my_index": {
"settings": {
"index": {
"number_of_shards": "3", # 3 个主分片
"number_of_replicas": "1" # 每个主分片有 1 个副本
}
}
}
}

面试加分回答

  • 可以讲讲分片数量为什么不能修改(因为路由公式 shard = hash(_routing) % number_of_primary_shards
  • 可以讲讲如何规划分片数量(根据数据量和硬件资源)
  • 可以讲讲实际项目中的分片策略(比如按时间滚动索引)

Q3:Elasticsearch 的倒排索引(Inverted Index)是什么?

一句话总结:倒排索引是 ES 的核心数据结构,通过词项(Term)→ 文档列表(Posting List) 的映射,实现快速全文搜索。

深度解析

正排索引 vs 倒排索引

  • 正排索引(比如数据库索引):通过 ID → 内容 查找
  • 倒排索引:通过 词项 → 文档 ID 列表 查找

倒排索引的组成

  1. 词项字典(Term Dictionary):存储所有词项,按字典序排列(用 FST 压缩存储)
  2. 倒排列表(Posting List):存储包含该词项的文档 ID 列表(用 Roaring Bitmap 压缩存储)

示例

1
2
3
4
5
6
7
8
9
文档 1: "I love Elasticsearch"
文档 2: "Elasticsearch is fast"
文档 3: "I love fast search"

倒排索引:
"I" → [1, 3]
"love" → [1, 3]
"Elasticsearch" → [1, 2]
"fast" → [2, 3]

面试加分回答

  • 可以讲讲 FST(Finite State Transducer) 如何压缩词项字典
  • 可以讲讲 Roaring Bitmap 如何压缩倒排列表
  • 可以讲讲实际项目中的优化(比如禁用倒排索引的字段)

Q4:Elasticsearch 的文档 CRUD 操作有哪些?

一句话总结:ES 的文档 CRUD 操作包括:索引(Index)创建(Create)读取(Get)更新(Update)删除(Delete)

深度解析

CRUD 操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. 索引文档(ID 由 ES 自动生成)
POST /my_index/_doc
{
"title": "Elasticsearch 实战",
"author": "张三",
"price": 99
}

# 2. 创建文档(指定 ID,如果已存在则报错)
PUT /my_index/_create/1
{
"title": "Elasticsearch 实战",
"author": "张三",
"price": 99
}

# 3. 读取文档
GET /my_index/_doc/1

# 4. 更新文档(部分更新)
POST /my_index/_update/1
{
"doc": {
"price": 79
}
}

# 5. 删除文档
DELETE /my_index/_doc/1

面试加分回答

  • 可以讲讲 Index vs Create 的区别(PUT /_create/ 如果 ID 已存在则报错,POST /_doc/PUT /_doc/ 会覆盖)
  • 可以讲讲 Update 的内部原理(先获取文档,修改,再索引)
  • 可以讲讲实际项目中的最佳实践(比如使用 Bulk API 批量操作)

Q5:Elasticsearch 的搜索类型有哪些?

一句话总结:ES 的搜索类型包括:全文搜索结构化搜索聚合搜索地理位置搜索

深度解析

1. 全文搜索

1
2
3
4
5
6
7
8
9
# Match 查询(分词后搜索)
GET /my_index/_search
{
"query": {
"match": {
"title": "Elasticsearch 实战"
}
}
}

2. 结构化搜索

1
2
3
4
5
6
7
8
9
# Term 查询(精确匹配)
GET /my_index/_search
{
"query": {
"term": {
"status": 1
}
}
}

3. 聚合搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 按作者分组,统计每本书的平均价格
GET /my_index/_search
{
"aggs": {
"by_author": {
"terms": {
"field": "author.keyword"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}

4. 地理位置搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查询距离指定坐标 1km 内的文档
GET /my_index/_search
{
"query": {
"geo_distance": {
"distance": "1km",
"location": {
"lat": 40.7128,
"lon": -74.0060
}
}
}
}

面试加分回答

  • 可以讲讲 Match vs Term 的区别(match 会分词,term 不会分词)
  • 可以讲讲 聚合的性能优化(比如 size: 0 不返回文档,只返回聚合结果)
  • 可以讲讲实际项目中的应用(比如商品搜索、用户画像分析)

Q6:Elasticsearch 的 mapping(映射)是什么?

一句话总结:Mapping 是 ES 的数据模式定义,定义了文档的字段类型、分词器、是否索引等属性。

深度解析

Mapping 的类型

  1. 动态映射(Dynamic Mapping):ES 自动推断字段类型(不推荐,因为可能推断错误)
  2. 静态映射(Explicit Mapping):手动定义字段类型(推荐)

字段类型

  • text:用于全文搜索(会分词)
  • keyword:用于结构化搜索(不会分词)
  • integerlongfloatdouble:数值类型
  • date:日期类型
  • boolean:布尔类型
  • geo_point:地理位置类型

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建索引时定义 mapping
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text", # 全文搜索
"analyzer": "ik_max_word" # 中文分词器
},
"author": {
"type": "keyword" # 精确匹配
},
"price": {
"type": "float" # 数值类型
},
"publish_date": {
"type": "date" # 日期类型
}
}
}
}

面试加分回答

  • 可以讲讲 text vs keyword 的区别(text 会分词,用于全文搜索;keyword 不会分词,用于精确匹配)
  • 可以讲讲 动态映射的风险(比如数字被推断为 long,导致无法精确匹配)
  • 可以讲讲实际项目中的最佳实践(** always 使用静态映射**)

Q7:Elasticsearch 的分词器(Analyzer)是什么?

一句话总结:分词器是 ES 用于处理文本字段的组件,包括:字符过滤器(Character Filter)分词器(Tokenizer)词项过滤器(Token Filter)

深度解析

分词器的组成

  1. 字符过滤器:预处理文本(比如去除 HTML 标签)
  2. 分词器:将文本切分成词项(比如按空格分词)
  3. 词项过滤器:后处理词项(比如转小写、去除停用词、添加同义词)

内置分词器

  • Standard Analyzer:默认分词器,按词切分,转小写
  • Simple Analyzer:按非字母字符切分,转小写
  • Whitespace Analyzer:按空格切分
  • IK Analyzer:中文分词器(需要安装插件)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 测试分词器
POST /_analyze
{
"analyzer": "standard",
"text": "I love Elasticsearch"
}

# 返回:
{
"tokens": [
{ "token": "i", "position": 0 },
{ "token": "love", "position": 1 },
{ "token": "elasticsearch", "position": 2 }
]
}

面试加分回答

  • 可以讲讲 如何选择合适的分词器(英文用 standard,中文用 ik_max_word
  • 可以讲讲 如何自定义分词器(比如添加同义词过滤器)
  • 可以讲讲实际项目中的优化(比如禁用不必要的词项过滤器)

Q8:Elasticsearch 的评分机制(Scoring)是什么?

一句话总结:ES 使用 BM25 算法计算文档的相关性评分(_score),评分越高,排序越靠前。

深度解析

BM25 算法

  • TF-IDF 的改进版
  • 考虑词频(TF)逆文档频率(IDF)
  • 但会对词频进行饱和处理(避免高频词主导评分)

评分公式(简化版):

1
2
3
4
5
6
score = TF * IDF * Field-Length-Norm

其中:
- TF(词频):词项在文档中出现的次数(经过饱和处理)
- IDF(逆文档频率):1 / (包含该词项的文档数)
- Field-Length-Norm(字段长度归一化):1 / sqrt(字段长度)

示例

1
2
3
4
5
6
7
8
9
10
# 查看文档的评分详情
GET /my_index/_search
{
"explain": true,
"query": {
"match": {
"title": "Elasticsearch"
}
}
}

面试加分回答

  • 可以讲讲 如何自定义评分(使用 function_score 查询)
  • 可以讲讲 如何影响评分(比如给新发布的文档加权)
  • 可以讲讲实际项目中的优化(比如取消评分 _score 以提高性能)

Q9:Elasticsearch 的分布式架构是什么?

一句话总结:ES 是分布式系统,通过分片(Shard) 实现水平扩展,通过副本(Replica) 实现高可用。

深度解析

ES 的节点类型

  • 主节点(Master Node):负责集群管理(创建/删除索引、跟踪节点状态)
  • 数据节点(Data Node):负责存储数据和执行搜索
  • 协调节点(Coordinating Node):负责接收客户端请求,路由到正确的节点,合并结果
  • 预处理节点(Ingest Node):负责文档预处理(比如解析附件)

ES 的写入流程

  1. 客户端发送写请求到协调节点
  2. 协调节点根据 文档 ID路由值 计算目标主分片
  3. 协调节点将请求转发到主分片所在节点
  4. 主分片写入成功后,并行转发到所有副本分片
  5. 所有副本分片写入成功后,返回成功给客户端

面试加分回答

  • 可以讲讲 如何规划节点角色(小规模集群可以混合部署,大规模集群应该分离角色)
  • 可以讲讲 如何避免脑裂问题(设置 discovery.zen.minimum_master_nodes
  • 可以讲讲实际项目中的部署方案(比如 3 个主节点 + 多个数据节点)

Q10:Elasticsearch 的近实时搜索(NRT)是什么?

一句话总结:ES 的近实时搜索是指文档索引后,默认可在 1 秒 内被搜索到(不是实时,但接近实时)。

深度解析

为什么不是实时?

  • Lucene 的倒排索引是不可变的(Immutable)
  • 新的文档首先写入内存缓冲区(In-memory Buffer)
  • 然后定期(默认 1 秒)刷新(Refresh)文件系统缓存(File System Cache)
  • 只有刷新后,文档才能被搜索到

刷新(Refresh)vs 刷写(Flush)

  • 刷新(Refresh):将内存缓冲区写入文件系统缓存(轻量级,不保证持久化)
  • 刷写(Flush):将文件系统缓存写入磁盘(重量级,保证持久化)

示例

1
2
3
4
5
6
7
8
9
10
# 手动触发刷新
POST /my_index/_refresh

# 修改刷新间隔(默认 1 秒)
PUT /my_index/_settings
{
"index": {
"refresh_interval": "30s" # 30 秒刷新一次
}
}

面试加分回答

  • 可以讲讲 如何优化刷新间隔(提高写入性能 vs 提高搜索实时性)
  • 可以讲讲 为什么文件系统缓存很重要(Linux 会自动缓存文件,提高搜索性能)
  • 可以讲讲实际项目中的调优(比如批量导入时禁用刷新)

第二部分:Elasticsearch 索引和映射(Q11-Q20)

Q11:Elasticsearch 的索引模板(Index Template)是什么?

一句话总结:索引模板是 ES 的自动应用 mapping 和 settings 的机制,当创建新索引时,如果匹配模板模式,则自动应用模板中的配置。

深度解析

索引模板的组成

  • 索引模式(Index Pattern):匹配哪些索引(比如 log-*
  • Mapping:字段类型定义
  • Settings:索引设置(比如分片数量、刷新间隔)
  • 别名(Alias):索引别名

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 创建索引模板
PUT /_index_template/log_template
{
"index_patterns": ["log-*"], # 匹配所有 log- 开头的索引
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text", "analyzer": "ik_max_word" }
}
},
"aliases": {
"logs": {} # 自动添加别名 logs
}
},
"priority": 10 # 模板优先级(数字越大优先级越高)
}

面试加分回答

  • 可以讲讲 索引模板的使用场景(比如日志索引、时间序列索引)
  • 可以讲讲 如何滚动索引(使用 Rollover API
  • 可以讲讲实际项目中的应用(比如按天创建日志索引)

Q12:Elasticsearch 的别名(Alias)是什么?

一句话总结:别名是 ES 的索引昵称,可以通过别名访问多个索引,实现零停机时间重建索引

深度解析

别名的好处

  1. 简化查询:可以通过一个别名查询多个索引
  2. 零停机时间重建索引:先创建新索引,然后切换别名
  3. 过滤别名:可以给别名添加过滤器,实现多租户

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 创建别名
POST /_aliases
{
"actions": [
{ "add": { "index": "log-2024-01-01", "alias": "logs" }},
{ "add": { "index": "log-2024-01-02", "alias": "logs" }}
]
}

# 通过别名查询
GET /logs/_search
{
"query": { "match_all": {} }
}

# 零停机时间重建索引
POST /_aliases
{
"actions": [
{ "remove": { "index": "my_index_v1", "alias": "my_index" }},
{ "add": { "index": "my_index_v2", "alias": "my_index" }}
]
}

面试加分回答

  • 可以讲讲 别名的实现原理(别名是保存在集群状态中的)
  • 可以讲讲 如何使用别名实现零停机时间重建索引
  • 可以讲讲实际项目中的应用(比如版本化索引)

Q13:Elasticsearch 的动态映射(Dynamic Mapping)有什么问题?

一句话总结:动态映射是 ES 自动推断字段类型的机制,但可能推断错误,导致搜索结果不符合预期

深度解析

动态映射的问题

  1. 数字被推断为 long:比如 "123" 被推断为 long,导致无法精确匹配
  2. 日期被推断为 text:比如 "2024-01-01" 被推断为 text,导致无法按日期范围搜索`
  3. 新字段自动加入 mapping:可能导致 mapping 爆炸(比如动态生成成千上万个字段)

解决方案

  1. 使用静态映射(推荐)
  2. 禁用动态映射"dynamic": false
  3. 严格动态映射"dynamic": "strict"(不允许新字段)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 动态映射可能推断错误
POST /my_index/_doc
{
"price": "123", # 被推断为 long
"date": "2024-01-01" # 被推断为 text
}

# 查询时出现问题
GET /my_index/_search
{
"query": {
"term": {
"price": "123" # 无法匹配,因为 price 是 long 类型
}
}
}

面试加分回答

  • 可以讲讲 为什么应该禁用动态映射
  • 可以讲讲 如何修复错误的 mapping(重建索引)
  • 可以讲讲实际项目中的最佳实践(** always 使用静态映射**)

Q14:Elasticsearch 的嵌套对象(Nested Object)是什么?

一句话总结:嵌套对象是 ES 的复杂数据类型,用于数组中的对象,保持对象的独立性,避免数组扁平化问题

深度解析

数组扁平化问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 错误示例:数组中的对象会被扁平化
PUT /my_index/_doc/1
{
"users": [
{ "name": "张三", "age": 20 },
{ "name": "李四", "age": 30 }
]
}

# 查询时出现问题:
GET /my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "users.name": "张三" }},
{ "match": { "users.age": 30 }} # 会匹配到文档 1(错误!)
]
}
}
}

嵌套对象解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 使用 nested 类型
PUT /my_index
{
"mappings": {
"properties": {
"users": {
"type": "nested", # 嵌套对象类型
"properties": {
"name": { "type": "keyword" },
"age": { "type": "integer" }
}
}
}
}
}

# 查询嵌套对象(必须使用 nested 查询)
GET /my_index/_search
{
"query": {
"nested": {
"path": "users",
"query": {
"bool": {
"must": [
{ "match": { "users.name": "张三" }},
{ "match": { "users.age": 20 }} # 不会匹配到李四
]
}
}
}
}
}

面试加分回答

  • 可以讲讲 nested vs object 的区别(object 类型会扁平化,nested 类型保持独立性)
  • 可以讲讲 nested 的性能问题(嵌套查询较慢,因为需要加载整个嵌套文档)
  • 可以讲讲实际项目中的应用(比如订单中的商品列表)

Q15:Elasticsearch 的父子关系(Parent-Child Relationship)是什么?

一句话总结:父子关系是 ES 的关联数据模型,用于一对多关系,父文档和子文档是独立的文档,但可以联合查询

深度解析

父子关系 vs 嵌套对象

对比项 父子关系 嵌套对象
数据存储 父文档和子文档是独立的文档 嵌套对象是父文档的一部分
更新 可以独立更新子文档 必须更新整个父文档
查询 支持父子联合查询 只支持嵌套查询
性能 较慢(需要 Join) 较快

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 创建父子关系 mapping
PUT /my_index
{
"mappings": {
"properties": {
"question": { "type": "keyword" },
"answer": { "type": "text" },
"my_join_field": {
"type": "join",
"relations": {
"question": "answer" # question 是父,answer 是子
}
}
}
}
}

# 索引父文档
PUT /my_index/_doc/1
{
"question": "什么是 Elasticsearch?",
"my_join_field": "question"
}

# 索引子文档(必须指定 routing=父文档 ID)
PUT /my_index/_doc/2?routing=1
{
"answer": "Elasticsearch 是一个分布式搜索和分析引擎",
"my_join_field": {
"name": "answer",
"parent": "1"
}
}

# 查询子文档(使用 has_parent 查询)
GET /my_index/_search
{
"query": {
"has_parent": {
"parent_type": "question",
"query": {
"match": { "question": "Elasticsearch" }
}
}
}
}

面试加分回答

  • 可以讲讲 父子关系的性能问题(Join 操作较慢)
  • 可以讲讲 父子关系的使用场景(比如问答系统、评论系统)
  • 可以讲讲实际项目中的替代方案(比如非规范化数据,将父子数据放在同一个文档中)

Q16:Elasticsearch 的索引生命周期管理(ILM)是什么?

一句话总结:ILM 是 ES 的自动化索引管理功能,可以自动执行滚动、收缩、强制合并、删除等操作,适用于时间序列数据(比如日志)。

深度解析

ILM 的阶段

  1. Hot 阶段:索引正在被频繁写入和查询
  2. Warm 阶段:索引不再写入,但偶尔查询
  3. Cold 阶段:索引很少查询,可以存储在便宜的硬件上
  4. Delete 阶段:索引可以被删除

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 创建 ILM 策略
PUT /_ilm/policy/log_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "1GB", # 索引大小超过 1GB 时滚动
"max_age": "7d" # 索引创建超过 7 天时滚动
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": {
"number_of_shards": 1 # 收缩到 1 个分片
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"freeze": {} # 冻结索引(释放内存)
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {} # 删除索引
}
}
}
}
}

面试加分回答

  • 可以讲讲 ILM 的使用场景(比如日志索引、指标索引)
  • 可以讲讲 如何监控 ILM 的执行(使用 GET /_ilm/status
  • 可以讲讲实际项目中的应用(比如按天创建日志索引,自动删除 90 天前的索引)

Q17:Elasticsearch 的索引设置(Index Settings)有哪些重要的?

一句话总结:索引设置是 ES 的索引级别配置,包括:分片数量刷新间隔写入限流合并策略等。

深度解析

重要的索引设置

  1. number_of_shards:主分片数量(不能修改
  2. number_of_replicas:副本分片数量(可以动态修改)
  3. refresh_interval:刷新间隔(默认 1 秒)
  4. index.translog.flush_threshold_size:刷写阈值(默认 512MB)
  5. index.merge.scheduler.max_thread_count:合并线程数

示例

1
2
3
4
5
6
7
8
9
# 修改索引设置
PUT /my_index/_settings
{
"index": {
"number_of_replicas": 2, # 增加副本数量
"refresh_interval": "30s", # 降低刷新频率(提高写入性能)
"translog.flush_threshold_size": "1gb" # 提高刷写阈值(减少磁盘 I/O)
}
}

面试加分回答

  • 可以讲讲 如何优化写入性能(增大刷新间隔、禁用副本、使用 Bulk API)
  • 可以讲讲 如何优化查询性能(增加副本、使用文件系统缓存、优化 mapping)
  • 可以讲讲实际项目中的调优经验(比如批量导入时临时禁用刷新)

Q18:Elasticsearch 的 mapping 优化技巧有哪些?

一句话总结:Mapping 优化技巧包括:禁用不需要搜索的字段使用 keyword 类型启用 doc_values禁用 _source 等。

深度解析

Mapping 优化技巧

  1. 禁用不需要搜索的字段"index": false
  2. 使用 keyword 类型:用于精确匹配(比 text 类型快)
  3. 启用 doc_values:用于排序和聚合(默认启用)
  4. 禁用 _source:如果不获取原始文档,可以禁用(节省磁盘空间)
  5. 使用常量关键字(constant_keyword):如果字段值固定,可以使用(节省存储空间)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"content": {
"type": "text",
"index": false # 禁用搜索(只用于存储)
},
"status": {
"type": "keyword"
},
"price": {
"type": "float",
"doc_values": false # 禁用 doc_values(如果不需要排序和聚合)
}
}
}
}

面试加分回答

  • 可以讲讲 如何减少索引大小(禁用不需要的功能)
  • 可以讲讲 如何优化聚合性能(启用 doc_values)
  • 可以讲讲实际项目中的优化经验(比如只为需要的字段启用索引)

Q19:Elasticsearch 的索引重建(Reindex)是什么?

一句话总结:索引重建是将旧索引的数据复制到新索引的操作,用于修改 mapping、增加分片数量、拆分索引等场景。

深度解析

为什么需要重建索引?

  • Mapping 错误(比如字段类型推断错误)
  • 需要修改分片数量(主分片数量不能修改,只能重建索引)
  • 需要优化索引结构(比如启用/doc_values、禁用 _source)

重建索引的步骤

  1. 创建新索引(正确的 mapping 和 settings)
  2. 使用 Reindex API 复制数据
  3. 等待重建完成
  4. 切换别名(实现零停机时间)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 重建索引
POST /_reindex
{
"source": {
"index": "my_index_v1"
},
"dest": {
"index": "my_index_v2"
}
}

# 切换别名(零停机时间)
POST /_aliases
{
"actions": [
{ "remove": { "index": "my_index_v1", "alias": "my_index" }},
{ "add": { "index": "my_index_v2", "alias": "my_index" }}
]
}

面试加分回答

  • 可以讲讲 如何加速重建索引(使用 slices 参数并行重建)
  • 可以讲讲 如何避免重建索引时的性能问题(限制重建速度)
  • 可以讲讲实际项目中的经验(比如提前规划 mapping,避免重建索引)

Q20:Elasticsearch 的索引拆分(Split)是什么?

一句话总结:索引拆分是 ES 的增加主分片数量的操作,但有限制(新分片数量必须是原分片数量的倍数)。

深度解析

为什么需要拆分索引?

  • 主分片数量不能修改(因为路由公式)
  • 但如果索引的设置 index.number_of_routing_shards 大于 index.number_of_shards,则可以拆分`

拆分的限制

  • 新分片数量必须是原分片数量的倍数
  • 原索引必须只读(不能写入)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. 将原索引设置为只读
PUT /my_index/_settings
{
"index": {
"blocks.write": true
}
}

# 2. 拆分索引(分片数量从 3 增加到 6)
POST /my_index/_split/my_index_new
{
"settings": {
"index": {
"number_of_shards": 6
}
}
}

# 3. 等待拆分完成
GET /_cat/recovery/my_index_new?v=

# 4. 切换别名
POST /_aliases
{
"actions": [
{ "remove": { "index": "my_index", "alias": "my_index" }},
{ "add": { "index": "my_index_new", "alias": "my_index" }}
]
}

面试加分回答

  • 可以讲讲 拆分索引的使用场景(比如数据量增长,需要增加分片数量)
  • 可以讲讲 拆分索引的限制(必须是倍数)
  • 可以讲讲实际项目中的替代方案(比如按时间滚动索引,而不是拆分索引)

第三部分:Elasticsearch 搜索(Q21-Q30)

Q21:Elasticsearch 的 Match 查询和 Term 查询的区别是什么?

一句话总结match 查询会分词,用于全文搜索term 查询不会分词,用于精确匹配

深度解析

Match 查询

  • 会对查询字符串进行分词
  • 然后对每个词项进行搜索
  • 最后合并结果(默认是 OR 关系)

Term 查询

  • 不会对查询字符串进行分词
  • 直接精确匹配倒排索引中的词项**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Match 查询(会分词)
GET /my_index/_search
{
"query": {
"match": {
"title": "Elasticsearch 实战"
}
}
}
# 等价于:搜索包含 "elasticsearch" OR "实战" 的文档

# Term 查询(不会分词)
GET /my_index/_search
{
"query": {
"term": {
"title": "Elasticsearch 实战"
}
}
}
# 等价于:搜索包含词项 "Elasticsearch 实战" 的文档(通常匹配不到,因为 title 是 text 类型,已经被分词了)

面试加分回答

  • 可以讲讲 Match vs Term 的区别(match 会分词,term 不会分词)
  • 可以讲讲 如何选择合适的查询类型(全文搜索用 match,精确匹配用 term
  • 可以讲讲实际项目中的常见错误(比如对 text 字段使用 term 查询)

Q22:Elasticsearch 的 Bool 查询是什么?

一句话总结bool 查询是 ES 的复合查询,可以组合多个查询条件,包括:mustshouldmust_notfilter

深度解析

Bool 查询的子句

  1. must必须匹配,会贡献评分
  2. should可以匹配,会贡献评分(但可以通过 minimum_should_match 控制至少匹配几个)
  3. must_not必须不匹配
  4. filter必须匹配,但不会贡献评分(会使用缓存,性能更高)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET /my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Elasticsearch" }} # 必须包含 "Elasticsearch"
],
"should": [
{ "match": { "title": "实战" }}, # 可以包含 "实战"(匹配到会提高评分)
{ "match": { "title": "教程" }} # 可以包含 "教程"(匹配到会提高评分)
],
"minimum_should_match": 1, # 至少匹配 1 个 should 子句
"must_not": [
{ "term": { "status": 0 }} # 必须不包含 status=0 的文档
],
"filter": [
{ "range": { "price": { "gte": 50, "lte": 100 }}} # 价格必须在 50-100 之间(不贡献评分)
]
}
}
}

面试加分回答

  • 可以讲讲 filter vs must 的区别(filter 不贡献评分,会使用缓存)
  • 可以讲讲 如何优化 bool 查询的性能(将不需要评分的条件放在 filter 中)
  • 可以讲讲实际项目中的复杂查询案例(比如电商搜索)

Q23:Elasticsearch 的聚合(Aggregation)是什么?

一句话总结:聚合是 ES 的分析功能,类似于 SQL 的 GROUP BY 和聚合函数,包括:指标聚合桶聚合管道聚合

深度解析

聚合的类型

  1. 指标聚合(Metric Aggregation):计算指标(比如 sumavgmaxmincardinality
  2. 桶聚合(Bucket Aggregation):将文档分组(比如 termsrangehistogram
  3. 管道聚合(Pipeline Aggregation):对聚合结果进行二次计算(比如 avg_bucketmax_bucket

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 按作者分组,统计每本书的平均价格、最高价格、不同价格区间的文档数
GET /my_index/_search
{
"size": 0, # 不返回文档,只返回聚合结果
"aggs": {
"by_author": {
"terms": {
"field": "author.keyword"
},
"aggs": {
"avg_price": {
"avg": { "field": "price" }
},
"max_price": {
"max": { "field": "price" }
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 50 },
{ "from": 50, "to": 100 },
{ "from": 100 }
]
}
}
}
}
}
}

面试加分回答

  • 可以讲讲 聚合的性能优化(比如 size: 0、使用 execution_hint
  • 可以讲讲 聚合的内存限制(比如 circuit_breaker
  • 可以讲讲实际项目中的应用(比如用户画像分析、日志统计分析)

Q24:Elasticsearch 的排序(Sorting)是什么?

一句话总结:排序是 ES 的自定义文档顺序的功能,可以按字段值评分地理距离排序。

深度解析

排序的类型

  1. 按字段值排序:比如按价格、日期排序
  2. 按评分排序:按 _score 排序(默认)
  3. 按地理距离排序:按距离指定坐标的远近排序**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 按价格升序排序
GET /my_index/_search
{
"query": { "match_all": {} },
"sort": [
{ "price": { "order": "asc" }}
]
}

# 按地理距离排序
GET /my_index/_search
{
"query": { "match_all": {} },
"sort": [
{
"_geo_distance": {
"location": { "lat": 40.7128, "lon": -74.0060 },
"order": "asc",
"unit": "km"
}
}
]
}

面试加分回答

  • 可以讲讲 排序的性能问题(排序需要加载字段值,会消耗内存)
  • 可以讲讲 如何优化排序性能(启用 doc_values、使用 unmapped_type
  • 可以讲讲实际项目中的需求(比如多维度排序,先按评分排序,再按时间排序)

Q25:Elasticsearch 的分页(Pagination)是什么?

一句话总结:分页是 ES 的限制返回结果数量的功能,包括:From/SizeScrollSearch After

深度解析

分页的类型

  1. From/Size浅分页(适合前 1000 条结果)
  2. Scroll深分页(适合导出大量数据)
  3. Search After深分页(适合实时分页)

From/Size 的问题

  • 比如 from: 990, size: 10,ES 需要从每个分片获取 1000 条结果,然后在协调节点合并排序,最后返回第 990-1000 条
  • 性能很差(占用大量内存和 CPU)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# From/Size 分页(浅分页)
GET /my_index/_search
{
"query": { "match_all": {} },
"from": 0,
"size": 10
}

# Scroll 分页(深分页,适合导出数据)
POST /my_index/_search?scroll=1m
{
"query": { "match_all": {} },
"size": 100
}

# 获取下一页
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "XXXXXXXXXX"
}

# Search After 分页(深分页,适合实时分页)
GET /my_index/_search
{
"query": { "match_all": {} },
"size": 10,
"sort": [
{ "_id": "asc" } # 必须包含唯一值字段
]
}

# 下一页(使用上一页最后一条文档的 sort 值)
GET /my_index/_search
{
"query": { "match_all": {} },
"size": 10,
"sort": [
{ "_id": "asc" }
],
"search_after": ["doc_id_10"] # 上一页最后一条文档的 _id 值
}

面试加分回答

  • 可以讲讲 为什么 From/Size 不适合深分页
  • 可以讲讲 Scroll vs Search After 的区别(scroll 适合导出数据,search_after 适合实时分页)
  • 可以讲讲实际项目中的分页方案(比如无限滚动分页,使用 search_after

Q26:Elasticsearch 的高亮(Highlighting)是什么?

一句话总结:高亮是 ES 的在搜索结果中标记关键词的功能,通常用于全文搜索

深度解析

高亮的类型

  1. unified:默认高亮器,适用于大多数场景
  2. plain:传统高亮器,适用于小片段**
  3. fvh(Fast Vector Highlighter):快速向量高亮器,适用于大文档**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
GET /my_index/_search
{
"query": {
"match": { "content": "Elasticsearch" }
},
"highlight": {
"fields": {
"content": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"]
}
}
}
}

# 返回:
{
"hits": {
"hits": [
{
"_source": { "content": "Elasticsearch 是一个搜索引擎" },
"highlight": {
"content": ["<em>Elasticsearch</em> 是一个搜索引擎"]
}
}
]
}
}

面试加分回答

  • 可以讲讲 高亮的性能问题(高亮需要重新分析文本,会消耗 CPU)
  • 可以讲讲 如何优化高亮性能(使用 fvh,提前存储词项向量)
  • 可以讲讲实际项目中的优化(比如禁用高亮 _score 以提高性能)

Q27:Elasticsearch 的建议器(Suggester)是什么?

一句话总结:建议器是 ES 的搜索建议功能,包括:Term SuggesterPhrase SuggesterCompletion Suggester

深度解析

建议器的类型

  1. Term Suggester拼写纠正(比如输入 “elasticserch”,建议 “elasticsearch”)
  2. Phrase Suggester短语建议(基于 Term Suggester,但考虑词组)
  3. Completion Suggester自动补全(输入 “ela”,建议 “elasticsearch”)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Term Suggester(拼写纠正)
GET /my_index/_search
{
"suggest": {
"my_suggest": {
"text": "elasticserch",
"term": {
"field": "title"
}
}
}
}

# Completion Suggester(自动补全)
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "completion" # 自动补全类型
}
}
}
}

POST /my_index/_doc
{
"title": "Elasticsearch 实战"
}

GET /my_index/_search
{
"suggest": {
"my_suggest": {
"prefix": "ela",
"completion": {
"field": "title"
}
}
}
}

面试加分回答

  • 可以讲讲 建议器的使用场景(比如搜索框的自动补全、拼写纠正)
  • 可以讲讲 如何优化建议器的性能(使用 completion 类型,存储在内存中)
  • 可以讲讲实际项目中的应用(比如电商搜索的自动补全)

Q28:Elasticsearch 的地理位置搜索(Geo Search)是什么?

一句话总结:地理位置搜索是 ES 的基于地理位置的搜索功能,包括:地理距离查询地理边界查询地理聚合

深度解析

地理位置字段类型

  1. geo_point:一个点(经纬度)
  2. geo_shape:一个形状(圆形、多边形等)

地理位置查询

  1. geo_distance:查询距离指定坐标一定范围内的文档
  2. geo_bounding_box:查询在指定矩形范围内的文档
  3. geo_polygon:查询在指定多边形范围内的文档**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PUT /my_index
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}

POST /my_index/_doc/1
{
"name": "纽约帝国大厦",
"location": { "lat": 40.7484, "lon": -73.9857 }
}

# 查询距离指定坐标 1km 内的文档
GET /my_index/_search
{
"query": {
"geo_distance": {
"distance": "1km",
"location": { "lat": 40.7128, "lon": -74.0060 }
}
}
}

面试加分回答

  • 可以讲讲 地理位置搜索的使用场景(比如附近的商家、配送范围)
  • 可以讲讲 如何优化地理位置搜索的性能(使用 geo_point 类型,启用 doc_values
  • 可以讲讲实际项目中的应用(比如外卖平台的附近商家搜索)

Q29:Elasticsearch 的多索引搜索(Multi-Index Search)是什么?

一句话总结:多索引搜索是 ES 的同时搜索多个索引的功能,可以通过索引模式别名实现。

深度解析

多索引搜索的方式

  1. 指定多个索引GET /index1,index2/_search
  2. 使用索引模式GET /log-*/_search
  3. 使用别名GET /logs/_search(别名可以指向多个索引)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 搜索多个索引
GET /my_index_v1,my_index_v2/_search
{
"query": { "match_all": {} }
}

# 搜索匹配模式的索引
GET /log-2024-01-*/_search
{
"query": { "match_all": {} }
}

# 搜索别名(指向多个索引)
GET /logs/_search
{
"query": { "match_all": {} }
}

面试加分回答

  • 可以讲讲 多索引搜索的使用场景(比如日志索引、时间序列索引)
  • 可以讲讲 如何优化多索引搜索的性能(使用别名、限制搜索的索引数量)
  • 可以讲讲实际项目中的最佳实践(总是使用别名

Q30:Elasticsearch 的批量操作(Bulk API)是什么?

一句话总结:Bulk API 是 ES 的批量执行多个操作的功能,可以显著提高写入性能

深度解析

Bulk API 的操作类型

  1. index:索引文档(如果已存在则覆盖)
  2. create:创建文档(如果已存在则报错)
  3. update:更新文档(部分更新)
  4. delete:删除文档**

Bulk API 的格式

1
2
3
4
5
{ "index": { "_index": "my_index", "_id": "1" } }
{ "title": "Elasticsearch 实战", "price": 99 }
{ "delete": { "_index": "my_index", "_id": "2" } }
{ "update": { "_index": "my_index", "_id": "3" } }
{ "doc": { "price": 79 } }

示例

1
2
3
4
5
6
7
8
9
# 批量操作
POST /_bulk
{ "index": { "_index": "my_index", "_id": "1" } }
{ "title": "Elasticsearch 实战", "price": 99 }
{ "create": { "_index": "my_index", "_id": "2" } }
{ "title": "Lucene 实战", "price": 79 }
{ "delete": { "_index": "my_index", "_id": "3" } }
{ "update": { "_index": "my_index", "_id": "1" } }
{ "doc": { "price": 89 } }

面试加分回答

  • 可以讲讲 Bulk API 的性能优化(批量大小控制在 5-15MB)
  • 可以讲讲 Bulk API 的错误处理(某个操作失败不会影响其他操作)
  • 可以讲讲实际项目中的应用(比如批量导入数据、批量更新数据)

第四部分:Elasticsearch 集群和分布式(Q31-Q40)

Q31:Elasticsearch 的集群健康状态(Cluster Health)有哪些?

一句话总结:ES 的集群健康状态包括:绿色(Green)黄色(Yellow)红色(Red)

深度解析

集群健康状态

  1. 绿色(Green):所有主分片和副本分片都可用
  2. 黄色(Yellow):所有主分片可用,但有些副本分片不可用
  3. 红色(Red)有些主分片不可用

查看集群健康状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /_cluster/health

# 返回:
{
"cluster_name": "my-cluster",
"status": "yellow", # 集群状态
"number_of_nodes": 3, # 节点数量
"number_of_data_nodes": 3, # 数据节点数量
"active_primary_shards": 10, # 活动主分片数量
"active_shards": 15, # 活动分片数量(主分片 + 副本分片)
"relocating_shards": 0, # 正在迁移的分片数量
"initializing_shards": 0, # 正在初始化的分片数量
"unassigned_shards": 5, # 未分配的分片数量(副本分片没有地方分配)
"delayed_unassigned_shards": 0
}

面试加分回答

  • 可以讲讲 为什么集群状态是黄色(因为副本分片没有地方分配,比如只有一个节点)
  • 可以讲讲 如何处理红色状态(找到不可用主分片的原因,可能是节点故障)
  • 可以讲讲实际项目中的监控(比如使用 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
2
3
4
5
6
7
# ES 7.x 之前的配置(zen discovery)
discovery.zen.ping.unicast.hosts: ["node1", "node2", "node3"]
discovery.zen.minimum_master_nodes: 2

# ES 7.x 之后的配置(coordinator)
discovery.seed.hosts: ["node1", "node2", "node3"]
cluster.initial_master_nodes: ["node1", "node2"]

面试加分回答

  • 可以讲讲 为什么 ES 7.x 废弃了 zen discovery(容易配置错误,导致脑裂)
  • 可以讲讲 如何避免脑裂问题
  • 可以讲讲实际项目中的部署方案(比如 3 个 Coordinator 节点)

Q33:Elasticsearch 的主节点选举(Master Election)是什么?

一句话总结:主节点选举是 ES 的选举主节点的机制,保证集群有唯一的主节点管理集群状态。

深度解析

主节点选举的流程

  1. 节点启动:节点尝试加入集群(或形成集群)
  2. 选举临时主节点:从候选主节点中选举一个作为临时主节点
  3. 投票:候选主节点向临时主节点投票
  4. 选举成功:如果临时主节点获得 超过半数 的候选主节点投票,则成为正式主节点
  5. 选举失败:如果没有候选主节点获得超过半数投票,则重新选举

防止脑裂

  • minimum_master_nodes:最少候选主节点数量(ES 7.x 之前)
  • 公式minimum_master_nodes = (候选主节点数量 / 2) + 1

示例

1
2
3
4
# 3 个候选主节点,minimum_master_nodes = 2
node.master: true # 该节点是候选主节点

discovery.zen.minimum_master_nodes: 2 # ES 7.x 之前

面试加分回答

  • 可以讲讲 主节点选举的原理(类似 Raft 协议)
  • 可以讲讲 为什么需要超过半数投票(防止脑裂)
  • 可以讲讲实际项目中的部署方案(比如 3 个候选主节点)

Q34:Elasticsearch 的分片分配(Shard Allocation)是什么?

一句话总结:分片分配是 ES 的将分片分配到节点的机制,包括:主分片分配副本分片分配再平衡

深度解析

分片分配的阶段

  1. 主分片分配:当索引创建时,主分片分配到哪些节点
  2. 副本分片分配:当主分片分配完成后,副本分片分配到哪些节点(不能和主分片在同一个节点
  3. 再平衡:当节点加入或离开时,重新分配分片(保持平衡)

分片分配的策略

  1. Same Shard Policy:不要让主分片和副本分片在同一个节点
  2. Awareness Policy:按机房机架分配分片(提高容灾能力)
  3. Filter Policy:允许/禁止将分片分配到某些节点**

示例

1
2
3
4
5
6
7
# 按机房分配分片(提高容灾能力)
node.attr.zone: zone1 # 节点属性

cluster.routing.allocation.awareness.attributes: zone # 启用机房感知

# 禁止将分片分配到某些节点
cluster.routing.allocation.exclude._ip: "192.168.1.1"

面试加分回答

  • 可以讲讲 如何优化分片分配(按机房分配、控制每个节点的分片数量)
  • 可以讲讲 如何手动迁移分片(使用 cluster reroute API)
  • 可以讲讲实际项目中的经验(比如避免单个节点分配过多分片

Q35:Elasticsearch 的写入一致性(Write Consistency)是什么?

一句话总结:写入一致性是 ES 的控制写入操作需要多少副本分片可用的机制,包括:allquorumone

深度解析

写入一致性的级别

  1. all:所有副本分片都可用(最强一致性)
  2. quorum:大部分副本分片可用(默认,公式是 (主分片数量 + 副本分片数量) / 2 + 1
  3. one:只要主分片可用(最弱一致性)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 设置写入一致性级别
PUT /my_index/_settings
{
"index": {
"write.wait_for_active_shards": "all" # 等待所有分片可用
}
}

# 写入时指定一致性级别
PUT /my_index/_doc/1?wait_for_active_shards=all
{
"title": "Elasticsearch 实战"
}

面试加分回答

  • 可以讲讲 写入一致性和可用性的权衡all 一致性最强,但可用性最差)
  • 可以讲讲 如何保证数据不丢失(设置 wait_for_active_shards=all
  • 可以讲讲实际项目中的配置(比如金融场景用 all,日志场景用 one

Q36:Elasticsearch 的读取一致性(Read Consistency)是什么?

一句话总结:读取一致性是 ES 的控制读取操作从哪个分片读取的机制,包括:allquorumone

深度解析

读取一致性的级别

  1. all:从所有分片读取(最慢,但结果最准确)
  2. quorum:从大部分分片读取
  3. one:从单个分片读取(最快,但结果可能不准确)

ES 的实际实现

  • ES 没有 读取一致性级别(和 Cassandra 不同)
  • ES 的读取请求会自动路由到相关分片(主分片或副本分片)
  • 但可以通过 preference 参数控制读取哪个分片

示例

1
2
3
4
# 控制读取哪个分片
GET /my_index/_search?preference=_primary # 只读取主分片
GET /my_index/_search?preference=_replica # 只读取副本分片
GET /my_index/_search?preference=custom_value # 相同 value 的请求会路由到相同分片(提高缓存命中率)

面试加分回答

  • 可以讲讲 ES 为什么没有读取一致性级别(因为 ES 是近实时搜索,主分片和副本分片可能有延迟)
  • 可以讲讲 如何保证读取结果准确(使用 preference=_primary
  • 可以讲讲实际项目中的配置(比如提高缓存命中率,使用 preference=session_id

Q37:Elasticsearch 的集群扩容(Cluster Scaling)是什么?

一句话总结:集群扩容是 ES 的增加节点的操作,可以提高容量提高性能

深度解析

扩容的方式

  1. 增加数据节点:提高容量和读取性能
  2. 增加协调节点:提高请求路由性能
  3. 增加预处理节点:提高文档预处理性能**

扩容的限制

  • 主分片数量不能修改(如果容量不够,需要重建索引)
  • 但可以增加副本分片数量(提高读取性能)

示例

1
2
3
4
5
6
7
8
9
10
11
# 增加副本分片数量(提高读取性能)
PUT /my_index/_settings
{
"index": {
"number_of_replicas": 2 # 从 1 个副本增加到 2 个副本
}
}

# 添加数据节点(只需要启动新节点,ES 会自动分配分片)
# 新节点会加入集群,集群状态变为黄色(因为副本分片正在分配)
# 分配完成后,集群状态变为绿色

面试加分回答

  • 可以讲讲 如何规划集群规模(根据数据量、写入 QPS、读取 QPS)
  • 可以讲讲 如何避免扩容时的性能问题(控制分片分配速率)
  • 可以讲讲实际项目中的扩容方案(比如滚动扩容,逐个重启节点)

Q38:Elasticsearch 的集群缩容(Cluster Shrink)是什么?

一句话总结:集群缩容是 ES 的减少节点的操作,通常用于下线故障节点降低硬件成本

深度解析

缩容的步骤

  1. 迁移分片:将待下线节点上的分片迁移到其他节点
  2. 等待集群状态变为绿色:确保所有分片都有副本
  3. 下线节点:关闭待下线节点

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 迁移分片(排除待下线节点)
PUT /_cluster/settings
{
"transient": {
"cluster.routing.allocation.exclude._ip": "192.168.1.1"
}
}

# 2. 等待分片迁移完成
GET /_cat/recovery?v=

# 3. 下线节点
# 关闭待下线节点的 ES 进程

面试加分回答

  • 可以讲讲 如何安全下线节点(先迁移分片,再下线)
  • 可以讲讲 如何避免缩容时的数据丢失(确保副本分片可用)
  • 可以讲讲实际项目中的缩容方案(比如滚动缩容,逐个下线节点)

Q39:Elasticsearch 的跨集群搜索(Cross-Cluster Search)是什么?

一句话总结:跨集群搜索是 ES 的搜索多个集群的功能,适用于多数据中心冷热分离场景。

深度解析

跨集群搜索的配置

  1. 配置远程集群:在本地集群中配置远程集群的连接信息
  2. 搜索远程集群:使用 集群别名: 前缀搜索远程集群

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 配置远程集群
PUT /_cluster/settings
{
"persistent": {
"cluster.remote": {
"cluster_one": {
"seeds": ["node1:9300", "node2:9300"]
},
"cluster_two": {
"seeds": ["node3:9300", "node4:9300"]
}
}
}
}

# 搜索远程集群
GET /cluster_one:my_index,cluster_two:my_index/_search
{
"query": { "match_all": {} }
}

面试加分回答

  • 可以讲讲 跨集群搜索的使用场景(比如多数据中心、冷热分离)
  • 可以讲讲 如何优化跨集群搜索的性能(使用 CCR(Cross-Cluster Replication) 复制数据到本地集群)
  • 可以讲讲实际项目中的应用(比如搜索历史数据,从远程集群搜索)

Q40:Elasticsearch 的跨集群复制(CCR - Cross-Cluster Replication)是什么?

一句话总结:跨集群复制是 ES 的复制索引到远程集群的功能,适用于灾备就近读取场景。

深度解析

CCR 的使用场景

  1. 灾备:将索引复制到远程集群,防止数据中心故障
  2. 就近读取:将索引复制到多个数据中心,提高读取性能
  3. 数据本地化:将全局索引复制到本地集群,减少跨数据中心延迟**

示例

1
2
3
4
5
6
7
8
9
# 创建复制规则
PUT /_ccr/follow/my_index
{
"remote_cluster": "cluster_one",
"leader_index": "my_index"
}

# 查看复制状态
GET /_ccr/stats

面试加分回答

  • 可以讲讲 CCR 和跨集群搜索的区别(CCR 是复制数据,跨集群搜索是远程搜索)
  • 可以讲讲 如何优化 CCR 的性能(使用自动跟随模式,自动复制新索引)
  • 可以讲讲实际项目中的应用(比如灾备方案,将索引复制到远程集群)

第五部分:Elasticsearch 性能优化(Q41-Q50)

Q41:Elasticsearch 的写入性能优化有哪些?

一句话总结:写入性能优化包括:禁用刷新禁用副本使用 Bulk API增加刷新间隔使用 SSD

深度解析

写入性能优化技巧

  1. 禁用刷新index.refresh_interval: -1(批量导入完成后恢复)
  2. 禁用副本index.number_of_replicas: 0(批量导入完成后恢复)
  3. 使用 Bulk API:批量写入(批量大小控制在 5-15MB)
  4. 增加刷新间隔index.refresh_interval: 30s(降低刷新频率)
  5. 使用 SSD:SSD 的随机 I/O 性能远好于机械硬盘**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 批量导入时临时优化写入性能
PUT /my_index/_settings
{
"index": {
"refresh_interval": "-1", # 禁用刷新
"number_of_replicas": 0 # 禁用副本
}
}

# 批量导入完成后恢复设置
PUT /my_index/_settings
{
"index": {
"refresh_interval": "1s", # 恢复刷新
"number_of_replicas": 1 # 恢复副本
}
}

面试加分回答

  • 可以讲讲 如何平衡写入性能和搜索实时性(根据业务需求调整 refresh_interval
  • 可以讲讲 如何使用 Bulk API 的最佳实践(控制批量大小、并行写入)
  • 可以讲讲实际项目中的优化经验(比如日志导入,禁用刷新和副本)

Q42:Elasticsearch 的读取性能优化有哪些?

一句话总结:读取性能优化包括:增加副本使用文件系统缓存优化 mapping使用 filter 查询避免深度分页

深度解析

读取性能优化技巧

  1. 增加副本:提高读取吞吐量(但需要更多硬件资源)
  2. 使用文件系统缓存:Linux 会自动缓存文件(需要足够的内存)
  3. 优化 mapping:禁用不需要搜索的字段、使用 keyword 类型
  4. 使用 filter 查询:filter 查询不贡献评分,会使用缓存
  5. 避免深度分页:使用 search_after 代替 from/size

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 增加副本(提高读取吞吐量)
PUT /my_index/_settings
{
"index": {
"number_of_replicas": 2
}
}

# 使用 filter 查询(会使用缓存)
GET /my_index/_search
{
"query": {
"bool": {
"filter": [
{ "term": { "status": 1 }},
{ "range": { "price": { "gte": 50 }}}
]
}
}
}

面试加分回答

  • 可以讲讲 如何优化聚合性能(使用 doc_values、控制聚合数量)
  • 可以讲讲 如何优化排序性能(使用 doc_values
  • 可以讲讲实际项目中的优化经验(比如为热数据增加副本

Q43:Elasticsearch 的硬件选择有哪些建议?

一句话总结:ES 的硬件选择建议:CPU 不需要太强(主要瓶颈在 I/O 和内存)、内存要足够(文件系统缓存)、使用 SSD(提高 I/O 性能)、网络要快(分布式系统)。

深度解析

硬件选择建议

  1. CPU:2-8 核(不需要太强,ES 主要瓶颈在 I/O 和内存)
  2. 内存:64GB-128GB(一半给 ES,一半给文件系统缓存)
  3. 磁盘:SSD(提高 I/O 性能,尤其是写入性能)
  4. 网络:千兆网卡或万兆网卡(分布式系统,节点间通信频繁)

示例

1
2
3
4
# 设置 ES 的 JVM 堆内存(建议设置为物理内存的一半,但不超过 32GB)
# 修改 config/jvm.options
-Xms32g
-Xmx32g

面试加分回答

  • 可以讲讲 为什么 JVM 堆内存不要超过 32GB(因为 JVM 的压缩指针机制,超过 32GB 后效率下降)
  • 可以讲讲 如何监控硬件资源使用率(使用 node.stats API)
  • 可以讲讲实际项目中的硬件选择经验(比如热数据用 SSD,冷数据用机械硬盘

Q44:Elasticsearch 的 JVM 堆内存优化有哪些?

一句话总结:JVM 堆内存优化包括:设置合适的堆内存大小避免频繁 Full GC使用 G1GC

深度解析

JVM 堆内存优化技巧

  1. 设置合适的堆内存大小XmsXmx 设置为相同值(避免动态调整)
  2. 不要超过 32GB:因为 JVM 的压缩指针机制,超过 32GB 后效率下降
  3. 使用 G1GC:ES 默认使用 G1GC(适合大堆内存)

示例

1
2
3
4
5
6
# 修改 config/jvm.options
-Xms32g # 初始堆内存
-Xmx32g # 最大堆内存(不要超过 32GB)

# 使用 G1GC(ES 默认)
-XX:+UseG1GC

面试加分回答

  • 可以讲讲 如何监控 JVM 堆内存使用率(使用 node.stats API 或 Kibana)
  • 可以讲讲 如何避免频繁 Full GC(增加堆内存、优化查询)
  • 可以讲讲实际项目中的调优案例(比如解决 OOM 问题

Q45:Elasticsearch 的索引性能监控有哪些指标?

一句话总结:索引性能监控指标包括:索引速率索引延迟索引拒绝次数合并速率刷写速率

深度解析

索引性能监控指标

  1. 索引速率(Index Rate):每秒索引多少文档
  2. 索引延迟(Index Latency):索引一个文档需要多少时间
  3. 索引拒绝次数(Index Rejected):线程池拒绝次数(如果很高,说明写入过载)
  4. 合并速率(Merge Rate):每秒合并多少文档
  5. 刷写速率(Flush Rate):每秒刷写多少次**

示例

1
2
3
4
5
# 查看索引性能统计
GET /_nodes/stats/indices

# 查看线程池统计(包括拒绝次数)
GET /_nodes/stats/thread_pool

面试加分回答

  • 可以讲讲 如何判断写入过载(索引拒绝次数 > 0)
  • 可以讲讲 如何优化写入性能(增加线程池大小、优化 mapping)
  • 可以讲讲实际项目中的监控方案(比如使用 Prometheus + Grafana 监控 ES 指标)

Q46:Elasticsearch 的搜索性能监控有哪些指标?

一句话总结:搜索性能监控指标包括:搜索速率搜索延迟搜索拒绝次数缓存命中率内存使用率

深度解析

搜索性能监控指标

  1. 搜索速率(Search Rate):每秒执行多少次搜索
  2. 搜索延迟(Search Latency):搜索需要多少时间
  3. 搜索拒绝次数(Search Rejected):线程池拒绝次数(如果很高,说明搜索过载)
  4. 缓存命中率(Cache Hit Rate):filter 查询缓存命中率
  5. 内存使用率(Memory Usage):JVM 堆内存使用率**

示例

1
2
3
4
5
6
7
8
# 查看搜索性能统计
GET /_nodes/stats/indices/search

# 查看缓存统计
GET /_nodes/stats/indices/query_cache

# 查看内存统计
GET /_nodes/stats/jvm

面试加分回答

  • 可以讲讲 如何判断搜索过载(搜索拒绝次数 > 0)
  • 可以讲讲 如何优化搜索性能(增加副本、使用 filter 查询、优化 mapping)
  • 可以讲讲实际项目中的监控方案(比如使用 Elastic APM 监控搜索性能)

Q47:Elasticsearch 的常见性能问题有哪些?

一句话总结:常见性能问题包括:写入过载搜索过载内存不足磁盘 I/O 瓶颈网络延迟

深度解析

常见性能问题及解决方案

  1. 写入过载:索引拒绝次数 > 0 → 增加数据节点、优化 mapping、使用 Bulk API
  2. 搜索过载:搜索拒绝次数 > 0 → 增加数据节点、增加副本、优化查询
  3. 内存不足:JVM 堆内存使用率 > 75% → 增加堆内存、优化查询、增加节点
  4. 磁盘 I/O 瓶颈:磁盘 I/O 使用率 > 80% → 使用 SSD、增加节点**
  5. 网络延迟:节点间通信延迟高 → 使用万兆网卡、将节点部署在同一个机房**

面试加分回答

  • 可以讲讲 如何排查性能问题(使用 node.stats API、查看日志)
  • 可以讲讲 如何优化性能(硬件升级、配置调优、查询优化)
  • 可以讲讲实际项目中的性能问题案例(比如解决写入拒绝问题

Q48:Elasticsearch 的数据建模最佳实践有哪些?

一句话总结:数据建模最佳实践包括:避免过度嵌套使用非规范化数据合理使用父子关系控制字段数量

深度解析

数据建模最佳实践

  1. 避免过度嵌套:嵌套查询较慢,如果嵌套层级很深,性能会很差
  2. 使用非规范化数据:将关联数据存储在同一文档中(提高查询性能)
  3. 合理使用父子关系:父子关系查询较慢,如果不需要独立更新子文档,使用嵌套对象或非规范化数据
  4. 控制字段数量:字段数量过多会导致 mapping 爆炸,影响性能**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 反例:过度嵌套
{
"user": {
"name": "张三",
"orders": [ # 嵌套对象
{
"order_id": 1,
"products": [ # 多层嵌套
{ "product_id": 1, "name": "商品1" }
]
}
]
}
}

# 正例:非规范化数据
{
"user_name": "张三",
"order_id": 1,
"product_name": "商品1"
}

面试加分回答

  • 可以讲讲 如何选择合适的关联数据模型(嵌套对象 vs 父子关系 vs 非规范化数据)
  • 可以讲讲 如何避免 mapping 爆炸(禁用动态映射、使用 nested 类型)
  • 可以讲讲实际项目中的数据建模案例(比如电商搜索的数据建模

Q49:Elasticsearch 的备份和恢复(Snapshot and Restore)是什么?

一句话总结:备份和恢复是 ES 的数据备份功能,可以将索引备份到远程仓库(比如 HDFS、S3),然后恢复。

深度解析

备份和恢复的步骤

  1. 创建快照仓库:配置远程仓库(比如 HDFS、S3)
  2. 创建快照:备份索引
  3. 恢复快照:恢复索引**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 创建快照仓库(使用本地文件系统)
PUT /_snapshot/my_backup
{
"type": "fs",
"settings": {
"location": "/path/to/backup",
"compress": true
}
}

# 2. 创建快照(备份所有索引)
PUT /_snapshot/my_backup/snapshot_1?wait_for_completion=true

# 3. 恢复快照
POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "my_index", # 只恢复 my_index 索引
"include_global_state": false
}

面试加分回答

  • 可以讲讲 备份和恢复的使用场景(比如数据迁移、灾难恢复)
  • 可以讲讲 如何自动化备份(使用 Watcher 定时创建快照)
  • 可以讲讲实际项目中的备份方案(比如每天备份一次,保留最近 7 天的快照)

Q50:Elasticsearch 的安全机制(Security)有哪些?

一句话总结:ES 的安全机制包括:身份认证权限控制传输加密审计日志

深度解析

ES 的安全功能(需要安装 X-Pack 插件):

  1. 身份认证:使用 Realm(比如 Native Realm、LDAP Realm)
  2. 权限控制:使用 RoleUser
  3. 传输加密:使用 TLS/SSL 加密节点间通信
  4. 审计日志:记录用户操作**

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建用户
POST /_security/user/john
{
"password": "password",
"roles": ["admin"]
}

# 创建角色
POST /_security/role/devops
{
"indices": [
{ "names": ["*"], "privileges": ["all"] }
]
}

# 启用 TLS/SSL
# 修改 config/elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ll.enabled: true

面试加分回答

  • 可以讲讲 为什么需要启用安全机制(防止未授权访问、保护敏感数据)
  • 可以讲讲 如何集成 LDAP/AD(使用 LDAP Realm)
  • 可以讲讲实际项目中的安全方案(比如启用身份认证和权限控制

💪 实战演练(真实面试场景)

🎯 面试技巧:面试时遇到 Elasticsearch 问题,不要只背概念,要结合实际项目经验回答。

场景 1:请你设计一个电商搜索系统?

回答思路

  1. 数据建模:商品数据如何存储(使用非规范化数据,将商品信息、库存信息、价格信息存储在同一文档中)
  2. 分词器选择:中文分词器(使用 IK Analyzer)
  3. 搜索类型:全文搜索(使用 match 查询)、过滤搜索(使用 filter 查询)
  4. 排序:按评分排序、按销量排序、按价格排序
  5. 分页:使用 search_after 实现无限滚动分页**
  6. 性能优化:增加副本、使用文件系统缓存、使用 filter 查询**

场景 2:如何优化 ES 的写入性能?

回答思路

  1. 禁用刷新和副本(批量导入时)
  2. 使用 Bulk API(批量写入)
  3. 增加刷新间隔(降低刷新频率)
  4. 使用 SSD(提高 I/O 性能)
  5. 优化 mapping(禁用不需要搜索的字段)

场景 3:ES 集群状态是红色,如何排查?

回答思路

  1. 查看集群健康状态GET /_cluster/health
  2. 查看未分配的分片GET /_cat/shards?h=index,shard,prirep,state,unassigned.reason
  3. 查看节点状态GET /_cat/nodes
  4. 查看日志tail -f logs/elasticsearch.log
  5. 解决方案:如果是节点故障,下线故障节点,恢复副本分片**

📚 扩展学习资源**

📖 持续学习: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 权威指南》(旧版,但基础概念讲得好)

博客推荐

视频教程

实战项目


💪 最后的鼓励

恭喜你!如果你认真学完了上面的 50 个问题,那么你已经掌握了 Elasticsearch 的核心知识

下一步建议

  1. 动手实践:搭建一个 ES 集群,创建索引,执行搜索
  2. 阅读源码:如果你对 ES 的实现原理感兴趣,可以阅读 Lucene 源码
  3. 参与社区:在 Elasticsearch 中文社区回答问题,加深理解
  4. 准备面试:刷 LeetCode 数据库题目,复习 ES 知识

最后的最后

  • 面试不仅考察知识,还考察思维能力沟通能力
  • 回答问题时,要逻辑清晰深入浅出
  • 遇到不会的问题,不要慌,可以引导到你会的方向

祝你面试顺利!🎉


💡 提示:本文档会持续更新,如果你发现错误或想补充内容,欢迎提 Issue!

🎉 总结

恭喜你!如果你认真学完了上面的 50 个问题,那么你已经掌握了 Elasticsearch 的核心知识

下一步建议

  1. 动手实践:搭建一个 ES 集群,创建索引,执行搜索
  2. 阅读源码:如果你对 ES 的实现原理感兴趣,可以阅读 Lucene 源码
  3. 参与社区:在 Elasticsearch 中文社区回答问题,加深理解
  4. 准备面试:刷 LeetCode 数据库题目,复习 ES 知识**

最后的最后

  • 面试不仅考察知识,还考察思维能力沟通能力
  • 回答问题时,要逻辑清晰深入浅出
  • 遇到不会的问题,不要慌,可以引导到你会的方向

祝你面试顺利!🎉


💡 提示:本文档会持续更新,如果你发现错误或想补充内容,欢迎提 Issue!


Elasticsearch 面试八股文(50题)
https://whyalwaysme.lol/2026/06/09/2026-06-09-elasticsearch-interview-deep/
作者
Cassiur
发布于
2026年6月9日
许可协议