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
      }
    }
  }
}'
相关推荐
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm
Elasticsearch2 天前
Elastic Observability 的跨项目搜索:通过一个查询搜索所有关联项目
elasticsearch
wuminyu2 天前
HotSpot的轻量锁与膨胀后的ObjectMonitor状态重建原理
java·linux·c语言·jvm·c++
需要8262 天前
JVM 内存区域与对象创建:一次 GC 从哪来
java·jvm·spring boot·spring·servlet·tomcat
Elasticsearch2 天前
Elasticsearch 中的 agentic 工作流:暂停 AI agent 等待人工审批,72 小时后恢复
elasticsearch
凤山老林2 天前
Spring Boot 应用 JVM 性能调优实战:GC 日志分析、堆内存规划与容器环境避坑
jvm·spring boot·gc·堆内存
Elastic 中国社区官方博客2 天前
jina-ocr-v1:在低成本 GPU 上实现更快速的文档解析
大数据·数据库·elasticsearch·搜索引擎·全文检索·jina
vx-程序开发3 天前
【计算机毕设】django校园跑腿服务系统83141
java·数据库·vue.js·spring boot·spring·elasticsearch·django
Elasticsearch3 天前
jina-ocr-v1:在低成本 GPU 上实现更快速的文档解析
elasticsearch
深海鱼肝油ya3 天前
向量数据库Elasticsearch(四)搜索文档——各种方式
人工智能·elasticsearch·向量数据库·es搜索文档·只能体·非结构化数据库