真实面经题目 · 原创解析
12306 区间购票系统如何设计?
这题考区间库存建模和高并发交易一致性,关键是防止重叠区间超卖,并让占座、支付、释放形成闭环。
真实面经题目 · 原创解析
这题考区间库存建模和高并发交易一致性,关键是防止重叠区间超卖,并让占座、支付、释放形成闭环。
我会把一趟车按相邻站点拆成多个区间,座位从起点到终点覆盖的所有小区间都可用时才可售。查询阶段可以用缓存和预计算提升速度,但下单不能相信缓存,必须在库存服务或数据库事务里对覆盖区间做原子占用,生成待支付订单。支付成功后确认出票,超时未支付要释放库存,所有状态变更都要幂等,并通过消息、定时扫描和对账处理异常。
核心不是按起终点存一个库存数字,而是把站点 A-B-C-D 拆成 A-B、B-C、C-D 等相邻区间。一次 A 到 C 的购票会占用 A-B 和 B-C,同一座位不能再卖给任何重叠区间。
查询可以从区间库存、座位可用位图或预聚合余票中计算,并用缓存承接高频读。缓存只用于展示和筛选,最终能否购买必须以下单占座的原子结果为准。
下单时要对车次、日期、席别、座位和覆盖区间做原子校验与扣减。实现可以用库存服务串行化、数据库事务加乐观锁、位图 CAS 或分段锁,目标是重叠区间不能同时成功。
占座成功后生成待支付订单,支付成功转出票或已支付,超时转取消并释放库存。支付回调、取消任务、用户重复提交都要靠订单号、幂等键和状态流转约束避免重复扣减或重复释放。
热门车次需要限流、排队、读写分离、库存热点隔离和降级策略。查询链路可以牺牲实时性,下单链路必须保证正确性;异常时用消息补偿、定时扫描和对账修正状态。
对覆盖的所有区间做同一个原子校验和占用,不能先查缓存再异步扣库存;同时用乐观锁、事务或库存服务保证并发冲突只有一个成功。
订单进入取消状态后释放已占区间,释放操作要幂等;如果延迟消息失败,还要靠定时扫描待支付超时订单补偿。
允许查询结果短时间不准,但下单必须重新校验库存。缓存通过变更消息、短 TTL、版本号或主动刷新降低误差。
把查询和下单分离,查询走缓存和预计算,下单走限流排队和库存热点隔离,必要时按车次日期分片处理。