题目重点:从 Netflix 宽题面 resilient file system 出发,界定 ACK 后数据可恢复的承诺,讨论写前日志、快照、重放、部分写与生产瓶颈。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版承诺:create/write/delete 成功 ACK 之后,单节点进程崩溃重启仍能恢复该操作;未 ACK 操作允许已生效或未生效,需用操作 id 去重。
- 先处理单机磁盘持久化,不假定机架故障或多区域灾备;若需节点/磁盘故障容忍,要加复制与 quorum 条件。
- 文件操作按单文件原子提交;跨文件 rename/transaction 是否需要原子性是独立追问。
解题路线
- 定义元数据(路径、文件 id、版本、blob 指针、校验和)与内容数据。写新内容到不可变 blob 或预写区,校验写入完成,再把指向新版本的事务记录追加 WAL 并 fsync;持久提交后才 ACK。若只 fsync 日志但内容尚未落盘,日志必须含可重建内容或保证 blob 已稳定。
- 恢复时读取最近一致快照,按 LSN 顺序重放完整且校验通过的 WAL 记录;截断尾部不完整记录,重复 operation id 幂等。对 delete 写 tombstone,对 overwrite 保留或清理旧 blob 取决于保留策略。
- 崩溃点测试覆盖内容写中途、WAL 写中途、fsync 前、提交后 ACK 前、快照期间;每个点明确恢复后允许哪些状态,避免出现元数据指向缺失内容。
- 生产化拆元数据服务和内容对象存储,批量/组提交降低 fsync 成本,冷热分层与后台快照控制恢复时长;多副本需考虑主从切换及已 ACK 写是否丢失,不能只说‘加缓存’。
手动走一遍
训练例文件 `/x` 原内容 A,准备写 B:B blob 落稳后 WAL commit v2 落稳,再 ACK。若在 WAL commit 前崩溃,恢复仍指 A,孤儿 B 可 GC;若 commit 后 ACK 前崩溃,恢复指 B,客户端重试应凭 operation id 得到同一结果。
规模与取舍
写入成本至少包括内容大小 B 的顺序写及持久化日志记录;索引查找通常约 O(log F) 或预期 O(1),恢复时间与快照后 WAL 长度 W 成正比 O(W)。频繁 fsync 提高持久性但限制吞吐,组提交降低平均成本却增加等待延迟。
易错点与追问
容易失分的边界
- 成功 ACK 后只存进内存缓存,崩溃即丢数据。
- WAL 记录有新文件指针,但实际内容还没稳定落盘。
- 重放重复执行非幂等写或增量操作。
- 快照与日志截断顺序错误,恢复时出现历史缺口。
- 把 q9 内存版本管理直接称为崩溃可恢复方案;版本不等于持久化。
继续深挖
- 磁盘损坏而非进程崩溃时怎样复制并定义已 ACK 写的耐久性?
- 大文件分片覆盖时如何做到原子切换?
- 日志无限增长怎么做快照与压缩?
- 热目录或热点文件如何减轻锁和元数据瓶颈?
