1. 程式人生 > >Linux ------清除記憶體中的cache

Linux ------清除記憶體中的cache

首先以Centos6.4的來說,Centos7有些區別

一、buffer/cache/swap的介紹

#cat /etc/redhat-release  #檢視系統版本

CentOS release 6.4 (Final)  

#free -m  #檢視緩衝區及記憶體使用情況

                   total       used       free     shared    buffers     cached

Mem:          7814       7681        132          0         23       5727

-/+ buffers/cache:       1930       5884

Swap:         8191         32       8159

 

先看第二行Mem行:

Mem:          7814       7681        132          0         23       5727  #記憶體總大小為7814MB,使用7681MB,空閒132MB,共享記憶體0M,buffers:23MB,cached:5727MB

然後看地三行-/+ buffers/cache行:

-/+ buffers/cache:       1930       5884   #(-buffers/cache) used記憶體數:1930MB(指的第一部分Mem行中的used – buffers – cached),(+buffers/cache) free記憶體數:5884MB(指的第一部分Mem行中的free + buffers + cached),也就是說-buffers/cache反映的是被程式實實在在吃掉的記憶體,而+buffers/cache反映的是可以挪用的記憶體總數.

然後看第四列Swap行:

Swap:         8191         32       8159 #這也就是我們經常說的虛擬記憶體,8192為swap分割槽的總大小為8192MB,32為swap分割槽的使用為32MB,8159為swap空閒為8159MB。

 

swap分割槽的作用:

Linux核心為了提高讀寫效率與速度,會將檔案在記憶體中進行快取,這部分記憶體就是Cache Memory(快取記憶體)。即使你的程式執行結束後,Cache Memory也不會自動釋放。這就會導致你在Linux系統中程式頻繁讀寫檔案後,你會發現可用實體記憶體變少。當系統的實體記憶體不夠用的時候,就需要將實體記憶體中的一部分空間釋放出來,以供當前執行的程式使用。那些被釋放的空間可能來自一些很長時間沒有什麼操作的程式,這些被釋放的空間被臨時儲存到Swap空間中,等到那些程式要執行時,再從Swap分割槽中恢復儲存的資料到記憶體中。這樣,系統總是在實體記憶體不夠時,才進行Swap交換。所以swap分割槽不被佔用或者佔用很少,說明現在系統記憶體夠用,執行還算良好,不會影響系統執行。

 

首先,當實體記憶體不足以支撐系統和應用程式(程序)的運作時,這個Swap交換分割槽可以用作臨時存放使用率不高的記憶體分頁,把騰出的記憶體交給急需的應用程式(程序)使用。有點類似機房的UPS系統,雖然正常情況下不需要使用,但是異常情況下, Swap交換分割槽還是會發揮其關鍵作用。

其次,即使你的伺服器擁有足夠多的實體記憶體,也有一些程式會在它們初始化時殘留的極少再用到的記憶體分頁內容轉移到 swap 空間,以此讓出實體記憶體空間。對於有發生記憶體洩漏機率的應用程式(程序),Swap交換分割槽更是重要,因為誰也不想看到由於實體記憶體不足導致系統崩潰。

最後,現在很多個人使用者在使用Linux,有些甚至是PC的虛擬機器上跑Linux系統,此時可能常用到休眠(Hibernate),這種情況下也是推薦劃分Swap交換分割槽的。

其實少量使用Swap交換空間是不會影響效能,只有當RAM資源出現瓶頸或者記憶體洩露,程序異常時導致頻繁、大量使用交換分割槽才會導致嚴重效能問題。另外使用Swap交換分割槽頻繁,還會引起kswapd0程序(虛擬記憶體管理中, 負責換頁的)耗用大量CPU資源,導致CPU飆升。



空閒記憶體/已用記憶體換算(也可參考-/+ buffers/cache這行資訊也是記憶體正確使用率):

空閒記憶體=free(132)+buffers(23)+cached(5727)=5882

