前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一条报警引起的对 swap 认识

一条报警引起的对 swap 认识

作者头像
用户2825413
发布2020-03-10 17:06:16
1.4K0
发布2020-03-10 17:06:16
举报

一个服务器报警信息

今天讲一个排查问题的小故事吧.

早上匆匆忙忙去上班了, 在一个例行的早会上, 被告知昨天 消息推送服务 内存报警超出了80%.

听完后不由的虎躯一震, 因为从业务上和日常报警上是没有反馈的, 机器报警目前只报告给特定的运维团队, 并且距离此事情已经过去一段时间了.

抱着侥幸的心里, 登录到报警的机器上查看相关指标

首先查看了下负载、业务进程和相关日志, 都没有错误日志记录, 也没有 OOM 被 kill 的记录.

既然是内存报警, 先重点看下内存占用情况

代码语言:javascript
复制
free -m

可以看到当前空余内存还是挺多的, 但是 Swap used保持在 149M 的占用, 证明了极有可能出现过机器内存不够使用的情况, 由于没有耗尽所有物理内存, 并没有出现 OOM 情况, 具体原因先不探究, 我们看下为什么会存在 swap 占用.

接下来引入我们今天故事的主题 Swap

思考一个问题, 当操作系统内存不够用的时会怎么办呢?

我们知道磁盘一般比内存是廉价的, 并且存储容量大. 最好的办法是将一部分当前不重要的数据放入磁盘来替代内存, 解燃眉之急.

其实,早期内存一般都比较小,很容易就出现内存不足的问题,所以很早就提出了一个交换分区(swap partition)的概念。

swap 分区是将磁盘当作内存使用,使得虚拟地址空间的范围大小可以超出物理内存的实际大小,在物理内存空间不足时,可以将物理内存中的一些不重要数据拷贝到磁盘的 swap 分区中,从而让出内存空间,并且在需要那些已被拷出数据时再从 swap 分区中拷回到内存,从而不再那么容易发生OOM错误。

只有在出现物理内存耗尽或即将耗尽的时候,如果进程继续请求分配内存,将报错 out-of-memory(OOM)表示内存不足,并且在出现 OOM 的时候,操作系统将触发 OOM Killer 程序从进程列表中筛选出一个内存密集型进程杀掉,从而释放大片内存

介绍完 swap 概念, 我们看下指定进程占用 swap 情况

代码语言:javascript
复制
#找到进程ID编号为 32132
cat /proc/32132/status
或
cat /proc/32132/smaps

我们核心的几个参数含义

代码语言:javascript
复制
VmPeak 进程所使用的虚拟内存的峰值
VmSize 进程当前使用的虚拟内存的大小
VmLck 已经锁住的物理内存的大小(锁住的物理内存不能交换到硬盘)
VmHWM 进程所使用的物理内存的峰值
VmRSS 进程当前使用的物理内存的大小
VmData 进程占用的数据段大小
VmStk 进程占用的栈大小
VmExe 进程占用的代码段大小(不包括库)
VmLib 进程所加载的动态库所占用的内存大小(可能与其它进程共享)
VmPTE 进程占用的页表大小(交换表项数量)
VmSwap 进程所使用的交换区的大小

我们可以看到此进程占用了 swap 交换区的 236kb

在上面参数含义中进程有虚拟内存、物理内存概念, 不知道你注意观察过没有, Top命令里也有 VIRT、RES、SHR相关的参数, 这是什么意思呢?

VIRT

1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等;

2、假如进程新申请10MB的内存,但实际只使用了1MB,那么它会增长10MB,而不是实际的1MB使用量。

3、VIRT = SWAP + RES

RES

1、进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量;

2、包含其他进程的共享;

3、如果申请10MB的内存,实际使用1MB,它只增长1MB,与VIRT相反;

4、关于库占用内存的情况,它只统计加载的库文件所占内存大小。

5、RES = CODE + DATA

SHR:

1、除了自身进程的共享内存,也包括其他进程的共享内存;

2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小;

3、计算某个进程所占的物理内存大小公式:RES – SHR;

4、swap out后,它将会降下来。

堆、栈分配的内存,如果没有使用是不会占用实存的,只会记录到虚存。如果程序占用实存比较多,说明程序申请内存多,实际使用的空间也多。如果程序占用虚存比较多,说明程序申请来很多空间,但是没有使用。工作中,遇到过有的程序虚存300G+, 实存只有不到15G。

了解了这些内存的概念后我们在重新回到 swap 上面来, 上面我们通过指定 pid 可以查看单个进程的 swap 占用情况, 我可以清理或者重启进程清理掉 swap 占用, 但是我如何快速列出究竟是哪些进程 swap 占用比较高呢.

查看占用 swap 排名前10的进程pid

代码语言:javascript
复制
for i in $(cd /proc;ls | grep "^[0-9]"|awk '$0 >100');do awk '/Swap:/{a=a+$2}END{print "'$i'", a/1024"M"}' /proc/$i/smaps 2>/dev/null;done | sort -k2nr | head -10

经过重启清理后, 重新观察 swap 占用情况, 释放了部分空间

关于 swap 其他命令

开启swap

代码语言:javascript
复制
# 含义为增加1G的交换分区, 文件大小= bs * count
dd if=/dev/zero of=/root/swapfile bs=1M count=1024

mkswap /root/swapfile #建立swap的文件系统
swapon /root/swapfile #启用swap文件

查看 swap 使用情况

代码语言:javascript
复制
swapon -s
或
cat /proc/swaps
代码语言:javascript
复制
#关闭交换区
swapoff /root/swapfile 
#查看内存情况
free -m

我们发现 Swap 项全部变为了0, swapoff 可以不用重启进程快速释放交互区数据, 但存在的风险是数据是有可能丢失的.

代码语言:javascript
复制
#重新开启
swapon /root/swapfile 
#查看内存情况
free -m

参考文章

  • https://blog.csdn.net/u011296165/article/details/95066920
  • https://www.cnblogs.com/xudong-bupt/p/8643094.html
  • https://www.cnblogs.com/liujunjun/p/12404588.html
  • https://www.cnblogs.com/kerrycode/p/5246383.html
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 呆呆熊的技术路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一个服务器报警信息
  • 接下来引入我们今天故事的主题 Swap
    • VIRT
      • RES
        • SHR:
        • 关于 swap 其他命令
        • 参考文章
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档