Elasticsearch (ES)内存管理降低内存占用率

Elasticsearch 主要通过以下机制和方法管理内存使用
名词解释
Field data(字段数据) 是 Elasticsearch 中存储文档字段值的一种数据结构,用于支持聚合、排序、脚本和其他操作。在 Elasticsearch 中,文档中的每个字段都可以被索引,并且可以被搜索和分析。

当你执行聚合操作、排序、或者使用脚本时,Elasticsearch 需要对字段数据进行处理。Field data 缓存存储了字段数据的一部分或全部内容,以便于快速访问和处理。这样,当你执行相同的操作时,Elasticsearch 可以直接从缓存中获取字段数据,而不必每次都从磁盘或者内存中重新加载。

Field data 缓存对于聚合操作特别重要,因为聚合操作通常需要处理大量的文档字段值。通过缓存字段数据,Elasticsearch 可以提高聚合操作的性能,减少对底层数据的读取次数,从而加快查询的速度。

然而,由于 field data 缓存需要占用内存,如果字段数据量很大,缓存可能会占用大量的系统内存。因此,Elasticsearch 提供了一些参数(如 indices.fielddata.cache.size)来控制 field data 缓存的大小,以避免占用过多的内存资源。

  1. Fielddata Cache
    • Elasticsearch 使用 fielddata 缓存来加速聚合和排序操作。默认情况下,fielddata 会根据最近最少使用 (Least Recently Used, LRU) 算法进行管理,频繁访问的数据会保留在内存中,而不常访问的数据会被剔除。
    • 可以通过设置 indices.fielddata.cache.size 来限制 fielddata 缓存的大小,从而间接控制内存使用。
  2. Query Cache
    • Elasticsearch 提供查询缓存 (query cache) 来缓存频繁使用的查询结果。同样采用 LRU 算法管理,不常使用的缓存条目会被淘汰。
    • 可以配置 indices.queries.cache.sizeindices.queries.cache.count 来限制查询缓存的大小和条目数。
  3. Circuit Breaker
    • Elasticsearch 使用电路断路器 (circuit breaker) 机制来防止内存过载。当内存使用超过一定阈值时,会拒绝新的请求来保护系统稳定性。
    • 可以调整 indices.breaker.fielddata.limitindices.breaker.total.limit 等参数来控制断路器的行为。
  4. Segment Merging and Refreshing
    • Elasticsearch 会定期合并和刷新段 (segments),这些操作会影响内存使用。虽然无法直接控制哪些数据保留在内存中,但可以通过优化索引配置来减少不必要的内存开销。

监控

获取节点统计信息(包括内存使用情况)

bash 复制代码
curl --user username:password -X GET "http://127.0.0.1:9200/_nodes/stats?pretty"
json 复制代码
"os" : {
  "mem" : {
    "total_in_bytes" : 16313823232,
    "free_in_bytes" : 1427173376,
    "used_in_bytes" : 14886649856,
    "free_percent" : 9,
    "used_percent" : 91
  }
},
操作系统级别的内存:
总内存:16313823232 字节(约为 15.2GB)
空闲内存:1427173376 字节(约为 1.33GB)
使用内存:14886649856 字节(约为 13.86GB)
使用百分比:91%
"jvm" : {
  "mem" : {
    "heap_used_in_bytes" : 518682624,
    "heap_used_percent" : 12,
    "heap_committed_in_bytes" : 4294967296,
    "heap_max_in_bytes" : 4294967296,
    "non_heap_used_in_bytes" : 134244584,
    "non_heap_committed_in_bytes" : 145391616,
    ...
  }
},
JVM(Java 虚拟机)内存:
堆内存使用:518682624 字节(约为 494.6MB)
堆内存使用百分比:12%
堆内存提交:4294967296 字节(约为 4GB)
非堆内存使用:134244584 字节(约为 128MB)
非堆内存提交:145391616 字节(约为 138MB)

获取节点热线程信息

bash 复制代码
curl --user elastic:password -X GET "http://127.0.0.1:9200/_nodes/hot_threads?pretty"

设置 Fielddata Cache

