天天看點

Elasticsearch 緩存深入詳解

2、Elasticsearch 緩存經常被問道的問題彙總

怎樣知道自己的查詢時命中緩存了還是走的磁盤搜尋?

我想每次查詢的時候直接顯示幾個小時以前的資料 而不是隻有實時的,這些是要存到緩存中麼?

看 Elasticsearch API的時候看到 /_cache/clear,這個緩存什麼時候需要清理?有什麼場景需要使用?

以上問題都是實戰業務場景的問題。

3、Elasticsearch 緩存分類

3.1 節點查詢緩存(Node query cache)

filter 過濾查詢的結果緩存在節點查詢緩存中,以便快速查找。

每個節點都有一個所有分片共享的查詢緩存。緩存使用 LRU ( Least Recently Used 緩存淘汰政策)政策,當緩存已滿時,優先清理最近最少使用的查詢結果,以騰出空間存放新結果資料。

使用者無法檢視節點查詢緩存的内容。

3.1.1 節點查詢緩存适用場景

Term 查詢和 filter 查詢。

除  Term 查詢和 filter 查詢之外使用的查詢不符合緩存條件。

3.1.2 節點查詢緩存記憶體上限

預設情況下,節點查詢緩存最多可容納10000個查詢,最多占總堆空間的10%。

為了确定查詢是否符合緩存條件,Elasticsearch 維護查詢曆史記錄以跟蹤事件的發生。

如果一個段至少包含 10000 個文檔,并且該段具有超過一個分片的文檔總數的 3% 的文檔數,則按每個段進行緩存。由于緩存是按段劃分的,是以合并段可使緩存的查詢無效。

3.1.3 節點查詢緩存配置

說一下靜态配置(static)和 動态配置 (dynamic)配置的本質差別:

靜态配置:隻能在配置檔案配置,重新開機後生效。

動态配置:可以通過指令行(更新 setting)配置,配置後無需重新開機即刻生效。

配置1:indices.queries.cache.size

靜态配置,需要在叢集的每個資料節點配置。

含義:控制 filter 緩存的堆記憶體大小。

接受百分比值(例如5%)或精确值(例如 512mb)。

預設:為10%。

配置2:index.queries.cache.enabled

靜态配置,針對每個索引的配置。

含義:控制是否啟用節點查詢緩存。

設定時機:隻能在建立索引或者關閉索引(close)時設定。

可設定:true 或者 false。

預設:true。關閉緩存舉例:

PUT my_index_0003

{

 "settings": {

   "index.queries.cache.enabled": false

 }

}

3.2 分片請求緩存(Shard request cache)

當對一個索引或多個索引運作搜尋請求時,每個涉及的分片都會在本地執行搜尋并将其本地結果傳回到協調節點,協調節點将這些分片級結果合并為一個“全局”結果集。

分片級請求緩存在每個分片上快取區域結果,這使得頻繁使用的搜尋請求幾乎立即傳回結果。分片請求緩存非常适合日志用例場景,在這種情況下,資料不會在舊索引上更新,并且可以将正常聚合保留在高速緩存中以供重用。

預設情況下:

請求緩存将僅緩存 size = 0 的搜尋請求的結果,是以将不緩存hits,但将緩存hits.total,aggregations(聚合)和suggestions。

大多數使用 now 的查詢無法緩存。

3.2.1 分片請求緩存失效

重新整理間隔(refresh_interval)越長,緩存的條目将保持有效的時間越長。如果緩存已滿,将驅逐最近最少使用的緩存。

可以使用 clear_cache API手動使緩存過期,舉例如下:

POST /kimchy,elasticsearch/_cache/clear?request=true

3.2.2 啟停分片請求緩存

設定索引時預設停用緩存

PUT my_index

   "index.requests.cache.enable": false

更新索引,啟用緩存

PUT /my_index/_settings

 "index.requests.cache.enable": true

查詢時,設定分片請求緩存

如下的設定會覆寫索引級别的緩存設定。

