ElasticSearch的緩存清除策略

前面說起了字段過濾緩存,那麼與之相反的清楚緩存策略
單一索引緩存,多索引緩存和所有緩存的清理正則表達式

1.清空所有緩存
curl localhost:9200/_cache/clear?pretty
{
  "_shards" : {
    "total" : 72,
    "successful" : 72,
    "failed" : 0
  }
}數據庫

2.清除單一索引緩存
curl localhost:9200/index/_cache/clear?pretty
{
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  }
}json

3.清除多索引緩存
curl localhost:9200/index1,index2,index3/_cache/clear?pretty
{
  "_shards" : {
    "total" : 12,
    "successful" : 12,
    "failed" : 0
  }
}
固然了清楚緩存時也能夠添加參數使之清楚對用的緩存並不是全部的
filter:此類緩存能夠設置filter參數爲true來清理,相反的不須要清楚此類緩存那麼能夠設置參數爲false來保留此類緩存
field_data:此類緩存能夠設置filter參數爲true來清理,相反的不須要清楚此類緩存那麼能夠設置參數爲false來保留此類緩存
bloom:此類緩存能夠設置filter參數爲true來清理(若是某種倒排索引格式中引用了bloom filter則可能使用此類緩存),相反的不須要清楚此類緩存那麼能夠設置參數爲false來保留此類緩存
fields:清楚字段相關的緩存,能夠爲單個或者多個字段,多個字段的時候用逗號隔開(英文)緩存

上述參數使用格式(可使用一個或者多個參數)
curl localhost:9200/index/_cache/clear?pretty&filter=false&field_data=true&bloom=false&fields=tag,name數據結構

 

 

Elasticsearch 三種緩存介紹:Query Cache、Request Cache、Fielddata Cache

1、Query Cache

Query Cache也稱爲Filter Cache,顧名思義它的做用就是對一個查詢中包含的過濾器執行結果進行緩存。app

好比咱們經常使用的term,terms,range過濾器都會在知足某種條件後被緩存,注意,這裏的bool過濾器是不會被緩存的,但bool過濾器包含的子query clause會被緩存,咱們能夠用下面的命令來查詢Query Cache的狀況。dom

http://192.168.0.109:9200/_stats/query_cache?pretty&human

舉個栗子,看下面的查詢curl

{
  "from": 0,
  "size": 5,
  "query": {
    "bool": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "productID": "JODL-X-1937-#pV7"
              }
            },
            {
              "range": {
                "price": {
                  "from": 20,
                  "to": null,
                  "include_lower": true,
                  "include_upper": true
                }
              }
            }
          ]
        }
      }
    }
  }
}

上面有兩個過濾器一個Term過濾器用來過濾productID爲「JODL-X-1937-#pV7」 的產品,一個range過濾器用來過濾價格在20以上的產品,在這個例子中這兩個過濾器執行的結果會分別做爲一個BitSet(位圖)緩存,返回的查詢結果則是這兩個位圖交集。elasticsearch

上面提到Filter Cache只會在知足某種條件下才會被緩存,至因而哪些條件這裏就不介紹了,想了解的童鞋戳下面連接。函數

關於Filter執行流程及緩存原理 ,請參看此文:《Elasticsearch2.X Filter執行流程及緩存原理》

2、Request Cache

當一個查詢發送到ES集羣的某個節點上時,這個節點會把該查詢擴散到其餘節點並在相應分片上執行,咱們姑且把在分片上執行的結果叫「本地結果集「,這些本地結果集最終會聚集到最初請求到達的那個協調節點,這些「分片級」的結果集會合併成「全局」結果集返回給調用端。

Request Cache模塊就是爲了緩存這些「分片級」的本地結果集,可是目前只會緩存查詢中參數size=0的請求,因此就不會緩存hits 而是緩存 hits.total,aggregations和suggestions

緩存失效

Request Cache是很是智能的,它可以保證和在近實時搜索中的非緩存查詢結果一致。這句話讀起來很難懂,簡單解釋下。

