Linux系統排查1——內存篇


  常見工作中,計算機系統的資源主要包括CPU,內存,硬盤以及網絡,過度使用這些資源將使系統陷入困境。本系列一共四篇博文,結合我在實習期間的學習,介紹一些常見的Linux系統排障工具及方法。

  第1篇——內存篇

  第2篇——CPU篇

  第3篇——磁盤I/O篇

  第4篇——網絡篇

 

  事實上,當上述服務器系統資源中的任何一個遭遇瓶頸,都會帶來服務器性能的下降,典型的症狀就是系統運行遲緩。

  本文從以下幾個角度介紹Linux系統內存相關的排查。

  1. 內存的使用率如何查看,使用率真的很高嗎

  2. 內存用在哪里了

  3. 內存優化可以有哪些手段

 

1. 內存硬件查看

# dmidecode -t memory

# dmideocde -t memory
//以下為命令輸出節選
# dmidecode 2.12
# SMBIOS entry point at 0x7f6be000
SMBIOS 2.5 present.

Handle 0x0005, DMI type 16, 15 bytes
Physical Memory Array
    Location: System Board Or Motherboard
    Use: System Memory
    Error Correction Type: Single-bit ECC
    Maximum Capacity: 192 GB
    Error Information Handle: Not Provided
    Number Of Devices: 18

Handle 0x0010, DMI type 6, 12 bytes
Memory Module Information
    Socket Designation: DIMM06
    Bank Connections: 0 0
    Current Speed: 1 ns
    Type: DIMM
    Installed Size: 8192 MB (Single-bank Connection)
    Enabled Size: 8192 MB (Single-bank Connection)
    Error Status: OK

Handle 0x0011, DMI type 17, 27 bytes
Memory Device
    Array Handle: 0x0005
    Error Information Handle: Not Provided
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB
    Form Factor: DIMM
    Set: None
    Locator: DIMM06
    Bank Locator: BANK06
    Type: Other
    Type Detail: Unknown
    Speed: 800 MHz
    Manufacturer: Hynix
    Serial Number: 5781322C
    Asset Tag: Unknown
    Part Number: HMT31GR7BFR4C-H9

 

  通過dmidecode工具可以查看很多硬件相關的數據,這里僅以內存為例。我們可以看到,服務器最大支持內存擴充為192GB,目前已經安裝了一塊海力士(Hynix)生產的8GB內存,該內存插在主板的第六個DIMM插槽上面(物理插槽又稱socket)。

  該命令能夠給出物理內存的許多詳細信息,本文並不一一介紹。

 

2. 內存的大體使用情況

free -m/-h

  free命令用來查看系統內存的整體使用情況。

# free -m
             total       used       free     shared    buffers     cached
Mem:         11972       6345       5627          1        305       2140
-/+ buffers/cache:       3899       8073
Swap:          856          0        856

   free -m以MB為單位顯示整個系統的內存使用情況,free -h則自動選擇以適合理解的容量單位顯示:

# free -h
             total       used       free     shared    buffers     cached
Mem:           11G       6.2G       5.5G       1.2M       305M       2.1G
-/+ buffers/cache:       3.8G       7.9G
Swap:         856M         0B       856M

   可以看到系統內存12GB(總可用11.7GB),當前已用6.2G,剩余5.5GB。這個例子中我們看到系統的內存使用並不高,但即便free命令顯示的"used"的值很高,接近total的值,那么系統就真的沒有內存空間了嗎?

  我們可以看到free 命令下面有一行“-/+ buffers/cache”,該行顯示的used是上一行“used”的值減去buffers和cached的值,同時該行的free是上一行的free加上buffers和cached的值。這里可以看到,盡管第一行的used顯示共使用了6.2GB的物理內存,但除去buffers和cached數據后,實際僅僅占用了3.8GB的內存,而如果剩余空間加上buffers和cached數據當前占用的內存,將達到8BG之多。

  這是因為buffers和cache數據是動態變化的,內存充足時,內核出於性能考慮會進行一定的緩存,當內存空間不足時,buffers, cached占用的空間是可以為了程序釋放的。

  因此判斷系統內存是否耗竭的實際指標是看減去buffer和cache的空間后used空間是否依舊很大,以及交換空間是否被大量占用。顯然這個例子不符合內存耗竭的情形。

  那么buffers與cached又有什么區別呢?

  (1) buffers:記錄文件系統的metadata,例如目錄里面有什么內容,權限等等;

  (2) cached:用來給文件做緩沖,緩存剛剛訪問的文件。

 

