CircuitBreakingException[[FIELDDATA] Data too large, data for [proccessDate] would be larger than li

来源:互联网 发布:淘宝店铺如何快速升钻 编辑:程序博客网 时间:2024/05/20 11:46

CircuitBreakingException[[FIELDDATA] Data too large, data for [proccessDate] would be larger than limit of [10307921510/9.5gb]]; }]”

今天再用kibana查询日志时,报了标题所示的错误。仔细研究了一天,总结一下。

ES缓冲区概述

ES在查询时,会将索引数据缓存在内存(JVM)中:

ES在查询时,会将索引数据缓存在内存(JVM)中。
当缓存数据到达驱逐线时,会自动驱逐掉部分数据,把缓存保持在安全的范围内。当用户准备执行某个查询操作时,缓存数据+当前查询需要缓存的数据量到达断路器限制时,会返回Data too large错误,阻止用户进行这个查询操作。ES把缓存数据分成两类,FieldData和其他数据,我们接下来详细看FieldData,它是造成我们这次异常的“元凶”。

ES配置中提到的FieldData指的是字段数据。当排序(sort),统计(aggs)时,ES把涉及到的字段数据全部读取到内存(JVM Heap)中进行操作。相当于进行了数据缓存,提升查询效率。

indices.fielddata.cache.size控制分配给fielddata多少堆内存。当在一个字段首次执行查询时,es会把它加载到内存中,同时添加到fielddata。如果fielddata超过了指定的堆内存,会从fielddata占用的内存中删除掉一些值。但是默认,这个设置是undounded,也就是没限制。这样,fielddata就会一直增加。但是,一旦它占用的内存超过了断路器规定的内存,就不会往里面加载更多fielddata了。

下面,让我们来看看断路器又是什么鬼。断路器一共有三个。

    indices.breaker.fielddata.limit
fielddata断路器默认限制fielddata占用堆内存的60%
    indices.breaker.request.limit
请求断路器,估算请求或者聚合占用内存大小,默认限制大小为堆内存的40%
    indices.breaker.total.limit
默认情况下,total断路器保证请求和fielddata断路器的和小与堆内存的70%

断路器的设置可以在config/elasticsearch.yml中设置,也可以动态更新:


PUT /_cluster/settings
{
"persistent" : {
"indices.breaker.fielddata.limit" : "40%"
}
}

当fielddata断路器的大小超过设置的值,就会出现开头提到的Data too large。

总结

  • 这次Data too large异常是ES默认配置的一个坑,我们没有配置indices.fielddata.cache.size,它就不回收缓存了。缓存到达限制大小,无法往里插入数据。

  • 当前fieldData缓存区大小 < indices.fielddata.cache.size
    当前fieldData缓存区大小+下一个查询加载进来的fieldData < indices.breaker.fielddata.limit
    fielddata.limit的配置需要比fielddata.cache.size稍大。而fieldData缓存到达fielddata.cache.size的时候就会启动自动清理机制。

  • indices.breaker.request.limit限制查询的其他部分需要用的内存大小。indices.breaker.total.limit限制总(fieldData+其他部分)大小。

官方文档看这里: [ 限制内存使用 ]

0 0
原创粉丝点击