overcommit_memory 是什么
vm.overcommit_memory 决定内核在应用申请内存(malloc、mmap、fork 等)时有多宽松。默认为 0,走启发式判断:明显超出物理内存加 swap 的申请会被拒绝,常规申请一律答应;1 表示总是答应,申请多少都先给,直到真的写满内存才由 OOM 机制处理;2 表示严格模式,按 CommitLimit 核算,超过上限的申请直接被拒。它管的是「申请承诺」而不是「实际占用」,因此对 fork、大页预留与数据库的行为影响很直接。
基本信息
| 参数 | vm.overcommit_memory |
|---|---|
| 取值 | 0 启发式(默认) / 1 总是允许 / 2 严格核算 |
| 严格模式公式 | CommitLimit = swap 总量 + 物理内存 × ratio%,也可用 vm.overcommit_kbytes 直接指定 |
| 当前承诺量 | /proc/meminfo 的 Committed_AS |
| 常见实践 | Redis 等依赖后台 fork 持久化的服务建议设为 1 |
| 拒绝表现 | 应用层看到 Cannot allocate memory |
典型使用场景
- Redis 等 fork 型持久化:避免启启发式判断拒绝 fork 所需的地址空间
- 故障复盘:应用报内存分配失败时,先区分是物理内存不足还是承诺额度被拒
- 容量核对:用 Committed_AS 与 CommitLimit 对比,判断是否存在明显的超售风险
- 严格管控环境:希望内存申请失败尽早暴露而不是留到运行时 OOM
- 容器与多租户主机:评估超售策略对邻居干扰与 OOM 行为的影响
查看与核对
查看与核对
sysctl vm.overcommit_memory # 读当前策略
sysctl vm.overcommit_ratio vm.overcommit_kbytes # 严格模式的额度来源
grep -E 'CommitLimit|Committed_AS|MemTotal|SwapTotal' /proc/meminfo # 额度与已承诺量
cat /proc/vmstat | grep -i commit # 承诺相关计数
sysctl -w vm.overcommit_memory=1 # 临时切到总是允许落盘与回读
落盘与回读
# /etc/sysctl.d/99-vm-tuning.conf
vm.overcommit_memory = 1 # 总是允许申请,配合应用侧的容量监控使用
# 回读命令:sysctl vm.overcommit_memory三种模式对比
| 取值 | 行为 | 适用与风险 |
|---|---|---|
| 0 | 启发式判断,明显超出容量的申请被拒 | 通用默认值,兼顾灵活性与明显异常拦截 |
| 1 | 一律允许,不做额度核算 | 适合 fork 与大预留场景,风险是运行时 OOM |
| 2 | 按 CommitLimit 严格核算,超限即拒 | 适合强管控环境,容易让大地址空间预留的应用启动失败 |
模式 1 不等于不会 OOM:它只是把拒绝的时机从申请阶段推迟到实际写入内存的阶段,此时由 OOM 机制来选择牺牲者。因此切到模式 1 之后,内存监控与 OOM 日志的收集必须跟上。
从 0 切到 2 之前必须核算现状:先读 Committed_AS 与切换后会得到的 CommitLimit,确认余量足够,否则应用会以分配失败的形式立刻报错。数据库与大堆内存的 JVM 服务尤其要谨慎,它们的地址空间预留量往往远超实际使用量。