已用記憶體=total(7814)-空閒記憶體(5882)=1932

 

buffers和cache的區別:

為了提高磁碟存取效率, Linux做了一些精心的設計, 除了對dentry進行快取(用於VFS,加速檔案路徑名到inode的轉換),還採取了兩種主要Cache方式:Buffer Cache和Page Cache。前者針對磁碟塊的讀寫,後者針對檔案inode的讀寫。這些Cache有效縮短了I/O系統呼叫(比如read,write,getdents)的時間。

磁碟的操作有邏輯級(檔案系統)和物理級(磁碟塊),這兩種Cache就是分別快取邏輯和物理級資料的。

Page cache實際上是針對檔案系統的,是檔案的快取,在檔案層面上的資料會快取到page cache。檔案的邏輯層需要對映到實際的物理磁碟,這種對映關係由檔案系統來完成。當page cache的資料需要重新整理時,page cache中的資料交給buffer cache,因為Buffer Cache就是快取磁碟塊的。但是這種處理在2.6版本的核心之後就變的很簡單了,沒有真正意義上的cache操作。

Buffer cache是針對磁碟塊的快取,也就是在沒有檔案系統的情況下,直接對磁碟進行操作的資料會快取到buffer cache中,例如,檔案系統的元資料都會快取到buffer cache中。

Buffer:緩衝區,一個用於儲存速度不同步的裝置或優先順序不同的裝置之間傳輸資料的區域。通過緩衝區,可以使程序之間的相互等待變少,從而使從速度慢的裝置讀入資料時,速度快的裝置的操作程序不發生間斷。

緩衝(buffers)是根據磁碟的讀寫設計的,把分散的寫操作集中進行,減少磁碟碎片和硬碟的反覆尋道,從而提高系統性能。linux有一個守護程序定 期清空緩衝內容(即寫如磁碟),也可以通過sync命令手動清空緩衝。

簡單說來,page cache用來快取檔案資料,buffer cache用來快取磁碟資料。在有檔案系統的情況下,對檔案操作,那麼資料會快取到page cache,如果直接採用dd等工具對磁碟進行讀寫,那麼資料會快取到buffer cache。

所以我們看linux,只要不用swap的交換空間,就不用擔心自己的記憶體太少.如果常常swap用很多,可能你就要考慮加實體記憶體了.這也是linux看記憶體是否夠用的標準.

 

Cache: 快取記憶體,是位於CPU與主記憶體間的一種容量較小但速度很高的儲存器。由於CPU的速度遠高於主記憶體,CPU直接從記憶體中存取資料要等待一定時間周 期,Cache中儲存著CPU剛用過或迴圈使用的一部分資料,當CPU再次使用該部分資料時可從Cache中直接呼叫,這樣就減少了CPU的等待時間,提 高了系統的效率。Cache又分為一級Cache(L1 Cache)和二級Cache(L2 Cache),L1 Cache整合在CPU內部,L2 Cache早期一般是焊在主機板上,現在也都整合在CPU內部,常見的容量有256KB或512KB L2 Cache。

如果 cache 的值很大,說明cache住的檔案數很多。如果頻繁訪問到的檔案都能被cache住,那麼磁碟的讀IO bi會非常小。

快取(cached)是把讀取過的資料儲存起來,重新讀取時若命中(找到需要的資料)就不要去讀硬碟了,若沒有命中就讀硬碟。其中的資料會根據讀取頻率進行組織,把最頻繁讀取的內容放在最容易找到的位置,把不再讀的內容不斷往後排,直至從中刪除。

 

注:下面是Centos7.2系統free -m的顯示:

#free -m

              total        used        free      shared  buff/cache   available

Mem:          64252        2924         258        3233       61069       57654

Swap:          8191         144        8047

 

博文來自:www.51niux.com

二、記憶體檢視命令

2.1 用free加各種引數例如:

命令引數:

