大厂Java面试实战:Spring Boot微服务、Redis缓存、Kafka消息队列与Spring AI RAG

大厂Java面试实战:Spring Boot微服务、Redis缓存、Kafka消息队列与Spring AI RAG

故事背景

面试地点:某互联网大厂(电商 + 内容社区 + AIGC 智能客服一体化业务)。

角色:

  • 面试官(M):严肃、节奏快、喜欢追问原理与线上落地。
  • 候选人小Y(Y):气氛担当的"水货程序员",简单题能答,难题开始"凭感觉"。

规则:一共 3轮 ,每轮 3-5个问题,问题围绕同一业务链路逐步加深。


第一轮:电商下单链路(Java/JVM + Spring Boot + 数据库与连接池)

Q1:你负责的电商"创建订单"接口,Spring MVC里从请求到落库,大致流程是什么?

M:别背概念,说清楚线程模型、参数绑定、事务、异常怎么回。

Y :呃......就是 Controller 接到请求,调用 Service,然后 DAO/MyBatis 写数据库。事务就 @Transactional 一加,异常就......统一返回一个 JSON。

M :还行,至少没把 DAO 写在 Controller 里。那你说说线程是谁在用

Y:线程是......Tomcat给的?

M:对。继续。


Q2:订单库用 MyBatis + HikariCP。为什么大厂更常用 HikariCP,不太爱 C3P0?

Y:HikariCP快!据说是"光"一样快。

M:回答像广告词。你说说"快"体现在哪?

Y:嗯......它比较轻量,锁少?

M:勉强算点到点上。


Q3:你怎么排查线上"接口偶发慢",怀疑是 JVM 停顿或GC导致?

Y:我会先看日志......然后看看是不是SQL慢。

M :我问的是 JVM停顿。你给我一个可落地的排查链路。

Y:那我......加大内存?

M:(沉默两秒)你继续说。

Y :看 jstat?然后 jmap

M:至少工具名说对了。


Q4:你们库表变更怎么做?Flyway/Liquibase 用过吗?

Y :用过 Flyway,写 SQL 脚本编号,比如 V1__init.sql

M:不错。那多人协作冲突怎么办?

Y:就......沟通一下,别冲突。

M:行,第一轮到这。


第二轮:高并发与异步解耦(Redis缓存 + Kafka + 分布式追踪与监控)

Q1:内容社区"爆款商品"被大量访问,商品详情接口如何做缓存?用 Spring Cache + Redis 怎么设计 key?

Y :用 @Cacheable,key 就 productId

M:太粗了。商品详情和"地区/用户等级/活动价"有关怎么办?

Y:那......key 里拼上地区?

M:对,继续。


Q2:缓存击穿、穿透、雪崩你分别怎么处理?

Y

  • 击穿:加锁
  • 穿透:布隆过滤器
  • 雪崩:随机过期时间

M:不错,这题答得像个正常人。那加锁你用什么?

Y :Redis setnx

M:可以。


Q3:下单成功后要异步做"发券、发消息、更新推荐画像",为什么要上 Kafka?如何保证至少一次投递?

Y:Kafka吞吐高。至少一次......就是消费者消费失败就重试?

M:那重复消费呢?

Y:那就......不要重复?

M:你这回答很"哲学"。


Q4:线上出现"用户投诉下单后没收到券",你怎么用 Prometheus + Grafana + Jaeger/Zipkin 排查?

Y:Grafana 看看曲线,然后 Jaeger 看看链路。

M:你能说具体点吗?

Y:就......看错误率、延迟,然后找到某个 span 慢。

M:还行,但细节不够。


第三轮:AIGC智能客服(Spring AI + RAG + 向量库 + Agent工具调用)

业务设定:电商平台上线"智能客服",用户问:

"我这单为什么没发货?能不能退款?顺便推荐一个类似商品。"

客服需要:

  • 查订单(权限校验)
  • 读平台规则文档(退款/发货时效)
  • 调用工具(订单服务、物流服务)
  • 支持多轮对话记忆

Q1:你会如何用 Spring AI 做一个"RAG企业文档问答"?流程拆一下。

