大厂Java面试实战:Spring Boot + Redis + Kafka + Spring Cloud + RAG(Spring AI/MCP)三轮连问(含标准答案)

故事背景

一家互联网大厂的「内容社区 + UGC + AIGC 助手」业务线招 Java 后端。你(面试官)严肃认真,候选人是搞笑的水货程序员小Y:简单题能答,复杂题就开始“哲学化”。

业务设定:

  • 社区用户发帖/评论/点赞/关注
  • 热榜与推荐(含缓存、异步、搜索)
  • AIGC:给帖子生成摘要/标题/合规改写,企业知识库问答(RAG)
  • 微服务:内容服务、互动服务、搜索服务、风控服务、AIGC 服务

下面开始三轮提问,每轮 3~5 题,循序渐进。


第一轮:从「发帖链路」入手(基础到中级)

Q1(Spring Boot + MVC):发帖接口怎么设计?如何做参数校验与统一返回?

面试官:你来设计一个发帖 API,要求支持标题、正文、图片列表、话题 tags。Spring Boot 怎么做参数校验?

小Y:这题简单!@RestController 然后 @PostMapping("/posts"),DTO 上用 @NotBlank 啥的。返回就 Result.success(),异常就……额,try-catch 一把梭。

面试官:参数校验和分层思路是对的,异常处理别 try-catch 到处飞,继续。


Q2(JPA/MyBatis + 事务):发帖要落库两张表(post、post_tag),如何保证一致性?

面试官:发帖写两张表,怎么做事务?JPA 和 MyBatis 你分别怎么处理?

小Y@Transactional 啊!JPA 就 save(),MyBatis 就 mapper insert()。一致性就一致了。

面试官:对,事务边界要清楚。那如果后面还要发消息呢?


Q3(Redis + 热榜):发帖后要让帖子进入热榜,热榜怎么设计?缓存怎么更新?

面试官:热榜是按“热度分”排序(点赞、评论、时间衰减)。你会怎么用 Redis 做?怎么更新?

小Y:用 ZSETZADD,点赞就 ZINCRBY。更新的话……就更新呗。

面试官:ZSET 是正解。注意一致性和回源策略,下一题。


Q4(日志 + 链路追踪):线上排查发帖慢,你怎么定位?

面试官:发帖接口偶尔 2s,你怎么查?用哪些工具?

小Y:看日志!Logback、SLF4J 打印一下时间。再不行就……重启试试。

面试官:前半句可用,后半句非常“社区风格”。我们需要指标、Trace、慢 SQL。进入第二轮。


第二轮:微服务化后的「异步与稳定性」(中级到高级)

Q1(Kafka/RabbitMQ):发帖成功后要异步做:审核、索引、AIGC 摘要。消息队列怎么选?怎么保证不丢消息?

面试官:你选 Kafka 还是 RabbitMQ?为什么?如何保证消息可靠?

小Y:都行吧!Kafka 听起来大厂,用 Kafka。保证不丢……多发几遍?

面试官:选择理由要结合吞吐、顺序、延迟、消费模型。可靠性要讲到确认、重试、幂等。


Q2(分布式一致性/Outbox):数据库写成功但消息没发出去,怎么办?

面试官:经典问题:事务提交了,但消息发送失败。你怎么解决?

小Y:那就……再发一次?或者写个定时任务扫一下?

面试官:方向接近 outbox/本地消息表,但需要完整方案。继续。


Q3(Spring Cloud/OpenFeign + Resilience4j):AIGC 服务偶发超时,怎么做熔断、限流、隔离?

面试官:内容服务调用 AIGC 服务(OpenFeign),偶发超时。怎么保护主链路?

小Y:加个超时时间,然后 catch 异常返回“稍后再试”。熔断……我知道 Hystrix,但它不是凉了吗?

面试官:知道 Hystrix 退役不错,用 Resilience4j。要讲 Bulkhead、CircuitBreaker、Retry、TimeLimiter。


Q4(监控):你会监控哪些指标?怎么用 Prometheus+Grafana 做看板?

面试官:你会重点监控哪些?怎么落地?

小Y:CPU、内存、QPS。Grafana 上拖一拖就行。

面试官:还要业务指标(发帖成功率、队列堆积、审核延迟)、以及 p95/p99、错误码分布、依赖耗时。


第三轮:AIGC + 企业知识库 RAG(高阶)

Q1(Spring AI + RAG):给帖子生成摘要,如何减少 AI 幻觉?

面试官:AIGC 摘要不能胡编,如何减少 hallucination?

小Y:提示词写严谨点,告诉它不要乱说。

面试官:提示工程是其一,更关键是让模型“有依据”:RAG、引用、约束输出格式。


Q2(向量化 + 向量库 Milvus/Redis):企业文档问答怎么做检索?向量维度、相似度、分片你了解吗?

面试官:RAG 的检索层怎么设计?用 Milvus/Chroma/Redis Vector 都行。说说 embedding、topK、chunk。

