Cassandra的記憶體占用分析
最近,由于我們使用的Cassandra經常因為記憶體不足而挂掉,由于分析了一陣子Cassandra的記憶體占用的機制,總結如下:
預設配置Cassandra的記憶體占用并非是Java的Heap(-Xmx參數控制)加上正常的Linux程序所需的少量記憶體即可,而是還需加上Direct Memory。
假設我們在Cassandra設定MAX_HEAP_SIZE=4096M,但通過ps看到該Java記憶體占用達到6-7G。而根據我的了解, 除了Heap記憶體之外,Java程序還需要其它一些記憶體占用,包括Linux本地程序和Java自身的記憶體占用(如每個線程的棧,靜态代碼區等等)。但這些記憶體占用應該是較少量才合理,而不應該達到2-3G。于是在網上搜尋了一翻,才發現Java自從Nio開始,可以直接存取Linux程序的本地記憶體,稱為Direct Memory。而Cassandra就是利用了這種技術(Cassandra中稱為Off-Heap),導緻之前我用傳統方式對Java記憶體機制的了解總是與實際不符。
該部分記憶體可通過以下配置進行限制以及檢視
-XX:MaxDirectMemorySize=1024M -XX:NativeMemoryTracking=summary
需要檢視Direct Memory時調用:
jcmd [PID] VM.native_memory
Cassandra中檢視記憶體占用的方法
使用nodetool info可以檢視Cassandra中堆記憶體占用情況。但是有些奇怪的是Cassandra中沒有提供檢視Direct Memory的方法(或許是我沒有找到)。
誰是Cassandra記憶體占用的大頭?
之前認為Cassandra作為持久化的資料庫元件,不應該占用過多的記憶體。而我們現網通過反複調整,發現目前穩定的需要6-7G,這個值是相當可觀的,于是有理由分析清楚Cassandra記憶體占用的機制。一般資料庫都有Cache機制,Cassandra也是類似的,Cassandra中是key_cache,row_cache,counter_cache,但這些都不是記憶體的大頭,大頭是memtable。原來Cassandra寫性能很高的原因也是因為memtable。
為何在Cassandra中建立幾百個沒有資料的空表就導緻了記憶體不足?
為了搞清楚memtable的記憶體需求機制,我用MAX_HEAP_SIZE=400M參數下建立了幾百個表,但沒有資料,當表資料達到500個時,Cassandra挂掉了,提示記憶體不足。檢視Cassandra配置項的文檔, 發現memtable_heap_space_in_mb這個配置項可配置總計的memtable記憶體大小,預設是1/4 Heap。但是不了解的是我建立的表是空的,還沒有資料,為何記憶體不足,而且我也沒有看到單獨每一個memtable的配置。搜尋了一翻,在以下連結找到了答案,也就是Cassandra會為每一個memtable配置設定1M的初始空間!連結:http://stackoverflow.com/questions/11151498/what-is-the-impact-of-increase-in-no-of-column-families-of-cassandra-on-heap-uti
另外,如果想檢視每一個表的memtable情況,可使用nodetool cfstats指令
注:Cassandra中Table就等同于Colume Family(簡稱cf)