Redis慢日志中GET/SET延迟飙升的主因是磁盘IO饱和导致aof_delayed_fsync持续增长,表明主线程被后台fsync阻塞;需通过INFO persistence和系统日志验证,并优先排查磁盘负载而非调整Redis配置。

Redis慢日志里频繁出现GET/SET但没查到复杂命令?先盯aof_delayed_fsync
这不是命令本身慢,而是主线程被磁盘阻塞了。当appendfsync everysec启用时,Redis会用后台线程调用fsync,但若磁盘忙(比如IO饱和、机械盘寻道慢、SSD写放大严重),fsync迟迟不返回,主线程在下一次write写AOF buffer时就会卡住——此时哪怕一个GET也会延迟飙升。
验证方法很简单:INFO Persistence里看aof_delayed_fsync是否持续增长;同时系统日志或redis.log中会出现Asynchronous AOF fsync is taking too long (disk is busy?)警告。
- 这个指标每增加1,代表一次主线程因等待
fsync完成而被迫延迟 - 如果每秒涨几个甚至几十个,说明磁盘已成瓶颈,不是Redis配置问题,是IO层问题
- 别急着调
appendfsync,先确认是不是AOF重写(bgrewriteaof)正在发生——它会让fsync压力雪上加霜
为什么no-appendfsync-on-rewrite yes能缓解,但不能乱开
这个配置的意思是:当AOF重写子进程运行时,主进程暂停调用fsync,只做write(即把数据扔进内核缓冲区就返回)。它本质是让渡「最多30秒数据丢失」来保主线程不卡。
但它生效的前提是:你当前用的是appendfsync everysec(默认值),且重写期间磁盘确实扛不住双路写入(主进程AOF追加 + 子进程重写文件)。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
no-appendfsync-on-rewrite yes仅在AOF重写期间起作用,平时仍按everysec执行fsync - 设为
yes后,重写期间若发生宕机,可能丢失上次fsync之后到宕机前的所有写操作(理论最长30秒) - 设为
no(默认)更安全,但一旦磁盘慢,重写+同步叠加会导致大面积延迟抖动 - 注意:它对
appendfsync always无效——因为always必须同步,无法跳过
appendfsync策略选no还是everysec?关键看业务容灾底线
appendfsync no不是“完全不管”,而是把刷盘时机交给操作系统——Linux通常在脏页达到vm.dirty_ratio(默认20%内存)或超时(vm.dirty_expire_centisecs,默认30秒)时批量刷。性能最好,但故障时可能丢最近几十秒数据。
everysec折中,但要注意它隐含两个风险点:
- 即使没重写,单次
fsync超时也会拖慢后续所有命令(因主线程write要等前一次fsync释放缓冲区) -
aof-rewrite-incremental-fsync yes(默认开启)虽能分批刷重写文件,但无法缓解主AOF流的fsync压力 - 若业务允许秒级丢失(如会话缓存、实时排行榜),
no比强行保everysec更稳;若要求强一致(如金融类计数),就得换更快存储或接受延迟波动
真正治本:别只调配置,检查磁盘和内核参数
调no-appendfsync-on-rewrite只是止痛,磁盘IO才是病灶。以下三点比改Redis配置更关键:
- 用
iostat -x 1看%util是否长期>80%,await是否突增——确认是不是磁盘真忙,而非Redis假慢 - 禁用
transparent_hugepage:echo never > /sys/kernel/mm/transparent_hugepage/enabled,否则fork子进程(如AOF重写)会卡顿 - AOF文件务必放在独立物理盘(不要和系统盘、RDB盘混用),SSD优先;若只能用HDD,至少确保
noatime挂载,减少元数据更新
最常被忽略的一点:no-appendfsync-on-rewrite只解决重写期间的冲突,但如果磁盘本身持续高负载,即使关掉重写,everysec照样会反复触发aof_delayed_fsync——这时候再怎么调Redis参数都只是徒劳。

















