# 08.面试八股-场景题

# 🔥 场景一:高并发下超卖怎么解决

# 📋 问题描述

面试官:秒杀活动中,10 个人抢 1 个商品,最后卖了 3 个出去,超卖了。你怎么解决?

# 🟢 第一问

:超卖产生的根本原因是什么?

根本原因:多个线程/请求同时读到库存 > 0,然后各自扣减,导致最终扣减次数超过实际库存。

# 🟡 第二问(追问)

:怎么解决?说 3 种方案,并比较优劣。

方案 实现 优点 缺点
数据库乐观锁 UPDATE SET stock = stock - 1 WHERE id = 1 AND stock > 0 简单,不用额外组件 高并发下冲突多,性能差
Redis 原子操作 Lua 脚本扣减 性能高 数据最终要同步到 DB,可能丢
分布式锁 Redisson 锁住扣减过程 逻辑清晰 性能比 Redis 原子操作差,锁持有时间需要控制
-- 防超卖 Lua脚本
local stockKey = KEYS[1]
local deductNum = tonumber(ARGV[1])

-- 获取当前库存
local currentStock = tonumber(redis.call('get', stockKey) or 0)

-- 库存不足
if currentStock < deductNum then
    return 0
end

-- 库存充足,原子扣减
redis.call('decrby', stockKey, deductNum)
return 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 🔥 场景二:怎么保证接口安全

# 📋 问题描述

面试官:你写的接口,怎么防止被别人恶意调用?

# 🟢 第一问

:接口安全的威胁有哪些?说 3 种。

💡 答案要点
威胁 说明
未授权访问 没登录就能调用需要登录的接口
越权操作 用户 A 删了用户 B 的数据
恶意刷接口 频繁调用导致资源耗尽、费用超标

# 🟡 第二问(追问)

:分别怎么防御?

💡 答案要点
威胁 防御方案
未授权访问 Token/Session 校验 + 白名单接口放行
越权操作 权限校验(Spring Security / Shiro),每次操作检查当前用户是否有权限
恶意刷接口 限流(Sentinel / Redisson RateLimiter)+ 黑名单

# 🔥 场景三:线上接口慢怎么排查

# 📋 问题描述

面试官:用户反馈某个接口响应很慢,你怎么排查?

# 🟢 第一问

:给出完整的排查步骤。

💡 答案要点

从外到内,分层排查

  1. 确认范围:是所有人都慢?还是某个人、某个地区?(客户端 → 网络)

  2. 检查监控:看该接口的平均耗时、P99、成功率(是否有监控?没有就加)

  3. 看日志:该接口最近的请求日志,有没有异常堆栈?

  4. 链路追踪:如果有 SkyWalking/Jaeger,看哪个环节耗时最长(DB?Redis?RPC?)

  5. 针对性排查

    • DB 慢 → 看慢查询日志,EXPLAIN 分析

    • Redis 慢 → 检查大 key、慢日志

    • RPC 慢 → 检查下游服务

  6. 压测复现:本地 / 压测环境复现,用 Arthas 等工具定位

# 🟡 第二问(追问)

:如果定位到是 SQL 慢,你怎么优化?

  1. 开启慢日志查询

  2. 通过explain分析时间长的sql,看看是不是索引出了问题

  3. 然后再检查是否有锁竞争

# 🔴 第三问(深度追问)

:如果定位到是 GC 导致接口慢,你怎么确认和解决?

💡 答案要点

确认

  1. jstat -gcutil <pid> 1s 看 GC 频率和耗时

  2. 开启 GC 日志 -Xloggc:gc.log 分析

解决

问题 解决方案
频繁 Young GC 增大年轻代大小
频繁 Full GC 排查内存泄漏(jmap dump 分析)
GC 停顿时间长 换 G1 / ZGC 垃圾回收器

# 🔥 场景四:服务挂了怎么处理

# 📋 问题描述

面试官:某个微服务突然挂了,你怎么保证整个系统不瘫痪?

# 🟢 第一问

:有哪些常见的故障转移方案?

💡 答案要点
方案 说明
多实例部署 一个挂了,其他顶上(Nacos 自动摘除)
熔断 调用方不再调用故障服务(快速失败)
降级 返回兜底数据(如缓存、默认值)
重试 换个实例重试(需幂等)
主从切换 数据库、Redis 主从自动切换

# 🟡 第二问(追问)

:服务重启后,怎么保证业务不丢?

💡 答案要点

关键在于消息队列 + 持久化

  • 请求先写入 MQ(持久化),消费者处理完才 ACK

  • 服务挂了,消息还在 MQ 里

  • 服务重启后,消费者继续消费

:服务宕机时,有没有可能已经扣了库存但没返回给用户?

# 🔴 第三问(深度追问)

服务宕机时,有没有可能已经扣了库存但没返回给用户?

有这种可能。解决方案:

  1. 订单状态机管控

    定义订单状态流转,Redis 扣库存成功后先生成预订单,标记为待支付 / 待确认状态;用户最终展示的抢购结果,不由单次请求直接返回,由后台根据订单状态机统一判定兜底。

  2. 客户端重试 + 服务端幂等

    客户端请求超时后允许自动重试;服务端以用户 ID + 商品 ID作为唯一幂等标识,保证同一用户同一件商品只能扣一次库存、下一次单,避免重试引发超卖和重复下单。

  3. 延迟消息定时兜底回滚(核心方案)

    Redis 扣库存成功后,立即发送一条延迟消息(延迟 15~30 分钟)到 MQ:

  • 正常流程:用户正常创建订单并完成支付,业务端主动消费 / 标记这条延迟消息,无需任何处理;
  • 异常流程:服务宕机、流程中断或用户抢到后未付款,延迟消息到期触发消费,主动校验订单支付状态;若无有效支付记录,自动回滚 Redis 和数据库库存,释放虚占库存,解决库存冻结、数据不一致问题。
最近更新: 9/19/2026, 1:27:08 PM
编程NOTE   |