以下内容部分摘录整理自:ElasticSearch CPU和内存占用高的优化记录

当ElasticSearch天突然大面积出现查询超时,以下指令对于诊断是有帮助的。

查询所有segment的驻留内存的情况

curl "http://127.0.0.1:9200/_cat/segments?v&h=index,segment,size"

查看node的内存和cpu的使用情况

curl "http://127.0.0.1:9200/_cat/nodes?v"

查看ElasticSearch运行日志

[gc][51125] overhead, spent [15s] collecting in the last [15.2s]

Java JVM GC的解释

与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理。JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自动把不再被使用的存储空间释放掉,也就是说,GC机制可以有效地防止内存泄露以及内存溢出。

JAVA 垃圾回收器的主要任务是:

分配内存
确保被引用对象的内存不被错误地回收
回收不再被引用的对象的内存空间
凡事都有两面性。垃圾回收器在把程序员从释放内存的复杂工作中解放出来的同时,为了实现垃圾回收,garbage collector必须跟踪内存的使用情况,释放没用的对象,在完成内存的释放之后还需要处理堆中的碎片, 这样做必定会增加JVM的负担。

为什么要了解JAVA的GC机制? 综上所述,除了作为一个程序员,精益求精是基本要求之外,深入了解GC机制让我们的代码更有效率,尤其是在构建大型程序时,GC直接影响着内存优化和运行速度。

GC的一些说明

需要提的一点就是 GC 是非常影响性能的,所以我们来简单介绍一下 JVM 的机制。启动 JVM 虚拟机的时候,会分配固定大小的内存块,也就是堆 heap。堆又分成两组,Young 组是为新实例化的对象所分配的空间,比较小,一般来说几百 MB,Young 组内又分为两个 survivor 空间。Young 空间满了后,就垃圾回收一次,还存活的对象放到幸存空间中,失效的就被移除。Old 组就是保存那些重启存活且一段时间不会变化的内容,对于 ES 来说可能有 30 GB 内存是 Old 组,同样,满了之后就垃圾回收。

垃圾回收的时候,JVM 采用的是 STW(Stop The World) 机制,Young 组比较小还好,但是 Old 组可能需要几秒十几秒,那就是服务器无响应啊!所以我们必须非常关注 GC 性能。

如果 ES 集群中经常有很耗时的 GC,说明内存不足,如果影响集群之间 ping 的话,就会退出集群,然后因为分片缘故导致更大的影响。我们可以在节点状态中的 jvm 部分查看对应的数值,最重要是 heap_used_percent,如果大于 75,那么就要垃圾回收了,如果长期在 75 以上,那就是内存不足。

查看ElasticSearch 节点状态

curl "http://10.61.13.142:9200/_nodes/stats"
//jvm 占用cpu 98%  内存 80%

综合上述,给出修改思路

  • jvm heap 设置比较小,默认是2g,本机有10g,配置内存为6g
  • jvm GC 配置原来为UseConcMarkSweepGC,更新为 UseG1GC
  • 修改elasticSeaerch安装目录下:jvm.options,如果是集群则每个节点都要改
    //注释掉原来的配置
    ## GC configuration
    #-XX:+UseConcMarkSweepGC
    #-XX:CMSInitiatingOccupancyFraction=75
    #-XX:+UseCMSInitiatingOccupancyOnly

    //更新为
    -XX:+UseG1GC
    -XX:MaxGCPauseMillis=50

    //修改

    -Xms6g
    -Xms6g

其实核心就是,增大内存,调整GC回收方式。



Related Posts: ElasticSearch CPU和内存占用高的优化记录 :

留言