Elasticsearch八股文汇总

ylnxwlp 菲比啾比!

一、ES基础概念与原理

基础概念

什么是Elasticsearch?

Elasticsearch 是一个开源的分布式搜索和分析引擎,基于 Apache Lucene 构建。它提供了一个分布式、多租户的全文搜索引擎,能够近乎实时(NRT)地存储、搜索和分析大量数据。

Elasticsearch 的基本概念有哪些?

· 集群(Cluster):一个或多个节点的集合,共同保存整个数据,并提供跨所有节点的联合索引和搜索能力。
· 节点(Node):集群中的一个服务器,用于存储数据并参与集群的索引和搜索功能。
· 索引(Index):逻辑命名空间,指向一个或多个分片,相当于关系型数据库中的“数据库”或“表”。
· 文档(Document):索引中的基本数据单元,是 JSON 格式的记录,类似于关系型数据库中的一行。
· 类型(Type):在 7.x 版本之前,一个索引下可以有多个类型,用于区分不同结构的文档;7.x 后已废弃,一个索引只对应一种文档结构。

text 和 keyword 类型的区别

· text:用于全文搜索。在索引时会被分词器(analyzer)处理,生成多个词条并建立倒排索引。
· keyword:用于精确匹配、聚合和排序。不会被分词,整个字符串作为一个词条存储。
关键区别:text 用于搜索,keyword 用于过滤、聚合和排序。此外,keyword 默认启用 doc_values,而 text 不支持。

DocValues 的作用是什么?

DocValues 是一种列式存储结构,在索引时构建,用于加速排序、聚合和脚本计算。它将字段值按列组织,避免了将整个文档加载到内存,从而节省堆内存并提升性能。

什么是停顿词过滤?

停用词是指在自然语言中频繁出现但对语义贡献较小的词(如“的”、“是”、“the”、“and”)。ES 通过 stop token filter 在分词阶段移除这些词,以减小索引体积并提高搜索相关性。

query 和 filter 的区别是什么?

· query:用于全文搜索,会计算相关性得分(_score),结果按相关性排序。不缓存。
· filter:用于精确匹配(布尔、范围、存在性等),不计算得分,结果是“是/否”。结果会被缓存,性能更高。

Elasticsearch 有哪些数据类型?

· 字符串:text, keyword
· 数值:integer, long, float, double
· 日期:date
· 布尔:boolean
· 地理:geo_point
· 对象:object, nested

Elasticsearch 支持事务吗?

不支持传统 ACID 事务。ES 通过乐观并发控制(基于 _version)和副本机制保证一定程度的数据一致性,但无法实现多文档的原子提交与回滚。

核心原理

什么是倒排索引?

倒排索引(Inverted Index)是 Lucene 的核心数据结构。它将“词项(Term)”映射到包含该词的文档列表,从而实现快速全文检索。

倒排索引的实现原理

· 文档被分词后,每个词项对应一个倒排列表(Posting List),记录包含该词的文档 ID 及位置信息。
· 通过词典(Term Dictionary)快速定位词项,再通过倒排列表获取文档。

在 Elasticsearch 中,如何根据一个词找到对应的倒排索引?

ES 使用 FST(Finite State Transducer) 或 字典树(Trie) 结构存储词典,支持前缀压缩和快速查找,时间复杂度接近 O(len(term))。

如何在保留不变性的前提下实现倒排索引的更新?

Lucene 的索引是不可变的(Immutable)。更新操作实际上是:
1、删除旧文档(标记为删除)
2、写入新文档
3、后台通过 Merge 操作将多个 Segment 合并,移除已删除文档。

Lucene 内部结构是什么?

Lucene 索引由多个 Segment(段) 组成,每个 Segment 是一个独立的倒排索引。ES 中的一个分片(Shard)对应一个 Lucene 索引。

是否了解字典树?

字典树(Trie)是一种树形数据结构,用于高效存储和检索字符串前缀。ES/Lucene 使用其变种(如 FST)来压缩词典并加速词项查找。

Elasticsearch 和 MySQL 的区别

对比

Elasticsearch 为什么适合搜索?

· 基于倒排索引,支持高效的全文检索和复杂查询(布尔、短语、模糊等)。
· 分布式架构支持海量数据并行处理。
· 近实时(NRT)搜索能力。

Elasticsearch 的原理和结构是怎样的?

· 写入:数据先写入内存 buffer 和 translog → refresh 生成 Segment(可搜索)→ flush 持久化到磁盘。
· 查询:协调节点将请求分发到相关分片,并行执行后合并结果。

ES 为什么这么快?

· 倒排索引 + FST 词典:快速定位词项。
· 列式存储(DocValues):加速聚合。
· 分布式并行计算:分片机制天然支持水平扩展。
· 文件系统缓存(Filesystem Cache):Segment 常驻内存,避免磁盘 I/O。

存储机制

String 类型在 ES 中是怎么存储的?

ES 7.x 后不再有 string 类型,而是拆分为:
· text:分词后存入倒排索引(行式,用于搜索)。
· keyword:原样存储,并生成 doc_values(列式,用于聚合)。

