ElasticSearch 面试题集锦
整理自真实面试问答,涵盖 ES 核心概念、索引结构、查询优化、集群管理等高频考点。
一、基础概念
Q1: ElasticSearch 用的是哪个版本?
A: ElasticSearch 版本众多,当前主流版本为:
- ES 7.x / 8.x(最新稳定版)
- 7.x 版本引入了新的集群协调子系统,去除了 Type 的概念
- 8.x 版本默认开启了安全特性(HTTPS、安全配置向导)
生产环境推荐使用 7.x 或 8.x 稳定版,避免使用过旧的 5.x/6.x。
Q2: ElasticSearch 的默认端口是多少?
A:
- 9200:RESTful API 端口,用于客户端通信
- 9300:节点间通信(Transport)端口,用于集群内部通信
访问示例:http://localhost:9200
Q3: 为什么要用 ElasticSearch?
A:
| 对比维度 | MySQL/关系型数据库 | ElasticSearch |
|---|---|---|
| 数据量 | 千万级以下高效 | 亿级数据毫秒响应 |
| 搜索方式 | LIKE 模糊查询(全表扫描) | 倒排索引(精准高效) |
| 全文检索 | 能力弱 | 强大,支持分词、相关性排序 |
| 实时性 | 实时写入 | 近实时(NRT ≈ 1秒) |
| 扩展性 | 垂直扩展为主 | 水平扩展,天然分布式 |
| 聚合分析 | 弱 | 聚合能力强大 |
典型使用场景:
- 海量数据全文检索
- 日志分析(ELK)
- 商品搜索、站内搜索
- 复杂条件组合查询
Q4: ElasticSearch 为什么快?
A:
-
倒排索引(Inverted Index)
- 词 → 文档的映射,查询时 O(1) 定位
- 无需扫描全表
-
分片机制(Sharding)
- 数据分散到多个分片,并行查询
- 天然支持横向扩展
-
多种缓存
- Segment Cache(段级缓存)
- Filter Cache(过滤器缓存)
- Query Cache(查询缓存)
-
零跳跃(Skip List / FST)
- 使用 FST(Finite State Transducer)实现前缀树压缩
- 查询跳表加速定位
-
写入优化
- 写入时先写内存和 Translog,定期刷盘生成 Segment
- 段文件只读不可变,避免随机写
二、索引与数据结构
Q5: ElasticSearch 的索引结构是啥样的?
A: ES 索引的层级结构:
Index(索引)
├── Shard(分片)
│ ├── Primary Shard(主分片)
│ └── Replica Shard(副本分片)
├── Segment(段)
│ ├── _segments.json(元数据)
│ ├── FST(倒排索引)
│ ├── doc_values(列式存储)
│ └── norms(评分因子)
└── Translog(事务日志)
核心特点:
- 每个分片是一个独立的 Lucene 索引
- Segment 是实际存储数据的文件集合,只读不可变
- 新数据先写入内存 buffer,定期刷新(flush)生成新 Segment
- Translog 保证数据可靠性(类似 MySQL redo log)
Q6: ElasticSearch 深度分页问题怎么解决?
A: 问题本质:深度分页(如第 10000 页)需要汇总大量分片数据,资源消耗巨大。
解决方案:
| 方案 | 说明 |
|---|---|
| Scroll API | 适合大数据导出,滚动翻页,内部维护快照 |
| Search After | 基于排序值游走,适合实时翻页,不支持跳页 |
| PIT(Point In Time) | ES 7.x+ 引入,比 Scroll 更灵活 |
| 限制 max_result_window | 默认 10000 条,超出需申请 |
Search After 示例:
GET /index/_search
{
"size": 10,
"sort": [{"create_time": "desc"}, {"_id": "asc"}],
"search_after": [1640000000000, "doc_id_123"]
}
Q7: ElasticSearch 的算分方式有哪些?
A: ES 使用 TF-IDF 相关性评分算法,核心公式基于 Lucene 的 Practical Scoring Function:
score(q,d) = queryNorm(q) · coord(q,d) · Σ(t in q) [ tf(t in d) · idf(t)² · t.getBoost() · norm(t,d) ]
关键算分因素:
| 因子 | 说明 |
|---|---|
| TF(词频) | 词在文档中出现次数越多,相关性越高 |
| IDF(逆文档频率) | 词在越少文档中出现,权重越高 |
| boost | 字段/查询权重提升 |
| norm | 字段长度归一化因子 |
| coord | 查询词命中比例 |
常用算分模型:
BM25(ES 5.0+ 默认,可配置参数 k1、b)boolean(不做评分,返回 0/1)constant_score(固定分数)function_score(自定义函数评分)
Q8: ElasticSearch 的分词算法有哪些?
A: 按粒度分类:
- Standard(标准分词):按单词切分,适合英文
- Simple:按非字母字符切分
- Whitespace:按空格切分
- Keyword:不分词,保留原样
- Pattern:正则分词
中文分词器:
- IK:最常用,支持细粒度和智能分词
- jieba:结巴分词,Python 生态常用
- hanlp:支持多种分词模式
- THULAC:清华开源,标注式分词
分词器组成:
分词器(Analyzer)= 字符过滤器(Character Filter)+ 分词器(Tokenizer)+ 词元过滤器(Token Filter)
三、项目实战
Q9: 项目中数据量有多少?怎么还用 ES 了?
A: 回答思路:
- 说明数据量规模(如:日增 100 万+,总量数亿)
- 阐述业务痛点(MySQL 查询慢、无法满足复杂检索)
- ES 带来的效果(毫秒级响应、用户体验提升)
示例回答:
项目中我们有约 5000万+ 的商品数据,高峰期日增 50 万。使用 MySQL 的 LIKE 查询在千万级数据下响应超过 3 秒,用户体验很差。引入 ES 后,通过倒排索引和分片并行查询,P99 响应时间控制在 50ms 以内,同时支持复杂的组合条件查询和全文检索。
Q10: 项目中 ElasticSearch 的使用步骤?
A:
1. 数据同步
├── Logstash / Canal 监听 MySQL binlog
├── 定时任务全量/增量同步
└── MQ 消息队列异步写入
2. 索引设计
├── 定义 Mapping(字段类型、分词器)
├── 配置分片数(建议 3-5 个 Primary Shard)
└── 设置副本数(一般 1-2 个 Replica)
3. 数据写入
├── Bulk API 批量写入
└── 控制写入频率(避免写入过快导致集群压力)
4. 查询开发
├── Bool Query 组合查询
├── 高亮显示
└── 聚合统计
5. 性能优化
├── 冷热数据分离
├── 路由优化(routing)
└── 缓存优化
Q11: 什么场景适合使用 ElasticSearch?
A:
| 场景 | 说明 |
|---|---|
| 全文检索 | 站内搜索、商品搜索、文档检索 |
| 日志分析 | ELK 日志收集与分析 |
| 数据分析 | 聚合统计、实时仪表盘 |
| 地理搜索 | LBS 附近的人/商家 |
| 模糊匹配 | 拼音搜索、错别字容错 |
| 复杂查询 | 多条件组合、嵌套查询 |
不适合场景:
- 强事务要求(使用 MySQL/PostgreSQL)
- 频繁更新/删除(段合并开销大)
- 简单 K-V 查询(使用 Redis/HBase)
四、ELK 生态与集成
Q12: ELK 知道是啥吗?
A: ELK 是 Elastic Stack 的简称:
| 组件 | 作用 |
|---|---|
| Elasticsearch | 搜索引擎、存储、检索 |
| Logstash | 数据收集、过滤、转换 |
| Kibana | 数据可视化、Web UI |
| Beats | 轻量级数据采集器(Filebeat、Metricbeat 等) |
数据流向:
日志源 → Beats/Logstash → Elasticsearch → Kibana
(采集/过滤) (存储检索) (可视化)
Q13: ElasticSearch 和 MySQL 的数据如何保证一致性?
A: 同步方案对比:
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 双写 | 写 MySQL 时同步写 ES | 实现简单 | 一致性难以保证 |
| 异步双写 | MQ 异步同步 | 解耦、可用性高 | 延迟、数据丢失风险 |
| Canal 监听 | 监听 binlog 同步 | 侵入性低 | 运维复杂 |
| DataX/ETL | 定时全量/增量同步 | 简单可靠 | 实时性差 |
最佳实践:
- 核心交易数据:Canal + MQ 保证最终一致性
- 日志类数据:Logstash 直接采集,允许短暂不一致
- 定期对账补偿机制
Q14: ElasticSearch 的倒排索引解释下,跟正排索引有什么区别?
A: 正排索引(Forward Index):
文档 → 词列表
doc1 → [词A, 词B, 词C]
doc2 → [词B, 词D]
查询时需要遍历所有文档,复杂度 O(n)。
倒排索引(Inverted Index):
词 → 文档列表
词A → [doc1, doc3]
词B → [doc1, doc2]
查询时根据词直接定位文档,复杂度 O(1)。
ES 倒排索引结构:
Term Dictionary(词字典)→ Term Index(FST 前缀树)→ Posting List(倒排列表)
├── doc ID
├── frequency
└── position
Q15: ElasticSearch 的底层基于什么技术开发的?
A:
- 核心引擎:Apache Lucene(Java 开发的全文搜索引擎库)
- 通信层:Netty(高性能网络框架)
- 分布式协调:ZooKeeper / 自行实现(ES 7.x+ 自研 ZenDiscovery)
- 底层语言:Java(JVM 运行时)
- 数据结构:FST(有限状态自动机)、Skip List、B-Tree
ES 在 Lucene 基础上实现了分布式、RESTful API、高可用等企业级特性。
Q16: ElasticSearch 跟 MySQL 有啥区别?
A:
| 维度 | MySQL | ElasticSearch |
|---|---|---|
| 定位 | 事务型数据库 | 搜索引擎/文档数据库 |
| 数据结构 | 行存储、严格 Schema | 文档存储、Schema-less |
| 索引 | B-Tree 主键/辅助索引 | 倒排索引 + 多类型索引 |
| 事务 | ACID 完整支持 | 无事务(文档级原子性) |
| 关联查询 | JOIN 支持 | 嵌套文档/宽表设计 |
| 写入性能 | 较高 | 写入延迟较大(先写内存再刷盘) |
| 查询性能 | 复杂查询较慢 | 全文检索、聚合分析快 |
| 数据量 | 千万级 | 亿级+ |
最佳实践:MySQL 作为主数据源,ES 作为检索/分析引擎,二者配合使用。
Q17: ElasticSearch 的体系结构是啥样的?
A:
┌─────────────────────────────────────────────────┐
│ Cluster(集群) │
│ ┌─────────────────────────────────────────┐ │
│ │ Node(节点) │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ Index(索引) │ │ │
│ │ │ ┌───────────┐ ┌───────────┐ │ │ │
│ │ │ │ Primary │ │ Replica │ │ │ │
│ │ │ │ Shard │ │ Shard │ │ │ │
│ │ │ └─────┬─────┘ └─────┬─────┘ │ │ │
│ │ │ ↓ ↓ │ │ │
│ │ │ ┌───────────────────┐ │ │ │
│ │ │ │ Segment │ │ │ │
│ │ │ │ (Lucene Index) │ │ │ │
│ │ │ └───────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
关键概念:
- Cluster:由多个 Node 组成,共享同一 Cluster Name
- Node:ES 实例,分 Master/Data/Ingest/Coordinating 角色
- Index:逻辑数据组织单位,类似数据库
- Shard:数据分片,Primary Shard 负责写入,Replica Shard 负责备份和查询
- Segment:Lucene 底层数据文件,只读不可变
五、Mapping 与分词
Q18: 项目中搜索对应的 ES 索引库映射关系有哪些字段?
A: 示例商品索引 Mapping:
{
"mappings": {
"properties": {
"id": { "type": "keyword" },
"title": {
"type": "text",
"analyzer": "ik_max_word",
"fields": { "keyword": { "type": "keyword" } }
},
"description": { "type": "text", "analyzer": "ik_smart" },
"category_id": { "type": "keyword" },
"price": { "type": "double" },
"stock": { "type": "integer" },
"brand": { "type": "keyword" },
"tags": { "type": "keyword" },
"location": { "type": "geo_point" },
"create_time": { "type": "date" },
"status": { "type": "integer" }
}
}
}
字段设计原则:
- 需要分词检索的字段 →
text+ 分词器 - 精确匹配/聚合/排序字段 →
keyword - 数值范围查询 →
integer/double/long - 地理搜索 →
geo_point
Q19: 哪些字段是可分词的?
A:
- text 类型:可分词,ES 默认对 text 字段进行分词处理
- keyword 类型:不可分词,作为整体精确匹配
示例:
{
"title": {
"type": "text", // 可分词:用于全文检索
"fields": {
"keyword": { // 不可分词:用于精确匹配、排序
"type": "keyword"
}
}
}
}
Q20: 分词器用的什么?
A: 中文分词器推荐:
- IK Analyzer:最成熟,生态好,支持细粒度和智能分词
ik_max_word:最细粒度分词("中华人民共和国" → "中华人民共和国/中华人民/华人/人民/共和国/共和国") ik_smart:最粗粒度("中华人民共和国" → "中华人民共和国")
配置示例:
PUT /index
{
"settings": {
"analysis": {
"analyzer": {
"my_ik": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["lowercase"]
}
}
}
}
}
Q21: ES 的分词器有几种?
A:
| 类别 | 分词器 | 说明 |
|---|---|---|
| 内置 | standard | ES 默认,英文按词切分 |
| simple | 按非字母字符切分 | |
| whitespace | 按空格切分 | |
| keyword | 不分词,保留原样 | |
| pattern | 正则表达式分词 | |
| 中文 | IK | 最流行,需安装插件 |
| jieba | 社区活跃 | |
| hanlp | 多种分词模式 | |
| 拼音 | pinyin | 搜索友好(拼音首字母) |
Q22: ES 的字符串类型有几种?
A:
| 类型 | 说明 | 适用场景 |
|---|---|---|
| text | 可分词,全文检索 | 描述、标题、内容 |
| keyword | 不可分词,精确匹配 | ID、分类、标签、排序字段 |
| match_only_text | 7.6+,禁用打分优化存储 | 日志场景 |
注意事项:
- ES 5.x 后移除了 string 类型,统一使用 text/keyword
- 两者可以同时使用(multi-field):
"field": { "type": "text", "fields": { "keyword": { "type": "keyword" } } }
六、查询类型
Q23: ES 有哪些查询类型?
A: 按查询方式分类:
| 类型 | 说明 |
|---|---|
| 全文检索 | match、multi_match、query_string |
| 精确查询 | term、terms、range |
| 复合查询 | bool、boosting、constant_score |
| 模糊查询 | fuzzy、wildcard、regexp |
| 地理位置 | geo_distance、geo_bounding_box |
| 嵌套查询 | nested、has_child、has_parent |
| 相似度 | more_like_this |
| 脚本查询 | script |
常用查询示例:
GET /index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "手机" } }
],
"filter": [
{ "term": { "category_id": "1" } },
{ "range": { "price": { "gte": 1000, "lte": 5000 } } }
]
}
}
}
Q24: ES 的聚合查询怎么用?
A: 主要聚合类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| bucket | 分桶聚合 | terms、range、date_histogram |
| metric | 指标聚合 | avg、sum、max、min、stats |
| pipeline | 管道聚合 | sum_bucket、avg_bucket |
示例:
GET /index/_search
{
"size": 0,
"aggs": {
"category_stats": {
"terms": { "field": "category_id", "size": 10 },
"aggs": {
"avg_price": { "avg": { "field": "price" } },
"max_price": { "max": { "field": "price" } }
}
}
}
}
Q25: 用的是什么查询类型?
A: 常见最佳实践:
| 场景 | 推荐查询类型 |
|---|---|
| 全文检索 | bool + match |
| 精确过滤 | bool + filter + term/range |
| 排序 + 检索 | bool + match + sort |
| 高亮展示 | match + highlight |
| 关联嵌套文档 | nested + bool |
推荐结构:
{
"query": {
"bool": {
"must": [
{ "match": { "title": "搜索词" } }
],
"filter": [
{ "term": { "status": 1 } }
],
"should": [
{ "match": { "brand": "品牌词" } }
]
}
}
}
Q26: 用于搜索的 Java API 类叫啥名字?
A: 原生 Java High Level REST Client:
// 创建客户端
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 构建查询
SearchRequest searchRequest = new SearchRequest("index_name");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("title", "手机"));
sourceBuilder.from(0).size(20);
sourceBuilder.sort("create_time", SortOrder.DESC);
searchRequest.source(sourceBuilder);
// 执行搜索
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析结果
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
Spring Boot 集成:
- Spring Data Elasticsearch
- Elasticsearch RestTemplate
七、集群与运维
Q27: ElasticSearch 有搭建集群吗?
A: 常见集群架构:
| 架构 | 说明 | 适用场景 |
|---|---|---|
| 单机 | 开发/测试 | 开发环境 |
| 多节点集群 | 生产标准 | 中小规模(3-5 节点) |
| 热温冷架构 | 分层存储 | 大规模日志/时序数据 |
| 跨机房集群 | 高可用容灾 | 核心业务 |
集群健康检查:
GET /_cluster/health
# green: 所有分片正常
# yellow: 主分片正常,副本未分配
# red: 有主分片丢失
Q28: ElasticSearch 集群如果发生脑裂问题,如何解决?
A: 脑裂(Split-Brain): 集群因网络分区导致多个节点认为自己是主节点,破坏数据一致性。
原因:
- 网络抖动
- Master 节点负载过高,响应超时
minimum_master_nodes配置不当
解决方案:
| 措施 | 说明 |
|---|---|
| 正确配置 | minimum_master_nodes = (N/2) + 1(N 为合格节点数) |
| 降低负载 | 避免 Master 节点承担大量查询 |
| 网络隔离 | 确保网络稳定,跨机架/机房合理部署 |
| 手动恢复 | 确认合法 Master,剔除异常节点 |
| 重启集群 | 极端情况下重启集群 |
配置示例:
# elasticsearch.yml
discovery.zen.minimum_master_nodes: 2 # 3节点集群设为2
discovery.zen.ping_timeout: 3s
Q29: Elasticsearch 中的函数?
A: function_score 查询:允许使用函数影响文档评分。
| 函数 | 说明 | 示例 |
|---|---|---|
| script_score | 自定义脚本计算分数 | 基于字段运算 |
| random_score | 随机评分 | 打破评分相同时的排序 |
| field_value_factor | 字段值因子 | 点赞数影响排序 |
| decay_functions | 衰减函数 | 时间/距离衰减 |
| weight | 固定权重 | boost 权重调整 |
示例:时间衰减
{
"query": {
"function_score": {
"query": { "match": { "title": "手机" } },
"gauss": {
"create_time": {
"origin": "now",
"scale": "30d",
"decay": 0.5
}
}
}
}
}
八、补充:高频追问
Q30: ES 的数据写入流程?
A:
客户端 → Coordinating Node → Primary Shard
↓
写入内存 Buffer
↓
定期 Refresh(默认1秒)
↓
生成 Segment
↓
写入 Translog
↓
定期 Flush(删除旧 Translog)
Q31: ES 如何保证高可用?
A:
- 副本分片:每个 Primary Shard 可配置多个 Replica
- 故障转移:Master 节点监控,异常时重新选主
- 分片分配:自动均衡分配,避免单点
- 脑裂防护:
minimum_master_nodes机制
Q32: ES 优化建议?
A:
| 维度 | 优化建议 |
|---|---|
| 写入 | 批量写入、Bulk API、减少 Refresh 频率 |
| 查询 | 避免 SELECT *、Filter 缓存、路由优化 |
| 索引 | 合理分片数、Alias 切换零停机 |
| 硬件 | SSD、内存充足、CPU 高性能 |
| 分词 | 选择合适分词器、冷热分离 |
📚 面试技巧:回答时结合实际项目经验,用数据说明效果(如:查询耗时从 3s 降到 50ms),比纯概念更有说服力。