服務器性能指標(三)——內存使用分析及問題排查

日常的工做中,在衡量服務器的性能時,常常會涉及到幾個指標,load、cpu、mem、qps、rt等。每一個指標都有其獨特的意義,不少時候在線上出現問題時,每每會伴隨着某些指標的異常。大部分狀況下,在問題發生以前,某些指標就會提早有異常顯示。java

第一篇文章中,咱們介紹了一個重要的指標就是負載(Load),其中咱們提到Linux的負載高,主要是因爲CPU使用、內存使用、IO消耗三部分構成。任意一項使用過多,都將致使服務器負載的急劇攀升。本文就來分析其中的第二項,內存使用。緩存

什麼是內存

內存是計算機中重要的部件之一,它是與CPU進行溝通的橋樑。計算機中全部程序的運行都是在內存中進行的,所以內存的性能對計算機的影響很是大。服務器

內存(Memory)也被稱爲內存儲器,其做用是用於暫時存放CPU中的運算數據,以及與硬盤等外部存儲器交換的數據。併發

物理內存

物理內存指經過物理內存條而得到的內存空間。即隨機存取存儲器(random access memory,RAM),是與CPU直接交換數據的內部存儲器,也叫主存(內存)。dom

虛擬內存

虛擬內存是計算機系統內存管理的一種技術。它使得應用程序認爲它擁有連續可用的內存(一個連續完整的地址空間),而實際上,它一般是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁盤存儲器上,在須要時進行數據交換(也就是說,當物理內存不足時,可能會借用硬盤空間來充當內存使用)。與沒有使用虛擬內存技術的系統相比,使用這種技術的系統使得大型程序的編寫變得更容易,對真正的物理內存(例如RAM)的使用也更有效率。函數

Swap分區

Swap分區(即交換區)在系統的物理內存不夠用的時候,把硬盤空間中的一部分空間釋放出來,以供當前運行的程序使用。那些被釋放的空間可能來自一些很長時間沒有什麼操做的程序,這些被釋放的空間被臨時保存到Swap分區中,等到那些程序要運行時,再從Swap分區中恢復保存的數據到內存中。工具

程序運行時的數據加載,線程併發,I/O緩衝等等,都依賴於內存,可用內存的大小,決定了程序是否能正常運行以及運行的性能。性能

查看內存使用狀況

在Linux機器上,有多個命令均可以查看機器的內存信息。其中包括free、top等。spa

free命令

free命令能夠顯示Linux系統中空閒的、已用的物理內存swap分區以及被內核緩衝區內存。在Linux系統監控的工具中,free命令是最常用的命令之一。操作系統

$free
             total       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392
-/+ buffers/cache:    1272576    7116032
Swap:     16777208          0   16777208
複製代碼

上圖中,一共有3行6列數據,行數據的意義以下: Mem 行是內存的使用狀況。 -/+ buffers/cache 行是物理內存的緩存統計狀況。 Swap 行是交換空間的使用狀況。

前面分別介紹過了物理內存和Swap分區。這裏再介紹一下buffers和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.

簡單點說:

buffers 就是存放要輸出到disk(塊設備)的數據,緩衝滿了一次寫,提升IO性能(內存 -> 磁盤)

cached 就是存放從disk上讀出的數據,經常使用的緩存起來,減小IO(磁盤 -> 內存)

buffer 和 cache,二者都是RAM中的數據。簡單來講,buffer是即將要被寫入磁盤的,cache是被從磁盤中讀出來的。

介紹完了buffer和cache的區別,接下來分析下free命令查詢到的數據。

Mem行

total       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392
複製代碼

這一行展現物理內存的總體狀況。

Total:8388608。表示物理內存總大小。

Used :2926968。表示總計分配給緩存(包含buffers 與cache )使用的數量,但其中可能部分緩存並未實際使用。

Free :5461640。表示未被分配的內存。

Shared:0。共享內存,通常系統不會用到。

Buffers:0。系統分配但未被使用的buffers 數量。

Cached:1654392。系統分配但未被使用的cache 數量。

total(Mem) = used(Mem) + free(Mem)

-/+ buffers/cache 行

total       used       free     shared    buffers     cached
-/+ buffers/cache:    1272576    7116032
複製代碼

Used:1272576。 表示實際使用的buffers 與cache 總量,也是實際使用的內存總量。

Free:7116032。 未被使用的buffers 與cache 和未被分配的內存之和,這就是系統當前實際可用內存。

used(-/+ buffers/cache) = used(Mem) - cached(Mem) - buffers(Mem)

free(-/+ buffers/cache) = free(Mem) + cached (Mem)+ buffers(Mem)

Swap 行

$free
             total       used       free     shared    buffers     cached
Swap:     16777208          0   16777208
複製代碼

Total:16777208。Swap內存總大小。

Used:0。表示已分配的Swap大小。

Free:16777208。表示未被分配的內存。

接下來,再來總體看一下數據

$free
             total       used       free     shared    buffers     cached
