高 JVM 内存压力
编辑高 JVM 内存压力
编辑高 JVM 内存使用率会降低集群性能并触发断路器错误。为防止这种情况,如果节点的 JVM 内存使用率持续超过 85%,我们建议采取措施来降低内存压力。
诊断高 JVM 内存压力
编辑检查 JVM 内存压力
在您的部署菜单中,单击Elasticsearch。在实例下,每个实例都会显示一个 JVM 内存压力指示器。当 JVM 内存压力达到 75% 时,指示器会变为红色。
您还可以使用节点统计 API来计算每个节点的当前 JVM 内存压力。
resp = client.nodes.stats( filter_path="nodes.*.jvm.mem.pools.old", ) print(resp)
response = client.nodes.stats( filter_path: 'nodes.*.jvm.mem.pools.old' ) puts response
const response = await client.nodes.stats({ filter_path: "nodes.*.jvm.mem.pools.old", }); console.log(response);
GET _nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
使用响应按如下方式计算内存压力
JVM 内存压力 = used_in_bytes
/ max_in_bytes
要计算每个节点的当前 JVM 内存压力,请使用节点统计 API。
resp = client.nodes.stats( filter_path="nodes.*.jvm.mem.pools.old", ) print(resp)
response = client.nodes.stats( filter_path: 'nodes.*.jvm.mem.pools.old' ) puts response
const response = await client.nodes.stats({ filter_path: "nodes.*.jvm.mem.pools.old", }); console.log(response);
GET _nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
使用响应按如下方式计算内存压力
JVM 内存压力 = used_in_bytes
/ max_in_bytes
检查垃圾回收日志
随着内存使用量的增加,垃圾回收变得更加频繁,耗时更长。您可以在elasticsearch.log
中跟踪垃圾回收事件的频率和时长。例如,以下事件表明 Elasticsearch 在过去 40 秒的时间里,有超过 50% (21 秒) 的时间在执行垃圾回收。
[timestamp_short_interval_from_last][INFO ][o.e.m.j.JvmGcMonitorService] [node_id] [gc][number] overhead, spent [21s] collecting in the last [40s]
捕获 JVM 堆转储
要确定高 JVM 内存压力的确切原因,请在 JVM 内存使用率较高时捕获其堆转储,并捕获同一时间段的垃圾回收器日志。
降低 JVM 内存压力
编辑本节包含一些关于降低 JVM 内存压力的常见建议。
减少分片数量
每个分片都会占用内存。在大多数情况下,少量的大分片比许多小分片使用的资源更少。有关减少分片数量的技巧,请参阅调整分片大小。
昂贵的搜索会占用大量内存。为了更好地跟踪集群上的昂贵搜索,请启用慢日志。
昂贵的搜索可能具有较大的size
参数,使用具有大量桶的聚合,或包含昂贵的查询。要防止昂贵的搜索,请考虑以下设置更改
- 使用
index.max_result_window
索引设置降低size
限制。 - 使用search.max_buckets集群设置减少允许的最大聚合桶数。
- 使用
search.allow_expensive_queries
集群设置禁用昂贵的查询。 - 使用
search.default_search_timeout
集群设置设置默认搜索超时。
resp = client.indices.put_settings( settings={ "index.max_result_window": 5000 }, ) print(resp) resp1 = client.cluster.put_settings( persistent={ "search.max_buckets": 20000, "search.allow_expensive_queries": False }, ) print(resp1)
response = client.indices.put_settings( body: { 'index.max_result_window' => 5000 } ) puts response response = client.cluster.put_settings( body: { persistent: { 'search.max_buckets' => 20_000, 'search.allow_expensive_queries' => false } } ) puts response
const response = await client.indices.putSettings({ settings: { "index.max_result_window": 5000, }, }); console.log(response); const response1 = await client.cluster.putSettings({ persistent: { "search.max_buckets": 20000, "search.allow_expensive_queries": false, }, }); console.log(response1);
PUT _settings { "index.max_result_window": 5000 } PUT _cluster/settings { "persistent": { "search.max_buckets": 20000, "search.allow_expensive_queries": false } }
防止映射爆炸
定义过多的字段或将字段嵌套过深会导致映射爆炸,从而占用大量内存。要防止映射爆炸,请使用映射限制设置来限制字段映射的数量。
分散批量请求
虽然比单独的请求更高效,但大型批量索引或多搜索请求仍然会产生较高的 JVM 内存压力。如果可能,请提交较小的请求并允许它们之间有更多的时间间隔。
升级节点内存
繁重的索引和搜索负载会导致高 JVM 内存压力。为了更好地处理繁重的工作负载,请升级您的节点以增加其内存容量。