上次帮一个制造业客户排查问题,他们的订单服务连续3天在凌晨被OOM杀掉,翻日志只看到"Killed process 1234 (java) total-vm:2048000kB",找了半天找不到是谁占了内存把核心进程挤死了,最后发现是他们内部跑的Python数据同步脚本,每次同步要占18G内存,启动时间刚好比订单服务早10秒,oom_score算出来比订单服务高200多分,内核直接把占内存更大的订单服务杀了。
你说冤不冤?
很多人以为OOM杀的就是占内存最多的那个进程。
大错特错。
这也是为什么你光搜"Out of memory"的日志,经常看不到全貌——内核在打印日志的时候,只会把最终被杀的那个进程信息打出来,触发OOM的内存占用大户,往往只是在日志里留了个模糊的内存统计行,稍不注意就漏过去。
这里教个最快的拆解方法:拿到OOM日志之后,先找日志里的"Memory cgroup out of memory"或者"Node 0 DMA"开头的内存统计块,从下往上数,找anon-rss列**的那个进程,那个就是占了最多内存、把系统挤到OOM的真凶。哦对,还要注意cgroup的边界——如果你是在容器环境,看到的日志是cgroup层面的OOM,那内存统计只会列当前cgroup里的进程,不会列主机上其他cgroup的进程,别把主机的内存统计和容器的搞混了。