解剖 Elasticsearch 集群 - 之三

本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇。在本篇文章中,我们会讨论 Elasticsearch 如何提供准实时搜索以及如何在搜索相关度计算与延迟间权衡。

在之前的文章中,我们讨论了 Elasticsearch 如何应对分布式系统的一些基本挑战。这里我们主要讨论:

  • Elasticsearch 的准实时
  • 为什么深度分页会很危险?
  • 权衡搜索相关度的计算

准实时搜索(Near real-time search)

Elasticsearch 里的修改不是立刻可见,但它确实提供了一个准实时的搜索引擎。如之前文章提到的,将 Lucene 的修改提交到磁盘是一个代价高昂的操作。为了让提交修改到磁盘的时候文档仍然可供搜索,在内存缓冲与磁盘之间有一个文件系统缓存。内存缓冲每秒刷新(默认)同时包含倒排索引的新段会创建与文件系统缓存中。这个段是开放的并可供搜索。

文件系统缓存有文件句柄,可以打开、读取以及关闭文件,不过它是在内存中的。因为默认刷新的间隔是 1 秒,修改并不是立即可见,尽管如此它还是准实时的。因为 translog 是一条对未持久化到磁盘的所有修改的持久化记录,它对 CRUD 操作的准实时方面也有所帮助。对于每次请求,都会在查看相关的段信息之前,先搜索 translog ,所以客户端可以在准实时状态下访问所有发生的修改。

也可以显式地在每次 Create/Update/Delete 操作后刷新索引,让修改对客户端立刻可见,但我们并不推荐这么做,因为这样会创建很多小段导致搜索的性能下降。在 Elasticsearch 索引里一个分片的所有的段都会被搜索,但是读取所有匹配文档或读取处于深度分页里的文档是很危险的。让我们看看为什么会这样。

为什么在分布式搜索中深度分页是十分危险的?

当搜索匹配 Elasticsearch 中的很多文档时,默认情况下,会返回第一页的内容并包括最前的 10 个结果。搜索 API 有参数 fromsize 指定搜索结果的深度。例如,如果想看排名第 5060 的文档,那么参数值应该是 from=50size=10 。每个分片都会接收到搜索请求,它创建一个大小为 from+size 的优先队列满足自身的搜索结果,然后将结果返回到协调节点。

如果想要看排名从 50,000 到 50,010 的结果,那么每个分片就会需要创建大小为 50,010 的优先队列,协调节点就需要在内存中对 number of shards * 50,010 个结果进行排序。由于硬件资源的限制,这种层次的分页可能不大可能,但是这种深度分页需要非常小心,因为它可以轻而易举地弄垮集群。

可以通过 scroll API 获得所有匹配的文档,这和关系型数据库中游标的的行为很像。在 scroll API 中,排序是被禁用的,只要文档与搜索匹配,分片就会返回结果。

如果有大量文档被读取,对评分结果的排序是个代价昂贵的过程。因为 Elasticsearch 是一个分布式系统,为文档计算搜索相关度评分代价很大。让我们看看如果做权衡。

权衡搜索相关度的计算

Elasticsearch 用 tf-idf 来评价搜索的相关度,由于它分布性的本质,计算全局的 idf(倒排文档频率 - inverse document frequency)是十分昂贵的。相反,每个分片计算一个局部的 idf 并为结果分配一个相关度评分,然后只返回改分片内的文档。相似地,所有分片返回结果以及本地 idf 计算出的相关度评分,协调节点会对所有结果进行排序并返回处于最前的文档。这在大多数情况下都是有效的,除非索引根据关键字进行了调整或单个分片没有足够的数据能代表集群的全局分布。

例如,如果搜索 “insight” 这个词,分片内大多数文档都包含词项 “insight” ,与查询匹配的文档可能不会在每个分片中进行正确排名,因为局域 idf 值的变化会很大,搜索结果可能不会那么相关。类似地,如果没有足够的数据,局域 idf 值也会变化很大,搜索结果的相关性也不如期望的那样。真实世界的数据往往是充足的,局域 idf 值会趋同搜索结果的评分也会是公平的。

也有一些方式可以规避局域 idf 评分的影响,但并不推荐在生产环境使用。

  • 一种方式是只为索引使用一个分片,这样局域的 idf 就是全局的 idf ,但这牺牲了并行性和扩展,对巨量索引也不切实际。
  • 另外一种方式是为搜索请求使用参数 dfs_query_then_search (dfs = distributed frequency search) ,它会先为所有分片计算局域 idf ,然后将这些局域的 idf 值为整个索引计算出一个全局的 idf ,返回结果的相关度评分是根据这个全局 idf 计算出来的。不推荐在生产环境使用它,足够的数据就可以保证词频能很好的分布。

