宠物经济大厂Java面试实录:JDK17、Redis分布式锁、Kafka订单削峰、Seata分布式事务、Spring AI+RAG智能养宠助手,谢飞机三轮被虐哭(附完整答案解析)
宠物经济大厂Java面试实录:JDK17、Redis分布式锁、Kafka订单削峰、Seata分布式事务、Spring AI+RAG智能养宠助手,谢飞机三轮被虐哭(附完整答案解析)
场景设定
公司:宠物经济独角兽「萌宠星球」——宠物电商、宠物医疗、宠物社区、智能养宠硬件四轮驱动,注册用户8000万、日订单1000万单、宠物主粮大促峰值每秒80万单。
业务链路:注册登录 → 创建宠物档案 → 浏览主粮/零食/玩具 → 下单支付 → 智能分仓发货 → 宠物在线问诊 → 社区晒宠 → AI养宠助手(喂食建议/体检报告解读/医疗问答)贯穿全程。
第一轮·筑基期(核心语言与平台、构建工具、ORM与连接池)
老K(严肃面试官):你好,谢飞机同学。先聊聊技术选型,我们线上服务是Spring Boot 3.x,你来说说JDK 8/11/17的区别,为什么必须上17?
谢飞机:JDK 8是经典老干妈,11是保温杯,17是……折叠屏!17就是“一起发”嘛,寓意好,大家涨薪一起发!至于区别……嗯,8有Lambda和Stream,17有……有更贵的授权费?
老K:(血压升高)……那JVM运行时内存分区你总该知道吧?
谢飞机:堆、栈、还有那个……元宇宙空间!对,元空间就是元宇宙空间,类元数据都放那儿!
老K:……如果线上OOM了你怎么排查?
谢飞机:重启大法!先重启,不行就加内存,256G拉满!再不行就换电脑!我们之前项目都是这么干的,物理重启,专治各种疑难杂症!
老K:(扶额)……那Maven依赖冲突呢?
谢飞机:谁报错就删谁!删了还报错就换版本,换到不报错为止。实在不行把同事的本地仓库也删了,大家同归于尽!
老K:……行吧。那聊聊ORM,我们订单表数据量很大,你用MyBatis还是JPA?
谢飞机:MyBatis!JPA一时爽,排查火葬场。写SQL咱心里有底,MyBatis还能用动态SQL,就是SQL要自己手写,但咱不怕!
老K:嗯,这点你倒是说对了。那连接池呢,为什么用HikariCP而不是C3P0?
谢飞机:名字短!加载快!C3P0一听就像科幻电影里的机器人,HikariCP听着就很快,像博尔特,还是日本名字,看着就卷!
老K:(难得点头)虽然比喻离谱,但结论正确。
第二轮·历劫期(缓存、分布式锁、消息队列、分布式事务)
老K:我们大促时主粮商品会被瞬间秒光,说说缓存穿透、击穿、雪崩怎么处理?
谢飞机:这个我会!口诀:防空、加锁、错峰!穿透就是查了个不存在的key,布隆过滤器挡在前面“防空”;击穿是热点key过期一瞬间,互斥锁“加锁”顶上;雪崩是大面积key同时过期,过期时间加随机值“错峰”!
老K:不错,这次背得挺熟。那库存扣减你怎么保证不超卖?
谢飞机:用Redis!setnx锁,抢到锁就扣库存……嗯,还要记得finally里释放锁,再给锁设个过期时间,防止死锁!
老K:那你锁过期了怎么办?业务还没执行完,锁就被释放了,别的线程进来了怎么办?
谢飞机:啊这……那就再抢一次?不行就……让楼下那条大黄狗看着锁,谁也不能动!
老K:……那是看门狗机制(WatchDog),不是真的狗!还有你setnx只设值不设过期时间,宕机了锁就永远不释放了。
谢飞机:哦哦,对,要SET key value NX EX 30这种原子操作!
老K:那Kafka怎么保证消息不丢失?
谢飞机:大厂产品不会丢的!Kafka是King!王者不丢王冠!
老K:……生产者acks=all、副本min.insync.replicas、消费者手动提交+幂等,三环节一个都不能少。
谢飞机:哦!对对对,我就是这个意思!
老K:下单要扣库存、减优惠券、生成订单,三个服务跨库操作,怎么保证一致性?
谢飞机:撒海盐!Seata!往数据库里撒一把海盐,就一致了!它有四种模式,海盐味、烧烤味、番茄味、原味……
老K:……是AT、TCC、SAGA、XA四种模式!行了,进第三轮吧。
第三轮·飞升期(WebSocket、可观测性、Spring AI全家桶)
老K:我们宠物社区有百万用户同时在线的实时消息,WebSocket怎么撑住百万连接?
谢飞机:for循环挨个发消息啊!连上就存起来,有消息就遍历一遍全发出去!100万连接,就for循环100万次,很快的!
老K:(深吸一口气)……那是O(n)灾难,要用Netty+ChannelGroup管理连接,消息通过Redis Pub/Sub广播。
老K:系统出问题怎么快速定位?
谢飞机:这个我会!Prometheus收集指标、Grafana画大盘、ELK存日志、Jaeger/Zipkin做链路追踪!指标、日志、链路三件套,比福尔摩斯还神!
老K:难得利索一次。最后一个方向,我们要做AI养宠助手,怎么用Spring AI?
谢飞机:ChatClient!跟JdbcTemplate一个味儿,写起来倍儿亲切!
老K:用户问“我家猫一天吃多少粮”,模型不知道你家猫的体重,怎么办?
谢飞机:RAG!先搜后答!把宠物档案、喂养手册、药品说明书都切块向量化存进向量数据库,用户提问先做语义检索,再把检索结果塞给大模型,让它基于资料回答!
老K:不错。向量数据库你选什么?
谢飞机:Milvus!社区大、性能强!小规模就用Chroma,想要简单还能用Redis Stack,一个Redis全搞定!
老K:那AI怎么调用我们现有的库存查询、疫苗预约接口?
谢飞机:MCP!模型上下文协议,AI界的USB-C!把工具标准化注册进去,大模型想调哪个插哪个,即插即用!
老K:那如果用户问的是多轮复杂问题,比如“我家狗吐了,附近哪家医院能看,帮我预约”,普通RAG够吗?
谢飞机:不够!要Agentic RAG!AI侦探模式,先检索宠物症状资料判断紧急程度,再调用地图服务找医院,再调预约接口下单,一步步推理、一步步调工具,跟破案一样!
老K:那AI会不会瞎编答案?比如把狗粮推荐成猫粮?
谢飞机:AI幻觉嘛,只能缓解不能消除!得靠RAG给资料兜底、提示词约束、答案引用溯源、人工审核兜底,多管齐下!
老K:……虽然中间有不少离谱发言,但最后AI这块答得还行。
谢飞机:那我能入职了吗?
老K:回去等通知吧。
谢飞机:好嘞!这是我集齐的第七张“等通知”卡片了,再集两张就能召唤神龙了!🐉
📚 文末答案解析(小白学习版,16大考点)
1. JDK 8/11/17特性对比与选型
| 版本 | 关键特性 | 定位 | |------|---------|------| | JDK 8 | Lambda、Stream、Optional、新日期API | 经典老干妈,LTS | | JDK 11 | 局部变量var、ZGC试验、HttpClient | 保温杯,LTS | | JDK 17 | 密封类、ZGC成熟、Spring Boot 3.x强制要求 | 折叠屏,最新LTS |
选型逻辑:Spring Boot 3.x/Spring Framework 6 基于Jakarta EE 9+,最低要求JDK 17。新项目直接17,老项目至少规划升级到11。
2. JVM内存分区与OOM排查
- 堆:对象实例,新生代(Eden+两个Survivor)+老年代
- 栈:线程私有,存局部变量、方法调用栈,StackOverflowError在这
- 方法区/元空间:类元数据、常量池,OOM时元空间报“Metaspace”
- 程序计数器、本地方法栈:小角色
OOM排查四板斧:
jps找PIDjmap -dump:format=b,file=heap.hprof PID导堆jstack PID看线程栈- MAT分析大对象/泄漏点
3. Maven/Gradle依赖冲突
冲突原因:不同依赖传递引入同一坐标不同版本。解决四板斧:
mvn dependency:tree看依赖树- 找到冲突路径,
exclusion排除 - 统一用BOM(Bill of Materials)管理版本
- 规则:就近原则 + 先声明者优先,必要时显式声明版本
4. MyBatis vs JPA + HikariCP
- MyBatis:手写SQL,灵活可控,适合复杂查询、大数据量、DBA强管控场景(订单/报表)
- JPA/Hibernate:对象映射省代码,适合CRUD密集型,但复杂查询容易N+1、SQL不可控
- 口诀:JPA一时爽,排查火葬场(调侃,实际按场景选)
HikariCP为什么快:
- FastList:替代ArrayList,优化get/remove性能
- ConcurrentBag:无锁化借还连接,比锁队列更高效
- 字节码精简、无反射开销
5. 缓存穿透/击穿/雪崩
| 问题 | 现象 | 解法 | |------|------|------| | 穿透 | 查不存在的key,打爆DB | 布隆过滤器 + 空值缓存 | | 击穿 | 热点key过期瞬间 | 互斥锁 + 逻辑过期 | | 雪崩 | 大量key同时过期 | 过期时间加随机值 + 多级缓存 |
口诀:防空、加锁、错峰
6. Redis分布式锁三大坑
- 没设过期时间→ 宕机锁永不释放 → 必须
SET key value NX EX 30原子操作 - 锁被误删→ 线程A锁过期,线程B拿到锁,A执行完把B的锁删了 →value用UUID标识,删除前Lua脚本校验
- 锁过期业务没执行完→ 用Redisson看门狗(WatchDog),默认每10秒续期到30秒,业务结束自动释放
7. Kafka消息不丢失三环节
- 生产者:
acks=all(所有副本确认)+ 重试机制 - Broker:
min.insync.replicas(最小同步副本数)+ 副本机制 - 消费者:手动提交offset+ 消费成功后提交 +幂等消费(唯一业务ID去重)
8. 分布式事务四方案
| 方案 | 原理 | 适用 | |------|------|------| | XA/2PC | 数据库层两阶段提交 | 强一致、低并发 | | TCC | Try-Confirm-Cancel 业务补偿 | 高并发、业务可拆分 | | 可靠消息 | 本地消息表 + MQ最终一致 | 异步链路、容忍延迟 | | Seata AT | 自动生成回滚SQL | 透明无侵入,最常用 |
9. 注册中心CAP对比
- Eureka:AP,服务注册,Netflix OSS
- Nacos:AP/CP可切换,配置中心+注册中心,中文文档全,国内主流
- Consul:CP,一致性更强,自带KV存储
10. WebSocket百万连接架构
- Netty:NIO高并发网络框架,单机可扛几十万连接
- ChannelGroup:统一管理连接,广播O(1)级别
- 粘性会话:保证同一用户连接同一节点
- Redis Pub/Sub:跨节点广播,一个节点发消息所有节点同步推送
- 心跳机制:定期ping/pong清理死连接
- 千万别:for循环挨个遍历百万连接发消息(O(n)灾难)
11. 可观测性三件套
- 指标:Prometheus采集 + Grafana可视化(QPS、RT、GC、CPU)
- 日志:SLF4J + Logback/Log4j2 + ELK(Elasticsearch+Logstash+Kibana)
- 链路:Micrometer + Jaeger/Zipkin 实现分布式链路追踪,一次请求全链路打点
12. Spring AI核心能力
- ChatClient:统一对话API,跟JdbcTemplate一样简洁
- EmbeddingModel:文本向量化(OpenAI/Ollama本地模型)
- Function Calling:让模型调用Java方法(查库存、预约、下单)
- ChatMemory:聊天会话内存,多轮对话上下文
- Advisors:提示词填充、RAG检索增强、安全校验等横切逻辑
13. RAG离线/在线双阶段
离线阶段:文档加载 → 切分chunk → Embedding向量化 → 存入向量数据库(Milvus/Chroma/Redis Stack)在线阶段:用户提问 → 向量化 → 语义检索TopK → 拼接上下文 → 大模型生成(答案带引用)
价值:解决AI幻觉、知识时效性、企业私有知识库问答
14. 向量数据库选型
| 库 | 特点 | 场景 | |----|------|------| | Milvus | 分布式、十亿级、性能强 | 大规模生产 | | Chroma | 轻量、嵌入式 | 原型/小规模 | | Redis Stack | 复用Redis、简单 | 中小规模、已有Redis |
15. MCP + A2A + Agentic RAG
- MCP(模型上下文协议):AI界的USB-C,统一工具调用标准,客户端-服务器架构,三大原语(工具/资源/提示),解决“每个AI接一套API”的碎片化
- A2A(Agent-to-Agent):智能体之间互相通信协作,Google提出
- Agentic RAG vs 普通RAG:普通RAG“搜一次答一次”;Agentic RAG是ReAct循环(Reason+Act)——先推理需要什么信息,检索,调工具,再推理,再行动,直到完成复杂任务(如“狗吐了→查资料→找医院→预约”多步流程)
16. AI幻觉本质与缓解
本质:大模型本质是概率生成,没有真实世界校验,会“一本正经地胡说八道”。六大缓解手段:
- RAG检索增强,给资料兜底
- 提示词约束(“不知道就说不知道”)
- 答案引用溯源,标注来源
- 温度参数调低,减少发散
- 人工审核兜底(高敏场景)
- 模型微调/持续更新
划重点:AI幻觉只能缓解,不能消除,面试答这句最加分!
彩蛋:据说谢飞机三个月后靠这份答案解析入职了竞品宠物公司,工牌上写着「等通知侠」。🫡