系统设计面试:如何构建不可篡改的对象保留服务?
题干与适用场景
你要提供一个面向多个租户的 WORM 对象服务。对象按版本保存,可设置固定保留期限,也可由 Legal Hold 无限期保护。客户要求在保留期间拒绝删除和覆盖,支持合规模式与治理模式,且管理员、复制任务和生命周期清理都不能绕过审计。请说明写入、读取、删除、复制、恢复和审计流程。
面试官考察点
- 是否区分对象版本、保留期限、治理模式、合规模式和 Legal Hold。
- 是否把不可变性放在存储执行层,而不是只依赖客户端约定。
- 是否设计权限、绕过治理、根账号边界和双人审批。
- 是否处理跨区域复制、失败重试、删除标记和时钟一致性。
- 是否能证明每次策略变化和拒绝操作都可审计。
回答前需要澄清的问题
- 保留策略按桶、前缀、对象版本还是租户合同定义?
- 合规模式是否要求连根账号也不能在日期前删除?
- Legal Hold 的发起、解除和审批主体是谁,是否需要四眼原则?
- 复制目标是否必须保留同样的锁状态和时间,跨区域延迟上限是多少?
- 客户需要强一致读取、版本列表、导出证明还是只要删除拒绝?
30 秒回答框架
“我会把对象数据、版本索引和保留策略分成独立但原子更新的层。写入先生成不可变版本,策略引擎计算 retainUntil、模式和 Legal Hold 状态,存储删除路径在同一授权边界再次检查这些状态。治理模式允许特定权限显式绕过,合规模式不允许任何主体在到期前删除;Legal Hold 没有时间期限,只能由授权流程解除。复制携带版本和锁元数据,审计记录每次写入、删除拒绝、绕过和策略变化,并用不可篡改日志保存证明。”
分步骤深入解答
1. 建模对象版本与锁状态
对象键不是唯一实体,真正受保护的是 objectVersionId。版本记录包含内容摘要、写入时间、retainUntil、模式、Legal Hold、租户和策略版本。简单删除只产生 delete marker,不应把受保护版本物理删除;永久删除必须明确指定版本并通过锁检查。
2. 设计写入与默认保留
桶或租户策略可以提供默认保留模式和期限,写入请求也可声明对象级值。服务端验证最大期限、时钟来源和权限,计算后的值写入版本元数据并与对象提交绑定。策略变更只影响未来版本,不能回溯缩短已有版本的保留期限。
{
"objectVersionId": "v_91c2",
"retention": {"mode": "COMPLIANCE", "retainUntil": "2027-01-01T00:00:00Z"},
"legalHold": "OFF",
"policyVersion": 18
}3. 实现删除与覆盖闸门
删除、覆盖、缩短期限和解除 Legal Hold 都走同一个授权服务。它读取最新版本状态并在条件更新中校验当前时间、模式、主体权限和 hold 状态。治理模式需要显式 bypass 权限和请求标记;合规模式在到期前一律拒绝,包括高权限管理员。拒绝响应包含稳定错误码和审计 ID。
4. 设计 Legal Hold 与审批
Legal Hold 独立于期限,开启后一直保护版本直到授权解除。解除流程要绑定案件或合同、理由、操作者、审批人和二次认证;高风险租户可要求双人批准。解除后若 retainUntil 尚未到期,版本仍不可删除,避免把 hold 当成期限覆盖开关。
5. 处理复制、恢复与时钟
复制任务传输内容、版本 ID、摘要和完整锁元数据,目标端在落盘前验证来源签名与策略版本。复制延迟期间源端继续拒绝删除;目标端未确认锁状态前不能宣称合规副本。恢复使用新版本 ID,不修改旧版本的保留状态。所有期限比较使用受控时间服务和单调审计时间,不能依赖单台机器时钟。
6. 做审计与可证明性
审计事件包括写入、版本创建、删除成功或拒绝、bypass、Legal Hold 变化、复制确认和策略发布。事件写入独立的追加式日志,带前序摘要或签名链,并限制查询权限。定期导出对象版本清单、锁状态和审计摘要,让客户能证明某版本在某时间点受保护。
高质量示范回答
“我会把版本和锁元数据当作不可变事实,删除路径每次读取最新状态并执行条件检查。对象写入时由策略引擎计算期限、模式和 Legal Hold,并与版本提交原子绑定。治理模式允许具有明确 bypass 权限的主体显式绕过,合规模式在到期前拒绝所有删除;Legal Hold 只能通过有案件号、理由和审批的流程解除。复制携带版本、摘要和锁元数据,目标确认后才算合规副本。删除拒绝、绕过、策略变化和复制都进入追加式签名审计日志,客户可导出版本清单和证明摘要。”
常见错误
- 只在 API 层检查锁 → 其他清理或复制路径可绕过 → 在存储删除执行层复查。
- 把桶策略变更应用到旧版本 → 可能非法缩短既有期限 → 策略版本化且只影响未来写入。
- 把 Legal Hold 当作固定期限 → 到期后自动删除仍可能违反案件要求 → hold 独立存在,明确解除流程。
- 治理模式默认可绕过 → 高权限误用无法解释 → 要求显式权限、请求标记和审批审计。
- 复制完成就宣称合规 → 目标可能丢失锁元数据 → 验证目标版本和锁状态后再确认。
追问及应对
为什么简单 DELETE 可以返回成功却不删除版本?
版本化对象可以把简单 DELETE 表示为新的 delete marker,隐藏当前版本;受保护版本仍存在。永久删除必须指定版本 ID,并在锁闸门中被拒绝或允许。
合规模式为什么需要更强的账号边界?
它的语义是在保留日期前任何主体都不能删除,包括根账号或存储管理员。系统应把删除能力从普通 IAM 授权中隔离,避免“超级权限”破坏合规保证。
如何证明某次删除拒绝不是系统漏记?
让授权决策、对象版本状态和审计事件使用同一请求 ID,并将事件写入独立追加日志。周期性对账删除请求、版本清单和拒绝事件,检测缺口后冻结高风险操作。
复制延迟时能否先删除源对象?
不能仅凭任务已提交就删除。源端锁必须持续到目标确认内容摘要、版本 ID 和保留元数据;否则复制链路故障会造成没有合规副本的窗口。