Elasticsearch系列---搜索执行过程及scroll游标查询

本篇主要介绍一下分布式环境中搜索的两阶段执行过程

两阶段搜索过程

回顾我们之前的CRUD操作,因为只对单个文档进行处理,文档的唯一性很容易确定,并且很容易知道是此文档在哪个node,哪个shard中。

但搜索比CRUD复杂,符合搜索条件的文档,可能散落在各个node、各个shard中,我们需要找到匹配的文档,并且把从各个node,各个shard返回的结果进行汇总、排序,组成一个最终的结果排序列表,才算完成一个搜索过程。我们将按两阶段的方式对这个过程进行讲解。

查询阶段

假定我们的ES集群有三个node,number_of_primary_shards为3,replica shard为1,我们执行一个这样的查询请求:

GET /music/children/_search { "from": 980, "size": 20 }

查询阶段的过程示意图如下:

Elasticsearch系列---搜索执行过程及scroll游标查询

Java客户端发起查询请求,接受请求的node-1成为Coordinate Node(协调者),该node会创建一个priority queue,长度为from + size即1000。

Coordinate Node将请求分发到所有的primary shard或replica shard中,每个shard在本地创建一个同样大小的priority queue,长度也为from + size,用于存储该shard执行查询的结果。

每个shard将各自priority queue的元素返回给Coordinate Node,元素内只包含文档的ID和排序值(如_score),Coordinate Node将合并所有的元素到自己的priority queue中,并完成排序动作,最终根据from、size值对结果进行截取。

补充说明:

哪个node接收客户端的请求,该node就会成为Coordinate Node。

Coordinate Node转发请求时,会根据负载均衡算法分配到同一分片的primary shard或replica shard上,为什么说replica值设置得大一些可以增加系统吞吐量的原理就在这里,Coordinate Node的查询请求负载均衡算法会轮询所有的可用shard,并发场景时就会有更多的硬件资源(CPU、内存,IO)会参与其中,系统整体的吞吐量就能提升。

此查询过程Coordinate Node得到是轻量级的元素信息,只包含文档ID和_score这些信息,这样可以减轻网络负载,因为分页过程中,大部分的数据是会丢弃掉的。

取回阶段

在完成了查询阶段后,此时Coordinate Node已经得到查询的列表,但列表内的元素只有文档ID和_score信息,并无实际的_source内容,取回阶段就是根据文档ID,取到完整的文档对象的过程。如下图所示:

Elasticsearch系列---搜索执行过程及scroll游标查询

Coordinate Node根据from、size信息截取要取回文档的ID,如{"from": 980, "size": 20},则取第981到第1000这20条数据,其余丢弃,from/size为空则默认取前10条,向其他shard发出mget请求。

shard接收到请求后,根据_source参数(可选)加载文档信息,返回给Coordinate Node。

一旦所有的shard都返回了结果,Coordinate Node将结果返回给客户端。

前面几篇有提到deep paging的问题,我们在这里又复习一遍,使用from和size进行分页时,传递信息给Coordinate Node的每个shard,都创建了一个from + size长度的队列,并且Coordinate Node需要对所有传过来的数据进行排序,工作量为number_of_shards * (from + size),然后从里面挑出size数量的文档,如果from值特别大,那么会带来极大的硬件资源浪费,鉴于此原因,强烈建议不要使用深分页。

不过深分页操作很少符合人的行为,翻几页还看不到想要的结果,人的第一反应是换一个搜索条件,只有机器人或爬虫才这么不知疲倦地一直翻页直到服务器崩溃。

preference设置

查询时使用preference参数,可以影响哪些shard可以用来执行搜索操作,6.1.0版本后,许多参数值已声明为弃用,我们挑几个目前还在使用的简单介绍一下:

_only_local:只搜索当前node中的shard

_local:优先搜索当前node中的shard,搜不到再去其他的shard

_prefer_nodes:abc,xyz:优先从指定的abc/xyz节点上搜索,如果两个节点都有存在数据的shard,随机从里面挑一个节点执行搜索

_only_nodes:abc,xyz,...:只在符合通配abc、xyz名称的节点上搜索,如果多个节点都有存在数据的shard,随机从里面挑一个节点执行搜索

_shards:2,3:指定shard进行搜索,这个条件如与其他条件搭配使用,此条件要写在前面,如_shards:2,3|_local

自定义字符串:一般用sessionid或userid

bouncing results问题

假如两个文档有相同的字段值,并且时间戳也一样,如果按时间戳字段来排序,由于请求是在所有可用的shard上轮询的,可能存在一种情况:这两个文档记录在不同的shard之间保存的顺序不相同。结果就是同一个条件的查询,如果执行多次,分配在primary shard得到的是一种顺序,分配在replica shard又是另一个顺序,这个就是所谓的bouncing results问题。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpspyx.html