容器不主动释放缓存,真正响应内存压力并回收非核心缓存的是linux内核的cgroups v2 memory controller;需配置memory.low和memory.high参数,配合禁用swap与启用memory_reclaim_enabled,使内核在内存紧张时优先回收page cache、tmpfs、slab等可回收内存,避免oom。
容器本身不主动“释放缓存”,它没有操作系统级的缓存管理权限;真正能响应宿主机内存压力、主动回收非核心缓存的是linux内核的内存子系统(cgroups v2 + memory controller),而容器只是运行在其中的一个控制组。所谓“容器主动释放”,本质是通过合理配置 cgroup 内存参数,让内核在宿主机内存紧张时,优先压缩或回收该容器内可回收内存(如 page cache、slab、tmpfs),而非直接 oom kill。
要实现“宿主机物理内存告警时主动释放非核心缓存”,关键不是改容器应用,而是配置容器的 cgroup v2 内存软限与回收策略,并确保宿主机启用对应内核机制。以下是具体落地方式:
一、启用 cgroup v2 并确认内核支持
Docker 默认从 20.10+ 开始默认启用 cgroup v2(需宿主机内核 ≥5.4)。验证方式:
stat -fc %T /sys/fs/cgroup # 输出应为 "cgroup2fs" cat /proc/sys/kernel/unprivileged_userns_clone # 应为 1(推荐)
若未启用,需在 GRUB 启动参数中添加 systemd.unified_cgroup_hierarchy=1 并重启。
二、设置 memory.low 和 memory.high(核心手段)
这两个参数是触发“主动回收”的关键开关,仅在 cgroup v2 下有效:
-
memory.low:内存保障水位(soft reservation)。内核会尽量保留不低于此值的内存给该 cgroup,但不阻止回收。 -
memory.high:内存压力触发阈值。当 cgroup 使用内存超过此值,内核立即启动后台异步回收(kswapd),优先释放 page cache、tmpfs、slab 等可回收内存,不会杀进程。
例如,为容器设置:
docker run -d \ --memory=2g \ --memory-reservation=1g \ # 对应 cgroup v1 的 soft_limit,v2 中建议用 memory.low --ulimit memlock=-1:-1 \ --name cache-friendly-app \ -e JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=60.0" \ my-java-app
但 Docker CLI 不直接暴露 memory.low/memory.high,需通过以下任一方式配置:
✅ 方式1:使用 systemd 服务单元(推荐,生产可控)
将容器作为 systemd service 运行,并在 .service 文件中写入:
[Service] MemoryLow=800M MemoryHigh=1.5G MemoryMax=2G
然后 systemctl daemon-reload && systemctl start my-container.service
✅ 方式2:启动后手动写入 cgroup(适合调试)
# 获取容器对应的 cgroup path(以 containerd 为例)
CGROUP_PATH="/sys/fs/cgroup/system.slice/docker-$(docker inspect -f '{{.Id}}' cache-friendly-app).scope"
echo 838860800 > $CGROUP_PATH/memory.low # 800MB
echo 1572864000 > $CGROUP_PATH/memory.high # 1.5GB
⚠️ 注意:
memory.low值必须 ≤memory.high≤memory.max,且三者单位均为字节。
三、配合内核行为优化:禁用 swap + 启用 memory.reclaim
确保宿主机配置支持及时回收:
# 禁用 swap(避免延迟回收,强制走 page reclaim) sudo swapoff -a # (永久禁用:注释 /etc/fstab 中 swap 行) # 启用 cgroup v2 的自动回收开关(Linux 5.15+) echo 1 | sudo tee /proc/sys/vm/memory_reclaim_enabled
此时,当宿主机整体内存紧张(如 MemAvailable memory.high 超标的组触发 memcg reclaim,优先回收:
- 文件页缓存(page cache)
- tmpfs 内存盘内容(⚠️前提是该 tmpfs 挂载在该 cgroup 下)
- slab 分配器中的可回收对象(如 dentry、inode 缓存)
而 JVM 堆、应用私有匿名页等不可回收内存不受影响,因此不会导致 OOM 或业务中断。
四、验证是否生效
监控两项指标即可确认机制运行:
# 查看该容器 cgroup 的回收统计 cat /sys/fs/cgroup/system.slice/docker-*.scope/memory.events # 关注:low, high, max —— 当 high > 0,说明已触发过回收 # 查看实际回收量 cat /sys/fs/cgroup/system.slice/docker-*.scope/memory.stat | grep pgpgout
同时,在宿主机执行 free -h 观察 Available 是否回升,slabtop 查看 dentry/inode_cache 是否下降,即表明非核心缓存正在被主动释放。
不复杂但容易忽略