小Y:向量就是一串数字……topK 就取前 K 个。分片的话……按心情分?

面试官:知道基础概念,但工程细节需要补。还有 chunk 策略、元数据过滤、召回与重排。


Q3(MCP/Agent + 工具调用):让 AI 自动查“用户发帖违规原因”,需要调用风控与内容服务接口,你怎么设计工具执行框架?

面试官:如果做 Agent,让它自动调用内部工具(风控、帖子详情、用户画像),怎么做“可控”的工具调用?

小Y:给它接口文档,让它自己调?

面试官:这会失控。需要工具注册、参数 schema、鉴权、审计、沙箱、超时、幂等、回放。


Q4(安全):AIGC/知识库接口如何鉴权与防刷?JWT/OAuth2/Keycloak 你怎么选?

面试官:对内/对外两套调用,怎么做鉴权和限流?

小Y:JWT 就行,一个 token 走天下。限流就 nginx。

面试官:JWT 适合无状态,但企业场景往往要 OAuth2/OIDC(Keycloak)做统一身份。限流要到网关+服务端双层。


面试收尾

面试官:整体看基础还可以,能说出 MVC、事务、Redis ZSET 这些关键点;但在消息一致性、微服务稳定性、RAG 工程化与 Agent 工具治理上偏虚。你回去把这些点系统补一补,我们这边有结果会通知你。


标准答案与落地方案(小白可学版)

下面把每一轮问题的“面试官期望答案”按业务链路讲清楚,并给出可落地做法。

第一轮答案:发帖链路(Spring Boot / ORM / Redis / 日志)

1)发帖 API 设计与参数校验(Spring MVC / Validation)

业务目标:确保请求合法、响应统一、错误可定位。

推荐做法

  • Controller 只做参数接收与校验,业务放 Service
  • DTO 使用 jakarta.validation(或 javax.validation)注解
  • @RestControllerAdvice 做全局异常处理

示例

@PostMapping("/posts")
public ApiResponse<Long> create(@Valid @RequestBody CreatePostRequest req) {
    return ApiResponse.ok(postService.create(req));
}

public record CreatePostRequest(
  @NotBlank String title,
  @NotBlank String content,
  @Size(max=9) List<@NotBlank String> imageUrls,
  @Size(max=10) List<@NotBlank String> tags
) {}

@RestControllerAdvice
class GlobalExceptionHandler {
  @ExceptionHandler(MethodArgumentNotValidException.class)
  public ApiResponse<?> handleValid(MethodArgumentNotValidException e){
    return ApiResponse.fail("PARAM_INVALID", e.getBindingResult().toString());
  }
}

2)两表落库一致性(JPA/MyBatis + @Transactional

业务目标:post 与 post_tag 要么都成功,要么都失败。

关键点

  • 事务边界在 Service 层
  • 同一个数据源、同一个事务管理器
  • 注意不要在同类内部调用导致事务失效(Spring AOP)

MyBatis 示例

@Transactional
public Long create(CreatePostRequest req){
  postMapper.insert(post);
  tagMapper.batchInsert(post.getId(), req.tags());
  return post.getId();
}

3)Redis 热榜(ZSET)设计:写入、更新与回源

业务目标:快速获取 topN 热帖,点赞/评论实时涨分。

方案

  • Key:hot:posts:{day}hot:posts:{hour} 做时间窗口
  • 数据结构:ZSET,member=postId,score=热度分
  • 点赞/评论:ZINCRBY
  • 读取:ZREVRANGE key 0 99 WITHSCORES

一致性

  • 热榜是“派生数据”,允许短暂不一致
  • DB 为事实源(source of truth),Redis 为加速层
  • 缓存失效策略:定期重算 + 增量更新

热度分示例:

  • score = like3 + comment5 + log(view+1) - timeDecay

4)发帖慢如何定位(Micrometer + Prometheus + Tracing + 日志)

业务目标:快速判断是应用、DB、下游还是网络问题。

落地工具链

  • 日志:SLF4J + Logback/Log4j2,打印 requestId/userId/耗时
  • 指标:Micrometer 暴露到 Prometheus
  • Trace:OpenTelemetry + Jaeger/Zipkin(或 Spring Cloud Sleuth 旧体系)
  • 慢 SQL:MySQL 慢日志、ORM SQL 日志(注意采样)

关键指标

  • http.server.requests 的 p95/p99
  • DB 连接池(HikariCP)active/idle/queue
  • 下游依赖耗时(feign client metrics)

第二轮答案:异步、可靠性与稳定性(MQ / Outbox / Resilience4j / 监控)

1)Kafka vs RabbitMQ 如何选 & 如何保证不丢

内容社区场景常见选择

  • Kafka:高吞吐、分区并行、适合日志/事件流/异步流水(审核、索引、画像)
  • RabbitMQ:低延迟、路由灵活、适合业务指令/工作队列

可靠性要点(以 Kafka 为例)

  • Producer:acks=all、开启幂等(enable.idempotence=true)、合理重试
  • Consumer:处理成功后再提交 offset(手动提交/至少一次)
  • 消费幂等:以 eventId 或 (postId, type) 做去重表/Redis set
  • DLQ:失败进入死信队列或错误主题

