SWAP的罪与罚

发表于2012-11-08

说个案例:一台Apache服务器,由于其MaxClients参数设置过大,并且恰好又碰到访问量激增,结果内存被耗光,从而引发SWAP,进而负载攀升,最终导致宕机。

正所谓:SWAP,性能之大事,死生之地,存亡之道,不可不察也。

哪些工具可以监测SWAP

最容易想到的就是free命令了,它指明了当前SWAP的使用情况:

shell> free -m
total used free
Swap: 34175 11374 22801

另一个常用的是sar命令,它能列出系统在各个时间的SWAP使用情况:

shell> sar -r
kbswpfree kbswpused %swpused kbswpcad
23345644 11650572 33.29 4656908
23346452 11649764 33.29 4656216
23346556 11649660 33.29 4650308
23346932 11649284 33.29 4649888
23346992 11649224 33.29 4648848

不过free命令和sar命令显示的都不是实时数据,如果需要,可以使用vmstat命令:

shell> vmstat 1
-----------memory------------- ---swap--
swpd free buff cache si so
11647532 123664 305064 7193168 0 0
11647532 123672 305064 7193172 0 0
11647532 125728 305064 7193468 0 0
11647532 125376 305064 7193476 0 0
11647532 124508 305068 7193624 0 0

每秒刷新一次结果,在SWAP一栏里列出了相关数据,至于si和so的解释,大致如下:

  • si: Amount of memory swapped in from disk (/s).
  • so: Amount of memory swapped to disk (/s).

如果它们一直是零当然最好不过了,偶尔不为零也没啥,糟糕的是一直不为零。

前面介绍的方法,看到的都是SWAP的整体情况,可是如果我想查看到底是哪些进程使用了SWAP,应该如何操作呢?这个问题有点棘手,我们来研究一下:

好消息是top命令能提供这个信息,不过缺省并没有显示,我们需要激活一下:

  1. 打开top;
  2. 按「f」进入选择字段的界面;
  3. 按「p」选择「SWAP」字段;
  4. 按回车确认。

坏消息是top命令提供的SWAP信息只是一个理论值,或者更直白一点儿来说它根本就是不可信的(在top里SWAP的计算公式是:SWAP=VIRT-RES)。

BTW:相比之下,top里的「nFLT」字段更有价值,它表示PageFault的次数。

那到底我们能不能获取到进程的SWAP情况呢?别着急,看代码:

#!/bin/bash

cd /proc

for pid in [0-9]*; do
command=$(cat /proc/$pid/cmdline) swap=$(
awk '
BEGIN { total = 0 }
/Swap/ { total += $2 }
END { print total }
' /proc/$pid/smaps
) if (( $swap > 0 )); then
if [[ "${head}" != "yes" ]]; then
echo -e "PID\tSWAP\tCOMMAND"
head="yes"
fi echo -e "${pid}\t${swap}\t${command}"
fi
done

说明:请使用root权限来运行此脚本。

哪些因素可能影响SWAP

内存不足无疑会SWAP,但有些时候,即便看上去内存很充裕,还可能会SWAP,这种现象被称为SWAP Insanity,罪魁祸首主要有以下几点:

Swappiness的迷失

实际上,当可用内存不足时,系统有两个选择:一个是通过SWAP来释放内存,另一个是删除Cache中的Page来释放内存。一个很常见的例子是:当拷贝大文件的时候,时常会发生SWAP现象。这是因为拷贝文件的时候,系统会把文件内容在Cache中按Page来缓存,此时一旦可用内存不足,系统便会倾向于通过SWAP来释放内存。

内核中的swappiness参数可以用来控制这种行为,缺省情况下,swappiness的值是60:

shell> sysctl -a | grep swappiness
vm.swappiness = 60

它的含义是:如果系统需要内存,有百分之六十的概率执行SWAP。知道了这一点,我们很自然的会想到用下面的方法来降低执行SWAP的概率:

shell> echo "vm.swappiness = 1" >> /etc/sysctl.conf
shell> sysctl -p

这样做的确可以降低执行SWAP的概率,但并不意味着永远不会执行SWAP。据网友报道某些情况下,直接改为0有可能出现灵异问题,所以建议改为1。

补:Memcached在启动的时候如果带上了k选项,就能避免使用SWAP,但要慎用。

早些年,YouTube曾经被SWAP问题困扰过,他们当时的解决方法很极端:删除SWAP!不得不说这真是艺高人胆大,可惜对芸芸众生的我们而言,这实在是太危险了,因为如此一来,一旦内存耗尽,由于没有SWAP的缓冲,系统会立即开始OOM结果可能会让问题变得更加复杂,所以大家还是安分守己做个老实人吧。

摘自:https://huoding.com/2012/11/08/198

