Linux性能调优一文讲清内存问题的排查方法建议收藏便于查阅

Linux内存问题排查全解析

cover_image

1、前言

从前面几篇文章,我们已经谈了内存的原理、swap的使用、缓存的类型,还有如果内存发生泄漏应该使用什么工具来排查,现在已经对内存有了基础的认识。如果在工作学习中遇到了内存问题,应该怎么排查或者从哪里入手呢,文章就主要谈一下内存问题的排查思路。

一般情况下,我们怀疑出现内存问题时,首先会有内存方面的告警指标提醒我们,也就是这些最基础的指标会第一时间反映出问题。有了指标,我们可以选择合适的工具再进一步的分析。根据工具深入分析后一般都能够很快判断出问题在哪里,然后进行处理。

2、内存指标

根据前文的描述,我们需要关心的内存指标,如下
系统内存指标: 总内存、空闲内存、已用内存、缓存(buffer/cache)使用量、缓存命中率、缺页异常、slab可回收内存等。
进程内存指标:
虚拟内存(VIRT)、常驻内存/物理内存(RES/RSS)、共享内存(SHR)、进程内存使用百分比(%MEM)、独占内存(约等于RES -
SHR)、进程使用的虚拟内存大小(VSZ)等。
swap内存: 总内存、已用内存、剩余内存、换出换入速度。

3、查看工具

了解了上面这些指标,我们需要相应的工具及时的查看到准确的数据,来进行判断问题出现哪里。

root@test:~# free -wh  
              total        used        free      shared     buffers       cache   available  
Mem:          1.0Ti        48Gi       803Gi       3.0Mi       2.0Gi       152Gi       954Gi  
Swap:          39Gi          0B        39Gi

free是查看内存最常用的工具,可以快速看到内存的使用情况,用了多少,还剩余多少。

各列含义:
total: 总内存量
used: 已使用的内存量(used = total - free - buffers - cache)
free: 未被使用的内存量
shared: 多个进程共享的内存总量(通常为0,或者很小)
buffers: 内核缓冲区使用的内存量
cache: 页面缓存和slab使用的内存量
available: 估计可用于启动新应用程序的内存量(不含交换分区)

top - 11:34:44 up 526 days, 20:11,  1 user,  load average: 0.84, 0.92, 1.04  
Tasks: 1343 total,   1 running, 1342 sleeping,   0 stopped,   0 zombie  
%Cpu(s):  0.4 us,  0.0 sy,  0.0 ni, 99.6 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st  
MiB Mem : 1031349.+total, 823056.8 free,  50146.1 used, 158146.7 buff/cache  
MiB Swap:  40960.0 total,  40960.0 free,      0.0 used. 976896.4 avail Mem  
  
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                     
   4095 mysql     20   0 6189264   1.6g 550648 S  21.5   0.2 204441:48 mysqld                                                                                                                                      
   2732 root      20   0  141524  34936   9324 S  17.2   0.0 194545:07 node_exporter                                                                                                                               
1129876 root      20   0 7095304   1.1g  54208 S   5.6   0.1   1770:30 prometheus                                                                                                                                  
2936909 root      20   0 5411276 231104  56112 S   2.0   0.0  19108:45 wsssr_defence_s

top命令也是查看内存的重要工具,可以实时看到内存的变化情况。更详细的可以使用htop命令,需要单独安装。

1)第四行(内存):
MiB Mem : 总内存。
free:空闲内存MiB。
used:已使用内存 MiB。
buff/cache:用作缓冲缓存的内存 MiB。
2)第五行(交换分区):
MiB Swap: 总交换分区。
free:空闲交换分区 MiB。
used:已使用交换分区MiB。
avail Mem:可用内存估计数(包括未使用的和缓冲缓存中可回收的)MiB。
3)进程实时展示
PID:进程ID。
USER:进程所有者。
PR:优先级。
NI:Nice值,负值表示高优先级,正值表示低优先级。
VIRT:虚拟内存使用量(单位KiB)。
RES:常驻内存大小(单位KiB)。
SHR:共享内存大小(单位KiB)。
S:进程状态(S=睡眠,R=运行,等)。
%CPU:CPU使用百分比。
%MEM:内存使用百分比。
TIME+:进程使用的CPU时间总和,精确到百分之一秒。
COMMAND:进程名称。

