示例成品 看全文 ↓

程序员面试题模拟+项目和八股追问练习

技术面既问算法和系统设计,又爱顺着简历项目一层层追问,八股背了但一被问「你项目里怎么做的」就露馅。

免费看示例成品:文字简历求职 ›

有人这样说「刚投完字节后端岗,简历里写了个用Redis实现的秒杀系统,现在怕被问穿。」

能替你选的都选好了。不想动,直接点下面「交给 AI 办」,点一下就开始做;想改,就点一下要的那个。

已替你选好想改就点一下

只有你知道的不填就先空着,成品里留【待填】

还能补充

还想怎么改可以不选

高级选项一般不用动 · 这件事通常 1 分钟左右做好

示例成品全文按上面这组示例选项真跑出来的

下面按“面试官原话 → 追问链 → 你该怎么答”来。答案不是标准答案,是你能直接改成自己项目细节的骨架,尽量说人话。


Q1|项目链路与压测数据

面试官:先把你这个秒杀系统从用户点击到返回结果的完整链路讲一下,只说关键节点。

追问:

  • Redis 和 MySQL 分别承担什么?
  • 下单是同步还是异步?
  • 你实测 QPS 多少?瓶颈在哪?
  • 机器配置是什么?压测怎么做的?

你可以这样答:

链路:
用户点击 → Nginx/网关限流 → 校验登录/活动时间/用户资格 → Redis 预热库存,用 Lua 原子扣减 → 扣减成功发 MQ → 快速返回“已抢到/排队中” → 订单服务消费 MQ,写 MySQL 订单和库存。

Redis 是库存唯一扣减源,MySQL 只做最终落库,不直接接秒杀流量。
下单走异步,不然同步写 MySQL 会把链路拖垮。

压测数据要提前准备好,别只说“能扛高并发”。可以讲:
“单机 Redis 跑几万 QPS 没问题,我的瓶颈在应用层连接池/序列化,不是 Redis 本身。压测用 wrk/JMeter,机器几核几 G,错误率多少。”


Q2|Redis 库存原子扣减

面试官:库存扣减具体怎么做的?为什么能防止超卖?

追问:

  • Lua 脚本里写了什么?
  • 为什么不先 GET 再判断再 SET?
  • DECR 变负数怎么办?
  • 扣减成功但下单失败,怎么回补?

你可以这样答:

我用 Lua 脚本,核心逻辑是:

local stock = tonumber(redis.call('GET', KEYS[1]) or 0)
local bought = tonumber(redis.call('HGET', KEYS[2], ARGV[1]) or 0)

if stock <= 0 then return -1 end
if bought >= tonumber(ARGV[2]) then return -2 end

redis.call('DECRBY', KEYS[1], 1)
redis.call('HINCRBY', KEYS[2], ARGV[1], 1)
return 1

KEYS[1] 是商品库存 key,KEYS[2] 是用户已购 hash,ARGV[1] 是用户 ID,ARGV[2] 是限购数。

Redis 执行 Lua 是原子的,不会出现“多个请求同时读到库存 1,都扣成 0”的情况。
不能先 GET 再判断再 SET,中间有竞态,Lua 就是解决这个。

如果扣减成功,下单失败,我用 MQ 重试 + 死信 + 定时对账回补,不能只嘴上说“回补”。


Q3|Redis 与 MySQL 一致性

面试官:Redis 扣了库存,MySQL 什么时候扣?两边怎么保证一致?

追问:

  • 为什么不先扣 MySQL?
  • 如果 MySQL 更新失败,Redis 已经扣了怎么办?
  • 反过来,Redis 扣减失败但 MySQL 还有库存怎么办?

你可以这样答:

秒杀场景以 Redis 库存为唯一入口,MySQL 是最终存储。
扣减成功后发 MQ,订单服务消费后写订单、扣 MySQL 库存。一致性是最终一致,不是强一致。

异常处理:
MQ 消费失败重试,重试多次进死信,定时任务对账 Redis 和 MySQL,不一致就补偿或告警。

不要套“延迟双删”那套,那是缓存回填,不是库存扣减。
面试官问为什么不先扣 MySQL,你就说:MySQL 行锁会串行化扣减,扛不住高并发,Redis 单线程原子扣减更快。


Q4|分布式锁到底用没用

面试官:你这个系统用到分布式锁了吗?如果没用,为什么?

追问:

  • 扣库存为什么可以不靠分布式锁?
  • Redis 的 SETNX 加锁有什么坑?
  • 锁超时业务没执行完怎么办?
  • 主从切换锁丢失怎么办?

