query phase
假设我们有一个index里面的数据分布在3个primary shard上(对应的replica也有),现在总共有7个shard,我们现在要搜索这个index中的数据的第10000条到10010条.如图所示
请求发送给某一个shard时,这个shard就是coordinate node, coordinate node会构建一个 priority queue,队列长度是查询时的from和size的和,默认是0 + 10 = 10;
我们要查询的是10000-10010条数据,所以请求的from = 9999,size = 10,这个时候coordinate node会在它本地建立一个长度是 9999 + 10 = 10009 的 priority queue, 然后coordinate node将请求打到其他的shard上去
接收到请求的每个shard,也会在本地建立一个 from + size大小的priority queue,每个shard将自己下标是0 - 10009的数据放到这个队列中, 也就是10010条数据,返回给coordinate node.
coordinate node 将返回的所有数据进行合并,合并成一份from * size大小的priority queue,全局排序后,放到自己队列中去
最后在自己的队列中取出当前要获取的那一页的数据.
这里也可以看出我们之前提到过的deep paging问题,就是说,from * size分页太深,那么每个shard都要返回大量的数据给coordinate node,消耗大量的带宽,内存, CPU
fetch phase
在上面的query phase的工作处理完成之后,coordinate node 在priority queue里面找到了需要的数据, 但是其实这个队列时存的document的id, 这个时候,coordinate node就发送mget请求(批量查询)到所有shard上去获取对应的document
然后各个shard将document返回给coordinate node, coordinate node将合并后的document结果返回给客户端
bouncing results问题
比如说有两个document,field值相同;但是分布在不同的shard上面,在不同的shard上可能排序也不相同, 每次请求轮询打到不同的shard上去,页面上看到的搜索结果的排序可能都不一样, 这就是 bouncing results,也就是跳跃的结果.
preference
preference 决定了哪些shard会执行搜索请求.
bouncing results问题解决
将preference设置为一个字符串,比如说user_id,让每个user每次搜索的时候,都使用同一个shard去执行,就不会看到bouncing results了