Java大厂面试实录:Spring Boot + Kafka + Redis 在电商秒杀场景下的应用与坑点
面试官:资深架构师 | 谢飞机:自学成才的“注解型”程序员
🎬 面试场景设定:电商大促秒杀系统设计
某互联网大厂正在搭建“618”大促秒杀平台,要求高并发、低延迟、防超卖。面试官围绕此业务背景,对候选人谢飞机展开三轮技术拷问。
🔹 第一轮:基础构建 —— 从项目搭建到核心组件选型
Q1:如果让你用 Spring Boot 搭建一个秒杀服务,你会怎么组织项目结构?依赖怎么管理?
谢飞机:呃……我一般直接去 start.spring.io 创建项目,勾选 Web、JPA、Redis 就行了!Maven 管依赖,pom.xml 自动搞定~
面试官(点头):还行,至少知道脚手架和 Maven。但要注意版本对齐,比如 Spring Boot 3.x 要求 Java 17+,别在生产环境用快照版。
Q2:为什么选择 Redis 而不是本地缓存如 Caffeine 来存库存?
谢飞机:因为……Redis 快啊!还能持久化!而且我们老师说“缓存必须上 Redis”,不然不高级!
面试官(微微一笑):方向没错,但没说到点子上。关键在于分布式一致性。多台机器部署时,本地缓存无法同步库存扣减,会导致超卖。而 Redis 是集中式存储,配合 Lua 脚本可实现原子扣减。
Q3:数据库连接池你用过哪些?HikariCP 为什么是 Spring Boot 默认?
谢飞机:我只用过默认的,没改过配置……HikariCP 听起来像日语,可能是因为日本人写得快?
面试官(忍住笑):它确实是日本人写的,但“快”不只是语言优势。HikariCP 的核心是极致优化——基于字节码增强、轻量锁、无垃圾回收设计,在高并发下性能碾压其他池(如 C3P0)。这也是为何 Spring Boot 2.x 开始将其设为默认。
✅ 小结:第一轮过关,基础尚可,但缺乏深度思考。
🔹 第二轮:进阶挑战 —— 并发控制与消息削峰
Q4:用户抢购时大量请求涌入,数据库扛不住怎么办?如何用 Kafka 削峰?
谢飞机:这个我知道!加 Kafka!所有请求先发到 Kafka,然后慢慢消费,就像……早高峰地铁限流!
面试官:比喻不错。具体流程呢?
谢飞机:呃……前端调接口 → 写入 Kafka → 消费者读出来 → 扣库存?
面试官:接近了。正确姿势是:
- 秒杀接口校验通过后,将订单请求封装为消息投递至 Kafka Topic;
- 异步消费者组从 Topic 拉取,执行最终落库;
- 用户端返回“排队中”,通过 WebSocket 或轮询查结果。
⚠️ 注意:不能把数据库压力转移到 Kafka 生产者!需前置限流(如令牌桶)、幂等处理、防止重复下单。
Q5:Kafka 如何保证消息不丢失?尤其是在宕机情况下?
谢飞机:嗯……Kafka 很稳定,很少丢数据吧?
面试官:这不是答案。要从三个层面保障:
- Producer:设置
acks=all,确保 ISR 全体副本确认; - Broker:
replication.factor >= 3,min.insync.replicas=2; - Consumer:手动提交 offset,且在业务处理成功后再提交。
否则,自动提交可能导致“消息已消费但未落库”的悲剧。
Q6:如果多个消费者同时消费同一个商品的消息,会不会重复扣减库存?
谢飞机:那……可以让只有一个消费者?或者加 synchronized?
面试官:synchronized 只能在单机生效。分布式环境下要用:
- Kafka 分区策略:相同商品 ID 映射到同一 Partition,确保单消费者线程处理;
- 数据库乐观锁:
UPDATE stock SET count = count - 1 WHERE id = ? AND count > 0; - 或使用 Redis 分布式锁(如 Redlock),但注意复杂性和性能损耗。
🚫 切忌盲目加锁,影响吞吐量。
🔹 第三轮:高阶陷阱 —— 缓存一致性与安全防护
Q7:Redis 中库存为 0 后,数据库还没更新完,这时来了新请求怎么办?
谢飞机:哦!我知道!这就是缓存穿透!要用布隆过滤器!
面试官(皱眉):你搞混了。这是缓存与数据库不一致问题。你说的布隆过滤器是用来防“查不存在的商品ID”的。
当前情况应采用:
- 双写一致性:更新数据库后,主动失效 Redis 缓存(Cache Aside Pattern);
- 延迟双删:删除缓存 → 更新 DB → 延迟几百毫秒再删一次,应对主从复制延迟;
- 订阅 binlog(如 Canal):监听 MySQL 变更,异步刷新缓存,实现最终一致。
Q8:如何防止脚本恶意刷单?比如有人用 JMeter 模拟万人抢购。
谢飞机:加验证码呗!图形验证码、滑动验证码都行!
面试官:可以,但不够。还需:
- 接口级限流(如 Resilience4j 限流器,每秒最多 1000 次);
- 用户行为分析(如登录态、设备指纹、IP 黑名单);
- 商品维度限流(每人限购一件);
- 前端混淆 + HTTPS 加密防抓包。
安全是个体系,不能只靠验证码“守门”。
Q9:整个链路监控怎么做?比如某个请求卡住了,怎么定位?
谢飞机:看日志……Logback 输出 info……不行就 debug 断点?
面试官:生产环境不能 debug!你应该:
- 使用 SkyWalking / Zipkin 做分布式追踪,通过 TraceID 串联全流程;
- 集成 Prometheus + Grafana 监控 QPS、响应时间、错误率;
- 日志统一收集到 ELK,便于搜索异常堆栈;
- 关键指标设置告警(如 Kafka Lag > 1000 触发企业微信通知)。
这才是可观测性三大支柱:Logging, Tracing, Metrics。
✅ 面试尾声
面试官:今天的问题就到这里。你的基础知识还有提升空间,尤其对原理理解不够深入。不过思维活跃,有潜力。
谢飞机:那……我是过了吗?
面试官(微笑):回去等通知吧。
💡 最终解析:技术点全景图
🎯 业务场景:电商秒杀系统
目标:支撑百万级 QPS 抢购,防止超卖、保障用户体验、系统稳定。
🧩 技术架构图(简化)
用户请求 → Nginx 负载均衡 → API Gateway(限流/鉴权)
↓
Spring Boot 应用集群
↓
┌──────────── Redis(库存缓存) ← Canal ← MySQL
│ ↑
↓ ↓
Kafka(消息队列) ← 秒杀请求
↑ ↓
└── 消费者服务 → 数据库落单
🔍 核心技术点总结
| 技术栈 | 作用 | 最佳实践 | |--------|------|-----------| | Spring Boot | 快速构建微服务 | 使用 Starter 统一管理依赖 | | Redis | 高速库存访问、分布式锁 | 使用 Lua 脚本保证原子性 | | Kafka | 请求削峰、异步解耦 | 设置合理分区数,避免热点 | | MySQL + JPA/Hibernate | 持久化订单 | 乐观锁防超卖 | | HikariCP | 数据库连接池 | 合理配置最大连接数 | | Resilience4j | 限流降级 | 定义规则保护核心资源 | | Prometheus + Grafana | 系统监控 | 自定义 Dashboard | | Zipkin/SkyWalking | 链路追踪 | 注解或 Agent 注入 TraceID | | Flyway/Liquibase | 数据库版本控制 | CI/CD 中自动执行 |
📚 学习建议
- 不要停留在“会用”,要探究“为什么”;
- 多画架构图,理清组件关系;
- 动手搭建迷你项目(如 mini-seckill),跑通全流程;
- 阅读官方文档,特别是 Spring 和 Kafka 的 Reference Guide。
🌟 记住:面试不是背八股,而是展现你解决问题的能力。
—— 本文献给每一位在深夜调试代码、准备面试的你。

278

被折叠的 条评论
为什么被折叠?



