Elasticsearch-07-ES中的缓存

3.7 ES中的缓存

Elasticsearch在运行过程中会使用到各种各样的缓存,如Query cache、Request cache、page cache、fielddata。这里主要讨论Query cache 和 Request cache

3.7.1 Shard Request Cache

1)简介

顾名思义,这是分片级别的缓存。缓存采用LRU机制,key包含shard、indexreader、查询请求的信息,value是查询结果序列化之后的数据。

由于客户端查询请求会被序列化之后作为key的一部分,所以有可能同样的查询、json内容顺序不同等变化都会导致无法命中缓存

由于这是分片级别的缓存,所以当新的段写入到分片后,原有的缓存将会失效

2)缓存策略

不是所有的查询请求都会被缓存。在IndicesService#canCache中定义了哪些请求时不能被缓存的。不被缓存的情况有

  • 使用了scroll滚动查询
  • 查询类型不是QUERY_THEN_FETCH
  • 带有分析的查询,设置了profile属性
  • 设置不需要缓存
  • 范围查询中带有now的。这种查询是毫秒级别的,缓存没有意义
3)配置项与监控api
  • indices.requests.cache.size:设置缓存占用堆空间的大小,默认是1%

  • index.requests.cache.enable:缓存开关

  • GET /_nodes/stats/indices/request_cache?human

3.7.2 Node Query Cache

1)简介

相比于Shard Request Cache这种分片级别的缓存,Node Query Cache就只缓存filter中过滤的结果。所以,Node Query Cache又被称为Filter Cache。

Filter查询和普通查询最主要的区别就是不会计算评分

它可以缓存不同查询之间使用到重复数据的部分。比如说张三查询了近一个月内火腿肠的销量,李四查询了近一个月内火腿肠不合格的数量。这两次查询的共同之处是时间范围都是一个月内。而Node Query Cache会在第一次查询时对近一个月内的数据打上标记,在下一次查询的时候只去搜索这些打过标记的数据。

这种缓存是Lucene中实现的,ES主要进行的是策略控制。

2)工作原理

Node Query Cache使用位图这种数据结构来对数据进行标记。首先创建一个大小为maxDoc(文档数量)的位图:FixedBitSet。然后在遍历过程中对命中的文档在位图对应位置做标记。例如,[1,2,7]位置的文档命中了查询条件,那么对应的位图则为[1,1,0,0,0,0,1]。当一个查询中有多个filter条件时,只需要做位运算即可快速准确的找到命中的文档

3)缓存策略

ES使用UsageTrackingQueryCachingPolicy作为默认的缓存策略。这个策略的主要关注点是:

  • 是不是特定类型的查询。如term query(精确查询)、MatchAllDocsQuery、MatchNoDocsQuery。以及子查询为空的BooleanQuery、DisjunctionMaxQuery
  • 某条 query 的访问频率大于等于特定阈值之后,该 query结果才会被缓存。对于访问频率,主要分为2类,一类是访问2次就会被缓存,包括: MultiTermQuery、MultiTermQueryConstantScoreWrapper、TermInSetQuery、PointQuery 在 isCostly方法中定义。其余类型的查询访问5次会被缓存。

如何统计某个query的频率?

Lucene中维护了一个长度为256的环形buffer。每个查询在被hash之后保存进去。因此,上面的频率可以理解为最近256次查询中出现的频率

4)配置项与监控
  • indices.queries.cache.count,缓存查询的数量,默认是1w
  • indices.queries.cache.size,缓存占堆内存的大小,默认是10%
  • GET /_nodes/stats/indices/query_cache?human
posted @ 2021-09-26 10:35  PrimaBruceXu  阅读(2107)  评论(0编辑  收藏  举报