cgroup 限额与 maxmemory
容器里 Redis 能用的物理内存由 cgroup 限额决定:cgroup v2 对应 memory.max,cgroup v1 对应 memory/memory.limit_in_bytes,Kubernetes 里就是 resources.limits.memory。maxmemory 只是 Redis 自己的逻辑上限,用来触发键淘汰;两者作用对象不同,maxmemory 管数据区,cgroup 管整个进程的常驻内存。进程 RSS 一旦顶到 cgroup 红线,内核直接 OOM 杀进程(K8s 表现为 OOMKilled、退出码 137),Redis 没有机会执行淘汰或落盘,所以限额必须留出余量给复制缓冲、客户端缓冲和 fork 期间的写时复制。
基本信息
| 生效顺序 | cgroup 限额先于 maxmemory |
|---|---|
| cgroup v2 查看 | cat /sys/fs/cgroup/memory.max |
| cgroup v1 查看 | cat /sys/fs/cgroup/memory/memory.limit_in_bytes |
| K8s 对应项 | resources.limits.memory |
| 建议取值 | maxmemory 取限额的 70%~80% |
| RSS 语义 | 含分配器碎片与各类缓冲 |
| 调整权限 | 容器内可读,改限额需编排层操作 |
典型使用场景
- K8s 或 Docker 部署 Redis,需要确定 maxmemory 到底设多少
- 实例被反复 OOMKilled,要区分是 Redis 自身问题还是限额撞顶
- 内存水位告警设计时,为 RSS 与限额之间的差值单独设阈值
- 排查 maxmemory 从未触发淘汰但进程已经死的矛盾现象
- 给复制积压缓冲、客户端输出缓冲预留余量的容量规划
- 多容器混部在同一台宿主机上,判断是节点内存还是容器限额先到顶
容器内确认限额与用量
容器内确认限额与用量
cat /sys/fs/cgroup/memory.max # cgroup v2 限额
cat /sys/fs/cgroup/memory.current # 当前 cgroup 实际用量
redis-cli INFO memory | grep -E 'used_memory_rss|maxmemory'
redis-cli INFO memory | grep -E 'mem_fragmentation_ratio'
kubectl describe pod redis-0 | grep -i -A2 oom # 查 OOM 证据
docker inspect -f '{{.State.OOMKilled}}' redis # 容器是否被 OOM 杀过
kubectl top pod redis-0 # 与限额对照看余量内存指标对照
| 指标 | 含义 | 要点 |
|---|---|---|
| used_memory | 分配器统计的逻辑用量 | 淘汰判断依据 |
| used_memory_rss | 操作系统视角的常驻内存 | 比逻辑用量更早逼近 cgroup 红线 |
| maxmemory | 触发淘汰的阈值 | 需为复制与客户端缓冲留余量 |
| mem_fragmentation_ratio | rss 与逻辑用量之比 | 比值高时 RSS 增长快于逻辑用量 |
| memory.current | cgroup 统计的整进程用量 | 含 Redis 之外的同容器进程 |
把 maxmemory 设成等于容器限额是常见事故源:复制积压缓冲、客户端缓冲与 fork 期间的写时复制都不在 maxmemory 计数里,RSS 会先撞线。
改 cgroup 限额通常要重建容器或调整编排配置,属有损操作;能用容量规划与 maxmemory 解决的,优先不动限额。
同容器里还跑着监控 agent、日志采集等进程时,它们的 RSS 也计入 cgroup 用量,限额评估要把这部分算进去。