60 秒回答模板

我会把一趟车按相邻站点拆成多个区间,座位从起点到终点覆盖的所有小区间都可用时才可售。查询阶段可以用缓存和预计算提升速度,但下单不能相信缓存,必须在库存服务或数据库事务里对覆盖区间做原子占用,生成待支付订单。支付成功后确认出票,超时未支付要释放库存,所有状态变更都要幂等,并通过消息、定时扫描和对账处理异常。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

区间建模

核心不是按起终点存一个库存数字,而是把站点 A-B-C-D 拆成 A-B、B-C、C-D 等相邻区间。一次 A 到 C 的购票会占用 A-B 和 B-C,同一座位不能再卖给任何重叠区间。

02

余票查询

查询可以从区间库存、座位可用位图或预聚合余票中计算,并用缓存承接高频读。缓存只用于展示和筛选,最终能否购买必须以下单占座的原子结果为准。

03

并发占座

下单时要对车次、日期、席别、座位和覆盖区间做原子校验与扣减。实现可以用库存服务串行化、数据库事务加乐观锁、位图 CAS 或分段锁,目标是重叠区间不能同时成功。

04

订单状态机

占座成功后生成待支付订单,支付成功转出票或已支付,超时转取消并释放库存。支付回调、取消任务、用户重复提交都要靠订单号、幂等键和状态流转约束避免重复扣减或重复释放。

05

高峰保护

热门车次需要限流、排队、读写分离、库存热点隔离和降级策略。查询链路可以牺牲实时性,下单链路必须保证正确性;异常时用消息补偿、定时扫描和对账修正状态。

易错点

  • 只按起点终点保存库存,忽略中间相邻区间的重叠关系。
  • 把查询缓存里的余票当作下单依据,导致并发超卖。
  • 没有待支付状态和超时释放,库存被长期占住。
  • 支付回调、取消和重试没有幂等控制,可能重复出票或重复释放。

面试官追问

如何防止超卖?

对覆盖的所有区间做同一个原子校验和占用,不能先查缓存再异步扣库存;同时用乐观锁、事务或库存服务保证并发冲突只有一个成功。

支付超时后如何释放库存?

订单进入取消状态后释放已占区间,释放操作要幂等;如果延迟消息失败,还要靠定时扫描待支付超时订单补偿。

余票缓存不一致怎么办?

允许查询结果短时间不准,但下单必须重新校验库存。缓存通过变更消息、短 TTL、版本号或主动刷新降低误差。

如何提升热门线路吞吐?

把查询和下单分离,查询走缓存和预计算,下单走限流排队和库存热点隔离,必要时按车次日期分片处理。