集群熔断-Data too large
问题现象:
排查监控发现存在熔断,查看日志如下
代码语言:go复制应用日志:
2022-05-24T21:17:53.142 0800 ERROR service/task.go:580 SearchSesionlogRecord err=%v
{"error": "elastic: Error 429 (Too Many Requests):
[parent] Data too large, data for [<http_request>] would be [15578885702/14.5gb],
which is larger than the limit of [15461882265/14.3gb],
real usage: [15578885480/14.4gb], new bytes reserved: [222/222b],
usages [request=173877960/165.8mb, fielddata=725/725b,
in_flight_requests=3126550/2.9mb, model_inference=0/0b, single_request=0/0b, accounting=129583700/123.5mb]
[type=parent_circuit_breaking_exception]"}
解读:
- [parent]父熔断,此外还有fielddata、in_flight_request,介绍见附录
- Data too large, data for <http_request> would be 15578885702/14.3gb 这个就是上限内存(缺省是它是ES最⼤内存的90%)
- real usage: 15578885480/14.4gb ES已经使⽤的内存
- new bytes reserved: 222/222b 本次查询需要的内存
原因分析和解决方案
出现熔断说明当前节点 JVM 使用率过高,通过熔断保护进程不会 OOM。此时可以通过适当降低读写、清理内存等方法降低节点负载,也可以通过升级节点内存规格来提高 JVM 大小。
计算方式(父熔断,其他熔断方式类同):
腾讯云默认JVM大小为机器的50%,如节点为16C32G,则JVM默认为16G,通过
GET _cluster/settings?include_defaults&flat_settings查询熔断器配置,可以看到熔断器父熔断总限制为JVM的90%,16*0.9=14.5gb,那么如果内存不足,为了保护集群,就会产生父熔断保护集群。
如为fielddata熔断,则查看indices.breaker.fielddata.limit,如下图为20%
常用的内存清理方法
清理 fielddata cache:
在 text 类型的字段上进行聚合和排序时会使用 fileddata 数据结构,可能占用较大内存。可以在 Kibana 界面的【Dev Tools】中使用如下命令查看索引的 fielddata 内存占用:
代码语言:javascript复制GET/_cat/indices?v&h=index,fielddata.memory_size&s=fielddata.memory_size:desc
若 fielddata 占用内存过高,可以在 Kibana 界面的【Dev Tools】中使用如下命令清理 fielddata:
代码语言:javascript复制POST /${fielddata占用内存较高的索引}/_cache/clear?fielddata=true
清理 segment:
每个 segment 的 FST 结构都会被加载到内存中,并且这些内存是不会被 GC 回收的。因此如果索引的 segment 数量过大,也会导致内存使用率较高。可以在 Kibana 界面的【Dev Tools】中使用如下命令查看各节点的 segment 数量和占用内存大小:
代码语言:javascript复制GET/_cat/nodes?v&h=segments.count,segments.memory&s=segments.memory:desc
若 segment 占用内存过高,可以通过删除部分不用的索引、关闭索引,或定期合并不再更新的索引等方式缓解。
扩容集群:
如果您清理内存后,仍频繁触发熔断,说明您的集群规模已经不匹配于您的业务负载,最好的方式是扩大集群规模,具体可参考 扩容集群。
更新内核:
优先推动更新内核,根据客户使用情况来重启集群更新到最新版本的内核,会有所优化。ES内核基本上每个月都有迭代,会修复一些已知的问题。内核版本查看:
附录:
Elasticsearch 官方熔断器
父熔断器(Parent circuit breaker)
父熔断器限制所有子熔断器上使用的内存总量,当触发父熔断器熔断时,可能的日志信息如下:
代码语言:javascript复制Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<transport_request>] would be [1749436147/1.6gb], which is larger than the limit of [1622605824/1.5gb], real usage: [1749435872/1.6gb], new bytes reserved: [275/275b]
- Field data 熔断器(Field data breaker) 当对 text 字段聚合或排序时,会产生 Field data 数据结构。Field data 熔断器会预估有多少数据被加载到内存中。当预估的数据占用内存到达 Field data 熔断器阈值时,会触发 Field data 熔断器熔断。此时可能的日志信息如下:
org.elasticsearch.common.breaker.CircuitBreakingException: [fielddata] Data too large, data for [_id] would be [943928680/900.2mb], which is larger than the limit of [255606128/243.7mb]
- In flight 请求熔断器(In flight requests circuit breaker) In flight 请求熔断器限制了在 transport 和 HTTP 层的所有当前传入的请求所使用的内存。当触发 In flight 请求熔断器时,可能的日志信息如下:
[o.e.x.m.e.l.LocalExporter] [1611816935001404932] unexpected error while indexing monitoring document org.elasticsearch.xpack.monitoring.exporter.ExportException: RemoteTransportException[[1611816935001404732][9.10Elasticsearch