ES源码阅读——seach流程

search流程,分为查询query阶段,和fetch取回阶段,也叫query then fetch。

为什么要分成2个阶段。因为协调节点,也不知道数据分别在哪个分片上,所有在协调节点会找到所有分片,让每个分片执行查询,最后在协调节点将结果合并,返回给客户端。

假设有5个分片,查询相关度最高的10个文档,那么协调节点会让5个分片都执行查询,每个分片都要查询相关度最高的10个文档,协调节点再将50个文档再次排序,最终返回top10给客户端。

协调节点:接收客户端请求的节点。
数据节点:真正执行搜索任务的节点是数据节点。

search流程

1、合并分片

执行查询的逻辑是在TransportSearchAction类下面,为何要起这个名字,传过来查询的动作。用SearchAction岂不是更好。

之所以用Transport,是因为查询的逻辑属于Transport模块

ES的几个模块:

  • Cluster
  • allocation
  • discovery
  • gateway
  • indices
  • http
  • transport
  • engine

查询的逻辑,会将本地的分片列表和远程的分片列表合并到一起


        // 本地集群分片列表
        GroupShardsIterator<ShardIterator> localShardsIterator = clusterService.operationRouting().searchShards(clusterState,
                concreteIndices, routingMap, searchRequest.preference(), searchService.getResponseCollectorService(), nodeSearchCounts);
        // 将本地集群分片列表和远程集群分片列表合并,得到目的分片列表
        GroupShardsIterator<SearchShardIterator> shardIterators = mergeShardsIterators(localShardsIterator, localIndices,
            remoteShardIterators);

2、执行查询

找到所有分片信息后,开启线程进行查询,使用的方法是searchAsyncAction。

AbstractSearchAsyncAction类是个抽象类,父类是InitialSearchPhase,InitialSearchPhase类继承了SearchPhase。SearchPhase这个类实现了CheckedRunnable接口。

@FunctionalInterface
public interface CheckedRunnable<E extends Exception> {
    void run() throws E;
}

InitialSearchPhase的run方法,对所有分片执行遍历

if (shardsIts.size() > 0) {
            int maxConcurrentShardRequests = Math.min(this.maxConcurrentShardRequests, shardsIts.size());
            for (int index = 0; index < maxConcurrentShardRequests; index++) {
                final SearchShardIterator shardRoutings = shardsIts.get(index);
                assert shardRoutings.skip() == false;
                // 分片执行遍历的逻辑
                performPhaseOnShard(index, shardRoutings, shardRoutings.nextOrNull());
            }
        }

fetch流程

posted @ 2021-06-10 14:17  清泉白石  阅读(407)  评论(0编辑  收藏  举报