2)数据库与消息一致性:Outbox(本地消息表)

问题:DB 提交成功,但 MQ 发送失败。

推荐方案:Transactional Outbox

  • 在同一事务内:写业务表 + 写 outbox 表(待发送事件)
  • 事务提交后:异步任务/CDC(Debezium)把 outbox 事件投递到 Kafka
  • 投递成功:标记 outbox 状态或删除

优点

  • 不依赖分布式事务
  • 消息可追溯、可重放

表结构建议:

  • id, event_type, payload(json), status, retry_count, next_retry_time, created_at

3)AIGC 服务超时:Resilience4j 组合拳

目标:AIGC 挂了也不拖垮主链路(发帖/浏览)。

实践

  • 超时:TimeLimiter(或 HTTP client 超时)
  • 重试:Retry(只对幂等调用;生成类一般不建议重试过多)
  • 熔断:CircuitBreaker(错误率/慢调用阈值)
  • 隔离:Bulkhead(线程池/信号量隔离)
  • 降级:返回“无摘要/稍后生成”,并投递异步任务

链路建议:

  • 发帖主链路只写库 + 发事件
  • 摘要生成走异步消费者更新 post_summary

4)Prometheus+Grafana 监控什么(技术 + 业务)

技术指标

  • JVM:GC 次数/停顿、堆内存、线程数
  • HTTP:QPS、p95/p99、4xx/5xx
  • DB:连接池等待、慢查询
  • MQ:topic lag、消费失败率

业务指标

  • 发帖成功率、审核积压时长
  • 热榜计算延迟
  • AIGC 摘要生成成功率/平均耗时/失败原因分布

报警

  • 错误率突增、p99 飙升、lag 持续上升、熔断打开次数异常

第三轮答案:RAG / 向量检索 / MCP Agent / 安全治理

1)摘要如何减少幻觉(RAG + 约束输出 + 引用)

核心思路

  • 让模型只基于“帖子内容”生成,不允许引入外部事实
  • 若信息不足,输出“无法确定”而不是编造

手段

  • Prompt:明确“仅根据给定上下文”
  • 结构化输出:JSON schema(标题、要点、风险提示)
  • 引用:要求输出引用的句子片段位置(可选)
  • 审核:敏感词/合规模型二次校验

在 Spring AI 中可用:

  • Document 作为上下文
  • 输出解析器(JSON)

2)RAG 检索层:chunk、embedding、向量库与召回

标准流程

  1. 文档加载(PDF/HTML/DB)
  2. 清洗与切分(chunk)
  3. 向量化(embedding model)
  4. 写入向量库(Milvus/Chroma/Redis Vector)
  5. Query embedding + 相似度检索 topK 6.(可选)重排 rerank + 元数据过滤
  6. 拼装上下文给 LLM 生成

工程要点

  • chunk 策略:按段落/标题切,控制 token(如 300~800 tokens),重叠 overlap 50~100
  • 相似度:cosine / inner product(与向量归一化相关)
  • 元数据过滤:部门/权限/时间范围(解决“搜到不该看的文档”)
  • 召回质量:topK 不要盲目大;必要时 BM25 + 向量混合检索

3)MCP/Agent 工具调用如何“可控”

目标:让模型能调用工具,但不能乱调、不能越权、不能不可追踪。

设计清单

  • 工具注册:tool name、描述、参数 schema(JSON Schema)
  • 鉴权:服务到服务(mTLS/OAuth2 client credentials)
  • 审计:记录每次工具调用的输入、输出、耗时、调用人
  • 安全策略:只允许白名单工具;敏感参数脱敏
  • 失败策略:超时、重试、幂等键、回滚/补偿
  • 会话内存:只存必要摘要,避免泄露隐私

典型落地

  • 采用 MCP 协议标准化工具调用
  • Agent 侧做“计划-执行-验证”,每步都可观测

4)AIGC/知识库接口鉴权与防刷(Spring Security / OAuth2 / Keycloak)

对外(多租户/开放平台)

  • OAuth2/OIDC + Keycloak(统一登录、权限、token 生命周期)
  • API Gateway 校验 JWT/opaque token

对内(微服务互调)

  • mTLS + OAuth2 client credentials 或 SPIFFE/SPIRE

防刷与滥用

  • 网关限流(令牌桶/漏桶),按用户/租户/IP
  • 服务端二次限流(Resilience4j RateLimiter)
  • 配额:每天多少次生成/多少 token
  • 风控:异常行为检测(设备指纹、频次、内容相似度)

小结(学习路径建议)

  • 先掌握:Spring MVC + 事务 + Redis ZSET
  • 再掌握:Kafka/RabbitMQ 可靠性 + Outbox
  • 最后补齐:Resilience4j 稳定性、Prometheus 可观测性、RAG/向量检索、MCP/Agent 工具治理

(全文完)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