Y:就是把文档丢给模型,然后模型回答。

M:太天真。RAG 的 "R" 是什么?

Y:Retrieval?检索。

M:对。那检索用什么?

Y:用......向量库?

M:继续。


Q2:向量化(Embedding)怎么做?Milvus/Chroma/Redis Vector 你怎么选?

Y:Embedding 就是把文字变成向量。选哪个看公司喜欢哪个。

M:如果你这么回答,基本就凉了。你至少要从"规模、延迟、运维成本"说。

Y:那我选 Redis,因为我们本来就有 Redis。

M:能落地,但别忘了向量检索能力和召回质量。


Q3:智能客服最怕"AI幻觉"。你怎么降低幻觉?

Y:让它别胡说?

M:你当模型是你儿子吗?给我工程手段。

Y:加提示词?

M:提示词只是开始。


Q4:如果要做 Agent:模型根据用户问题自动调用"订单查询、物流查询、退款规则查询"工具,怎么设计"工具执行框架"和"会话内存"?

Y:用 Spring AI 的工具调用。会话内存就存 Redis。

M:可以,但你得解释清楚"何时调用工具、参数怎么约束、怎么审计"。

Y:审计......打日志?

M:......


面试收尾

M :整体来看,你基础题还行,工程化和原理深挖偏弱,尤其是消息幂等、可观测性闭环、以及 AI 这块的落地细节。今天先到这,回去等通知

Y:好的好的,我回去就把自己"从水货升级成正品"。


文末答案详解(按业务场景+技术点,小白可学习)

说明:下方是每个问题更"标准的大厂回答",包含场景、要点与可执行做法。


第一轮答案:下单链路(Spring MVC + MyBatis/JPA + HikariCP + JVM)

A1:Spring MVC 下单接口从请求到落库流程(线程/绑定/事务/异常)

业务场景:用户点击"提交订单",请求进入订单服务。

典型链路

  1. HTTP线程模型
    • Tomcat/Jetty 使用线程池(如 http-nio)为每个请求分配工作线程。
    • 线程贯穿 Controller → Service → DAO 直到响应返回(同步MVC场景)。
  2. DispatcherServlet
    • 通过 HandlerMapping 找到对应 Controller 方法。
    • 参数解析与绑定(JSON→对象):常见是 Jackson(MappingJackson2HttpMessageConverter)。
  3. 校验与鉴权
    • @Valid + Hibernate Validator 做参数校验。
    • Spring Security Filter Chain 做认证鉴权(如 JWT/OAuth2)。
  4. 事务
    • Service 层使用 @Transactional(基于 AOP 代理)。
    • 关键:默认对 RuntimeException 回滚;受检异常需要配置 rollbackFor
  5. 持久化
    • MyBatis:执行SQL,映射ResultSet。
    • JPA/Hibernate:实体状态转换、脏检查、flush。
  6. 统一异常处理
    • @ControllerAdvice + @ExceptionHandler 将异常映射为统一错误码/错误信息。

A2:HikariCP vs C3P0(为什么大厂更爱HikariCP)

核心点

  • 性能与稳定性:HikariCP 以更少的锁和更低的开销提供更高吞吐与更低延迟。
  • 配置简洁:常用参数少,默认值更合理。
  • 监控友好:可暴露连接池指标(配合 Micrometer → Prometheus)。

关键配置建议(示例):

  • maximumPoolSize:按数据库承载能力与QPS评估
  • connectionTimeout:避免线程长时间阻塞
  • leakDetectionThreshold:辅助定位连接泄漏

A3:排查"偶发慢"是否JVM停顿/GC导致(可落地链路)

业务现象:少量请求RT飙升(例如从50ms到3s),但SQL并不慢。

