You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elasticsearch内存占用异常过高的原因排查与优化方案咨询

问题描述

我有一台Debian 10服务器,具备200GB+磁盘空间与32GB内存,运行两个基于nginx+MySQL+PHP架构的网站,分别使用Elasticsearch 6.1.4和7.2.1版本实现自动补全与搜索功能。

当前索引数据量与磁盘占用极小:

$ curl http://localhost:9721/_cat/indices?v
health status index                                                  uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   xxxxxxxx_xxxxxx_prod_documents-en_us_2022-06-08-082626 eRNQbX8bS1uQGM-jSIM9-Q   1   1     157364           20     10.3mb         10.3mb
yellow close  xxxxxxxx_xxxxxx_prod_documents-en_us_2022-06-07-163138 UA-ZpoLIQZSmId8beIFPMQ   1   1                                                  
yellow open   xxxxxxxx_xxxxxx_prod_documents-fr_fr_2022-06-08-082803 eCO2D3VoRlac1MOUVJTkmA   1   1     157364         4672     20.8mb         20.8mb
yellow close  xxxxxxxx_xxxxxx_prod_documents-fr_fr_2022-06-07-163316 tlim20SmTzy8pPouPC_ngA   1   1                                                 
$ curl http://localhost:9200/_cat/indices?v
health status index                                   uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   xxxxxxxx_quote_option_taxons_preprod    Ns95mRp0Ty-h3f6Y75NQoA   5   1          0            0      1.2kb          1.2kb
yellow open   xxxxxxxx_quote_full_text_prod           QBSA2OWoSx2OkBPkWnBoWw   5   1     108174           45     23.6mb         23.6mb
yellow open   xxxxxxxx_quote_full_text_preprod        l4tlrIidSe26JMg2ZGf0NA   5   1     107780            0     24.5mb         24.5mb
yellow open   xx_xxxxxxxx_shop_full_text_prod         a_g7ihFzTpWqqykaiBvriQ   5   1       1710           30      1.3mb          1.3mb
yellow open   xx_xxxxxxxx_shop_product_prod           d3vtuMGiQGKFibUAUTsARg   5   1       1710           78      1.1mb          1.1mb
yellow open   xxxxxxxx_xxxxxx_shop_product_preprod    YGIbbUtFRRyl2nHcViLgBw   5   1          0            0      1.2kb          1.2kb
yellow open   xxxxxxxx_quote_product_prod             T1u9YMtnSomBKCKP6pN6uA   5   1     108244           82     23.2mb         23.2mb
yellow open   xxxxxxxx_quote_product_preprod          whf6uxXmTJawURA9qAhHTw   5   1     107780            0     23.1mb         23.1mb
yellow open   xxxxxxxx_quote_attribute_taxons_prod    DvWW2SxnTCq530scIM4VBQ   5   1          0            0      1.2kb          1.2kb
yellow open   xx_xxxxxxxx_attribute_taxons_prod       WMLW-iKBQ9CFeVFyxt6Vrw   5   1         21            0     25.3kb         25.3kb
yellow open   xx_xxxxxxxx_option_taxons_prod          CA4nHrRlTH-JZvA8FqCkfQ   5   1          4            0     12.3kb         12.3kb
yellow open   xxxxxxxx_quote_option_taxons_prod       QrbOC8GWQOGMjfBr4xg4-Q   5   1          0            0      1.2kb          1.2kb
yellow open   xxxxxxxx_quote_attribute_taxons_preprod Y3rml_gGSSeWWRiZfgX0lw   5   1          0            0      1.2kb          1.2kb

每个Elasticsearch实例的堆内存配置为1GB:

-Xms1g
-Xmx1g

但实际监控显示,每个实例占用约9GB内存:

$ ./sysmon.sh 
PID       OWNER          MEMORY         COMMAND
23883     elastic+       9149420K       /bin/java
28790     xxxxxxxx       9116236K       /var/www/elasticsearch-7.2.1/jdk/bin/java

服务器因此频繁耗尽内存并触发交换分区(swap),且swap主要被Java进程占用:

$ for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | head -n 1
java 317076 kB

请问该现象的原因是什么?是否有方法将内存占用降至与数据量匹配的水平?


原因分析与解决方案

核心原因

Elasticsearch的内存占用分为**堆内存(Heap)和堆外内存(Off-Heap)**两部分,你看到的9GB是整个Java进程的总内存,并非仅配置的1GB堆内存:

  1. 堆外内存无限制占用:ES会利用堆外内存处理Lucene索引缓存、网络缓冲区、线程栈、内部组件开销等,默认JVM不会限制这部分内存,当系统内存充足时会无上限占用,加上双ES实例+其他服务的内存消耗,直接触发swap。
  2. 分片数量冗余:部分索引设置了5个主分片,但实际数据量极小,每个分片都会占用独立的内存结构与缓存,累加后大幅增加内存开销。
  3. GC与JVM额外开销:7.2.1版本默认使用的G1垃圾收集器会有额外的内存占用,进一步拉高进程总内存。

优化方案

1. 限制JVM堆外内存

  • 在ES的JVM配置文件(jvm.options)中添加直接内存限制参数,建议设置为与堆内存相当:
    -XX:MaxDirectMemorySize=1g
    
  • 在elasticsearch.yml中开启内存锁定,防止ES内存被系统swap:
    bootstrap.memory_lock: true
    
    注意:开启前需确保系统已配置足够的内存锁定限制(可通过ulimit -l调整)。

2. 精简分片数量

  • 对于数据量极小的索引(如预生产环境的空索引或小数据索引),将主分片数调整为1:
    # 重新索引现有索引到分片数为1的新索引
    POST _reindex
    {
      "source": {
        "index": "xxxxxxx_quote_option_taxons_preprod"
      },
      "dest": {
        "index": "xxxxxxx_quote_option_taxons_preprod_v2",
        "settings": {
          "number_of_shards": 1,
          "number_of_replicas": 1
        }
      }
    }
    
  • 删除不再使用的关闭索引,释放闲置资源。

3. 调整ES缓存配置

  • 在elasticsearch.yml中限制字段数据缓存与请求缓存的大小:
    # 限制字段数据缓存为堆内存的20%
    indices.fielddata.cache.size: 20%
    # 限制请求缓存为堆内存的10%
    indices.requests.cache.size: 10%
    

4. 系统层面优化

  • 关闭服务器上不必要的服务,释放内存给核心组件。
  • 降低系统swapiness参数,减少主动swap的概率:
    # 临时生效
    sysctl vm.swappiness=10
    # 永久生效,写入/etc/sysctl.conf
    echo "vm.swappiness=10" >> /etc/sysctl.conf
    

内容的提问来源于stack exchange,提问作者Julien Rouvier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:05:32