1. 程式人生 > >解決liunx的Slab佔用比較高的有關問題

解決liunx的Slab佔用比較高的有關問題

最近經常報記憶體超過80%的閥值.

統計了下記憶體實際使用只有1.6G,希望能幫我們分析下為什麼記憶體的使用率顯示使用了3178M.

-bash-3.2$ ps -eo 'pid,rss' --sort=-rss (Not all processes could be identified, non-owned process info  will not be shown, you would have to be root to see it all.)   PID   RSS 20872 732320  5030 617408 15583 219672 15320 15940  9654 10088  1846  9100  8580  8748  9665  8588  3938  8304  2711  3996  8575  3276  7753  3260 19912  2464  2689  2140 14368  2036 28490  1968  2690  1800  7755  1748  7756  1568  2049  1548  2429  1480  1841  1304  2588  1304 23519  1212 23559  1176  2687  1052  8587  1048  8592  1040  2386   888  1897   864  8593   856  1833   808  8588   804  8594   740  8590   736 29128   672  2526   652     1   648  1842   648  1788   584  1946   572  1864   568  1856   556  1806   448  2558   416  2559   416  2562   416  2585   416  2586   416  2587   416   450   368  1791   332  2405   284     2     0     3     0     4     0     5     0     6     0     7     0     8     0     9     0    10     0    45     0    50     0    51     0    52     0    97     0    98     0   101     0   103     0   177     0   180     0   181     0   182     0   318     0   331     0   332     0   360     0   361     0   362     0   372     0   391     0   417     0  1339     0  1340     0  1341     0  1368     0  6460     0  6468     0 然後統計 rss列的記憶體總數是1,680M 遠小於顯示使用的3G.請問那部分記憶體被什麼程式佔用了? 確認應用程序佔用記憶體不多,可以安裝工具atop,或者執行命令cat /proc/meminfo |grep -i slab看看slab佔用的記憶體是否較多。

 
SLAB是Linux作業系統的一種記憶體分配機制。其工作是針對一些經常分配並釋放的物件,您可以看看哪些應用程序的slab佔用的記憶體比較多,是否這些應用需要頻繁的請求和釋放記憶體,比如進行一些小檔案的讀寫。如果都是應用的正常使用,可以考慮升級伺服器記憶體,如果記憶體不足影響業務,需要臨時釋放一下slab佔用的記憶體, 可以參考以下步驟: #echo 2 > /proc/sys/vm/drop_caches 等記憶體回收完畢後再 #echo 0 > /proc/sys/vm/drop_caches 其中drop_caches的4個值有如下含義: 0:不做任何處理,由系統自己管理 1:清空pagecache 2:清空dentries和inodes 3:清空pagecache、dentries和inodes --------------------------------------------------

問題描述

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

問題排查

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

  1. total       used       free     shared    buffers     cached 
  2. Mem:      24675796   24587144      88652          0     357012    1612488 
  3. -/+ buffers/cache:   22617644    2058152 
  4. Swap:      2096472     108224    1988248 

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

然後,接著通過top命令,shift + M按記憶體排序後,觀察系統中使用記憶體最大的程序情況,發現只佔用了18GB記憶體,其他程序均很小,可忽略。

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

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

  1. ...... 
  2. Mapped:          25212 kB 
  3. Slab:          3688732 kB 
  4. PageTables:      43524 kB 
  5. ...... 

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

  1. OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME 
  2. 13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache 
  3. 334040 262056  78%    0.09K   8351       40     33404K buffer_head 
  4. 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的官方文件):

  1. Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free. 
  2. To free pagecache: 
  3. * echo 1 > /proc/sys/vm/drop_caches 
  4. To free dentries and inodes: 
  5. * echo 2 > /proc/sys/vm/drop_caches 
  6. To free pagecache, dentries and inodes: 
  7. * echo 3 > /proc/sys/vm/drop_caches 
  8. 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. 
  9. This tunable was added in 2.6.16. 

2. 方法1需要使用者具有root許可權,如果不是root,但有sudo許可權,可以通過sysctl命令進行設定:

  1. $sync 
  2. $sudo sysctl -w vm.drop_caches=3
  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中有相關的解釋:

  1. 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.  

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

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

sudo strace -fp <pid> -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閾值之間,停止回收。

原文連結:http://www.cnblogs.com/panfeng412/p/drop-caches-under-linux-system.html