记一次Cassandra Java堆外内存排查经历
背景
最近準備上線cassandra這個產(chǎn)品,同事在做一些小規(guī)格ECS(8G)的壓測。壓測時候比較容易觸發(fā)OOM Killer,把cassandra進程干掉。問題是8G這個規(guī)格我配置的heap(Xmx)并不高(約6.5g)已經(jīng)留出了足夠的空間給系統(tǒng)。只有可能是Java堆外內(nèi)存使用超出預期,導致RES增加,才可能觸發(fā)OOM。
調(diào)查過程
0.初步懷疑是哪里有DirectBuffer泄漏,或者JNI庫的問題。
1.按慣例通過google perftools追蹤堆外內(nèi)存開銷,但是并未發(fā)現(xiàn)明顯的異常。
2.然后用Java NMT?看了一下,也沒有發(fā)現(xiàn)什么異常。
3.查到這里思路似乎斷了,因為跟DirectBuffer似乎沒啥關系。這時候我注意到進程虛擬內(nèi)存非常高,已經(jīng)超過ECS內(nèi)存了。懷疑這里有些問題。
4.進一步通過/proc/pid/smaps 查看進程內(nèi)存地址空間分布,發(fā)現(xiàn)有大量mmap的文件。這些文件是cassandra的數(shù)據(jù)文件。
此時這些mmap file 虛擬內(nèi)存是2G,但是物理內(nèi)存是0(因為我之前重啟過,調(diào)低過內(nèi)存防止進程掛掉影響問題排查)。
顯然mmap的內(nèi)存開銷是不受JVM heap控制的,也就是堆外內(nèi)存。如果mmap的文件數(shù)據(jù)被從磁盤load進物理內(nèi)存(RES增加),Java NMT和google perftool是無法感知的,這是kernel的調(diào)度過程。
5.考慮到是在壓測時候出現(xiàn)問題的,所以我只要讀一下這些文件,觀察下RES是否會增加,增加多少,為啥增加,就能推斷問題是不是在這里。通過下面的命令簡單讀一下之前導入的數(shù)據(jù)。
cassandra-stress read?duration=10m?cl=ONE?-rate?threads=20?-mode?native?cql3?user=cassandra?password=123?-schema?keysp ace=keyspace5?-node?core-36.可以觀察到壓測期間(sar -B),major page fault是明顯上升的,因為數(shù)據(jù)被實際從磁盤被load進內(nèi)存。
同時觀察到mmap file物理內(nèi)存增加到20MB:
最終進程RES漲到7.1g左右,增加了大約600M:
如果加大壓力(50線程),還會漲,每個mmap file物理內(nèi)存會從20MB,漲到40MB
7.Root cause是cassandra識別系統(tǒng)是64還是32來確定要不要用mmap,ECS都是64,但是實際上小規(guī)格ECS內(nèi)存并不多。
結論
1.問題誘因是mmap到內(nèi)存開銷沒有考慮進去,具體調(diào)整方法有很多。可以針對小規(guī)格ECS降低heap配置或者關閉mmap特性(disk_access_mode=standard)
2.排查Java堆外內(nèi)存還是比較麻煩的,推薦先用NMT查查,用起來比較簡單,配置JVM參數(shù)即可,可以看到內(nèi)存申請情況。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉載。
總結
以上是生活随笔為你收集整理的记一次Cassandra Java堆外内存排查经历的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源软件 Apache Dubbo 牵手
- 下一篇: 【从入门到放弃-Java】并发编程-NI