题目重点:以不可变数据块和原子发布清单构造读写路径,解释孤儿块、旧版本、故障恢复与持久ACK。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练对象存储模型:data为不可变chunk,metadata为object_id、generation、chunk manifest与状态;更新创建新generation。
- 同一对象发布清单原子,多个对象不提供跨对象事务;ACK后的持久性故障域必须事先明确。
- metadata的强一致发布与data副本就绪是不同阶段,不能用‘都复制了’省略失败窗口。
解题路线
- 写路径先创建upload id,传块并核checksum,达到规定数据副本/故障域条件后提交manifest。metadata用条件generation更新,发布之后才ACK。chunk成功但manifest未提交是未发布写,读取不应看见半文件。
- 读路径读取已发布manifest及generation,然后从data节点取相应不可变块并核checksum;缓存manifest带版本,缓存旧manifest读取完整旧版与读到半新半旧不同,明确允许多旧。
- 更新与删除使用新generation/tombstone。并发客户端通过if-match约束,避免旧写覆盖新写;未ACK操作可能已发布,重试必须按upload/op id查结果,不能新建第二对象。
- 故障恢复分别对metadata日志/快照与data块进行校验和复制修复。返回成功的写若丢metadata或数据任一层就不可读,持久性预算必须覆盖两层依赖;不能只谈块副本数。
- 垃圾回收清理未发布孤儿块和不再引用旧generation,用宽限期、活跃upload标记及引用/快照协议防止删仍被读或上传的块。GC崩溃可重试,先标记候选再安全删除。
- 性能取舍测manifest查询延迟、块吞吐、小对象元数据占比、写放大与恢复带宽;跨域复制提高耐久但增加ACK延迟。热点manifest可缓存,条件写与授权仍需权威路径。
手动走一遍
训练例上传两块c1/c2,c1成功后客户端断线;对象未发布,读旧generation或404,不读c1半文件。重连用同upload id续传c2并提交manifest。如果commit已成功但ACK丢失,查询upload结果返回同generation;GC不能在恢复窗口删除c1。
规模与取舍
大对象O(数据字节)传输,manifestO(chunk数);小对象可能主要受metadata操作与复制往返支配。恢复与GC按未同步/候选字节计成本,不能用O(1)API查找掩盖实际I/O。
易错点与追问
容易失分的边界
- 块上传完便ACK,metadata仍未持久发布。
- cache把不同generation块混读。
- GC见无manifest就立即删除尚在上传的块。
- 只备份data忽略metadata恢复。
继续深挖
- manifest已发布但一个data副本丢块,怎样选回源/修复?
- 同一对象两个并发upload哪个能提交?
- 删除后旧版本读者还能访问多久?
- 小对象高QPS下metadata怎样分片与缓存?
