AOF / 故障窗口实验

客户端收到“成功”,数据就真的落盘了吗?

一次写命令要穿过四道门。崩溃发生在哪道门之后,决定了 AOF 重启时还能找回多少。 改变策略、写入压力和磁盘抖动,观察“响应快”与“故障窗口小”为什么不能同时免费获得。

redis-aof / 落盘监视器
正在接收写命令
01 选择 appendfsync 策略
600 条/秒
3.7 秒
+150 毫秒

一条命令的四段旅程

主线程调用 write 后,每秒由后台任务发起一次 fsync;两次落盘之间形成故障窗口。

阶段 01

命令已执行

内存数据已经改变,客户端可能很快就能看到新值。

2,220 条
阶段 02

AOF 缓冲区

Redis 把命令编码后追加到用户态缓冲区,尚未交给内核。

0 条待处理
阶段 03

write → 页缓存

write 成功只代表内核接管了数据,并不等于介质已经写好。

420 条未落盘
阶段 04

fsync → 持久化介质

完成 fsync 的边界之前,才是这次模拟中可恢复的记录。

1,800 条可恢复
0 秒         崩溃前写入活动黄色脉冲=批次写入 绿色虚线=完成 fsync
AOF 写入与持久化故障窗口时间线 时间线上显示写入脉冲、完成落盘的位置和崩溃位置。崩溃线与最近落盘线之间的数据可能丢失。
本次故障窗口700 ms最近一次完成落盘 → 崩溃
预计未落盘记录420 条按稳定写入速率估算,不代表业务事务数
单次写入延迟影响中等多数写入不等待磁盘,后台落盘仍会争用 I/O
崩溃前已持久化81%以本次 6 秒观察窗为分母

估算假设:write 很快进入页缓存;每秒落盘的实际完成时刻叠加当前磁盘抖动。

读懂这条线

write 完成,不等于物理介质完成

Redis 先把 AOF 内容写进自己的缓冲区,再调用 write 交给操作系统。此时数据通常停留在页缓存里:进程认为写入完成,内核也接管了这批字节,但突然断电仍可能让它们消失。

所以这里把“绿色落盘边界”画在 fsync 完成之后。红色区间越宽,恢复时可能缺失的尾部命令越多。

always

每次事件循环写完 AOF 都请求 fsync。它把已确认写入的丢失窗口压得最小,却会把磁盘延迟放进写请求路径。它仍不是“跨系统绝对不丢”:磁盘控制器谎报完成、硬件故障、复制链路或业务侧确认语义,都不在一次本机 fsync 的保证范围内。

everysec

主线程照常 write,后台任务大约每秒发起 fsync。正常情况下通常承担约 1 秒尾部数据的风险;磁盘卡顿时,落盘完成会推迟,窗口也会随之变宽。它是延迟与耐久性之间最常见的折中。

no

Redis 不主动安排 fsync,把刷盘时机交给操作系统。吞吐更轻松,但故障窗口不再由 Redis 的 1 秒节拍约束,可能随内核回写策略和磁盘负载显著扩大。时间线中的 3 秒只是教学模型,不是生产上限承诺。