SWE · Hiring Event System Design

Microsoft 电影院购票系统:座位暂锁、支付与超时回收

定义场次座位库存与订单状态机,处理并发抢座、暂锁过期、支付回调重试和退款。

题目重点:定义场次座位库存与订单状态机,处理并发抢座、暂锁过期、支付回调重试和退款。

题意与假设

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

  • 训练版用户选具体场次和座位,座位在该场次只售一次;不对不同场次共享座位库存。
  • 座位先有短期 hold,再付款出票;hold 时长和支付失败策略由业务设定。
  • 支付回调可重复或延迟,外部支付结果需对账;假设出票后可退款,但退票规则题目未明确。

解题路线

  1. 实体分 Theater、Auditorium、Seat、Show、ShowSeat、Hold、Order、Ticket;ShowSeat 的唯一键是 (showId,seatId),不能只按物理 seatId 锁。
  2. 持座操作在事务中检查 ShowSeat 为 AVAILABLE 或已过期 HOLD,条件更新为 HELD(owner,expiresAt,version);同座并发只有一个条件写成功。
  3. 订单从 CREATED→HELD→PAYMENT_PENDING→CONFIRMED/FAILED/EXPIRED;超时 worker 回收 hold,但以版本/owner 检查,防旧定时任务释放新用户的锁。
  4. 创建支付 intent 和处理回调都用 orderId/支付事务 ID 幂等;付款成功但 hold 已失效时不能盲出票,要走退款或补偿并告知用户。
  5. 出票写唯一 ticketId 和座位归属,发布通知经 outbox;查询座位图可用缓存但最终占座必须经过权威条件写。
  6. 热点首映按 showId 分片或队列化抢座,读缓存快速展示、权威库处理争抢;指标看锁冲突、过期回收延迟、支付后出票失败和对账差异。

手动走一遍

两用户同时抢同场次 A 排 5 座,条件更新只让一个获得 hold。该用户在 5 分钟后过期,旧释放任务带 version=3;另一用户重获 version=4 后,旧任务不得把 version=4 的 hold 释放。若支付回调重复两次,只生成一张票。

规模与取舍

S 个场次座位需要 O(S) 库存状态;一次锁座/出票预期按唯一键 O(log S) 索引定位,批量选 k 座需一个事务内检查 k 个条目,避免部分成功。实际峰值受热门场次读写集中度与支付 SLA 影响。

易错点与追问

容易失分的边界

  • 缓存显示空位就直接出票,没有原子占座。
  • 座位唯一性只按物理座位 ID,导致不同时段冲突。
  • 过期任务不校验版本,释放了后来的合法 hold。
  • 支付成功与出票失败之间没有补偿路径。
  • 重复支付回调重复出票或重复扣款。

继续深挖

  • 如何保证同一订单选择的相邻 k 个座位要么全锁成功,要么全失败?
  • 场次被取消后已付款票怎样批量退款与通知?
  • 黄牛高频抢座与普通用户如何公平?
  • 弱网下用户看到过期倒计时与服务端时间不一致怎么办?
✓已复制微信号!