FE堆外内存泄漏

【详述】fe主节点发生内存不足告警,通过TOP命令,占用机器88%的内存,另外两台fellower节点top观察占用约40%~50%左右,三台fe节点机器为16G,-xmx配置的是12G,通过jmap -heap输出结果显示,fe实际使用的堆内存只有3.58G,占比-xmx的29.8%,但是实际物理机,已经没有多少空余内存了。初步判定是fe进程应该发生了比较严重的内存泄漏,这种情况该如何解决?
【背景】无
【业务影响】fe节点告警,fe机器内存会被逐渐耗尽
【是否存算分离】否
【StarRocks版本】3.1.10
【集群规模】3fe(1 follower+2observer)+3be
【机器信息】FE节点: 4C16G
【其他】ps -ef | grep fe_pid输出: /usr/java/jdk/bin/java -Dlog4j2.formatMsgNoLookups=true -Xmx12288m -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/sr/fe/log/fe.gc.log.20240509-075712 -XX:+PrintConcurrentLocks -Djava.security.policy=/sr/fe/conf/udf_security.policy com.starrocks.StarRocksFE截屏2024-05-11 22.05.45
截屏2024-05-11 22.05.29
截屏2024-05-11 22.09.11

你好,之前我也遇到这个问题,你的问题解决了么?

还没有呢,具体是fe哪一块导致的堆外内存泄漏,还没有找到原因,只能先通过重启临时恢复下,头疼。。。

我之前也是重启了一遍,下去了,但是现在内存又开始慢慢的上去,但是不降,一个星期上升百分比三个点

fe进程里面有比较多的线程在执行与 Netty 相关的网络操作,会使用到堆外内存优化网络数据的传输。当存在大量的 Netty 调用时,如果没有管理 好Netty 的缓冲区引用或释放操作,堆外内存就比较容易泄漏,这个是我觉得是fe堆外内存泄漏可能性比较大的原因

free 部分是 8628MB? 这部分 jvm cache 住的不一定会立刻归还 OS,有当时的 gc 日志吗,可以看下当时的 heap 大小,如果 heap 用了 12G(used + free),OS 层面 RES 13.2G,感觉也正常, 另外你 java 版本用的多少,有没有尝试升级到 jdk11 最新的版本

G1 有 heap shrink 功能,会根据内存分配压力,决定是不是缩小 heap 空间,follower 节点,你也可以看下 jmap 信息和 free/used

gc日志用jstat -gcutil $pid 1000 1000 查看么?

重启后你的内存是不是也在慢慢的上去,但是不掉

是的,JVM的内存有增有减,GC正常,但FE机器的总内存使用只增不减,机器上只有FE这一个进程。

fe/log 下面有 gc 日志

可以参考这个:https://www.cnblogs.com/duanxz/p/3738858.html ,用 NMT分析一下堆外内存的使用情况。
另外你把 max heap 调整到 10G,看下 RES 最终会上涨到多少

image


老师,实际占用的内存也不大,

JVM也正常,
但是就是内存一直上涨
image ,上涨了10个点,目前还是在一点一点的上涨,有什么办法,可以让内存先降下去么

这个 used 是 jvm 使用的 heap , 41.82% 这个是进程的内存使用?你 top 看一下,另外,你执行 jmap histo:live pid 触发 full gc,看下进程的内存使用是不是就降下来了

这样的报错老师,我发现在执行instet语句,然后内存现在已经涨到45了

jmap -histo:live $pid

没帮助老师,内存还是不掉


在 Java 8 及更新版本中,可以通过启用 NMT(Native Memory Tracking)来查看堆外内存的使用情况。堆外内存是指在 Java 堆之外分配的内存,比如直接内存(通过 NIO 使用的堆外内存)等。

要启用 NMT 并查看堆外内存的使用情况,可以使用以下步骤:

  1. 启用 Native Memory Tracking

    • 在启动 Java 应用程序时,可以使用 -XX:NativeMemoryTracking=summary 参数来启用 NMT。例如:
      java -XX:NativeMemoryTracking=summary -jar YourApplication.jar
      
  2. 运行应用程序

    • 使用上述参数启动应用程序后,应用程序会在运行时收集有关堆外内存使用情况的信息。
  3. 查看 NMT 输出

    • 在应用程序运行时,可以使用 jcmd 命令来查看 NMT 输出。例如:
      jcmd <pid> VM.native_memory summary
      

    这将显示堆外内存的使用情况摘要,包括堆外内存的分配情况、使用情况和释放情况。

请注意,NMT 的输出可能会比较详细,包括不同类型的堆外内存使用情况。你可以根据自己的需求选择性地查看这些信息。

需要注意的是,NMT 功能在不同的 Java 版本中可能会有所不同,因此在具体使用时,建议查阅对应版本的官方文档以获取最准确的信息。

在JAVA_OPTS中加下这个 -XX:NativeMemoryTracking=summary

老师,我试着做下NMT,还有老师除了jmap -histo:live $pid 这个方式,还有什么可以降下去内存