题目重点:围绕 JSON 文档文件的创建、读取、更新、删除设计 URI、验证、ETag 条件写、审计和大文件边界。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版每个 tenant 有若干 JSON 文档资源 documentId,内容是符合大小上限和 JSON 语法的对象或数组;文件命名/目录规则题目未明确。
- 授权以 tenant 与 documentId 为边界,读写权限分开;审计记录写操作与敏感读取。
- 更新使用乐观并发 ETag/版本防止覆盖别人的改动;是否需要 JSON Patch、查询 JSON 内部字段或跨文档事务须另问。
解题路线
- 定义 POST /documents 创建并返回稳定 ID、Location 和版本;GET /documents/{id} 读取 JSON 与 ETag;PUT 全量替换需 If-Match,DELETE 也用 If-Match;列表 GET 带分页与过滤,不返回全租户无限数据。
- 服务端验证 Content-Type、请求体大小、JSON 语法、可选 schema 与深度上限;规范化内容 hash 不替代语义版本,重序化可能改变字节但不改逻辑内容。
- 写入先认证/授权,再在同一原子提交中检查版本并生成下一版本;条件不匹配返回明确冲突/预条件失败,客户端重新读取合并,避免 lost update。
- 元数据表保存 tenant、owner、version、contentHash、size、createdAt、updatedAt 和状态;内容可存数据库或对象存储。若对象存储与元数据非同事务,用 staging 对象+manifest 发布,并回收孤儿对象。
- 删除可先标记 tombstone 再异步清理,版本历史可支持恢复;敏感内容加密、限额、审计和租户隔离。监控 p95、冲突率、无效 JSON、存储量、版本保留及清理积压。
手动走一遍
客户端 A/B 同时 GET version=7。A 用 If-Match:7 更新为 8 成功;B 仍用 If-Match:7 更新时被拒,不能直接覆盖 A。若客户端发送不完整 JSON,服务端在生成版本前拒绝,旧 version=8 仍可读。
规模与取舍
文档正文大小 S:全量读取/替换至少 O(S) 传输与解析,元数据索引查询约 O(log N)。若大 JSON 频繁修改单字段,PUT 全量写放大明显,可考虑 PATCH,但需定义路径并发与审计;题目未明确规模。
易错点与追问
容易失分的边界
- 只画 CRUD 路由,不定义并发更新时的版本条件。
- 用文件名作唯一权限边界,忽略 tenant 隔离与路径穿越。
- 先发布元数据再上传正文,读到不存在的对象。
- 默认 JSON 均小且安全,没有大小/深度限制。
- 把训练示例 endpoint 说成题目给定接口。
继续深挖
- 如何支持局部 JSON Patch 且防两人改同一路径冲突?
- 对象存储上传成功但元数据提交失败如何清理?
- 超大 JSON 文档如何流式验证或限制?
- 删除后恢复与合规彻底删除有什么冲突?