排查步骤

  1. 看现象是否全局抖动
    • Grafana 看 P99 延迟是否同时抬升。
  2. 检查 GC 日志 (最有效):
    • 开启 GC log(JDK11+用 -Xlog:gc*)。
    • 观察 Full GC/Young GC 次数与停顿时间。
  3. jstat 快速确认
    • jstat -gcutil <pid> 1s 10 看GC频率、老年代占用。
  4. jcmd/jmap/jfr 深入分析
    • jcmd <pid> GC.heap_info / GC.class_histogram
    • jmap -dump:format=b,file=heap.hprof <pid> 配合 MAT 分析内存泄漏
    • JFR(Java Flight Recorder)定位停顿原因(锁竞争/IO/GC)。
  5. 常见原因
    • 内存泄漏导致频繁 Full GC
    • 大对象分配、晋升失败
    • 线程池耗尽/锁竞争造成"假慢"

A4:Flyway/Liquibase 管理表结构变更与冲突

推荐做法

  • 每次变更以增量脚本提交(不可修改已发布版本脚本)。
  • 冲突处理:
    • 通过脚本版本号/时间戳排序
    • Code Review 把控"同一张表多分支修改"的合并
  • CI阶段执行迁移:测试库先跑 Flyway,失败即阻断。

第二轮答案:高并发(Redis缓存 + Kafka + 可观测性)

A1:商品详情缓存设计(Spring Cache + Redis key设计)

业务点 :商品详情可能随 地区、用户等级、活动 变化。

Key建议

  • 基础:product:detail:{productId}
  • 多维:product:detail:{productId}:{region}:{userLevel}:{activityId}

注意

  • 维度过多会导致 key 爆炸,需要权衡:
    • 把"个性化"拆成独立子缓存
    • 或缓存"基础详情",价格与活动走实时/短缓存

A2:缓存击穿/穿透/雪崩

  • 击穿(热点key过期)
    • 互斥锁:Redis SET key value NX PX
    • 双层缓存:逻辑过期 + 异步刷新
  • 穿透(查不存在)
    • 布隆过滤器(Bloom Filter)
    • 缓存空对象(短TTL)
  • 雪崩(大量key同一时间过期)
    • TTL加随机抖动
    • 多级缓存(本地 Caffeine + Redis)
    • 限流/熔断保护

A3:为什么用Kafka?如何做到"至少一次"与"幂等"

业务场景:下单后异步:发券、发站内信、更新画像。

Kafka价值

  • 削峰填谷、解耦、可回放(按偏移量重放)、高吞吐。

**至少一次(At-least-once)**关键:

  • 消费端:处理成功后再提交offset(手动提交或事务性消费)。
  • 失败重试:可本地重试 + 死信队列(DLQ)/重试topic。

