白话Elasticsearch52-深入聚合数据分析之fielddata内存控制、circuit breaker短路器、fielddata filter、预加载机制以及序号标记预加载
文章目錄
- 概述
- 官網(wǎng)
- fielddata核心原理
- fielddata內(nèi)存限制
- 監(jiān)控fielddata內(nèi)存使用
- circuit breaker
- fielddata filter的細粒度內(nèi)存加載控制
- fielddata預加載機制以及序號標記預加載
- fielddata預加載 eager
- 序號標記預加載 eager_global_ordinals
概述
繼續(xù)跟中華石杉老師學習ES,第52篇
課程地址: https://www.roncoo.com/view/55
官網(wǎng)
中文指南(2.x):戳這里
fielddata核心原理
fielddata加載到內(nèi)存的過程是lazy加載的,對一個analzyed field執(zhí)行聚合時,才會加載,而且是field-level加載的.
一個index的一個field,所有doc都會被加載,而不是少數(shù)doc,不是index-time創(chuàng)建,是query-time創(chuàng)建
fielddata內(nèi)存限制
indices.fielddata.cache.size: 20%,超出限制,清除內(nèi)存已有fielddata數(shù)據(jù)
fielddata占用的內(nèi)存超出了這個比例的限制,那么就清除掉內(nèi)存中已有的fielddata數(shù)據(jù).
默認無限制,限制內(nèi)存使用,但是會導致頻繁evict和reload,大量IO性能損耗,以及內(nèi)存碎片和gc
查詢
GET _cat/nodes?v&h=id,ip,port,r,ramPercent,ramCurrent,heapMax,heapCurrent,fielddataMemory,queryCacheMemory,requestCacheMemory,segmentsMemoryindices.fielddata.cache.size 控制為 fielddata 分配的堆空間大小。 當你發(fā)起一個查詢,分析字符串的聚合將會被加載到 fielddata,如果這些字符串之前沒有被加載過。如果結(jié)果中 fielddata 大小超過了指定 大小 ,其他的值將會被回收從而獲得空間。
默認情況下,設置都是 unbounded ,Elasticsearch 永遠都不會從 fielddata 中回收數(shù)據(jù)。
這個默認設置是刻意選擇的:fielddata 不是臨時緩存。它是駐留內(nèi)存里的數(shù)據(jù)結(jié)構,必須可以快速執(zhí)行訪問,而且構建它的代價十分高昂。如果每個請求都重載數(shù)據(jù),性能會十分糟糕。
設想我們正在對日志進行索引,每天使用一個新的索引。通常我們只對過去一兩天的數(shù)據(jù)感興趣,盡管我們會保留老的索引,但我們很少需要查詢它們。不過如果采用默認設置,舊索引的 fielddata 永遠不會從緩存中回收! fieldata 會保持增長直到 fielddata 發(fā)生斷熔(請參閱 斷路器),這樣我們就無法載入更多的 fielddata。
這個時候,我們被困在了死胡同。但我們?nèi)匀豢梢栽L問舊索引中的 fielddata,也無法加載任何新的值。相反,我們應該回收舊的數(shù)據(jù),并為新值獲得更多空間。
為了防止發(fā)生這樣的事情,可以通過在 config/elasticsearch.yml 文件中增加配置為 fielddata 設置一個上限:
indices.fielddata.cache.size: 20%可以設置堆大小的百分比,也可以是某個值,例如: 5gb 。
有了這個設置,最久未使用(LRU)的 fielddata 會被回收為新數(shù)據(jù)騰出空間。
在 Fielddata的大小 中,我們提過關于給 fielddata 的大小加一個限制,從而確保舊的無用 fielddata 被回收的方法。 indices.fielddata.cache.size 和 indices.breaker.fielddata.limit 之間的關系非常重要。
如果斷路器的限制低于緩存大小,沒有數(shù)據(jù)會被回收。為了能正常工作,斷路器的限制 必須 要比緩存大小要高
監(jiān)控fielddata內(nèi)存使用
GET /_stats/fielddata?fields=* GET /_nodes/stats/indices/fielddata?fields=* GET /_nodes/stats/indices/fielddata?level=indices&fields=*circuit breaker
如果一次query load的feilddata超過總內(nèi)存,就會oom --> 內(nèi)存溢出
circuit breaker會估算query要加載的fielddata大小,如果超出總內(nèi)存,就短路,query直接失敗
indices.breaker.fielddata.limit:fielddata的內(nèi)存限制,默認60% indices.breaker.request.limit:執(zhí)行聚合的內(nèi)存限制,默認40% indices.breaker.total.limit:綜合上面兩個,限制在70%以內(nèi)fielddata filter的細粒度內(nèi)存加載控制
POST /test_index/_mapping/my_type {"properties": {"my_field": {"type": "text","fielddata": { "filter": {"frequency": { "min": 0.01, "min_segment_size": 500 }}}}} }-
min:僅僅加載至少在1%的doc中出現(xiàn)過的term對應的fielddata
比如說某個值,hello,總共有1000個doc,hello必須在10個doc中出現(xiàn),那么這個hello對應的fielddata才會加載到內(nèi)存中來
-
min_segment_size:少于500 doc的segment不加載fielddata
加載fielddata的時候,也是按照segment去進行加載的,某個segment里面的doc數(shù)量少于500個,那么這個segment的fielddata就不加載
這個fielddata filter一般不會去設置它,了解就好。
fielddata預加載機制以及序號標記預加載
如果真的要對分詞的field執(zhí)行聚合,那么每次都在query-time現(xiàn)場生產(chǎn)fielddata并加載到內(nèi)存中來,速度可能會比較慢,是不是可以預先生成加載fielddata到內(nèi)存中來???
fielddata預加載 eager
POST /test_index/_mapping/test_type {"properties": {"test_field": {"type": "string","fielddata": {"loading" : "eager" }}} }query-time的fielddata生成和加載到內(nèi)存,變?yōu)閕ndex-time,建立倒排索引的時候,會同步生成fielddata并且加載到內(nèi)存中來,這樣的話,對分詞field的聚合性能當然會大幅度增強.
序號標記預加載 eager_global_ordinals
global ordinal原理解釋
doc1: status1
doc2: status2
doc3: status2
doc4: status1
有很多重復值的情況,會進行global ordinal標記
status1 --> 0
status2 --> 1
doc1: 0
doc2: 1
doc3: 1
doc4: 0
建立的fielddata也會是這個樣子的,這樣的好處就是減少重復字符串的出現(xiàn)的次數(shù),減少內(nèi)存的消耗
POST /test_index/_mapping/test_type {"properties": {"test_field": {"type": "string","fielddata": {"loading" : "eager_global_ordinals" }}} }總結(jié)
以上是生活随笔為你收集整理的白话Elasticsearch52-深入聚合数据分析之fielddata内存控制、circuit breaker短路器、fielddata filter、预加载机制以及序号标记预加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 白话Elasticsearch51-深入
- 下一篇: 白话Elasticsearch53-深入