上一篇 下一篇 分享链接 返回 返回顶部

Page Cache占用过高导致业务OOM?香港服务器如何设置Drop Cache策略并合理释放内存?

发布人:Minchunlin 发布时间:2025-07-31 10:32 阅读量:801

我是负责外贸公司多台海外服务器运维工作的工程师,我本以为已经对线上服务资源调度了如指掌。但一次突如其来的线上事故彻底打破了这种自信——我们部署在香港的数据采集服务突然出现了频繁的 OOM(Out of Memory)异常,多个业务进程被内核直接 kill。这些服务器的硬件配置并不差,32G 内存,业务负载也不算高,起初我怀疑是内存泄漏,但深入排查后才发现,元凶竟然是——Page Cache 占用过高。

这次事件也让我意识到,即便不是内存泄漏,Linux 内核对缓存机制的“好意”也有可能在特定场景下反噬业务。下面是我如何定位问题、分析原因、制定 Drop Cache 策略,并最终解决这个问题的全过程。

一、问题定位:Page Cache 暴涨导致业务内存挤压

1.1 现象复盘

服务器进程频繁 OOM,查看 dmesg 输出类似如下:

Out of memory: Kill process 15323 (collector) score 902 or sacrifice child
Killed process 15323 (collector) total-vm:3030216kB, anon-rss:2670280kB, file-rss:40kB, shmem-rss:0kB

使用 free -m 查看内存使用情况:

            total        used        free      shared  buff/cache   available
Mem:          32000       28000         300         100        3700        1000

可以看到,buff/cache 占用了将近 3.7G 内存,而可用内存剩下不到 1G,显然 Page Cache 占用了大量资源。

1.2 Page Cache 是什么?

Linux 的内存管理采用“空闲即浪费”的理念,会自动将未使用的内存用于缓存磁盘文件内容,即 Page Cache,从而提升读写性能。但问题在于,当业务本身对内存敏感且瞬时需求上升时,Page Cache 不一定会“让路”给业务进程,反而导致内存紧张被 OOM Killer 触发。

二、深挖细节:Page Cache 持续增长的成因

我们业务中存在大量日志拉取、文件切分、磁盘扫描等操作,虽然都是短时间任务,但频繁的 read 和 stat 操作会导致内核不断将文件页缓存到内存中。而 Linux 不会自动清理 Page Cache,除非内存压力极大,或者我们主动干预。

在香港服务器上,这个问题尤其突出,可能与磁盘性能、IO Scheduler 策略和业务负载特征有关。

三、解决思路:合理配置 Drop Cache 策略

3.1 Drop Cache 是什么?

Linux 提供了手动释放缓存的机制,可通过如下方式实现:

# 清除 Page Cache
echo 1 > /proc/sys/vm/drop_caches

# 清除 dentries 和 inodes
echo 2 > /proc/sys/vm/drop_caches

# 清除所有缓存(包括 Page Cache、dentries、inodes)
echo 3 > /proc/sys/vm/drop_caches

注意:执行前建议先进行 sync,以免清除掉尚未写入磁盘的缓存页

sync && echo 3 > /proc/sys/vm/drop_caches

3.2 设置定时释放策略(以香港服务器为例)

步骤一:创建自动释放脚本

#!/bin/bash
# 文件名:drop_cache.sh

# 同步磁盘数据
sync

# 释放 Page Cache、dentries、inodes
echo 3 > /proc/sys/vm/drop_caches

# 日志记录
echo "$(date '+%Y-%m-%d %H:%M:%S') - Dropped cache" >> /var/log/drop_cache.log

赋予执行权限:

chmod +x /usr/local/bin/drop_cache.sh

步骤二:配置 crontab 定时任务

crontab -e

添加以下内容(每小时执行一次):

0 * * * * /usr/local/bin/drop_cache.sh

可根据实际业务负载调整频率,例如低峰期频率加高,业务高峰期避免释放缓存。

四、进阶优化:动态释放与内核参数调整

4.1 使用 systemd 定时器实现更可靠的执行

比 cron 更现代的做法是使用 systemd timer,不仅能监控任务状态,还能防止重启丢失任务。

4.2 动态监测 + 条件触发(智能释放)

配合 free 或 vmstat 实时判断内存情况,当可用内存低于阈值时再释放缓存,例如:

#!/bin/bash

# 设置阈值:单位为 MB
THRESHOLD=2048

available=$(free -m | awk '/Mem:/ {print $7}')
if [ "$available" -lt "$THRESHOLD" ]; then
    sync
    echo 3 > /proc/sys/vm/drop_caches
    echo "$(date '+%F %T') Dropped cache due to low memory ($available MB)" >> /var/log/drop_cache.log
fi

4.3 内核参数优化(非强制)

通过 /etc/sysctl.conf 或 sysctl -w 动态调整以下参数,有助于降低缓存占用:

vm.vfs_cache_pressure=200   # 提高dentry/inode回收倾向
vm.dirty_ratio=10           # 降低脏页比例
vm.dirty_background_ratio=5 # 更早开始写脏页

应用更改:

sysctl -p

五、运维工作的警钟与反思

这次香港服务器因 Page Cache 导致业务 OOM 的事故,对我来说是一次重要的警钟。作为运维工程师,我们不仅要掌握系统表象的处理技巧,更要理解 Linux 内核行为背后的逻辑。在复杂系统中,“不是 bug 的 bug”往往才是最致命的隐患。

通过设置合理的 Drop Cache 策略、动态内存监控和内核参数优化,我最终稳定了服务器运行环境。写这篇文章,不只是为了记录一场危机的应对过程,更是想提醒同行:性能优化,始于对操作系统行为的敬畏与理解。

目录结构
全文