ES查询内核流程

网友投稿 802 2022-05-29

1     概述

ES查询分为GET和SEARCH两类,GET查询指定_index,_type,_id,从正排索引中获取指定Doc。SEARCH查询不指定_id,根据关键字从倒排索引中获取内容。以下主要分析SEARCH过程:

(1)    SEARCH过程分为两个阶段:Query和Fetch。

(2)    SEARCH过程涉及两类节点:协调节点和数据节点。

Query阶段客户端将请求发送给协调节点,协调节点将请求转发到数据节点上索引的每个主分片或副本分片中,每个分片在本地执行查询,并进行打分,添加结果到大小为from+size的本地有序优先队列中。每个分片返回各自优先队列中所有文档的ID和排序值给协调节点,协调节点合并这些值到自己的优先队列中,产生一个全局排序后的列表。

Fetch阶段根据Query阶段的结果,协调节点向相关数据节点发送GET请求,分片所在节点向协调节点返回数据,协调节点等待所有文档被取得,然后返回给客户端。

2     源码分析

2.1      协调节点流程

2.1.1        Query阶段:

1.解析请求

RestSearchAction#prepareRequest方法中将请求体解析为SearchRequest数据结构:

2.构造目的shard列表

将请求涉及的本集群shard列表和远程集群的shard列表合并,TransportSearchAction#executeSearch完成了合并操作,调用了mergeShardIterators:

3.遍历所有shard发送请求

请求是基于shard遍历的,如果列表中有N个shard位于同一个节点,则向其发送N次请求。AbstractSearchAsyncAction#run完成此操作,        performPhaseOnShard发送请求:

4.收集返回结果

AbstractSearchAsyncAction#onShardResult完成收集操作,consumeResult对收集的结果进行合并:

successfulShardException检查是否所有请求都已收到回复,是否进入下一阶段:

以上方法调用的OnPhaseDone方法会调用executeNextPhase,从而开始执行Fetch取回阶段。

2.1.2        Fetch阶段:

1.     发送Fetch请求

Query阶段的executeNextPhrase方法触发Fetch阶段,Fetch阶段的起点为FetchSearchPharse#innerRun函数,再进一步调用executeFetch方法,从查询阶段的shard列表中遍历来获取数据。

executeFetch的主要实现:

executeFetch中定义一个Listener,每成功获取一个shard数据后就执行counter.onResult,其中调用对结果的处理回调,把result保存到数组中,然后执行countDown:

2.     收集结果

收集器定义在innerRun中,包括收到的shard数据存放在哪里,收集完成后谁来处理:

fetchResults用于存储从某个shard收集到的结果,每收到一个shard的数据就执行一次counter.countDown。当所有shard数据收集完毕后,countDown会触发执行finishPhase:

moveToNextPhase方法执行下一阶段,下一阶段要执行的任务定义在FetchSearchPhase构造函数中,主要是触发ExpandSearchPharse,取回阶段完成之后执行ExpandSearchPharse#run,主要判断是否启用字段叠加,根据需要实现字段叠加功能。

3.     回复客户端

ExpandSearchPharse执行完之后回复客户端,在sendResonsePharse方法中实现:

2.3      数据节点流程

2.2.1        响应Query请求

主要过程就是执行查询,然后发送Response。Query,Fetch请求的处理入口注册于SearchTransportService#registerRequestHandler:

查询入口在searchService.executeQueryPhase中。查询时,先看是否允许cache,由以下配置决定:

index.requests.cache.enable

默认为true,会把查询结果放到cache中,查询时优先从cache中取。这个cache由节点的所有分片共享,基于LRU算法实现:空间满的时候删除最近最少使用的数据。所以cache并不缓存全局检索结果。

核心的查询封装在queryPhase.execute(context)中,其中调用Lucene实现检索,同时实现聚合:

其中包含几个核心功能:

executeInternal():调用Lucene的searcher.search()实现搜索;

rescoreRhase:全文检索且需要打分;

suggestPhase:自动补全及纠错;

aggregationPhase:实现聚合。

ES查询内核流程

2.2.2        响应Fetch请求

主要过程是执行Fetch,然后发送Response:

对Fetch响应的实现封装在searchService.executeFetrchPhase中,核心是调用fetchPhase.execute(context)。按照命中的doc取得相关数据,填充到SearchHits中,最终封装到FetchSearchResult中

Elasticsearch

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:科技抗疫!云脉疫情防控登记系统强化园区复工防控
下一篇:开发一个社区网站,只要20分钟?小白也能轻松掌握云上敏捷开发
相关文章