3. 哪些進程消耗內存比較多?

top

  top命令用來查看具體進程消耗的內存空間。

# top
top - 14:45:43 up 35 days, 2:54, 2 users, load average: 0.35, 0.23, 0.21 Tasks: 213 total, 3 running, 210 sleeping, 0 stopped, 0 zombie %Cpu(s): 2.1 us, 2.2 sy, 0.0 ni, 95.3 id, 0.3 wa, 0.0 hi, 0.1 si, 0.0 st KiB Mem: 12260128 total, 6502480 used, 5757648 free, 312864 buffers KiB Swap: 877564 total, 0 used, 877564 free. 2192620 cached Mem

 

  top 命令查看系統的實時負載, 包括進程、CPU負載、內存使用等等;

  進入top的實時界面后,默認按照CPU的使用率排序,通過“shift+m”按鍵將進程按照內存使用情況排序,可以查看哪些進程是當前系統中的內存開銷“大戶”。

  top命令中,按下 f 鍵,進入選擇排序列的界面,這里可以選擇要顯示的信息列,要按照哪些信息列進行排序等,該界面上有簡要的介紹,這里不再贅述。

  可以看到top命令也會顯示系統整體的內存使用情況,同樣包括了total, used, free, buffers, cached等,需要注意的是,這里並沒有像free命令那樣提供-/+ buffers/cached之后的值,因此需要經過額外計算才能獲得當前系統實際剩余的可用內存。

  另一方面,我們查看不同進程的內存開銷,

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND    
 1501 mysql     20   0  655848 309724   9928 S   0.7  2.5 266:53.23 mysqld     
 2816 rabbitmq  20   0 2444216 248528   2612 S   1.7  2.0 868:40.86 beam.smp   
22589 nova      20   0  402236 144884   4084 S   0.0  1.2  17:42.08 nova-api   
22591 nova      20   0  401848 144508   4092 S   0.0  1.2  17:44.65 nova-api   
22590 nova      20   0  401312 143884   4068 S   0.0  1.2  17:47.23 nova-api   
22588 nova      20   0  400592 143260   4080 S   0.0  1.2  17:45.53 nova-api 

  通過%MEM列,可以查看哪幾個進程占用了大量的內存,在緩解內存不足的緊急情況時,可以終止這些占用內存較多的進程。

  top命令中有以下與內存相關的數據列:

  (1)VIRT:虛擬內存,是進程申請的虛擬內存總量;

  (2)RES: 常駐內存,是進程切實使用的物理內存量,free命令中看到的used列下面的值,就包括常駐內存的加總,但不是虛擬內存的加總;

  (3)SHR:共享內存,比如共享庫占用的內存等。

 

 4. 交換空間

# swapon
# swapoff
# mkswap

  使用free命令可以查看內存的總體使用,顯示的內容也包括交換分區的大小,可以使用swapon,swapoff,命令開啟或關閉交換空間,交換空間是磁盤上的文件,並不是真正的內存空間。

例如:關閉交換分區

# swapoff -a
# free
             total       used       free     shared    buffers     cached
Mem:      12260128    6497332    5762796       1256     312980    2191960
-/+ buffers/cache:    3992392    8267736
Swap:            0          0          0

  此時交換分區顯示全為0,說明系統沒有開啟交換分區。swapon命令可以啟用交換分區。

  當內存不足時,系統會選擇通過:1.將部分不常被訪問的內存頁交換到內存空間,或2.刪除部分cache的文件來釋放內存空間。

  系統的可用內存一般等於物理內存 + 交換分區。交換分區在磁盤上, 因此速度比內存讀寫要慢得多。

  交換分區實際上就是磁盤上的文件,可以通過mkswap命令來創建交換空間。

 