关闭swap的危害——一旦内存耗尽,由于没有SWAP的缓冲,系统会立即开始OOM的更多相关文章

  1. 攻城狮在路上(叁)Linux(二十五)--- linux内存交换空间(swap)的构建

    swap的功能是应付物理内存不足的状况,用硬盘来暂时放置内存中的信息. 对于一般主机,物理内存都差不多够用,所以也就不会用到swap,但是对于服务器而言,当遇到大量网络请求时或许就会用到. 当swap ...

  2. webdriver.close() quit() 批量kill进程 内存耗尽的解决办法

    问题现象: shell窗口卡,换IP的登录窗,不开: 猜测: 内存耗尽 spider_url,py driver = webdriver.PhantomJS( executable_path='/us ...

  3. 内存使用空间之swap建置[转]

    http://www.cnblogs.com/ggjucheng/archive/2012/08/22/2651502.html 内存置换空间(swap)之建置 安装时一定需要的两个 partitio ...

  4. Allowed memory size of 134217728 bytes exhausted解决办法(php内存耗尽报错)【简记】

    报错: PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) i ...

  5. Linux下php-fpm进程过多导致内存耗尽问题

    这篇文章主要介绍了解决Linux下php-fpm进程过多导致内存耗尽问题,需要的朋友可以参考下   最近,发现个人博客的Linux服务器,数据库服务经常挂掉,导致需要重启,才能正常访问,极其恶心,于是 ...

  6. redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请求,导致 redis 短时间不可用

    redis 突然大量逐出导致读写请求block   内容目录: 现象 背景 原因 解决方案 ref 现象 redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请 ...

  7. 早期malloc分配时,如果内存耗尽分配不出来,会直接返回NULL。现在分配不出来,直接抛出异常(可使用nothrow关键字)

    今天和同事review代码时,发现这样的一段代码: Manager * pManager = new Manager(); if(NULL == pManager) { //记录日志 return f ...

  8. 【操作系统之十】内存分页管理与swap

    一.虚拟内存电脑里内存分内存条(这里我们叫物理内存)和硬盘,内存条保存程序运行时数据,硬盘持久保存数据.那么虚拟内存是什么? 程序运行会启动一个进程,进程里有程序段.全局数据.栈和堆,这些都会加载到内 ...

  9. 【故障公告】redis内存耗尽造成博客后台无法保存

    非常抱歉,今天上午11:00~11:30左右,由于 redis 服务器内存耗尽造成博客后台故障--保存博文时总是提示"请求太过频繁,请稍后再试",由此给您带来麻烦,请您谅解. 由于 ...

随机推荐

  1. Linux - 进程服务资源

    1.进程查看操作管理 ps -eaf # 查看所有进程 kill - PID # 强制终止某个PID进程 kill - PID # 安全退出 需程序内部处理信号 cmd & # 命令后台运行 ...

  2. luogu P3304 [SDOI2013]直径

    树的直径两遍dfs救星了 至于一定在直径中的边数,可以发现这些边一定是连续的(不然你两条直径中间能有空挡?),然后,如果某个点往下有多条直径,那么这条点以下都不算入答案.所以以直径分别两端点为根,找出 ...

  3. POJ3177 Redundant Paths【双连通分量】

    题意: 有F个牧场,1<=F<=5000,现在一个牧群经常需要从一个牧场迁移到另一个牧场.奶牛们已经厌烦老是走同一条路,所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可以 ...

  4. 闭包传递(floyed)

    题目链接: https://cn.vjudge.net/contest/66569#problem/H 题目大意: n代表母牛的个数,m代表给定的信息的组数.每一组数包括a,b. 代表b崇拜a(突然发 ...

  5. 解决jdk1.7,1.8共存问题小思

    一 起因 随着jdk1.9呼之欲出之势,准备花点时间把jdk1.8搞掉,于是准备下一个项目的依赖改为jdk1.8,先去下载安装,安装好之后电脑上就存在两个版本的jdk.然后将两个版本的jdk路径都配置 ...

  6. Linux驱动技术(三) _DMA编程【转】

    转自:https://www.cnblogs.com/xiaojiang1025/archive/2017/02/11/6389194.html DMA即Direct Memory Access,是一 ...

  7. 解决mysql开启GTID主从同步出现1236错误问题【转】

    最近遇到mysql开启gtid做复制时,从库出现1236错误,导致同步无法进行,本文就这问题记录下处理步骤,有关gtid知识在这里不做介绍,mysql版本为5.7.16. 一.错误原因分析 错误信息如 ...

  8. Python创建、删除桌面、启动组快捷方式的例子分享

    一.Python创桌面建快捷方式的2个例子 例子一: 代码如下: import osimport pythoncomfrom win32com.shell import shell    from w ...

  9. (网络编程)基于tcp(粘包问题) udp协议的套接字通信

    import   socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...

  10. mysql数据库报错:InnoDB: Operating system error number 13 in a file operation

    环境:centos6.5 x86_64 启动mysql发现日志报错(日志路径可以查看/etc/my.cnf的配置) 160722 10:34:08 [Note] Found 42570716 of 4 ...