重复消费(必须回答清楚)

  • 通过幂等 保证:
    • 唯一业务键(如 orderId+eventType
    • 消费表/去重表(数据库唯一索引)
    • Redis set去重(注意过期与内存)
  • 例:发券服务写 coupon_send_log,以 order_id 建唯一索引;重复消息插入失败即视为已处理。

A4:Prometheus+Grafana+Jaeger/Zipkin 排查"没收到券"

排查闭环

  1. 指标层(Prometheus)
    • coupon_send_success_totalcoupon_send_fail_total
    • Kafka consumer lag
    • 接口P99、错误率
  2. 日志层(ELK)
    • traceId/orderId 搜索跨服务日志
  3. 链路追踪(Jaeger/Zipkin)
    • 看下单请求是否产生"发券事件"span
    • 看消息生产是否成功(producer ack)
    • 看消费端 span 是否存在、是否报错、耗时是否异常
  4. 结论定位
    • 生产失败?(Kafka不可用/超时)
    • 消费积压?(lag高)
    • 消费报错?(依赖服务/DB异常)
    • 幂等挡住了?(重复订单/重复事件)

第三轮答案:AIGC智能客服(Spring AI + RAG + Agent)

A1:Spring AI 实现RAG企业文档问答(完整流程)

目标:回答必须基于企业规则文档,减少幻觉。

流程

  1. 文档加载:PDF/HTML/数据库(Spring AI DocumentReader)。
  2. 切分(Chunking):按段落/标题切块,控制chunk大小与重叠。
  3. 向量化(Embedding):调用 Embedding 模型(OpenAI/Ollama等)将chunk转向量。
  4. 入库(Vector Store):Milvus/Chroma/Redis 向量索引保存向量+元数据。
  5. 检索(Retrieval):用户问题 → 向量化 → 相似度召回 topK chunks。
  6. 提示填充(Prompt Stuffing):把召回的内容作为"证据"塞进提示词。
  7. 生成回答(LLM):要求引用依据、无法确定就说不知道。

A2:Milvus/Chroma/Redis Vector 如何选型(规模/延迟/运维)

  • Redis Vector
    • 优点:公司已有Redis,运维成本低,延迟低,适合中小规模与快速落地。
    • 风险:向量能力、过滤与复杂检索能力相对受限(取决于版本与模块)。
  • Milvus
    • 优点:面向大规模向量检索,能力完整(索引类型、扩展性强)。
    • 成本:独立集群与运维复杂度更高。
  • Chroma
    • 优点:上手快,适合原型或中小规模。
    • 成本:生产化与高可用能力需评估。

选型口诀:小而快 → Redis/Chroma;大而强 → Milvus。


A3:降低AI幻觉(工程手段)

关键组合拳

  1. RAG + 引用约束:回答必须基于检索到的证据;无证据则拒答。
  2. 更强的系统提示
    • 明确"只依据上下文""不确定就说不知道"。
  3. 结构化输出
    • JSON Schema/函数调用(tool calling)约束格式,减少自由发挥。
  4. 检索质量提升
    • chunk切分合理、topK、重排序(rerank)、元数据过滤(按业务线/版本)。
  5. 在线评测与兜底
    • 置信度阈值:低置信度转人工
    • 敏感场景(退款/医疗/金融)增加规则引擎校验

A4:Agent工具调用框架 + 会话内存(订单/物流/规则查询)

目标 :模型不是"编答案",而是先查数据再回答

设计要点

  1. 工具定义标准化
    • 每个工具定义:名称、用途、入参Schema、出参Schema、权限要求。
    • 例如:getOrderStatus(orderId)getLogistics(traceNo)
  2. 何时调用工具
    • 通过 function/tool calling 让模型在需要事实数据时发起调用。
  3. 参数约束与安全
    • orderId 等参数做校验
    • 强制鉴权:只能查当前用户的订单(Spring Security)
    • 防止提示注入:工具调用前后做内容过滤与策略校验
  4. 会话内存(Chat Memory)
    • 存用户画像、上文问题、已确认的订单号等
    • 可用 Redis 存短期会话,设置TTL;长期用数据库
  5. 审计与可观测性
    • 每次工具调用记录:用户、入参、结果摘要、耗时、traceId
    • Prometheus统计工具成功率/失败率/延迟

你该如何把小Y"升级成正品"(学习路线)

  1. Kafka幂等/重试/死信 写成一套模板
  2. Prometheus指标 + traceId贯通日志 在demo里跑通
  3. 用 Spring AI 做一个最小可用RAG:文档→向量库→检索→回答→拒答策略

(完)

相关推荐
qingfeng154155 小时前
企业微信定时群发实战:API 如何实现批量消息自动发送?
java·开发语言·python·自动化·企业微信
手握风云-5 小时前
Redis:不只是缓存那么简单(十二)
redis·缓存
qingfeng154155 小时前
企业微信 API 可以做什么?
java·开发语言·python·自动化·企业微信
梧桐和风5 小时前
2026 年 Java 趋势:AI 浪潮下,Java 会过时吗?
java·开发语言·人工智能
Hesionberger5 小时前
LeetCode105:前序中序构建二叉树(三解法)
java·数据结构·python·算法·leetcode·深度优先
嗨嗨的迷子5 小时前
JDK 17 远程调试连不上 5005:从 attach timeout 到 JDWP 监听地址变更
java·开发语言
Chase_______5 小时前
【Java杂项】为什么 long 可以自动转 float?宽化基本类型转换与精度丢失详解
java·开发语言·python
invicinble5 小时前
java数组相关的信息量
java·开发语言·python
小江的记录本5 小时前
【Java基础】Java 8-21新特性 :JDK17:密封类、模式匹配、Record类(附《思维导图》+《面试高频考点清单》)
java·数据结构·后端·python·mysql·面试·职场和发展