列式存储与行式存储的区别?列式存储的优势?

· 行式存储:按文档存储所有字段,适合读取完整记录(如 MySQL)。
· 列式存储(DocValues):按字段存储所有文档的值,适合只读取少数字段的聚合操作,I/O 更少,压缩率更高。

你了解 Elasticsearch 的 Segment 吗?

Segment 是 Lucene 的最小索引单元,不可变。每次 refresh 会生成新 Segment。多个 Segment 可通过 Merge 合并以提升查询效率并回收空间。

Refresh 机制

· 默认每 1 秒 将内存 buffer 中的数据写入新 Segment,并使其可搜索。
· 不持久化到磁盘,依赖 translog 保证可靠性。
· 是 ES 实现“近实时搜索”的关键。

Flush 操作

· 触发条件:每 30 分钟或 translog 达到 512MB。
· 作用:将内存中的 Segment 持久化到磁盘,清空 translog,生成 commit point。

Merge 操作

后台自动将多个小 Segment 合并为大 Segment,删除已标记为删除的文档,减少文件数量,提升查询性能。

ES 如何保证数据不丢失?

· Translog:所有写入操作先写入 translog(持久化日志),即使断电也可恢复。
· 副本机制(Replica):每个主分片可配置多个副本,分布在不同节点,防止单点故障。
· Flush 机制:定期将数据持久化到磁盘。

二、ES架构与集群管理

集群架构

Elasticsearch 的架构是怎样的?

· 节点 (Node):一个运行中的 ES 实例。
· 集群 (Cluster):一个或多个拥有相同 cluster.name 的节点集合。
· 索引 (Index):逻辑命名空间,用于存储文档集合。
· 分片 (Shard):索引的物理子集,实现水平扩展。
· 副本 (Replica):分片的拷贝,提供高可用性和读取吞吐量。

分片机制如何实现分布式集群?

· 写入:文档通过 routing 规则分配到特定主分片。
· 查询:协调节点将请求广播到所有相关分片(主/副本),合并结果。
· 实现数据和计算负载分散,支持水平扩展。

分片和副本的区别?

· 主分片 (Primary Shard):数据写入入口,数量创建后不可变。
· 副本分片 (Replica Shard):
    高可用:主分片宕机时可提升为新主分片。
    提升读性能:查询可路由到副本。

分段机制(Segment)

· 写入 → 内存 buffer + translog → refresh → 生成不可变 Segment。
· 后台 Merge 合并小 Segment,清理已删除文档。

ES 是如何运行的?跑了几个节点?

生产集群通常角色分离:
· Master 节点(3~5个):集群管理。
· Data 节点(N个):存储数据、执行 CRUD/聚合。
· Coordinating 节点(2+个):接收请求、路由、合并结果。

Master 选举与脑裂

Elasticsearch 的分布式原理

基于分片/副本机制 + 去中心化集群状态管理。Master 节点维护全局集群状态(Cluster State),所有节点同步该状态。

Master 选举机制

· 资格:仅 node.roles: [master] 节点可参选。
· 发现:通过 discovery.seed_hosts 发现其他节点。
· 选举:基于改进的 Bully 算法,通常 ID 最小的合格节点胜出。

脑裂问题及解决方案

脑裂(Split Brain):网络分区导致多个 Master。
解决方案:
· 旧版(<7.x):设置 discovery.zen.minimum_master_nodes = (master_nodes / 2) + 1
· 7.x+:使用 discovery.seed_hosts + cluster.initial_master_nodes,自动计算法定人数(quorum),从根本上避免脑裂。

如何避免脑裂?

通过 法定人数(Quorum) 机制,确保仅一个 Master 被认可。

节点协调与负载

节点和分片如何协调?

· Master 节点:维护分片路由表,决定分片分配。
· Coordinating 节点:根据路由表转发请求到目标分片所在节点。

客户端如何选择节点执行请求?

· 客户端通过负载均衡(轮询/随机)连接任意节点。
· 该节点作为协调者,自动路由到正确分片,客户端无需关心物理位置。

数据倾斜问题及处理

· 原因:routing 策略不合理或数据分布不均。
· 处理:
    优化 routing key
    增加分片数
    使用 ILM 滚动索引
    手动 _cluster/reroute 重分配分片

什么是长尾问题?

· 现象:多数请求快,少数请求极慢(P99/P999 高)。
· ES 中体现:某分片所在节点负载高(Merge/GC),拖慢整体查询。
· 缓解:
    增加副本数
    优化 JVM/GC
    避免 dfs_query_then_fetch

三、数据写入与更新

写入流程

Elasticsearch 索引文档的过程

1、写入内存 buffer + translog
2、Refresh(默认1秒):buffer → 新 Segment(OS Cache,可搜索)
3、Flush(30分钟或512MB):Segment fsync 到磁盘,清空 translog

新增文档如何快速被检索?

Refresh 后新 Segment 加入倒排索引,搜索时查询所有 Segment(含新旧)。

更新删除

更新和删除过程

