面试题答案
一键面试ElasticSearch 删除文档底层原理
内部数据结构
- 倒排索引:ElasticSearch 核心数据结构,由文档集合构建。每个词条关联包含该词条的文档列表,记录文档 ID 及词条在文档中的位置等信息。如文档集合
[doc1: "apple banana", doc2: "banana cherry"]
,构建倒排索引:“apple” -> [doc1],“banana” -> [doc1, doc2],“cherry” -> [doc2]。 - 段(Segment):Lucene 层面,数据存储在段中。段是不可变的,每个段有自己的倒排索引。新文档写入时,先写入内存中的索引缓冲区,达到一定条件后刷新到新段。段合并时,旧段数据合并到新段,旧段被标记为可删除。
操作流程
- 标记删除:当执行删除文档操作时,ElasticSearch 并非立即从磁盘物理删除文档。而是在对应的段中,为要删除的文档添加删除标记(.del 文件记录删除信息)。查询时,被标记删除的文档不会出现在结果集中,但实际数据依然存在于段中。
- 段合并与物理删除:随着不断有文档被标记删除,以及新文档写入生成新段,ElasticSearch 会在后台触发段合并操作。合并过程中,会将多个段合并成一个大段。此时,被标记删除的文档不会被复制到新段,从而实现物理删除。
删除大量文档性能瓶颈分析
- 磁盘 I/O 瓶颈:
- 标记删除阶段:大量删除文档时,需频繁写入删除标记到磁盘(.del 文件),产生大量小 I/O 操作,磁盘 I/O 性能下降。
- 段合并阶段:合并涉及读取多个段数据并写入新段,大量文档删除后段数量多,合并时磁盘 I/O 压力大。
- 内存瓶颈:
- 索引缓冲区:删除操作可能导致索引缓冲区频繁刷新,影响新文档写入性能。且删除大量文档后,后续段合并时,需要足够内存进行数据处理,若内存不足,会频繁进行磁盘交换,降低性能。
- 查询性能影响:删除大量文档过程中,虽文档被标记删除,但仍占用磁盘空间且影响查询时倒排索引遍历,导致查询性能下降。
性能优化策略
- 批量删除:使用批量删除 API,减少请求次数,降低网络开销和 I/O 操作次数。如使用
DELETE
批量删除 API 一次删除多个文档。 - 优化段合并策略:
- 调整合并参数:通过调整
index.merge.policy
相关参数,如max_merge_at_once
(一次合并的最大段数)、max_merge_at_once_explicit
(手动触发合并的最大段数)等,控制段合并频率和规模,减少磁盘 I/O 压力。 - 预热合并:在业务低峰期手动触发段合并,减少对正常业务的影响。
- 调整合并参数:通过调整
- 优化磁盘 I/O:
- 使用高性能存储:如 SSD 磁盘,提升磁盘读写性能,减少 I/O 等待时间。
- 优化磁盘布局:合理规划磁盘空间,避免磁盘碎片,提高 I/O 效率。
- 控制索引缓冲区:适当调整
index.buffer.size
等参数,平衡索引写入和删除操作对缓冲区的影响,减少不必要的缓冲区刷新。 - 异步删除:使用异步删除方式,将删除操作放入队列,后台线程处理,避免影响前台业务。如通过
DELETE BY QUERY
并设置wait_for_completion=false
进行异步删除。