天天看點

linux 系統記憶體剩餘記憶體不足,Cache占用過多記憶體導緻Linux系統記憶體不足問題排查...

linux 系統記憶體剩餘記憶體不足,Cache占用過多記憶體導緻Linux系統記憶體不足問題排查...

問題描述

Linux伺服器記憶體使用量超過門檻值,觸發報警。

問題排查

首先,通過free指令觀察系統的記憶體使用情況,顯示如下:

total used free shared buffers cached

Mem: 24675796 24587144 88652 0 357012 1612488

-/+ buffers/cache: 22617644 2058152

Swap: 2096472 108224 1988248

其中,可以看出記憶體總量為24675796KB,已使用22617644KB,隻剩餘2058152KB。

然後,接着通過top指令,shift +

M按記憶體排序後,觀察系統中使用記憶體最大的程序情況,發現隻占用了18GB記憶體,其他程序均很小,可忽略。

是以,還有将近4GB記憶體(22617644KB-18GB,約4GB)用到什麼地方了呢?

進一步,通過cat /proc/meminfo發現,其中有将近4GB(3688732 KB)的Slab記憶體:

......

Mapped: 25212 kB

Slab: 3688732 kB

PageTables: 43524 kB

......

Slab是用于存放核心資料結構緩存,再通過slabtop指令檢視這部分記憶體的使用情況:

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

發現其中大部分(大約3.5GB)都是用于了dentry_cache。

問題解決

1.

修改/proc/sys/vm/drop_caches,釋放Slab占用的cache記憶體空間(參考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權限,如果不是root,但有sudo權限,可以通過sysctl指令進行設定:

$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,調整清理inode/dentry

caches的優先級(預設為100),LinuxInsight中有相關的解釋:

At the default value ofvfs_cache_pressure=100the 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.

具體的設定方法,可以參考方法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

以下記錄的是進一步排查的進展情況。

更深層次的原因

上文排查到Linux系統中有大量的dentry_cache占用記憶體,為什麼會有如此多的dentry_cache呢?

1.

首先,弄清楚dentry_cache的概念及作用:目錄項高速緩存,是Linux為了提高目錄項對象的處理效率而設計的;它記錄了目錄項到inode的映射關系。是以,當應用程式發起stat系統調用時,就會建立對應的dentry_cache項(更進一步,如果每次stat的檔案都是不存在的檔案,那麼總是會有大量新的dentry_cache項被建立)。

2.

目前伺服器是storm叢集的節點,首先想到了storm相關的工作程序,strace一下storm的worker程序發現其中有非常頻繁的stat系統調用發生,而且stat的檔案總是新的檔案名:

sudo strace -fp -e trace=stat

3. 進一步觀察到storm的worker程序會在本地目錄下頻繁的建立、打開、關閉、删除心跳檔案,每秒鐘一個新的檔案名:

sudo strace -fp -e trace=open,stat,close,unlink

以上就是系統中為何有如此多的dentry_cache的原因所在。

一個奇怪的現象

通過觀察/proc/meminfo發現,slab記憶體分為兩部分:

SReclaimable // 可回收的slab

SUnreclaim // 不可回收的slab

當時伺服器的現狀是:slab部分占用的記憶體,大部分顯示的都是SReclaimable,也就是說可以被回收的。

但是通過slabtop觀察到slab記憶體中最主要的部分(dentry_cache)的OBJS幾乎都是ACTIVE的,顯示100%處于被使用狀态。

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狀态呢?求Linux核心達人看到後熱心解釋下:(

會不會由于是ACTIVE狀态,導緻dcache沒有被自動回收釋放掉呢?

讓系統自動回收dcache

上一小節,我們已經提到,伺服器上大部分的slab記憶體是SReclaimable可回收狀态的,那麼,我們能不能交給作業系統讓他在某個時機自動觸發回收操作呢?答案是肯定的。

查了一些關于Linux

dcache的相關資料,發現作業系統會在到了記憶體臨界門檻值後,觸發kswapd核心程序工作才進行釋放,這個門檻值的計算方法如下:

1. 首先,grep low /proc/zoneinfo,得到如下結果:

low 1

low 380

low 12067

2.

将以上3列加起來,乘以4KB,就是這個門檻值,通過這個方法計算後發現目前伺服器的回收門檻值隻有48MB,是以很難看到這一現象,實際中可能等不到回收,作業系統就會hang住沒響應了。

3.

可以通過以下方法調大這個門檻值:将vm.extra_free_kbytes設定為vm.min_free_kbytes和一樣大,則/proc/zoneinfo中對應的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.

舉個例子,當low門檻值被設定為1GB的時候,當系統free的記憶體小于1GB時,觀察到kswapd程序開始工作(程序狀态從Sleeping變為Running),同時dcache開始被系統回收,直到系統free的記憶體介于low門檻值和high門檻值之間,停止回收。