zoukankan      html  css  js  c++  java
  • 记一次Elasticsearch OOM(内存溢出)的优化过程—基于segments force merge 和 store type 转为 hybridfs

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

    转载请注明出处:https://www.cnblogs.com/NaughtyCat/p/elasticsearch-OOM-optimize-story.html  

    业务场景:

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

    题外话,ES OOM 会生成  .hprof 文件,如下图(作者【CoderBaby】):

     用jhat来分析OOM堆转储文件,具体命令:  jhat -port 7401 -J-Xmx4G java_pid19546.hprof

    解决办法:

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

    设置存储类型为:“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命令,即:stat -gcutil 6811 (ES的PID)查看ES的jvm,如下图:

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

    •  不要自己创建文档ID

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

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

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

    •  扩大堆内存

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

    • 扩大虚拟内存空间

    命令: sysctl -w vm.max_map_count=2621440(默认值是 “262144”),扩大这个,可以防止这个数量太低而导致的OOM(详见附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多万,具体如下表:

    index total_segments_berfore_merge total_segments_after_merge query_IP_after(seconds)   query_IP_after(seconds)  decrease(count/percentage)
    pcap_flow-2019-12-09  1412695374 137249867 10 3.6 40196703/ %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

     

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    *****************************************************************************************************

    精力有限,想法太多,专注做好一件事就行

    • 我只是一个程序猿。5年内把代码写好,技术博客字字推敲,坚持零拷贝和原创
    • 写博客的意义在于打磨文笔,训练逻辑条理性,加深对知识的系统性理解;如果恰好又对别人有点帮助,那真是一件令人开心的事

    *****************************************************************************************************

  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/NaughtyCat/p/elasticsearch-OOM-optimize-story.html
Copyright © 2011-2022 走看看