Cache占用过多内存导致Linux系统内存不足问题排查
問題描述
Linux服務(wù)器內(nèi)存使用量超過閾值,觸發(fā)報(bào)警。
問題排查
首先,通過free命令觀察系統(tǒng)的內(nèi)存使用情況,顯示如下:
total ? ? ? used ? ? ? free ? ? shared ? ?buffers ? ? cached
Mem: ? ? ?24675796 ? 24587144 ? ? ?88652 ? ? ? ? ?0 ? ? 357012 ? ?1612488
-/+ buffers/cache: ? 22617644 ? ?2058152
Swap: ? ? ?2096472 ? ? 108224 ? ?1988248
其中,可以看出內(nèi)存總量為24675796KB,已使用22617644KB,只剩余2058152KB。
然后,接著通過top命令,shift + M按內(nèi)存排序后,觀察系統(tǒng)中使用內(nèi)存最大的進(jìn)程情況,發(fā)現(xiàn)只占用了18GB內(nèi)存,其他進(jìn)程均很小,可忽略。
因此,還有將近4GB內(nèi)存(22617644KB-18GB,約4GB)用到什么地方了呢?
進(jìn)一步,通過cat /proc/meminfo發(fā)現(xiàn),其中有將近4GB(3688732 KB)的Slab內(nèi)存:
......
Mapped: ? ? ? ? ?25212 kB
Slab: ? ? ? ? ?3688732 kB
PageTables: ? ? ?43524 kB
......
Slab是用于存放內(nèi)核數(shù)據(jù)結(jié)構(gòu)緩存,再通過slabtop命令查看這部分內(nèi)存的使用情況:
OBJS ACTIVE ?USE OBJ SIZE ?SLABS OBJ/SLAB CACHE SIZE NAME
13926348 13926348 100% ? ?0.21K 773686 ? ? ? 18 ? 3494744K dentry_cache
334040 262056 ?78% ? ?0.09K ? 8351 ? ? ? 40 ? ? 33404K buffer_head
151040 150537 ?99% ? ?0.74K ?30208 ? ? ? ?5 ? ?120832K ext3_inode_cache
發(fā)現(xiàn)其中大部分(大約3.5GB)都是用于了dentry_cache。
問題解決
1. 修改/proc/sys/vm/drop_caches,釋放Slab占用的cache內(nèi)存空間(參考drop_caches的官方文檔):
Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.
To free pagecache:
* echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
* echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
* echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects are notfreeable, the user should run "sync" first in order to make sure allcached objects are freed.
This tunable was added in 2.6.16.
2. 方法1需要用戶具有root權(quán)限,如果不是root,但有sudo權(quán)限,可以通過sysctl命令進(jìn)行設(shè)置:
$sync
$sudo sysctl -w vm.drop_caches=3
$sudo sysctl -w vm.drop_caches=0 #recovery drop_caches
操作后可以通過sudo sysctl -a | grep drop_caches查看是否生效。
3. 修改/proc/sys/vm/vfs_cache_pressure,調(diào)整清理inode/dentry caches的優(yōu)先級(默認(rèn)為100),LinuxInsight中有相關(guān)的解釋:
At the default value of vfs_cache_pressure = 100 the kernel will attempt to reclaim dentries and inodes at a “fair” rate with respect to pagecache and swapcache reclaim. Decreasing vfs_cache_pressure causes the kernel to prefer to retain dentry and inode caches. Increasing vfs_cache_pressure beyond 100 causes the kernel to prefer to reclaim dentries and inodes. ?
具體的設(shè)置方法,可以參考方法1或者方法2均可。
參考資料
https://www.kernel.org/doc/Documentation/sysctl/vm.txt
http://major.io/2008/12/03/reducing-inode-and-dentry-caches-to-keep-oom-killer-at-bay/
http://linux-mm.org/Drop_Caches
以下記錄的是進(jìn)一步排查的進(jìn)展情況。
更深層次的原因
上文排查到Linux系統(tǒng)中有大量的dentry_cache占用內(nèi)存,為什么會有如此多的dentry_cache呢?
1. 首先,弄清楚dentry_cache的概念及作用:目錄項(xiàng)高速緩存,是Linux為了提高目錄項(xiàng)對象的處理效率而設(shè)計(jì)的;它記錄了目錄項(xiàng)到inode的映射關(guān)系。因此,當(dāng)應(yīng)用程序發(fā)起stat系統(tǒng)調(diào)用時(shí),就會創(chuàng)建對應(yīng)的dentry_cache項(xiàng)(更進(jìn)一步,如果每次stat的文件都是不存在的文件,那么總是會有大量新的dentry_cache項(xiàng)被創(chuàng)建)。
2. 當(dāng)前服務(wù)器是storm集群的節(jié)點(diǎn),首先想到了storm相關(guān)的工作進(jìn)程,strace一下storm的worker進(jìn)程發(fā)現(xiàn)其中有非常頻繁的stat系統(tǒng)調(diào)用發(fā)生,而且stat的文件總是新的文件名:
sudo strace -fp <pid> -e trace=stat3. 進(jìn)一步觀察到storm的worker進(jìn)程會在本地目錄下頻繁的創(chuàng)建、打開、關(guān)閉、刪除心跳文件,每秒鐘一個(gè)新的文件名:
sudo strace -fp <pid> -e trace=open,stat,close,unlink以上就是系統(tǒng)中為何有如此多的dentry_cache的原因所在。
一個(gè)奇怪的現(xiàn)象
通過觀察/proc/meminfo發(fā)現(xiàn),slab內(nèi)存分為兩部分:
SReclaimable // 可回收的slab SUnreclaim // 不可回收的slab當(dāng)時(shí)服務(wù)器的現(xiàn)狀是:slab部分占用的內(nèi)存,大部分顯示的都是SReclaimable,也就是說可以被回收的。
但是通過slabtop觀察到slab內(nèi)存中最主要的部分(dentry_cache)的OBJS幾乎都是ACTIVE的,顯示100%處于被使用狀態(tài)。
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 13926348 13926348 100% 0.21K 773686 18 3494744K dentry_cache 334040 262056 78% 0.09K 8351 40 33404K buffer_head 151040 150537 99% 0.74K 30208 5 120832K ext3_inode_cache為什么顯示可回收的,但是又處于ACTIVE狀態(tài)呢?求Linux內(nèi)核達(dá)人看到后熱心解釋下:(
會不會由于是ACTIVE狀態(tài),導(dǎo)致dcache沒有被自動(dòng)回收釋放掉呢?
讓系統(tǒng)自動(dòng)回收dcache
上一小節(jié),我們已經(jīng)提到,服務(wù)器上大部分的slab內(nèi)存是SReclaimable可回收狀態(tài)的,那么,我們能不能交給操作系統(tǒng)讓他在某個(gè)時(shí)機(jī)自動(dòng)觸發(fā)回收操作呢?答案是肯定的。
查了一些關(guān)于Linux dcache的相關(guān)資料,發(fā)現(xiàn)操作系統(tǒng)會在到了內(nèi)存臨界閾值后,觸發(fā)kswapd內(nèi)核進(jìn)程工作才進(jìn)行釋放,這個(gè)閾值的計(jì)算方法如下:
1. 首先,grep low /proc/zoneinfo,得到如下結(jié)果:
low 1low 380low 120672. 將以上3列加起來,乘以4KB,就是這個(gè)閾值,通過這個(gè)方法計(jì)算后發(fā)現(xiàn)當(dāng)前服務(wù)器的回收閾值只有48MB,因此很難看到這一現(xiàn)象,實(shí)際中可能等不到回收,操作系統(tǒng)就會hang住沒響應(yīng)了。
3. 可以通過以下方法調(diào)大這個(gè)閾值:將vm.extra_free_kbytes設(shè)置為vm.min_free_kbytes和一樣大,則/proc/zoneinfo中對應(yīng)的low閾值就會增大一倍,同時(shí)high閾值也會隨之增長,以此類推。
$ sudo sysctl -a | grep free_kbytes vm.min_free_kbytes = 39847 vm.extra_free_kbytes = 0$ sudo sysctl -w vm.extra_free_kbytes=836787 ######1GB
4. 舉個(gè)例子,當(dāng)low閾值被設(shè)置為1GB的時(shí)候,當(dāng)系統(tǒng)free的內(nèi)存小于1GB時(shí),觀察到kswapd進(jìn)程開始工作(進(jìn)程狀態(tài)從Sleeping變?yōu)镽unning),同時(shí)dcache開始被系統(tǒng)回收,直到系統(tǒng)free的內(nèi)存介于low閾值和high閾值之間,停止回收。
原文鏈接:http://www.cnblogs.com/panfeng412/p/drop-caches-under-linux-system.html
http://www.cnblogs.com/panfeng412/p/drop-caches-under-linux-system-2.html
轉(zhuǎn)載于:https://blog.51cto.com/lucifer119/1364760
總結(jié)
以上是生活随笔為你收集整理的Cache占用过多内存导致Linux系统内存不足问题排查的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: uniapp使用colorUI 组件
 - 下一篇: 无线安全***--启程