在之前的一些文章中,我们查看了 Elasticsearch 的一些基本原理,这对理解和使用它非常重要。在后续的文章中,我会介绍如何使用 Apache Spark 将数据索引到 Elasticsearch。

参考

参考来源:

Anatomy of an Elasticsearch Cluster: Part III

结束

解剖 Elasticsearch 集群 - 之三的更多相关文章

  1. 解剖 Elasticsearch 集群 - 之二

    解剖 Elasticsearch 集群 - 之二 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论 Elasticsearch 是如何处理 3C ...

  2. 解剖 Elasticsearch 集群 - 之一

    解剖 Elasticsearch 集群 - 之一 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论底层的存储模型以及 CRUD(创建.读取.更新 ...

  3. Ubuntu 14.04中Elasticsearch集群配置

    Ubuntu 14.04中Elasticsearch集群配置 前言:本文可用于elasticsearch集群搭建参考.细分为elasticsearch.yml配置和系统配置 达到的目的:各台机器配置成 ...

  4. elasticsearch 集群

    elasticsearch 集群 搭建elasticsearch的集群 现在假设我们有3台es机器,想要把他们搭建成为一个集群 基本配置 每个节点都要进行这样的配置: cluster.name: ba ...

  5. 我的ElasticSearch集群部署总结--大数据搜索引擎你不得不知

    摘要:世上有三类书籍:1.介绍知识,2.阐述理论,3.工具书:世间也存在两类知识:1.技术,2.思想.以下是我在部署ElasticSearch集群时的经验总结,它们大体属于第一类知识“techknow ...

  6. Elasticsearch集群中处理大型日志流的几个常用概念

    之前对于CDN的日志处理模型是从logstash agent==>>redis==>>logstash index==>>elasticsearch==>&g ...

  7. elasticsearch 集群配置

    2015-10-10 09:56 by 轩脉刃, 999 阅读, 1 评论, 收藏, 编辑 elasticsearch 集群 搭建elasticsearch的集群 现在假设我们有3台es机器,想要把他 ...

  8. 翻译【ElasticSearch Server】第一章:开始使用ElasticSearch集群(5)

    数据操作与REST API(Data manipulation with REST API) ElasticSearch REST API可用于各种任务.多亏了它,我们可以管理索引,更改实例参数,检查 ...

  9. Elasticsearch集群搭建

    现有两部机器:192.168.31.86,192.168.31.87   参考以往博文对Elasticsearch进行配置完成:http://www.cnblogs.com/zhongshengzhe ...

随机推荐

  1. GridView的RowCreated与RowDataBound事件区别

    在西门子面试时,项目负责人除了道试题关于RowCreated与RowDataBound事件区别,经过google一下,得出结果: GridView的RowCreated与RowDataBound的一个 ...

  2. centos 安装FTP server详情(转)

    centos 安装FTP server详情 分类: linux 2013-12-27 16:45 227人阅读 评论(0) 收藏 举报 我们这里以安装vsftpd 服务器端为例子: 1.进入到cent ...

  3. 执行 apt-get -f install 提示错误

    执行 apt-get -f install 提示错误 分类: Linux 2015-01-24 21:26 554人阅读 评论(0) 收藏 举报 1. 问题: usloft1359:~# rvm in ...

  4. PS2鼠标+LCD12864实验(调试未成功)

    此试验我一人调试许久都未成功,但发送ff时,读出来的数据确是对的,一开始让我窃喜,但发送f4时,读出来的数据确是错的,哎让苦恼啊,能力有限,只能先暂时就这样吧,那位什么还要贴出来呢,有两个原因: 1. ...

  5. zookeeper常用sehll命令

    ZooKeeper服务命令: 在准备好相应的配置之后,可以直接通过zkServer.sh 这个脚本进行服务的相关操作 1. 启动ZK服务:       sh bin/zkServer.sh start ...

  6. margin 如何居中

    #id { margin-left: auto; margin-right: auto;width:100px}一定得增加width:100px这一个属性.margin:[N]px auto;widt ...

  7. CodeForces 662D International Olympiad

    写出前几个找规律,然后直接输出. #include<cstdio> #include<cstring> #include<cmath> #include<al ...

  8. PHP Markdown 解析器Parsedown

    PHP Markdown 解析器Parsedown http://parsedown.org/demo

  9. ubuntu中mysql修改编码utf8

    摘要:Ubuntu Server 服务器下使用apt-get 命令安装的mysql,默认不是utf8.在这里记录一下如何将编码修改成utf8. 办法解决: 1.查看mysql编码 show varia ...

  10. 关于NOMINMAX这个预处理宏

    标准库在<algorithm>头中定义了两个模板函数std::min() 和 std::max().通常用它可以计算某个值对的最小值和最大值.可惜在 Visual C++ 无法使用它们,因 ...