Linux服務(wù)器Cache占用過多內(nèi)存導(dǎo)致系統(tǒng)內(nèi)存不足問題的排查解決(續(xù))
作者: 大圓那些事 | 文章可以轉(zhuǎn)載,請以超鏈接形式標(biāo)明文章原始出處和作者信息
網(wǎng)址: http://www.rzrgm.cn/panfeng412/archive/2013/12/17/drop-caches-under-linux-system-2.html
前一篇文章里已經(jīng)描述了具體遇到的問題及一些解決方法。但是還有些疑問點沒有搞清楚,進(jìn)一步學(xué)習(xí)了Linux系統(tǒng)下內(nèi)存的分配使用機(jī)制,這里有兩個資料講的比較全面:
Where is the memory going? Memory waste under Linux
Where is the memory going?Memory usage in the 2.6 kernel
以下記錄的是進(jìn)一步排查的進(jìn)展情況。
更深層次的原因
前一篇文章里排查到Linux系統(tǒng)中有大量的dentry_cache占用內(nèi)存,為什么會有如此多的dentry_cache呢?
1. 首先,弄清楚dentry_cache的概念及作用:目錄項高速緩存,是Linux為了提高目錄項對象的處理效率而設(shè)計的;它記錄了目錄項到inode的映射關(guān)系。因此,當(dāng)應(yīng)用程序發(fā)起stat系統(tǒng)調(diào)用時,就會創(chuàng)建對應(yīng)的dentry_cache項(更進(jìn)一步,如果每次stat的文件都是不存在的文件,那么總是會有大量新的dentry_cache項被創(chuàng)建)。
2. 當(dāng)前服務(wù)器是storm集群的節(jié)點,首先想到了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=stat
3. 進(jìn)一步觀察到storm的worker進(jìn)程會在本地目錄下頻繁的創(chuàng)建、打開、關(guān)閉、刪除心跳文件,每秒鐘一個新的文件名:
sudo strace -fp <pid> -e trace=open,stat,close,unlink
以上就是系統(tǒng)中為何有如此多的dentry_cache的原因所在。
一個奇怪的現(xiàn)象
通過觀察/proc/meminfo發(fā)現(xiàn),slab內(nèi)存分為兩部分:
SReclaimable // 可回收的slab SUnreclaim // 不可回收的slab
當(dāng)時服務(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沒有被自動回收釋放掉呢?
讓系統(tǒng)自動回收dcache
上一小節(jié),我們已經(jīng)提到,服務(wù)器上大部分的slab內(nèi)存是SReclaimable可回收狀態(tài)的,那么,我們能不能交給操作系統(tǒng)讓他在某個時機(jī)自動觸發(fā)回收操作呢?答案是肯定的。
查了一些關(guān)于Linux dcache的相關(guān)資料,發(fā)現(xiàn)操作系統(tǒng)會在到了內(nèi)存臨界閾值后,觸發(fā)kswapd內(nèi)核進(jìn)程工作才進(jìn)行釋放,這個閾值的計算方法如下:
1. 首先,grep low /proc/zoneinfo,得到如下結(jié)果:
low 1 low 380 low 12067
2. 將以上3列加起來,乘以4KB,就是這個閾值,通過這個方法計算后發(fā)現(xiàn)當(dāng)前服務(wù)器的回收閾值只有48MB,因此很難看到這一現(xiàn)象,實際中可能等不到回收,操作系統(tǒng)就會hang住沒響應(yīng)了。
3. 可以通過以下方法調(diào)大這個閾值:將vm.extra_free_kbytes設(shè)置為vm.min_free_kbytes和一樣大,則/proc/zoneinfo中對應(yīng)的low閾值就會增大一倍,同時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. 舉個例子,當(dāng)low閾值被設(shè)置為1GB的時候,當(dāng)系統(tǒng)free的內(nèi)存小于1GB時,觀察到kswapd進(jìn)程開始工作(進(jìn)程狀態(tài)從Sleeping變?yōu)镽unning),同時dcache開始被系統(tǒng)回收,直到系統(tǒng)free的內(nèi)存介于low閾值和high閾值之間,停止回收。
浙公網(wǎng)安備 33010602011771號