记一次Cassandra Java堆外内存排查经历

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: 背景 最近准备上线cassandra这个产品,同事在做一些小规格ECS(8G)的压测。压测时候比较容易触发OOM Killer,把cassandra进程干掉。问题是8G这个规格我配置的heap(Xmx)并不高(约6.5g)已经留出了足够的空间给系统。

背景

最近准备上线cassandra这个产品,同事在做一些小规格ECS(8G)的压测。压测时候比较容易触发OOM Killer,把cassandra进程干掉。问题是8G这个规格我配置的heap(Xmx)并不高(约6.5g)已经留出了足够的空间给系统。只有可能是Java堆外内存使用超出预期,导致RES增加,才可能触发OOM。

调查过程

0.初步怀疑是哪里有DirectBuffer泄漏,或者JNI库的问题。
1.按惯例通过google perftools追踪堆外内存开销,但是并未发现明显的异常。
2.然后用Java NMT 看了一下,也没有发现什么异常。
0e964369341ad29ff6ea1e20ea75f0d3ed8e963f

3.查到这里思路似乎断了,因为跟DirectBuffer似乎没啥关系。这时候我注意到进程虚拟内存非常高,已经超过ECS内存了。怀疑这里有些问题。
ab6a0b6198cf86c4de8eac020f0c472564241cb8

4.进一步通过/proc/pid/smaps 查看进程内存地址空间分布,发现有大量mmap的文件。这些文件是cassandra的数据文件。
956c61ef2bcd58ba40d0f498350619730ee14a26

此时这些mmap file 虚拟内存是2G,但是物理内存是0(因为我之前重启过,调低过内存防止进程挂掉影响问题排查)。

显然mmap的内存开销是不受JVM heap控制的,也就是堆外内存。如果mmap的文件数据被从磁盘load进物理内存(RES增加),Java NMT和google perftool是无法感知的,这是kernel的调度过程。

5.考虑到是在压测时候出现问题的,所以我只要读一下这些文件,观察下RES是否会增加,增加多少,为啥增加,就能推断问题是不是在这里。通过下面的命令简单读一下之前导入的数据。

cassandra-stress read duration=10m cl=ONE -rate threads=20 -mode native cql3 user=cassandra password=123 -schema keysp
ace=keyspace5 -node core-3

6.可以观察到压测期间(sar -B),major page fault是明显上升的,因为数据被实际从磁盘被load进内存。
4944c8972d4df6a173c805cf7d5e91aa6049c49f

同时观察到mmap file物理内存增加到20MB:
3751993b8ffc483ab37658181e40585a685b0d06

最终进程RES涨到7.1g左右,增加了大约600M:
2c56dc8fad29d7266a6e67ca6601d319c6914b76

如果加大压力(50线程),还会涨,每个mmap file物理内存会从20MB,涨到40MB

7.Root cause是cassandra识别系统是64还是32来确定要不要用mmap,ECS都是64,但是实际上小规格ECS内存并不多。
27b11488d70f5a5d36d0d5ff6af8c706b1578e46

结论

1.问题诱因是mmap到内存开销没有考虑进去,具体调整方法有很多。可以针对小规格ECS降低heap配置或者关闭mmap特性(disk_access_mode=standard)
2.排查Java堆外内存还是比较麻烦的,推荐先用NMT查查,用起来比较简单,配置JVM参数即可,可以看到内存申请情况。

相关实践学习
一小时快速掌握 SQL 语法
本实验带您学习SQL的基础语法,快速入门SQL。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
存储 Java 编译器
Java内存区域详解
Java内存区域详解
18 0
Java内存区域详解
|
17天前
|
缓存 算法 Java
Java内存管理与调优:释放应用潜能的关键
【4月更文挑战第2天】Java内存管理关乎性能与稳定性。理解JVM内存结构,如堆和栈,是优化基础。内存泄漏是常见问题,需谨慎管理对象生命周期,并使用工具如VisualVM检测。有效字符串处理、选择合适数据结构和算法能提升效率。垃圾回收自动回收内存,但策略调整影响性能,如选择不同类型的垃圾回收器。其他优化包括调整堆大小、使用对象池和缓存。掌握这些技巧,开发者能优化应用,提升系统性能。
|
13天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
20天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
60 0
|
3天前
|
存储 缓存 监控
Java内存管理:垃圾回收与内存泄漏
【4月更文挑战第16天】本文探讨了Java的内存管理机制,重点在于垃圾回收和内存泄漏。垃圾回收通过标记-清除过程回收无用对象,Java提供了多种GC类型,如Serial、Parallel、CMS和G1。内存泄漏导致内存无法释放,常见原因包括静态集合、监听器、内部类、未关闭资源和缓存。内存泄漏影响性能,可能导致应用崩溃。避免内存泄漏的策略包括代码审查、使用分析工具、合理设计和及时释放资源。理解这些原理对开发高性能Java应用至关重要。
|
17天前
|
Java
java中jar启动设置内存大小java -jar 设置堆栈内存大小
java中jar启动设置内存大小java -jar 设置堆栈内存大小
11 1
|
18天前
|
缓存 算法 Java
Java内存管理:优化性能和避免内存泄漏的关键技巧
综上所述,通过合适的数据结构选择、资源释放、对象复用、引用管理等技巧,可以优化Java程序的性能并避免内存泄漏问题。
25 5
|
21天前
|
监控 网络协议 NoSQL
java线上排查OOM内存溢出
java线上排查OOM内存溢出
21 0
|
存储 Java
Java的内存划分的五个部分
Java的内存划分的五个部分