redis周期性卡顿主因是linux的thp特性,开启后fork()触发的写时复制需拷贝2mb大页而非4kb,导致incr/set等命令进慢日志;须永久关闭thp(如grub加transparent_hugepage=never),并验证anonhugepages为0、rdb_last_bgsave_time_sec≤0.1s。

Redis 在 Linux 上出现周期性、不可预测的卡顿,大概率不是 Redis 自身 bug 或配置错误,而是操作系统层的 transparent_hugepage(THP)在作祟——它会让 fork() 后的内存写时复制(Copy-on-Write)开销暴增,直接拖慢所有写命令,哪怕 INCR、SET 这类简单操作也会进慢日志。
为什么 THP 会让 Redis 卡顿
Redis 的 RDB 持久化依赖 fork() 创建子进程。开启 THP 后,内核默认用 2MB 大页管理内存,而 Redis 主进程频繁分配/释放小对象(如字符串、dict entry),导致:
– fork() 虽快,但后续每个写操作触发的 COW 实际要拷贝 2MB 页,而非传统 4KB;
– khugepaged 后台线程持续扫描合并小页,与 Redis 内存操作争抢 mmap 锁,引发抖动;
– 即使启用了 madvise 模式(如 AWS Ubuntu 默认),Redis 的 malloc 行为仍会高频触发 THP 合并。
典型现象包括:
– INFO persistence 中 rdb_last_bgsave_time_sec 突然飙升到 2~5s(正常应 ≤0.1s);
– SLOWLOG GET 10 里大量 INCR、HSET 耗时超 10ms;
– strace -p $(pgrep redis-server) -e trace=fork,clone 显示 fork() 返回后,紧跟着大量 write 系统调用延迟毛刺。
怎么确认 THP 当前是否启用
别只信 Redis 启动日志里的 WARNING,有些发行版(如 RHEL/CentOS 6+)把路径改成了 /sys/kernel/mm/redhat_transparent_hugepage/enabled,而 Redis 源码里硬编码读的是 /sys/kernel/mm/transparent_hugepage/enabled,所以可能没报错但问题照旧。
执行以下命令逐个检查:
– cat /sys/kernel/mm/transparent_hugepage/enabled
– cat /sys/kernel/mm/redhat_transparent_hugepage/enabled(RHEL/CentOS 6+ 专用)
– cat /proc/cmdline | grep transparent_hugepage
只要任一输出含 [always] 或 [madvise],就说明 THP 未真正禁用。
PyCharm 2026.2.0.1 Linux版提供 JetBrains 官方 2026.2.0.1 版本安装包,适合需要指定 PyCharm 版本进行 Python 项目开发、运行和调试的用户。
永久关闭 THP 的可靠方法
临时关(重启失效)只用于验证:
– echo never > /sys/kernel/mm/transparent_hugepage/enabled
– echo never > /sys/kernel/mm/transparent_hugepage/defrag
(注意:必须同时关 enabled 和 defrag,否则 khugepaged 仍会活跃)
永久生效推荐两种方式,选其一:
– 修改 GRUB:在 /etc/default/grub 的 GRUB_CMDLINE_LINUX 末尾加 transparent_hugepage=never,再运行 update-grub && reboot;
– systemd 方式:新建 /etc/systemd/system/disable-thp.service,内容包含上述两个 echo 命令,并启用服务:systemctl daemon-reload && systemctl enable disable-thp.service。
关键点:
– 不要用 /etc/rc.local:systemd 环境下该文件常被忽略,且执行时机不可控;
– 关完必须重启 Redis:THP 是进程启动时继承的内核策略,不重启 Redis 无效;
– 验证是否真关掉:除了看 enabled 文件,还要 grep AnonHugePages /proc/$(pgrep redis-server)/smaps | awk '{sum += $2} END {print sum}',结果应为 0。
THP 关闭后还需同步调整的 Redis 相关参数
关 THP 是治本,但若 RDB 仍高频触发,fork 峰值压力还在。建议配套调整:
– 把 save 规则从 save 60 10000 改为更宽松的 save 300 10,避免写入突增时密集 fork;
– 确保 no-appendfsync-on-rewrite yes,防止 AOF rewrite 和 RDB bgsave 叠加 fork;
– 检查 vm.overcommit_memory = 1(通过 sysctl vm.overcommit_memory 查),否则 fork 可能因内存预估失败直接返回 ENOMEM;
– 别用 CONFIG SET save "" 动态清空规则——已排队的 bgsave 仍会执行,必须改配置 + redis-cli config rewrite + 重载或重启。
最易被忽略的一点:云服务器(尤其是容器化部署)可能由上层调度器强制启用 THP,即使你本地关了,也要登录宿主机确认。卡顿若依旧,先 strace 抓 fork 耗时,再看 AnonHugePages 是否归零——这两项不达标,其他优化都是白忙。










