事情本身不复杂,线索都在日志里。一台 16 核 64G 的 CentOS 7 跑 Redis 和 Java 混部,按调优文档把 transparent_hugepage 的 defrag 设成 always,之后接口每隔几秒出现一次百毫秒抖动。

第一反应是「Redis 的 fork 对延迟敏感,规整期间 fork 直接变慢」,验证下来不成立。

这类报错背后常见的原因有几处,逐个排除就行。always 让内核在分配时同步做内存规整,规整过程会暂停分配线程。也可能是规整要迁移页,跨 NUMA 节点的迁移成本更高,抖动被放大。

还有一种情况,内存碎片本身已经严重,强制规整只是把代价搬到分配路径上。

第一件事是看当前的 THP 策略

cat /sys/kernel/mm/transparent_hugepage/enabled /sys/kernel/mm/transparent_hugepage/defrag

再往下改成只在需要时规整

echo madvise > /sys/kernel/mm/transparent_hugepage/defrag

然后确认碎片情况再决定是否彻底关闭

cat /proc/buddyinfo && grep -i huge /proc/meminfo

等前面都确认过,再把策略写进开机脚本固化

printf 'echo madvise > /sys/kernel/mm/transparent_hugepage/defrag\n' > /etc/rc.d/init.d/thp.sh && chmod +x /etc/rc.d/init.d/thp.sh

改完先别撤,确认这几项。接口的 p99 抖动消失,/sys/kernel/mm/transparent_hugepage/defrag 显示 madvise,buddyinfo 中高阶块数量不再持续下降。

容易忽略的是,数据库和缓存类服务通常建议关掉 THP 或改成 madvise,但关了会增加 TLB miss,是否关要看基准测试,不能照抄别人的结论。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189