前幾天遇到的一個問題,自己本地用VM配置的虛擬機,一般會top查看進程以及CPU占用的一些情況。又一次用laravel 打印對象,里面的內容比較多,瀏覽器當時就卡了。
然后看進程的情況。我以為會是nginx和php-fpm 這兩個一半一半這樣子的情況,結果發現 kswapd0 這個進程直接99%。然后馬上又降下去了。前幾天一直沒時間找原因,今天抽出點時間把這個整理下。
總結下:
swap分區的作用是當物理內存不足時,會將一部分硬盤當做虛擬內存來使用。
kswapd0 占用過高是因為 物理內存不足,使用swap分區與內存換頁操作交換數據,導致CPU占用過高。
可以通過修改 /etc/sys/vm/swappiness 里面的數值來修改swap分區使用與否,默認 60,數值越大表示更多的使用swap分區
swap 分區和內存 都有緩存區,緩存的內容為之前使用過的數據,用於加快第二次打開時訪問速度。
swap分區 可以使用多個交換區(使用多硬盤?) 來加快swap訪問速度
swap 分區使用的為硬盤的內容,速度比直接訪問內存慢幾千倍
真正使用的內存 used -(buffers+ cached) buuffer和cached部分作為緩存,可以使用命中率的方式提高使用效率,而且這部分緩存是根據指令隨時可以釋放的,
我們可以認為這部分內存沒有實際被使用,也可以認為它是空閑的。
Cache:高速緩存,是位於CPU與主內存間的一種容量較小但速度很高的存儲器。
Cache:高速緩存,是位於CPU與主內存間的一種容量較小但速度很高的存儲器。 Buffer:緩沖區,一個用於存儲速度不同步的設備或優先級不同的設備之間傳輸數據的區域。通過緩沖區,可以使進程之間的相互等待變少,從而使從速度慢的設備讀入數據時,速度快的設備的操作進程不發生間斷。 通俗點: cache是高速緩存,用於CPU和內存之間的緩沖; buffer是I/O緩存,用於內存和硬盤的緩沖
操作系統都用分頁機制來管理物理內存,操作系統將磁盤的一部分划出來作為虛擬內存,由於內存的速度要比磁盤快得多,所以操作系統要按照某種換頁機制將不需要的頁面換到磁盤中,將需要的頁面調到內存中,由於內存持續不足,這個換頁動作持續進行,kswapd0是虛擬內存管理中負責換頁的,當服務器內存不足的時候kswapd0會執行換頁操作,這個換頁操作是十分消耗主機CPU資源的。如果通過top發現該進程持續處於非睡眠狀態,且運行時間較長,可以初步判定系統在持續的進行換頁操作,可以將問題轉向內存不足的原因來排查。問題描述:kswapd0 進程占用了系統大量 CPU 資源。處理辦法:Linux 系統通過分頁機制管理內存的同時,將磁盤的一部分划出來作為虛擬內存。而 kswapd0 是 Linux 系統虛擬內存管理中負責換頁的進程。當系統內存不足時,kswapd0 會頻繁的進行換頁操作。而由於換頁操作非常消耗 CPU 資源,所以會導致該進程持續占用較高 CPU 資源。如果通過 top 等監控發現 kswapd0 進程持續處於非睡眠狀態,且運行時間較長並持續占用較高 CPU 資源,則通常是由於系統在持續的進行換頁操作所致。則可以通過 free 、ps 等指令進一步查詢系統及系統內進程的內存占用情況,做進一步排查分析。
physical mem 不足,引起 swap 頻繁讀寫。
kswapd0 是系統的虛擬內存管理程序,如果物理內存不夠用,系統就會喚醒 kswapd0 進程,由 kswapd0 分配磁盤交換空間作緩存,因而占用大量的 CPU 資源。
查看內存及swap使用率:發現還有空余的內存,但是已經開始用swap了。
內存使用到多少開始使用swap?
vm.swappiness 這個內核參數控制
/proc/sys/vm/swappiness
這個交換參數控制內核從物理內存移出進程,移到交換空間。該參數從0到100,當該參數=0,表示只要有可能就盡力避免交換進程移出物理內存;該參數=100,這告訴內核瘋狂的將數據移出物理內存移到swap緩存中。
The defaultvalue I’ve seen on both enterprise level Red Hat and SLES servers is 60.
To find out what the default value is on aparticular server, run:
sysctl vm.swappiness
The value is also located in/proc/sys/vm/swappiness.
PS:設置vm.swappiness=0 后並不代表禁用swap分區,只是告訴內核,能少用到swap分區就盡量少用到,設置vm.swappiness=100的話,則表示盡量使用swap分區,默認的值是60
調整內存參數,當內存使用率不足10%(開始是默認值60)時在使用swap,盡量避免使用swap,減少喚醒軟中斷進程,從而降低ksoftirqd進程對cpu的占用。
關於linux內存分配機制
在linux的內存分配機制中,優先使用物理內存,當物理內存還有空閑時(還夠用),不會釋放其占用內存,就算占用內存的程序已經被關閉了,該程序所占用的內存用來做緩存使用,對於開啟過的程序、或是讀取剛存取過得數據會比較快。
一. 我們先來查看一個內存使用的例子:
[oracle@db1 ~]$ free -m
total used free shared buffers cached
Mem: 72433 67075 5357 0 558 62221
-/+ buffers/cache: 4295 68138
Swap: 72096 91 72004
上述結果顯示了67075M的used,但是(-/+ buffers/cache)減去buffers和cache的結果可以看到,所以當前進程實際占用內存是4296M。
可以這么理解:在linux的內存分配機制中,優先使用物理內存,當物理內存還有空閑時(還夠用),不會釋放其占用內存,就算占用內存的程序已經被關閉了,該程序所占用的內存用來做緩存使用,對於開啟過的程序、或是讀取剛存取過得數據會比較快。
如上面的例子:使用了72433M的內存,67075M被占用,但是buuffer和cached部分作為緩存,可以使用命中率的方式提高使用效率,而且這部分緩存是根據指令隨時可以釋放的,我們可以認為這部分內存沒有實際被使用,也可以認為它是空閑的。
因此查看目前進程正在實際被使用的內存,是used-(buffers+cache),也可以認為如果swap沒有大量使用,mem還是夠用的,只有mem被當前進程實際占用完(沒有了buffers和cache),才會使用到swap的。
二. 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的速度是解決不了問題的。
三. Linux 內存機制
Linux支持虛擬內存(VirtualMmemory),虛擬內存是指使用磁盤當作RAM的擴展,這樣可用的內存的大小就相應地增大了。內核會將暫時不用的內存塊的內容寫到硬盤上,這樣一來,這塊內存就可用於其它目的。當需要用到原始的內容時,它們被重新讀入內存。這些操作對用戶來說是完全透明的;Linux下運行的程序只是看到有大量的內存可供使用而並沒有注意到時不時它們的一部分是駐留在硬盤上的。當然,讀寫硬盤要比直接使用真實內存慢得多(要慢數千倍),所以程序就不會象一直在內存中運行的那樣快。用作虛擬內存的硬盤部分被稱為交換空間(Swap Space)。
一般,在交換空間中的頁面首先被換入內存;如果此時沒有足夠的物理內存來容納它們又將被交換出來(到其他的交換空間中)。如果沒有足夠的虛擬內存來容納所有這些頁面,Linux就會波動而不正常;但經過一段較長的時間Linux會恢復,但此時系統已不可用了。
有時,盡管有許多的空閑內存,仍然會有許多的交換空間正被使用。這種情況是有可能發生的,例如如果在某一時刻有進行交換的必要,但后來一個占用很多物理內存的大進程結束並釋放內存時。被交換出的數據並不會自動地交換進內存,除非有這個需要時。此時物理內存會在一段時間內保持空閑狀態。對此並沒有什么可擔心的,但是知道了是怎么一回事,也就無所謂了。
許多操作系統使用了虛擬內存的方法。因為它們僅在運行時才需要交換空間,以解決不會在同一時間使用交換空間,因此,除了當前正在運行的操作系統的交換空間,其它的就是一種浪費。所以讓它們共享一個交換空間將會更有效率。
注意:如果會有幾個人同時使用這個系統,他們都將消耗內存。然而,如果兩個人同時運行一個程序,內存消耗的總量並不是翻倍,因為代碼頁以及共享的庫只存在一份。
Linux系統常常動不動就使用交換空間,以保持盡可能多的空閑物理內存。即使並沒有什么事情需要內存,Linux也會交換出暫時不用的內存頁面。這可以避免等待交換所需的時間:當磁盤閑着,就可以提前做好交換。可以將交換空間分散在幾個硬盤之上。針對相關磁盤的速度以及對磁盤的訪問模式,這樣做可以提高性能。
與訪問物理內存相比,磁盤的讀寫是很慢的。另外,在相應較短的時間內多次讀磁盤同樣的部分也是常有的事。例如,某人也許首先閱讀了一段E-mail消息,然后為了答復又將這段消息讀入編輯器中,然后又在將這個消息拷貝到文件夾中時,使得郵件程序又一次讀入它。或者考慮一下在一個有着許多用戶的系統中 ls命令會被使用多少次。通過將信息從磁盤上僅讀入一次並將其存於內存中,除了第一次讀以外,可以加快所有其它讀的速度。這叫作磁盤緩沖(Disk Buffering),被用作此目的的內存稱為高速緩沖(Buffer Cache)。但是,由於內存是一種有限而又不充足的資源,高速緩沖不可能做的很大(它不可能包容要用到的所有數據)。當緩沖充滿了數據時,其中最長時間不用的數據將被舍棄以騰出內存空間用於新的數據。
對寫磁盤操作來說磁盤緩沖技術(非緩存)同樣有效。一方面,被寫入磁盤的數據常常會很快地又被讀出(例如,原代碼文件被保存到一個文件中,又被編譯器讀入),所以將要被寫的數據放入緩沖中是個好主意。另一方面,通過將數據放入緩沖中,而不是將其立刻寫入磁盤,程序可以加快運行的速度。以后,寫的操作可以在后台完成,而不會拖延程序的執行。
大多數操作系統都有高速緩沖(盡管可能稱呼不同),但是並不是都遵守上面的原理。有些是直接寫(Write-Through):數據將被立刻寫入磁盤(當然,數據也被放入緩存中)。如果寫操作是在以后做的,那么該緩存被稱為后台寫(Write-Back)。后台寫比直接寫更有效,但也容易出錯:如果機器崩潰,或者突然掉電,緩沖中改變過的數據就被丟失了。如果仍未被寫入的數據含有重要的薄記信息,這甚至可能意味着文件系統(如果有的話)已不完整。
針對以上的原因,出現了很多的日志文件系統,數據在緩沖區修改后,同時會被文件系統記錄修改信息,這樣即使此時系統掉電,系統重啟后會首先從日志記錄中恢復數據,保證數據不丟失。當然這些問題不再本文的敘述范圍。
由於上述原因,在使用適當的關閉過程之前,絕對不要關掉電源,Sync命令傾空(Flushes)緩沖,也即,強迫所有未被寫的數據寫入磁盤,可用以確定所有的寫操作都已完成。在傳統的UNIX系統中,有一個叫做update的程序運行於后台,每隔30秒做一次sync操作,因此通常無需手工使用sync命令了。Linux另外有一個后台程序,Bdflush,這個程序執行更頻繁的但不是全面的同步操作,以避免有時sync的大量磁盤I/O操作所帶來的磁盤的突然凍結。
在Linux中,Bdflush是由update啟動的。通常沒有理由來擔心此事,但如果由於某些原因bdflush進程死掉了,內核會對此作出警告,此時你就要手工地啟動它了(/sbin/update)。
緩存(Cache)實際並不是緩沖文件的,而是緩沖塊的,塊是磁盤I/O操作的最小單元(在Linux中,它們通常是1KB)。這樣,目錄、超級塊、其它文件系統的薄記數據以及非文件系統的磁盤數據都可以被緩沖了。緩沖的效力主要是由它的大小決定的。緩沖太小的話等於沒用。它只能容納一點數據,因此在被重用時,所有緩沖的數據都將被傾空。實際的大小依賴於數據讀寫的頻次、相同數據被訪問的頻率。只有用實驗的方法才能知道。
如果緩存有固定的大小,那么緩存太大了也不好,因為這會使得空閑的內存太小而導致進行交換操作(這同樣是慢的)。為了最有效地使用實際內存,Linux自動地使用所有空閑的內存作為高速緩沖,當程序需要更多的內存時,它也會自動地減小緩沖的大小。
這就是一般情況下Linux內存的一般機制,真正的Linux內存的運行機制遠遠比這個復雜。