大厂Java面试实战:Spring Boot/Cloud + Redis/Kafka + K8s + RAG/Agent 追问全流程(小Y翻车记)
场景:某互联网大厂「内容社区 + 音视频 + AIGC」业务线,一面。
角色:
- 面试官(严肃):不笑,但句句致命。
- 小Y(搞笑水货):简单题能答,复杂题开始"我感觉""应该是"。
第一轮:从内容社区入口到基本功(Java/JVM/Spring Boot/DB)
Q1(业务起点):内容社区的"发帖"接口,你会怎么设计?
面试官 :我们有UGC内容社区,用户发帖(文字+图片+视频链接)。你用 Spring Boot 写一个 POST /posts,你会考虑哪些点?
小Y :就......Controller 接一下 DTO,然后 Service 存数据库。图片视频我就放 OSS,然后存 URL。要不我再加个 @Valid。
面试官:基本方向对。那你会做幂等吗?比如用户手滑点两次。
小Y:可以......前端禁用按钮?
面试官:后端也要。继续。
Q2(延伸到数据库):帖子写入与"热度"字段,如何避免并发写热点?
面试官 :帖子有 like_count、comment_count,高并发下怎么更新?
小Y :直接 update set like_count = like_count + 1?数据库很强的。
面试官:强是强,但你得解释"强在哪里"。行锁?热点行?缓存?
小Y:嗯......行锁......应该会锁住那一行,然后排队。
面试官:至少知道行锁。继续。
Q3(JVM基本功):线上偶发Full GC,你怎么排查?
面试官:发帖高峰期偶发 RT 抖动,监控看到 Full GC,你的排查路径?JDK 11。
小Y :我会先看看日志......然后 jmap 一下?或者重启。
面试官:重启是最后一步。你说说:GC 日志、堆转储、谁在分配、是不是大对象。
小Y:哦对对,看 GC 日志,看看是不是内存泄漏。大概这样。
面试官:至少方向没偏。
Q4(框架理解):Spring Boot 自动配置原理你能讲清楚吗?
面试官 :为什么你引入 spring-boot-starter-web 就有 Tomcat、MVC、Jackson?
小Y:因为它"自动"。
面试官 :......你说 @SpringBootApplication 包含什么?spring.factories(或新版本的自动配置导入)怎么加载?
小Y :这个我记得是......@EnableAutoConfiguration 会扫描 classpath,满足条件就注入 Bean。
面试官:还不错。
第二轮:引入分布式与高并发(Redis/Kafka/Spring Cloud/Resilience4j)
Q1(场景升级):帖子发布后要异步做"内容审核 + 提取标签 + 推送Feed",怎么解耦?
面试官:发帖接口必须 200ms 内返回,但后面要走审核、AIGC标签、Feed 扩散。你怎么设计?
小Y:用 MQ!比如 Kafka。发帖成功发个消息,然后消费者去做审核和推送。
面试官:为什么 Kafka?RabbitMQ 行不行?怎么保证"至少一次/恰好一次"?
小Y:Kafka 吞吐高。恰好一次......我记得 Kafka 有事务?反正不会丢。
面试官:不会丢≠不会重复。
Q2(缓存与一致性):Feed 流用 Redis 缓存,怎么处理缓存穿透/击穿/雪崩?
面试官:用户打开首页,Feed 读 Redis,缓存没命中就查 DB。怎么防穿透、击穿、雪崩?
小Y:穿透可以用布隆过滤器;击穿加互斥锁;雪崩加随机过期时间。
面试官:很好。这些你做过?
小Y:嗯......看过文章,理论上会。
面试官:至少背得对。
Q3(分布式调用):审核服务挂了,发帖还能成功吗?怎么做降级与隔离?
面试官:你用 Spring Cloud/OpenFeign 调审核服务,审核服务慢/挂,会把发帖拖死。怎么做?
小Y:可以设置超时、重试,然后......熔断?用 Resilience4j。
面试官:说说舱壁隔离、限流、重试风暴怎么避免。
小Y:舱壁就是线程池隔离;限流就是 QPS 限制;重试风暴......少重试?
面试官:可以。
Q4(数据一致性):发帖写库成功但发Kafka失败,怎么办?
面试官:你先写 MySQL,再发 Kafka。如果写库成功但发消息失败,Feed 就不同步了。怎么保证最终一致?
小Y:加事务?数据库和 Kafka 一个事务。
面试官:跨系统事务很难。你听过 Outbox/本地消息表 吗?
小Y:听过......就是先写一张消息表,然后定时任务发?
面试官:不错,继续。
第三轮:云原生 + 可观测 + AI-RAG(K8s/Prometheus/Jaeger/Spring AI/向量库)
Q1(音视频场景):视频上传后要转码、截图、生成字幕,如何做"任务编排"?
面试官:音视频处理是典型长耗时 pipeline:上传→转码→截图→ASR字幕→审核。你怎么编排?
小Y:用消息队列串起来,一个服务消费完再发下一个主题。或者搞个工作流引擎。
面试官:那失败重试与幂等呢?比如转码重复执行成本很高。
小Y:用任务ID去重?重复就不做。
面试官:可以。
Q2(Kubernetes):你的发帖服务在K8s里,如何做灰度发布与自动扩缩容?
面试官:K8s里怎么灰度?怎么基于指标扩缩容?
小Y:灰度就是多起几个 Pod,然后慢慢切流。扩缩容可以 HPA,看 CPU。
面试官:只看 CPU 不够,QPS/延迟呢?
小Y:可以用 Prometheus 指标,然后自定义扩缩容......具体 YAML 我记不清。
面试官:嗯。
Q3(可观测性):线上"发帖慢"你怎么定位是哪一环?
面试官:用户投诉发帖慢。你如何用 Micrometer + Prometheus/Grafana + ELK + Jaeger 定位?
小Y:Grafana 看 RT,ELK 查日志,Jaeger 看链路。然后就能找到慢的地方。
面试官:你至少知道工具的分工。那 TraceId 如何贯穿日志?
小Y:MDC?
面试官:对。
Q4(AI加分题):我们做"企业知识库问答"给审核同学用,RAG怎么落地?
面试官 :现在要做一个内部"审核规则问答",文档很多。你用 Spring AI 怎么做 RAG?向量库用 Milvus/Chroma/Redis 都行。
小Y:RAG 就是先把文档向量化,存到向量库,然后问问题时去检索相似内容,再把内容塞给大模型。
面试官:不错。那如何降低幻觉?如何做会话记忆?Agent 什么时候需要?
小Y:幻觉就......多给上下文?记忆就是把聊天记录存起来。Agent 就是让它能调用工具,比如查数据库。
面试官:回答有点虚,但方向对。
面试收尾
面试官:今天先到这里。你基础还可以,分布式一致性和云原生细节需要更扎实,AI/RAG 也要多做落地。回去等通知,有消息 HR 会联系。
小Y:好的老师,我回去就把"我感觉"换成"我验证过"。
参考答案与知识点拆解(按业务链路讲清楚)
目标:把面试中的问题补齐成可落地方案,小白按这份复盘能搭出"内容社区 + 音视频 + AIGC/RAG"的基础架构。
第一轮答案:接口设计、并发计数、JVM、自动配置
A1 发帖接口如何设计(Spring Boot + 幂等 + 校验)
业务目标 :POST /posts 在 200ms 内返回,主体写入成功即可,耗时任务异步。
关键点:
- DTO校验 :
@Valid+ Hibernate Validator;限制标题长度、正文大小、URL白名单等。 - 幂等 :
- 客户端生成
Idempotency-Key(或请求唯一ID),服务端用 Redis SETNX / DB 唯一索引保存处理结果。 - 幂等窗口例如 5~10 分钟。
- 客户端生成
- 安全:Spring Security + JWT/OAuth2,接口鉴权、限流(网关或 Resilience4j RateLimiter)。
- 落库 :MySQL/PostgreSQL,字段包含
post_id(雪花/UUID)、user_id、content、media_urls、status(待审核/已发布/驳回)。 - 返回 :只返回
post_id+ 状态(例如PENDING_REVIEW),后续进度由异步通知/轮询查询。
A2 点赞/评论数并发更新(热点行问题)
问题本质 :update post set like_count = like_count + 1 where id=? 会对同一行加锁(InnoDB 行锁),高并发时形成热点,吞吐下降。
常见方案:
- Redis 计数 + 异步回写 (推荐):
- 点赞先
INCR post:like:{id}; - 定时/批量(Kafka/定时任务)回写 DB;
- 需要处理:宕机丢数据(AOF/RDB)、回写幂等、对账。
- 点赞先
- 分片计数 :对同一 post 的计数拆成 N 个 key:
post:like:{id}:{shard},读时汇总,写时随机打散。 - 数据库层优化:减少频繁写热点,或把计数拆表;但核心仍是"写扩散"。
A3 Full GC 排查路径(JDK 11)
步骤(从快到慢):
- 确认现象 :Prometheus/Grafana 看
jvm_gc_pause_seconds、RT、CPU、容器内存。 - 开启/分析 GC 日志 :JDK11 用
-Xlog:gc*:file=gc.log:time,uptime,level,tags。 - 定位原因 :
- 内存泄漏(Old 区持续上涨);
- 大对象/突刺(瞬时分配导致晋升);
- 不合理堆设置(容器内存限制下 Xmx 过大/过小)。
- 堆转储 :
jmap -dump:live,format=b,file=heap.hprof <pid>(注意线上风险),用 MAT/VisualVM 分析 dominator tree。 - 结合分配剖析:JFR/async-profiler 看热点分配。
A4 Spring Boot 自动配置原理
核心链路:
@SpringBootApplication=@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan@EnableAutoConfiguration通过 AutoConfigurationImportSelector 导入候选配置类。- 候选配置来源:
- Spring Boot 2.x:
META-INF/spring.factories - Spring Boot 3.x:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- Spring Boot 2.x:
@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty等条件注解决定是否生效。
第二轮答案:MQ解耦、缓存三大问题、熔断隔离、最终一致性
B1 异步解耦:Kafka/RabbitMQ怎么选?如何保证语义
场景:发帖后触发:审核、标签、Feed、推送。
选型:
- Kafka:高吞吐、顺序性(分区内)、适合日志流/事件流、可回放。
- RabbitMQ:路由灵活、延迟队列等能力强,业务命令型消息常用。
至少一次(at-least-once):最常用。
- 生产者:发送成功确认(acks=all)
- 消费者:处理成功后再提交 offset
- 代价:可能重复,需要 消费者幂等。
恰好一次(exactly-once):Kafka 事务 + 幂等生产者 + 下游支持事务/幂等;工程复杂,通常仍以"至少一次 + 幂等"落地。
B2 Redis 缓存穿透/击穿/雪崩
- 穿透 (查不存在的 key):
- 布隆过滤器(Bloom Filter)挡掉绝大多数非法请求;
- 缓存空值(短 TTL)。
- 击穿 (热点 key 过期瞬间大量并发打 DB):
- 互斥锁/单飞:
SETNX lock,只有一个线程回源; - 逻辑过期:后台异步刷新,前台先返回旧值。
- 互斥锁/单飞:
- 雪崩 (大量 key 同时过期):
- TTL 加随机抖动;
- 分层缓存(Caffeine + Redis);
- 限流/降级保护 DB。
B3 审核服务慢/挂:Resilience4j 的组合拳
- Timeout:上游调用设置严格超时(比如 50~100ms)。
- Bulkhead(舱壁):线程池/信号量隔离,避免把主业务线程耗尽。
- CircuitBreaker(熔断):错误率/慢调用超阈值打开熔断,快速失败。
- RateLimiter(限流):保护下游。
- Retry(重试):仅对幂等请求;设置退避(exponential backoff)避免重试风暴。
- Fallback(降级) :审核不可用时:
- 发帖仍成功,但状态置为
PENDING_REVIEW; - 由异步审核补偿。
- 发帖仍成功,但状态置为
B4 写库成功但发消息失败:Outbox(本地消息表)
目标:保证"写库"和"发事件"最终一致。
做法:同一个 DB 事务内:
- 写
post表 - 写
outbox_event表(event_id, aggregate_id, payload, status)
之后由后台任务/CDC:
- 定时扫描
outbox_event未投递事件 → 投递 Kafka → 标记已投递 - 或用 Debezium 等 CDC 监听 outbox 表变更推 Kafka
消费者侧 :用 event_id 做幂等(去重表/Redis set)。
第三轮答案:音视频编排、K8s发布扩缩容、可观测、RAG落地
C1 音视频处理 pipeline:编排 + 幂等
推荐架构:
- 事件驱动(Kafka/Pulsar)+ 状态机(DB 状态)或工作流引擎(Temporal/Argo Workflows)
- 每一步产物落对象存储(转码文件、截图、字幕文件)
幂等:
- 以
job_id/media_id作为幂等键;每一步写入 step 状态(SUCCESS/FAILED) - 重试只对失败步骤;若检测到产物已存在则直接跳过
C2 K8s 灰度发布与自动扩缩容
- 灰度 :
- Deployment 滚动更新(最基础)
- 进阶:Service Mesh(Istio)或 Ingress 按比例/按 Header 分流(金丝雀)
- 扩缩容 HPA :
- CPU/内存指标
- 更合理:自定义指标(QPS、p95 延迟、队列堆积)
- Prometheus Adapter 将指标暴露给 HPA
C3 可观测性:从"慢"定位到具体环节
- 指标(Metrics) :Micrometer 埋点
http.server.requests、DB连接池、Kafka lag,自顶向下看 p95/p99。 - 日志(Logs):Logback/Log4j2 + JSON 格式,统一 TraceId;ELK 查询异常与慢日志。
- 链路(Traces):OpenTelemetry/Jaeger/Zipkin 看到一次请求跨服务耗时分布。
- TraceId 贯穿 :
- 在网关生成 TraceId
- 通过 HTTP Header 透传
- 日志 MDC 打印
traceId字段
C4 RAG 落地:Spring AI + 向量库 + 反幻觉
流程:
- 文档加载:PDF/HTML/Confluence/数据库 → 分段(chunk)
- 向量化(Embedding):OpenAI/Ollama embedding 模型
- 入库:Milvus/Chroma/Redis Vector
- 检索:相似度 + 元数据过滤(部门/版本/生效日期)
- 提示填充:把 topK 片段作为"证据"塞进 Prompt
- 生成回答:大模型输出 + 引用来源
降低幻觉:
- 强制"基于检索片段回答,不足则说不知道"
- 输出带引用(source + chunk id)
- 设置信心阈值:低于阈值直接拒答/转人工
会话记忆:
- 短期:把最近 N 轮对话做摘要(Conversation Summary Memory)
- 长期:把重要事实向量化存储,按语义检索回填
Agent 何时需要:
- 问题需要"多步工具调用/复杂工作流"时:查库、查工单、触发审批、调用审核规则服务等
- 采用工具执行框架(Tool Calling),并做权限控制与审计
完整面试链路总结: 发帖(Spring Boot + 幂等)→ 写库(MyBatis/JPA + 连接池)→ 事件(Kafka)→ 缓存(Redis)→ 微服务治理(Resilience4j)→ 云原生(K8s + HPA)→ 可观测(Prometheus/ELK/Jaeger)→ AI能力(Spring AI RAG/Agent)。