Mem:       8388608    2926968    5461640          0          0    1654392
-/+ buffers/cache:    1272576    7116032
Swap:     16777208          0   16777208
複製代碼

機器上實際可用內存大小:

Free(-/+ buffers/cache)= Free(Mem)+buffers(Mem)+Cached(Mem);

                               7116032 = 5461640 + 0+ 1654392
複製代碼

已經分配的內存大小:

Used(Mem) = Used(-/+ buffers/cache)+ buffers(Mem) + Cached(Mem)

          2926968 = 1272576 + 0 + 1654392
複製代碼

物理內存總大小

total(Mem) = used(-/+ buffers/cache) + free(-/+ buffers/cache)

                 8388608 = 1272576 + 7116032
複製代碼

總結一下,整個機器的總內存大小8388608,其中已經分配的內存有2926968,還未分配的內存有5461640。而分配的2926968中,有1654392尚未使用,有1272576已經用掉了。當前機器中還有7116032內存可使用。

free命令參數

-m 以M爲單位顯示內存

$free -m
             total       used       free     shared    buffers     cached
Mem:          8192       2802       5389          0          0       1559
-/+ buffers/cache:       1243       6948
Swap:        16383          0      16383
複製代碼

-g 以G爲單位顯示內存

$free -g
             total       used       free     shared    buffers     cached
Mem:          8          2          5         0         0           1
-/+ buffers/cache:       1          6
Swap:        16          0          16
複製代碼

-s 2持續的觀察內存的情況,每隔2秒打印一次

$free -s 2
         total       used       free     shared    buffers     cached
Mem:       8388608    2873128    5515480          0          0    1600588
-/+ buffers/cache:    1272540    7116068
Swap:     16777208          0   16777208

             total       used       free     shared    buffers     cached
Mem:       8388608    2873168    5515440          0          0    1600628
-/+ buffers/cache:    1272540    7116068
Swap:     16777208          0   16777208
複製代碼

除了free ,還能夠在Linux下可使用/proc/meminfo文件查看操做系統內存的使用狀態,其實,free命令的內容也是來自於/proc/meminfo文件。

top命令

top命令是Linux下經常使用的性能分析工具,可以實時顯示系統中各個進程的資源佔用情況,相似於Windows的任務管理器。

在前面兩篇文章中介紹過使用top命令查看Load Avg和CPU利用率。top還會打印的一部分信息就是內存狀況。

top - 17:49:32 up 2 days,  6:25,  1 user,  load average: 0.01, 0.09, 0.12
Tasks:  30 total,   1 running,  29 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.1%us,  0.0%sy,  0.0%ni, 88.0%id,  3.8%wa,  0.0%hi,  0.0%si,  8.1%st
Mem:   8388608k total,  2884716k used,  5503892k free,        0k buffers
Swap: 16777208k total,        0k used, 16777208k free,  1612080k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 85690 admin     20   0 5138m 1.1g  47m S  2.3 13.9  93:28.92 java
複製代碼

上面的Mem行和Swap行展現的就是內存的使用狀況。而且也會按照進行展現不一樣進程的內存佔用狀況。十分好用。

Java Web應用內存佔用飆高排查思路

JVM以一個進程(Process)的身份運行在Linux系統上,對於Linux來講,JVM不過是一個具備自助管理內存的乖孩子而已。

通常在應用啓動時均可以經過JVM參數來設置JVM內存的大小。若是超過這個限制就會拋出異常。因此,咱們比較常見的內存佔用太高問題,最顯著的現象就是拋出各類OutOfMemoryError。

有一種可能致使直接內存,也就是Linux的物理內存太高的狀況,就是NIO的使用。NIO引入了一種基於通道與緩衝區的IO方式,他可使用Native函數庫直接分配堆外內存,而後經過一個存儲在Java堆中的DirectByteBuffer對象做爲這塊內存的引用進行操做。

因此,在使用NIO的時候,要特別當心,避免致使機器內存被擠滿。

致使JVM中內存佔用飆高的緣由可能有不少。最多見的就是內存泄露。

內存泄露排查思路

一、使用top命令,查看佔用內存較高的進程ID。

➜  ~ top

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
3331 admin     20   0 7127m 2.6g  38m S 10.7 90.6  10:20.26 java
複製代碼

發現PID爲3331的進程佔用內存 90.6%。並且是一個Java進程,基本判定是程序問題。

二、使用jmap查看內存狀況,並分析是否存在內存泄露。

jmap -heap 3331:查看java 堆(heap)使用狀況

jmap -histo 3331:查看堆內存(histogram)中的對象數量及大小

jmap -histo:live 3331:JVM會先觸發gc,而後再統計信息

jmap -dump:format=b,file=heapDump 3331:將內存使用的詳細狀況輸出到文件
複製代碼

獲得堆dump文件後,能夠進行對象分析。若是有大量對象在持續被引用,並無被釋放掉,那就產生了內存泄露,就要結合代碼,把不用的對象釋放掉。

wechat

參考資料

Linux 內存 buffer 和 cache 的區別

相關文章
相關標籤/搜索