appendfsync always不能保证不丢数据,因存在内核page cache缓存、硬盘写缓存未禁用、进程被sigkill强杀于write与fsync之间三重断层,实际最多丢失1条命令;everysec是默认推荐,兼顾可靠性与吞吐;no仅适用于纯缓存或高写压且有外部兜底的场景。

appendfsync 不是调得越激进就越安全,选错档位反而会让数据更不可控。 生产环境里最常见的误操作,就是把 appendfsync always 当成“不丢数据”的银弹,结果既没真正防住丢失,又把写吞吐压到 1/5 以下。
appendfsync always 为什么不能保证不丢数据
它只保证 Redis 主线程在每次写命令后调用 fsync(),但中间还有三层断层:
- Linux 内核的
page cache可能缓存了fsync()调用本身(尤其 ext4 + barrier 关闭时) - SSD 或硬盘自身的写缓存(Write Cache)若未禁用(如没执行
hdparm -W0 /dev/sda),fsync()只是通知设备“数据就绪”,不代表已落盘 - Redis 进程若被
SIGKILL强杀,或刚完成write()就崩溃,那条命令就卡在 AOF 缓冲区里,永远没机会fsync()
所以 appendfsync always 的实际 RPO(恢复点目标)仍是“最多 1 条命令”,且这个上限依赖硬件和内核配合——生产环境极少满足。
everysec 是默认起点,但要注意它的“秒”不是准时钟
appendfsync everysec 是大多数业务可接受的平衡点,但它不是严格每 1000ms 刷一次盘:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 刷盘由 Redis 主循环定时器触发,若主线程卡住(比如执行
KEYS *、序列化大 value),延迟可能达数秒 - 后台
bgrewriteaof进行时,主进程仍持续往旧 AOF 文件追加命令,everysec对这部分依然生效 - 当磁盘 I/O 延迟突增(如 SSD 垃圾回收、RAID 卡电池学习),Redis 会自动临时降级为
always,除非你显式配置了no-appendfsync-on-rewrite yes
如果你的业务能容忍秒级 RPO(例如用户发帖失败后前端自动重试),everysec 的吞吐通常是 always 的 5–10 倍,且稳定性高得多。
appendfsync no 只适合两类明确场景
appendfsync no 把刷盘完全交给操作系统(通常 30–60 秒一次),仅适用于:
- 纯缓存型 Redis:AOF 仅用于故障后重建热 key 分布,不要求精确恢复(如 session 存储 + 前端兜底)
- 写压极高且磁盘 I/O 已是瓶颈的节点:例如每秒写入 50k+ 小命令,
everysec下iostat -x显示%util > 90%
但必须同步做两件事:save 配置项必须清空(避免 fork + rdb save 加剧延迟),且应用层必须有外部补位机制(如双写 MySQL、投递 Kafka 消息),否则宕机即全量丢失。
真正影响数据丢失量的,从来不只是 appendfsync 这一个参数。它必须和 no-appendfsync-on-rewrite、auto-aof-rewrite-percentage、磁盘 write cache 状态、甚至 maxmemory-policy 的淘汰行为联动看。单点调参,容易忽略副本同步延迟、主从断连窗口这些更隐蔽的丢失路径。