· 删除:标记为 deleted(.del 文件),Merge 时物理删除。
· 更新:先删旧文档(标记删除),再索引新文档(新 _version)。
文档本质不可变,更新=删除+新增。

高并发写入

写压力大时如何处理?

· 使用 Bulk API 批量写入
· 调大 refresh_interval(如 30s)或设为 -1
· 合理增加分片数
· 使用 ILM 按时间分索引
· 优化 Translog 和 Segment 策略

并发下如何保证读写一致?

· 乐观并发控制(OCC):通过 _version、if_seq_no、if_primary_term
· wait_for_active_shards:确保 N 个分片活跃才写入
· 主分片写入模型:主分片验证 → 并行写副本 → 全部成功才返回

四、搜索与查询

搜索流程

两阶段查询(Query Then Fetch)

Query 阶段:
· 协调节点广播查询到所有分片
· 各分片返回匹配的 doc ID + score
· 协调节点合并,选出 top-N doc ID
Fetch 阶段:
· 根据 doc ID 拉取 _source
· 组装完整结果返回

分词与查询

分词器(Analyzer)流程

1、Character Filter:预处理(如去 HTML 标签)
2、Tokenizer:切词(如空格、中文分词)
3、Token Filter:处理 tokens(小写、去停用词、同义词)

搜索示例

1
2
3
4
5
6
GET /index/_search
{
"query": {
"match": { "title": "手机" }
}
}

title 字段通常设为 text 类型,若需精确匹配/聚合,可添加 keyword 子字段:

1
2
3
4
5
6
"title": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" }
}
}

深度分页

深度分页问题与解决方案

· from + size:深度分页(如 from=100000)性能差
· Scroll:
    用于数据导出/全量遍历
    基于快照,期间数据变更不可见
· 推荐方案(7.x+):search_after + PIT(Point in Time)
    使用上一页最后一个文档的 sort 值
    支持排序,更轻量

五、性能优化与调优

索引优化

建立索引阶段性能提升方法

· 使用 Bulk API(5–15MB/批)
· 临时设 number_of_replicas=0,增大 refresh_interval
· 使用 SSD
· 合理规划分片数
· 禁用 _source 或不需要的字段

索引数据多了怎么办?

· ILM(Index Lifecycle Management):自动滚动、降冷、删除
· 索引别名:业务透明切换索引
· Force Merge:只读索引合并 Segment

常见调优手段

· 写入优化(如上)
· 查询优化:多用 filter context、避免深度分页
· 硬件优化:JVM 堆内存、GC 策略

聚合优化

上亿量级聚合如何实现?

· 分布式聚合:分片并行计算,协调节点汇总
· 增加分片数:提升并行度
· 近似聚合:如 cardinality 使用 HyperLogLog
· Index Sorting:预排序实现 early termination
· execution_hint:尝试 “map” 替代默认模式

系统调优

Linux 系统优化

· vm.swappiness=1(关闭 swap)
· nofile=65536+(文件描述符)
· vm.max_map_count=262144(设置虚拟内存)
· 文件系统:XFS > ext4(文件系统)

GC 注意事项

· 堆内存 ≤ 32GB(启用压缩指针),≤ 物理内存 50%
· 使用 G1GC(默认)
· 监控 GC 日志(频率、停顿时间)

六、部署与运维

部署相关

生产环境部署建议

· 角色分离:
    3+ Master 节点(专用)
    多 Data 节点
    专用 Coordinating 节点
· 网络:低延迟局域网,避免跨机房
· 配置管理:Ansible / Docker / K8s

集群监控

· Kibana Monitoring:可视化集群状态
· Metricbeat:采集指标(JVM、线程池、索引速率等)
· 关键指标:
    cluster health(green/yellow/red)
    heap usage
    thread pool rejections
    indexing/query latency

七、数据同步与一致性

数据同步

数据库如何同步到 ES?

1、同步双写:
· 应用层同时写 DB 和 ES
· 简单但强耦合,易不一致
2、异步消息队列:
· 监听 Binlog(Canal/Debezium)→ Kafka → 消费者写 ES
· 解耦、高吞吐、最终一致

如何保证 ES 与 MySQL 一致性?

· 幂等写入:应对消息重复
· 接受最终一致:短暂不一致可接受
· 定期校验修复:离线任务比对修复差异

八、应用场景与实战

使用场景

Elasticsearch 主要应用场景

· 全文搜索:电商、站内搜索
· 日志分析:ELK 栈(Logstash + ES + Kibana)
· 实时数据分析:用户行为、业务指标
· SIEM:安全日志分析
· 地理空间搜索:附近的人、区域查询

特殊场景

ES 如何构建地图索引?

· geo_point:
    表示经纬度点
    使用 GeoHash 编码,支持范围/附近查询
· geo_shape:
    支持线、多边形等复杂形状
    使用 BKD Tree 索引,支持相交、包含等空间关系查询

  • 标题: Elasticsearch八股文汇总
  • 作者: ylnxwlp
  • 创建于 : 2025-10-27 23:28:27
  • 更新于 : 2025-10-28 00:03:04
  • 链接: https://www.swissroll.today/2025/10/27/Elasticsearch-八股文汇总/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论