为什么 Vultr VPS 内存不足导致 OOM Killer 进程被杀?

文章导读
Vultr VPS 内存不足导致 OOM Killer 进程被杀的根本原因在于 Linux 内核的内存管理机制。当物理内存和 Swap 空间耗尽时,内核为了保护系统不崩溃,会触发 OOM Killer 机制,强制终止占用内存较高的进程。在 Vultr 等云服务器上,由于内存资源通常是固定配额的,一旦应用程序(如 Java、MySQL)内存规划不当或存在泄漏,极易触发此机制。解决方案包括增加 VPS
📋 目录
  1. A 为什么我的进程被 kill 掉了
  2. B 记录一次应用被突然 kill 掉的问题定位经历
  3. C 故障分析 | MySQL OOM 故障应如何下手
  4. D 细说|Linux Out Of Memory 机制
  5. E 深入了解 Linux OOM Killer:一次可怕的内核事件
  6. F FAQ
A A

Vultr VPS 内存不足导致 OOM Killer 进程被杀的根本原因在于 Linux 内核的内存管理机制。当物理内存和 Swap 空间耗尽时,内核为了保护系统不崩溃,会触发 OOM Killer 机制,强制终止占用内存较高的进程。在 Vultr 等云服务器上,由于内存资源通常是固定配额的,一旦应用程序(如 Java、MySQL)内存规划不当或存在泄漏,极易触发此机制。解决方案包括增加 VPS 内存配置、优化应用内存使用、配置 Swap 分区或调整进程的 oom_score_adj 参数来降低被杀优先级。

为什么我的进程被 kill 掉了

先来看段代码:这段代码非常简单,就是先用 mmap 的方式,为该进程分配 10GiB 的虚拟内存,然后再用 page 写的方式,让操作系统为这 10GiB 虚拟内存,分配对应的物理内存,最后 sleep,等待我们测试。运行下:没啥问题,和我们预期的一样,正常执行。打开另一个终端,执行以下命令,看下它的内存占用:上图中的 VSZ 指的是虚拟内存,RSS 指的是物理内存,单位都是 KiB,所以该进程虚拟内存和物理内存的使用,都约等于 10GiB,没问题。我们再开个终端,再执行下这个程序:第二次执行这个程序也没问题,但奇怪的是,此时第一次执行的那个程序却被 kill 掉了:这是为什么呢?上面我们说到,该程序的逻辑是分配 10GiB 的物理内存,所以运行两次,也就是要分配 20GiB 的物理内存。但在我们的测试机器上,物理内存一共才 16GiB,所以,运行两个这样的进程肯定是不行的。在第二次执行该程序,且向操作系统申请物理内存时,操作系统会发现,物理内存已经没有了。此时,为了防止整个系统 crash 掉,linux 内核会触发 OOM/Out of Memory killing 机制,即按照一定的规则选择一个进程,将其 kill 掉,以便回收物理内存,以此来保证机器整体的稳定运行。

记录一次应用被突然 kill 掉的问题定位经历

以上信息可以看到内存溢出被 linux 杀掉的 java 应用信息; 4、但是我应用内存占用并不是特别高,通过 jinfo -flags 发现 java 应用的启动预申请内存达到了 10G; 启动参数 5、通过 free 或者 vmstat 查看剩余内存大小只有 10G 了,内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个"bad"进程杀掉,如何判断和选择一个"bad"进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程。6、oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠 (adj -= 30; 分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。

故障分析 | MySQL OOM 故障应如何下手

前阵子处理这样一个案例,某客户的实例 mysqld 进程内存经常持续增加导致最终被 OOM killer。作为 DBA 肯定想知道有哪些原因可能会导致 OOM(内存溢出)。OOM Killer(Out of Memory Killer) 是当系统内存严重不足时 linux 内核采用的杀掉进程,释放内存的机制。OOM Killer 通过检查所有正在运行的进程,然后根据自己的算法给每个进程一个 badness 分数,拥有最高 badness 分数的进程将会在内存不足时被杀掉。它打分的算法如下:某一个进程和它所有的子进程都占用了很多内存的将会打一个高分。为了释放足够的内存来解决这种情况,将杀死最少数量的进程 (最好是一个进程)。内核进程和其他较重要的进程会被打成相对较低的分。上面打分的标准意味着,当 OOM killer 选择杀死的进程时,将选择一个使用大量内存,有很多子进程且不是系统进程的进程。简单来讲,oom-killer 的原则就是损失最小、收益最大,因此它会让杀死的进程数尽可能小、释放的内存尽可能大。在数据库服务器上,MySQL 被分配的内存一般不会小,因此容易成为 oom-killer 选择的对象。

细说|Linux Out Of Memory 机制

有时候我们会发现系统中某个进程会突然挂掉,通过查看系统日志发现是由于 OOM 机制导致进程被杀掉。今天我们就来介绍一下什么是 OOM 机制以及怎么防止进程因为 OOM 机制而被杀掉。什么是 OOM 机制 OOM 是 Out Of Memory 的缩写,中文意思是内存不足。而 OOM 机制是指当系统内存不足时,系统触发的应急机制。当 Linux 内核发现系统中的物理内存不足时,首先会对系统中的可回收内存进行回收,能够被回收的内存有如下:读写文件时的页缓存。为了性能而延迟释放的空闲 slab 内存页。当系统内存不足时,内核会优先释放这些内存页。因为使用这些内存页只是为了提升系统的性能,释放这些内存页也不会影响系统的正常运行。如果释放上述的内存后,还不能解决内存不足的情况,那么内核会如何处理呢?答案就是:触发 OOM killer 杀掉系统中占用内存最大的进程。如下图所示:可以看出,OOM killer 是防止系统崩溃的最后一个手段,不到迫不得已的情况是不会触发的。

为什么 Vultr VPS 内存不足导致 OOM Killer 进程被杀?

深入了解 Linux OOM Killer:一次可怕的内核事件

一、简介 The OOM Killer 是内核中的一个进程,当系统出现严重内存不足时,它就会启用自己的算法去选择某一个进程并杀掉。之所以会发生这种情况,是因为 Linux 内核在给某个进程分配内存时,会比进程申请的内存多分配一些。这是为了保证进程在真正使用的时候有足够的内存,因为进程在申请内存后并不一定立即使用,当真正使用的时候,可能部分内存已经被回收了。比如 当一个进程申请 2G 内存时,内核可能会分配 2.5G 的内存给它。通常这不会导致什么问题。然而一旦系统内大量的进程在使用内存时,就会出现内存供不应求。很快就会导致内存耗尽。这时就会触发这个 oom killer,它会选择性的杀掉某个进程以保证系统能够正常运行。二、OOM Killer 理解 OOM Killer: Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存 (over-commit memory) 的办法来间接利用这部分“空闲”的内存,提高整体内存的使用效率。

FAQ

问:Vultr VPS 如何确认是否触发了 OOM Killer?

答:可以通过执行 dmesg -T | grep -i "out of memory" 命令查看内核日志,如果有相关记录则说明发生了 OOM 事件。

为什么 Vultr VPS 内存不足导致 OOM Killer 进程被杀?

问:如何降低重要进程被 OOM Killer 杀死的概率?

答:可以通过调整/proc//oom_score_adj 参数,将其设置为负数(如 -500),降低该进程的 OOM 评分,从而减少被杀风险。

问:增加 Swap 分区能完全解决 OOM 问题吗?

答:增加 Swap 可以缓解内存压力,但 Swap 位于硬盘上,读写速度远低于物理内存,频繁使用会导致系统性能严重下降,建议作为临时方案。