SWE · Phone System Design

Snowflake 跨服务存储 Quota:高并发下原子预留与对账

题目给用户 100GB 配额、Drive 30GB 和 Photo 20GB,强调高并发低延迟;本文设计跨服务预留、提交/取消与故障对账。

题目重点:题目给用户 100GB 配额、Drive 30GB 和 Photo 20GB,强调高并发低延迟;本文设计跨服务预留、提交/取消与故障对账。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版每用户的 100GB 是 Drive+Photo 共享硬上限;上传前可获知最大占用字节数并申请 reservation,提交时按实际字节结算。
  • 只有 quota 服务拥有 user 的 used+reserved 状态;每个请求带幂等 operationId。硬限制选择故障时拒绝新预留,题目未指定 fail-open/fail-closed。
  • 例子按十进制 GB 计算;真实存储系统需固定字节单位、对象开销和压缩后/压缩前计量口径。

解题路线

  1. 把读取当前 usage 与增加 reserved 合成同一用户键上的原子条件操作:若 used+reserved+delta≤limit,则写 reservationId、reserved+=delta;否则拒绝。
  2. Drive/Photo 上传完成后调用 commit(reservationId,actualBytes),在同一事务里减少 reserved、增加 used;失败或超时 cancel/TTL 释放,但已完成上传不能只因 ACK 丢失就释放,需用 operationId 查状态。
  3. 对删除/缩容发出幂等 usage delta 事件,并周期从对象元数据按用户对账;事件重放用 sourceEventId 去重,修复计数漂移。
  4. 按 userId 分区,使同一用户串行化或在 Redis Lua/事务 KV 上做 compare-and-swap;跨区域写入需明确单写主区或一致性协议,不能两个 region 独立批准最后余额。
  5. 容量估算从峰值预留 QPS、热点大客户和每用户 reservation 数入手;缓存可加速只读展示,但放行检查必须到权威状态。

手动走一遍

配额 100GB,Drive 已用 30GB,Photo 已用 20GB,当前可预留 50GB。两个并发上传分别要 40GB,第一笔原子预留后 reserved=40GB,第二笔检查 50+40+40>100 而拒绝。若第一笔只实际用 35GB,提交后 used=85GB、reserved=0,可再预留 15GB。

规模与取舍

每次预留/提交在单用户键上为 O(1) 状态更新加持久化延迟;状态存储约 O(U+R),U 用户数、R 活跃 reservation 数。每日完整对象对账若 M 对象为 O(M),可按用户/分区增量化。P99 受热点用户串行化和跨区一致性影响,不能仅报 Redis 平均延迟。

易错点与追问

容易失分的边界

  • Drive 与 Photo 各查共享剩余额度但分别扣减,产生并发超卖。
  • 只在上传后计费,多个并发大文件都通过事前检查。
  • 预留永不超时导致额度泄漏,或超时后不核上传状态就释放导致低估。
  • 重试 commit 双重加 used,没有幂等状态机。
  • 把对象存储最终用量与 quota 快照视为永远一致,不做对账。

继续深挖

  • 上传大小事前未知时,分块预留怎样实现?
  • 跨地域用户同时上传,选强一致、软超额还是本地区额度切片?
  • 配额从 100GB 降到 60GB 而已使用 80GB 时,读写策略如何定义?
  • 共享组织配额与个人配额同时生效时怎样原子检查?
✓已复制微信号!