問題發現
操作系統都用分頁機制來管理物理內存,操作系統將磁盤的一部分划出來作為虛擬內存,由於內存的速度要比磁盤快得多,所以操作系統要按照某種換頁機制將不需要的頁面換到磁盤中,將需要的頁面調到內存中,由於內存持續不足,這個換頁動作持續進行,kswapd0是虛擬內存管理中負責換頁的,當服務器內存不足的時候kswapd0會執行換頁操作,這個換頁操作是十分消耗主機CPU資源的。如果通過top發現該進程持續處於非睡眠狀態,且運行時間較長,可以初步判定系統在持續的進行換頁操作,可以將問題轉向內存不足的原因來排查。
問題描述:kswapd0 進程占用了系統大量 CPU 資源。
處理辦法:Linux 系統通過分頁機制管理內存的同時,將磁盤的一部分划出來作為虛擬內存。而 kswapd0 是 Linux 系統虛擬內存管理中負責換頁的進程。當系統內存不足時,kswapd0 會頻繁的進行換頁操作。而由於換頁操作非常消耗 CPU 資源,所以會導致該進程持續占用較高 CPU 資源。如果通過 top 等監控發現 kswapd0 進程持續處於非睡眠狀態,且運行時間較長並持續占用較高 CPU 資源,則通常是由於系統在持續的進行換頁操作所致。則可以通過 free 、ps 等指令進一步查詢系統及系統內進程的內存占用情況,做進一步排查分析。
kswapd0是什么
Linux uses kswapd for virtual memory management such that pages that have been recently accessed are kept in memory and less active pages are paged out to disk. (what is a page?)…Linux uses manages memory in units called pages. So,the kswapd process regularly decreases the ages of unreferenced pages…and at the end they are paged out(moved out) to disk
kswapd0進程的作用:
它是虛擬內存管理中,負責換頁的,操作系統每過一定時間就會喚醒kswapd ,看看內存是否緊張,如果不緊張,則睡眠。
在 kswapd 中,有2 個閥值,pages_hige 和 pages_low,當空閑內存頁的數量低於 pages_low 的時候,kswapd進程就會掃描內存並且每次釋放出32 個free pages,直到 free page 的數量到達pages_high。
kswapd0 占用過高是因為 物理內存不足,使用swap分區與內存換頁操作交換數據,導致CPU占用過高。
可以通過修改 /etc/sys/vm/swappiness 里面的數值來修改swap分區使用與否,默認 60,數值越大表示更多的使用swap分區
- swap 分區和內存 都有緩存區,緩存的內容為之前使用過的數據,用於加快第二次打開時訪問速度。
- swap分區 可以使用多個交換區(使用多硬盤?) 來加快swap訪問速度
- swap 分區使用的為硬盤的內容,速度比直接訪問內存慢幾千倍
物理內存和虛擬內存
內存的讀寫性能要比硬盤快的多,因此,在設計上會充分利用內存進行數據的讀取和寫入,提高性能,但是內存是有限的,這就引入了物理內存和虛擬內存的概念。
物理內存指通過物理內存條而獲得的內存空間,稱為RAM。
虛擬內存的概念,是為了滿足物理內存不足的情況下,利用磁盤空間虛擬出的一塊邏輯內存,用作虛擬內存的磁盤空間被稱為交換空間(swap space)。
就是指將硬盤的一塊區域划分來作為內存。內存主要作用是在計算機運行時為操作系統和各種程序提供臨時儲存。當物理內存不足時,可以用虛擬內存代替。
vm.swappiness是Linux內核的一個參數,范圍是0~100。它表示實際內存和虛擬內存區域進行數據交換的傾向性大小,數值越大表示傾向性越大,即交換的頁面文件越多,反之亦然。一般默認值為60。可用'cat /proc/sys/vm/swappiness’查看。
Linux會在物理內存不足的時,使用交換分區的虛擬內存,也就是說,內核會將暫時不用的內存塊信息寫到交換空間,以釋放物理內存。
Linux的內存管理采取的是分頁存取機制,為了保證物理內存能得到充分的利用,內核會在適當的時候將物理內存中不經常使用的數據塊自動交換到虛擬內存中,而將經常使用的信息保留到物理內存。swap si/so 交換區的換進換出。
所有的進程都需要內存,但是不是每個進程都需要一直將對象加載到內存中。基於這點,kernel通過將進程的部分或全部內存換出到磁盤上,來釋放物理內存,直到需要再次使用,然后再次讀到內存中。
kernel采用分頁和交換進行內存管理。其中:
- si:將分頁被重新讀取到物理內存。也稱作page-in
- so:將內存的要交換的分頁寫到磁盤上。也稱作page-out
Buffer與Cache
buffer 和 cache都是通過使用物理內存的一部分.
A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use
但是我們平常對系統資源進行監控時看到的buffer cache,其實都是cache,其中,buffer是buffer cache,cache是page cache,例如free命令中展示的結果:

