一、緩存機制介紹
在Linux系統中,為了提高檔案系統性能,核心利用一部分實體記憶體配置設定出緩沖區,用于緩存系統操作和資料檔案,當核心收到讀寫的請求時,核心先去緩存區找是否有請求的資料,有就直接傳回,如果沒有則通過驅動程式直接操作磁盤。
緩存機制優點:減少系統調用次數,降低CPU上下文切換和磁盤通路頻率。
CPU上下文切換:CPU給每個程序一定的服務時間,當時間片用完後,核心從正在運作的程序中收回處理器,同時把程序目前運作狀态儲存下來,然後加載下一個任務,這個過程叫做上下文切換。實質上就是被終止運作程序與待運作程序的程序切換。
Swap用途:Swap意思是交換分區,通常我們說的虛拟記憶體,是從硬碟中劃分出的一個分區。當實體記憶體不夠用的時候,核心就會釋放緩存區(buffers/cache)裡一些長時間不用的程式,然後将這些程式臨時放到Swap中,也就是說如果實體記憶體和緩存區記憶體不夠用的時候,才會用到Swap。
swap清理:swapoff -a && swapon -a
注意:這樣清理有個前提條件,空閑的記憶體必須比已經使用的swap空間大
二、檢視緩存區及記憶體使用情況
對于cpu負載的了解,首先需要搞清楚下面幾個問題:
1)系統load高不一定是性能有問題。
因為Load高也許是因為在進行cpu密集型的計算
2)系統Load高不一定是CPU能力問題或數量不夠。
因為Load高隻是代表需要運作的隊列累計過多了。但隊列中的任務實際可能是耗Cpu的,也可能是耗i/0或者其他因素的。
3)系統長期Load高,解決辦法不是一味地首先增加CPU
因為Load隻是表象,不是實質。增加CPU個别情況下會臨時看到Load下降,但治标不治本。
4)在Load average 高的情況下需要鑒别系統瓶頸到底是CPU不足,還是io不夠快造成或是記憶體不足造成的。
===============================================================================================================
要想獲得伺服器的CPU負載情況,有下面幾種指令:
1)w指令
[root@localhost ~]# w
12:12:41 up 167 days, 20:46, 2 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.1.5 10:01 1.00s 0.11s 0.00s w
root pts/2 192.168.1.5 10:19 1:47m 0.04s 0.04s -bash
2)uptime指令(一般首先會根據最後那個15分鐘的load負載為準)
[root@localhost ~]# uptime
12:12:55 up 167 days, 20:46, 2 users, load average: 0.00, 0.01, 0.05
3)top指令
[root@localhost ~]# top
top - 12:13:22 up 167 days, 20:47, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 272 total, 1 running, 271 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 65759080 total, 58842616 free, 547908 used, 6368556 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 64264884 avail Mem
................
對于第一行的解釋:
12:13:22:表示目前系統時間
167 days, 20:47:表示系統已經運作了167天20小時47分鐘(在這期間沒有重新開機過)
2 users — 目前有2個使用者登入系統
load average: 0.00, 0.01, 0.05:表示load average後面的三個數分别是1分鐘、5分鐘、15分鐘的負載情況
這裡需要注意:
load average資料是每隔5秒鐘檢查一次活躍的程序數,然後按特定算法計算出的數值。
如果這個數除以邏輯CPU的數量,結果高于5的時候就表明系統在超負荷運轉了!!!!!
對上面第三行cpu的狀态的解釋:
us(user cpu time):使用者态使用的cpu時間比。該值較高時,說明使用者程序消耗的 CPU 時間比較多,比如,如果該值長期超過 50%,則需要對程式算法或代碼等進行優化。
sy(system cpu time):系統态使用的cpu時間比。
ni(user nice cpu time):用做nice權重的程序配置設定的使用者态cpu時間比
id(idle cpu time):空閑的cpu時間比。如果該值持續為0,同時sy是us的兩倍,則通常說明系統則面臨着 CPU 資源的短缺。
wa(io wait cpu time):cpu等待磁盤寫入完成時間。該值較高時,說明IO等待比較嚴重,這可能磁盤大量作随機通路造成的,也可能是磁盤性能出現了瓶頸。
hi(hardware irq):硬中斷消耗時間
si(software irq):軟中斷消耗時間
st(steal time):虛拟機偷取時間
以上解釋的這些參數的值加起來是100%。
4)vmstat
[root@localhost ~]# vmstat
procs -----------memory---------------------swap-------io---------system--------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 0 0 1639792 724280 4854236 0 0 4 34 4 0 19 45 35 0 0
解釋說明:
-----------------------------
procs部分的解釋
r 清單示運作和等待cpu時間片的程序數,如果長期大于1,說明cpu不足,需要增加cpu。
b 清單示在等待資源的程序數,比如正在等待I/O、或者記憶體交換等。
-----------------------------
cpu部分的解釋
us 列顯示了使用者方式下所花費 CPU 時間的百分比。us的值比較高時,說明使用者程序消耗的cpu時間多,但是如果長期大于50%,需要考慮優化使用者的程式。
sy 列顯示了核心程序所花費的cpu時間的百分比。這裡us + sy的參考值為80%,如果us+sy 大于 80%說明可能存在CPU不足。
wa 列顯示了IO等待所占用的CPU時間的百分比。這裡wa的參考值為30%,如果wa超過30%,說明IO等待嚴重,這可能是磁盤大量随機通路造成的,也可能磁盤或者
磁盤通路控制器的帶寬瓶頸造成的(主要是塊操作)。
id 列顯示了cpu處在空閑狀态的時間百分比
-----------------------------
system部分的解釋
in 清單示在某一時間間隔中觀測到的每秒裝置中斷數。
cs清單示每秒産生的上下文切換次數,如當 cs 比磁盤 I/O 和網絡資訊包速率高得多,都應進行進一步調查。
-----------------------------
memory部分的解釋
swpd 切換到記憶體交換區的記憶體數量(k表示)。如果swpd的值不為0,或者比較大,比如超過了100m,隻要si、so的值長期為0,系統性能還是正常
free 目前的空閑頁面清單中記憶體數量(k表示)
buff 作為buffer cache的記憶體數量,一般對塊裝置的讀寫才需要緩沖。
cache: 作為page cache的記憶體數量,一般作為檔案系統的cache,如果cache較大,說明用到cache的檔案較多,如果此時IO中bi比較小,說明檔案系統效率比較好。
-----------------------------
swap部分的解釋
si 由記憶體進入記憶體交換區數量。
so由記憶體交換區進入記憶體數量。
-----------------------------
IO部分的解釋
bi 從塊裝置讀入資料的總量(讀磁盤)(每秒kb)。
bo 塊裝置寫入資料的總量(寫磁盤)(每秒kb)
5)也可以使用dstat指令檢視cpu資訊
[root@localhost ~]# dstat
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
19 45 35 0 0 0| 30k 265k| 0 0 | 0 0 |9025 12k
9 18 73 0 0 0| 0 144k|2578k 65k| 0 0 |3956 4343
6)可以使用iostat檢視IO負載
[root@localhost ~]# iostat 1 1
Linux 2.6.32-696.16.1.el6.x86_64 (nc-ftp01.kevin.cn) 2017年12月29日 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
19.32 0.00 45.44 0.06 0.26 34.93
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 14.17 29.94 265.17 63120486 558975100
解釋說明:
avg-cpu: 總體cpu使用情況統計資訊,對于多核cpu,這裡為所有cpu的平均值
%user: 在使用者級别運作所使用的CPU的百分比.
%nice: nice操作所使用的CPU的百分比.
%sys: 在系統級别(kernel)運作所使用CPU的百分比.
%iowait: CPU等待硬體I/O時,所占用CPU百分比.
%idle: CPU空閑時間的百分比.
Device段:各磁盤裝置的IO統計資訊
tps: 每秒鐘發送到的I/O請求數.
Blk_read /s: 每秒讀取的block數.
Blk_wrtn/s: 每秒寫入的block數.
Blk_read: 讀入的block總數.
Blk_wrtn: 寫入的block總數.
[root@localhost ~]# iostat -x -k -d 1
Linux 2.6.32-696.el6.x86_64 (centos6-vm02) 01/04/2018 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
scd0 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 0.36 0.36 0.00 0.36 0.00
vda 0.01 0.13 0.04 0.13 0.60 0.89 18.12 0.00 2.78 0.19 3.53 2.55 0.04
dm-0 0.00 0.00 0.04 0.22 0.58 0.88 11.25 0.00 3.27 0.25 3.82 1.61 0.04
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 0.13 0.13 0.00 0.04 0.00
dm-2 0.00 0.00 0.00 0.00 0.00 0.00 7.91 0.00 0.19 0.10 5.00 0.16 0.00
解釋說明:
rrqm/s: 每秒對該裝置的讀請求被合并次數,檔案系統會對讀取同塊(block)的請求進行合并
wrqm/s: 每秒對該裝置的寫請求被合并次數
r/s: 每秒完成的讀次數
w/s: 每秒完成的寫次數
rkB/s: 每秒讀資料量(kB為機關)
wkB/s: 每秒寫資料量(kB為機關)
avgrq-sz:平均每次IO操作的資料量(扇區數為機關)
avgqu-sz: 平均等待處理的IO請求隊列長度
await: 平均每次IO請求等待時間(包括等待時間和處理時間,毫秒為機關)
svctm: 平均每次IO請求的處理時間(毫秒為機關)
%util: 采用周期内用于IO操作的時間比率,即IO隊列非空的時間比率
如果 %util 接近 100%,說明産生的I/O請求太多,I/O系統已經滿負荷,該磁盤可能存在瓶頸。
idle小于70% IO壓力就較大了,一般讀取速度有較多的wait。
同時可以結合vmstat 檢視檢視b參數(等待資源的程序數)和wa參數(IO等待所占用的CPU時間的百分比,高過30%時IO壓力高)
三、buffers和cached解釋
緩存(cached)是把讀取過的資料儲存起來,重新讀取時若命中(找到需要的資料)就不要去讀硬碟了,若沒有命中就讀硬碟。其中的資料會根據讀取頻率進行組織,把最頻繁讀取的内容放在最容易找到的位置,把不再讀的内容不斷往後排,直至從中删除。
緩沖(buffers)是根據磁盤的讀寫設計的,把分散的寫操作集中進行,減少磁盤碎片和硬碟的反複尋道,進而提高系統性能。linux有一個守護程序定期清空緩沖内容(即寫入磁盤),也可以通過sync指令手動清空緩沖。舉個例子吧:我這裡有一個ext2的U盤,我往裡面cp一個3M的MP3,但U盤的燈沒有跳動,過了一會兒(或者手動輸入sync)U盤的燈就跳動起來了。解除安裝裝置時會清空緩沖,是以有些時候解除安裝一個裝置時要等上幾秒鐘。
修改/etc/sysctl.conf中的vm.swappiness右邊的數字可以在下次開機時調節swap使用政策。該數字範圍是0~100,數字越大越傾向于使用swap。預設為60,可以改一下試試。–兩者都是RAM中的資料。
兩者都是RAM中的資料,簡單來說,buffer是即将要被寫入磁盤的,而cache是被從磁盤中讀出來的。
buffer是由各種程序配置設定的,被用在如輸入隊列等方面。一個簡單的例子如某個程序要求有多個字段讀入,在所有字段被讀入完整之前,程序把先前讀入的字段放在buffer中儲存。
cache經常被用在磁盤的I/O請求上,如果有多個程序都要通路某個檔案,于是該檔案便被做成cache以友善下次被通路,這樣可提高系統性能。
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。它是根據程式的局部性原理而設計的,就是cpu執行的指令和通路的資料往往在集中的某一塊,是以把這塊内容放入cache後,cpu就不用在通路記憶體了,這就提高了通路速度。當然若cache中沒有cpu所需要的内容,還是要通路記憶體的。從記憶體讀取與磁盤讀取角度考慮,cache可以了解為作業系統為了更高的讀取效率,更多的使用記憶體來緩存可能被再次通路的資料。
Cache并不是緩存檔案的,而是緩存塊的(塊是I/O讀寫最小的單元);Cache一般會用在I/O請求上,如果多個程序要通路某個檔案,可以把此檔案讀入Cache中,這樣下一個程序擷取CPU控制權并通路此檔案直接從Cache讀取,提高系統性能。
Buffer:緩沖區,一個用于存儲速度不同步的裝置或優先級不同的裝置之間傳輸資料的區域。通過buffer可以減少程序間通信需要等待的時間,當存儲速度快的裝置與存儲速度慢的裝置進行通信時,存儲慢的資料先把資料存放到buffer,達到一定程度存儲快的裝置再讀取buffer的資料,在此期間存儲快的裝置CPU可以幹其他的事情。
Buffer:一般是用在寫入磁盤的,例如:某個程序要求多個字段被讀入,當所有要求的字段被讀入之前已經讀入的字段會先放到buffer中。Buffer是根據磁盤的讀寫設計的,把分散的寫操作集中進行,減少磁盤碎片和硬碟的反複尋道,進而提高系統性能。linux有一個守護程序定期清空緩沖内容(即寫入磁盤),也可以通過sync指令手動清空緩沖。
cache是高速緩存,用于CPU和記憶體之間的緩沖;
buffer是I/O緩存,用于記憶體和硬碟的緩沖;
cache最初用于cpu cache,主要原因是cpu 與memory,由于cpu快,memory跟不上,且有些值使用次數多,是以放入cache中,主要目的是,重複使用,并且一級\二級實體cache速度快,
buffer主要用于disk與 memory,主要是保護硬碟或減少網絡傳輸的次數(記憶體資料表現dataSet).當然也可以提高速度(不會立即寫入硬碟或直接從硬碟中讀出的資料馬上顯示),重複使用,最初最主要的目的是保護disk,
Free中的buffer和cache:(它們都是占用記憶體):
buffer : 作為buffer cache的記憶體,是塊裝置的讀寫緩沖區
cache: 作為page cache的記憶體, 檔案系統的cache
如果 cache 的值很大,說明cache住的檔案數很多。如果頻繁通路到的檔案都能被cache住,那麼磁盤的讀IO bi會非常小。
========================================================
下面通過一些簡單通俗的例子來說明下Cache和Buffer緩存之間的差別:
1)Cache緩存
假設某地發生了自然災害(比如地震),居民缺衣少食,于是派救火車去給若幹個居民點送水。救火車到達第一個居民點,開閘放水,老百姓就拿着盆盆罐罐來接水。假如說救火車在一個居民點停留100分鐘放完了水,然後重新儲水花半個小時,再開往下一個居民點。這樣一個白天來來來回回的,也就是4-5個居民點。
但我們想想,救火車是何等存在,如果把水龍頭完全打開,其強大的水壓能輕易沖上10層樓以上, 10分鐘就可以把水全部放完。但因為居民是拿盆罐接水,100%打開水龍頭那就是給人洗澡了,是以隻能打開一小部分(比如10%的流量)。但這樣就降低了放水的效率(隻有原來的10%了),10分鐘變100分鐘。
那麼,我們是否能改進這個放水的過程,讓救火車以最高效率放完水、盡快趕往下一個居民點呢?
方法就是:在居民點建蓄水池。
救火車把水放到蓄水池裡,因為是以100%的效率放水,10分鐘結束然後走人。居民再從蓄水池裡一點一點的接水。
我們分析一下這個例子,就可以知道Cache的含義了。
救火車要給居民送水,居民要從救火車接水,就是說居民和救火車之間有互動,有聯系。
但救火車是"高速裝置",居民是"低速裝置",低速的居民跟不上高速的救火車,是以救火車被迫降低了放水速度以适應居民。
為了避免這種情況,在救火車和居民之間多了一層"蓄水池(也就是Cache)",它一方面以100%的高效和救火車打交道,另一方面以10%的低效和居民打交道,這就解放了救火車,讓其以最高的效率運作,而不被低速的居民拖後腿,于是救火車隻需要在一個居民點停留10分鐘就可以了。
是以說,蓄水池是"活雷鋒",把高效留給别人,把低效留給自己。把10分鐘留給救火車,把100分鐘留給自己。
從以上例子可以看出,所謂Cache,就是"為了彌補高速裝置和低速裝置之間的沖突"而設立的一個中間層。因為在現實裡經常出現高速裝置要和低速裝置打交道,結果被低速裝置拖後腿的情況。Cache的存在是為了解決什麼問題?速度太慢了,要加快速度!
以PC為例。CPU速度很快,但CPU執行的指令是從記憶體取出的,計算的結果也要寫回記憶體,但記憶體的響應速度跟不上CPU。CPU跟記憶體說:你把某某位址的指令發給我。記憶體聽到了,但因為速度慢,遲遲不見指令傳回,這段時間,CPU隻能無所事事的等待了。這樣一來,再快的CPU也發揮不了效率。
怎麼辦呢?在CPU和記憶體之間加一塊"蓄水池",也就是Cache(片上緩存),這個Cache速度比記憶體快,從Cache取指令不需要等待。當CPU要讀記憶體的指令的時候先讀Cache再讀記憶體,但一開始Cache是空着的,隻能從記憶體取,這時候的确是很慢,CPU需要等待。但從記憶體取回的不僅僅是CPU所需要的指令,還有其它的、目前不需要的指令,然後把這些指令存在Cache裡備用。CPU再取指令的時候還是先讀Cache,看看裡面有沒有所需指令,如果碰巧有就直接從Cache取,不用等待即可傳回(命中),這就解放了CPU,提高了效率。(當然不會是100%命中,因為Cache的容量比記憶體小)
2)Buffer緩存
比如說吐魯番的葡萄熟了,要用大卡車裝葡萄運出去賣果園的姑娘采摘葡萄,當然不是前手把葡萄摘下來,後手就放到卡車上,而是需要一個中間過程"籮筐":摘葡萄→放到籮筐裡→把籮筐裡的葡萄倒入卡車。也就是說,雖然最終目的是"把葡萄倒入卡車",但中間必須要經過"籮筐"的轉手,這裡的籮筐就是Buffer。是"暫時存放物品的空間"。
注意2個關鍵詞:暫時,空間
再換句話說,為了完成最終目标:把葡萄放入卡車的空間,需要暫時把葡萄放入籮筐的空間。
以BT為例,BT下載下傳需要長時間的挂機,電腦就有可能24小時連軸轉,但BT下載下傳的資料是碎片化的,展現在硬碟寫入上也是碎片化的,因為硬碟是機械尋址器件,這種碎片化的寫入會造成硬碟長時間高負荷的機械運動,造成硬碟過早老化損壞,當年有大量的硬碟因為BT下載下傳而損壞。于是新出的BT軟體在記憶體裡開辟了Buffer,資料暫時寫入Buffer,攢到一定的大小(比如512M)再一次性寫入硬碟,這種"化零為整"的寫入方式大大降低了硬碟的負荷。這就是:為了完成最終目标:把資料寫入硬碟空間,需要暫時寫入Buffer的空間。
3)二者之間的差別總結
Cache和Buffer的相同點:都是2個層面之間的中間層,都是記憶體。
Cache和Buffer的不同點:Cache解決的是時間問題,Buffer解決的是空間問題。
為了提高速度,引入了Cache這個中間層。
為了給資訊找到一個暫存空間,引入了Buffer這個中間層。
為了解決2個不同次元的問題(時間、空間),恰巧取了同一種解決方法:加入一個中間層,先把資料寫到中間層上,然後再寫入目标。
這個中間層就是記憶體“RAM”,既然是存儲器就有2個參數:寫入的速度有多塊(速度),能裝多少東西(容量)
Cache利用的是RAM提供的高讀寫速度,Buffer利用的是RAM提供的存儲容量(空間)。
簡言之:
1. Buffer(緩沖區)是系統兩端處理速度平衡(從長時間尺度上看)時使用的。它的引入是為了減小短期内突發I/O的影響,起到流量整形的作用。比如生産者——消費者問題,他們産生和消耗資源的速度大體接近,加一個buffer可以抵消掉資源剛産生/消耗時的突然變化。
2. Cache(緩存)則是系統兩端處理速度不比對時的一種折衷政策。因為CPU和memory之間的速度差異越來越大,是以人們充分利用資料的局部性(locality)特征,通過使用存儲系統分級(memory hierarchy)的政策來減小這種差異帶來的影響。
3. 假定以後存儲器通路變得跟CPU做計算一樣快,cache就可以消失,但是buffer依然存在。比如從網絡上下載下傳東西,瞬時速率可能會有較大變化,但從長期來看卻是穩定的,這樣就能通過引入一個buffer使得OS接收資料的速率更穩定,進一步減少對磁盤的傷害。
四、手動清理緩存
釋放緩存區記憶體的方法
1)清理pagecache(頁面緩存)
[root@backup ~]# echo 1 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=1
2)清理dentries(目錄緩存)和inodes
[root@backup ~]# echo 2 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=2
3)清理pagecache、dentries和inodes
[root@backup ~]# echo 3 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=3
上面三種方式都是臨時釋放緩存的方法,要想永久釋放緩存,需要在/etc/sysctl.conf檔案中配置:vm.drop_caches=1/2/3,然後sysctl -p生效即可!
另外,可以使用sync指令來清理檔案系統緩存,還會清理僵屍(zombie)對象和它們占用的記憶體
[root@backup ~]# sync
溫馨提示:
上面操作在大多數情況下都不會對系統造成傷害,隻會有助于釋放不用的記憶體。
但是如果在執行這些操作時正在寫資料,那麼實際上在資料到達磁盤之前就将它從檔案緩存中清除掉了,這可能會造成很不好的影響。
那麼如果避免這種事情發生呢?
是以,這裡不得不提一下/proc/sys/vm/vfs_cache_pressure這個檔案,告訴核心,當清理inoe/dentry緩存時應該用什麼樣的優先級。
[root@backup ~]# cat /proc/sys/vm/vfs_cache_pressure
100
vfs_cache_pressure=100 這個是預設值,核心會嘗試重新聲明dentries和inodes,并采用一種相對于頁面緩存和交換緩存比較"合理"的比例。
減少vfs_cache_pressure的值,會導緻核心傾向于保留dentry和inode緩存。
增加vfs_cache_pressure的值,(即超過100時),則會導緻核心傾向于重新聲明dentries和inodes
總之,vfs_cache_pressure的值:
小于100的值不會導緻緩存的大量減少
超過100的值則會告訴核心你希望以高優先級來清理緩存。
其實無論vfs_cache_pressure的值采用什麼值,核心清理緩存的速度都是比較低的。
如果将此值設定為10000,系統将會将緩存減少到一個合理的水準。
======================================================
這裡順便說下自己遇到的一個記憶體問題:
IDC機房有一台專門的備份伺服器,每天淩晨執行多個備份腳本。某天早上突然發現收到很多條zabbix監控報警資訊:這台備份伺服器的記憶體使用了已超過80%!
于是,趕緊登陸這台備份伺服器,使用free指令檢視記憶體使用情況:
[root@backup ~]# free -m
total used free shared buffers cached
Mem: 64181 48585 15596 3 2 18
-/+ buffers/cache: 48564 15617
Swap: 32767 0 3276
确實發現記憶體使用率已超過80%!但是使用"top"指令檢視,發現此時并沒有什麼程序在占用記憶體,并且本機是備份伺服器,隻有晚上執行備份腳本,
其他時間都沒有服務程序在跑!于是嘗試手動釋放記憶體:
[root@backup ~]# echo 1 > /proc/sys/vm/drop_caches
[root@backup ~]# echo 2 > /proc/sys/vm/drop_caches
[root@backup ~]# echo 3 > /proc/sys/vm/drop_caches
[root@backup ~]# sync
發現在執行了上面第三條指令後,記憶體才真正被釋放出來了,其他指令都沒有起到效果。
五、"Cannot allocate memory"問題
啟動伺服器上的tomcat服務,發現啟動後服務沒有起來!檢視日志發現"Cannot allocate memory",記憶體不夠了!
[root@tomcat ~]# /opt/tomcat_b/tomcat_7777/startup.sh start
[root@tomcat ~]# ps -ef|grep tomcat_7777
bxapp 2165 1821 0 11:50 pts/5 00:00:00 grep tomcat_7777
[root@tomcat ~]#
[root@tomcat ~]# cat catalina.out
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000a0000000, 1610612736, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 1610612736 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /opt/tomcat_b/pay-service/hs_err_pid125225.log
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000a0000000, 1610612736, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 1610612736 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /opt/tomcat_b/tomcat_7777/bin/hs_err_pid125352.log
解決"Cannot allocate memory"問題的方法(記憶體不夠,沒法配置設定記憶體):
1)調整系統的記憶體參數
# echo 1 > /proc/sys/vm/overcommit_memory # 臨時修改
# vim /etc/sysctl.conf # 永久修改
vm.overcommit_memory=1
# sysctl -p
2) 調整系統的最大程序數目
檢視系統允許的目前最大程序數
主要是檢視pid_max名額的,pid_max是Linux核心用來限制程序數的一個最大名額。
換言之,即最大允許程序就這麼多,超過了這個設定值,伺服器就挂了("ps -eLf | wc -l"檢視本機器的程序數)
# sysctl kernel.pid_max # centos7系統執行"systemctl kernel.pid_max"指令
kernel.pid_max = 32768
或者
# cat /proc/sys/kernel/pid_max
32768
一般出現 -bash: fork: Cannot allocate memory 本機的程序數應該接近或等于pid_max名額值的。
# echo 65536 > /proc/sys/kernel/pid_max # 臨時修改
# echo "kernel.pid_max=65536" >> /etc/sysctl.conf # 永久修改
# sysctl -p
kernel.pid_max = 65536
3)調整項目部署的tomcat的jvm記憶體參數
在setenv.sh或catalina.sh檔案裡重新調整記憶體,這種情況是設定的過大,包括-Xms2048M、-Xmx2048M、-Xmn512M、-Xss1024K、NewSize=256M、-XX:MaxNewSize=512M 這樣的值,
實體記憶體不夠,把配置調小即可。
4)設定swap或者調大swap記憶體太小。有時系統預設沒有開啟虛拟記憶體,就會經常遇到軟體記憶體不足,運作崩潰的情況。
有時在雲伺服器上(比如阿裡雲),為了減少購買昂貴的記憶體資源,可以暫時使用虛拟記憶體代替(根據運作的程式需求,性能會降低一些)。
swap虛拟記憶體說明和運維注意點:
https://www.cnblogs.com/kevingrace/p/5991604.html
https://www.cnblogs.com/kevingrace/p/5570197.html
1. 檢視記憶體使用情況,發現swap虛拟記憶體空間竟然為0
# free -m
2. 建虛拟記憶體磁盤卷。做法如下:
# dd if=/dev/zero of=/opt/swap bs=1024 count=2048000
# mkswap /opt/swap
# swapon /opt/swap
再次檢視内容,發現swap虛拟記憶體就有了
# free -m
3. 如果想取消檔案虛拟記憶體,即删除swap,做法如下:(當然根據系統配置,也可以保留swap,以後繼續用)。
# swapoff /opt/swap
# rm /opt/swap
4. swap開機挂載
# vim /etc/fstab
/opt/swap swap swap defaults 0 0
上面挂載參數分别為:
裝置檔案或僞檔案系統 挂載點 檔案系統類型 挂載選項 備份頻率 開機自檢次序
===========================================================================
這裡順便說下,阿裡雲伺服器預設沒有開啟虛拟記憶體,經常遇到軟體記憶體不足,運作崩潰的情況。
阿裡雲虛拟機上建立swap虛拟記憶體磁盤卷的做法如下:
大概count=2024288,2G左右,可以視磁盤大小和需求建立。
1. 預設存放在/swap/swapadd,可以是自己的任何目錄。
阿裡雲伺服器預設沒有swap,需要自己建立。
# mkdir /swap
# dd if=/dev/zero of=/swap/swapadd bs=1024 count=2024288
2. 将磁盤卷轉為虛拟記憶體卷
# mkswap /swap/swapadd
3. 啟用虛拟記憶體服務
# swapon /swap/swapadd
4. 這時再檢視記憶體,發現已經開啟了swap虛拟記憶體。即多出來2G左右的swap空間。
# free -m
5. 如果想再關閉虛拟記憶體服務,執行下面指令即可:
# swapoff -v /swap/swapadd
6. 移動虛拟記憶體空間
如果目前的虛存所在的磁盤空間不夠,可以首先關閉虛存服務,将其移動到别的磁盤,再啟用即可。
# swapoff -v /swap/swapadd
# mv /swap/swapadd /mnt/swap
# swapon /swap/swapadd
5)極端情況:沒有足夠記憶體配置設定,導緻機器操作一直處于卡着的情況!
在linux終端裡執行指令時,發現"-bash: fork: Cannot allocate memory:"問題即程序數滿了!!
出現這種情況,主要是因為程序跑滿了,memory被消耗光了,無法再為其他操作配置設定記憶體,包括執行一般操作指令和SSH連接配接配置設定記憶體!
除了上面四種處理方式外,還有一種比較粗暴的的方法,就是重新開機伺服器,注意不是重新開機tomcat!
# init 6
如果執行"init 6"重新開機機器不行,就使用"reboot"或者"init 0"強制重新開機(可能需要多敲幾次)
*************** 當你發現自己的才華撐不起野心時,就請安靜下來學習吧!***************