03-limit-memory-usage-es控制聚合内存使用-elasticsearch权威指南翻译

为了让类似agg这种需要获取field value的操作是需要返回请求迅速的,这是为什么会把fielddata加载到内存中的原因,但是大量的fielddata会导致内存回收慢,甚至内存异常。

也许你惊奇的会发现es不仅把匹配你查询的文档的值放到了fielddata中,竟然把所有文档的值放在了内存中,甚至包括type。

逻辑是,你查询前面的可能会查询后面的,一次把所有数据加载进来并保存到内存中会很方便的和快速的,否则每个请求都去倒排索引中查一次。

JVM HEAP是有限制的,应该明智使用。有各种各样的机制来限制fielddata的使用,这些限制是非常重要的,因为滥用HEAP会导致系统不稳定甚至不可用。

选择一个HEAP SIZE

有两种规则来设置这个值,通过$ES_HEAP_SIZE变量

(1)不能超过系统内存的50%

(2)不能超过32GB,在32GB内,JVM会自动压缩,这样可以节约很多的内存,8bytes压缩到4 bytes,超过32,意味着你可用内存会越来越小,因为原来压缩的都变大了。

field data

indices.fielddata.cache.size 这个值控制了多少内存用于field data,当你进行查询的时候,需要新的field value,系统将会把数据加载dao内存而且尝试把数据加载到fielddata中,如果这些值超过了范围,其他的值将被踢出去来让出空间来。

默认es没有限制这个值,也就是说es从不会剔除数据去。

这个默认设置系统是有意这样做的,fielddata不是短暂数据,这些数据存在内存中能很快执行,而且建立这些数据是非常不容易的,如果每次请求再去加载这些数据表现会很差。

通过设置一个限定值将会根据值剔除数据,我们接下来会看到如何设置这个值。

首先,这个值是一个安全值,但不是内存不足的解决方案。

如果你没有足够的内存让这些数据常驻内存,es将会经常的从硬盘加载数据然后剔除旧的数据给新数据让出空间,evict过程会导致大量的IO操作,并且生成大量的内存垃圾需要去回收。

想象一下你正在index log数据,每天使用新的index,突然有天你想看前两天数据,如果是默认设置,旧数据酒会不断给内存中加入,直到circuit breaker。但这个时候系统也不能再加载新的数据了,因为都让fielddata占用了。

为了防止这件事情,需要在yml文件中进行设置:

indices.fielddata.cache.size: 40%

也可以设置一个具体的值:5gb

通过这个设置,上述那种情况中的新的fielddata会剔除出去,旧的会进来。

监控fielddata

对index监控

GET /_stats/fielddata?fields=*

对每个nodes监控

GET /_nodes/stats/indices/fielddata?fields=*

对每个index每个node监控

GET /_nodes/stats/indices/fielddata?level=indices&fields=*


circuit breaker(也许带入的fielddata 超过了整个的size)

细心的读者会发现一个问题:fielddata size是在数据加载进内存才核对的,如果一个query加入的fielddata比设置值大怎么办?结果是内存异常。

es有个circuit breaker就是用于处理这个问题的,这个模块会估计一个query进来带入的fielddata需要的内存,然后检察是否会超过fielddata的size

如果获取的值超过这个值,该query会在数据加载进来前被停止,也就是说不会看到内存异常.

默认这些值进行了设置:

indices.breaker.fielddata.limit 默认是HEAP的60%

indices.breaker.request.limit 默认是HEAP 40%

indices.breaker.total.limit 两者合起来不能超过HEAP 70%默认

可以动态的设置

PUT /_cluster/settings

{

"persistent" : {

"indices.breaker.fielddata.limit" : "40%"

}

}


circuit breaker limit 设置必须比indices.fielddata.cache.size大,如果小了,就不存在数据evict了,达到limit就阻止query了,cache第一道防线,limit最后一道防线。

最后这些值是保守值,用户还得好好思考啊

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结