Elasticsearch分布式检索

前言

本篇笔记主要简单记录一下Elasticsearch在分布式环境中是怎么执行的?(Elasticserch权威指南读书笔记)

查询阶段

在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。每个分片在本地执行搜索并构建一个匹配文档的优先队列。

这里使用官方的一张图来说明查询过程:
查询过程图

  • 客户端向Elasticsearch集群发起一个查询请求,请求发送到node3上面。
  • node3接收到请求,创建一个大小为from+size(偏移量+请求数量)的空优先队列。
  • node3根据Elasticsearch的路由算法,得到每一个主分片或者副分片的位置,将查询请求转发到索引的每个主分片或副本分片中。
  • 每个分片在本地执行查询并添加结果到大小为from+size的本地有序优先队列中,返回给node3。
  • node3合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。

搜索选项

在搜索时,有几个查询参数可以影响到搜索过程。

偏好

偏好这个参数 preference 允许 用来控制由哪些分片或节点来处理搜索请求,它可以避免 bouncing results 问题。

Bouncing Results问题:有两个文档有同样值的时间戳字段,搜索结果用 timestamp 字段来排序。由于搜索请求是在所有有效的分片副本间轮询的,那就有可能发生主分片处理请求时,这两个文档是一种顺序, 而副本分片处理请求时又是另一种顺序。简单的说就是每次用户刷新页面,搜索结果表现是不同的顺序。

时限

我们可以使用参数timeout告诉分片允许处理数据的最大时间。如果没有足够的时间处理所有数据,这个分片的结果可以是部分的,甚至是空数据。而搜索的返回结果会用属性 timed_out 标明分片是否返回的是部分结果:

   ...
    "timed_out":     true,  
    ...

注意:很可能查询会超过设定的超时时间,主要是因为下面两个问题:

  • 超时检查是基于每文档做的。 但是某些查询类型有大量的工作在文档评估之前需要完成。 这种 "setup" 阶段并不考虑超时设置,所以太长的建立时间会导致超过超时时间的整体延迟。
  • 时间检查是基于每个文档的,一次长时间查询在单个文档上执行并且在下个文档被评估之前不会超时。这也意味着差的脚本(比如带无限循环的脚本)将会永远执行下去。
路由

我们可以通过配置参数routing,来指定搜索的相关分片(比如属于某个用户的文档被存储在某个分片上。在搜索的时候,不用搜索索引的所有分片,而是通过指定几个routing值来限定只搜索几个相关的分片):

GET /_search?routing=user_1,user2
搜索类型

我们可以通过设置search_type参数,来设置搜索的类型,Elasticsearch默认的搜索类型为query_then_fetch。

GET /_search?search_type=dfs_query_then_fetch

每种搜索类型的不同,暂时不做了解。

游标查询Scroll

scroll查询主要用来对Elasticsearch有效地执行大批量的文档查询,而又不用付出深度分页那种代价。

深度分页的代价根源是结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。 游标查询用字段 _doc 来排序。 这个指令让 Elasticsearch 仅仅从还有结果的分片返回下一批结果。

启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间。 游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。

GET /old_index/_search?scroll=1m 
{
    "query": { "match_all": {}},
    "sort" : ["_doc"], 
    "size":  1000
}

查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串 。 现在我们能传递字段 _scroll_id 到 _search/scroll 查询接口获取下一批结果:

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs="
}
注意:游标查询每次返回一个新字段 _scroll_id。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段 _scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。
作者:红雨
出处:https://www.cnblogs.com/52why
微信公众号: 红雨python
原文地址:https://www.cnblogs.com/52why/p/14436080.html