root@test:~# ps -aux |head -5  
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND  
root           1  0.1  0.0 171128 13972 ?        Ss    2024 1505:02 /sbin/init nopti  
root           2  0.0  0.0      0     0 ?        S     2024   8:41 [kthreadd]  
root           3  0.0  0.0      0     0 ?        I<    2024   0:00 [rcu_gp]  
root           4  0.0  0.0      0     0 ?        I<    2024   0:00 [rcu_par_gp]

使用ps命令可以查看进程的内存使用情况。

各列的含义如下:
USER: 进程的所有者(哪个用户启动的)
PID: 进程ID
%CPU: 进程占用CPU的百分比
%MEM: 进程占用内存的百分比
VSZ: 进程使用的虚拟内存大小(单位KB)
RSS: 进程使用的物理内存大小(单位KB)
TTY: 进程在哪个终端上运行(如果为?则表示与终端无关)
STAT: 进程状态(例如:S-睡眠,R-运行,Z-僵尸等)
START: 进程启动时间
TIME: 进程占用CPU的总时间
COMMAND: 启动进程的命令

   root@test:~# cat /proc/meminfo  
    ...  
    Slab:           24081144 kB  
    SReclaimable:   18618148 kB  
    SUnreclaim:      5462996 kB  
    ...  
    AnonHugePages:   3555328 kB  
    ...  
    HugePages_Total:       0  
    HugePages_Free:        0  
    HugePages_Rsvd:        0  
    HugePages_Surp:        0  
    Hugepagesize:       2048 kB

/proc/meminfo是一些特殊内存指标的重要位置,可以查看slab内核内存、配置的大页内存。

SReclaimable:可回收Slab,可被回收的内核缓存
SUnreclaim:不可回收Slab,内核必须保留的内存
AnonHugePages:匿名大页,透明大页使用的内存
HugePages_Total:空闲大页数,未使用的大页数量
HugePages_Free:总大页数,配置的大页数量
Hugepagesize:大页大小,每个大页2MB

root@test:~# vmstat 1 2  
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----  
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st  
 0  0      0 842544896 2081680 160133632    0    0     0     4    0    0  1  0 99  0  0  
 2  0      0 842544192 2081680 160133744    0    0     0    92 3923 5803  2  0 98  0  0

vmstat工具可以查看内存指标的动态变化,1表示时间间隔,2表示次数。

procs(进程):
r: 运行队列中的进程数(正在运行和等待CPU的进程数)
b: 等待I/O的进程数(处于不可中断睡眠状态的进程数)
memory(内存,单位:KB):
swpd: 已使用的虚拟内存大小(交换分区,KB)
free: 空闲的物理内存大小(KB)
buff: 用作缓冲区的内存大小(KB)
cache: 用作缓存的内存大小(KB)
swap(交换分区,单位:KB/秒):
si: 从磁盘读入交换分区的数据量(KB/秒)
so: 从交换分区写到磁盘的数据量(KB/秒)
io(IO,单位:块/秒):
bi: 从块设备接收的块数(块/秒,读磁盘)
bo: 发送到块设备的块数(块/秒,写磁盘)
system(系统):
in: 每秒的中断数(包括时钟中断)
cs: 每秒的上下文切换次数
cpu(CPU使用率,百分比):
us: 用户进程占用CPU时间百分比
sy: 内核进程占用CPU时间百分比
id: 空闲CPU时间百分比
wa: 等待I/O的CPU时间百分比
st: 被偷走的CPU时间百分比(一般是在虚拟化环境中,其他虚拟机占用的CPU时间)

   root@test:~# sar -r 1 3  
    Linux 5.4.0-59-generic (jnai1asan01)    11/05/2025      _x86_64_        (128 CPU)  
      
    02:36:42 PM kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty  
    02:36:43 PM 842489592 1000321788  45882776      4.34   2081692 141547176  53245784      4.85 142730504  44375344      1200  
    02:36:44 PM 842489340 1000321652  45883056      4.34   2081692 141547236  53245784      4.85 142730656  44375460      1260  
    02:36:45 PM 842489772 1000322360  45882228      4.34   2081692 141547508  53245784      4.85 142730568  44375676      1536

