fork 与写时复制是什么
后台快照靠派生一个子进程完成:子进程与父进程共享同一份内存页,只有当某一页被改写时才复制一份给子进程(写时复制)。因此快照期间写入越频繁,额外复制的内存越多,峰值内存可能接近翻倍;内存越大的实例,派生本身的停顿也越明显。
基本信息
| 派生耗时 | 与页表规模相关,大内存实例可达数百毫秒 |
|---|---|
| 写时复制放大 | 快照期间写入越多,被复制的页越多 |
| 关键指标 | 最近一次派生耗时、写时复制体积、内存峰值 |
| 透明大页 | 开启时会显著放大派生与复制开销,通常建议关闭 |
| 内存预留 | 上限要留出足够余量,避免快照期间触发交换或被杀 |
典型使用场景
- 周期性延迟尖刺排查:定时快照导致的毫秒级停顿是常见来源
- 快照策略调整:把快照集中到低峰,或交由从库承担
- 实例规格评估:按峰值内存而不是当前内存规划容量
- 透明大页治理:确认系统层面已关闭,避免放大开销
- 大规模写入期间的快照冲突:批量导入时主动错开快照时间
观察派生与快照开销
观察派生与快照开销
redis-cli INFO stats | grep latest_fork_usec # 最近一次派生耗时(微秒)
redis-cli INFO persistence | grep -E "rdb_last_cow_size|rdb_last_bgsave_status"
redis-cli INFO memory | grep -E "used_memory_peak|used_memory_rss"
# 关闭透明大页(需 root,写入后立即生效)
cat /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/enabled
# 手动触发一次快照以验证配置
redis-cli BGSAVE && tail -3 /var/log/redis/redis-server.log指标逐项读法
| 指标 | 含义 | 判读 |
|---|---|---|
| 最近派生耗时 | 上次派生子进程占用的微秒数 | 数值偏大说明单次停顿明显 |
| 写时复制体积 | 快照期间复制出的内存量 | 越大说明期间写入越密集 |
| 内存峰值 | 历史最高内存占用 | 接近物理内存即存在风险 |
| 常驻内存 | 进程实际占用的物理内存 | 与逻辑内存差值反映碎片与复制页 |
把快照交给从库承担是常见做法:主库减少派生与复制开销,从库承担磁盘写入压力。
内存已经接近上限时才触发快照:派生需要额外内存,容易触发交换甚至被系统杀掉进程。