elasticsearch6.1.3查询只返回部分数据或报错Data too large

问题背景

1、ES导出报错CircuitBreakingException[[FIELDDATA] Data too large, data for [proccessDate] would be larger than limit of [10307921510/9.5gb]]
2、ES导出丢失数据,只返回范围内部分数据,同时未报错

问题原因在这里插入图片描述

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+其他部分)大小。

修改方式

修改vi /home/elasticsearch-6.1.3/config/elasticsearch.yml
增加

indices.fielddata.cache.size: 60%
indices.breaker.fielddata.limit: 70%

重启服务即可

拓展

下面这条可以不加
bootstrap.memory_lock: true

elasticsearch官网建议生产环境需要设置bootstrap.memory_lock: true
官网的解释 是:发生系统swapping的时候ES节点的性能会非常差,也会影响节点的稳定性。所以要不惜一切代价来避免swapping。swapping会导致Java GC的周期延迟从毫秒级恶化到分钟,更严重的是会引起节点响应延迟甚至脱离集群。
所以最好限制住elasticsearch占用的内存情况,可选少用swap
开启bootstrap.memory_lock: true后,在Elasticsearch集群启动的时候,会报如下错误

ERROR: bootstrap checks failed memory locking requested for elasticsearch process but memory is not locked

解决方法

方案1:
此方案适用于非systemd管理的linux发行版,centos 6及以下可以仅通过这个方案解决
临时解决

ulimit -l unlimited

永久解决

root权限编辑/etc/security/limits.conf
vi /etc/security/limits.conf
添加如下内容,保存退出

* soft memlock unlimited
* hard memlock unlimited

这里的*代表的是所有用户名称,可以更换为指定用户名
另:这里有个坑就是如果/etc/security/limits.d文件夹下的有配置文件,那么会覆盖刚才修改的文件,所以请确保该目录没有其它文件,如有请联系运维人员确认删除
编辑/etc/sysctl.conf

sudo echo "vm.swappiness=0" >> /etc/sysctl.conf

这个参数的作用是告诉Linux内核尽少的使用swap分区,不等于禁用swap,通过少使用swap来提高性能。
如果想立即生效而不是重启之后让sysctl.conf生效,请使用sysctl -p
重新登录或重启服务器方可生效

方案2:
适用于systemd管理的发行版,有文章提到centos 7需要使用此方案,本人使用debian 9.9.0 亲测解决问题,推荐先完成上边的方案后尝试本方案
这里还是推荐使用上边方法的第3步,尽少使用swap分区
在Centos7系统中,使用Systemd替代了之前的SysV。/etc/security/limits.conf文件的配置作用域缩小了。/etc/security/limits.conf的配置,只适用于通过PAM认证登录用户的资源限制,它对systemd的service的资源限制不生效。因此登录用户的限制,通过/etc/security/limits.conf与/etc/security/limits.d下的文件设置即可。
对于systemd service的资源设置,则需修改全局配置,全局配置文件放在/etc/systemd/system.conf和/etc/systemd/user.conf,同时也会加载两个对应目录中的所有.conf文件/etc/systemd/system.conf.d/.conf和/etc/systemd/user.conf.d/.conf。system.conf是系统实例使用的,user.conf是用户实例使用的。
全局生效方式

vi /etc/systemd/system.conf

在最下方添加

DefaultLimitNOFILE=65536
DefaultLimitNPROC=32000
DefaultLimitMEMLOCK=infinity

保存, 重启系统
局部生效方式:(针对包管理器安装elasticsearch的形式)

sudo systemctl edit elasticsearch

此命令会在/etc/systemd/system下创建elasticsearch.service.d/override.conf文件
添加如下内容

[Service]
LimitMEMLOCK=infinity

保存,退出,执行如下命令生效

sudo systemctl daemon-reload

保存, 重启系统

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值