你可以这样答:

扣库存我用 Lua 原子扣减,不需要分布式锁。
分布式锁会降低并发,能不用就不用。

如果一定要用锁,比如防止重复创建订单,我会用:
SET key value NX PX + 唯一 requestId,释放时用 Lua 校验后 DEL,不能直接 DEL。

超时问题用 Redisson 看门狗续期。
主从切换锁丢失,Redlock 可以降低概率,但不绝对。更稳的是用数据库唯一索引/幂等兜底,锁只是性能优化。


Q5|秒杀开始 10 万 QPS 怎么限流削峰

面试官:秒杀开始瞬间 10 万 QPS,你怎么保护系统?

追问:

  • 限流在哪一层做?
  • 为什么用 MQ?MQ 积压怎么办?
  • 前端有什么防刷手段?
  • 库存没了怎么快速失败?

你可以这样答:

分层处理:

  1. 前端:按钮置灰、防抖、验证码/风控。
  2. 网关/Nginx:对 IP、用户限流。
  3. 业务层:令牌桶/漏桶限制下单接口。
  4. Redis 扣库存是最终闸门,库存不足直接返回“已抢光”。

MQ 用来削峰,不阻塞主链路。
如果 MQ 积压,先扩容消费者,批量消费,关闭非核心消息,必要时限流生产者。

核心思路:入口先拒绝,别让流量打到后端。


Q6|缓存击穿、穿透、雪崩,结合秒杀

面试官:缓存击穿、穿透、雪崩分别是什么?秒杀里哪个最容易发生?

追问:

  • 秒杀热点库存 key 过期怎么办?
  • 库存为 0 后,这个 key 还是热 key 吗?
  • 布隆过滤器在秒杀里有用吗?

你可以这样答:

击穿:热点 key 过期,大量请求打到 MySQL。
穿透:请求不存在的商品 ID,Redis 和 MySQL 都没有。
雪崩:大量 key 同时过期,或者 Redis 宕机。

秒杀里最容易发生的是击穿和雪崩。库存 key 是天然热 key,活动期间不能简单设置随机过期。
库存为 0 也是高频访问,要缓存“已抢光”状态,否则请求还会压到后端。

布隆过滤器主要防穿透,对热 key 击穿没帮助。


Q7|幂等与重复下单

面试官:用户狂点按钮、网络重试,会不会重复扣库存或者重复下单?你怎么做幂等?

追问:

  • Redis 扣库存已经原子了,为什么还会重复下单?
  • 数据库唯一索引怎么设计?
  • TOKEN 幂等和唯一索引区别?

你可以这样答:

超卖和重复下单是两个问题。

Lua 原子扣库存只保证库存不超卖,不保证一个用户只下单一次。
我在 Lua 里同时检查用户已购数量,用户限购 1 件时,同一用户重复请求会直接失败。

但订单服务消费 MQ 可能重复投递,所以还要做接口幂等。
最终兜底用数据库唯一索引:user_id + activity_id 或者订单号唯一。
TOKEN 幂等是防前端重复提交,唯一索引是最后防线。


Q8|Redis 持久化与宕机恢复

面试官:Redis 持久化怎么配的?秒杀场景 Redis 宕机能接受丢多少数据?

追问:

  • RDB 和 AOF 区别?
  • AOF everysec 丢多少?
  • 主从同步会丢数据吗?
  • Redis 挂了库存怎么恢复?

你可以这样答:

配置:AOF everysec + RDB 做备份,主从 + 哨兵。
AOF everysec 最多丢约 1 秒写入,RDB 可能丢几分钟到更久。
主从异步复制,主宕机时从可能没同步到最新数据,所以也可能丢一点。

Redis 宕机后,先熔断秒杀入口,不要直接拿 MySQL 库存覆盖 Redis。
因为可能有“Redis 已经扣了,但订单还没落 MySQL”的情况。
要先用 AOF/用户已购标记/订单流水对账,再重新预热库存。
原则:宁可少卖,不能超卖。


Q9|Redis 单线程是优势还是瓶颈

面试官:Redis 单线程为什么快?在秒杀里单线程是优势还是瓶颈?

追问:

  • Lua 脚本

同类还能办

全部 ›
选面试时间免费看示例 ›写面试准备稿免费看示例 ›模拟面试问题免费看示例 ›写面试自我介绍免费看示例 ›准备统一面试题免费看示例 ›准备面试常见问题免费看示例 ›

同样出简历求职的

首页