文章目录
- 问题
- 可能原因分析
- 可能原因分析
- 尝试各种解决方案
- 尝试解决过程
- 解决办法: 调整 overcommit_meory参数
- overcommit_memory详解
- 什么是 `overcommit_memory`?
- `overcommit_memory` 的选项及其含义
- 配置 `overcommit_memory`
- 查看当前设置
- 设置 `overcommit_memory`
- 配置 `overcommit_ratio`
- 参数设置对系统的影响
- 启发式内存分配(0)
- 总是允许内存分配(1)
- 禁止过度分配(2)
- 实例与使用建议
- 数据库服务器
- 高性能计算应用
- RedHat官网调优指南 (临时或永久改变系统的内存管理行为)
- 临时调整内存参数
- 永久调整内存参数
- 参考命令
问题
启动的时候直接抛出如下异常
Native memory allocation (mmap) failed to map 2879048192 bytes for committing reserved memory
在 Linux 上部署项目时遇到 Native memory allocation (mmap) failed to map 2879048192 bytes for committing reserved memory
错误,这通常表明系统在尝试分配内存时遇到了问题。虽然 free
命令显示有足够的可用内存,并且 ulimit -a
显示内存没有被限制,但仍可能有其他原因导致该问题。
可能原因分析
可能原因分析
-
内存碎片化:
- 尽管
free
显示有足够的可用内存,但这些内存可能不是连续的。mmap
需要分配连续的内存块,如果内存碎片化严重,可能无法找到足够大的连续内存块。
- 尽管
-
地址空间不足:
- 32 位系统的虚拟地址空间有限,即使物理内存充足,虚拟地址空间也可能不足。
- 64 位系统通常不太可能出现这个问题,但在极端情况下(例如,系统运行多个内存密集型应用程序)也可能发生。
-
内核参数限制:
- 某些内核参数(如
vm.max_map_count
、vm.overcommit_memory
)可能限制了内存分配。
- 某些内核参数(如
-
容器或虚拟机限制:
- 如果在 Docker 容器或虚拟机中运行应用程序,容器或虚拟机本身可能有内存限制。
尝试各种解决方案
-
检查内存碎片化:
- 使用
cat /proc/meminfo
查看内存详细信息。 - 重点关注
MemFree
、MemAvailable
、HugePages_Total
和HugePages_Free
。 - 使用
sudo sysctl -a | grep vm.min_free_kbytes
确认内核保留的最小空闲内存。
- 使用
-
调整内核参数:
vm.max_map_count
:最大 mmap 区域数。sudo sysctl -w vm.max_map_count=262144
vm.overcommit_memory
:内存过度提交策略。 【我们通过调整参数,临时修复了该问题】sudo sysctl -w vm.overcommit_memory=1
-
检查虚拟地址空间:
- 确保系统运行在 64 位模式下。
- 检查应用程序是否有特定的内存限制。
-
检查容器/虚拟机限制:
- 对于 Docker 容器:
docker inspect <container_id> | grep Memory
- 对于虚拟机,检查虚拟机管理工具的内存设置。
- 对于 Docker 容器:
尝试解决过程
-
检查内存详细信息:
cat /proc/meminfo
-
检查内核参数:
sudo sysctl -a | grep vm
-
调整内核参数:
sudo sysctl -w vm.max_map_count=262144 sudo sysctl -w vm.overcommit_memory=1
-
检查 Docker 容器内存设置:
docker inspect <container_id> | grep Memory
解决办法: 调整 overcommit_meory参数
调整 overcommit_meory参数。
overcommit_memory详解
在 Linux 操作系统中,内存分配是一个关键的任务。内存的高效使用和管理直接影响系统的性能和稳定性。overcommit_memory
是一个重要的内核参数,用于控制内存分配策略。
什么是 overcommit_memory
?
overcommit_memory
是 Linux 内核中的一个参数,通过 /proc/sys/vm/overcommit_memory
文件进行配置。它决定了内核如何处理内存分配请求,尤其是在可用物理内存不足的情况下。
overcommit_memory
的选项及其含义
overcommit_memory
参数有三个可能的值,每个值对应一种特定的内存分配策略:
-
0 - 启发式内存分配(默认值)
- 内核根据一定的启发式算法决定是否允许内存分配请求。内核会考虑当前的内存使用情况和预期的内存需求,通常会允许合理范围内的内存过度分配。
- 优点:灵活性较高,适合大多数应用场景。
- 缺点:可能在内存非常紧张时导致 OOM(Out Of Memory)错误。
-
1 - 总是允许内存分配
- 内核允许所有内存分配请求,无论当前的内存使用情况如何。这意味着即使系统内存已经耗尽,内核也会继续分配内存。
- 优点:极大的灵活性,确保所有内存分配请求都能成功。
- 缺点:可能导致严重的内存不足问题,甚至导致系统崩溃。
-
2 - 禁止过度分配
- 内核严格限制内存分配,只有在有足够的物理内存和交换空间时才允许内存分配请求。这个策略会结合
overcommit_ratio
参数来确定可用的内存总量。 - 优点:提高系统稳定性,防止 OOM 错误。
- 缺点:降低内存分配灵活性,可能拒绝一些合理的内存分配请求。
- 内核严格限制内存分配,只有在有足够的物理内存和交换空间时才允许内存分配请求。这个策略会结合
配置 overcommit_memory
可以通过以下命令查看和设置 overcommit_memory
参数:
查看当前设置
cat /proc/sys/vm/overcommit_memory
设置 overcommit_memory
例如,将 overcommit_memory
设置为 1:
echo 1 > /proc/sys/vm/overcommit_memory
配置 overcommit_ratio
如果 overcommit_memory
设置为 2,还需要配置 overcommit_ratio
参数来决定可用内存总量。overcommit_ratio
是一个百分比值,表示可分配的物理内存和交换空间的比例。
echo 50 > /proc/sys/vm/overcommit_ratio
这个配置表示内核允许分配的内存总量为物理内存加上 50% 的交换空间。
参数设置对系统的影响
启发式内存分配(0)
这种设置平衡了灵活性和稳定性,适合大多数应用场景。系统会尝试合理地分配内存,防止过度分配,但在极端情况下可能仍会遇到 OOM 错误。
总是允许内存分配(1)
这种设置提供了最大的灵活性,但也伴随着最高的风险。适用于需要极大内存灵活性的场景,如高性能计算或科学计算,但需注意可能的内存不足问题。
禁止过度分配(2)
这种设置提供了最大的稳定性,适用于需要严格内存控制的场景,如数据库服务器或关键业务应用。通过合理设置 overcommit_ratio
,可以确保系统不会因内存不足而崩溃。
实例与使用建议
数据库服务器
对于数据库服务器,建议使用禁止过度分配的策略(设置 overcommit_memory
为 2),并合理配置 overcommit_ratio
以确保稳定性。例如,对于一个拥有 16GB 内存和 8GB 交换空间的系统,可以将 overcommit_ratio
设置为 50:
echo 2 > /proc/sys/vm/overcommit_memory
echo 50 > /proc/sys/vm/overcommit_ratio
高性能计算应用
对于高性能计算应用,可以考虑启用总是允许内存分配的策略(设置 overcommit_memory
为 1),以确保所有内存分配请求都能成功:
echo 1 > /proc/sys/vm/overcommit_memory
RedHat官网调优指南 (临时或永久改变系统的内存管理行为)
https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-captun
在 Linux 上,调整内存相关参数可以临时或永久改变系统的内存管理行为。
临时调整内存参数
临时调整内存参数可以通过向 /proc/sys
文件系统中的相应文件写入值来实现。这种方法在系统重启后会失效,需要重新设置。
-
调整
overcommit_memory
参数:echo 1 > /proc/sys/vm/overcommit_memory
-
调整
overcommit_ratio
参数:echo 50 > /proc/sys/vm/overcommit_ratio
-
调整
max_map_count
参数:echo 262144 > /proc/sys/vm/max_map_count
-
调整
nr_hugepages
参数:echo 128 > /proc/sys/vm/nr_hugepages
-
调整其他相关参数:
echo 65536 > /proc/sys/kernel/msgmax echo 65536 > /proc/sys/kernel/msgmnb echo 1985 > /proc/sys/kernel/msgmni echo 4294967296 > /proc/sys/kernel/shmall echo 68719476736 > /proc/sys/kernel/shmmax echo 4096 > /proc/sys/kernel/shmmni echo 32768 > /proc/sys/kernel/threads-max echo 65536 > /proc/sys/fs/aio-max-nr echo 1048576 > /proc/sys/fs/file-max
永久调整内存参数
为了使内存参数的调整在系统重启后依然有效,可以将这些设置写入 /etc/sysctl.conf
文件,或在 /etc/sysctl.d/
目录下创建一个新的配置文件。
-
编辑
/etc/sysctl.conf
文件:sudo nano /etc/sysctl.conf
添加以下内容:
vm.overcommit_memory = 1 vm.overcommit_ratio = 50 vm.max_map_count = 262144 vm.nr_hugepages = 128 kernel.msgmax = 65536 kernel.msgmnb = 65536 kernel.msgmni = 1985 kernel.shmall = 4294967296 kernel.shmmax = 68719476736 kernel.shmmni = 4096 kernel.threads-max = 32768 fs.aio-max-nr = 65536 fs.file-max = 1048576
-
创建新的配置文件(例如
/etc/sysctl.d/99-custom.conf
):sudo nano /etc/sysctl.d/99-custom.conf
添加相同的内容:
vm.overcommit_memory = 1 vm.overcommit_ratio = 50 vm.max_map_count = 262144 vm.nr_hugepages = 128 kernel.msgmax = 65536 kernel.msgmnb = 65536 kernel.msgmni = 1985 kernel.shmall = 4294967296 kernel.shmmax = 68719476736 kernel.shmmni = 4096 kernel.threads-max = 32768 fs.aio-max-nr = 65536 fs.file-max = 1048576
-
应用配置:
sudo sysctl -p
参考命令
-
临时调整参数:
echo 1 > /proc/sys/vm/overcommit_memory echo 262144 > /proc/sys/vm/max_map_count
-
永久调整参数:
sudo nano /etc/sysctl.d/99-custom.conf sudo sysctl -p