GET /my_index/_search?request_cache=true

 "size": 0,

 "aggs": {

   "popular_colors": {

     "terms": {

       "field": "colors"

     }

   }

注意:

第一:如果你的查詢使用結果有不确定的腳本(例如,使用随機函數或引用目前時間),則應将request_cache标志設定為false以禁用該請求的緩存。

第二:即使在索引設定中啟用了請求緩存,也不會緩存大小大于0(size > 0)的請求。要緩存這些請求,您将需要使用 query-string 參數(詳見官方文檔)。

3.2.3 緩存設定

緩存是在節點級别進行管理的,預設最大大小為堆的1%。可以使用以下指令在config / elasticsearch.yml 檔案中進行更改:

indices.requests.cache.size: 2%

此外,您可以使用 index.requests.cache.expire 設定為緩存的結果指定TTL,但是沒有理由這樣做(提供此設定僅出于完整性考慮)。

請記住,重新整理索引後(refreshed),舊的結果将自動失效。

3.2.4 緩存分片請求監控

GET /_stats/request_cache?human

GET /_nodes/stats/indices/request_cache?human

3.3 Field data 緩存

Field data 緩存包含 field data 和 global ordinals,它們均用于支援某些字段類型上的聚合。由于這些都是堆上的資料結構,是以監視緩存的使用非常重要。

field data 咱們之前文章分析過:Elasticsearch 内部資料結構深度解讀

global ordinals 可以簡單了解為:預熱全局序号,全局序号可以了解為:一種資料結構,使用者 keyword 字段的 terms 聚合等用途。

Field data 緩存的建構成本很高,是以預設行為是将緩存加載到記憶體中。預設的緩存大小是無限的,這将導緻緩存高速增長直到達到field data斷路器設定的限制。

如果設定了 field data 緩存大小限制,同樣的,緩存将開始清除緩存中最新最少更新的資料。此設定可以自動避開斷路器限制,但需要根據需要重建緩存。

如果達到 field data 斷路器限制,Elasticsearch 底層将阻止進一步增加緩存大小的請求。在這種情況下,你應該手動清除緩存。

這裡要擴充兩個Field data 斷路器 配置:

參數1:indices.breaker.fielddata.limit

動态參數。

預設值:堆記憶體40%。

參數2:indices.breaker.fielddata.overhead

估計值常數,預設:1.03

3.3.1 Field data 緩存設定

設定參數:indices.fielddata.cache.size。

參數類型:靜态參數。

參數含義:field data 緩存的最大值。

參數舉例:

1)百分比,如:38%,代表:堆記憶體38%。

      2)固定值,如:12 GB。

預設值:無

設定舉例:需要在:elasticsearch.yml 中設定,重新開機後生效,注意手動設定大小要小于斷路器大小或者比例值。

3.3.2 Field data 緩存監控

以下兩種方法可用于監控:Field data 緩存及 斷路器使用情況。

Field data 緩存監控方法 1:

GET /_nodes/stats

Field data 緩存監控方法 2:

GET /_cat/fielddata

4、查詢與清理緩存

4.0 查詢緩存

全局檢視緩存方法

GET _cat/nodes?v&h=id,queryCacheMemory,queryCacheEvictions,requestCacheMemory,requestCacheHitCount,requestCacheMissCount,flushTotal,flushTotalTime

4.1 清理節點查詢緩存

POST /twitter/_cache/clear?query=true

4.2 清理 request 請求緩存

POST /twitter/_cache/clear?request=true    

4.3 清理 field data 緩存

POST /twitter/_cache/clear?fielddata=true

4.4 指定索引清理緩存

POST /kimchy,elasticsearch/_cache/clear

4.5 清理全部的緩存

POST /_cache/clear

5、Elasticsearch 三種緩存應用場景

緩存類型 緩存内容

節點請求緩存 緩存可維護在 filter 上下文中使用的查詢結果。

分片請求緩存 緩存 size = 0 時頻繁使用的查詢的結果,尤其是聚合的結果。

字段請求緩存 (Field data) 用于排序和支援某些字段類型上的聚合。

6、小結

讀到這裡,開頭的問題的答案自然得出。

特将緩存使用注意事項說明如下:

将聚合操作與“正常”查詢處理分開。

原因:避免聚合随着使用者的翻頁(查詢)重新計算。

區分 filter 過濾器 和 match 比對子句。

第一:通用 filter 過濾器具有很高的可緩存性,并且計算迅速;

第二:基于評分的 query 是相比 filter 更為昂貴的查詢,并且難以緩存。

在評分之前,使用可重複使用的過濾器(filters)來縮小結果集的範圍。使用scripted fields進行評分,但不要使用過濾器。

Filters 過濾器或多或少地按順序執行。ES 内部進行了一些查詢重寫,但通常将廉價的過濾器(執行快)放在首位,将較昂貴的過濾器(執行慢)放在第二位。

如果必須按時間戳過濾,請使用粗粒度,以確定查詢值改動小。

參考:

1、官方文檔

2、

https://opster.com/elasticsearch-glossary/elasticsearch-cache/

3、

https://opensourceconnections.com

繼續閱讀