Mem是物理內存統計,如上面顯示的,total表示物理內存總量是8006M,used表示總計分配給緩存(包括buffers和cached的)使用的數量,但其中可能部分緩存並未實際使用。
used使用的內存有7253M,free未被分配的內存為752M,共享內存shared 一般系統不會用到,總是0。
Buffer是系統分配但未被使用的buffer數量有183M,cache是系統分配但未被使用的cache數量有5153M,關系:total(8006M) = used(7253M) + free(752M),除去buffer和cache,真正使用的內存即-/+ buffers/cache中顯示的used的值,也就是1934M。
即下面的關系:
(-buffers/cache) used內存數:1934M (指的第一部Mem行中的used–buffers– cached)
(+buffers/cache) free內存數: 6071M (指的第一部分Mem行中的free + buffers + cached) 所以-buffers/cache反映的是被程序實實在在吃掉的內存,而+buffers/cache反映的是可以挪用的內存總數。
Linux2.4.10之前的內核中,分兩種disk cache, 分別為buffer cache和page cache。
但在2.4.10后的內核,buffer cache已經不存在了(或者說換了一種數據存放的方法) 而這種頁面的叫法也變了,叫做 buffer page, 而buffer page放在什么地主呢? 它放在page cache中。
總結: 2.4.10之后的內核的disk cache 只有 page cache, 而page cache中有些頁面被叫做buffer page的,是因為這些頁面(buffer page)都有與其相關的buffer_head 描述符,也正是這樣頁面被free 統計為 buffer 占用。
如果沒有buffer_head與該頁相關,則被free統計為 cache占用。
Swap配置對性能的影響
分配太多的Swap空間會浪費磁盤空間,而Swap空間太少,則系統會發生錯誤。如果系統的物理內存用光了,系統就會跑得很慢,但仍能運行;
如果Swap空間用光了,那么系統就會發生錯誤。例如,Web服務器能根據不同的請求數量衍生出多個服務進程(或線程),如果Swap空間用完,則服務進程無法啟動,通常會出現“application is out of memory”的錯誤,嚴重時會造成服務進程的死鎖。因此Swap空間的分配是很重要的。
通常情況下,Swap空間應大於或等於物理內存的大小,最小不應小於64M,通常Swap空間的大小應是物理內存的2-2.5倍。
但根據不同的應用,應有不同的配置:如果是小的桌面系統,則只需要較小的Swap空間,而大的服務器系統則視情況不同需要不同大小的Swap空間。特別是數據庫服務器和Web服務器,隨着訪問量的增加,對Swap空間的要求也會增加,一般來說對於4G 以下的物理內存,配置2倍的swap,4G 以上配置1倍。
另外,Swap分區的數量對性能也有很大的影響。
因為Swap交換的操作是磁盤IO的操作,如果有多個Swap交換區,Swap空間的分配會以輪流的方式操作於所有的Swap,這樣會大大均衡IO的負載,加快Swap交換的速度。
如果只有一個交換區,所有的交換操作會使交換區變得很忙,使系統大多數時間處於等待狀態,效率很低。用性能監視工具就會發現,此時的CPU並不很忙,而系統卻慢。這說明,瓶頸在IO上,依靠提高CPU的速度是解決不了問題的。
解決方案(存疑)
/proc是一個虛擬文件系統,我們可以通過對它的讀寫操作做為與kernel實體間進行通信的一種手段。也就是說可以通過修改/proc中的文件,來對當前kernel的行為做出調整。那么我們可以通過調整/proc/sys/vm/drop_caches來釋放內存。操作如下:
cat1 /proc/sys/vm/drop_caches 0
#drop_caches的值可以是0-3之間的數字,代表不同的含義: #0:不釋放(系統默認值) #1:釋放頁緩存 #2:釋放dentries和inodes #3:釋放所有緩存
手動執行命令
sync
輸入手動釋放內存的命令
echo 1 > /proc/sys/vm/drop_caches
釋放完內存后改回去讓系統重新自動分配內存
echo 0 >/proc/sys/vm/drop_caches
原理:
在Linux系統下,我們一般不需要去釋放內存,因為系統已經將內存管理的很好。
但是凡事也有例外,有的時候內存會被緩存占用掉,導致系統使用SWAP空間影響性能,例如當你在linux下頻繁存取文件后,物理內存會很快被用光,當程序結束后,內存不會被正常釋放,而是一直作為caching。
此時就需要執行釋放內存(清理緩存)的操作了。
Linux系統的緩存機制是相當先進的,他會針對dentry(用於VFS,加速文件路徑名到inode的轉換)、Buffer Cache(針對磁盤塊的讀寫)和Page Cache(針對文件inode的讀寫)進行緩存操作。
但是在進行了大量文件操作之后,緩存會把內存資源基本用光。但實際上我們文件操作已經完成,這部分緩存已經用不到了。
這個時候,我們難道只能眼睜睜的看着緩存把內存空間占據掉嗎?
所以,我們還是有必要來手動進行Linux下釋放內存的操作,其實也就是釋放緩存的操作了。
/proc是一個虛擬文件系統,我們可以通過對它的讀寫操作做為與kernel實體間進行通信的一種手段.
也就是說可以通過修改/proc中的文件,來對當前kernel的行為做出調整.那么我們可以通過調整/proc/sys/vm/drop_caches來釋放內存。
要達到釋放緩存的目的,我們首先需要了解下關鍵的配置文件/proc/sys/vm/drop_caches。這個文件中記錄了緩存釋放的參數,默認值為0,也就是不釋放緩存。
一般復制了文件后,可用內存會變少,都被cached占用了,這是linux為了提高文件讀取效率的做法:
為了提高磁盤存取效率, Linux做了一些精心的設計, 除了對dentry進行緩存(用於VFS,加速文件路徑名到inode的轉換), 還采取了兩種主要Cache方式:Buffer Cache和Page Cache。前者針對磁盤塊的讀寫,后者針對文件inode的讀寫。
這些Cache有效縮短了I/O系統調用(比如read,write,getdents)的時間。
釋放內存前先使用sync命令做同步,以確保文件系統的完整性,將所有未寫的系統緩沖區寫到磁盤中,包含已修改的 i-node、已延遲的塊 I/O 和讀寫映射文件;否則在釋放緩存的過程中,可能會丟失未保存的文件。