BGREWRITEAOF执行后文件未变小,需先检查INFO persistence中aof_base_size与aof_current_size是否接近;若后者远大于前者且持续上涨,说明重写期间长连接高频写入导致旧AOF边删边涨。

BGREWRITEAOF执行后文件没变小,先看INFO persistence里的aof_base_size
重写是否真起效,不能只盯appendonly.aof文件大小变化——它在重写完成前会继续追加新命令。真正要对比的是aof_base_size(上次重写后的基准大小)和aof_current_size(当前大小)。如果两者接近,说明重写确实生成了更紧凑的文件;如果aof_current_size远大于aof_base_size且持续上涨,大概率是重写期间有长连接在疯狂写入,导致旧AOF边删边涨。
长连接持续写入如何干扰AOF重写效果
Redis重写时,主进程照常接收写命令,并全部追加到**旧AOF文件**末尾;子进程则基于fork时刻的内存快照生成新AOF。这意味着:
- 若某客户端保持连接并每秒发1000条
INCR、LPUSH或SET,重写耗时几分钟,旧AOF就可能新增几百MB - 重写生成的新AOF只反映fork那一刻的数据状态,但旧AOF里新增的命令不会被“回收”,最终原子替换时,新文件体积仍会被这些增量拉高
- 极端情况下(如监控系统用
PUBLISH高频打点),重写刚结束,新AOF立刻又被写爆——看起来“白重写了”
怎么确认是不是长连接在捣鬼
直接查活跃连接和写入来源,别猜:
- 运行
redis-cli --stat观察in/out流量趋势,持续高位说明有连接在刷数据 - 用
redis-cli client list过滤cmd=字段,找长时间执行publish、lpush、incr的client,重点关注idle值小(age大(>300秒)的连接 - 检查
INFO clients中的connected_clients和client_longest_output_list,后者异常高往往对应缓冲区堆积的长连接 - 翻应用日志,确认是否有定时任务、消息消费者、埋点SDK在固定周期批量写入
重写期间压不住写入流量,就得换策略
不是所有场景都适合等BGREWRITEAOF慢慢跑。当确认是长连接主导写入时:
- 临时限流:用
CONFIG SET timeout 60踢掉空闲连接,或配合CLIENT KILL干掉特定IP/ID的写入源 - 切到混合持久化:
CONFIG SET aof-use-rdb-preamble yes,让重写开头直接塞RDB快照,大幅缩短子进程工作时间,降低被写穿的概率 - 避开高峰重写:用
redis-cli -c连上后,先CLIENT PAUSE 5000 WRITE暂停写入5秒(仅限Redis 3.2+),再立刻发BGREWRITEAOF,抢出一个干净窗口 - 别依赖自动触发:把
auto-aof-rewrite-percentage设为0,改用定时脚本+redis-cli --raw BGREWRITEAOF,并在crontab里加判断逻辑,比如if [ $(du -m appendonly.aof | awk '{print $1}') -gt 10240 ]; then ...
重写本身不丢数据,但若写入速率长期超过重写吞吐,就永远在追赶——这时候该查业务逻辑,而不是调参数。

















