On Heap&&Off Heap
Elasticsearch內存分爲on heap以及off heap兩部分。Elasticsearch能控制的是On Heap內存部分,這部分由JVM管理;Off Heap由Lucene管理,負責緩存倒排索引數據空間(Segment Memory)。
On Heap
- Indexing Buffer 索引寫入緩衝區,用於存儲新寫入的文檔,當其被填滿時,緩衝區中的文檔被寫入磁盤中的 segments 中。節點上所有 shard 共享。這部分空間是可以通過GC被反覆利用的。
緩衝區默認大小:indices.memory.index_buffer_size: 10%
如果緩衝區大小設置了百分百則indices.memory.min_index_buffer_size
用於這是最小值,默認爲 48mb。indices.memory.max_index_buffer_size
用於最大大小,無默認值。 - Node Query Cache (node級別的filter過濾器結果緩存),每個節點有一個,被所有 shard 共享,filter query查詢結果要麼是 yes 要麼是no,不涉及 scores 的計算。使用LRU淘汰策略,內存無法被GC。
集羣中每個節點都要配置,默認爲:indices.queries.cache.size:10%
可以通過配置關閉該緩存(如果能接受巨差的性能的話)
"settings": { "index.queries.cache.enable": false }
- Shard Request Cache (shard級別的query result緩存)每個shard一個,默認情況下該緩存只緩存request的結果size爲0的查詢。所以該緩存不會緩存hits,但卻會緩存 hits.total, aggregations 和 suggestions。可以通過Clear cache API清除緩存,但是這個基本上就是飲鴆止渴,很快又會填滿。如果實在不想用,可以使用下面配置禁止該緩存:
"settings": { "index.requests.cache.enable": false }
該緩存使用LRU淘汰策略,內存無法被GC。默認最大爲:
indices.requests.cache.size:1%
- Field Data Cache (用於排序、聚合使用的字段的緩存)。因爲構建字段數據緩存代價昂貴,所以建議有足夠的內存來存儲。
Fielddata 是 延遲 加載。如果你從來沒有聚合一個分析字符串,就不會加載 fielddata 到內存中。如果沒有足夠的內存保存fielddata時,Elastisearch會不斷地從磁盤加載數據到內存,並剔除掉舊的內存數據。剔除操作會造成嚴重的磁盤I/O,並且引發大量的GC,會嚴重影響Elastisearch的性能。
該配置默認無內存上限,但是可以通過配置來設置佔用的heap總量:
indices.fielddata.cache.size:30%
-
Segments Cache(segments FST數據的緩存),爲了加速查詢,FST 永駐堆內內存,無法被 GC 回收。該部分內存無法設置大小,長期佔用 50% ~ 70% 的堆內存,只能通過delete index,close index以及force-merge index釋放內存。
解釋下FST:
ES 底層存儲採用 Lucene(搜索引擎),寫入時會根據原始數據的內容,分詞,然後生成倒排索引。查詢時,先通過 查詢倒排索引找到數據地址(DocID)),再讀取原始數據(行存數據、列存數據)。但由於 Lucene 會爲原始數據中的每個詞都生成倒排索引,數據量較大。所以倒排索引對應的倒排表被存放在磁盤上。這樣如果每次查詢都直接讀取磁盤上的倒排表,再查詢目標關鍵詞,會有很多次磁盤 IO,嚴重影響查詢性能。爲了解磁盤 IO 問題,Lucene 引入排索引的二級索引 FST [Finite State Transducer] 。原理上可以理解爲前綴樹,加速查詢。
Off Heap
Lucene 中的 倒排索引 segments 存儲在文件中,由Lucene管理,爲提高訪問速度,都會把它加載到內存中,從而提高 Lucene 性能。所以建議至少留系統一半內存給Lucene。
解釋下Segment Cache,Segment Memory以及Segment的定義與關係
位置 | 存儲數據 | 調用關係 | |
Segment Cache | Heap | Segment的FST數據 |
Segment-->Segment Cache(加載) Client-->Segment Cache(查詢) |
Segment Memory | Off Heap |
通過Segment Cache的FST關聯出Segment數據, 加載到Off Heap用於加速查詢 |
Segment-->Segment Memory(加載) Client-->Segment Memory(查詢) |
Segment | Disk | 原始的Lucene數據 |
Segment Cache-->Segment(查詢) Segment-->Segment Memory(查詢加載) Segment-->Segment Cache(持續加載) index Buffer-->Segment(持續寫入) |