Elasticsearch 的心脏引擎---Lucene
摘要:Elasticsearch(ES)通过分布式架构实现高效数据存储与检索。写入流程包含:1)协调节点路由请求至主分片;2)数据先写入内存缓冲区并记录到Translog;3)定期刷新生成可搜索的Segment;4)Commit将数据持久化到磁盘;5)同步副本分片。查询流程采用Scatter-Gather模式:1)广播查询至各分片;2)各分片使用Lucene倒排索引执行本地搜索;3)协调节点合并排
1. Lucene 是什么? (搜索引擎的“引擎” ⚙️)
-
定义:Lucene 是一个由 Apache 软件基金会开发的、开源的、高性能的 Java 全文检索引擎工具包。
-
形态:它不是一个完整的应用或服务器,而是一个 Java 类库 (JAR包)。开发者可以将它集成到自己的 Java 应用中。
-
核心能力:
-
提供了强大的 索引 (Indexing) 和 搜索 (Search) 功能。
-
其底层核心是 倒排索引 (Inverted Index),这是实现快速全文检索的关键技术。
-
-
局限性:
-
使用复杂:直接使用 Lucene 的 API 相对底层和繁琐。
-
功能单一:只关注索引和搜索,不提供分布式、高可用、数据聚合等高级功能。
-
非开箱即用:需要开发者自己编写大量代码来构建一个完整的搜索引擎应用。
-
核心概念梳理
在深入流程之前,必须理解几个关键概念的对应关系:
| Elasticsearch 概念 | Lucene 概念 | 解释 |
| Index (索引) | Directory (目录) | 一个 ES 索引由多个分片组成,每个分片都是一个独立的 Lucene 实例。 |
| Shard (分片) | 完整的 Lucene 实例 | 一个分片就是一个功能完备的搜索引擎。它是 ES 数据分发和并行化的基本单位。 |
| Segment (段) | Segment (段) | 一个 Lucene 索引由多个段组成。段是不可变的、独立的索引单元。 |
| Inverted Index | Inverted Index (倒排索引) | Lucene 的核心数据结构,用于快速查找包含特定词项的文档。 |
关键点:ES 负责处理分布式的复杂性(如何将请求路由到正确的分片、如何汇总结果),而每个分片(Shard)内部则是一个独立的 Lucene 实例,负责本地的索引和搜索工作。
2. 写入(Indexing)数据的过程
当你向 ES 发送一个索引请求(例如 POST /my_index/_doc),整个流程如下:
ES 分布式层面 (协调与路由)
-
接收请求:客户端请求发送到集群中的任意一个节点。这个节点被称为 协调节点 (Coordinating Node)。
-
路由计算:协调节点根据文档的 _id 通过一个哈希公式 (hash(_id) % num_primary_shards) 计算出这份文档应该存储在哪个 主分片 (Primary Shard) 上。
-
请求转发:协调节点将请求转发到持有该主分片的 数据节点 (Data Node)。
Lucene 本地层面 (实际写入)
现在,请求到达了目标数据节点,该节点上的主分片开始工作。这部分是纯粹的 Lucene 操作:
-
写入内存缓冲区 (In-memory Buffer):
-
文档首先被写入内存中的一个缓冲区。这里的数据还不能被搜索到。
-
同时,为了数据安全,ES 会将这次操作记录到一个叫 Translog (事务日志) 的文件中。这是一种预写日志(Write-Ahead Log),即使节点宕机,重启后也可以通过 Translog 恢复数据。
-
-
Refresh (刷新) -> 生成 Segment:
-
默认情况下,每隔1秒(可配置),内存缓冲区的数据会被 "refresh" 到文件系统缓存中,形成一个新的 段 (Segment)。
-
关键点:一旦数据被写入一个 Segment,它就变得 可以被搜索到 了。这就是 ES 被称为 “近实时 (Near Real-Time)” 的原因——从写入到可被搜索有秒级的延迟。
-
Segment 是 不可变 的。更新或删除文档实际上是在新的 Segment 中标记旧文档为“已删除”,而不是修改旧 Segment。
-
-
Commit (提交/落盘):
-
虽然数据通过 Refresh 已经可以被搜索,但它仍在文件系统缓存中。为了防止断电导致数据丢失,ES 会定期执行 commit 操作(或当 Translog 达到一定大小时触发)。
-
Commit 操作会调用 Lucene 的 commit 方法,将文件系统缓存中的所有 Segment 数据 强制刷写(fsync)到物理磁盘上。
-
一旦 Commit 完成,对应的 Translog 就可以被安全地清除了。
-
ES 分布式层面 (数据同步与响应)
-
同步到副本:主分片完成索引操作后,会将请求并行地转发给所有的 副本分片 (Replica Shards)。副本分片会执行与主分片完全相同的 Lucene 写入流程(步骤 4, 5, 6)。
-
返回响应:一旦足够数量的分片(主分片 + N个副本分片,可配置)完成了操作,主分片所在节点就会向协调节点报告成功,协调节点最终向客户端返回成功响应。
流程图示:
codeCode
Client -> Coordinating Node -> Primary Shard Node -> [1. Translog, 2. Memory Buffer]
|
(refresh, ~1s)
|
v
New Lucene Segment (Searchable)
|
(commit/fsync)
|
v
Disk (Durable)
3. 查询(Searching)数据的过程
当你向 ES 发送一个搜索请求(例如 GET /my_index/_search?q=...),流程如下,这个过程被称为 Scatter-Gather (分发-汇聚)。
ES 分布式层面 (分发查询 - Scatter Phase)
-
接收请求:客户端请求同样到达一个 协调节点。
-
广播查询:协调节点将查询请求广播到该索引 (my_index) 所涉及的 每一个分片(可以是主分片或副本分片,ES 会做负载均衡)。
Lucene 本地层面 (执行查询)
-
本地搜索:每个分片(一个独立的 Lucene 实例)在本地执行该查询。
-
Lucene 会查询自己持有的 所有 Segment。
-
它利用 倒排索引 快速找到包含查询词项的文档 ID 列表。
-
对匹配的文档计算相关性得分 (_score)。
-
每个分片都会生成一个根据得分排序的、包含文档 ID 和分数的 本地结果优先队列 (例如,返回前10条结果,它可能会先找出本地的前10条)。
-
ES 分布式层面 (汇聚结果 - Gather Phase)
-
结果汇聚:所有分片将自己的本地结果(只包含文档 ID 和分数,不包含完整文档)返回给协调节点。
-
全局排序:协调节点收集到所有分片的结果后,将它们合并并进行 全局重新排序,以找出真正的 Top N 结果(例如,从3个分片各收到的10条结果中,选出全局得分最高的10条)。
-
获取文档 (Fetch Phase):协调节点现在知道了最终要返回的文档的 _id。它会根据这些 _id,向持有这些文档的原始分片发起一个 Multi-GET 请求,以获取完整的文档内容 (_source)。
-
返回最终结果:协调节点将获取到的完整文档内容与排序结果合并,形成最终的 JSON 响应,返回给客户端。
流程图示:
codeCode
Client -> Coordinating Node
|
| (Broadcast Query)
+----------------> Shard 1 (Lucene Search -> Local Top N)
+----------------> Shard 2 (Lucene Search -> Local Top N)
+----------------> Shard 3 (Lucene Search -> Local Top N)
|
| (Gather Results)
<---------------- Shard 1 [IDs + Scores]
<---------------- Shard 2 [IDs + Scores]
<---------------- Shard 3 [IDs + Scores]
|
v
Coordinating Node (Merge & Global Sort -> Final Top N IDs)
|
| (Multi-GET by ID)
+----------------> Relevant Shards to fetch _source
|
<---------------- Full Documents
|
v
Client <--- Final Response
总结
-
写入时:ES 负责 路由 到正确的主分片,并协调 副本同步;主分片内的 Lucene 负责将数据写入 内存、生成 Segment、并最终持久化到磁盘。
-
查询时:ES 负责将查询 分发 到所有相关分片,并 汇聚、排序 各分片的结果;每个分片内的 Lucene 负责利用 倒排索引 在本地的 Segment 集合上进行高效搜索。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)