shell 复制代码
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
indices.fielddata.cache.size: 40%
# 允许 Field Data 缓存占用 JVM 堆内存的 40%,也可以使用具体的数值,例如 `12GB`。
indices.breaker.fielddata.limit: 60%
# 当 Field Data 缓存在 JVM 堆内存中的使用达到 JVM 堆内存的 60% 时,Elasticsearch 将会限制 Field Data 缓存的进一步分配

动态设置 Fielddata 缓存

可以使用 Elasticsearch 的动态设置 API 在运行时调整 fielddata 缓存的大小:

sh 复制代码
curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d '{
  "persistent": {
    "indices.fielddata.cache.size": "40%"
  }
}'

配置 indices.fielddata.cache.sizeindices.breaker.fielddata.limit 这两个参数是为了控制 Elasticsearch 中 Field Data 缓存的使用。

  1. indices.fielddata.cache.size 这个参数指定了 Field Data 缓存在 JVM 堆内存中所占用的百分比。在你的配置中,设置为 40%,表示你允许 Field Data 缓存占用 JVM 堆内存的 40%。
  2. indices.breaker.fielddata.limit 这个参数指定了 Field Data 缓存在 JVM 堆内存中的占用限制。在你的配置中,设置为 60%,表示当 Field Data 缓存在 JVM 堆内存中的使用达到 JVM 堆内存的 60% 时,Elasticsearch 将会限制 Field Data 缓存的进一步分配。

这两个参数一起配置的目的是为了控制 Field Data 缓存在 JVM 堆内存中的使用,以避免过度占用内存而导致系统性能下降或者内存溢出问题。通过限制 Field Data 缓存的大小和使用百分比,可以确保系统的稳定性和性能。

总的来说,indices.fielddata.cache.size 控制了 Field Data 缓存的大小,而 indices.breaker.fielddata.limit 则控制了 Field Data 缓存在 JVM 堆内存中的占用限制。两者结合起来可以有效地管理 Field Data 缓存的使用。

配置 Query Cache

yaml 复制代码
indices.queries.cache.size: 10%
# 限制查询缓存的大小

indices.queries.cache.count: 10000
# 限制查询缓存的条目数

配置 Circuit Breaker

yaml 复制代码
indices.breaker.fielddata.limit: 60%
indices.breaker.total.limit: 70%
# 以上配置将 fielddata 缓存使用限制为堆内存的 60%,总内存使用限制为堆内存的 70%。

调整 Indexing 和 Refresh 设置

设置刷新间隔

增加索引刷新间隔,可以减少刷新操作的频率,从而降低内存使用:

sh 复制代码
curl -X PUT "localhost:9200/my_index/_settings" -H "Content-Type: application/json" -d '{
  "index": {
    "refresh_interval": "30s"
  }
}'

设置合并策略

优化段合并策略可以减少内存使用。通过设置 index.merge.policy 参数来控制合并行为:

sh 复制代码
curl -X PUT "localhost:9200/my_index/_settings" -H "Content-Type: application/json" -d '{
  "index": {
    "merge": {
      "policy": {
        "max_merged_segment": "5gb",
        "segments_per_tier": 10,
        "deletes_pct_allowed": 20
      }
    }
  }
}'
相关推荐
武子康5 天前
调查研究-197 FAISS vs Elasticsearch 全面对比:从向量检索、全文搜索到 RAG 选型指南
人工智能·elasticsearch·agent
Elasticsearch6 天前
Elasticsearch ES|QL:现已支持视图、子查询和读取时模式定义
elasticsearch
Elasticsearch9 天前
Kibana 中的 SNMP 拓扑数据:从采集到 Canvas
elasticsearch
Elasticsearch11 天前
3个信号、2个环境变量、0个采集器:使用 Python 和 Elastic 的托管 OTLP 端点实现 OpenTelemetry
elasticsearch
Elasticsearch13 天前
如何通过 Claude Code 来写入 CSV 数据到 Elasticsearch
elasticsearch
大志哥12315 天前
ES和Logstash日志链路系统上线后遭遇切片爆炸(解决)
大数据·elasticsearch
源分享15 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm
JAVA96515 天前
JAVA面试-JVM篇 03-JVM运行时数据区哪些是线程私有的哪些是共享的
java·jvm·面试
TableRow15 天前
参数化搜索的实现原理:从多维索引到查询优化
elasticsearch·全文检索