5. 內核態內存占用

# slabtop

  slab系統用來處理系統中比較小的元數據,如文件描述符等,進而組織內核態的內存分配。

  一個slab包含多個object,例如dentry這些數據結構就是object,可以通過slabtop命令查看系統中活動的object的數量與內存占用情況,從而了解哪些數據結構最占用內核態的內存空間。

例如:使用slabtop命令查看內核數據結構及內存占用

 Active / Total Objects (% used)    : 1222616 / 1575898 (77.6%)
 Active / Total Slabs (% used)      : 39945 / 39945 (100.0%)
 Active / Total Caches (% used)     : 67 / 125 (53.6%)
 Active / Total Size (% used)       : 276332.00K / 318115.77K (86.9%)
 Minimum / Average / Maximum Object : 0.01K / 0.20K / 15.75K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
848211 516003  60%    0.10K  21749       39     86996K buffer_head
266406 266158  99%    0.19K   6343       42     50744K dentry
 75300  73560  97%    0.63K   3012       25     48192K proc_inode_cache
 70224  70224 100%    0.96K   2128       33     68096K ext4_inode_cache
 56960  56489  99%    0.06K    890       64      3560K kmalloc-64
 52530  50791  96%    0.04K    515      102      2060K ext4_extent_status
 30702  29066  94%    0.19K    731       42      5848K kmalloc-192
 27076  22278  82%    0.55K    967       28     15472K radix_tree_node
 26532  26532 100%    0.11K    737       36      2948K sysfs_dir_cache
 20910  20910 100%    0.05K    246       85       984K shared_policy_node
 12712  12712 100%    0.57K    454       28      7264K inode_cache
 11536  10815  93%    0.07K    206       56       824K anon_vma
  9088   7840  86%    0.03K     71      128       284K kmalloc-32
  6752   3567  52%    0.25K    211       32      1688K kmalloc-256
  6656   6656 100%    0.02K     26      256       104K kmalloc-16
  6560   4747  72%    0.12K    205       32       820K kmalloc-128
  6656   6656 100%    0.02K     26      256       104K kmalloc-16

 

  通常關注1. 哪些數據結構的內存占用最大,2. 哪些類型的數據結構對應的object最多,比如inode多代表文件系統被大量引用等。

  該交互命令支持的選項與排序標准有:

選項:
--delay=n, -d n    每隔n秒刷新信息
--once, -o         只顯示一次
--sort=S, -s S     按照S排序,其中S為排序標准

排序標准(shift + 對應的鍵):
a:根據active objects數量高低排序
b:根據 objects / slab高低來排序
c:根據cache大小排序
l:根據slab數量排序
v:根據active slabs數量排序
n:按 name 排序
o:按照 objects 數量排序
p:按照 pages / slab 的值排序
s:按照 object 大小排序
u:按照 cache 使用量排序

 

 

6. 查看內存使用的動態變化

# vmstat

  vmstat命令可以查看內存使用的動態變化,

例如: 使用vmstat動態監視內存變動

# vmstat  1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 5755120 312980 2192136    0    0     1    33    1    0  5  2 92  1  0
 0  0      0 5755120 312980 2192136    0    0     0     8 2000 2770  1  2 97  0  0
 1  0      0 5755120 312980 2192136    0    0     0    24 2033 2715  1  2 96  1  0
 0  0      0 5755120 312980 2192136    0    0     0     0 1999 2317  1  2 98  0  0
 3  1      0 5754996 312980 2192136    0    0     0     4 2187 3004  6  3 91  0  0

 

  其中# vmstat N 代表每隔N秒更新一次數據。

 

7. dstat

# dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw
  5   2  92   1   0   0|4630B  129k|   0     0 |   0     0 |2246  2808
  2   2  93   4   0   0|   0   708k|  53k 6732k|   0     0 |2091  2828
  1   2  96   1   0   0|   0  8192B|  34k 6595k|   0     0 |2198  2621
  1   2  96   0   0   1|   0    12k|  39k 6898k|   0     0 |2209  2679
  2   2  96   0   0   0|   0  4096B|  44k 7256k|   0     0 |2217  2907
  1   2  97   0   0   0|   0     0 |  38k 7109k|   0     0 |2128  2413
  2   3  94   1   0   0|   0    24k|  37k 7295k|   0     0 |2217  2594
  2   2  96   0   0   0|   0    12k|  36k 7482k|   0     0 |2106  2613
  1   1  97   0   0   0|   0  4096B|  37k 6923k|   0     0 |2255  2516

 

 

8. 查看共享內存空間

pmap

  可以使用pmap命令查看進程使用的共享內存,包括使用的庫,所在堆棧空間等。

# pmap -d 1
1:   /sbin/init
Address           Kbytes Mode  Offset           Device    Mapping
00007fb45d59c000      44 r-x-- 0000000000000000 008:00002 libnss_files-2.19.so
00007fb45d5a7000    2044 ----- 000000000000b000 008:00002 libnss_files-2.19.so
00007fb45d7a6000       4 r---- 000000000000a000 008:00002 libnss_files-2.19.so
00007fb45d7a7000       4 rw--- 000000000000b000 008:00002 libnss_files-2.19.so
00007fb45d7a8000      44 r-x-- 0000000000000000 008:00002 libnss_nis-2.19.so
00007fb45d7b3000    2044 ----- 000000000000b000 008:00002 libnss_nis-2.19.so
00007fb45d9b2000       4 r---- 000000000000a000 008:00002 libnss_nis-2.19.so
00007fb45d9b3000       4 rw--- 000000000000b000 008:00002 libnss_nis-2.19.so

 

  

9. 查看系統內存歷史記錄

# sar

  可以使用sar命令查看一個月以內的內存使用情況。

 

如何清理內存使用

  1. 釋放占用的緩存空間

# sync     //先將內存刷出,避免數據丟失
# echo 1 > /proc/sys/vm/drop_caches //釋放pagecache
# echo 2 > /proc/sys/vm/drop_caches //釋放dentry和inode
# echo 3 > /proc/sys/vm/drop_caches //釋放pagecache、dentry和inode

  2. 終止進程

 

與Linux內存相關的文件系統文件

/proc/meminfo

  內存信息

/proc/$pid/status

  進程狀態信息,

/proc/$pid/statm

  進程物理內存信息

/proc/slabinfo

  slab的分布狀況

/proc/vmstat

  虛擬內存信息

 

一些額外的小技巧

1. 降低swap的使用率:

# sysctl -a | grep swappiness
vm.swappiness = 60

  可以查看當前swap的使用

 

2. 限制其他用戶的內存使用

# vim /etc/security/limits.conf

user1 hard as 1000 (用戶user1所有累加起來,內存不超過1000kiB)
user1 soft as 800 (用戶user1一次運行,內存不超過800kiB)

  

3. 大量連續內存數據:

# vim /etc/sysctl.conf

vm.nr_hugepage=20

  

4. 調節page cache(大量一樣的請求 調大page cache)

vm.lowmem_reserve_ratio = 256 256 32 (保留多少內存作為pagecache 當前 最大 最小)
vm.vfs_cache_pressure=100 (大於100,回收pagecache)
vm.page.cluster=3(一次性從swap寫入內存的量為2的3次方頁)
vm.zone_reclaim_mode=0/1(當內存危機時,是否盡量回收內存 0:盡量回收 1:盡量不回收)
min_free_kbytes:該文件表示強制Linux VM最低保留多少空閑內存(Kbytes)。

 

5.  臟頁

vm.dirty_background_radio=10 (當臟頁占內存10%,pdflush工作)
vm.dirty_radio=40 (當進程自身臟頁占內存40%,進程自己處理臟頁,將其寫入磁盤)
vm.dirty_expire_centisecs=3000 (臟頁老化時間為30秒 3000/100=30秒)
vm.dirty_writeback_centisecs=500 (每隔5秒,pdflush監控一次內存數量 500/100=5秒)

   臟頁是指已經更改但尚未刷到硬盤的內存頁,由pdflush往硬盤上面刷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM