Elasticsearch circuit_breaking_exception 处理

文章目录

问题:

某天kibana无法正常使用,查看es容器log,发现GC无法正常回收JVM内存

{"type": "server", "timestamp": "2021-05-14T02:16:17,936Z", "level": "INFO", "component": "o.e.i.b.HierarchyCircuitBreakerService", "cluster.name": "docker-cluster", "node.name": "es0", "message": "GC did bring memory usage down, before [23301315824], after [23252356736], allocations [1], duration [20]", "cluster.uuid": "Bs2Sbp4wQEiPmaKiJmtsfg", "node.id": "4Jop7UNfQgOYJ8-b-_tXCA"  }

解决办法:

优化ES内存配置

1.配置断路器

  • indices.breaker.fielddata.limit

fielddata 断路器默认设置堆的 60% 作为 fielddata 大小的上限。

PUT /_cluster/settings
{
  "persistent": {
    "indices.breaker.fielddata.limit": "60%"
  }
} 
  • indices.breaker.request.limit

request 断路器估算需要完成其他请求部分的结构大小,例如创建一个聚合桶,默认限制是堆内存的 40%。

PUT /_cluster/settings
{
  "persistent": {
    "indices.breaker.request.limit": "40%"
  }
} 
  • indices.breaker.total.limit

total 揉合 request 和 fielddata 断路器保证两者组合起来不会使用超过堆内存的 70%。

PUT /_cluster/settings
{
  "persistent": {
    "indices.breaker.total.limit": "70%"
  }
} 

当前fieldData缓存区大小 < indices.fielddata.cache.size
当前fieldData缓存区大小 + 下一个查询加载进来的fieldData < indices.breaker.fielddata.limit
indices.breaker.request.limit + indices.breaker.fielddata.limit < indices.breaker.total.limit

  • indices.fielddata.cache.size

缓存回收大小,无默认值, 有了这个设置,最久未使用(LRU)的 fielddata 会被回收为新数据腾出空间;这个参数无法动态配置,需要修改elasticsearch.yml文件,并且重启节点

indices.fielddata.cache.size:  40%

ES相关文档说明:

字段数据

字段数据(fielddata),在 Lucene 中又叫 uninverted index。我们都知道,搜索引擎会使用倒排索引(inverted index)来映射单词到文档的 ID 号。而同时,为了提供对文档内容的聚合,Lucene 还可以在运行时将每个字段的单词以字典序排成另一个 uninverted index,可以大大加速计算性能。

作为一个加速性能的方式,fielddata 当然是被全部加载在内存的时候最为有效。这也是 ES 默认的运行设置。但是,内存是有限的,所以 ES 同时也需要提供对 fielddata 内存的限额方式:

  • indices.fielddata.cache.size 节点用于 fielddata 的最大内存,如果 fielddata 达到该阈值,就会把旧数据交换出去。该参数可以设置百分比或者绝对值。默认设置是不限制,所以强烈建议设置该值,比如 10%
  • indices.fielddata.cache.expire 进入 fielddata 内存中的数据多久自动过期。注意,因为 ES 的 fielddata 本身是一种数据结构,而不是简单的缓存,所以过期删除 fielddata 是一个非常消耗资源的操作。ES 官方在文档中特意说明,这个参数绝对绝对不要设置!

Circuit Breaker

Elasticsearch 在 total,fielddata,request 三个层面上都设计有 circuit breaker 以保护进程不至于发生 OOM 事件。在 fielddata 层面,其设置为:

  • indices.breaker.fielddata.limit 默认是 JVM 堆内存大小的 60%。注意,为了让设置正常发挥作用,如果之前设置过 indices.fielddata.cache.size 的,一定要确保 indices.breaker.fielddata.limit 的值大于 indices.fielddata.cache.size 的值。否则的话,fielddata 大小一到 limit 阈值就报错,就永远道不了 size 阈值,无法触发对旧数据的交换任务了。

ES内存分配规划

类目默认占比是否常驻淘汰策略(在控制大小情况下)控制参数
query cache10%LRUindices.queries.cache.size
request cache1%LRUindices.requests.cache.size
fielddata cache无限制LRUindices.fielddata.cache.size
segment memory无限制不能通过参数控制
common space70%GC通过熔断器 indices.breaker.total.limit 限制
原文链接:,转发请注明来源!

发表回复