1.概述
转载:ES内存分配规划
听说这个是老黄历了,新版的es都进行大改了
2.ES内存使用分析
ES的JVM heap按使用场景分为可GC部分和常驻部分。 可GC部分内存会随着GC操作而被回收; 常驻部分不会被GC,通常使用LRU策略来进行淘汰; 内存占用情况如下图:
-
common space
包括了indexing buffer和其他ES运行需要的class。 -
indexing buffer
由indices.memory.index_buffer_size
参数控制, 默认最大占用10%,当full up后,该部分数据被刷入磁盘对应的Segments中。这部分空间是可以被回收反复利用的。 -
queryCache
是node级别的filter过滤器结果缓存,大小由indices.queries.cache.size
参数控制,默认10%。使用LRU淘汰策略。 -
requestCache
是shard级别的query result缓存,通常 only requests of size 0 such as aggregations, counts and suggestions will be cached。使用LRU淘汰策略。通过indices.requests.cache.size
参数控制,默认1%。设置后整个NODE都生效。 -
fieldDataCache
,针对text字段,没有docValues属性(相当于列存储),当对text类型字段进行sort,agg时,需要将对应的字段内容全部加载到内存,这部分数据就放在fieldDataCache。通过indices.fielddata.cache.size
参数限制大小,默认不限制。这种情况下,占用内存会逐渐增多,直到触发熔断;新数据无法加载。 -
segmentsMemory
,缓存段信息,包括FST,Dimensional points for numeric range filters,Deleted documents bitset ,Doc values and stored fields codec formats等数据。这部分缓存是必须的,不能进行大小设置,通常跟index息息相关,close index、force merge均会释放部分空间。 可以通过命令
GET _cat/nodes?v&h=id,ip,port,r,ramPercent,ramCurrent,heapMax,heapCurrent,fielddataMemory,queryCacheMemory,requestCacheMemory,segmentsMemory
id ip port r ramPercent ramCurrent heapMax heapCurrent fielddataMemory queryCacheMemory requestCacheMemory segmentsMemory
SN22 xx..28 9300 cdfhimrstw 94 29.9gb 16gb 10.9gb 1.4gb 27.6mb 163.8mb 61.6mb
drMa xx..30 9300 cdfhimrstw 79 25.1gb 16gb 9.3gb 1.4gb 21.4mb 87.6mb 51.5mb
kdgH xx..29 9300 cdfhimrstw 79 25.3gb 16gb 6.7gb 1.5gb 21.1mb 47.5mb 54.4mb
TSGg xx..31 9300 cdfhimrstw 82 26.2gb 16gb 5.6gb 1.4gb 16.3mb 11.4mb 51.8mb
查看当前各块的使用情况。
3. 熔断器
Elasticsearch 有一系列的断路器,它们都能保证内存不会超出限制:
-
indices.breaker.fielddata.limit
fielddata 断路器默认设置堆的 60% 作为 fielddata 大小的上限。 -
indices.breaker.request.limit
request 断路器估算需要完成其他请求部分的结构大小,例如创建一个聚合桶,默认限制是堆内存的 60%。它实际上是node level的一个统计值,统计的是这个结点上,各类查询聚合操作,需要申请的Bigarray的空间大小总和。 所以如果有一个聚合需要很大的空间,同时在执行的聚合可能也会被break掉。 -
indices.breaker.total.limit
父熔断,inflight、request(agg)和fielddata不会使用超过堆内存的 70%。 -
network.breaker.inflight requests.limit
限制当前通过HTTP等进来的请求使用内存不能超过Node内存的指定值。这个内存主要是限制请求内容的长度。 默认100%。 -
script.max_compilations_per_minute
限制script并发执行数,默认值为
参考文档 Circuit Breaker
4.ES内存分配规划
类目 | 默认占比 | 是否常驻 | 淘汰策略(在控制大小情况下) | 控制参数 |
---|---|---|---|---|
query cache | 10% | 是 | LRU | indices.queries.cache.size |
request cache | 1% | 是 | LRU | indices.requests.cache.size |
fielddata cache | 无限制 | 是 | LRU | indices.fielddata.cache.size |
segment memory | 无限制 | 是 | 无 | 不能通过参数控制 |
common space | 70% | 否 | GC | 通过熔断器 indices.breaker.total.limit 限制 |
common space(可GC)
子类目 | 默认占比 | 控制参数 |
---|---|---|
indexing buffer | 10% | indices.memory.index_buffer_size |
request agg data | 60% | indices.breaker.request.limit |
in-flight data | 100% | network.breaker.inflight_requests.limit |
通过上表可知,segment memory是非常重要,而且是不可通过参数干预的内存空间,而cache部分则可以提升性能,可以被清除。common space 是运行时的动态空间,可以被GC。
综上所述,需要保证segment memory+cache+common space
不超过100%。由于熔断器是按整个heap大小来计算的,所以如果segment memory 过大,仍然可能会导致OOM。为了减少这种情况的发生,需要预留足够空间给segment。 优化
-
限制fielddata大小,fielddata是针对text类型进行排序、聚合才用到。正常应该避免这种情况发生。
-
限制request agg data大小,这个参数会影响聚合使用的内存,如果触发熔断,业务需要进行优化。
4.1 内存分配
segment memory
|
预留10%
| |
fielddata cache
|
限制在20%
| |
query cache
|
限制10%
| |
request cache
|
限制1%
| |
indexing buffer
|
限制10%
| |
request agg data
|
限制1%
|
父熔断器配置30%,扣除fielddata,agg剩余的就是in-flight
|
in-flight data
|
限制9%
|
参数设置
indices.fielddata.cache.size:1%--需要重启节点
PUT _cluster/settings
{
"persistent": {
"indices.breaker.fielddata.limit":"20%",
"indices.breaker.request.limit":"1%",
"indices.breaker.total.limit":"70%"
}
}