今天ElasticSearch遇到一个查询出错问题,情况是:查询老的数据没问题,查询近两天的新数据报错
其原因及解决方法可参考:
http://blog.csdn.net/yinchunxiang/article/details/39011297
限制内存使用
为了让聚集(或者任何需要访问字段值的请求)能够快点,访问fielddata一定会快些, 这就是为什么它加载到内存的原因。但是加载太多的数据到内存会导致垃圾回收缓慢, 因为JVM试着发现堆里面的额外空间,甚至导致OutOfMemory异常。
可能让你吃惊的是,你会发现Elaticsearch不是只把符合你的查询的值加载到fielddata. 而是把index里的所有document都加载到内存,甚至是不同的 _type
的document。
逻辑是这样的,如果你在这个查询需要访问documents X,Y和Z, 你可能在下一个查询 就需要访问别的documents。而一次把所有的值都加载并 保存在内存 , 比每次查询 都去扫描倒排索引要更方便。
JVM堆是一个有限制的资源需要聪明的使用。有许多现存的机制去限制fielddata对堆内 存使用的影响。这些限制非常重要,因为滥用堆将会导致节点的不稳定(多亏缓慢的垃 圾回收)或者甚至节点死亡(因为OutOfMemory异常)。
对于环境变量 $ES_HEAP_SIZE
在设置Elasticsearch堆大小的时候有2个法则可以运用:
-
不超过RAM的50%
Lucene很好的利用了文件系统cache,文件系统cache是由内核管理的。如果没有足够的文 件系统cache空间,性能就会变差。
-
不超过32G
如果堆小于32GB,JVM能够使用压缩的指针,这会节省许多内存:每个指针就会使用4字节 而不是8字节。
把对内存从32GB增加到34GB将意味着你将有 更少 的内存可用,因为所有的指针占用了 双倍的空间。同样,更大的堆,垃圾回收变得代价更大并且可能导致节点不稳定。
这个限制对大内存的影响主要是fielddata。
Fielddata大小
参数 indices.fielddata.cache.size
控制有多少堆内存是分配给fielddata的。当你 执行一个查询需要访问新的字段值的时候,将会把值加载到内存,然后试着把它们加入到 fielddata。如果结果的fielddata大小超过指定的 大小
,为了腾出空间别的值就会被 驱逐出去。
默认情况下,这个参数设置的是 无限制 — Elasticsearch将永远不会把数据从fielddata 里替换出去。
这个默认值是故意选择的:fielddata不是临时的cache。它是一个在内存里为了快速执行必须 能被访问的数据结构,而且构建它代价非常昂贵。如果你每个请求都要重新加载数据,性能就 会很差。
一个有限的大小强迫数据结构去替换数据。我们将看看什么时候去设置下面的值,首先让我们 看一个警告:
[警告]
这个设置是一个保护措施,而不是一个内存不足的解决方案
如果你没有足够的内存区保存你的fielddata到内存里,Elasticsearch将会经常性的从磁盘 重新加载数据,并且驱逐别的数据区腾出空间。这种数据的驱逐会导致严重的磁盘I/O并且在 内存里产生大量的垃圾,这个会在后面被垃圾回收。
假设你在索引日志,每天使用给一个新的索引。通常情况下你只会对过去1天或者2天的数据 感兴趣。即使你把老的索引数据保留着,你也很少查询它们。尽管如此,使用默认的设置, 来自老索引的fielddata也不会被清除出去!fielddata会一直增长直到它触发fielddata circuit breaker --参见下面的 断路器 --它将阻止你继续加载fielddata。
在那个时候你被卡住了。即使你仍然能够执行访问老的索引里的fielddata的查询, 你再也不能 加载任何新的值了。相反,我们应该把老的值清除出去给新的值腾出空间。
为了防止这种情景,通过在 config/elasticsearch.yml
文件里加上如下的配置给fielddata 设置了一个上限:
indices.fielddata.cache.size: 40% (1)
-
能设置成堆大小的百分比,或者一个具体的值,比如
5gb
.
通过适当的设置这个值,最近被访问的fielddata将被清除出去,给新加载的数据腾出空间。
[警告]
在网上你可能会看到另外一个设置参数: indices.fielddata.cache.expire
。
我们请求你 千万不要 使用这个设置!这个设置将来就会废弃了!
这个设置告诉Elasticsearch把比 过期时间
老的数据从fielddata里驱逐出去,而不管这个值 是否被用到。
这对性能是 非常可怕的 。驱逐数据是有代价的,并且这个有目的的高效的安排驱逐数据并没 有任何真正的收获。
没有任何理由去使用这个设置;我们一点也不能从理论上制造一个假设的有用的情景。现阶段存 在只是为了向后兼容。我们在这个书里提到这个设置是因为这个设置曾经在网络上的各种文章里 被作为一个 “性能小窍门” 被推荐过。
永远不要使用它!
监控fielddata
仔细监控fielddata使用了多少内存以及是否有数据被驱逐是非常重要的。大量的数据被驱逐会导 致严重的资源问题以及不好的性能。
Fielddata使用可以通过下面的方式来监控:
-
对于单个索引使用 {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=*
通过设置 ?fields=*
内存使用按照每个字段分解了.
断路器
聪明的读者可能已经注意到fielddata大小设置的一个问题。fielddata的大小是在数据被 加载之后才校验的。如果一个查询尝试加载到fielddata的数据比可用的内存大会发生什么 情况?答案是非常丑陋的:你将会获得一个OutOfMemory异常。
Elasticsearch包含了一个 fielddata断路器 ,这个就是设计来处理这种情况的。断路器 通过检查涉及的字段(它们的类型,基数,大小等等)来估计查询需要的内存。然后检查加 载需要的fielddata会不会导致总的fielddata大小超过设置的堆的百分比。
如果估计的查询大小超过限制,断路器就会触发并且查询会被抛弃返回一个异常。这个发生 在数据被加载之前,这就意味着你不会遇到OutOfMemory异常。
Elasticsearch拥有一系列的断路器,所有的这些都是用来保证内存限制不会被突破:
indices.breaker.fielddata.limit
这个 fielddata
断路器限制fielddata的大小为堆大小的60%,默认情况下。
indices.breaker.request.limit
这个 request
断路器估算完成查询的其他部分要求的结构的大小,比如创建一个聚集通, 以及限制它们到堆大小的40%,默认情况下。
indices.breaker.total.limit
这个 total
断路器封装了 request
和 fielddata
断路器去确保默认情况下这2个 使用的总内存不超过堆大小的70%。
断路器限制可以通过文件 config/elasticsearch.yml
指定,也可以在集群上动态更新:
PUT /_cluster/settings
{
"persistent" : {
"indices.breaker.fielddata.limit" : 40% (1)
}
}
-
限制设置的是堆的百分比
最好把断路器设置成一个相对保守的值。记住fielddata需要和堆共享 request
断路器, 索引内存缓冲区,过滤器缓存,打开的索引的Lucene数据结构,以及各种各样别的临时数据 结构。所以默认为相对保守的60%。过分乐观的设置可能会导致潜在的OOM异常,从而导致整 个节点挂掉。
从另一方面来说,一个过分保守的值将会简单的返回一个查询异常,这个异常会被应用处理。 异常总比挂掉好。这些异常也会促使你重新评估你的查询:为什么单个的查询需要超过60%的 堆空间。
在 Fielddata大小 部分我们谈到了要给fielddata大小增加一个限制去保证老的不使用 的fielddata被驱逐出去。indices.fielddata.cache.size
和 indices.breaker.fielddata.limit
的关系是非常重要的。如果断路器限制比缓冲区大小要小,就会没有数据会被驱逐。为了能够 让它正确的工作,断路器限制必须比缓冲区大小要大。
我们注意到断路器是和总共的堆大小对比查询大小,而不是和真正已经使用的堆内存区比较。 这样做是有一系列技术原因的(比如,堆可能看起来是满的,但是实际上可能正在等待垃圾 回收,这个很难准确的估算)。但是作为终端用户,这意味着设置必须是保守的,因为它是 和整个堆大小比较,而不是空闲的堆比较。
相关推荐
Kibana是Elastic Stack(以前称为ELK Stack,包括Elasticsearch、Logstash和Kibana)的一部分,提供了一个用户友好的界面,用于搜索、查看和分析Elasticsearch中的数据。Kibana Console允许用户直接在Web界面中编写...
在您提供的资源中,“elasticsearch-rolling-restart”是一个基于 Shell 脚本的工具,用于简化这个过程。让我们深入了解一下这个脚本的工作原理和相关知识点: 1. **Shell 脚本**:Shell 是 Linux 和 Unix 系统中的...
总结,EVM 是一个实用的工具,它使得管理多个 Elasticsearch 版本变得简单,尤其对于频繁在不同版本之间切换的开发者和运维人员来说,能够提高工作效率,降低出错的可能性。通过理解和熟练使用 EVM,你可以更好地...
这个文件可能用于解决在MacOS系统上安装或运行Elasticsearch可视化工具Kibana时遇到的问题。Kibana是Elasticsearch生态系统中的重要部分,它提供了数据的交互式探索、可视化的创建以及仪表板的构建功能,对于数据...
在单片机的串口通信应用中,经常会遇到由于上位机发送的字符串长度不匹配或是字符集不满等因素导致的接收字符串出错的问题。在51单片机串口通信中,发送的数据是通过一个个字符的形式逐个接收的,因此,单片机端一般...
以上是对S7-300系列PLC编程过程中可能遇到的一些问题及其解决方案的详细解析,这些问题涵盖了通讯、监控、错误处理、I/O配置、数据交换、硬件兼容性和网络设置等多个方面。理解并掌握这些知识点将有助于提高S7-300...
标题提到的"Android-一个国际化多语言的切换库对切换逻辑进行了封装",显然是一个专为简化Android应用多语言切换而设计的库,可能是开源项目。这个库的目标是帮助开发者轻松地管理和切换应用中的语言环境,从而提升...
首先,我们需要了解IE浏览器的一个常见问题是它对JavaScript的Console对象支持不完整。在早期版本的IE中,如果开发者尝试使用console.log或其他控制台方法,而用户并未开启开发者工具,浏览器会抛出错误。为解决这个...
"es-money"是一个基于TypeScript开发的金融货币处理库,主要设计用于在JavaScript环境中处理货币相关的计算和格式化。在JavaScript的世界里,由于语言本身的特性,处理精确的金融计算可能会遇到一些挑战,如浮点数...
Parcel.js是一个零配置的Web应用程序打包器,它的特点是快速和易于使用,能够自动处理项目的依赖关系。它的优势在于开箱即用,不需要繁琐的配置工作,这使得它非常适合前端开发者快速搭建项目。 然而,在使用Parcel...
这似乎是一个示例程序或项目,旨在演示或测试iPhone上的3D图形技术,但不幸的是,它遇到了错误。我们将尝试理解这个3D环境在iOS设备上的工作原理,并探索可能遇到的问题以及解决方案。 首先,iPhone 3D技术主要指的...
去哪儿网的安全工程师周军分享了他在构建和优化ELK(Elasticsearch、Logstash、Kibana)安全监控中心的过程中遇到的问题及解决方案,深入探讨了如何在企业级环境中实现有效的网络信息安全监控。 1. **安全监控的...
你可以选择将数据存储在文件(如CSV或JSON)、数据库(如MySQL、MongoDB)或者使用NoSQL解决方案如Elasticsearch。在Go中,有许多库可以方便地实现这些功能。 5. **处理反爬策略** 汽车之家等大型网站通常会有反爬...
为解决项目写保护问题,文档中建议了一个可能的解决方案,即安装“Microsoft Access Database Engine 2010 Redistributable”。该数据库引擎是Microsoft为不同版本的Access数据库提供运行时功能的软件包。该软件包...
函数体内的`await`关键字用于等待一个Promise的结果,当`await`后面是一个Promise时,`await`会阻塞函数的执行,直到Promise解析或拒绝,然后返回Promise的结果。 以下是一个使用`async/await`的例子: ```...
在这个"JS仿头条服务器错误页面特效.zip"压缩包中,包含了一个实现类似今日头条服务器错误页面的JS特效代码,即当用户尝试访问不存在或者出错的页面时,会展示一个具有互动性和视觉吸引力的错误提示页面。...
"Ogre_VC10_AppWizard_1.7.3" 是一个专为Visual Studio 2010(VC10)设计的项目模板,用于快速搭建基于Ogre 1.7.3版本的3D图形应用程序。Ogre是一个开源的、跨平台的3D渲染引擎,广泛应用于游戏开发、模拟软件以及...