结论:当内存耗尽且回收(回收页缓存、swap 等)也失败时,内核触发 OOM Killer,为每个进程计算 badness 分数(核心是该进程占用的内存比例,叠加 oom_score_adj 调整),杀掉得分最高的进程释放内存。
展开:细节:1)打分基础是进程 RSS + 页表 + swap 占用占可用内存的比例,root 进程有小幅折扣;2)/proc/<pid>/oom_score_adj(-1000 到 1000)是用户态干预入口——设为 -1000 基本免杀,正值放大被杀概率,数据库等关键服务常设负值保护;3)触发条件比"内存用光"复杂:内存分配在慢速路径上反复回收失败(直接回收、kswapd、压缩都无进展)才会走到 OOM;cgroup v2 还有独立的 memory.oom.group 语义,允许整组一起杀。易错点:OOM Killer 杀的不一定是元凶——大内存进程得分高,但可能是无辜的消费者;overcommit 策略(vm.overcommit_memory=0 默认启发式允许超分)决定了分配阶段不拒绝、运行期才爆雷的行为模式,Redis/Postgres 场景常讨论是否该严格限制。
排查手段:dmesg 里的 oom-kill 记录会列出当时各进程得分;echo f > /proc/sysrq-trigger 可手动触发测试。
追问方向:cgroup 内存限制触发的 cgroup OOM 与全局 OOM 的区别、早期用户态 OOM(earlyoom、systemd-oomd)的价值。