大厂 Java 面试实录:Spring Boot/Cloud、Kafka、Redis、JVM、K8s、RAG 一条龙(小Y翻车版)
故事背景
某互联网大厂「内容社区 + 音视频 + AIGC」事业群,招聘 Java 后端。
- 面试官(M):严肃、节奏快、喜欢追问"为什么"。
- 候选人小Y(Y):会一点,但不多;简单题能答上,难题开始"玄学输出"。
业务设定:社区用户上传短视频(UGC),平台提供内容推荐;同时接入 AIGC 文生文/文生视频能力,支持"智能客服 + 企业文档问答(RAG)"。系统微服务化,跑在 Kubernetes 上,核心链路包含 Kafka、Redis、MySQL/ES、对象存储、CDN。
第一轮(基础到进阶):从接口到线程,再到数据库与缓存
Q1:Spring Boot 里一个"发布视频"的接口,你会怎么设计?涉及哪些组件?
M: "用户上传短视频,提交标题、标签、封面,返回发布结果。你先说接口怎么设计。"
Y: "就......POST /video/publish,然后用 Spring MVC 接一下,存数据库,返回成功。"
M: "至少方向对。那参数校验、幂等、异步处理你考虑了吗?"
Y: "校验用 @Valid,幂等就......靠感觉?异步可以 @Async。"
M: "好,算你知道一些点,我们继续。"
Q2:你说用 @Async,那线程池怎么配置?为什么不直接用默认?
Y: "默认应该也行吧......反正它会开线程。"
M: "默认线程池容易把服务打挂,讲讲线程池参数:核心线程、最大线程、队列、拒绝策略。"
Y: "核心线程就是常驻的,最大线程是上限,队列是排队......拒绝策略就丢掉?"
M: "能说到这不错,但还不够。我们先记下,后面解析里展开。"
Q3:发布成功后要写 MySQL,用 MyBatis/Hibernate/JPA 你怎么选?连接池用 HikariCP 为什么更常见?
Y: "我用 MyBatis,SQL 可控。Hibernate/JPA 自动生成 SQL 容易翻车。HikariCP......听说快?"
M: "回答得还行。那你知道 HikariCP 为什么快、以及连接池关键指标怎么监控吗?"
Y: "因为它......轻量?监控可以看连接数?"
M: "好,有点概念。"
Q4:热门视频列表要扛流量,你会怎么用 Redis?如何避免缓存击穿/穿透/雪崩?
Y: "Redis 缓存热门列表,击穿就加锁,穿透加布隆过滤器,雪崩加随机过期。"
M: "不错,这题算你稳了。那本地缓存 Caffeine 什么时候用?"
Y: "呃......可能 QPS 太高的时候?"
M: "可以,下一轮我们上微服务链路。"
第二轮(微服务链路):从网关到消息队列,再到可观测与容错
Q1:发布视频后要做转码、封面抽帧、内容审核,你会怎么解耦?Kafka/RabbitMQ 怎么选?
Y: "用消息队列异步。Kafka 吞吐高,RabbitMQ 延迟低......吧?我选 Kafka。"
M: "理由还算像样。那说说 Kafka 的 topic/partition/consumer group,以及如何保证至少一次/恰好一次?"
Y: "partition 提高并行,consumer group 分摊消费。至少一次就是重试,恰好一次就是......不开重复?"
M: "开始飘了,但继续。"
Q2:微服务调用:OpenFeign + Resilience4j 你会怎么做超时、重试、熔断、限流?
Y: "Feign 调用,Resilience4j 加重试和熔断。超时就配置......限流也配置。"
M: "配置只是表象,核心是'哪些接口该重试、哪些不该',以及重试风暴怎么避免。你说说?"
Y: "应该......对幂等接口重试?不幂等就不重试。风暴就少重试。"
M: "还行,有方向。"
Q3:你们用 Spring Cloud/Consul/Eureka 做服务发现。为什么现在很多团队更偏向 K8s Service + DNS?
Y: "因为 Kubernetes 方便?省得自己搭?"
M: "嗯,算是。那你知道 K8s 下灰度发布/滚动升级对 Java 服务有什么坑吗?"
Y: "坑就是......可能会断流?我加个睡眠?"
M: "这回答很'水货',但我喜欢你诚实。"
Q4:链路追踪:Micrometer + Prometheus/Grafana + Jaeger/Zipkin 怎么串起来?
Y: "Micrometer 上报指标到 Prometheus,Grafana 看图;Jaeger 看 trace。"
M: "不错。那你如何定位一次发布视频接口'偶发 3 秒延迟'是 JVM GC 还是下游慢?"
Y: "看 Grafana......看一眼就知道?"
M: "你这属于'望诊'。我们后面写清楚方法。"
第三轮(高阶综合):JVM、数据一致性、RAG/Agent 与安全
Q1:你遇到过 JVM 频繁 Full GC 吗?线上怎么排查?
Y: "遇到过。就调大堆内存,或者重启。"
M: "这是'治标'。要说:指标、dump、定位对象、分析引用链。"
Y: "嗯......我会看下日志。"
M: "行,我们当你愿意学。"
Q2:发布视频要写 MySQL,同时发 Kafka 消息给转码服务。如何避免数据库成功但消息没发(或反过来)?
Y: "用分布式事务?比如......两阶段提交?"
M: "大厂很少直接上 2PC。你至少说出 Outbox/本地消息表、事务消息、幂等消费。"
Y: "对对对,本地消息表我听过,就是放一张表里。"
M: "还算有救。"
Q3:AIGC 智能客服要做企业文档问答(RAG)。你怎么设计:向量化、向量库、检索、提示填充、会话内存、工具调用?
Y: "RAG 就是把文档喂给大模型。向量库用 Milvus。然后问答就能回。"
M: "这回答像把 PPT 读了一遍。那:如何降低幻觉?如何做权限隔离?如何让模型能调用'订单查询'工具?"
Y: "幻觉就......加个提示词说不要胡说?权限隔离......按用户过滤?工具调用我没做过。"
M: "OK,知道你短板在哪了。"
Q4:安全:JWT + OAuth2/Keycloak 在 B 端 SaaS 多租户怎么落地?
Y: "JWT 放用户信息,OAuth2 登录授权。Keycloak 统一做 SSO。"
M: "不错。那租户隔离如何做?token 里放 tenantId 安全吗?"
Y: "放里面......应该可以?加密一下?"
M: "嗯,回答不够严谨。"
面试收尾
M: "整体来说,你基础还行,场景化和深度不足,尤其是 Kafka 语义、可观测落地、RAG 工程化。回去等通知吧,有结果 HR 会联系你。"
Y: "好的老师......不是,好的面试官。"
题目答案与解析(按业务场景讲清楚)
下面把每一题按"业务需求 → 技术点 → 推荐做法/要点"展开,新手可直接照着学习。
第一轮解析
1)发布视频接口设计(Spring MVC / Jakarta EE 思路类似)
业务需求:用户提交发布请求后,需快速返回;转码/审核等耗时操作异步。
技术点:
- Spring MVC Controller + DTO 校验:
@RestController、@Valid、@Validated - 幂等:防止用户重复点击导致重复发布
- 异步化:先落库,再发消息触发后续流程
- API 文档:Swagger/OpenAPI
推荐做法:
- API:
POST /api/v1/videos - 请求体包含:
title、tags、coverUrl、videoObjectKey、clientRequestId - 幂等键:
userId + clientRequestId(或业务唯一键) - 返回:
videoId、status=PENDING - 后续:Kafka 事件
VideoCreated驱动转码/审核
2)@Async 与线程池配置
业务需求:异步任务(如生成封面、调用审核)不能把 Tomcat/Netty 线程占满。
技术点:
- 默认
SimpleAsyncTaskExecutor不复用线程,风险大 ThreadPoolTaskExecutor/自定义Executor- 参数含义:
- corePoolSize:常驻线程数
- maxPoolSize:突发上限
- queueCapacity:缓冲队列
- keepAliveSeconds:非核心线程存活
- rejectedExecutionHandler:拒绝策略(Abort/CallerRuns/Discard/DiscardOldest)
推荐要点:
- IO 密集型:线程数可略大,但要有队列与限流
- 拒绝策略常用
CallerRunsPolicy(把压力"反压"回调用方),比悄悄丢任务更安全 - 配合监控:线程池活跃数、队列长度、拒绝次数
3)MyBatis vs JPA/Hibernate;HikariCP
业务需求:发布写入、查询列表、复杂筛选(可能还要 ES 同步)。
技术点:
- MyBatis:SQL 可控、便于性能调优
- JPA/Hibernate:开发效率高,但需警惕 N+1、懒加载、复杂查询性能
- HikariCP:默认在 Spring Boot 中广泛使用
为什么 HikariCP 常见(面试可答要点):
- 代码路径短、锁竞争少,性能好
- 连接泄漏检测(leakDetectionThreshold)
- 指标清晰:active/idle/pending
监控建议:
- Micrometer 采集连接池指标 → Prometheus → Grafana
- 关注:等待连接时间、连接耗尽、慢 SQL
4)Redis 缓存与三大风险
业务需求:热门列表 QPS 高,DB 扛不住。
技术点与解法:
- 缓存穿透(查不存在):
- 布隆过滤器(RedisBloom/自实现)
- 缓存空值(短 TTL)
- 缓存击穿(热点 key 过期瞬间大量打 DB):
- 互斥锁重建(Redis setnx)
- 逻辑过期(value 带过期字段,后台刷新)
- 缓存雪崩(大量 key 同时过期或 Redis 故障):
- TTL 加随机抖动
- 多级缓存(Caffeine + Redis)
- 限流/降级/熔断
Caffeine 适用:
- 单机内热点非常集中、对延迟极敏感
- 可做 L1,本地命中后不走网络
第二轮解析
1)Kafka 解耦转码/审核:基础概念与投递语义
业务需求:发布后触发多个异步流程(转码、抽帧、鉴黄、写 ES)。
Kafka 核心概念:
- Topic:事件类别(VideoCreated)
- Partition:并行度与顺序单位(同 key 保序)
- Consumer Group:同组分摊分区,实现水平扩展
至少一次 vs 恰好一次:
- 至少一次:消费失败可重试,但可能重复消费 → 要求消费端幂等
- 恰好一次(Kafka EOS):依赖事务生产者/事务性消费-生产链路,工程复杂;很多团队退而求其次:至少一次 + 幂等
工程建议:
- 事件 key 用
videoId保证同视频事件有序 - 消费端幂等:以
eventId/videoId+eventType做去重表或 Redis SET - 失败处理:重试 + DLQ(死信队列)
2)OpenFeign + Resilience4j:超时、重试、熔断、限流的正确姿势
业务需求:调用审核/用户服务/推荐服务,避免下游抖动拖垮上游。
关键点:
- 超时:必须有(连接超时、读超时)
- 重试:只对幂等请求(GET、或业务幂等的 POST)
- 熔断:下游错误率高时快速失败
- 限流:保护自己与下游
避免重试风暴:
- 重试次数小(如 1~2 次)
- 指数退避 + 抖动(避免同步重试)
- 配合熔断:熔断打开时不再重试
3)服务发现:Eureka/Consul vs K8s Service
业务背景:上 K8s 后,服务实例由 K8s 管理,注册中心的价值下降。
K8s Service + DNS 优点:
- 原生、运维成本低
- 与滚动升级/探针/弹性伸缩联动自然
滚动升级对 Java 的坑与对策:
- 坑:Pod 被 kill 时仍有连接/请求在途 → 断流
- 对策:
- readinessProbe:未就绪不接流量
- preStop + 优雅停机(Spring Boot graceful shutdown)
- 设置 terminationGracePeriodSeconds
4)可观测性:指标 + 日志 + Trace 联动定位延迟
业务需求:偶发 3 秒延迟,需要可定位。
体系串联:
- 指标(Metrics):Micrometer → Prometheus → Grafana
- 日志(Logs):Logback/Log4j2 → ELK
- 链路(Tracing):OpenTelemetry/Brave → Jaeger/Zipkin
定位方法(面试可背):
- Grafana 看接口 P95/P99 是否抬升
- 看 JVM 指标:GC 次数/停顿、堆使用、线程数
- 查下游依赖指标:DB 慢查询、连接池等待、Kafka lag
- 打开 trace:看 span 哪段耗时(DB、HTTP、序列化)
- 对应时间窗口去 ELK 查日志(异常、超时、重试)
第三轮解析
1)频繁 Full GC 排查(Java 8/11/17 通用)
业务现象:接口抖动、RT 飙升、CPU 高。
正确排查路径:
- 先看指标:GC 次数、GC pause、Old 区占用趋势
- 采集:
jcmd <pid> GC.heap_infojmap -dump:live,format=b,file=heap.hprof <pid>(谨慎)
- 分析 hprof:MAT/VisualVM 查大对象与引用链
- 常见根因:
- 缓存无上限(Map 持有)
- 线程池队列堆积持有大量对象
- 大对象(大 JSON、byte[]、图片)
- 不合理的日志/Trace 采样导致对象堆积
2)DB + Kafka 一致性:Outbox/本地消息表
业务需求:发布写库成功后必须"最终一定触发转码"。
问题:单体事务无法覆盖 DB 与 MQ。
常见工程解法:
- Outbox(本地消息表) :
- 同一 DB 事务内:写业务表 + 写 outbox 表(待发送事件)
- 后台任务/CDC(如 Debezium)把 outbox 事件投递 Kafka
- 投递成功把 outbox 标记已发送
- 消费端:幂等处理,支持重复投递
优点:不需要 2PC,可靠、可审计、易补偿。
3)RAG/Agent 工程化:降低幻觉、权限隔离、工具调用
业务需求:企业文档问答 + 客服工单查询,要求"答得对、可追溯、可控"。
RAG 标准链路:
- 文档加载:PDF/Word/网页(文档加载器)
- 切分:按段落/标题,控制 chunk 大小
- 向量化:Embedding 模型(OpenAI/Ollama 等)
- 向量库:Milvus/Chroma/Redis Vector
- 检索:相似度 + 关键字混合检索(可加 rerank)
- 提示填充:把检索到的上下文塞入 prompt(带引用)
- 生成:LLM 输出
降低幻觉(可答要点):
- 强制"基于上下文回答",无依据则说不知道
- 输出附带引用片段/文档链接
- 检索质量:chunk 合理、加 rerank
- 评测:用离线问答集做准确率评估
权限隔离(B 端常见):
- 向量数据加 tenantId / docAcl 字段
- 检索时先按权限过滤再相似度排序(或先粗过滤)
Agent/工具调用:
- 让模型调用"订单查询/工单创建"等工具:
- 定义 tool schema(名称、入参 JSON Schema、描述)
- 模型输出 function call
- 服务端执行工具 → 返回结果 → 模型二次总结
- MCP(模型上下文协议)/标准化工具调用:统一工具接入与扩展
4)JWT + OAuth2/Keycloak:多租户 SaaS 落地
业务需求:同一套系统服务多个企业(租户),数据隔离。
推荐做法:
- OAuth2/OIDC:Keycloak 负责认证与签发 token
- JWT 中可带:
sub、roles、tenantId(或 tenant realm)
token 里放 tenantId 是否安全?
- 可以放,但前提:
- token 必须签名校验(RS256 等)
- 服务端不能只"信任前端传参",而是信任已验证的 token claims
- 更强隔离:
- Keycloak realm per tenant(管理成本高)
- 或统一 realm + tenant claim + 后端强制数据过滤
后端落地要点:
- Spring Security:把 tenantId 写入 SecurityContext
- DB 层:MyBatis/JPA 拦截器自动追加 tenant 条件(谨慎处理跨租户后台账号)
学习路线(按本文覆盖栈)
- Spring Boot/MVC → 参数校验、异常处理、线程池
- MyBatis/JPA + HikariCP → 慢 SQL、连接池监控
- Redis/Caffeine → 多级缓存与高并发风险
- Kafka → 语义、幂等、DLQ、消费堆积
- Resilience4j → 超时/重试/熔断/限流组合
- Micrometer/Prometheus/Jaeger → 线上定位方法
- JVM → GC 与 dump 分析
- RAG/Agent → 检索、权限、工具调用、反幻觉
(完)