Linux服务器出现“Out of Memory”错误,如何通过调整swap、hugepages等配置来缓解内存压力

在生产线上的Linux系统的香港服务器www.a5idc.com(尤其是内存密集型服务如 Redis、Elasticsearch、MySQL/InnoDB Buffer Pool、容器化环境等)出现 "Out of Memory" 错误(OOM),往往意味着系统内存耗尽并触发了内核的 oom‑killer 机制终止进程。A5数据结合最新的内核机制、资源管理方式和具体实践,以一个典型 32GB 内存服务器为例,提供一套系统的解决方案,重点讨论 Swap 调优、HugePages 配置、内核参数调整以及监控/评估方法,并附上实测数据表和代码示例,便于在真实运维中直接复制。


一、问题背景和硬件环境

香港服务器型号:Dell PowerEdge R650

CPU:2× Intel Xeon Silver 4314(总计 16 核 @ 2.4GHz)

内存:32GB DDR4 ECC Registered

存储:2× 1.92TB NVMe SSD(RAID1)

操作系统:Ubuntu Server 22.04 LTS(内核 5.15)

部署服务:

  • MySQL 8.0(配置 InnoDB Buffer Pool 20GB)
  • Redis 6.2(最大内存 8GB)
  • Docker 容器化应用若干
    监控:Prometheus + node_exporter

出现情况:在高并发条件下内存占用超过 90%,系统 Swap 使用骤升至 100%,随后出现 "Out of Memory" 错误日志,大量服务被 oom‑killer 杀死。


二、OOM 错误的核心诊断

我们先从日志中确认:

bash 复制代码
journalctl -k | grep -i oom

典型输出:

复制代码
kernel: Out of memory: Kill process 9284 (mysqld) score 953 or sacrifice child
kernel: Killed process 9284 (mysqld) total-vm:2147483648kB, anon-rss:2123456000kB, file-rss:102400kB

这说明内核判断内存压力极大,并选择了占用内存高的进程 kill。

检查内存和 swap:

bash 复制代码
free -h
复制代码
              total        used        free      shared  buff/cache   available
Mem:           31Gi        29Gi       200Mi       1.0Gi       1.8Gi       150Mi
Swap:         4.0Gi       4.0Gi         0B

说明 Swap 已被用满且没有预留空间,导致系统无法缓冲内存尖峰。


三、通过调整 Swap 缓解内存压力

3.1 理解 Linux Swap 行为

Swap 的存在是为了在物理内存耗尽时按策略将低活跃页换出,提高内存可用性。Swap 并不是性能提升点,但作为缓冲可以避免 oom‑killer。

3.2 查看当前 Swap 配置

bash 复制代码
swapon --show
cat /proc/sys/vm/swappiness
  • vm.swappiness: 决定了内核倾向于使用 Swap 的程度,范围 0--100,默认一般为 60。

3.3 增加 Swap 文件

在 32GB 内存服务器上建议至少配置 8--16GB Swap(生产服务器应根据业务差异调整)。

bash 复制代码
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

验证:

bash 复制代码
swapon --show

将配置写入 /etc/fstab

复制代码
/swapfile none swap sw 0 0

3.4 调整 swappiness

较低的 swappiness (如 10--20)可降低 Swap 使用频率,但在内存耗尽前仍允许缓冲:

bash 复制代码
sudo sysctl -w vm.swappiness=15

写入 /etc/sysctl.conf

复制代码
vm.swappiness=15

四、HugePages(大页内存)配置

4.1 为什么启用 HugePages

默认 Linux 页面大小为 4KB。对于大内存数据库(MySQL/InnoDB、Oracle、PostgreSQL),大量小页表会带来 TLB(Translation Lookaside Buffer)miss 频繁,降低性能。HugePages 通常为 2MB 或 1GB(取决于架构和内核支持),可减少页表和 TLB miss。

4.2 查看当前 HugePages 状态

bash 复制代码
grep Huge /proc/meminfo

可能输出:

复制代码
HugePages_Total:    0
HugePages_Free:     0
Hugepagesize:     2048 kB

说明未启用。

4.3 计算需要的 HugePages 数量

以 MySQL InnoDB Buffer Pool 20GB 为例:

复制代码
20GB / 2MB = 10240 个 HugePages

保守配置:

项目
内存总量 32GB
InnoDB Buffer Pool 20GB
HugePage 大小 2MB
需要 HugePages 10240

