字节面试:Redis 机房故障、网络中断 30 秒,恢复后数据丢失,你怎么处理?
公众号名称:Fox爱分享
作者名称:Fox爱分享
发布时间:2026-06-20 07:00
前几天有个读者私信我。
说去字节面试后端开发岗,聊到项目里用 Redis 做缓存,面试官顺势抛了一个场景题。
「假设你的 Redis 节点机房故障,网络中断了 30 秒,恢复之后你发现 Redis 里有数据丢了,你怎么处理?」
他说他当时脑子里一片空白,憋了半天说了一句,「用 AOF 恢复?」
面试官没说对错,只是笑了笑,说你回去再想想。
他回来之后找我聊,我听完后说,这道题你确实没答好,但不是你的错,因为很多人对 Redis 持久化这件事,理解其实是错的。
先把这个场景拆清楚。
Redis 宕了 30 秒,恢复后发现数据丢了。
这里有两个独立的问题要搞清楚——
第一,数据是怎么丢的?
第二,丢了之后怎么处理?
这两个问题答不出来,面试官就知道,你对 Redis 的持久化机制只是背过名词,没有真懂。
先说数据是怎么丢的。
Redis 的数据为什么会丢?
原因其实只有一个,写操作没有落盘。
Redis 是内存数据库,所有数据都在内存里,如果某个写操作完成了,但还没来得及刷到磁盘,这时候 Redis 挂了,那这个写操作就丢了,永远找不回来。
那 Redis 有没有机制防止这件事?
有,就是 AOF 和 RDB。
但这两个机制的保证强度,完全不一样。
RDB,全称 Redis DataBase,它的做法是,每隔一段时间,把当前内存里的所有数据,拍一个快照,写到磁盘上。
这个「每隔一段时间」,是由配置项
save控制的。比如默认的——
save 900 1 save 300 10 save 60 10000意思是,900 秒内有至少 1 个 key 变了,就触发一次快照;300 秒内有至少 10 个 key 变了,也触发;60 秒内有 10000 个 key 变了,同样触发。
问题在于,如果这个 30 秒的宕机窗口,正好落在两次快照之间呢?
那这 30 秒里所有新写入的数据,全丢了,因为上一次快照里没有它们,AOF 如果也没开或者配置不够强,那就真的没了。
再看 AOF,全称 Append Only File。
它的做法是,每来一个写命令,就追加到磁盘上的一个文件里,这样即使 Redis 挂了,重启的时候可以把这个文件里的命令全部重放一遍,把数据恢复出来。
但 AOF 有一个关键配置,
appendfsync,它决定了「追加」这个动作什么时候真正刷到磁盘。
有三个可选值——
always,每个写命令都立刻 fsync 到磁盘,数据零丢失,但性能最差,因为每个写操作都要等磁盘 IO。
everysec,每秒 fsync 一次,把这一秒内的写命令批量刷盘,最多丢 1 秒的数据,性能和安全的平衡点,也是默认推荐值。
no,交给操作系统决定什么时候刷盘,Redis 自己不管,性能最好,但宕机时可能丢好几秒甚至更多数据。
回到面试官的题。
这道题最毒的地方,不是 Redis 宕机,而是网络分区,也就是常说的脑裂。
场景是这样的——
Redis 主节点和从节点、Sentinel 之间的网络断了 30 秒,但主节点自身还活着,一部分客户端也和主节点在同一个网络孤岛里,它们还在往旧主写数据。
与此同时,Sentinel 在那边等了 30 秒(
down-after-milliseconds默认 30 秒),判定主节点客观下线,把从节点提升为新主。另一部分客户端开始往新主写数据。两个主节点,两份数据,同时存在。
30 秒后网络恢复。
Sentinel 发现旧主回来了,但它的身份还是「主节点」,和集群里的新主冲突。Sentinel 的处理方式是,把旧主降为从节点,让它向新主发起全量同步。
旧主内存清空,用新主的数据整个覆盖。
那 30 秒里,孤岛客户端写入旧主的所有数据,彻底消失。
AOF 文件也在全量同步时被新主的数据覆盖,连补救的机会都没有。
这才是这道题真正想考的东西。
不是「AOF 和 RDB 的区别」,而是你对 Redis 高可用架构下,脑裂场景的数据一致性问题,有没有真实的理解。
那面试官到底想听什么答案?
我觉得分三层来答,面试官会觉得你真的干过。
第一层,先说清楚数据为什么会丢。
「30 秒的窗口里,如果写操作没有及时落盘,比如 AOF 配的是 everysec,那最多丢 1 秒的数据;如果配的是 no,可能丢更多;如果连 AOF 都没开,只靠 RDB,那丢的数据量取决于最后一次快照是什么时候。」
这一层考的是你对
appendfsync的理解。第二层,说怎么把丢的数据找回来。
「如果 AOF 文件还在,重启 Redis,它会自动加载 AOF 文件做重放,数据能恢复绝大部分,最多丢 1 秒。如果 AOF 文件也损坏了,可以用
redis-check-aof工具做修复,把损坏的部分截断,再重启。」这一层考的是你有没有真正运维过 Redis,有没有遇到过 AOF 文件损坏的情况。
第三层,说怎么让这件事不再发生。
「生产环境里,AOF 一定要开,
appendfsync配everysec,这是基础。但光靠 AOF 解决不了脑裂。要在主节点配置两个参数:
# Redis 5.0+ 新参数名 min-replicas-to-write 1 min-replicas-max-lag 10 # Redis 5.0 之前用这个,目前仍兼容 # min-slaves-to-write 1 # min-slaves-max-lag 10意思是,至少有一个从节点活着,且复制延迟不超过 10 秒,主节点才允许写入。这样在网络分区的 30 秒里,旧主发现没有从节点响应,会直接拒绝写入,把数据丢失的风险掐死在源头。
如果数据真的非常重要,还要在 Redis 之外建一条兜底链路,比如通过监听 MySQL 的 Binlog,用 Canal 把变更异步刷回缓存,或者通过消息队列做写入确认。Redis 是 AP 架构,单靠它自己,极端情况下一定会丢数据,兜底要做在缓存之外。」
这一层考的是你的架构意识,有没有从单点思维跳到高可用思维。
我那个读者后来跟我说,他回去之后把 Redis 的源码里 AOF 那部分翻了一遍。
他说以前背八股文的时候,
appendfsync三个值的区别他能倒背如流,但从来没有想过,「宕机 30 秒」这个场景里,真正危险的不是 Redis 挂了,而是网络恢复之后,旧主节点重新上线,被 Sentinel 重新配置成从节点,然后被清空。这一步,才是很多人在生产环境里真的踩过的坑。
说到这里,我想起一件事。
很多人学 Redis,都是从「怎么用」开始的,set、get、hset、hget,很快就能上手。
但「怎么在出事的时候不丢数据」,这件事,只有真的在生产环境里被坑过一次,才会认真去想。
我见过有人配 Redis,AOF 没开,RDB 的 save 配置用的是默认值,然后某天晚上机房割接,网络闪了 10 秒,恢复之后发现当天的活跃用户 session 全没了,客服电话被打爆。
这件事的代价,是那个工程师加班到凌晨 4 点,手动从业务数据库里把能补的数据全部补回去,补了 3 个小时。
所以这道题,面试官考你的,其实不是你知不知道 AOF 和 RDB 的区别。
他在看你会不会本能地去想,「如果这事发生在我负责的系统上,我会怎么做?」
这种思维,才是一个高级后端工程师值钱的地方。
不是你会多少命令,而是你能不能在系统出事之前,就把出事之后的应对方案想清楚。
那 30 秒的网络中断,在面试官嘴里是一个假设,但在真实的生产环境里,它就是一次机房割接、一根被挖断的光纤、一次误操作的网线拔除。
你无法阻止这些事发生,但你可以决定,当事情发生的时候,你是手忙脚乱地补数据,还是安安稳稳地重启 Redis,然后看着它把 AOF 文件重放完,数据一分不丢地全部回来。
后者的前提是,你曾经认真想过这件事。
关注「Fox爱分享」,更多后端面试深度解析,我们下篇见。
内容效果不满意?点此反馈


