大页与分支开销
透明大页会把内存按更大粒度组织,对普通应用往往省页表开销,但对依赖分支加写时复制的实例不友好:按 4KB 粒度改一页要复制整块大页,页表复制与内存拷贝量被成倍放大。表现就是快照、日志重写、全量同步期间出现明显延迟尖刺。
基本信息
| 适用平台 | Linux 主机,包含容器所在的宿主机 |
|---|---|
| 建议取值 | 关闭透明大页 |
| 检测命令 | 查看内核透明大页开关文件与当前策略 |
| 对应指标 | INFO stats 的最近一次分支耗时、INFO memory 的写时复制占用 |
| 启动提示 | 开启时进程启动日志会给出相关告警 |
排查场景
- 快照期间出现秒级延迟尖刺,且与快照时间对齐
- 日志重写与全量同步叠加时延迟进一步恶化
- 大内存实例分支耗时明显偏高
- 云主机默认开启透明大页,需要按发行版方式固化关闭并复查
检测与关闭
检测与关闭
cat /sys/kernel/mm/transparent_hugepage/enabled # 方括号在 always 上表示已开启
echo never > /sys/kernel/mm/transparent_hugepage/enabled # 临时关闭,重启失效
redis-cli INFO stats | grep latest_fork_usec # 最近一次分支耗时(微秒)
redis-cli INFO memory | grep rdb_last_cow_size # 上次快照期间的写时复制占用
redis-cli INFO persistence | grep rdb_last_bgsave_status # 快照是否成功
grep -i 'transparent huge' /var/log/redis/redis.log | tail -3 # 启动告警观测指标
| 指标 | 含义 | 异常表现 |
|---|---|---|
| 最近一次分支耗时 | 执行分支操作的耗时(微秒) | 达到毫秒级数千以上说明偏慢 |
| 快照写时复制占用 | 上次快照期间因写时复制增加的内存 | 过大说明分支后写入量大或页粒度粗 |
| 重写写时复制占用 | 上次日志重写期间增加的写时复制内存 | 重写期间更敏感,常与尖刺同时出现 |
| 透明大页策略取值 | always、madvise、never 三态 | 非 never 建议评估关闭 |
| 尖刺与快照时间对齐 | 定位因果关系 | 时间对齐才能确认是分支与复制放大 |
关闭方式要固化:临时写内核开关重启即失效,应通过内核启动参数、服务脚本、开机脚本或发行版的调优配置持久化,并在重启后复查一次实际取值。
容器内通常改不了宿主机的这项设置,因为内核参数是共享的。需要在宿主机层面操作,容器里执行可能报权限错误或只改变命名空间里的视角。
别把它当成延迟问题的唯一解释:分支耗时同时取决于实例内存规模(页表规模)、宿主机内存压力与是否发生交换。关闭后延迟没有改善,要继续看内存水位与存储延迟。