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堆内存:
- 堆外内存无限制占用:ES会利用堆外内存处理Lucene索引缓存、网络缓冲区、线程栈、内部组件开销等,默认JVM不会限制这部分内存,当系统内存充足时会无上限占用,加上双ES实例+其他服务的内存消耗,直接触发swap。
- 分片数量冗余:部分索引设置了5个主分片,但实际数据量极小,每个分片都会占用独立的内存结构与缓存,累加后大幅增加内存开销。
- GC与JVM额外开销:7.2.1版本默认使用的G1垃圾收集器会有额外的内存占用,进一步拉高进程总内存。
优化方案
1. 限制JVM堆外内存
- 在ES的JVM配置文件(
jvm.options)中添加直接内存限制参数,建议设置为与堆内存相当:-XX:MaxDirectMemorySize=1g - 在
elasticsearch.yml中开启内存锁定,防止ES内存被系统swap:
注意:开启前需确保系统已配置足够的内存锁定限制(可通过bootstrap.memory_lock: trueulimit -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
相关产品推荐
相关产品推荐

