【Elasticsearch】Elasticsearch中使用_id排序导致 data too large 问题

这篇具有很好参考价值的文章主要介绍了【Elasticsearch】Elasticsearch中使用_id排序导致 data too large 问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Elasticsearch】Elasticsearch中使用_id排序导致 data too large 问题



前言

Elasticsearch 一个弹性伸缩的搜索数据库,后文简称 :ES ,最近有一个ES 服务查询数据时候出现了数据Hits结果多次查询不一致的问题,而且这块代码已经很长时间没有修改,一直稳定运行了很长时间,用户翻译查询列表数据的时候又是出现1条,有时候出现2条或者3条。(再加上我们的ES 内存监控服务在次阶段进行了迁移。导致服务监控不可用,对于ES heap 堆内存过载的问题没有得到及时的反馈),于是紧急去排查了问题。在此记录排查问题后的一些总结。


以下是本篇文章正文内容,下面案例可供参考

一、出问题的代码

项目中使用了SpringData的NativeSearchQueryBuilder构造器进行查询。

        /***********上面省略其他构造条件**************
         
        //排序条件
        FieldSortBuilder fsb = SortBuilders.fieldSort("_id").order(SortOrder.DESC);
        //分页条件
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
        //构建查询
        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(bqb)
                .withSort(fsb)
                .withPageable(pageable)
                .build();

下面是错误休息由于个人原因不方便给出线上错误,此错误日志来自es官方文档,内容大致相同。

{
    "error": "... CircuitBreakingException[[FIELDDATA] Data too large, data for [proccessDate] would
     be larger than limit of [10307921510/9.5gb]]; }]",
    "status": 500

}

通过以上代码看出,此处代码使用了Elasticsearch 中自带的_id 字段进行排序,问题就出现在这里。

回顾下前置知识(次内容摘自Elasticsearch内核解析 - 数据模型篇):

内容提到了 ES底层数据模型是Lucene数据模型,而Lucene数据模型包括了

  • Index:索引,由很多的Document组成。
    • Invert Index:倒排索引,或者简称Index,通过Term可以查询到拥有该Term的文档。可以配置为是否分词,如果 分词可以配置不同的分词器。索引存储的时候有多种存储类型,分别是:
    • DOCS:只存储DocID。
    • DOCS_AND_FREQS:存储DocID和词频(Term Freq)。
    • DOCS_AND_FREQS_AND_POSITIONS:存储DocID、词频(Term Freq)和位置。
    • DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS:存储DocID、词频(Term Freq)、位置和偏移。
    • DocValues:正排索引,采用列式存储。通过DocID可以快速读取到该Doc的特定字段的值。由于是列式存储,性能会比较好。一般用于sort,agg等需要高频读取Doc字段值的场景。
    • Store:字段原始内容存储,同一篇文章的多个Field的Store会存储在一起,适用于一次读取少量且多个字段内存的场景,比如摘要等。
  • Document:由很多的Field组成,是Index和Search的最小单位。
  • Field:由很多的Term组成,包括Field Name和Field Value。
  • Term:由很多的字节组成,可以分词。

其中_id(在ES中使用的就是Lucene的_uid) 这个字段,此片文章给出一张图:
es data too large,Elasticsearch,elasticsearch,大数据,搜索引擎


通过上文了解到:_id字段是一个物理字段,用于唯一标识每个文档。而在ES中 默认的_id 并不会生成 DocValues】既然不会使用doc_values 那就是需要用到FieldData了,这个在ES中默认是关闭状态,恰好我们的ES服务是打开了这个开关的,所以在根据这个字段进行排序的时候,ES就开始在Heap 中开始建立临时的正排索引,来保证查询效率,同样Feild也会常驻内存,JVM垃圾回收并不会回收此区域的内存。而查询官方文档也说到了此问题(一下一段话摘自ES官方文档):

fielddata mapping parameter
text fields are searchable by default, but by default are not available for aggregations, sorting, or scripting. If you try to sort, aggregate, or access values from a script on a text field, you will see this exception:

Fielddata is disabled on text fields by default. Set fielddata=true on your_field_name in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.

Field data is the only way to access the analyzed tokens from a full text field in aggregations, sorting, or scripting. For example, a full text field like New York would get analyzed as new and york. To aggregate on these tokens requires field data.

Before enabling `fielddata·
It usually doesn’t make sense to enable fielddata on text fields. Field data is stored in the heap with the field data cache because it is expensive to calculate(这是一个非常昂贵的计算). Calculating the field data can cause latency spikes, and increasing heap usage is a cause of cluster performance issues(增加堆使用量是导致集群性能问题的原因).


如何监控FieldData
ES给出了API:
对于单个索引使用 {ref}indices-stats.html[indices-stats API]:
GET /_stats/fielddata?fields=*
对于单个节点使用 {ref}cluster-nodes-stats.html[nodes-stats API]:
GET /_nodes/stats/indices/fielddata?fields=*
或者甚至单个节点单个索引
GET /_nodes/stats/indices/fielddata?level=indices&fields=*

以下是 FieldData 监控的各字段的解释:

  • evictions:表示当前索引字段数据缓存被清除的次数。如果这个数字太高,说明字段数据缓存的大小可能太小了,需要增加缓存大小或者调整缓存清除策略。

  • memory_size_in_bytes:表示当前字段数据缓存使用的内存大小,以字节为单位。

  • field_name:表示当前监控的字段名。

  • account_count:表示当前字段数据缓存中已经缓存的项数。如果这个数字太高,说明字段数据缓存的大小可能太小了,需要增加缓存大小或者调整缓存清除策略。

  • circuit_breaker_limit_size:表示当前字段数据缓存的断路器限制大小。如果这个数字太低,可能会导致查询缓慢或者OOM异常。需要根据查询场景合理调整。

  • circuit_breaker_limit_size_in_bytes:表示当前字段数据缓存的断路器限制大小,以字节为单位。

注意:以上信息仅供参考,具体情况需要根据实际场景进行分析。

欸?按说这种错误应该直接报错啊?为什么出现了数据一会儿多一会儿少的问题呢?

我在Elasticsearch的官方博客上看到了一个19年一个用户对于类似问题的进行反馈,我的一个思考。
文章的内容大致描述报错内容和我很相似,题中一直提到 circuit_breaking_exception,我去ES 官方文档搜了一下这个异常的含义。其实这个错误也是ES为了给用户作为一个提醒的,提示用户你所用的当前的ES 集群是不是配置有问题,或者是用户当前的ES的集群配置是不是已经不在够维持当前数据量的负载(是不是需要增加配置)。

es data too large,Elasticsearch,elasticsearch,大数据,搜索引擎
在官方文档的文章最后 因为中也再次强调了,避免在text文档中使用fielddata,这会导致使用的大量的堆内存。建议使keyword类型,并且打开Docvalues进行加载到磁盘中进行使用比较合理。

所以当时ES集群中恰好是一台数据节点出现了熔断操作,所以并不会影响到另外两个节点的数据的正常返回。所以线上出现这种问题。所以 circuit_breaking_exception不会中断其他节点的查询结果,但是会中断发生异常的节点的查询结果。当发生circuit_breaking_exception异常时,节点会拒绝执行进一步的搜索或聚合请求,并向客户端返回错误响应。其他节点将继续处理查询请求,并返回它们自己的查询结果,而不会受到发生异常的节点的影响。

同时补充下ES 各个节点的类型以及作用:

在 Elasticsearch 集群中,不同节点类型的作用如下

  1. 主节点 (Master
    Node):主节点负责管理集群状态,并协调所有的变更操作。主节点通常不参与数据存储和搜索操作,只需要专注于协调管理工作。主节点的数量一般建议不超过3个,以确保在主节点发生故障时能够选举出新的主节点。
  2. 数据节点 (Data
    Node):数据节点负责存储索引数据和执行搜索操作。在大型集群中,通常会有多个数据节点以提高搜索和写入的性能。数据节点也可以与主节点合并成一个节点。
  3. 客户端节点 (Client
    Node):客户端节点不存储数据,仅用于路由搜索请求到数据节点,以避免搜索流量过度集中在数据节点上。客户端节点可以提高搜索性能,并且可以通过在客户端节点上运行负载均衡器来均衡负载。
  4. 协调节点 (Coordinating
    Node):协调节点负责协调搜索请求的路由,并将搜索结果从数据节点合并到一个单一的响应中。协调节点通常用于负载均衡,以避免搜索流量过度集中在单个数据节点上。

注意:以上节点类型不是互相独立的,同一个节点可以同时承担多种角色。

总结

提示:这里对文章进行总结:

以上就是今天要讲的内容,相信如果你看到了我这篇文章其实你已经搜索到了关于此类问题的很多解决方法,本文仅仅是对于当前问题的一个的思考以及衍生以及通过官方的角度来解决问题,想要临时解决,可以使用一下办法文章来源地址https://www.toymoban.com/news/detail-772882.html

  • 临时增大当前节点的堆内存大小(最直接的)
  • 清除缓存fielddata(可能导致该索引的查询变慢,引起业务抖动,提前和客户说明风险)执行下列语句)
    • json POST /索引名/_cache/clear?fielddata=true (无法根除)
  • 如果你的机器配置还是可以承受当前数据载体
    • 在 elasticsearch.yml中配置:
    • 参数: indices.breaker.fielddata.limit= 这个 fielddata 断路器限制fielddata的大小默认为堆内存的60%
    • 参数: indices.breaker.request.limit= 这个 request 断路器估算完成查询的其他部分要求的结构的大小默认为堆内存的40%
    • 参数: indices.breaker.total.limit=这个 total 断路器封装了 request 和 fielddata 断路器去确保默认情况下这2个部分使用的总内存不超过堆大小的70%。
    • 参数: indices.fielddata.cache.size=配置fieldData的Cache大小,可以配百分比也可以配一个准确的数值。cache到达约定的内存大小时会自动清理,驱逐一部分FieldData数据以便容纳新数据。默认值为unbounded无限
    • indices.fielddata.cache.expire=用于约定多久没有访问到的数据会被驱逐,默认值为-1,即无限。expire配置不推荐使用,按时间驱逐数据会大量消耗性能。而且这个设置在不久之后的版本中将会废弃。(目前了解到高版本以及取消了当前配置【ES官方也可能在随着磁盘和硬件的效率提示和算法优化逐渐剔除掉fieldData】因为在目前满大街的SSD的配置加持下硬盘速度也是很快的)

到了这里,关于【Elasticsearch】Elasticsearch中使用_id排序导致 data too large 问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • es 报错 Data too large 触发断路器

    报错原因是 es 在 full GC 之前触发了默认的断路器,导致报错 [parent] Data too large ,相似的报错内容如下: 查看当前 es 节点的 jvm 内存使用情况(ip和端口要换成自己的 es 节点) heap.current 当前使用的内存 heap.percent 内存使用量百分比 heap.max 内存最大值 如果本机内存足够,并且

    2024年01月18日
    浏览(46)
  • ES写入数据时:circuit_breaking_exception[[parent] Data too large

    原因: (1)表面原因是在ES中大量内存被占用,GC无法对heap进行垃圾回收,导致node内存用量超出limit限制。 (2)根本原因是ES设置有问题,默认配置是JVM内存使用达到75%的时候进行full GC,默认配置总熔断器indices.breaker.total.use_real_memory 它的值直接影响JVM堆内存分配的大小,

    2024年02月04日
    浏览(30)
  • ES报错:[parent] Data too large, data for [<http_request>] would be larger than limit of XXXX

    当es这个错误的时候 : [parent] Data too large, data for [http_request] would be larger than limit of [23941899878/22.2gb], with { bytes_wanted=23941987633 bytes_limit=23941899878 } 通常原因是 在于fielddata的内存被占用完了,其他索引无法分配更多的内存。 另外,查询语句写的不好,单个请求聚合查询的数据太

    2024年02月09日
    浏览(37)
  • 查询ES报错429 circuit_breaking_exception,“reason“:“[parent] Data too large, data for \[<http_request\>\]

    查询ES报错:429 Too Many Requests;circuit_breaking_exception,”reason”:”[parent] Data too large, data for [http_request]“ 问题 :ES查询报错:429 Too Many Requests;circuit_breaking_exception,“reason”:“[parent] Data too large, data for [http_request]” 原因 :ES查询缓存占用内存过大,超过阈值(默认70%),查

    2024年02月12日
    浏览(32)
  • 413 Request Entity Too Large问题解决方法

    最近我们有个小程序需求是现场拍照提取照片中的有效信息,上传图片只能通过现场拍照,由于目前手机像素普遍较高,导致上传接口出现413 Request Entity Too Large,上传文件过大引起nginx代理报错。 针对这个问题,解决方案是: 项目配置文件修改,比如springboot项目中的applic

    2024年02月16日
    浏览(27)
  • 访问elasticsearch集群提示ERROR 新增es数据失败,后台日志返回413 Request Entity Too Larg

    在运维paas云平台时有研发反馈客户端访问elasticsearch服务偶发性的出现报错,提示报错如下: 报错日志内容核心点如下: 根据日志报错内容及研发反馈的信息得到如下有用信息: 1、连接elasticsearch服务并请求处理业务是偶发性的提示报错,也就是说明elasticsearch服务是正常的

    2024年04月17日
    浏览(37)
  • MySQL:1118 - Row size too large(行大小不能超过 65535 问题)

    当我们创建表或新增字段时,我们可能遇到下面这个问题: 大概的意思是说:行的大小过大,最大限制为 65535 ,其中不包括 TEXT or BLOB 类型,建议调整一些列为 TEXT or BLOB 类型。 下面我们来具体分析一下这个问题,并探讨如何解决。 MySQL 行大小最大限制为65535,不包括TEXT、

    2024年01月21日
    浏览(30)
  • 【解决问题】413错误 413 Request Entity Too Large 接口返回413 报413nginx

    博客背景:JAVA项目,前端想弄个便捷富文本,直接很多图片转base64编码直接存库了。字段为longtext类型。 这种问题通常是在使用http请求对象太大的时候。。 1、如果是超长的话varchar类型改成longtext类型。 2、依旧怀疑超长的话,搜了一下longtext的最大长度 mysql里3种text类型的最

    2024年02月07日
    浏览(36)
  • spring-data-elasticsearch使用Sort排序时Please use a keyword field instead. ……异常解决

    核心提示在 Please use a keyword field instead. Alternatively, set fielddata=true on [dataTimestamp] in order to load field data by uninverting the inverted index. 待排序字段 dataTimestamp 没有为排序优化,所以无法排序,需要配置 FieldType.Keyword 或 fielddata = true ,可是代码中都配置了为什么还提示呢,往下看……

    2023年04月24日
    浏览(30)
  • MySQL排查问题row size too large (> 8126). Changing some columns to TEXT or BLOB may help.

    例子:给表增加一列报错: 1118: Row size too large ( 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline. 单行记录的合计最大大小超过了 8126 字节,那么根据文档描述的话,使用dynamic行格式的表行最大大小可以达到65536字节(因为mysql内部使用了

    2024年02月13日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包