天天看點

ES Cache: Node Cache

描述

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當容量滿了以後總是最先被淘汰的.

可配置項

  1. 給特定的index開啟/關閉.
  2. 設定最大可用記憶體.

源碼

涉及類

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)