ES整个查询过程是scatter/gather的过程,具体如下:

图见   最后

 

我是有些怀疑文章里面的说法的,因为如果都是由master来做merge的话,那么势必master的在查询比较多的时候会负载很高!我个人感觉应该是client node接受到查询,然后去master node的metadata里获取各个index对应shard,拿到shard后,然后给所有的shard发送搜索请求,然后client node根据各shard的搜索结果进行merge,最后返回。

 

该文章里的说法:

elasticsearch整个查询是scatter/gather思想,也是多数分布式查询的套路,即:
1. master服务端(配置为node.master: true)接收客户端请求,查找对应的index、shard,分发数据请求到对应node服务端(node.data: true)
2. node端负责数据查询,返回结果到master端
3. master端把查询结果进行数据合并
上面流程是一个逻辑流程,es的具体查询过程中会分为不同的查询类型:QUERY_THEN_FETCH、QUERY_AND_FETCH(Deprecated),有不同的查询动作。
由于QUERY_AND_FETCH在5.X已经废除(使用QUERY_THEN_FETCH替代),所以这里只介绍QUERY_THEN_FETCH查询流程。

 

更加清楚的介绍在:

 

 

master服务端
1、接收查询请求,进行readblock检查。根据request的index构造相应的ShardsIterator,shardIterators由localShardsIterator和remoteShardIterators合并而成,用户遍历所有的shard。生成shardits会有一些查询策略,控制每个shard的查询优先次序和条件控制。

preferenceType = Preference.parse(preference);
switch (preferenceType) {
   case PREFER_NODES:
       final Set<String> nodesIds =
               Arrays.stream(
                       preference.substring(Preference.PREFER_NODES.type().length() + 1).split(",")
               ).collect(Collectors.toSet());
       return indexShard.preferNodeActiveInitializingShardsIt(nodesIds);
   case LOCAL:
       return indexShard.preferNodeActiveInitializingShardsIt(Collections.singleton(localNodeId));
   case PRIMARY:
       return indexShard.primaryActiveInitializingShardIt();
   case REPLICA:
       return indexShard.replicaActiveInitializingShardIt();
   case PRIMARY_FIRST:
       return indexShard.primaryFirstActiveInitializingShardsIt();
   case REPLICA_FIRST:
       return indexShard.replicaFirstActiveInitializingShardsIt();
   case ONLY_LOCAL:
       return indexShard.onlyNodeActiveInitializingShardsIt(localNodeId);
   case ONLY_NODES:
       String nodeAttributes = preference.substring(Preference.ONLY_NODES.type().length() + 1);
       return indexShard.onlyNodeSelectorActiveInitializingShardsIt(nodeAttributes.split(","), nodes);
   default:
       throw new IllegalArgumentException("unknown preference [" + preferenceType + "]");
}

主(Master)节点说明

主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。

node.master: true 

node.data: false

 

elasticsearch可以使用preference参数来指定分片查询的优先级,使用时就是在请求url上加上preference参数,如:http://ip:host/index/_search?preference=_primary

java的调用接口翻译为:client.prepareSearch("index").setPreference("_primary")。

默认情况下es有5种查询优先级:

_primary: 指查询只在主分片中查询

_primary_first: 指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。

_local: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。

_only_node:指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,所以查询结果可能不完整。如_only_node:123在节点id为123的节点中查询。

Custom (string) value:用户自定义值,指在参数cluster.routing.allocation.awareness.attributes指定的值,如这个值设置为了zone,那么preference=zone的话就在awareness.attributes=zone*这样的节点搜索,如zone1、zone2。