今天面试中被问到了几个关于 Elasticsearch(ES)的问题,涉及数据模型、搜索过程、Master 选举以及文档搜索的细节。面试官的提问挺深入的,下面我把这些问题整理成博客,既是复盘自己的回答,也方便日后复习。
1. Elasticsearch 的数据模型核心概念
面试官第一个问题就直奔主题:"ES 的数据模型核心概念是什么?"我稍微整理了一下思路,回答了以下内容:
ES 是一个分布式搜索引擎,其数据模型设计非常灵活,和传统关系型数据库有些相似之处,但也有自己的特点。我主要提到了以下几个核心概念:
-
索引(Index)
我解释说,索引是 ES 中最顶层的逻辑单元,就像数据库中的"数据库"。一个索引包含一堆结构相似的文档数据,ES 用它来组织和管理数据。面试官追问了一句:"那索引是怎么分布的?"我补充说,索引会被分成多个分片(Shards),分片可以分布在集群的不同节点上,这样就能实现分布式存储和高并发处理。
-
类型(Type)
这里我稍微有点卡壳,因为类型这个概念在 ES 的新版本中变化挺大。我提到,在老版本(6.x 之前),一个索引可以有多个类型,就像数据库里的表。但从 7.x 开始,ES 废弃了多类型设计,默认只用
_doc
作为类型。我觉得自己这部分答得不够流畅,面试官也没深究。 -
文档(Document)
我说文档是 ES 的基本存储单位,相当于数据库里的一行数据,用 JSON 格式表示,每个文档有唯一的
_id
。文档会被分配到某个分片里存储。 -
字段(Field)
字段是文档的最小单元,就像数据库的列。每个字段有自己的数据类型,比如文本、数字或者日期,还可以通过映射(Mapping)来定义怎么存储和索引。
-
分片(Shard)与副本(Replica)
我特别强调了分片和副本的区别。主分片负责写入数据,副本分片是主分片的拷贝,用来提高查询性能和容错性。面试官点了点头,似乎对这个回答还算满意。
复盘下来,我觉得自己对数据模型的理解还算清晰,但提到"类型"时有点不够自信,下次得更熟练地解释版本演变。
2. 详细描述 ES 搜索的过程
第二个问题是:"ES 的搜索过程是怎么样的?能不能详细说说?"这个问题让我有点兴奋,因为之前正好研究过 ES 的搜索流程。我是这样回答的:
ES 的搜索过程可以分成两个主要阶段:查询阶段(Query Phase) 和 获取阶段(Fetch Phase)。
-
查询阶段
我说,当客户端发起一个搜索请求时,请求会先到达一个协调节点(Coordinating Node)。协调节点会解析查询条件,然后把请求广播到所有相关的主分片或副本分片(取决于分片分配)。每个分片独立执行查询,基于本地数据生成一个匹配文档的列表(通常是文档 ID 和得分),然后把结果返回给协调节点。协调节点会把这些结果汇总,排序后选出得分最高的前 N 个文档(N 由请求中的 size 参数决定)。
-
获取阶段
接着,我提到协调节点拿到文档 ID 列表后,会再次向对应的分片请求完整的文档数据。分片返回文档内容后,协调节点把结果整合好,再返回给客户端。
面试官追问:"如果数据量很大怎么办?"我想了想,说 ES 支持分布式并行处理,分片越多查询越快,但协调节点的汇总工作可能会成为瓶颈,所以得合理设置分片数和优化查询条件。这部分我觉得自己答得还行,但可以再补充一些细节,比如倒排索引的作用。
3. ES 是怎么做 Master 选举的,详细分析多节点时的状况
第三个问题是关于 Master 选举的,面试官问得挺细:"ES 的 Master 选举是怎么实现的?多节点情况下会怎么样?"这个问题考察的是 ES 的分布式机制,我尽量回忆了之前看过的源码和文档。
我回答说,ES 的 Master 选举基于一个叫 Zen Discovery 的模块,采用的是类 Raft 的分布式一致性算法。具体过程是这样的:
-
节点发现与集群状态
每个节点启动时会通过网络发现其他节点(可以用组播或单播),形成一个候选节点列表。集群的状态(Cluster State)由 Master 节点维护,包括分片分配、索引元数据等。
-
选举触发
如果当前 Master 宕机或者网络分区导致 Master 不可用,集群会触发选举。每个节点会根据自己的节点 ID 和一些配置(比如
discovery.zen.minimum_master_nodes
)判断谁能成为 Master。 -
选举过程
节点之间会互相通信,投票选出一个新的 Master。只有当某个节点获得了至少
minimum_master_nodes
(最小主节点数,通常设为集群节点数的一半加一)的支持时,它才能当选。选举成功后,新 Master 会同步集群状态,确保所有节点一致。 -
多节点情况
我特别分析了多节点场景。如果集群有 5 个节点,设
minimum_master_nodes
为 3,当网络分区发生时,比如分成 2 个和 3 个节点的子集群,只有 3 个节点的那部分能选出 Master,2 个节点的部分会进入"无 Master"状态,避免脑裂(Split Brain)。面试官问:"脑裂怎么完全避免?"我说除了设置合理的minimum_master_nodes
,还得优化网络配置,确保节点间通信稳定。
这部分我答得还算完整,但感觉可以再提一下故障转移的具体时间复杂度,显得更专业。
4. ES 搜索文档的详细过程
最后一个问题是:"ES 搜索文档的详细过程是什么?"我一开始以为和第二个问题重复,但面试官强调了"文档"二字,我才反应过来是要讲底层细节。
我回答说,ES 搜索文档主要依赖 倒排索引(Inverted Index),过程可以拆成以下几步:
-
查询解析
客户端发来的查询(比如
match
或term
)会被 ES 解析成 Lucene 能理解的查询对象,比如布尔查询或者词条查询。 -
倒排索引查找
ES 在每个分片的倒排索引里查找匹配的词条(Term)。倒排索引是一个词到文档的映射表,记录了每个词出现在哪些文档中,以及词频和位置信息。分片会根据查询条件快速定位匹配的文档 ID。
-
评分与排序
找到匹配文档后,ES 会用评分模型(默认是 BM25)计算每个文档的相关性得分。得分高的文档会被优先返回。如果不需要排序(比如用
filter
),这一步会跳过评分,直接返回结果。 -
分布式合并
因为数据分布在多个分片上,每个分片返回局部结果后,协调节点会把这些结果合并、排序,再去分片取完整的文档数据。
-
返回结果
最后,协调节点把文档内容组装成 JSON 返回给客户端。
面试官问了个扩展问题:"倒排索引怎么优化搜索效率?"我说可以通过压缩(比如 Roaring Bitmaps)和跳表(Skip List)来加速查找,还可以调整分词器减少无效索引。这部分我答得有点仓促,感觉可以再深入讲讲分词器的配置。
总结
这次面试让我意识到自己在 ES 的底层细节上还有些薄弱,比如 Master 选举的时间复杂度和倒排索引的优化策略。整体来说,回答还算流畅,但表达上可以更简洁一些。下次准备时,我得多看点源码和官方文档,把细节夯实。