【系统运维】OOM - Out of Memory的原理与相关配置

tanglu 219 2021-12-22

一、什么是OOM

OOM即out of memory,即系统在自身内存耗尽时的自我拯救措施。当系统内存不足时,由系统选择一个进程杀死以释放出内存,这个被杀的进程通常是使用内存最高的程序。这里使用了"通常"一词是因为系统在进行选择时,会参考多个因素。除了进程占用内存外,还和进程运行的时间、进程优先级、是否为root用户进程、子进程个数以及用户控制参数oom_adj相关。当触发OOM后,系统会使用select_bad_process函数遍历所有进程,并按照多个因素进行打分,最终oom_score分数最高的进程就是被杀掉的对象。


二、oom_adj设置

前面提到用户通过参数oom_adj可以影响OOM分数,而这个参数就是通过/proc/<pid>/oom_adj文件进行控制。该文件可配置范围为-16——15,如果配置为-17则代表该进程不会被系统杀死。所以如果有某个进程不能发生OOM的话,可以将该服务oom_adj 为-17


三、overcommit_memory

除了oom_adj文件外,还需要注意/proc/sys/vm/overcommit_memory的配置,该文件支持配置的值为0,1,2

· 当参数为0时为启发式OOM,即当申请的虚拟内存不是很夸张的大于物理内存时,系统会允许该申请。但是当进程申请的虚拟内存很夸张的大于物理内存,则产生OOM。例如只有Redis服务器内存为8G,Redis占用了3G的物理内存,但是在虚拟内存中存在24G数据,这个时候执行bgsave命令后,子进程会申请24G的虚拟内存,这明显大于很物理内存,然后触发OOM

· 当参数为1时则永远允许overmemory内存申请,即不管申请多大的虚拟内存系统会都允许,直到系统内存耗尽产生OOM。在上面那个Redis案例中,如果overcommit_memory=1是不会产生OOM的,因为物理内存足够
· 当参数为2时则永远都不能超出某个限定额的内存申请,这个限定额为SWAP+RAM* 系数(/proc/sys/vm/overcmmit_ratio,默认50%,可以自己调整),如果资源用光,后面任何尝试申请内存的行为都会返回错误,此时没法运行任何新程序


四、系统内存回收

当系统内存不足时有两种方式进行内存释放,一种是手动回收,另一种是系统自己触发的内存回收

1、手动回收内存

通过/proc/sys/vm/drop_caches文件可以手动释放pagecache中的内存,需要注意如果pagecache中有脏数据时,通过drop_caches是不能释放的,必须通过sync命令将脏数据刷新到磁盘再通过操作 drop_caches释放pagecache

· 当drop_caches为1时将释放pagecache中可释放的部分(有些 cache 是不能通过这个释放的)

· 当drop_caches为2时将释放dentries和inodes缓存

· 当drop_caches为3时同时释放上述两项

echo 1 >> /proc/sys/vm/drop_caches


2、系统自动回收内存

当系统内存不足时会有一套自我整理内存,会尽可能的释放内存。如果这套机制工作后依然不能释放足够多的内存,则发生OOM。这个自动回收内存原理是通过kswapd进程去周期性的检查内存使用情况,当内存水平低于某个极限阈值时会直接发出内存回收。由于SWAP发生后很占用系统IO,为了避免突发性的大量SWAP发生,导致服务器不能对外提供服务,可以通过swappiness参数进行相关设置,该参数对应文件为/proc/sys/vm/swappiness。该值越高越可能使用SWAP的方式回收内存,最大值为100。关于SWAP相关设置,可参考《【系统运维】SWAP交换分区介绍与配置教程

版权声明
本站所有文章均为原创,转载请注明出处!小站维护不易,如果对您有所帮助,希望能点击一下站内广告,谢谢!
上一篇:【MySQL运维】MySQL 8.0新特性介绍与升级MySQL 8.0
下一篇:【Redis运维】Redis 5.x配置文件示例与说明
相关文章

 发表评论

暂时没有评论,来抢沙发吧~

微信二维码