题目重点:Screen 系统设计题类似简化 S3,重点是避免重复文件保存;本文定义上传、哈希校验、租户权限和引用生命周期。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练场景用户通过 put/get/delete 保存不可变文件内容;同一内容在同一租户内可物理去重,用户可有多个逻辑路径指向相同 blob。跨租户去重默认不开启,以降低权限侧信道与密钥隔离风险。
- 对象大小上限、冷热比例、读写 QPS 与一致性目标未给;举例以 10TB 逻辑数据、30% 重复率作容量推演,不代表题目规模。
- 文件内容先临时上传并校验哈希,服务端不把客户端自报 hash 直接当真实性证明。
解题路线
- 把逻辑文件表 (tenant,path,version,blobId) 与物理 blob 表 (tenant,contentHash,size,storageKey,refCount,state) 分离。相同字节得到同一 blobId;文件名相同但内容不同必须有新版本或替换语义。
- 上传先到 staging 对象,服务端流式计算强哈希与长度;在租户域内按 (hash,size) 查找候选,必要时进一步字节校验以处理极低概率碰撞或恶意输入。
- 用唯一约束和事务保证并发两个相同上传最终只有一份 canonical blob;逻辑引用写入与 refCount 变化在同一事务或可恢复事件流里保持一致。
- 删除逻辑路径时减少引用,refCount 到零先进入 GC 候选,经过保留期与二次对账再删底层对象;失败重试和并发新引用不能误删。
- 读取先鉴权逻辑文件,再解析 blob 存储键;即使两个用户共享物理内容,也不能靠已知 hash 推断别人的文件存在。监控去重率、staging 泄漏、零引用待回收字节和读延迟。
手动走一遍
租户 T 上传 A.pdf=10MB,服务端哈希 h;再上传 B.pdf,字节完全相同,逻辑文件表有两条记录但 blob 表只有 h 一条、refCount=2。删除 A 后 refCount=1,仍可读 B;删除 B 后 refCount=0,延后 GC。若另一租户 U 上传同样字节,默认建 U 自己的 blob 与密钥域。
规模与取舍
设文件 F 个、唯一内容 B 个,元数据 O(F+B),物理数据存储约 Σ uniqueBlobSize 加副本;例 10TB 逻辑数据、30% 完全重复,理想原始载荷降至约 7TB,仍需算 staging、副本、索引和 GC 成本。每次上传需 O(fileSize) 读取/哈希,哈希查找期望 O(1),事务与对象存储延迟主导 p95。
易错点与追问
容易失分的边界
- 只按文件名去重,不同内容同名发生覆盖。
- 信客户端提供的 hash 而不验字节,恶意或错误上传指向他人内容。
- 先删除 blob 后减少引用,其他逻辑文件变成悬挂指针。
- 跨租户全局查 hash 时返回‘已存在’,形成文件存在性侧信道。
- 只算节省的存储字节,不算上传 staging、哈希 CPU、索引和 GC 成本。
继续深挖
- 大文件做分块去重如何处理块顺序、元数据膨胀与随机读?
- 租户使用不同加密密钥,跨租户去重为何困难?
- 怎样在 refCount 不可信时从逻辑文件表重建引用?
- 文件内容可修改时,版本与 copy-on-write 怎样设计?
