linux 内存占用_分享Linux内存占用几个案例
案例一
問題
最近一臺 CentOS 服務器,發現內存無端損失了許多,free 和 ps 統計的結果相差十幾個G,非常奇怪,后來Google了許久才搞明白。
分析
1、linux系統內存消耗主要有三個地方:
- 進程
- slab
- pagecacge
用 free 命令查看到的是系統整體的內容使用情況,而使用 ps 和 top 看到的內存使用情況都是以進程維度來看的,因此看不到 slabcache 和pagecache 的內存占用信息。
2、判斷應用程序是否有內存泄露問題,只根據進程的內存使用或機器的內存變化來判定都不太準確,如果單憑進程的內存變化可能會疏忽一些小對象的內存泄露問題。
同時對于機器的內存的使用也要做是否合理的判斷。對于不同語言的應用都有相應的神器可以輔助定位內存泄露問題,同時結合linux內存的監控工具進行分析, 除了 top,free還有 pmap,/proc/meminfo 和 /slabinfo,slaptop等。
3、通過這個問題,有一點比較重要的是,在使用監控工具進行監控和分析時,對其值的具體含義還是要了解的很清楚,否則會造成誤判,使問題變得更加復雜。
4、此外 page cache,dentries和inodes cache,系統是會自動回收的。
可以通過以下幾種方式加速其回收,不過實際并不需要這么做。
手工清除內存 緩存
- echo 1 > /proc/sys/vm/drop_caches 清除page cache
- echo 2 > /proc/sys/vm/drop_caches 清除denries和inodes
- echo 3 > /proc/sys/vm/drop_caches 清除page cache ,dentries及inodes
- 調整 vm.vfs_cache_pressure 值大小,默認是100。值越大,dentries和inodes cache的回收速度會越快
- 調整 vm.min_free_kbytes 值大小,該值為系統開始內存回收的閥值,越大表示系統會越早開始回收(一般情況下此值不建議調整)。
問題描述和初步調查
$?free?-g這臺服務器有 16G內存,但是結果顯示除了2G左右的文件Buffer緩存外,其余十幾G都被確確實實的用光了。(free按1024進制計算,總內存可能比實際偏小)
這里大概介紹下 free 結果的含義:
然后 top 看了下,沒有特別吃內存的程序。用 ps 大概統計下所有程序占用的總內存:
$?echo?`ps?aux?|awk?'{mem?+=?$6}?END?{print?mem/1024/1024}'`?GB0.595089
結果顯示所有進程占用的內存還不到 1G,實際上,因為free, ps的統計方式的差別和 Copy-on-write 和 Shared libraries等內存優化機制的存在,這兩者的統計結果通常是不一樣的。但是一般情況下絕對不會相差十幾個G,肯定是有什么隱藏的問題,Google了許久后發現,free沒有專門統計另一項緩存: Slab。
Slab 簡介和進一步調查
Slab Allocation 是Kernel 2.2之后引入的一個內存管理機制,專門用于緩存內核的數據對象,可以理解為一個內核專用的對象池,可以提高系統性能并減少內存碎片。(Kernel 2.6.23之后,SLUB成為了默認的allocator)
查看Slab緩存
$?cat?/proc/meminfo#?其中,Slab相關的數據為
Slab:?154212?kB
SReclaimable:?87980?kB
SUnreclaim:?66232?kB
SReclaimable(Linux 2.6.19+) 都是 clean 的緩存,隨時可以釋放。回到之前的內存問題,
查看服務器上Slab占用的內存:
方法1:
$?cat?/proc/meminfo|grep?SlabSlab:?12777668?kB
方法2:
echo?`cat?/proc/meminfo|grep?Slab|awk?'{mem?+=?$2}?END?{print?mem/1024/1024}'`?GB12G
12G的Slab緩存,有意思的是free把Slab緩存統計到了 usedmemory 中,這就是之前那個問題的癥結所在了。另外,還可以查看 /proc/slabinfo (或使用 slabtop 命令)來查看Slab緩存的具體使用情況。
結果發現,ext3_inode_cache 和 dentry_cache 占用了絕大部分內存。考慮到這臺服務器會頻繁地用 rsync 同步大量的文件,這個結果也并不意外。
解決問題
先說明一下,如果問題僅僅是Slab占用了太多的內存(SReclaimable),那么通常不需要太操心,因為這根本不是個問題(如果是SUnreclaim太多且不斷增長,那么很有可能是內核有bug)。但是,如果是因為Slab占用內存太多而引起了其他的問題,建議繼續往下閱讀。
清除Slab可回收緩存
通過 /proc/sys/vm/drop_caches 這個配置項,可以手動清除指定的可回收緩存(SReclaimable)
echo 2 > /proc/sys/vm/drop_caches 或者 sysctl vm.drop_caches=2
上面的命令會主動釋放 Slab 中 clean的緩存(包括inode和dentry的緩存),然后再 free -g 一下,空閑的內存陡增了十幾個G
注意的是,手動清除緩存可能會在一段時間內降低系統性能。原則上不推薦這么做,因為如果有需要,系統會自動釋放出內存供其他程序使用。另外,手動清除Slab緩存是一個治標不治本的辦法。因為問題不在Slab,實際操作的時候發現,清除緩存一段時間后,Slab緩存很快又會反彈回去。
如果需要治本,要么搞定問題進程,要么修改系統配置,要么增加物理內存。
調整系統 vm 配置
風險預警: 調整以下系統配置可能會對系統性能造成負面影響,請仔細測試并謹慎操作。
/etc/sysctl.conf 里有以下幾個對內存管理影響比較大的內核參數配置:
vm.vfs_cache_pressure
系統在進行內存回收時,會先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure 越大,每次回收時,inode cache和dentry cache所占比例越大。
vfs_cache_pressure
默認是100,該值越大inode cache和dentry cache的回收速度會越快,越小則回收越慢,為0的時候完全不回收,內存溢出(OOM!)。
vm.min_free_kbytes
系統的"保留內存"的大小,"保留內存"用于低內存狀態下的"atomic memory allocation requests"(eg. kmalloc + GFP_ATOMIC),該參數也被用于計算開始內存回收的閥值,默認在開機的時候根據當前的內存計算所得,越大則表示系統會越早開始內存回收。vm.min_free_kbytes 過大可能會導致 OOM,太小可能會導致系統出現死鎖等問題。查看默認設置:cat /proc/sys/vm/min_free_kbytes
vm.swappiness
該配置用于控制系統將內存 swap out 到交換空間的積極性,取值范圍是[0, 100]。vm.swappiness 越大,系統的交換積極性越高,默認是60, 如果為0則不會進行交換。
$?vim?/etc/sysctl.confvm.swappiness?=?1
查看默認設置:cat /proc/sys/vm/swappiness
drop_caches
默認值為0,將此值設置為1,2或3,使內核刪除頁面緩存和slab緩存的各種組合。
- 1 系統使所有的頁面緩沖存儲器失效并釋放。
- 2 系統釋放所有未使用的slab緩存內存。
- 3 系統釋放所有的頁面緩存和slab緩存內存。
查看默認設置:cat /proc/sys/vm/drop_caches
注:以上參數設置是非破壞性的操作,由于臟數據不能被釋放,建議設置以上參數的值之前運行sync把內存數據寫入硬盤。在生產環境中不建議使用drop_caches釋放內存。
案例二 (物理內存的外碎片回收)
問題
執行 docker ps 命令掛住
問題分析
查找 /var/log/messages,發現有錯誤信息:XFS: possible memory allocation deadlock in kmem_alloc (mode:0x250)
在linux中使用buddy算法解決物理內存的碎片問題,其把所有空閑的內存,以2的冪次方的形式,分成11個塊鏈表,分別對應為1、2、4、8、16、32、64、128、256、512、1024個頁塊。
Linux支持NUMA技術,對于NUMA設備,NUMA系統的結點通常是由一組CPU和本地內存組成,每一個節點都有相應的本地內存,因此buddyinfo 中的Node0表示節點ID;而每一個節點下的內存設備,又可以劃分為多個內存區域(zone),因此下面的顯示中,對于Node0的內存,又劃分類DMA、Normal、HighMem區域。而后面則是表示空閑的區域。
此處以 Normal 區域進行分析,第二列值為100,表示當前系統中normal區域,可用的連續兩頁的內存大小為1002PAGE_SIZE;第三列值為52,
表示當前系統中normal區域,可用的連續四頁的內存大小為 52*2^2* PAGE_SIZE
$?cat?/proc/buddyinfoNode?0,?zone?DMA?23?15?4?5?2?3?3?2?3?1?0
Node?0,?zone?Normal?149?100?52?33?23?5?32?8?12?2?59
Node?0,?zone?HighMem?11?21?23?49?29?15?8?16?12?2?142
可以看到從第5列開始,只剩下 44*16*PAGE_SIZE 的頁塊,后面剩下的分別是1 * 32 *PAGE_SIZE, 1 * 64 *PAGE_SIZE, 2 *128 * PAGE_SIZE,剩下256,512的頁塊都沒有了因此推測,導致這個問題出現的時候,該機器的內存碎片很多,當某個應用執行時,在xfs的申請內存中有這種連續的大塊的內存申請的操作的請求。
比如:6000: map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS); 就會導致內存一直分配不到。
例如:執行 docker ps,docker exec這些命令時,會一直阻塞在 kmem_alloc 的循環中,反復申請內存,由于內存碎片沒有被組合,因此就一直申請不到,執行這些命令也會卡住,這也就驗證了執行某些命令如ls、ssh都不會失敗(因為需要內存的 PAGE 不是那么大)。
臨時解決方法:
echo 1 > /proc/sys/vm/drop_caches
上述命令操作會把碎片化的 PAGE 重新分配,之后在申請大塊的PAGE內存就可以申請到,不阻塞了。
永久解決方法:
優化內核參數:
#?保留1G空閑內存,達到該值,觸發內存回收$?cat?>>?/etc/sysctl.conf?<vm.min_free_kbytes?=?1048576
EOF
#立即生效
$?sysctl?-p
什么是 overcommit or oom 問題
Linux對大部分申請內存的請求都回復"yes",以便能跑更多更大的程序,因為申請內存后,并不會馬上使用內存,這種技術叫做 Overcommit。
當linux發現內存不足時,會發生OOM killer(OOM=out-of-memory),它會選擇殺死一些進程(用戶態進程,不是內核線程),以便釋放內存。
當 oom-killer 發生時,linux會選擇殺死哪些進程?選擇進程的函數是oom_badness函數(在mm/oom_kill.c中),該函數會計算每個進程的點數(0~1000),點數越高,這個進程越有可能被殺死。
每個進程的點數跟 oom_score_adj 有關,而且 oom_score_adj 可以被設置(-1000最低,1000最高)。
內核參數 overcommit_memory, 它是內存分配策略
可選值:0、1、2。
- 0:表示內核將檢查是否有足夠的可用內存供應用進程使用;如果有足夠的可用內存,內存申請允許;否則,內存申請失敗,并把錯誤返回給應用進程。
- 1:表示內核允許分配所有的物理內存,而不管當前的內存狀態如何。
- 2:表示內核允許分配超過所有物理內存和交換空間總和的內存。
參考鏈接
- https://www.mawenbao.com/research/linux-ate-my-memory.html
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-tunables
- http://blog.51yip.com/nosql/1776.html
- http://linuxperf.com/?p=102
- 案例一原文出處:http://blog.atime.me/research/linux-ate-my-memory.html
- 案例二原文出處:https://www.cnblogs.com/beilong/p/8192676.html
熱門文章推薦
- 如何實現rsync多并發同步?
- Kubernetes YAML 生成器
- Kubernetes 臨時存儲需要限制嗎?
- Harbor v2.0 鏡像回收那些事
- IT運維面試問題總結-數據庫、監控、網絡管理
- 前端本地緩存概況之瀏覽器緩存策略
最后
- 歡迎您加我微信【ypxiaozhan01】,拉您進技術群,一起交流學習...
- 歡迎您關注【YP小站】,學習互聯網最流行的技術,做個專業的技術人...
【文章讓您有收獲,??贊或者在看支持我吧】
總結
以上是生活随笔為你收集整理的linux 内存占用_分享Linux内存占用几个案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我用python是什么梗_Python中
- 下一篇: 线性系统理论知识点总结_线性系统理论(七