咱們都知道ES是一個「near real-time」(近實時)搜索引擎,爲何是近實時搜索呢,那是由於當咱們向ES發送一個索引文檔請求到這個文檔變成Searchable(可搜索)默認的時間是1秒,咱們能夠經過index.refresh_interval參數來設置刷新時間間隔,也就是說咱們在執行一個搜索請求時實際上數據是有延遲的。回到剛纔的問題,剛纔那句話其實指的就是:ES能保證在使用Request Cache的狀況下的搜索結果和不使用Request Cache的近實時搜索結果相同,那ES是如何保證二者結果相同的呢?繼續……

Request Cache緩存失效是自動的,當索引refresh時就會失效,也就是說在默認狀況下Request Cache是每1秒鐘失效一次(注意:分片在這段時間內確實有改變纔會失效)。也就是說當一個文檔被索引到該文檔變成Searchable以前的這段時間內,不論是否有請求命中緩存該文檔都不會被返回,正是是由於如此ES才能保證在使用Request Cache的狀況下執行的搜索和在非緩存近實時搜索的結果一致。

若是咱們把索引刷新時間設置得越長那麼緩存失效的時間越長,若是緩存被寫滿將採用LRU策略清除。固然咱們也能夠手動設置參數indices.request.cache.expire指定失效時間,可是基本上咱們不必去這樣作,由於緩存在每次索引refresh時都會自動失效。

下面的命令能夠手動清除緩存

curl -XPOST 'localhost:9200/kimchy,elasticsearch/_cache/clear?request_cache=true'

緩存使用

在默認狀況下Request Cache是關閉的,咱們須要手動開啓

curl -XPUT localhost:9200/my_index/_settings -d'  
{ "index.requests.cache.enable": true }  
'

開啓緩存後,咱們須要在那些須要緩存的搜索請求上加上request_cache=true這個參數才能使咱們的查詢請求被緩存,好比:

curl 'localhost:9200/my_index/_search?request_cache=true' -d'  
{  
  "size": 0,  
  "aggs": {  
    "popular_colors": {  
      "terms": {  
        "field": "colors"  
      }  
    }  
  }  
}'

注意1:上面的參數size:0很是重要必須強制指定才能被緩存,不然請求是不會緩存的。

注意2(重要):在使用script執行查詢時必定要指定request_cache=false,由於腳本的執行結果是不肯定的(好比使用random函數或使用了當前時間做爲參數),這種狀況下應該避免使用緩存

緩存的Cache Key

對於Request Cache來講,它的Cache Key就是整個查詢的DSL語句,因此若是要命中緩存查詢生成的DSL必定要同樣,這裏的同樣是指DSL這個字符串同樣。只要有一個字符或者子查詢的順序變化都不會命中緩存。

經過下面的參數咱們能夠設置緩存的大小,默認狀況下是JVM堆的1%大小,固然咱們也能夠手動設置在elasticsearch.yml文件裏

indices.requests.cache.size: 1%  

Request Cache總結:

  1. Request Cache是一個「分片級」的緩存
  2. Request Cache是一個面向請求的緩存,緩存的key是查詢DSL字符串
  3. Request Cache默認沒有開啓,須要手動開啓,且要緩存生效須要在請求參數上加上request_cache=true並把size設置爲0
  4. 緩存是自動失效的,失效時間就是索引的refresh時間(index.refresh_interval),在分片有改變的狀況下默認是1秒失效一次
  5. 緩存的默認大小是JVM堆內存的1%,能夠經過參數indices.request.cache.expire 手動設置

3、Fielddata

一談到Fielddata咱們不得不提到doc_values,這二者的做用都是同樣:可以讓咱們在inverted index(倒排索引)的基礎之上作aggregation、sort或者在查詢中經過script訪問doc屬性,這裏咱們不討論doc_values,主要講下Fielddata,doc values相關知識請戳:http://blog.csdn.net/chennanymy/article/details/52555055

