互联网大厂 Java 面试实录:Spring Boot、MyBatis、Redis、Kafka、Spring Security、RAG 与 MCP 全链路问答
场景:某互联网大厂电商与 AI 客服中台团队面试现场。面试官严肃冷静,小Y是来面试的"水货程序员",但偶尔也能答对一些基础题。
第一轮:基础能力与项目落地
面试官: 小Y,先别紧张。我们做的是电商商品详情与订单服务。你先说说,Java 8 和 Java 17 在你这个项目里,你最常用、最有感知的区别是什么?
小Y: Java 8 我用得多,最常见的就是 Lambda、Stream,还有 Optional。Java 17 我知道有更好的性能和一些新特性,比如 record、switch 表达式,还有更现代的语法,写 DTO 比较省事。
面试官: 这题答得不错,说明你不是只会背八股。那你说说,为什么我们电商详情页接口会优先用 Spring Boot,而不是老式的 Struts 或者纯 Servlet?
小Y: Spring Boot 上手快,自动配置多,能少写很多 XML。电商接口迭代快,Boot 能更方便接入 MVC、缓存、日志、监控这些能力。Struts 比较老,维护成本高,不太适合现在高并发、快速迭代的业务。
面试官: 可以,方向对了。那你再说下,商品详情页的价格、库存、优惠券信息很多,你会怎么设计缓存?比如 Redis、Caffeine、Spring Cache 这些怎么配合?
小Y: 我会做多级缓存。像本地热点数据可以放 Caffeine,减少 Redis 压力;公共数据或分布式共享数据放 Redis;Spring Cache 负责统一注解封装。关键是设置合理 TTL,避免缓存穿透、击穿、雪崩,还要保证更新时先删缓存再更新数据库,或者使用延迟双删。
面试官: 这题回答得可以,至少没把缓存说成"加了就快"。那如果商品详情接口要查数据库,你倾向于 MyBatis 还是 JPA?为什么?
小Y: 如果是订单、商品这种 SQL 可控、查询复杂的场景,我更倾向 MyBatis。因为 SQL 可控,容易做性能优化。JPA 更适合简单 CRUD 和领域模型比较清晰的场景,但复杂查询有时候不如 MyBatis 直接。
面试官: 行,基础还算扎实。最后一个问题:Maven 依赖冲突你一般怎么排查?
小Y: 先用 mvn dependency:tree 看依赖树,找冲突版本;再看谁传递引入了不同版本;必要时用 exclusions 排除,或者在 dependencyManagement 里统一版本。大版本升级还会结合测试和启动日志一起看。
面试官: 可以,第一轮没翻车,先到这儿。
第二轮:微服务、消息、网关与安全
面试官: 现在我们把场景升级一下。电商订单创建后,需要同步发优惠、扣库存、发消息通知。你会怎么设计这条链路,避免接口超时?
小Y: 我会把核心下单接口做成"先落库,后异步处理"。订单服务先保证本地事务成功,然后通过 Kafka 发出订单创建事件,库存、积分、短信这些下游服务订阅消息异步处理。这样主链路更短,用户体验更好。
面试官: 说得不错。那如果 Kafka 消息重复消费了,你怎么办?
小Y: 这个要做幂等。比如订单号作为业务唯一键,在消费端先查处理状态,或者用数据库唯一索引防重。也可以在 Redis 记录消费标记,但最终还是要结合业务表和事务控制。
面试官: 嗯,知道"幂等"不是口号。那支付回调这种接口,安全上你怎么处理?JWT、OAuth2、Spring Security 你怎么配合?
小Y: 登录态可以用 Spring Security 做认证授权,OAuth2 适合第三方授权和统一身份体系,JWT 适合无状态会话传递。支付回调这种接口要校验签名、时间戳、防重放,还要限制 IP 白名单。不能只靠前端传 token。
面试官: 这个回答比较靠谱。那网关层呢?你会怎么做限流和熔断?
小Y: 网关层可以做统一鉴权、灰度、限流和路由。限流可以用令牌桶或漏桶思想;熔断用 Resilience4j。像秒杀、抢券场景可以在网关先挡掉一部分流量,避免把后端打挂。
面试官: 再往下问,订单服务和库存服务之间你更喜欢用 HTTP 还是 gRPC?
小Y: 如果是内部高频调用、对性能敏感,我会考虑 gRPC,因为基于 HTTP/2,协议更紧凑,IDL 也清晰;如果是外部开放接口,还是 REST 更常见,兼容性更好。
面试官: 好,第二轮比第一轮更像正经开发了。最后一个问题:Spring Cloud、Consul、Eureka 这些注册发现体系你怎么理解?
小Y: 服务注册发现是让服务不用写死地址。Eureka 是 Netflix 的方案,Consul 也能做注册发现,还能做健康检查和配置中心。现在很多项目也会结合 K8s Service 做服务发现,所以不一定还要依赖传统注册中心。
面试官: 可以,说明你知道"不是所有项目都要把老架构再背一遍"。
第三轮:高并发、可观测性、AI 与复杂业务
面试官: 最后一轮,我们换成一个更复杂的业务。现在公司要做"智能客服 + 企业文档问答 + 工单流转"的系统,既要接 WebSocket 实时对话,也要接入 AI 能力。你先说说,这个系统为什么不能只靠普通搜索?
小Y: 普通搜索主要是关键词匹配,用户问法一变就不准。AI 问答需要理解语义,尤其是企业文档、制度、合同这些内容,最好用 RAG,把文档先切分、向量化,再做语义检索,把相关上下文喂给大模型生成答案,这样命中率更高。
面试官: 这题答得不错。那 RAG 里"幻觉"怎么控制?
小Y: 要尽量让模型"有依据地回答"。比如检索召回要做得准,提示词里要求模型仅根据检索到的内容回答,不足时明确说不知道;还可以加引用来源、答案置信度、敏感问题转人工。对于高风险场景,不能让模型自由发挥。
面试官: 那如果我们要把企业知识库接到多个工具里,比如工单系统、CRM、知识库搜索、审批流,你会怎么设计 MCP 或工具调用?
小Y: 我理解 MCP 是一种标准化的工具接入方式,模型不直接"猜"工具接口,而是通过统一协议调用外部能力。这样可以把不同系统封装成工具,统一做鉴权、参数校验、审计和结果返回。Agent 就像调度员,根据用户意图选择要不要调用工具、调用哪个工具、调用几次。
面试官: 还行,没把 Agent 说成"大号聊天机器人"。那再说说,一个智能客服系统怎么做可观测性?
小Y: 我会分三层看:日志、指标、链路追踪。日志用 Logback 或 Log4j2 输出结构化日志;指标用 Micrometer 接 Prometheus,再给 Grafana 看 QPS、延迟、错误率;链路追踪可以接 Jaeger 或 Zipkin,排查一次用户会话里哪一步慢了。AI 场景还要关注 token 消耗、召回命中率和人工转接率。
面试官: 这个回答挺完整。那最后一个问题,如果客服对话过程需要记住上下文,聊天会话内存你会放哪里?
小Y: 简单点可以先放 Redis,方便多实例共享;如果会话很长,也可以做分层存储,短期上下文放缓存,长期记录落库。还可以按会话 ID 维护消息摘要,避免上下文太长导致成本变高。
面试官: 好,第三轮到这里。整体看下来,你基础题能接,场景题也能说出方向,但复杂链路的细节还不够扎实。你先回去等通知吧,我们后面再综合评估。
题目答案详解:从业务场景理解技术点
下面把前面的每道题拆开讲清楚,方便你按"业务场景 + 技术方案"的方式记忆。
1. Java 8 和 Java 17 的区别
在电商项目里,Java 8 常见用途是 Lambda、Stream、Optional、时间 API 等,帮助提升集合处理和代码可读性。Java 17 则更偏向现代化写法和长期维护,常见优势包括 record、更完善的 switch 表达式、模式匹配相关能力,以及更好的 JVM 性能和安全基线。
业务上,如果你在做商品详情、订单 DTO、活动配置对象,record 能减少大量样板代码;如果是高并发服务,升级新版本 JDK 往往也能得到更稳定的 GC 和更好的运行时表现。
2. 为什么电商接口优先用 Spring Boot
Spring Boot 适合快速开发和微服务化交付。它把依赖整合、自动配置、嵌入式容器、健康检查、配置管理都做得比较完整。电商场景的特点是接口多、迭代快、需求变化频繁,所以开发效率和可维护性非常重要。
相比之下,Struts 属于较老的 Web 框架,配置复杂、生态老旧、扩展不如 Spring 体系灵活。纯 Servlet 虽然底层,但工程化能力弱,适合练手,不适合大中型企业项目。
3. 多级缓存怎么设计
商品详情页会同时读取商品基础信息、价格、库存、活动、推荐等内容,热点很高,适合多级缓存:
- 本地缓存:Caffeine 适合存放短时间内高频访问的数据,命中快,减少远程调用。
- 分布式缓存:Redis 适合多实例共享数据,比如商品基础信息、活动配置、库存快照。
- 统一抽象:Spring Cache 可以用注解统一缓存逻辑,降低业务代码侵入。
核心要点是处理好缓存三大问题:
- 穿透:请求不存在的数据,可以用布隆过滤器、空值缓存等方式拦截。
- 击穿:热点 key 过期瞬间大量请求打到数据库,可以用互斥锁、逻辑过期。
- 雪崩:大量 key 同时失效,要设置随机 TTL 或分批失效。
更新策略上,常见做法是先更新数据库再删缓存,或者延迟双删,避免脏读。
4. MyBatis 和 JPA 怎么选
MyBatis 适合 SQL 可控、查询复杂、性能要求高的业务,比如订单查询、报表统计、库存扣减。它的优点是 SQL 明确,方便针对索引、执行计划做优化。
JPA 更偏向对象关系映射,适合 CRUD 多、模型清晰、业务简单的场景。它能减少模板代码,但复杂查询可控性较弱。
电商订单系统里,MyBatis 往往更常见,因为涉及大量联表、分页、聚合、动态查询,SQL 优化空间更大。
5. Maven 依赖冲突怎么处理
排查依赖冲突常用 mvn dependency:tree,先看传递依赖链路,再确认到底是谁引入了冲突版本。处理方式通常包括:
- 使用
dependencyManagement统一版本。 - 对冲突依赖做
exclusions。 - 必要时升级或替换第三方组件。
- 配合启动日志、测试结果和线上错误栈一起定位。
企业项目里,尤其是 Spring、Netty、Jackson、Guava 这类常见组件,很容易发生版本冲突,所以版本治理是基础能力。
6. 订单创建后如何异步化
典型电商链路是:用户下单 -> 订单服务落库 -> 发出事件 -> 库存、积分、短信、风控等服务异步处理。
这样做的好处是:
- 主链路更短,接口响应更快。
- 下游能力解耦,系统更容易扩展。
- 某个下游出问题,不一定阻塞用户下单。
Kafka 很适合做事件流和异步解耦。订单创建后发消息,由库存服务、营销服务、通知服务分别订阅处理。
7. Kafka 重复消费怎么解决
消息系统里"至少一次投递"很常见,因此重复消费是正常现象,关键是业务幂等。
常见方案:
- 业务唯一键去重,比如订单号、支付流水号。
- 数据库唯一索引,插入重复时直接失败。
- 消费表记录处理状态,先查状态再执行业务。
- Redis 做短期防重,但最终最好还是落到业务数据层保证一致性。
对支付、发券、积分这类敏感业务,幂等设计非常重要。
8. 支付回调如何保证安全
支付回调不是"带个 token 就行",而是必须做多层校验:
- 校验签名,确认消息确实来自支付平台。
- 校验时间戳和随机数,防止重放攻击。
- 校验订单金额、订单状态、商户号等关键字段。
- 做 IP 白名单或网络层限制。
- 回调处理必须幂等,避免重复记账。
Spring Security、JWT、OAuth2 更多用于登录态和授权体系;支付回调这种接口还要结合业务签名体系一起做。
9. 网关如何做限流和熔断
网关是流量入口,适合统一做鉴权、限流、灰度发布、路由和监控。
- 限流:常用令牌桶或漏桶思想,防止突发流量打爆后端。
- 熔断:Resilience4j 可以在下游异常率过高时快速失败,保护系统。
- 降级:必要时返回兜底结果,比如"系统繁忙,请稍后再试"。
秒杀、抢券、节假日活动这类场景尤其需要网关层前置防护。
10. 什么时候用 gRPC
gRPC 适合内部服务高频调用、对性能敏感、接口定义明确的场景。它基于 HTTP/2,使用 Protobuf 作为序列化协议,性能和传输效率都比较好。
适合:订单服务调库存服务、风控服务调策略服务、AI 编排层调内部工具等。
不太适合:对外开放 API,因为 REST 更通用,接入门槛更低。
11. 注册发现怎么理解
Eureka、Consul 这类组件的作用,是让服务实例动态注册和发现,避免写死地址。服务上线、下线、扩容、缩容时,调用方都能找到可用实例。
在 Kubernetes 环境里,很多基础服务发现能力会由 K8s Service 和 DNS 承担,所以传统注册中心不一定是必需品。企业要根据部署环境选择,而不是照搬旧方案。
12. 为什么普通搜索不够,AI 问答要用 RAG
普通搜索偏关键词匹配,适合找文档,不适合回答问题。用户问"员工年假怎么计算"时,可能不会直接命中文档中的原句。
RAG 的流程是:
- 文档加载:从 PDF、Word、网页、知识库等来源读取内容。
- 切分:把长文档切成更适合检索的小块。
- 向量化:用 Embedding 模型把文本转成向量。
- 存储:把向量放到向量数据库,如 Milvus、Chroma 或 Redis。
- 检索:根据用户问题做语义检索,找最相关的内容。
- 生成:把检索结果喂给大模型,让模型基于资料回答。
这样得到的答案更贴合企业知识库,也更容易控制。
13. RAG 如何降低 AI 幻觉
幻觉是大模型"看起来很会说,但内容不一定对"。企业场景里尤其不能接受。
控制方式包括:
- 检索召回要准确,尽量把真正相关的内容找出来。
- 提示词明确要求"仅根据提供资料回答"。
- 让模型输出引用来源,增强可追溯性。
- 找不到答案时明确拒答或转人工。
- 高风险场景加入人工审核和规则兜底。
这类做法非常适合智能客服、合同问答、医疗知识问答、金融合规问答。
14. MCP 和 Agent 怎么理解
MCP 可以理解为一种把模型和外部工具标准化连接的方式,让模型不直接依赖某个具体系统的私有接口,而是通过统一协议去调用工具。
Agent 则更像"智能调度员",它会根据用户意图决定:
- 是否要调用工具。
- 调用哪个工具。
- 调用几次。
- 如何组合多个结果。
比如用户问"帮我查一下订单并发起售后",Agent 可能先查订单系统,再调用售后工单系统,最后把结果整理给用户。
15. 聊天会话内存怎么存
短对话可以直接放在内存里,但企业级系统通常要考虑多实例和重启恢复问题,所以更常见的是:
- 短期上下文放 Redis。
- 长期记录落库。
- 对过长的会话做摘要压缩。
这样既能保留对话连续性,又能控制 token 成本和存储成本。
16. 智能客服系统怎么做可观测性
可观测性至少包括三部分:
- 日志:记录请求、会话 ID、用户 ID、错误信息、模型调用信息。
- 指标:用 Micrometer 接 Prometheus,再用 Grafana 看 QPS、耗时、错误率、转人工率、token 消耗。
- 链路追踪:用 Jaeger 或 Zipkin 跟踪一次用户请求经过了哪些服务。
AI 场景还要关注:
- 检索命中率。
- 答案采纳率。
- 人工转接率。
- 模型响应耗时。
17. 业务场景怎么把这些技术串起来
如果把前面的内容串成一个真实系统,它可能长这样:
用户在电商 App 里下单,同时在客服聊天窗口问"我的订单什么时候发货"。系统前端通过 WebSocket 保持实时会话,后端由 Spring Boot 提供 REST 接口,订单服务用 MyBatis 操作数据库,Redis 缓存商品和会话信息,Kafka 异步通知库存和营销服务,Spring Security + OAuth2 保护登录态,Micrometer + Prometheus + Grafana 做监控,Jaeger 跟踪链路。再往上叠加 AI 层,RAG 负责检索企业知识库,MCP 和 Agent 负责连接工单、CRM、知识库搜索等工具,最终形成一个既能回答问题又能流转工单的智能客服系统。
这就是大厂面试最喜欢问的东西:不是单点知识,而是你能不能把技术点放进业务链路里讲清楚。