【披荊斬棘的開發者】華為云·云享專家向宇:工欲善其事必先利其器,才能做數據的“管家”
717
2025-03-31
內存異常增長的排查經歷
背景介紹
華為云數據庫GaussDB(for Cassandra) 是一款基于計算存儲分離架構,兼容Cassandra生態的云原生NoSQL數據庫;它依靠共享存儲池實現了強一致,保證數據的安全可靠。核心特點是:存算分離、低成本、高性能。
問題描述
GaussDB(for Cassandra)自研架構下遇到一些挑戰性問題,比如cpu過高,內存泄漏,內存異常增長,時延高等問題,這些也都是開發過程中遇到的典型問題。分析內存異常增長是一個比較大的挑戰,內存的異常增長對于程序來說是一個致命的問題,因為其可能觸發OOM,進程異常宕機,業務中斷等結果,所以對內存進行合理的規劃使用及控制就顯得尤為重要。通過調整cache容量,bloom過濾器大小,以及memtable大小等等,實現性能提升,讀寫時延改善等效果。
在線下測試過程中發現內核在長時間運行后,內存只增不減,出現異常增長的情況,懷疑可能存在內存泄漏。
分析&驗證
首先根據內存使用,將內存分為堆內和堆外兩個部分,分別進行該兩塊內存的分析。確定有問題的內存是堆外內存,進一步對堆外內存分析。引入更高效的內存管理工具tcmalloc,解決內存異常增長問題。下面為具體分析驗證過程。
使用jdk的jmap命令和Cassandra的監控(配置jvm.memory.*監控項)等方法,每隔1min采集jvm的堆內內存及進程整體內存。
啟動測試用例,直到內核的整體內存達到上限。分析采集到的堆內內存和進程內存變化曲線,發現其堆內內存仍保持相對穩定,未出現一直持續上漲,但期間內核的整體內存仍然在持續上漲,兩者的增長曲線不符。即問題應該發生在堆外內存。
使用pmap命令打印進程的內存地址空間分布,發現有大量的64MB的內存塊和許多內存碎片,該現象與glibc的內存分配方式有關。堆外內存的使用和進程整體的內存增長趨勢相近,初步懷疑該問題是由堆外內存導致。加之glibc歸還內存的條件苛刻,即內存不易及時釋放,內存碎片多,猜測問題和gblic有關系。當內存碎片過多,空閑內存浪費嚴重,最終進程內存的最大使用量會出現超過預期計劃最大值的可能,甚至出現OOM。
引入tcmalloc內存管理器,代替glibc的ptmalloc內存管理方式。減少過多的內存碎片,提高內存使用效率,本次分析驗證采用gperftools-2.7源碼進行tcmalloc的編譯。運行相同的測試用例,發現內存仍在持續上漲,但是上漲幅度較之前降低,通過pmap打印出該內存地址分布情況,發現之前的小內存塊和內存碎片顯著減小,說明該工具有一定優化效果,印證了前面提到內存碎片過多的猜測。
但是內存異常增長的問題仍然存在,有點像是tcmalloc的回收不及時或者不回收導致。實際上tcmalloc的內存回收是比較 "reluctant" 的,主要是為了當再次需要內存申請時可以直接使用,減少系統調用次數,提高性能。基于此原因,下來進行手動調用其釋放內存接口releasefreememory。發現效果不明顯,原因暫時未知(可能確實存在沒待釋放的空閑內存)。
為驗證該問題,通過設置cache容量的方式進行。
先設置cache的容量為6GB,然后將讀請求壓起來,使cache的6GB容量填滿
修改cache的容量為2GB,為快速是內存釋放,手動調用tcmalloc的releasefreememory接口,發現沒有效果,推測采用tcmalloc之后,內存仍然一直上漲不下跌的原因可能與該接口的有關。
在releasefreememory接口內部的多個地方記錄日志,然后啟動進程再次測試,發現一處報錯是在進行系統調用madvise時有出現失敗。
代碼位置:
報錯日志信息:
通過該處的調用失敗,分析代碼。發現tcmalloc的內存釋放邏輯是“round-robin”,即中間有一個span釋放失敗,則后續待釋放的span被終止,releasefreememory邏輯調用結束。這個就和前面的現象吻合,執行完releasefreememory接口后基本沒有效果,發現每次都是在釋放了幾十MB時,因為該接口的調用失敗導致釋放邏輯終止。
再次分析該系統調用madvise失敗原因。通過給內核的該方法打patch,發現其失敗原因是因為傳入的地址塊對應的內存狀態是LOCKED狀態。導致系統調用失敗,報錯為非法參數。
內存為LOCKED狀態,和該狀態相關的有代碼調用mlock系統方法、系統的ulimit配置。分析相關代碼未發現異常點。查詢系統ulimit配置,發現max locked memory 為unlimited。修改其配置為16MB,重啟Cassandra進程,再次測試,發現內存釋放效果顯著。
繼續運行測試,發現內存持續上漲的情況消失。在業務持續存在的情況下,內存會上漲到最高,不再上漲,保持平穩,符合內存計劃使用量。業務壓力減少甚至停止后,內存出現緩慢下降趨勢。
解決&總結
引入tcmalloc工具,優化內存管理。比較優秀的內存管理器有Google的tcmalloc和Facebook的jemalloc等
修改系統的max locked memory參數配置。
合理分配進程需要使用內存的最大值,并預留一定容量,對于不符合預期增長的內存需要進一步分析。內存相關問題和程序相關性較強。系統的關鍵配置需謹慎,要評估其影響。同時排查了類似的所有配置。
增加releasefreememory的命令,后端進行調用,優化tcmalloc hold內存不釋放問題。不過releasefreememory命令的執行會鎖整個pageHeap,可能導致內存分配請求被hang,所以需要小心執行。
后端增加可動態配置tcmalloc_release_rate的參數,來調整tcmalloc將內存交還給操作系統的頻率。該值的合理范圍是[0-10],0表示永遠不交還,值越大,表示交還的頻率越高,默認值是1
結語
本文通過分析開發過程中遇到的內存增長問題,使用更優秀的內存管理工具,以及更細粒度的內存監控,更直觀的監控數據庫運行期間的內存狀態,確保數據庫平穩高性能運行。
產品首頁:https://www.huaweicloud.com/product/gaussdbforcassandra.html
歡迎加入我們!
華為云GaussDB(for Cassandra)團隊(深圳、西安、杭州)zhaojuan.zhao@huawei.com
云數據庫 GaussDB(for Cassandra) 數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。