描述
NodeCache也称为QueryCache, 是在Node(机器)级别缓存的, 同一个节点上的多个shards共用的一个Node Cache.
Node Cache是段级别的, 段在进行段合并而销毁的时候, 其对应的NodeCache会失效, 没有warmup.
缓存内容
缓存的是filter query(用在filter context中的query).
Term query不会被缓存.
缓存的一些特殊设置值
具有比较复杂的缓存条件, 受以下因素影响:
LRUQueryCache
- maxSize: 使用LRU策略清空旧缓存时最大保存的query的数量(这里的query与segment无关, 是在IndexSearcher内全局的)
- maxRamBytesUsed: 使用LRU策略清空旧缓存时最大保存的query内存占用bytes(这里的query与segment无关, 是在IndexSearcher内全局的)
- leavesToCache.minSize: 每个segment若要启用缓存则该segment的文档数必须>=minSize.
- leavesToCache.minSizeRatio: 每个segment若要启用缓存则"该segment的文档数/IndexSearcher总文档数"必须>=minSizeRatio.
- skipCacheFactor: 对于BooleanQuery, 首先计算一个leadCost代表用作lead的链表的cost, 然后一个Boolean条件要缓存的话, 需要满足cost/skipCacheFactor>leadCost, 其中cost为需要确定的这个Boolean条件的cost.
UsageTrackingQueryCachingPolicy
- historySize: 追踪的Query使用情况的总Query数量. 注意当追踪的Query数量>historySize时, 这里使用的并不是LRU策略, 而是FIFO策略, 即最先被记录的Query当容量满了以后总是最先被淘汰的.
可配置项
- 给特定的index开启/关闭.
- 设置最大可用内存.
源码
涉及类
代码语言:txt复制IndexSearcher.search ->
IndexSearcher.createWeight ->
IndexSearcher.queryCache= OptOutQueryCache (nested)-> IndicesQueryCache (nested)-> IndicesQueryCache$ElasticsearchLRUQueryCache.
IndexSearcher.queryCachingPolicy=UsageTrackingQueryCachingPolicy.
Q&A
Lucene
- QueryCache是怎样集成到搜索中的?
IndexSearcher会绑定一个LRUQueryCache和一个UsageTrackingQueryCachingPolicy, 在为query生成weight阶段, 如果发现query不需要打分, 就会在生成的weight外套一个CachingWrapperWeight, CachingWrapperWeight相当于原query的一个代理, 会在生成scorer的时候处理缓存的存储和读取.
- BooleanQuery的多个条件如何缓存的?
是分别缓存的, 只要顶层BooleanQuery是不需要分数的, 那么顶层BooleanQuery和其所有子Query都会分别单独缓存.
不过要注意的是在CachingPolicy里有个特殊处理, BooleanQuery的缓存查询数阈值为正常阈值-1, 也就是说如果只反复查询同一个BooleanQuery, 最终只会缓存这个BooleanQuery本身, 其他子query会处于要缓存的阈值.
- LRU的lru算法怎么实现的?
LRUQueryCache.evictIfNecessary()
- Node Cache如何递归实现的多层query的缓存?
通过Weight.scorerSupplier()方法的递归调用实现.
ES
- ES filter context 是如何使用QueryCache的?
被包裹在filter context中的query实际上是被包裹了一个ConstantScoreQuery, 而ConstantScoreQuery在createWeight时会调用被包裹query的createWeight, 调用被包裹query的createWeight时传入的打分模式是ScoreMode.COMPLETE_NO_SCORES, 因此相当于在这里给被包裹query的weight先包裹了一个CachingWrapperWeight, 这样就实现了缓存的应用.
- Solr Filter Cache的存储粒度是shard(某一个index在当前节点的shard), ES Node Cache的存储粒度是什么?
segment.
- ES Node Cache与Solr的Filter Cache的warm up 区别.
Solr Cache处理缓存问题是在一个新searcher被打开后, 当前searcher继续提供服务, 新searcher开始预热它的缓存, 新searcher使用老searcher的缓存重新执行来填充自己的缓存.
ES的Node Cache是以段为单位的, 当添加新段的时候, 老段的缓存不受影响, 当执行段合并的时候, 被销毁的段的NodeCache会直接失效, 没有warmup.
Ref
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-cache.html
ES源码(7.13.0)