-b  以Byte為單位顯示記憶體使用情況。 

-k  以KB為單位顯示記憶體使用情況。 

-m  以MB為單位顯示記憶體使用情況。

-g   以GB為單位顯示記憶體使用情況。 

-o  不顯示緩衝區調節列。 

-s<間隔秒數>  持續觀察記憶體使用狀況。 

-t  顯示記憶體總和列。 

-V  顯示版本資訊。

# free -k -s 1 #顯示單位為KB,然後每一秒重新整理一次。

但是這也只能顯示一個總量,如果記憶體真的是被使用了,我們應該如何查詢哪些程序佔用記憶體過大呢?

2.2 top命令

執行top,然後按shift+M,可以對進行使用記憶體情況從大到小排序

blob.png

 

2.3 ps命令

# ps -aux|sort -k 4 -n  #為了檢視方便,讓其從小到大排序

blob.png

第一列:USER  使用者名稱

第二列:PID 程序ID

第三列:%CPU 程序的cpu佔用率

第四列:%MEM 程序的記憶體佔用率

第五列:VSZ 虛擬記憶體中程序的大小,單位KB

第六列:RSS 程序實際記憶體大小,單位KB

第七列:TTY 與程序關聯的終端(tty)

第八列:STAT 程序的狀態

下面為STAT的狀態碼:

R 執行    Runnable (on run queue)            正在執行或在執行佇列中等待。
S 睡眠    Sleeping                休眠中, 受阻, 在等待某個條件的形成或接受到訊號。
I 空閒    Idle
Z 僵死    Zombie(a defunct process)        程序已終止, 但程序描述符存在, 直到父程序呼叫wait4()系統呼叫後釋放。
D 不可中斷    Uninterruptible sleep (ususally IO)    收到訊號不喚醒和不可執行, 程序必須等待直到有中斷髮生。
T 終止    Terminate                程序收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU訊號後停止執行執行。
P 等待交換頁
W 無駐留頁    has no resident pages        沒有足夠的記憶體分頁可分配。
X 死掉的程序
< 高優先順序程序                    高優先序的程序
N 低優先    級程序                    低優先序的程序
L 記憶體鎖頁    Lock                有記憶體分頁分配並縮在記憶體內
s 程序的領導者(在它之下有子程序);
l 多程序的(使用 CLONE_THREAD, 類似 NPTL pthreads)
+ 位於後臺的程序組

第九列:START  程序啟動時間和日期

第十列:TIME  程序使用的總cpu時間

第十一列: COMMAND 正在執行的命令列命令

注:如果要進一步排查記憶體佔用問題,可以用# pstree PID -ap #樹狀圖的顯示程序間的關係,預設PID為1,也就是全部

# ps -eo user,pid,command|grep mysql  #查出mysql的uid

# pstree 3584 -ap  #檢視mysql下面都有哪些程序

blob.png

注:pgrep

pgrep命令以名稱為依據從執行程序佇列中查詢程序,並顯示查詢到的程序id。每一個程序ID以一個十進位制數表示,通過一個分割字串和下一個ID分開,預設的分割字串是一個新行。對於每個屬性選項,使用者可以在命令列上指定一個以逗號分割的可能值的集合

引數: -o:僅顯示找到的最小(起始)程序號; -n:僅顯示找到的最大(結束)程序號; -l:顯示程序名稱; -P:指定父程序號; -g:指定程序組; -t:指定開啟程序的終端; -u:指定程序的有效使用者ID。

# pgrep -l mysqld  

3584 mysqld_safe

3752 mysqld

 

博文來自:www.51niux.com

2.4  #cat /proc/meminfo  #又或者說,我發現系統佔用記憶體不大,記憶體都被快取起來了,想看看記憶體使用的詳細資訊。

#cat /proc/meminfo

MemTotal:        8002048 kB   #所有可用RAM大小(即實體記憶體減去一些預留位和核心的二進位制程式碼大小)

