原文:http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/


最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有位客户抱怨 VPS 经常死机,登陆到终端看了一下,都是常见的 Out of memory 问题。

这通常是因为某时刻应用程序大量请求内存导致系统内存不足造成的,这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃。

如果检查相关的日志文件(/var/log/messages)就会看到下面类似的 Out of memory: Kill process 信息:

...
Out of memory: Kill process 9682 (mysqld) score 9 or sacrifice child
Killed process 9682, UID 27, (mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB
httpd invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
httpd cpuset=/ mems_allowed=0
Pid: 8911, comm: httpd Not tainted 2.6.32-279.1.1.el6.i686 #1
...
21556 total pagecache pages
21049 pages in swap cache
Swap cache stats: add 12819103, delete 12798054, find 3188096/4634617
Free swap  = 0kB
Total swap = 524280kB
131071 pages RAM
0 pages HighMem
3673 pages reserved
67960 pages shared
124940 pages non-shared

Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,

这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分 “空闲” 的内存,提高整体内存的使用效率。

一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。

用银行的例子来讲可能更容易懂一些,部分人取钱的时候银行不怕,银行有足够的存款应付,当全国人民(或者绝大多数)都取钱而且每个人都想把自己钱取完的时候银行的麻烦就来了,银行实际上是没有这么多钱给大家取的。

内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,

当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个 “bad” 进程杀掉。

如何判断和选择一个 “bad” 进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程。

/*** oom_badness - heuristic function to determine which candidate task to kill* @p: task struct of which task we should calculate* @totalpages: total present RAM allowed for page allocation** The heuristic for determining which task to kill is made to be as simple and* predictable as possible.  The goal is to return the highest value for the* task consuming the most memory to avoid subsequent oom failures.*/
unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,const nodemask_t *nodemask, unsigned long totalpages)
{long points;long adj;if (oom_unkillable_task(p, memcg, nodemask))return 0;p = find_lock_task_mm(p);if (!p)return 0;adj = (long)p->signal->oom_score_adj;if (adj == OOM_SCORE_ADJ_MIN) {task_unlock(p);return 0;}/** The baseline for the badness score is the proportion of RAM that each* task's rss, pagetable and swap space use.*/points = get_mm_rss(p->mm) + p->mm->nr_ptes +get_mm_counter(p->mm, MM_SWAPENTS);task_unlock(p);/** Root processes get 3% bonus, just like the __vm_enough_memory()* implementation used by LSMs.*/if (has_capability_noaudit(p, CAP_SYS_ADMIN))adj -= 30;/* Normalize to oom_score_adj units */adj *= totalpages / 1000;points += adj;/** Never return 0 for an eligible task regardless of the root bonus and* oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here).*/return points > 0 ? points : 1;
}

上面代码里的注释写的很明白,理解了这个算法我们就理解了为啥 MySQL 躺着也能中枪了,因为它的体积总是最大(一般来说它在系统上占用内存最多),所以如果 Out of Memeory (OOM) 的话总是不幸第一个被 kill 掉。

解决这个问题最简单的办法就是增加内存,或者想办法优化 MySQL 使其占用更少的内存,

除了优化 MySQL 外还可以优化系统(优化 Debian 5,优化 CentOS 5.x),让系统尽可能使用少的内存以便应用程序(如 MySQL) 能使用更多的内存,还有一个临时的办法就是调整内核参数,让 MySQL 进程不容易被 OOM killer 发现。

配置 OOM killer

我们可以通过一些内核参数来调整 OOM killer 的行为,避免系统在那里不停的杀进程。比如我们可以在触发 OOM 后立刻触发 kernel panic,kernel panic 10秒后自动重启系统。

# sysctl -w vm.panic_on_oom=1
vm.panic_on_oom = 1# sysctl -w kernel.panic=10
kernel.panic = 10# echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
# echo "kernel.panic=10" >> /etc/sysctl.conf

从上面的 oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程。

这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(adj -= 30; 分数越低越不容易被杀掉)。

我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。

比如,如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后,调整 oom_score_adj 为 -15(注意 points 越小越不容易被杀):

# ps aux | grep mysqld
mysql    2196  1.6  2.1 623800 44876 ?        Ssl  09:42   0:00 /usr/sbin/mysqld# cat /proc/2196/oom_score_adj
0
# echo -15 > /proc/2196/oom_score_adj

当然,如果需要的话可以完全关闭 OOM killer(不推荐用在生产环境):

# sysctl -w vm.overcommit_memory=2# echo "vm.overcommit_memory=2" >> /etc/sysctl.conf

找出最有可能被 OOM Killer 杀掉的进程

我们知道了在用户空间可以通过操作每个进程的 oom_adj 内核参数来调整进程的分数,这个分数也可以通过 oom_score 这个内核参数看到,比如查看进程号为981的 omm_score,这个分数被上面提到的 omm_score_adj 参数调整后(-15),就变成了3:

# cat /proc/981/oom_score
18# echo -15 > /proc/981/oom_score_adj
# cat /proc/981/oom_score
3

下面这个 bash 脚本可用来打印当前系统上 oom_score 分数最高(最容易被 OOM Killer 杀掉)的进程:

