公司银子不多,遇到Elasticsearch OOM(内存溢出),除了瞪白眼,还能干啥...

 点击上方蓝色“终端研发部”,选择“设为星标”

学最好的别人,做最好的我们

作者:CoderBaby

来源:cnblogs.com/NaughtyCat/p/elasticsearch-OOM-optimize-story.html

首先,说明笔者的机器环境(不结合环境谈解决方案都是耍流氓): cpu 32核,内存128G,非固态硬盘:RAID0 (4T * 6),单节点,数据量在700G到1800G,索引15亿~21亿。在蘑菇街,可多集群分片,固态硬盘,比不起啊。

# 业务场景

保存7天索引,每天有400G~500G。发现ES时不时的OOM(out of memory)和重启。当索引超过500G的时候,ES重启到加载所有分片,时间约30分钟到1小时。

题外话,ES OOM 会生成  .hprof 文件,如下图:

用jhat来分析OOM堆转储文件,具体命令: 

 jhat -port 7401 -J-Xmx4G java_pid19546.hprof

 

# 解决办法

1、改文件存储类型,减少内存占用

设置存储类型为:“hybridfs” ,即:"index.store.type": "hybridfs" (原来为“mmapfs”,详见附2;另外,ES 5.6应为“fs”,不支持“hybridfs”,最新的7.4版本支持“hybridfs”)。

  • mmapfs:index映射到内存;

  • niofs :并发多线程以NIO的方式读取index文件;

  •  hybridfs:混合 mmafs和niofs ,根据读取模式选择最佳的文件系统。

效果:在600G左右的索引,5天索引,确实没有了OOM。但一旦增大到7个索引,就不行了。用jstat命令,即:

jstat -gcutil 6811 (ES的PID)

查看ES的jvm,如下图:

O: Old space utilization as a percentage of the space's current capacity (老年代空间占用率)。O最高达到79,就往下降,原来为存储类型为“mmapfs”,O很容易就飙到100。

2、不要自己创建文档ID

ES默认会自动创建文档Id"(如:_id": "AW8922mK8RqpiZJD9zb2"),如果自己生成Id,则每次存储新的文档的时候,ES都会查看整个分片是否已经存在该Id。如果分片存储有上千万的文档,这是一个比较耗时的操作。

3、关闭暂时不用的索引,减少打开索引的数量

关闭索引(文件仍然存在于磁盘,只是释放掉内存,需要的时候可重新打开)。设置打开索引参数:"__es.maxPermanentlyOpenIndices":4 (最大打开索引:7改为4)。

4、扩大堆内存

设置堆大小,从15G提高到30G,即: -Xms30g -Xmx30g (注意:最大不要超过物理内存的 %50)。

5、扩大虚拟内存空间

命令: 

sysctl -w vm.max_map_count=2621440(默认值是 “262144”)

扩大这个,可以防止这个数量太低而导致的OOM(详见附6)

6、forcemerge

设置merge时最大的线程数:index.merge.scheduler.max_thread_count。固态硬盘——默认最大值  Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)) ,普通旋转磁盘——设置为1。

笔者机器上,单merge 线程,300G的索引耗时:7个小时

优化效果:term 单条件查询,查询时间从10秒多提高到3秒多,索引减少约%2.85,减少4000多万,具体如下表:

indextotal_segments_berfore_mergetotal_segments_after_mergequery_IP_after(seconds)  query_IP_after(seconds) decrease(count/percentage)
pcap_flow-2019-12-09 1412695374137249867103.640196703/ %2.845

 

可通过命令查看各个分片的情况,如下(可查看总的segments数量):

curl -s "http://localhost:9200/_cat/segments/pcap_flow-2019-12-10?v&h=shard,segment,size,size.memory" | awk '{sum += $NF} END {print sum}'

force merge的restful API:

curl -X POST "localhost:9200/pcap_flow-2019-12-11/_forcemerge?max_num_segments=2"

说明:

1)max_num_segments, 设置最大segement数量,数量越小,查询速度提高越明显,但merge耗时越长;

2)全部merge,不加索引ID,则如下:

curl -X POST "localhost:9200/_forcemerge"

3)merge过程是串行的,如果同时merge多个,后面的会被阻塞,直到第一个merge完成为止。另外,对于不再有写入的更新的index,才建议force merge,不然反而会让搜索的性能更差;

4)restful api 查看_segments,如下:

curl -X GET "localhost:9200/_cat/segments?v&pretty"

效果如下图:

 

题外话,如果贵司银子多,可以集群分片,搞SSD,否则只有结构优化,这一招。

 

# 参考

1)官网  index force merge说明:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-forcemerge.html

2) ES 存储类型:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-store.html

3)merge 线程数:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html

4)磁盘阵列RAID:https://zh.wikipedia.org/wiki/RAID

5)关于索引合并的统计分析:http://openskill.cn/article/375

6)扩大虚拟地址空间:https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.htm

BAT等大厂Java面试经验总结 想获取 Java大厂面试题学习资料扫下方二维码回复「BAT」就好了回复 【加群】获取github掘金交流群回复 【电子书】获取2020电子书教程回复 【C】获取全套C语言学习知识手册回复 【Java】获取java相关的视频教程和资料回复 【爬虫】获取SpringCloud相关多的学习资料回复 【Python】即可获得Python基础到进阶的学习教程回复 【idea破解】即可获得intellij idea相关的破解教程回复 【BAT】即可获得intellij idea相关的破解教程关注我gitHub掘金,每天发掘一篇好项目,学习技术不迷路!


回复 【idea激活】即可获得idea的激活方式

回复 【Java】获取java相关的视频教程和资料

回复 【SpringCloud】获取SpringCloud相关多的学习资料

回复 【python】获取全套0基础Python知识手册

回复 【2020】获取2020java相关面试题教程

回复 【加群】即可加入终端研发部相关的技术交流群

阅读更多

为什么HTTPS是安全的

因为BitMap,白白搭进去8台服务器...

《某厂内部SQL大全 》.PDF

字节跳动一面:i++ 是线程安全的吗?

大家好,欢迎加我微信,很高兴认识你!

在华为鸿蒙 OS 上尝鲜,我的第一个“hello world”,起飞!

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!


喜欢就给个“在看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值