MemFree:          141316 kB   #LowFree和HighFree的綜合,被系統留著未使用的記憶體

Buffers:            3492 kB    #用來給檔案做緩衝大小

Cached:          5850688 kB   #被高速緩衝儲存器(cache memory)用的記憶體的大小

SwapCached:         1004 kB  #被高速緩衝儲存器(cache memory)用的交換空間的大小

Active:          3685356 kB  #在活躍使用中的緩衝或高速緩衝儲存器頁面檔案的大小,除非非常必要否則不會被移作他用.

Inactive:        3634468 kB  # 在不經常使用中的緩衝或高速緩衝儲存器頁面檔案的大小,可能被用於其他途徑.

Active(anon):     760408 kB  

Inactive(anon):   706016 kB

Active(file):    2924948 kB

Inactive(file):  2928452 kB

Unevictable:           0 kB

Mlocked:               0 kB

SwapTotal:       8388600 kB   #交換空間的總大小

SwapFree:        8355464 kB   #未被使用交換空間的大小

Dirty:             60612 kB   #等待被寫回到磁碟的記憶體大小

Writeback:            44 kB  #正在被寫回到磁碟的記憶體大小

AnonPages:       1465384 kB  #未對映頁的記憶體大小

Mapped:            10028 kB  #裝置和檔案等對映的大小

Shmem:               128 kB  

Slab:             393984 kB   #核心資料結構快取的大小,可以減少申請和釋放記憶體帶來的消耗。

SReclaimable:     314272 kB  #可收回Slab的大小

SUnreclaim:        79712 kB   #不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)

KernelStack:        6656 kB

PageTables:        13848 kB  #管理記憶體分頁頁面的索引表的大小。

NFS_Unstable:          0 kB   #不穩定頁表的大小

Bounce:                0 kB

WritebackTmp:          0 kB

CommitLimit:    12389624 kB

Committed_AS:    6404932 kB

VmallocTotal:   34359738367 kB   #可以vmalloc虛擬記憶體大小

VmallocUsed:      291660 kB  #已經被使用的虛擬記憶體大小

VmallocChunk:   34359426484 kB  

HardwareCorrupted:     0 kB

AnonHugePages:    243712 kB

HugePages_Total:       0    #記憶體大頁的總數

HugePages_Free:        0    #記憶體大頁剩餘數量

HugePages_Rsvd:        0

HugePages_Surp:        0

Hugepagesize:       2048 kB  #記憶體大頁的大小(64位作業系統中有2MB/1GB兩種,預設是2MB。)

DirectMap4k:        4096 kB

DirectMap2M:     2084864 kB

DirectMap1G:     6291456 kB

 

博文來自:www.51niux.com

三、手工釋放記憶體區快取(這是隻是記錄,但是不建議操作,本來cache就是為了提升系統性能,是linux區別於windows的優勢所在,緩解磁碟的壓力,如果真有必要可手工釋放一下,也不要永久的的讓cache作用無法發揮)

# sync; echo 1 > /proc/sys/vm/drop_caches  #釋放 pagecache

# sync; echo 2 > /proc/sys/vm/drop_caches    #釋放  dentries 和 inodes:

# sync; echo 3 > /proc/sys/vm/drop_caches  #釋放 pagecache,dentries 和 inodes:

# sync; echo 0 > /proc/sys/vm/drop_caches  #預設0為不釋放,讓系統自己調節

注:

操作前要使用sync,強制將記憶體中內容寫入硬碟,包含已修改的 i-node、已延遲的塊 I/O 和讀寫對映檔案。這一步是確保第二步的安全性。防止資料或操作丟失。

linux核心2.6和核心3系列的區別:

核心2.6的版本執行上述的操作都沒問題的,但是到了核心3系列,就不能執行echo 0 >/proc/sys/vm/drop_caches的操作了,這是一個坑,重啟才能改回去

