目录

Elasticsearch缓存的理解

概述

ES 的缓存允许在内存中存储之前使用过的数据,并根据需要适时地重用。当然不可能去缓存所有的数据,因为数据容量总是大于内存容量,另外内存的构建代价也非常高。

过滤器缓存

这是 ES 中最简单的缓存,过滤器缓存是负责缓存查询中使用过的过滤器执行的结果。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "eusr": {
              "value": "testvj51299432"
            }
          }
        }
      ]
    }
  },
  "size": 100
}

在以上查询中,以后每个查询中存在相同的过滤器的话,都会重用其结果,节省了 I/O 和 CPU 资源。

过滤器缓存的种类

ES 中有两种类型的过滤器缓存,索引级和节点级的,可供选择。因为我们不能总是预知给定索引会分配到哪里,于是无法预测内存的使用,所以不建议使用索引级别的过滤器缓存。

节点级的过滤器缓存配置

这是默认的缓存类型,应用于分配到给定节点上的所有分片,可以通过设定 index.cache.filter.type 的属性为 node,或者不设置这个属性(默认)来启动。ES 也允许我们使用 indices.cache.filter.size 属性来配置这个缓存的大小,既可以为百分数,也可以是具体数值如1024MB。如果是百分数的话,ES 会根据当前节点的最大堆内存的百分比来计算内存的使用。节点级过滤器缓存是 LRU 类型的(最近最少使用)缓存,意味着为了给新纪录腾出空间,在删除缓存记录时,使用次数最少的那些会被删除。

字段数据缓存

当查询非倒排数据操作时,ES 加载相关字段的全部数据进入内存中,这样就能快速地基于文档访问这些值。这种缓存可以被 ES 用于切面计算、聚合、脚本计算、基于字段值的排序等场景。 当首次执行非倒排数据相关操作时,所有字段数据会加载到内存,默认情况下这些给定的字段的数据不会被移除,因此可以快速访问索引文档中给定字段的值。从硬件角度看,构建字段数据缓存代价通常非常高,需要消耗大量的 I/O 和 CPU 资源。

字段数据与文档值

doc_values 的性能已经跟字段数据缓存非常接近了,如果在某些场景下需要大量使用字段数据缓存,不妨尝试文档值,仅需要添加 doc_values属性。

1
"bi": {"type": "keyword", "doc_values": true}

节点级字段数据缓存

index.fielddata.cache.size 这个属性指定了字段数据缓存的容量大小,既可以是20%也可以是10GB。此外 index.fielddata.cache.expire 指定字段数据缓存助攻记录的过期时间,默认为-1,表示永不过期,如果我们希望设置字段数据缓存过期时长,可以设最大的空闲时间。

过滤

ES 允许选择哪些字段值加载到字段数据缓存中,在一些切面计算、聚合计算的场景中非常有用。

添加字段数据过滤信息

为了引入字段数据缓存过滤信息,需要在映射文件的字段定义部分添加一个额外的对象,fielddata对象及其子对象 filter

1
"bi": {"type": "keyword", "filterdata": {"filter": {...}}

基于词频过滤

允许只加载那些频率高于限值等的词项。

1
"bi": {"type": "keyword", "filterdata": {"filter": {"frequency":{}}}

索引级字段数据缓存配置

与索引级过滤器类似,我们也可以使用索引级别的字段数据缓存,但是因为同样的原因,是不建议使用的。

过滤

ES 允许我们选择将哪些字段值加载到字段数据缓存中。这在一些基于字段做数据排序或切面计算或聚合计算的时候很适合。ES 支持3种类型的字段数据过滤:基于词频,基于正则表达式,或基于两者的组合。

查询分片缓存

ES 引入了一种新的缓存(查询分片缓存),可以帮助提高查询性能。其原理是为每个分片缓存本地查询结果。当 ES 执行一个查询的时候,查询会被发送给所有相关的分片,然后在每个分片上执行查询。然后查询结果会被发送至接受查询的节点进行合并。而分片缓存是分片级的局部查询结果。 通过在索引设置 index.cache.query.enable 属性置为 true,就可以开启查询分片缓存,也可以通过 query_cache=true 的 URI 参数来实现。查询分片的一大好处是,它会自动失效及更新,当分片内容改变的时候,ES 会自动更新缓存内容,因此缓存或未缓存查询的结果都是一样的。 通过设置 indices.cache.query.size 来调整百分比。也可以设置 indices.cache.query.expire 属性来实现。

清除缓存

有时候清除缓存是很重要的,ES 允许我们使用 _cache REST 端点来清除缓存。可以选择清除单一索引有或者特定的索引缓存。

参考资料

  1. 《深入理解Elasticsearch》
  2. 《Elasticsearch技术解析与实战》
警告
本文最后更新于 2017年2月1日,文中内容可能已过时,请谨慎参考。