美文网首页
内存高排查

内存高排查

作者: Daisy小朋友 | 来源:发表于2020-02-06 16:04 被阅读0次
    1 测试工具

    清理系统缓存

    # 清理文件页、目录项、Inodes等各种缓存
    $ echo 3 > /proc/sys/vm/drop_caches
    Swap 空间清理方法
    $ swapoff -a && swapon -a 
    

    dd 作为一个磁盘和文件的拷贝工具,经常被拿来测试磁盘或者文件系统的读写性能,模拟磁盘和文件的 I/O,所以我们也需要观测 I/O 的变化情况。

    通过读取随机设备,生成一个 500MB 大小的文件
    $ dd if=/dev/urandom of=/tmp/file bs=1M count=500
    # 运行dd命令读取文件数据
    $ dd if=/tmp/file of=/dev/null
    
    2 指标

    内存高

    名次释义:

    系统内存使用情况

    已用内存和剩余内存很容易理解,就是已经使用和还未使用的内存。
    共享内存是通过 tmpfs 实现的,所以它的大小也就是 tmpfs 使用的内存大小。tmpfs 其实也是一种特殊的缓存。
    可用内存是新进程可以使用的最大内存,它包括剩余内存和可回收缓存。
    缓存包括两部分,一部分是磁盘读取文件的页缓存,用来缓存从磁盘读取的数据,可以加快以后再次访问的速度。另一部分,则是 Slab 分配器中的可回收内存。
    缓冲区是对原始磁盘块的临时存储,用来缓存将要写入磁盘的数据。这样,内核就可以把分散的写集中起来,统一优化磁盘写入
    

    进程内存使用情况

    虚拟内存,包括了进程代码段、数据段、共享内存、已经申请的堆内存和已经换出的内存等。这里要注意,已经申请的内存,即使还没有分配物理内存,也算作虚拟内存。
    常驻内存是进程实际使用的物理内存,不过,它不包括 Swap 和共享内存。
    共享内存,既包括与其他进程共同使用的真实的共享内存,还包括了加载的动态链接库以及程序的代码段等。
    Swap 内存,是指通过 Swap 换出到磁盘的内存
    
    image.png

    交换分区 swap

    Swap 其实就是把一块磁盘空间当成内存来用。
    它可以把进程暂时不用的数据存储到磁盘中(这个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程称为换入)。
    所以,你可以发现,Swap 把系统的可用内存变大了。
    不过要注意,通常只在内存不足时,才会发生 Swap 交换。并且由于磁盘读写的速度远比内存慢,Swap 会导致严重的内存性能问题。
    

    OOM机制

    OOM(Out of Memory),其实是内核的一种保护机制。它监控进程的内存使用情况,并且使用 oom_score 为每个进程的内存使用情况进行评分:一个进程消耗的内存越大,oom_score 就越大;一个进程运行占用的 CPU 越多,oom_score 就越小。这样,进程的 oom_score 越大,代表消耗的内存越多,也就越容易被 OOM 杀死,从而可以更好保护系统。当然,为了实际工作的需要,管理员可以通过 /proc 文件系统,手动设置进程的 oom_adj ,从而调整进程的 oom_score
    oom_adj 的范围是 [-17, 15],数值越大,表示进程越容易被 OOM 杀死;数值越小,表示进程越不容易被 OOM 杀死,其中 -17 表示禁止 OOM
    比如用下面的命令,你就可以把 sshd 进程的 oom_adj 调小为 -16,这样, sshd 进程就不容易被 OOM 杀死
    echo -16 > /proc/$(pidof sshd)/oom_adj
    

    buffer和cache

    Buffer是对磁盘数据的缓存,而Cache是文件数据的缓存,他们既会用在读请求中,也会在写请求中
    Buffer 和 Cache 的设计目的,是为了提升系统的 I/O 性能。它们利用内存,充当起慢速磁盘与快速 CPU 之间的桥梁,可以加速 I/O 的访问速度
    Buffer 和 Cache 分别缓存的是对磁盘和文件系统的读写数据。从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作。从读的角度来说,不仅可以提高那些频繁访问数据的读取速度,也降低了频繁 I/O 对磁盘的压力。
    磁盘和文件的区别:
    关于磁盘和文件的区别,本来以为大家都懂了,所以没有细讲。磁盘是一个块设备,可以划分为不同的分区;在分区之上再创建文件系统,挂载到某个目录,之后才可以在这个目录中读写文件。
    其实 Linux 中“一切皆文件”,而文章中提到的“文件”是普通文件,磁盘是块设备文件,这些大家可以执行 "ls -l <路径>" 查看它们的区别(输出的含义如果不懂请 man ls 查询)。
    在读写普通文件时,会经过文件系统,由文件系统负责与磁盘交互;而读写磁盘或者分区时,就会跳过文件系统,也就是所谓的“裸I/O“。这两种读写方式所使用的缓存是不同的,也就是文中所讲的 Cache 和 Buffer 区别
    磁盘读写——buffer
    文件读写——cache
    
    3 工具

    free
    top
    memleak 用来检测内存泄漏的工具,以跟踪系统或指定进程的内存分配、释放请求,然后定期输出一个未释放内存和相应调用栈的汇总情况(默认 5 秒),memleak 是 bcc 软件包中的一个工具,执行 /usr/share/bcc/tools/memleak 就可以运行它

    注意:bcc-tools 需要内核版本为 4.1 或者更高,如果你使用的是 CentOS7,或者其他内核版本比较旧的系统,那么你需要手动升级内核版本后再安装
    
    image.png
    image.png
    4 命令

    free

    # 注意不同版本的free输出可能会有所不同
    centos7
    $ free
                  total        used        free      shared  buff/cache   available
    Mem:        8169348      263524     6875352         668     1030472     7611064
    Swap:             0           0           0
    
    free 输出的是一个表格,其中的数值都默认以字节为单位。
    表格总共有两行六列,这两行分别是物理内存 Mem 和交换分区 Swap 的使用情况
    而六列中,每列数据的含义分别为:
    第一列,total 是总内存大小;
    第二列,used 是已使用内存的大小,包含了共享内存;
    第三列,free 是未使用内存的大小;
    第四列,shared 是共享内存的大小;
    第五列,buff/cache 是缓存和缓冲区的大小;
    最后一列,available 是新进程可用内存的大小。
    这里尤其注意一下,最后一列的可用内存 available 。available 不仅包含未使用内存,还包括了可回收的缓存,所以一般会比未使用内存更大。不过,并不是所有缓存都可以回收,因为有些缓存可能正在使用中
    
    centos6
    $ free
                 total       used       free     shared    buffers     cached
    Mem:       1815340    1628680     186660          0     130316    1327736
    -/+ buffers/cache:     170628    1644712
    Swap:      1020116          0    1020116
    
    Mem:表示物理内存统计
    -/+ buffers/cached:表示物理内存的缓存统计
    Swap:表示硬盘上交换分区的使用情况,这里我们不去关心。
    系统的总物理内存:1815340Kb(2GB),但系统当前真正可用的内存并不是第一行free 标记的 186660Kb,它仅代表未被分配的内存
    第1行 Mem:
    total:表示物理内存总量。1815340
    used:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。 1628680
    free:未被分配的内存。186660
    shared:共享内存,一般系统不会用到,这里也不讨论。0
    buffers:系统分配但未被使用的buffers 数量。130316
    cached:系统分配但未被使用的cache 数量。1327736     buffer 与cache 的区别见后面。
    total = used + free
    第2行 -/+ buffers/cached:
    used:也就是第一行中的used – buffers-cached 也是实际使用的内存总量。
    free:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行
    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
    第3行: 第三行所指的是从应用程序角度来看,对于应用程序来说,buffers/cached
    是等于可用的,因为buffer/cached是为了提高文件读取的性能,当应用程序需在用到内存的时候,buffer/cached会很快地被回收。
    所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached
    

    top

    按M内存排序
    
    # 按下M切换到内存排序
    $ top
    ...
    KiB Mem :  8169348 total,  6871440 free,   267096 used,  1030812 buff/cache
    KiB Swap:        0 total,        0 free,        0 used.  7607492 avail Mem
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      430 root      19  -1  122360  35588  23748 S   0.0  0.4   0:32.17 systemd-journal
     1075 root      20   0  771860  22744  11368 S   0.0  0.3   0:38.89 snapd
     1048 root      20   0  170904  17292   9488 S   0.0  0.2   0:00.24 networkd-dispat
        1 root      20   0   78020   9156   6644 S   0.0  0.1   0:22.92 systemd
    12376 azure     20   0   76632   7456   6420 S   0.0  0.1   0:00.01 systemd
    12374 root      20   0  107984   7312   6304 S   0.0  0.1   0:00.00 sshd
    ...
    VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。
    RES 是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。
    SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
    %MEM 是进程使用物理内存占系统总内存的百分比。
    第一,虚拟内存通常并不会全部分配物理内存。从上面的输出,你可以发现每个进程的虚拟内存都比常驻内存大得多。第二,共享内存 SHR 并不一定是共享的,比方说,程序的代码段、非共享的动态链接库,也都算在 SHR 里。当然,SHR 也包括了进程间真正共享的内存。所以在计算多个进程的内存使用时,不要把所有进程的 SHR 直接相加得出结果
    

    vmstat

    # 每隔1秒输出1组数据
    $ 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
    0  0      0 7743608   1112  92168    0    0     0     0   52  152  0  1 100  0  0
     0  0      0 7743608   1112  92168    0    0     0     0   36   92  0  0 100  0  0
    

    memleak

    # -a 表示显示每个内存分配请求的大小以及地址
    # -p 指定案例应用的PID号
    $ /usr/share/bcc/tools/memleak -a -p $(pidof app)
    WARNING: Couldn't find .text section in /app
    WARNING: BCC can't handle sym look ups for /app
        addr = 7f8f704732b0 size = 8192
        addr = 7f8f704772d0 size = 8192
        addr = 7f8f704712a0 size = 8192
        addr = 7f8f704752c0 size = 8192
        32768 bytes in 4 allocations from stack
            [unknown] [app]
            [unknown] [app]
            start_thread+0xdb [libpthread-2.27.so] 
    

    sar

    
    # 间隔1秒输出一组数据
    # -r表示显示内存使用情况,-S表示显示Swap使用情况
    $ sar -r -S 1
    04:39:56    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    04:39:57      6249676   6839824   1919632     23.50    740512     67316   1691736     10.22    815156    841868         4
    
    04:39:56    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    04:39:57      8388604         0      0.00         0      0.00
    
    04:39:57    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    04:39:58      6184472   6807064   1984836     24.30    772768     67380   1691736     10.22    847932    874224        20
    
    04:39:57    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    04:39:58      8388604         0      0.00         0      0.00
    
    …
    
    
    04:44:06    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    04:44:07       152780   6525716   8016528     98.13   6530440     51316   1691736     10.22    867124   6869332         0
    
    04:44:06    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    04:44:07      8384508      4096      0.05        52      1.27
    sar 的输出结果是两个表格,第一个表格表示内存的使用情况,第二个表格表示 Swap 的使用情况。其中,各个指标名称前面的 kb 前缀,表示这些指标的单位是 KB
    kbcommit,表示当前系统负载需要的内存。它实际上是为了保证系统内存不溢出,对需要内存的估计值。%commit,就是这个值相对总内存的百分比。
    kbactive,表示活跃内存,也就是最近使用过的内存,一般不会被系统回收。
    kbinact,表示非活跃内存,也就是不常访问的内存,有可能会被系统回收。
    
    5 场景

    内存泄漏

    6 内存泄漏导致cpu升高

    top 虽然能观察系统和进程的内存占用情况,但内存泄漏问题,我们更应该关注内存使用的变化趋势,vmstat 工具。

    7 小结
    如何计算出所有进程的物理内存使用量?
    就是/proc/<pid>/smaps中的Pss相加,因为Pss是私有内存+共享内存按比例属于自己计算的那一部分
    比如私有内存是200k, 共享内存500k和4个其它进程共享,那么是Pss就是200k+(500/(1+4))=200k+100k=300k。 这样所有进程的Pss相加就不会有重复相加的顾虑,因为Pss中已经将共享内存部分帮我们算好了
    参考命令:
    
    # 使用grep查找Pss指标后,再用awk计算累加值
    $ grep Pss /proc/[1-9]*/smaps | awk '{total+=$2}; END {printf "%d kB\n", total }'
    391266 kB
    另:
    查看当个进程实际物理内存使用,Pss是私有内存+共享内存按比例属于自己计算的那一部分
    $ awk '/Pss:/{ sum += $2 } END { print sum }' /proc/<PID>/smaps
    内存使用量大小
    $ ps aux --sort -rss|more
    ######内存高分析步骤:
    使用top和ps查询系统中大量占用内存的进程,使用cat /proc/[pid]/status和pmap -x pid查看某个进程使用内存的情况和动态变化
    

    为了迅速定位内存问题,我通常会先运行几个覆盖面比较大的性能工具,比如 free、top、vmstat、pidstat 等
    具体的分析思路主要有这几步。先用 free 和 top,查看系统整体的内存使用情况。再用 vmstat 和 pidstat,查看一段时间的趋势,从而判断出内存问题的类型。最后进行详细分析,比如内存分配分析、缓存 / 缓冲区分析、具体进程的内存使用分析等。同时,我也把这个分析过程画成了一张流程图,你可以保存并打印出来使用。


    image.png
    优化思路:

    常见的优化思路有这么几种。最好禁止 Swap。如果必须开启 Swap,降低 swappiness 的值,减少内存回收时 Swap 的使用倾向。减少内存的动态分配。比如,可以使用内存池、大页(HugePage)等。尽量使用缓存和缓冲区来访问数据。比如,可以使用堆栈明确声明内存空间,来存储需要缓存的数据;或者用 Redis 这类的外部缓存组件,优化数据的访问。使用 cgroups 等方式限制进程的内存使用情况。这样,可以确保系统内存不会被异常进程耗尽。通过 /proc/pid/oom_adj ,调整核心应用的 oom_score。这样,可以保证即使内存紧张,核心应用也不会被 OOM 杀死
    附:
    CentOS 系统中如何安装 bcc-tools
    1> 升级内核

    # 升级系统
    yum update -y
    # 安装ELRepo
    rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
    rpm -Uvh https://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
    # 安装新内核
    yum remove -y kernel-headers kernel-tools kernel-tools-libs
    yum --enablerepo="elrepo-kernel" install -y kernel-ml kernel-ml-devel kernel-ml-headers kernel-ml-tools kernel-ml-tools-libs kernel-ml-tools-libs-devel
    # 更新Grub后重启
    grub2-mkconfig -o /boot/grub2/grub.cfg
    grub2-set-default 0
    reboot
    # 重启后确认内核版本已升级为4.20.0-1.el7.elrepo.x86_64
    uname -r
    

    2>安装bcc-tools

    # 安装bcc-tools
    yum install -y bcc-tools
    # 配置PATH路径
    export PATH=$PATH:/usr/share/bcc/tools
    # 验证安装成功
    cachestat 
    

    相关文章

      网友评论

          本文标题:内存高排查

          本文链接:https://www.haomeiwen.com/subject/btmkxhtx.html