問題場景:
今天早上收到報警,系統剩餘內存低於15%;這臺機器運行的服務爲nginx,理論上佔用的內存不會很多,於是進行排查;
查看使用的內存:free -m
查看活躍進程使用的內存:ps aux --sort -rss | head
可以看到free -m使用的內存與前10個活躍進程使用的內存存在較在差距~
問題分析及解決:
通過查閱資料,有可能是slab佔用了內存;
步驟一:安裝atop工具,查看內存的具體使用情況
yum install atop -y
執行命令:atop
可以看到slab佔用了2.6G的內存,確定了引用內存異常的原因是slab
步驟二:查看slab佔用內存的具體情況
執行命令:cat /proc/meminfo | awk '{sum=$2/1024} {print $1 sum " MB"}' | grep claim
SReclaimable:3153.37 MB SUnreclaim:25.0664 MB
SReclaminable:表示可回收的slab佔用的內存
SUnreclaim:表示不可回收的slab佔用的內存
由此猜想,slab可回收的內存可以由系統進行自動回收或者手動回收
步驟三:查看具體是什麼佔用了slab內存
執行命令:slabtop
注:可以看到是dentry佔用大部分的slab內存
slab內存分類:
pagecache
dentries:目錄項高速緩存
inode
slab是Linux操作系統的一種內存分配機制。其工作是針對一些經常分配並釋放的對象,您可以看看哪些應用進程的slab佔用的內存比較多,是否這些應用需要頻繁的請求和釋放內存,比如進行一些小文件的讀寫。如果都是應用的正常使用,可以考慮升級服務器內存,如果內存不足影響業務,需要臨時釋放一下slab佔用的內存;
slab內存的釋放策略:
相關內核參數:vm.drop_caches
參數值含義:
0:不做任何處理,由系統自己管理
1:清空pagecache
2:清空dentries和inodes
3:清空pagecache、dentries和inodes
步驟四:手動回收slab中的可回收內存
#將內存的數據同步到磁盤
sync
#清空slab中可回收的內存
sudo sysctl -w vm.drop_caches=3 或者 echo 3 > /proc/sys/vm/drop_caches
#內存回收後把內核參數改爲原來的值
sudo sysctl -w vm.drop_caches=0 或者 echo 0 > /proc/sys/vm/drop_caches
注:以上修改的方式是臨時生效
相關內核參數:
vm.min_free_kbytes:保留給內核使用的;當到達min,系統會啓動 kswapd 進行內存回收;此參數的默認值爲67584;
可以通過此參數來的值讓系統自動回收slab,但是此參數不宜設置過大;
由此此參數引發的血案:
生產中某臺機器調高了此參數爲1G,當系統free的內存小於1GB時,觀察到kswapd進程開始工作(進程狀態從Sleeping變爲Running),同時dentry_cache開始被系統回收,直到系統free的內存介於low閾值和high閾值之間,停止回收。
如果系統的free內存一直低於1G,則kswapd一直運行,造成系統持續較大壓力!