# echo 0 >/proc/sys/vm/drop_caches

-bash: echo: write error: Invalid argument

# sysctl -a|grep vm.drop_caches  #核心中有這個引數

vm.drop_caches = 3

# sysctl -w vm.drop_caches=0  #也寫不進去,這個在核心2.6系列上面可以的,這也是手工釋放記憶體快取的另一種形式(sysctl -w vm.drop_caches=3)

error: "Invalid argument" setting key "vm.drop_caches"

# sysctl -w vm.drop_caches=1  #執行其他的是沒問題的,但是就是執行0的插入不可以,要重啟伺服器。

vm.drop_caches = 1

 

注:

swap清理:
swapoff -a && swapon -a
注意:這樣清理有個前提條件,空閒的記憶體必須比已經使用的swap空間大。

 

上述只是暫時生效,但是系統重啟後,系統還是按照自己預設的方法去使用快取,有的網友會寫定時任務指令碼晚上去釋放一下記憶體cache,還有一種暴力的永久生效的方法,使cache的作用基本無法發揮。

修改/etc/sysctl.conf 新增如下選項後就不會記憶體持續增加(這些配置摘抄自網上,未做測試,只是記錄一下)
vm.dirty_ratio = 1
vm.dirty_background_ratio=1
vm.dirty_writeback_centisecs=2
vm.dirty_expire_centisecs=3
vm.drop_caches=3
vm.swappiness =100
vm.vfs_cache_pressure=163
vm.overcommit_memory=2
vm.lowmem_reserve_ratio=32 32 8
kern.maxvnodes=3

#下面是相關解釋:

/proc/sys/vm/dirty_ratio

這個引數控制檔案系統的檔案系統寫緩衝區的大小,單位是百分比,表示系統記憶體的百分比,表示當寫緩衝使用到系統記憶體多少的時候,開始向磁碟寫出資料。增大之會使用更多系統記憶體用於磁碟寫緩衝,也可以極大提高系統的寫效能。但是,當你需要持續、恆定的寫入場合時,應該降低其數值,一般啟動上預設是 10。設1加速程式速度

/proc/sys/vm/dirty_background_ratio

這個引數控制檔案系統的pdflush程序,在何時重新整理磁碟。單位是百分比,表示系統記憶體的百分比,意思是當寫緩衝使用到系統記憶體多少的時候,pdflush開始向磁碟寫出資料。增大之會使用更多系統記憶體用於磁碟寫緩衝,也可以極大提高系統的寫效能。但是,當你需要持續、恆定的寫入場合時,應該降低其數值,一般啟動上預設是 5

/proc/sys/vm/dirty_writeback_centisecs

這個引數控制核心的髒資料重新整理程序pdflush的執行間隔。單位是 1/100 秒。預設數值是500,也就是 5 秒。如果你的系統是持續地寫入動作,那麼實際上還是降低這個數值比較好,這樣可以把尖峰的寫操作削平成多次寫操

/proc/sys/vm/dirty_expire_centisecs

這個引數宣告Linux核心寫緩衝區裡面的資料多“舊”了之後,pdflush程序就開始考慮寫到磁碟中去。單位是 1/100秒。預設是 30000,也就是 30 秒的資料就算舊了,將會重新整理磁碟。對於特別過載的寫操作來說,這個值適當縮小也是好的,但也不能縮小太多,因為縮小太多也會導致IO提高太快。建議設定為 1500,也就是15秒算舊。

/proc/sys/vm/drop_caches

釋放已經使用的cache

/proc/sys/vm/page-cluster

該檔案表示在寫一次到swap區的時候寫入的頁面數量,0表示1頁,1表示2頁,2表示4頁。

/proc/sys/vm/swapiness

該檔案表示系統進行交換行為的程度,數值(0-100)越高,越可能發生磁碟交換。

/proc/sys/vm/vfs_cache_pressure

該檔案表示核心回收用於directory和inode cache記憶體的傾向