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(持续写入) |