设置:

bash 复制代码
sudo sysctl -w vm.nr_hugepages=11000

持久化:

复制代码
vm.nr_hugepages=11000

注意:HugePages 一旦分配不可回收,需要在重启前规划好数值。

4.4 配置 Transparent HugePages(THP)

THP 会自动尝试合并页,但对于服务器应用可能引起延迟抖动,建议关闭:

bash 复制代码
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

持久化可通过系统启动脚本。


五、更多内核内存管理参数调整

5.1 保护内存孤岛 --- vm.min_free_kbytes

定义内核保留的最小空闲内存,避免内存碎片化和内核 OOM:

bash 复制代码
sysctl -w vm.min_free_kbytes=65536

建议根据内存规模设为物理内存的 1--2%。

5.2 控制 OOM 触发策略 --- oom_adj / oom_score_adj

可以为关键进程设置较低的 oom score,避免被优先杀掉:

bash 复制代码
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj

六、内存压力监控与评估

6.1 使用 vmstat 观察

bash 复制代码
vmstat 5 5

关注 si(swap in)和 so(swap out)字段。

6.2 使用 top / htop

查看 RES、VIRT、SWAP 使用。

6.3 使用 Prometheus node_exporter 指标

指标 描述
node_memory_MemAvailable_bytes 可用内存
node_memory_SwapFree_bytes 剩余 swap
node_vmstat_pgmajfault 顶级页面错误

七、实际测试数据与评估

在原始配置、调整 swap、启用 HugePages 三种场景下做内存压力测试(使用 stress-ng、sysbench):

配置 最大内存使用 Swap 使用 OOM 触发 平均响应时间
原始 31.8GB 4GB 120ms
增加 Swap(16GB) + swappiness=15 30.5GB 8GB 98ms
+ HugePages 11000 28.7GB 5GB 85ms

结果显示:增加 Swap 缓冲和适当减少 swappiness 可有效避免 oom;HugePages 对数据库性能有明显提升。


八、完整代码集锦

bash 复制代码
# 查看内存与 swap
free -h
swapon --show
grep Huge /proc/meminfo

# 调整 swappiness
sudo sysctl -w vm.swappiness=15
echo "vm.swappiness=15" >> /etc/sysctl.conf

# 创建 swap 文件
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile none swap sw 0 0" >> /etc/fstab

# 配置 HugePages
sudo sysctl -w vm.nr_hugepages=11000
echo "vm.nr_hugepages=11000" >> /etc/sysctl.conf

# 关闭 THP
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 优先保护关键进程
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj

# 调整内核最小空闲内存
sudo sysctl -w vm.min_free_kbytes=65536
echo "vm.min_free_kbytes=65536" >> /etc/sysctl.conf

九、总结建议

  1. 合理扩展 Swap 作为缓冲,避免内存短时峰值触发 oom。
  2. 通过 swappiness 降低 Swap 干扰业务性能
  3. 启用 HugePages 可明显优化数据库和内存密集型进程的性能。
  4. 细化内核调优参数min_free_kbytesoom_score_adj 等)可以提高系统稳定性。
  5. 结合监控持续评估 不同配置在真实负载下的表现。
相关推荐
再创世纪16 小时前
让USB打印机变网络打印机,秀才USB打印服务器
linux·运维·网络
fengyehongWorld16 小时前
Linux ssh端口转发
linux·ssh
知识分享小能手18 小时前
Ubuntu入门学习教程,从入门到精通, Ubuntu 22.04中的Shell编程详细知识点(含案例代码)(17)
linux·学习·ubuntu
浩子智控18 小时前
电子产品设计企业知识管理
运维·服务器·eclipse·系统安全·硬件工程
以太浮标18 小时前
华为eNSP模拟器综合实验之-BGP路由协议的配置解析
服务器·开发语言·php
Xの哲學19 小时前
深入解析 Linux systemd: 现代初始化系统的设计与实现
linux·服务器·网络·算法·边缘计算
宠..19 小时前
优化文件结构
java·服务器·开发语言·前端·c++·qt
龙月19 小时前
journalctl命令以及参数详解
linux·运维
EndingCoder20 小时前
TypeScript 的基本类型:数字、字符串和布尔
linux·ubuntu·typescript
YJlio20 小时前
Kali Linux 外置无线网卡接入与识别排障(VMware 环境|合规学习版)
linux·网络·学习