vm.swappiness过高导致内核过早换出匿名页;水位线设置不当引发回收延迟;脏页堆积阻塞writeback;cgroup v1硬限导致回收滞后。

vm.swappiness 设置过高导致内核过早换出匿名页
Linux 内存回收是否“及时”,首先取决于内核对内存压力的判断逻辑。vm.swappiness 控制的是内核在内存紧张时,倾向于回收文件页(page cache)还是换出匿名页(如进程堆、栈)的倾向值。默认是 60,但若设为 80 或更高,内核会更激进地将匿名页写入 swap,哪怕还有大量可回收的 page cache。
-
vm.swappiness=100:等同于“不区分页类型,能换就换”,容易掩盖真实内存压力,也拖慢回收响应 -
vm.swappiness=1到10更适合物理内存充足、追求低延迟的场景(如数据库服务器) - 查看当前值:
cat /proc/sys/vm/swappiness;临时修改:sysctl vm.swappiness=10
注意:该参数只影响“回收策略倾向”,不决定“是否触发回收”——真正触发回收的是 watermark 水位线。
内存水位线(watermark)设置不合理或被动态抬高
内核通过 min、low、high 三档 watermark 判断何时启动 kswapd 回收或直接阻塞分配。如果这些水位线被意外抬高(例如因大量 hugepage 预留、cgroup memory limit 过紧、或 /proc/sys/vm/lowmem_reserve_ratio 配置失当),会导致:
- kswapd 长时间不唤醒,直到内存耗尽才触发直接回收(direct reclaim),造成卡顿
- 即使有空闲 page cache,系统也拒绝分配,因为未跌破
low水位
验证方式:cat /proc/zoneinfo | grep -A 5 "pages free",关注各 zone 的 min 和 pages free 差值。若差值长期
脏页(dirty page)堆积阻塞 writeback 进程
当应用持续写文件且未显式 fsync(),或 vm.dirty_ratio 设得过大(如 80),会导致大量脏页滞留在内存中。此时即使有足够空闲内存,kswapd 也无法回收这些页——它们必须先由 pdflush(旧内核)或 writeback 线程刷盘。
常见现象:
前后台订单管理页添加商品缩图显示 后台系统设置可直接对商品缩图大小进行设置 去掉商品图片水印功能 上传一张图片,可同时生成列表页缩图及商品详细页缩图,以不同的大小满足页面不同的需要 商品收藏添加批量删除功能 修改商品详细页会员等级显示BUG 优化缩图生成功能(注:因此次优化已更换上传内核,所以有可能会影响已上传商品图片数据) 加入简繁转换 前台订单管理添加单订单在线支付功能 修正VS081样式前台
-
grep -i "dirty" /proc/meminfo显示Dirty:或Writeback:数值持续 > 500MB -
iostat -x 1观察%util不高,但await波动剧烈,说明 writeback 调度不及时
调整建议:
- 降低
vm.dirty_ratio至 20–30,配合vm.dirty_background_ratio设为 10–15,让后台刷盘更早启动 - 若应用本身控制写节奏,可考虑挂载时加
sync或使用O_SYNC
cgroup v1 的 memory.limit_in_bytes 导致子树回收滞后
在 cgroup v1 下,若容器或进程组设置了 memory.limit_in_bytes,但未配 memory.soft_limit_in_bytes,内核只会等到该 cgroup 内存用量真正触达硬限才开始回收——不会提前干预。这意味着:
- 其他 cgroup 可能已释放大量缓存,但受限 cgroup 仍卡在 high watermark 附近不动
-
memory.usage_in_bytes接近 limit 后,回收动作往往伴随 OOM killer 启动,而非平滑回收
解决方向:
- 升级到 cgroup v2(默认启用 memory.low 和 memory.high,支持软性分级回收)
- 若必须用 v1,至少设
memory.soft_limit_in_bytes为硬限的 80%,并确保memory.swappiness在该 cgroup 内单独调低
实际排查时,优先看 /sys/fs/cgroup/memory/xxx/memory.stat 中的 pgmajfault 和 pgpgout 增速,比单纯看 free 内存更能反映回收是否“跟得上”。