# vi oomscore.sh
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); doprintf "%2d %5d %s\n" \"$(cat $proc/oom_score)" \"$(basename $proc)" \"$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10# chmod +x oomscore.sh# ./oomscore.sh18   981 /usr/sbin/mysqld4 31359 -bash4 31056 -bash1 31358 sshd: root@pts/61 31244 sshd: vpsee [priv]1 31159 -bash1 31158 sudo -i1 31055 sshd: root@pts/31 30912 sshd: vpsee [priv]1 29547 /usr/sbin/sshd -D

转载于:https://www.cnblogs.com/MacoLee/p/5666951.html

理解和配置 Linux 下的 OOM Killer相关推荐

  1. 配置linux下oracle sqlplus/rman等历史记录回调功能

    配置linux下oracle sqlplus/rman等历史记录回调功能 ############################################################ # ...

  2. linux 无损拆分分区 asm,利用UDEV SCSI Rules配置linux下的ASM

    利用UDEV SCSI Rules配置linux下的ASM 使用oracle的ASM(Automatic Storage Manager),针对磁盘设备来说要有正确的权限和拥有者和拥有组来,oracl ...

  3. linux怎么设置自动缩进,配置Linux下vim自动缩进等功能

    从终端打开配置文件: vim ~/.vimrc 添加如下代码: set tabstop=4 set softtabstop=4 set shiftwidth=4 set autoindent set ...

  4. Linux内存清道夫--OOM Killer

    1.OOM Killer 1.1.OOM Killer定义 OOM(Out Of Memory) Killer作为linux系统中守护进程,主要在系统内存严重不足时开始工作.出现这种情况是因为服务器上 ...

  5. Linux 的 Out-of-Memory (OOM) Killer

    同事在 Linux 服务器上遇到点小问题,我也上去折腾半天.这还是第一次注意到 Linux 这个多年来就存在的特性:OOM Killer .说白了 OOM Killer 就是一层保护机制,用于避免 L ...

  6. linux mysql jdk路径配置,Linux下的jdk1.5+eclipse+mysql开发环境配置的经验总结

    先说个题外话,由于我一直都是用windows系统,所以很多资料都保存在windows分区.在linux挂载NTFS分区对于我太复杂,所以我就使用了U盘.我想也会有很多朋友和我一样,我就先说一下U盘的使 ...

  7. linux日志采集配置,linux下配置rsyslog日志收集服务器案例

    原标题:linux下配置rsyslog日志收集服务器案例 环境配置 centos6系统 client1:192.168.1.33 centos7系统 client2:192.168.1.44 cent ...

  8. linux下mysql的配置,Linux下Mysql配置()

    摘要 腾兴网为您分享:Linux下Mysql配置(),智慧医疗,小太阳,享家,相机美颜等软件知识,以及重庆地税12366,正常的小学上课时间表,移动云信,dnf幸运冒险家,八爪龙演播大师,几米入早教, ...

  9. linux下添加mq队列管理配置,linux下 MQ第二弹:队列管理器的配置,实现双机MQI通道异步双向通信,亲测!!...

    本人前面文章一提到MQ 在linux下的安装,在此只描述队列管理器的配置,实现MQI通道的双向通讯. 一下方法我已亲测!! 贴出A,B两机的MQ配置记录: A机: #**--------------- ...

最新文章

  1. FASHION STORE OPENCART 2.X 自适应主题模板 ABC-0588
  2. 圆头像 微信小程序 绘图_小程序canvas绘制圆形微信头像
  3. mysql 安装dso命令_LAMP环境搭建
  4. 用 Parity 发送 ERC20 Token
  5. c++函数模板和类模板
  6. jvm 垃圾收集算法_JVM垃圾收集和优化
  7. TestContainers和Spring Boot
  8. c语言正则表达式_CS143:编译原理|PA2:正则表达式和词法分析
  9. 【Day03】使用原型最大的好处及原型链的理解
  10. (14)Verilog数据类型-基本语法(二)(第3天)
  11. vue监听路由的变化,跳转到同一个页面时,Url改变但视图未重新加载问题
  12. solve stiffness matrix in matlab
  13. Android AP模式创建有/无密码热点
  14. ListView嵌套ScrollView后,设置dividerHeight属性后高度计算
  15. ajax实例详解(2)
  16. HCIE-Datacom V1.0 考试大纲
  17. python导入数据画直方图加正态曲线_用python制作正态分布图
  18. 数学专业偏向算法智力题的面试题
  19. 题目选自《第八届图灵杯》-------买花
  20. 倍福PLC的C++ ADS通讯定义数据类型时注意事项

热门文章

  1. php输出json html,html怎样格式化输出JSON数据
  2. 孙正义的软银愿景宫斗内幕:印度裔高管争宠,黑公关手段,设局桃色仙人跳...
  3. 一批美国名校被曝监控学生:14秒记录一次手机位置,想翘课更难了
  4. 高清重制版阿波罗11号录像,英伟达RTX还原50年前登月细节
  5. 给GAN一句描述,它就能按要求画画,微软CVPR新研究 | 附PyTorch代码
  6. sprint计划会议总结
  7. HTML5游戏开发(四):飞机大战之显示场景和元素
  8. UVA 122 Trees on the level 二叉树 广搜
  9. 怎么快速解决KeyShot占CPU100%问题
  10. lesson4-Qt窗口