先确认swap是否真被使用:用cat /proc/pid/status | grep -i swap查swap字段是否>0,若为0则卡顿与swap无关;vm.swappiness=1比=0更稳,须同步关闭thp、设overcommit_memory=1并均衡numa内存。

fork后Redis被换出到Swap,先确认是不是真问题
别一看到延迟就关Swap或调maxmemory。真实Swap压力得靠进程级数据验证:redis-cli info | grep process_id拿到PID,再执行cat /proc/<pid>/status | grep -i swap</pid>,重点看Swap字段是否大于0(不是SwapPss)。如果为0,说明卡顿跟Swap无关,后续所有调整都是白忙。
vm.swappiness=1比=0更稳,且必须配合THP关闭
vm.swappiness=60是默认值,但它会让内核在空闲内存还剩40%时就开始把Redis的COW页换出——这不是内存不足,是策略误伤。设为0看似彻底禁Swap,但OOM Killer可能在最后一刻直接杀掉Redis;设为1才是生产环境更稳妥的选择。
但只调swappiness没用,必须同步关闭透明大页:
echo never > /sys/kernel/mm/transparent_hugepage/enabled- 验证是否生效:用
grep -i "2048 kB" /proc/$(pgrep redis-server)/smaps,输出为空才算成功 - 该设置需写入
/etc/rc.local或systemdExecStartPre,否则重启失效
fork失败报“Cannot allocate memory”?查vm.overcommit_memory
日志里出现Can't save in background: fork: Cannot allocate memory,往往不是Redis内存用超了,而是内核在vm.overcommit_memory=2下严格校验total_vm(即VmSize)是否可承诺。Redis的VmSize常是VmRSS的2~3倍,内核一看“虚报这么多”,直接拒绝fork。
正确做法是两步同步改:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 立即生效:
sudo sysctl vm.overcommit_memory=1 - 同时调低swap倾向:
sudo sysctl vm.swappiness=1 - 永久写入
/etc/sysctl.conf并sysctl -p
只改overcommit_memory却不调swappiness,在残留策略下问题反而更顽固。
NUMA架构下,swap抖动可能来自内存分配不均
双路Xeon等NUMA服务器上,即使swappiness=1、THP已关,Redis仍可能在AOF重写时猛占Swap。这是因为主进程被调度到node 0,而该node本地内存已满,内核宁愿换出页,也不跨node分配。
缓解方法有限但有效:
- 启动Redis前加
numactl --interleave=all,强制内存跨node均匀分配 - 检查
numastat -p $(pgrep redis-server),确认各node内存使用是否严重倾斜 - 若无法改启动方式,至少确保
/proc/<pid>/status</pid>中MMU相关字段无异常放大
真正难处理的是:这些参数彼此耦合,swappiness调对了但THP没关,或overcommit_memory改了但NUMA没均衡,效果都会打折扣。排查必须从/proc/<pid>/smaps</pid>和/proc/<pid>/status</pid>原始数据出发,不能只信监控图表或free命令输出。










