大厂Java面试实录:Spring Boot/Cloud + Redis/Kafka + JWT + RAG/Agent(小Y翻车版)
故事背景
你面试的是一家互联网大厂的"电商内容社区 + AIGC 智能客服"团队:
- 前台:内容流(UGC)+ 商品详情 + 下单
- 中台:库存/订单/支付
- 智能化:AIGC 导购与客服(企业知识库问答)
面试官(严肃、逻辑强)VS 程序员小Y(搞笑、基础能答,复杂就开始"艺术化表达")。
第一轮(基础到实战起步):做一个"内容社区 + 商品详情"服务
目标:Spring Boot 单体起步,逐渐引入缓存、数据库与接口规范。
Q1:你用 Spring Boot 做内容流接口,如何设计分页与排序?
面试官: 内容流接口 GET /feeds,支持按时间倒序、按热度排序,你怎么做?
小Y: 这个简单,page、size、sort 三件套嘛。时间倒序就 createTime desc,热度就 likeCount desc。Spring Data JPA 直接 Pageable 搞定。
面试官: 还行。那"翻页重复/漏数据"怎么避免?
小Y: 呃......加个事务?或者让用户少刷新。
面试官: ......(沉默两秒)我们先往下。
Q2:商品详情页 QPS 很高,你怎么用 Redis 做缓存?
面试官: 商品详情 GET /items/{id},热点商品 QPS 很高,你的缓存策略?
小Y: Redis 啊,key=item:{id},先查 Redis,没命中查 DB 再 set。加个过期时间,比如 10 分钟。
面试官: 缓存穿透、击穿、雪崩?
小Y: 穿透就......把不存在的也缓存一下?击穿加锁,雪崩随机过期。
面试官: 方向对。你打算用什么实现?
小Y: Spring Cache 注解 @Cacheable,一键上车。
面试官: 还不错,知道 Spring Cache 的底层抽象么?
小Y: 就是......让你不用写 Redis 代码。
Q3:你选 MyBatis 还是 JPA?怎么做数据库迁移?
面试官: 内容表、商品表、点赞表,你用 JPA 还是 MyBatis?为什么?
小Y: JPA 开发快,MyBatis 可控。我一般看心情......呃看业务复杂度。
面试官: 数据库 schema 变更怎么做?
小Y: Flyway 或 Liquibase。我们用 Flyway,因为名字短。
面试官: ......行,至少知道工具。
Q4:单元测试怎么写?Mock 哪些?
面试官: 你怎么测试"点赞接口"既写库又发消息?
小Y: JUnit 5 + Mockito。Repository mock 掉,消息也 mock 掉。AssertJ 写断言。
面试官: 如果要做端到端?
小Y: Selenium?
面试官: 这是 Web UI 自动化......(叹气)继续。
第二轮(微服务与稳定性):点赞上报、异步化、链路追踪
目标:从单体走向微服务,Kafka 异步、Spring Cloud、可观测性。
Q1:点赞量/评论数如何异步更新?Kafka 还是 RabbitMQ?
面试官: 点赞接口高峰期很爆,你如何把"写库 + 更新计数"拆开?
小Y: 用 Kafka。点赞服务写一条消息到 topic,计数服务消费更新 Redis 或 ES。
面试官: 为什么 Kafka?
小Y: 因为它快,而且大厂都用。
面试官: ......那幂等怎么保证?
小Y: 消费端加个 try-catch,失败重试。
Q2:服务发现与配置管理:Eureka/Consul 怎么选?
面试官: 你们上 Spring Cloud,注册中心用什么?
小Y: Eureka 经典,Consul 也行。我们用......看公司祖传。
面试官: 配置中心、灰度发布怎么做?
小Y: Git 里改配置,发版就灰度了。
Q3:熔断限流怎么做?Resilience4j 你会怎么用?
面试官: 内容流依赖"用户画像服务",它慢了会拖垮你,怎么办?
小Y: 加超时、熔断。Resilience4j 注解加上,失败就走 fallback。
面试官: fallback 返回什么?
小Y: 返回默认画像,比如"该用户爱看猫"。
面试官: (忍笑)行,思路对。
Q4:链路追踪怎么打通?Micrometer + Prometheus + Jaeger?
面试官: 我想看一次请求从网关到内容服务再到画像服务的耗时,你怎么做?
小Y: Micrometer 把指标打到 Prometheus,Grafana 画图。链路追踪用 Jaeger 或 Zipkin。
面试官: traceId 怎么传?
小Y: 放 header 里,大家自觉传。
第三轮(安全 + AI 落地):AIGC 客服的 RAG/Agent 与风控
目标:从"业务可用"走向"安全可控 + AI 工程化"。
Q1:登录鉴权:Spring Security + JWT + OAuth2 怎么选?
面试官: App + Web + 小程序三端,怎么做统一鉴权?
小Y: JWT 就行,发个 token。Spring Security 配一下过滤器。
面试官: OAuth2 / Keycloak 呢?
小Y: 也能用,但我觉得 JWT 更"轻"。
面试官: token 失效、踢人、刷新怎么做?
小Y: 设置短过期,然后......让用户重新登录。
Q2:支付与风控:接口防重、幂等、分布式事务怎么做?
面试官: 下单支付回调可能重复通知,你怎么保证不重复记账?
小Y: 用唯一订单号,数据库加唯一索引。收到回调先查状态。
面试官: 库存扣减、订单创建、支付确认跨服务一致性?
小Y: 这个用分布式事务......或者最终一致性。具体怎么搞看框架。
Q3:企业知识库问答:RAG 的最小闭环怎么搭?
面试官: 我们要做"商家政策/售后规则/活动玩法"的客服问答,如何用 RAG?
小Y: 把文档丢到向量数据库,然后问问题就相似度搜索,找几段给大模型生成答案。
面试官: 文档怎么加载、怎么切分、embedding 用什么?
小Y: Spring AI 有现成的。切分就......按段落切。embedding 用 OpenAI 或 Ollama。
面试官: 幻觉怎么控制?
小Y: 让模型"不要幻觉"。
Q4:Agent 工具调用:MCP/工具执行框架你怎么设计?
面试官: 客服 Agent 需要"查订单、查物流、发优惠券",如何做工具调用标准化?
小Y: 设计几个 HTTP 接口给它调。MCP 就是......让它更会调工具。
面试官: 权限隔离、审计、超时、重试?
小Y: 日志打一下,超时设置 3 秒,重试 3 次,应该就行。
结束语
面试官: 今天先到这。你回去等通知吧,如果有后续我们会联系你。
小Y: 好的好的,我手机一直开着,外加心也一直开着。
文末答案详解(把小Y含糊的地方补齐)
按业务链路:内容流 → 商品详情 → 点赞异步 → 微服务稳定性 → 安全与支付 → RAG/Agent 客服。
1)内容流分页:为什么会"重复/漏数据"?怎么修
问题本质 :传统 offset/limit 在数据持续新增/删除时会导致翻页不稳定。
推荐方案:
- 游标分页(cursor pagination / seek method) :
- 以
(createTime, id)作为游标 - 下一页条件:
(createTime < lastTime) OR (createTime = lastTime AND id < lastId) - 排序:
ORDER BY createTime DESC, id DESC
- 以
- 热度排序通常需要"时间窗 + 预聚合"(否则全表排序昂贵):
- 点赞/评论通过 Kafka 异步累计到 Redis
- 定时任务把 Redis 的聚合落 ES 或 DB
- 内容流按热度从 ES/Redis TopN 取,再回源补全
技术点:Spring MVC 参数设计(cursor、limit)、MyBatis/JPA 自定义查询、避免深分页。
2)商品详情 Redis 缓存:穿透/击穿/雪崩落地
- 缓存穿透 (大量请求不存在的商品 id):
- 缓存空值(短 TTL)+ 参数校验
- 或 Bloom Filter(RedisBloom/Guava BloomFilter)
- 缓存击穿 (单个热点 key 过期瞬间大量并发打 DB):
- 互斥锁:
SETNX lock:item:{id}+ 过期时间 - 或逻辑过期:value 带
expireAt,过期后异步刷新,读请求先返回旧值
- 互斥锁:
- 缓存雪崩 (大量 key 同时过期):
- TTL 随机抖动:
baseTTL + random(0,n) - 分批预热 + 限流 + 熔断
- TTL 随机抖动:
实现建议:
- Spring Cache(抽象)+ RedisCacheManager(实现)
- 热点场景建议显式写缓存逻辑,方便加锁/逻辑过期/降级
3)JPA vs MyBatis 怎么选 + Flyway/Liquibase 的正确用法
- JPA :
- 优点:开发快、实体映射省心、CRUD 强
- 缺点:复杂 SQL、性能可控性、N+1 问题需经验
- MyBatis :
- 优点:SQL 可控、复杂查询更直观
- 缺点:样板代码更多
推荐落地:
- 简单 CRUD 用 JPA;复杂报表/多表 join 用 MyBatis
Flyway:
- 版本化脚本:
V1__init.sql、V2__add_index.sql - 保证生产环境 schema 可追溯、可回滚(结合规范与审核)
4)测试:单元/集成/端到端怎么分层
- 单元测试 :JUnit5 + Mockito + AssertJ
- mock:外部依赖(DB、MQ、HTTP Client)
- 不 mock:业务逻辑
- 集成测试 :
- Testcontainers 起 MySQL/Redis/Kafka
- Spring Boot
@SpringBootTest
- 契约测试/接口测试 :
- REST Assured / Postman/Newman
- 端到端 UI:Selenium(适合 Web 前端 UI 测试,不是后端主力)
5)Kafka 异步点赞:幂等与一致性
典型链路:
- 点赞服务写 DB(like 表)
- 写 Kafka 事件(
LikeCreated) - 计数服务消费,更新 Redis 计数
幂等手段:
- 事件带唯一 id(
eventId/likeId) - 消费端用 Redis/DB 记录已处理 eventId(去重表/幂等表)
- Kafka 消费位点提交与业务处理要配合(至少一次语义下必须做幂等)
进阶:
- Outbox Pattern:业务表与 outbox 表同库同事务写入,再由 CDC/任务发送 Kafka,避免"写库成功但发消息失败"。
6)服务发现/配置/灰度:别靠"祖传"和"Git改完就灰度"
- 服务发现:
- Spring Cloud 生态里常见:Eureka(历史)、Consul(更通用)
- K8s 场景很多直接用 Kubernetes Service + DNS
- 配置管理:
- Spring Cloud Config / Nacos(若允许)/ Consul KV
- 配合动态刷新(
/actuator/refresh或自动刷新机制)
- 灰度:
- 网关层按用户维度路由(Header/Cookie/UserId)
- K8s canary(按比例/按流量镜像)
7)Resilience4j:超时、熔断、限流、舱壁的组合拳
- Timeout:避免线程被慢调用拖死
- CircuitBreaker:错误率/慢调用比例触发熔断
- RateLimiter:保护自身
- Bulkhead:隔离线程池/信号量,避免级联
fallback 设计:
- 返回可接受的"降级数据"(默认画像/空推荐)
- 打点告警,避免静默失败
8)可观测性:指标、日志、追踪三件套
- 指标 :Micrometer → Prometheus → Grafana
- QPS、P99、线程池队列长度、GC、连接池活跃数
- 日志 :SLF4J + Logback/Log4j2,统一 traceId
- ELK(Elasticsearch + Logstash/FluentBit + Kibana)
- 链路追踪 :OpenTelemetry / Brave → Jaeger/Zipkin
- traceId/spanId 自动注入与透传(不要"大家自觉传")
9)鉴权:JWT 只是起点,OAuth2/Keycloak 解决"统一身份"
- JWT :适合无状态鉴权,但
- 踢人/撤销困难(需黑名单或短 token + refresh token)
- 权限变更实时性差
- 推荐 :
- OAuth2 + OIDC(统一登录)
- Keycloak 作为 IdP(用户、角色、客户端、token 签发)
- 资源服务用 Spring Security Resource Server 校验 JWT
token 刷新与踢人:
- access token 短(5-15 分钟)
- refresh token 长 + 可撤销(服务端存储/会话)
- 黑名单/版本号(
tokenVersion)控制强制下线
10)支付回调幂等 + 跨服务一致性
- 防重/幂等 :
- DB 唯一键(
payCallbackId/tradeNo) - 状态机:订单状态只允许从 A → B,非法跳转拒绝
- DB 唯一键(
- 一致性 :
- 优先最终一致性:事件驱动(Kafka)+ 补偿
- TCC/Saga 思路:库存预占→支付成功确认→失败释放
- 关键:每步可重试、可补偿、可观测
11)RAG 最小闭环(Spring AI 视角)
目标:让模型"只基于检索到的企业文档回答",降低幻觉。
流水线:
- 文档加载(PDF/HTML/Markdown/数据库)
- 清洗与切分(chunking:按语义/标题/长度;保留元数据:来源、更新时间、适用范围)
- 向量化(Embedding:OpenAI/Ollama 等)
- 写入向量库(Milvus/Chroma/Redis Vector)
- 查询:用户问题 → 向量检索 TopK → rerank(可选)
- 提示填充(Prompt Template):把检索片段、引用来源塞进 prompt
- 生成与后处理:引用标注、敏感信息过滤、置信度/拒答策略
控制幻觉:
- 强约束 prompt:仅使用给定 context,不足则明确说不知道
- 输出必须带引用(source id)
- 低相似度阈值直接拒答
- 关键问题走人工或工具校验(订单/退款必须查实时系统)
12)Agent + 工具调用(MCP/标准化)的工程化要点
核心:把"模型调用外部系统"的能力做成可治理的工具层。
- 工具标准化:
- 工具描述(name/description/input schema/output schema)
- 统一协议(可借鉴 MCP 思路:客户端-服务器架构、可扩展工具清单)
- 权限与隔离:
- 工具调用绑定用户身份(userId、scope)
- 细粒度授权:只能查"本人订单"
- 可靠性:
- 超时、重试、熔断(Resilience4j)
- 幂等(发券/改地址要 idempotency key)
- 审计与合规:
- 工具调用日志(入参脱敏、结果摘要、traceId)
- 风控规则:频率限制、黑名单、敏感操作二次确认
典型"Agentic RAG":
- 先 RAG 找到政策
- 再调用工具查订单状态
- 最后生成带引用、带实时数据的答复
到这里,小白可以按"内容流分页→缓存→消息→微服务稳定性→安全→RAG/Agent"完整走一遍大厂后端常见链路,把每个点都能落到工程实现。