Redis AOF everysec 模式下 fsync 并非严格每秒一次,而是主线程立即提交 fsync 请求至后台线程,实际执行依赖内核 writeback 线程、I/O 负载及脏页参数,可能延迟甚至失败。

Redis AOF everysec 模式下 fsync 真的是“每秒一次”吗?
不是。everysec 只保证 fsync 调用被提交到内核队列的频率上限,不保证实际落盘时间——它依赖内核线程 pdflush(旧内核)或 writeback(4.0+)异步执行,且受 I/O 压力、脏页比例、vm.dirty_ratio 等系统参数影响。
常见错误现象:INFO persistence 中 aof_delayed_fsync 持续增长;磁盘 I/O 尖峰时 AOF 写入延迟飙升;重启后发现最后几秒命令丢失(说明 fsync 实际未完成)。
-
everysec是 Redis 主线程把数据写入 AOF 缓冲区后,**立即**把 fsync 请求交给后台线程,主线程不阻塞 - 后台线程调用
fsync(),但该系统调用本身可能被内核排队,尤其当磁盘忙或脏页过多时 - 如果后台线程连续两次尝试 fsync 都失败(超时或 EAGAIN),Redis 会退化为
no模式,直到下个周期重试成功
如何确认当前 fsync 是否真在异步执行?
看 redis-cli info persistence 的三个关键字段:
-
aof_last_fsync:上一次成功 fsync 的 Unix 时间戳(注意是秒级,不是毫秒) -
aof_delayed_fsync:因 fsync 正在进行中而被跳过的写操作次数(> 0 表示有排队,但不等于失败) -
aof_pending_bio_fsync:等待后台 BIO 线程执行的 fsync 请求数(> 0 才说明异步队列里真有积压)
如果 aof_pending_bio_fsync 长期 > 0,同时 aof_delayed_fsync 也在涨,说明后台线程跟不上,I/O 已成瓶颈。
everysec 下哪些配置会影响 fsync 实际表现?
Redis 自身配置作用有限,真正起决定性作用的是 Linux 内核 I/O 调度与脏页管理策略:
-
vm.dirty_ratio和vm.dirty_background_ratio:值设得过高(如默认 20/10),会导致内核延迟刷脏页,间接拖慢 fsync 响应 - 使用
deadline或none(SSD)IO 调度器,避免cfq在高并发下引入额外延迟 -
fsync本身无法绕过存储栈——NVMe 盘比 SATA SSD 平均快 3–5 倍,机械盘基本不适合everysec - 不要在 AOF 文件所在磁盘挂载
noatime,nobarrier以外的激进选项(如data=writeback),否则可能丢数据
什么时候该放弃 everysec 改用 no 或 always?
别迷信“折中”。权衡点很实际:
- 选
no:只用于缓存场景,能接受进程崩溃即丢全部 AOF 缓冲区(通常几秒到几十秒),且磁盘 I/O 已严重争抢 - 选
always:仅限极小吞吐(QPS fsync() 上,TPS 断崖下跌 -
everysec失效的典型信号:aof_pending_bio_fsync> 10 且持续 30 秒以上,或aof_delayed_fsync单秒突增超 1000 —— 这时候不如切no,再加监控告警
真正难处理的不是 fsync 频率,而是 AOF 重写期间的双写放大:重写子进程写新 AOF,主线程继续追加老 AOF,两者共用同一块磁盘时,I/O 压力会翻倍。这个点容易被忽略,但比 everysec 的调度细节影响更大。