想必你們都知道倒排索引這種結構,若是咱們僅僅依靠倒排是很難在查詢中作到排序和統計的,由於它並非像關係型數據庫那樣採用「列式存儲」,而是基於一個「詞」到「文檔」的倒排。

Fielddata是專門針對分詞的字段在query-time(查詢期間)的數據結構的緩存。當咱們第一次在一個分詞的字段上執行聚合、排序或經過腳本訪問的時候就會觸發該字段Fielddata Cache的加載,這種緩存是「segment」級別的,當有新的segment打開時舊的緩存不會從新加載,而是直接把新的segement對應的Fielddata Cache加載到內存。

加載Fielddata Cache是一個很是昂貴的操做,一旦Fielddata被加載到內存,那麼在該Fielddata Cache對應的Segement生命週期範圍內都會駐留在內存中。也就是說當段合併時會觸發合併後更大段的Fielddata Cache加載。

Fielddata會消耗大部分的JVM堆內存,特別是當加載「高基數」的分詞字段時(那些分詞後存在大量不一樣詞的字段),針對這種字段的聚合排序實際上是很是沒有意義的,咱們更多的要去考慮是否能用not_analyzed代替(這樣就可使用doc_values實現聚合、排序)。

默認狀況下Fielddate Cache是默認開啓的,咱們能夠經過下面的設置來關閉,關閉後就沒法對分詞字段執行聚合、排序操做了。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "text": {
          "type": "string",
          "fielddata": {
            "format": "disabled" 
          }
        }
      }
    }
  }
}

在ES1.X裏面除了string類型其餘類型也是使用Fieldata的,在ES2.X中除了分詞的String類型字段,其餘類型都使用doc_values。

Fielddata的加載方式有3種:

1.lazy: 懶加載是默認的加載方式,當第一次使用時加載

2.eager:預加載模式是當一個新的索引段變成Searchable以前會被加載

3.eager_global_ordinals:全局序數預加載模式,這種方式能生成一份全局序數表,可下降內存使用。

以下設置爲eager_global_ordinals

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "text": {
          "type": "string",
           "fielddata": {
            "loading": "eager_global_ordinals" 
          }
        }
      }
    }
  }
}

Fielddata也可指定知足某些條件的term才被加載進內存

1.經過詞頻加載

PUT my_index  
{  
  "mappings": {  
    "my_type": {  
      "properties": {  
        "tag": {  
          "type": "string",  
          "fielddata": {  
            "filter": {  
              "frequency": {  
                "min": 0.001,  
                "max": 0.1,  
                "min_segment_size": 500  
              }  
            }  
          }  
        }  
      }  
    }  
  }  
}

上面的設置表示詞頻在0.001到0.1之間的且段持有的文檔數在500以上的term會被加載到內存。

2.經過正則表達式加載

PUT my_index  
{  
  "mappings": {  
    "my_type": {  
      "properties": {  
        "tweet": {  
          "type": "string",  
          "analyzer": "whitespace",  
          "fielddata": {  
            "filter": {  
              "regex": {  
                "pattern": "^#.*"  
              }  
            }  
          }  
        }  
      }  
    }  
  }  
}

上面的設置表示只有知足pattern的詞纔會被加載到內存。

Fielddata Cache設置

1.indices.fielddata.cache.size:此參數設置緩存大小(默認是不限制)。可設置百分數如30%,或者數字12GB

2.indices.breaker.fielddata.limit:此參數設置Fielddata斷路器限制大小(公式:預計算內存 + 現有內存 <= 斷路器設置內存限制),默認是60%JVM堆內存,當查詢嘗試加載更多數據到內存時會拋異常(以此來阻止JVM OOM發生)

3.indices.breaker.fielddata.overhead:一個常數表示內存預估值係數,默認1.03,好比預計算加載100M數據,那麼100*1.03=103M會用103M做爲參數計算是否超過斷路器設置的最大值。

相關文章
相關標籤/搜索