sar -r可以查看系统内存的具体情况,同时重点查看缓存使用、账页情况。

kbmemfree: 空闲的物理内存量(KB)。
kbavail: 可用的内存量(KB),这是一个估计值,包括空闲内存和可回收的缓存(不包括交换空间)。
kbmemused: 已使用的物理内存量(KB)。注意,这个值可能包括被内核使用的内存,包括缓存和缓冲区。
%memused: 已使用内存的百分比。
kbbuffers: 内核缓冲区占用的内存量(KB)。
kbcached: 内核缓存数据占用的内存量(KB)。
kbcommit: 当前工作负载所需的内存总量(KB)。这是估计值,包括已使用的内存和尚未使用但预计需要的内存(如malloc分配但未实际使用的)。
%commit: kbcommit与总内存(包括交换空间)的百分比。
kbactive: 活跃内存量(KB),即最近被访问的内存。
kbinact: 非活跃内存量(KB),即最近未被访问的内存,可能被回收用于其他用途。
kbdirty: 等待写回磁盘的脏内存量(KB)。

除了上面几个常用的工具之外还有cachetop(查看进程缓存和缓冲区命中率信息)、pmap(查看具体进程的分布情况)。同时还有总要的内存泄露检查工具memleak-
bpfcc和valgrind。

4、内存问题排查思路

当前我们了解了内存的相关指标,并且也了解了通过工具获取这些指标的数值。从上面的工具介绍看,这些指标并不是孤立独自存在的,而是交叉存在,这也说明系统底层的内存原理是固定的,各种工具都基于这些原来,在某一些角度来反应内存的使用情况。

当发现内存问题时,我们总不能挨个拿工具去把所有指标都找出来,这样既浪费时间,也没有必要。根据内存指标的特性,从全局到局部、分层次的来分析内存问题,会是更好的选择。我们来总结分析一种比较好的排查思路。

首先
内存问题的最直接表现就是使用的过多了,不符合预期。一般都首先用free、top命令看一下内存使用的整体情况,并不是剩余内存变少了就一定是问题,也可以是缓存占用了。当发现缓存占用了很多内存,可以使用vmstat
或者 sar观察一下缓存的变化趋势,确认是否存在不合理的增长。
如果缓存持续增加,可以使用cachetop或者slabtop,还有/proc/meminfo,看一下这些缓存都被哪些进程占用了。找到进程后,再使用pmap分析一下进程中内存的使用情况。

然后
如果缓存使用正常,观察一下swap是否已经参与使用,如果参与,一是可能内存配置不足,用vmstat观察一下swap的变化量,若swap在不断地换入换出,说明确实是内存配置不足了。再就是可能有进程的内存在大幅增长,导致整体内存使用在不断增长,可以使用top和ps工具找到相关进程分析。

再就是
若内存增长无法得到缓解,且不断增加还发生过OOM的情况,那可以判断可能有进程发生内存溢出了,这时可以根据前面的步骤找到相关进程,然后用memleak-
bpfcc和valgrind来分析一下泄露的进程和堆栈。

最后
有时候内存问题也可能并不是程序引起的,也有可能是硬件故障,例如网卡故障导致数据传输异常从而引发内存缓存升高。或者磁盘IO读写异常导致进程使用内存大幅增加。

🔥运维干货分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

企鹅侠客

您的打赏是我创作旅程中的关键燃

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值