当一个进程试图分配比可用内存更多的内存时,通常很难以一种好的方式处理这种情况。在某些情况下,程序可能能够释放非必要的内存(例如缓存),但在大多数情况下,它会导致致命的异常(另见[1])、交换和大规模系统减慢甚至杀死(相当随意) 使用OOM 杀手处理。
在单用户系统上,所有选项都不好,但至少你只能伤害自己(毕竟你对你机器上运行的所有代码负责)。
然而,在多用户系统上,我希望有可能让 OOM 杀手杀死可能由其他用户拥有的某些进程。有一定的限制,因为 OOM 杀手试图找到一个“正在使用大量内存但寿命不长的进程”(参见此处)。
然而,想象一个进程需要 x MB 内存并且没有存活很长时间(低 CPU 时间)并且由用户 X 拥有并且 x 明显多于系统上的可用内存的情况,用户 Y 可能能够分配比可用内存更多的内存并导致系统终止 X 的进程(因为它正在使用更多内存)。
这种情况听起来比单用户机器上的类似含义更可怕。可以为每个用户设置内存限制,甚至可以使用容器来进一步分离进程。但据我了解,只有将限制设置为total_memory / number_of_users
才能解决问题。但是,当设置这样的限制时,就会失去多用户系统的所有好处。该机器实际上类似于一个盒子中的多台单用户机器。人们通常希望允许一位用户在高峰时间使用更多内存,因为大多数时候用户需要的内存比平均内存少。
我最感兴趣的是在具有大量数据的大型计算的情况下解决这个问题。我想在 Web 服务器的情况下,可能能够更好地估计需要多少内存,因为有很多小操作,而不是少数大操作。但即使在这种情况下,我听说在正常情况下,只有 50% 的内存应该被填充,以避免在高峰期出现内存不足的问题。这不是浪费你50%的内存吗?
特别是我正在考虑托管一个 Jupyter 集线器或类似的东西。但我不希望用户杀死彼此的进程。
有没有其他解决方案可以缓解这个问题?像 Travis CI 这样的大型云提供商如何处理此类问题?
我相信现在限制一项任务对其他任务的影响的推荐方法是使用 cgroup 来限制它可以使用的内存。我发现最简单的方法是使用
systemd-run
. 例如,这以ls
1000 字节的低内存限制开始:运行journalctl -f,你会看到进程已经被立即杀死:
那么当然你会想要超额订阅机器,也许给每个任务 70% 的可用内存?这将允许内存消耗达到峰值,同时仍会快速终止使用不合理内存量的进程。
禁用 oom 杀手(
vm.oom-kill = 0
在由 读取的文件中sysctl
)并禁用内存过度使用 (vm.overcommit_memory = 2
)。任何试图分配超过可用内存的进程都将被终止。不会杀死其他进程。所有内存都可以使用;没有内存被浪费。这并不能防止内存占用。memory cgroup 的
memory.soft_limit_in_bytes
设置看起来可能有用(与memory.limit_in_bytes
and结合使用memory.memsw.limit_in_bytes
),但我没有找到关于它如何操作的详细说明。编辑:我查看
memory.soft_limit_in_bytes
了内核源代码中的使用方式。如果内存无法回收,则不会发生任何事情。您可以设置 sysctl
vm.oom_kill_allocating_task
。如果设置了此项,并且进程内存请求将导致内存不足,Linux 将终止该进程。从文档中: