Momenta 后端面试:预约超卖、缓存一致性与长事务
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 能否介绍自己和参与较深的项目,说明负责的部分?
- 热门充电站同一时段收到大量预约,怎样避免资源超卖?
- 怎样设计支持多个服务协同的灰度发布系统?
- Cache Aside 为什么不能天然提供数据库与缓存的强一致?
- 先删缓存再更新数据库,会出现什么并发问题?
- 用数据库变更日志驱动缓存失效时,怎样处理事件乱序?
- InnoDB 的 MVCC 怎样工作?
- Undo Log、Read View 和版本链分别负责什么?
- 可重复读下的主键查询命中索引,为什么仍可能很慢?
- 长事务会给 MySQL 带来哪些影响?
- 在线修改大表结构,怎样控制对业务的阻塞?
- Redis Lua 脚本具有原子执行特性,为什么仍可能影响可用性?
- Redis Cluster 扩容迁移槽位时,客户端会遇到哪些变化?
- 怎样设计能处理机器时钟回拨的分布式限流器?
《参考解析》
容量判断必须和扣减放在一起
可以把“剩余容量足够”作为数据库更新条件,并检查受影响的行数;预约记录、容量扣减与同一次请求的去重需要形成一致的业务结果。重复请求应返回同一预约结果,取消操作也不能重复释放容量。Redis 前置拦截可以减轻压力,但不能代替最终数据层的容量约束。
缓存不一致要画出两个请求的时间线
先删除缓存后,另一个请求可能读到数据库旧值并回填;随后数据库更新完成,缓存却留下旧值。先更新数据库再删缓存也存在删除失败和并发旧值回填的窗口。可以结合可重试失效事件、版本检查与过期机制缩小影响,但应明确业务允许多长时间的不一致。
只执行删除时,旧事件通常只是多删一次;如果事件处理还包含重新加载或写入,乱序就可能把旧值覆盖到新值上。回答时先说明消费者究竟做了什么,再决定版本号放在哪里。
长事务会让历史版本留得更久
一致性读通过可见性规则选择记录版本;需要保留旧快照时,相关历史版本不能随意清理。长事务也可能长时间占用锁,所以检查事务耗时和检查单条慢 SQL 不是一回事。把远程调用、文件处理或人工等待放进数据库事务,会拉长这段时间。
Lua 的原子执行不等于跨系统事务
脚本执行期间不会和其他命令交错,因此应控制循环次数和数据规模,避免让一个请求长时间占住实例。脚本中的 Redis 更新即使完成,也不能让另一个数据库的写入自动一起提交。原子执行也不表示脚本运行出错时,之前的写入一定回滚。
限流先定义时钟与状态来源
单机计算时间间隔可以使用单调时钟;多机共享额度时,不能假定各机器的单调时钟值可直接比较。需要集中维护限流状态,或明确时钟误差与分片额度的容忍范围。检测到时间回退时,不应让补充令牌的差值变成负数或额外发放额度,同时记录异常以便定位。