Java大厂面试实录:Spring Boot+微服务+分布式缓存三连问,谢飞机现场翻车?
面试官:你好,请坐。我是本次Java后端岗位的面试官,先简单自我介绍一下吧。
谢飞机:您好!我叫谢飞机,三年Java开发经验,熟悉Spring Boot、MyBatis、Redis,做过电商和社区类项目,能写CRUD,也会看报错日志……
面试官(微微一笑):不错,基础定位很准确。那我们开始吧——今天围绕一个本地生活服务平台展开,比如“美团”这类App中的商家优惠券系统。
第一轮:Spring Boot 与 Web 基础(难度:★☆☆☆☆)
Q1:如果我们要做一个优惠券领取接口,使用 Spring Boot 如何实现?需要哪些注解?
谢飞机:这个我会!用 @RestController 标记控制器,方法上加 @PostMapping("/coupon/receive"),参数用 @RequestBody 接收用户ID和券ID就行。
面试官:很好,思路清晰。那如果要校验用户是否登录,你怎么处理?
谢飞机:加个拦截器?或者用 @PreAuthorize("hasRole('USER')"),配合 Spring Security!
面试官:不错,Security 的基本用法掌握了。那返回结果呢?如何统一封装?
谢飞机:我们公司有 Result<T> 类,包含 code、msg、data,然后在 Controller 里手动封装,或者用 @ControllerAdvice 全局处理异常和返回值。
面试官:很好,具备工程化思维。
第二轮:数据库与缓存设计(难度:★★★☆☆)
Q4:高并发下大量用户抢一张优惠券,怎么防止超发?
谢飞机:呃……加 synchronized?不行不行,那是单机的。嗯……数据库加唯一索引?对!用户ID + 券ID 做联合唯一,插入失败就是领过了。
面试官:可以,但性能瓶颈在哪?
谢飞机:啊……MySQL 写太频繁了?锁表了?
面试官:接近了。那能不能先用缓存扛住?
谢飞机:可以用 Redis 啊!先查 Redis 有没有库存,有就 DECR,等于0就拒绝请求,再异步写数据库。
面试官:那如果 Redis 宕机了怎么办?
谢飞机:呃……重启?或者……主从?我还没配过哨兵……
面试官:提示一下,可以结合 DB + Redis + 消息队列做补偿。
谢飞机:哦!比如用 Kafka 记录领取行为,后台消费落库,失败重试?
面试官:方向正确,但细节还需打磨。
第三轮:微服务与高可用(难度:★★★★★)
Q7:优惠券服务独立成微服务,订单服务如何调用它?
谢飞机:用 OpenFeign!@FeignClient(name = "coupon-service"),定义个接口就行。
面试官:如果 coupon-service 挂了,订单服务会怎样?
谢飞机:会卡住?超时?我们可以设 feign.client.config.default.connectTimeout=5000……
面试官:那如果瞬时流量压垮了 coupon-service 呢?
谢飞机:加机器!扩容!
面试官:来不及呢?有没有保护机制?
谢飞机:熔断?Hystrix?但听说停更了……Resilience4j?我只听过名字……
面试官:那链路追踪呢?出问题怎么定位?
谢飞机:看日志……grep?ELK?
面试官:有没有更高效的?比如分布式链路追踪工具?
谢飞机:Jaeger?Zipkin?我在配置文件里见过,但没用过……
面试官:今天的面试就到这里。你对主流技术都有所了解,广度不错,但深度还需加强。回去等通知吧。
谢飞机(小声):又是这句……我已经收到8个“回去等通知”了……
【附录】技术解析:本地生活平台优惠券系统的架构设计
业务场景背景
本地生活服务平台(如美团、大众点评)中,商家发放限时限量优惠券,用户抢券。典型特征:短时间高并发、防超卖、最终一致性、服务拆分。
技术点详解
1. Spring Boot 构建 REST API
- 使用
@RestController+@RequestMapping快速暴露接口 - 配合
@Valid+@RequestBody实现参数校验 @ControllerAdvice统一处理异常与返回格式,提升可维护性
2. 防止优惠券超发的方案
方案一:数据库层面
- 唯一索引:
user_id + coupon_id联合唯一,避免重复领取 - 乐观锁:版本号控制,更新时判断
version = version + 1
方案二:Redis 缓存限流
- 初始化库存:
SET coupon:1001:stock 100 - 领取时原子操作:
DECR coupon:1001:stock,若结果 ≥0 可领取,否则拒绝 - 结合 Lua 脚本保证原子性
方案三:Redis + DB + 消息队列 异步削峰
- 用户请求 → Redis 扣减库存 → 成功则发消息到 Kafka → 消费者异步落库
- 即使 DB 瞬间压力大,也能通过队列缓冲,保障系统不崩
3. 微服务调用与容错
- OpenFeign:声明式 HTTP 客户端,简化服务间调用
- Resilience4j:轻量级熔断降级框架,支持速率限制、重试、熔断
resilience4j.ratelimiter.instances.couponService.limitForPeriod=100 - 服务注册发现:Nacos / Eureka 注册优惠券服务,订单服务动态调用
4. 分布式链路追踪
- Sleuth + Zipkin:请求链路打标,记录 traceId、spanId
- 出现慢请求时,通过 Zipkin UI 查看全流程耗时,快速定位瓶颈服务
5. 监控与告警
- Prometheus + Grafana:采集 JVM、HTTP 请求、Redis 连接池等指标
- ELK:集中收集日志,搜索错误堆栈
6. 高可用保障
- Redis:主从 + 哨兵 或 Cluster 模式,避免单点故障
- 数据库:读写分离 + 分库分表(如 ShardingSphere)
- 降级策略:优惠券服务不可用时,可降级为“离线领取”,后续补发
总结:一次看似简单的“领券”功能,背后涉及 Spring Boot、Redis、MySQL、Kafka、Feign、Resilience4j、Zipkin 等多种技术协同。大厂考察的不仅是你会不会写代码,更是你能否在复杂业务中做出高性能、高可用、可维护的设计。
如果你是“谢飞机”,别灰心,把每一轮问题吃透,下次就能笑着走出面试间。

774

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



