大厂 Java 面试实录:Spring Boot、JVM、MySQL、Redis、Kafka、Spring Cloud 场景化连环拷问
大厂 Java 面试实录:Spring Boot、JVM、MySQL、Redis、Kafka、Spring Cloud 场景化连环拷问
一、故事背景
谢飞机,江湖人称“飞机哥”,简历上写着:
- 精通 Java SE 8/11/17
- 熟悉 JVM 调优
- 深入理解 Spring Boot、Spring Cloud 微服务
- 擅长 Redis、Kafka、MyBatis、Hibernate、Docker、Kubernetes
- 有音视频、电商、AIGC、支付风控等多行业经验
面试官看完简历,推了推眼镜:“很好,今天我们就结合真实互联网业务场景聊聊。你不用紧张,我们分三轮,每轮几个问题,循序渐进。”
谢飞机点头如捣蒜:“好的面试官,我这个人最大的优点就是稳定输出,除了不会的,基本都能说两句。”
面试官:“开始吧。”
二、第一轮面试:内容社区与 UGC 场景
场景设定
公司在做一个大型内容社区,用户可以发图文、短视频、评论、点赞、关注作者。系统早期是单体架构,后面逐步向微服务演进。
问题 1:如果让你用 Spring Boot 设计一个内容发布系统,文章发布的核心链路你会怎么设计?
谢飞机: “这个我会。大概就是前端发请求到 Spring MVC 的 Controller,然后 Service 里做参数校验,接着 MyBatis 或者 JPA 落库。发布成功之后,可以异步发消息到 Kafka 或 RabbitMQ,用于做内容审核、消息通知、积分发放这些操作。
如果是高并发一点,我还会把热点数据放 Redis 缓存,比如文章详情、点赞数、评论数这些。”
面试官: “回答得不错,主流程是对的,也知道同步链路和异步链路拆分。那我再往下追问。”
问题 2:文章发布后,点赞数和评论数你会直接查数据库,还是用缓存?如何保证缓存与数据库的一致性?
谢飞机: “这个一般会用 Redis。因为点赞和评论数查得太频繁了,直接查 MySQL 顶不住。
一致性的话……呃……通常就是更新数据库之后删缓存,或者先删缓存再更新数据库。只要删了缓存,问题应该就不大。”
面试官: “方向是对的,但‘只要删缓存问题就不大’这个说法不够严谨。并发场景下一致性有很多细节。先记着,我们最后统一讲。”
谢飞机尴尬一笑:“我主要是战略上理解了。”
问题 3:如果短视频 feed 流首页需要高性能分页,你会怎么设计数据库和查询方案?
谢飞机: “这个……我知道不能直接 limit offset 翻太深,不然会慢。可以基于时间戳或者自增 ID 做游标分页。
数据库上建索引,比如作者 ID、发布时间、状态这些。然后热点内容还可以提前算好,放 Redis 里。”
面试官: “不错,这题答得可以。至少知道深分页问题和游标分页方案,说明做过一些高并发列表设计。”
谢飞机立刻挺直腰板:“我这个人属于遇强则强,简单问题尤其稳定。”
问题 4:内容社区里评论树非常深,如何设计评论系统?
谢飞机: “评论系统嘛,一般有主评论和子评论。可以有 parent_id。至于特别深的树……我觉得可以递归查。
如果层级太深,可能……嗯……也可以做扁平化?”
面试官: “你提到了 parent_id,这是基础。但如果评论量极大、楼中楼复杂,光靠递归查会比较危险,尤其在性能和排序上。后面答案里我会展开。”
三、第二轮面试:电商交易与支付风控场景
场景设定
公司现在拓展到电商业务,有商品、购物车、下单、库存扣减、支付回调、优惠券、风控校验等模块。技术栈采用 Spring Boot + Spring Cloud + MyBatis + Redis + Kafka。
问题 1:秒杀场景下如何防止库存超卖?
谢飞机: “这个我熟。可以把库存放 Redis,先在 Redis 里扣减,然后异步写数据库。也可以在数据库里用乐观锁,比如 version 字段。
再加上接口限流,像 Resilience4j 这种。还有消息队列削峰,用户先抢资格,再慢慢下单。”
面试官: “不错,思路比较完整,提到了缓存预扣、乐观锁、削峰限流。”
问题 2:支付回调为什么一定要做幂等?怎么做?
谢飞机: “因为第三方支付平台可能多次通知。如果不做幂等,订单可能被重复更新,积分也可能重复发。
做法一般是用订单号做唯一约束,或者加一个支付流水表。处理前先查状态,如果已经成功就直接返回成功。还可以借助 Redis 分布式锁。”
面试官: “很好,这题答得挺扎实。”
谢飞机谦虚地摆摆手:“一般一般,全国支付第三。”
问题 3:如果订单服务、库存服务、优惠券服务分成了多个微服务,如何保证分布式事务?
谢飞机: “这个……分布式事务比较复杂。可以用 2PC、3PC、TCC、Saga。
但是互联网项目里一般不建议强一致嘛,所以我觉得可以最终一致性。比如先发消息,再补偿。至于具体怎么落地……一般公司都有自己的中间件。”
面试官: “你至少知道几个方向,但回答还是偏概念化。真正面试里要结合业务链路讲清楚,不然很难拿高分。”
谢飞机:“我这个人属于理论比较云,落地比较飘。”
问题 4:订单系统中 MySQL、Redis、Kafka 分别承担什么角色?为什么不能只靠数据库?
谢飞机: “MySQL 用来存核心数据,比如订单、商品、库存、支付记录。
Redis 用来做缓存、分布式锁、热点数据存储,还可以做限流计数。
Kafka 用来做异步解耦,比如下单后发消息给积分、推荐、发票、履约系统。
如果只靠数据库,数据库压力会很大,而且业务耦合重,峰值也扛不住。”
面试官: “很好,说明你理解了不同组件的职责边界。”
四、第三轮面试:AIGC 平台与风控安全场景
场景设定
公司新业务是 AIGC 内容生成平台,用户上传素材,系统调用大模型服务生成文案、海报或数字人脚本。业务涉及用户鉴权、配额扣减、异步任务编排、审核、日志追踪和风控。
问题 1:如果让你设计一个 AIGC 异步生成任务系统,你会怎么做?
谢飞机: “前端发起生成请求后,后端可以先落库一个任务表,状态是 INIT。然后把任务投到 Kafka 或 RabbitMQ。
消费者拿到任务之后调用模型服务,可以用 OpenFeign 或 gRPC。调用完把结果存到数据库或者对象存储里,再更新任务状态。用户端可以轮询,也可以 WebSocket 推送进度。”
面试官: “不错,这个回答比较完整,链路意识有了。”
问题 2:如果大模型接口很慢、还经常失败,你如何做服务治理?
谢飞机: “这个可以用 Resilience4j 做超时、重试、熔断、限流。服务发现的话可以用 Consul 或 Eureka。调用链监控可以接 Micrometer、Prometheus、Grafana,分布式追踪用 Jaeger 或 Zipkin。
如果是 HTTP 调用可以用 OpenFeign,序列化可以用 Jackson。要是追求性能也能用 Protobuf + gRPC。”
面试官: “回答不错,能把服务治理、可观测性、调用技术栈串起来。”
谢飞机小声说:“终于到我会背的部分了。”
问题 3:AIGC 平台如何做用户认证与接口安全?
谢飞机: “这个一般用 Spring Security,然后登录后发 JWT。
如果企业级一点,可以接 OAuth2 或 Keycloak。接口层做鉴权,重要接口再做签名校验。密码相关可以用加密算法,比如 Bouncy Castle 这类库。
还有风控,比如同一个用户短时间大量生成内容,要限流。”
面试官: “很好,基础安全体系是对的。”
问题 4:如果线上某个生成任务长时间卡住,你会怎么排查?
谢飞机: “先看日志,用 SLF4J + Logback 或 Log4j2。再看监控,比如 Prometheus、Grafana。然后看消息有没有堆积,Kafka 消费是否正常。
如果调用链复杂,就看 Jaeger 或 Zipkin。再看看数据库任务状态是不是没更新、Redis 锁是不是没释放、线程池是不是满了、JVM 有没有 Full GC。”
面试官: “可以,这题答得不错,说明你有一定线上排障意识。”
五、面试结束
面试官合上电脑,语气平静:
“今天先到这里。你有些基础问题答得不错,比如内容发布链路、缓存、秒杀、支付幂等、AIGC 异步任务、服务治理和安全。但复杂问题上,比如缓存一致性、评论系统设计、分布式事务落地,回答还不够深入。
你先回去等通知,有结果我们会尽快同步。”
谢飞机站起来,郑重地点头:
“好的面试官。无论结果如何,今天我都学到了很多。主要是发现我原来会的部分,确实没有我想象得那么多。”
面试官:“这点你倒是挺诚实。”
六、详细答案解析
下面把上面每个问题的标准思路详细展开,帮助小白真正学懂业务场景和技术点。
1. 内容发布系统核心链路如何设计
业务目标
用户点击“发布文章/视频”后,系统需要快速返回成功,同时还要完成:
- 内容主数据落库
- 标签、话题、封面等附属信息保存
- 内容审核
- 给粉丝推送动态
- 发放积分
- 建立搜索索引
典型设计
同步链路
- 前端调用
Spring MVC / Spring Boot Controller - 进行参数校验,可结合
Jakarta Validation Service层执行业务逻辑- 使用
MyBatis / JPA / Hibernate持久化到 MySQL - 返回发布成功和内容 ID
异步链路
发布成功后,通过 Kafka / RabbitMQ / Pulsar 发送消息:
- 审核服务消费消息,执行敏感词、机器审核、人工审核流程
- 通知服务给粉丝推送消息
- 搜索服务写入 Elasticsearch
- 积分服务发放成长值
为什么这样设计
因为“发布”对用户来说最重要的是快。如果把审核、索引、通知、积分都放在同步请求里,接口会变慢,甚至超时。
所以核心原则是:
- 主链路只做必要动作
- 非核心动作异步化
- 用消息队列解耦业务
2. 点赞数、评论数如何使用 Redis,并保证缓存一致性
为什么要用缓存
内容详情页访问量极大,点赞数、评论数是高频读数据。如果每次都查 MySQL,数据库压力很大。
所以常见做法:
- 热点计数放 Redis
- 详情页优先读 Redis
- 定期或异步回写数据库
常见方案
方案一:旁路缓存(Cache Aside)
- 查询:先查 Redis,没有再查 MySQL,并写回缓存
- 更新:先更新数据库,再删除缓存
这是最常见方案。
为什么不是“更新数据库后更新缓存”
因为更新缓存更容易造成脏数据,例如并发写入时旧值覆盖新值。
并发一致性问题
比如:
- 线程 A 查询缓存未命中,准备查库
- 线程 B 更新数据库并删除缓存
- 线程 A 查到旧值,再把旧值写回缓存
这样缓存就脏了。
解决思路
- 设置缓存过期时间,脏数据会自动淘汰
- 延迟双删:更新数据库前删除缓存,更新后延迟再删一次
- 对强一致要求更高的场景,使用消息队列异步刷新缓存
- 对计数型场景,可 Redis 原子自增,再异步落库
点赞计数更适合什么模式
点赞数更适合:
- Redis 原子计数
INCR - 定时任务批量刷库
- 或通过 Kafka 异步写库
因为点赞是高频写操作,直接频繁更新数据库会很重。
3. Feed 流首页高性能分页如何设计
深分页问题
limit 100000, 20 这种 SQL 非常慢,因为数据库需要先扫描和跳过前面大量数据。
优化方案:游标分页
常见方式:
- 按
publish_time倒序 - 或按
id倒序 - 记录上一页最后一条记录的时间或 ID
- 下一页使用
where id < last_id limit 20
优势
- 避免大量 offset 扫描
- 性能更稳定
- 适合无限下拉场景
数据库设计建议
文章表常见字段:
idauthor_idcontent_typestatuspublish_timelike_countcomment_count
索引建议:
(status, publish_time)(author_id, publish_time)
如果是推荐 feed,还可能结合:
- Redis 缓存候选集合
- Elasticsearch 检索
- 推荐服务预计算结果
4. 评论系统如何设计
基础表结构
评论表可包含:
idcontent_iduser_idparent_idroot_idreply_to_user_idcontentlike_countcreate_time
字段含义
parent_id:直接父评论root_id:所属主评论
为什么要有 root_id
因为查询“某个主评论下的所有回复”时,直接按 root_id 查比层层递归查性能更好。
常见展示方案
方案一:两级结构
很多内容社区并不展示无限层级,而是:
- 一级评论
- 二级回复
更深层的回复在产品上仍挂到二级里展示。
方案二:逻辑多级,展示扁平化
数据库可以支持多级,但接口返回时按 root_id 聚合,前端按扁平列表展示。
为什么不建议无限递归查询
- SQL 和程序复杂
- 性能差
- 排序和分页难做
- 容易出现深层嵌套导致接口响应慢
所以互联网项目中,评论系统常常“逻辑允许多级,展示限制层级”。
5. 秒杀场景如何防止库存超卖
秒杀的核心问题
- 并发极高
- 流量瞬时爆发
- 库存有限
- 容易超卖
- 数据库扛不住
典型防超卖设计
第一层:前端和网关限流
- 活动开始前做预约/抢购资格
- Nginx、网关层限流
- 验证码、答题、防刷
第二层:Redis 预扣库存
把库存先加载到 Redis:
- 用户请求到达后先判断 Redis 库存是否大于 0
- 用 Lua 脚本保证扣减原子性
- 扣减成功后才进入下单流程
第三层:消息队列削峰
- 请求写入 Kafka/RabbitMQ
- 后端消费者异步创建订单
- 避免数据库被瞬时打爆
第四层:数据库兜底
MySQL 层仍要防超卖:
- 乐观锁
version - 或
update ... set stock = stock - 1 where id = ? and stock > 0
这样即使 Redis 层出现异常,数据库也能兜底。
重点
真正可靠的设计一定是多层防护,不是只靠单点方案。
6. 支付回调为什么必须做幂等
为什么会重复回调
支付平台为了确保商户收到通知,可能会:
- 网络超时后重复通知
- 商户未正确返回 success 时再次通知
- 用户支付过程异常后补发通知
如果不幂等会怎样
可能出现:
- 订单重复改状态
- 库存重复扣减
- 优惠券重复核销
- 积分重复发放
- 履约系统重复发货
幂等设计方法
方法一:订单状态机
订单状态必须按规则流转:
- 待支付 -> 已支付
- 已支付不能再次处理
更新时判断当前状态。
方法二:唯一约束
建立支付流水表:
- 以第三方交易号或业务订单号做唯一索引
- 重复插入直接失败
方法三:幂等记录表
记录每次回调处理结果,如果已处理则直接返回。
方法四:分布式锁
对于并发到达的相同回调,可对订单号加 Redis 锁,避免并发处理。
最佳实践
通常是:
- 验签
- 校验订单金额和商户号
- 加锁/查状态
- 更新订单与支付流水
- 发送后续消息
- 返回平台 success
7. 微服务下如何做分布式事务
业务场景
用户下单时涉及:
- 订单服务创建订单
- 库存服务扣减库存
- 优惠券服务核销优惠券
- 支付服务创建支付单
如果其中一个成功、另一个失败,就会出现数据不一致。
为什么互联网场景少用 2PC
2PC 强一致,但问题是:
- 性能差
- 锁资源时间长
- 可用性差
- 实现复杂
互联网高并发场景更偏向最终一致性。
常见方案
方案一:可靠消息最终一致性
步骤:
- 本地事务中保存订单和待发送消息
- 事务提交成功后发送消息到 Kafka
- 库存服务消费消息并扣库存
- 如果失败,执行重试或补偿
这就是“本地消息表 + MQ”模式。
方案二:TCC
- Try:预留资源
- Confirm:正式提交
- Cancel:取消释放
适合资金、库存等要求较高场景,但实现成本大。
方案三:Saga
把大事务拆成多个本地事务,每步失败时执行反向补偿。
比如:
- 创建订单成功
- 扣库存失败
- 补偿:取消订单
面试中如何回答更好
不要只背概念,要结合链路:
“订单服务本地落库后写消息表,通过定时任务或事务后投递 Kafka;库存服务消费后扣库存,失败则重试,超过次数进入死信队列,由人工或补偿任务处理。”
这样才算真正落地。
8. MySQL、Redis、Kafka 的职责边界
MySQL
负责:
- 订单、商品、库存、支付记录等核心持久化数据
- 事务支持
- 复杂查询
Redis
负责:
- 热点缓存
- 分布式锁
- 计数器
- 会话数据
- 限流
- 排行榜
Kafka
负责:
- 异步削峰
- 系统解耦
- 事件驱动
- 日志流/行为流处理
为什么不能只靠数据库
因为数据库不擅长:
- 承受极高并发读写
- 系统间异步解耦
- 削峰填谷
- 低延迟热点访问
所以现代互联网架构通常是三者组合使用。
9. AIGC 异步任务系统如何设计
业务特征
AIGC 生成常见特点:
- 耗时长,可能几秒到几分钟
- 调用外部模型服务,失败率不低
- 需要排队、重试、超时控制
- 用户希望看到进度
典型架构
第一步:创建任务
用户发起请求后:
- 校验登录态和配额
- 任务表插入一条记录,状态
INIT - 返回
taskId
第二步:投递消息
把任务 ID 发送到 Kafka/RabbitMQ。
第三步:异步执行
消费者获取任务:
- 更新状态为
RUNNING - 调用模型服务(OpenFeign/gRPC)
- 结果落库或存对象存储
- 更新为
SUCCESS/FAILED
第四步:结果通知
- 前端轮询任务状态接口
- 或通过 WebSocket 推送结果
任务表建议字段
task_iduser_idtask_typestatusrequest_payloadresult_urlerror_coderetry_countcreate_timeupdate_time
10. 大模型接口慢且不稳定,如何做服务治理
主要问题
- 响应时间长
- 超时
- 失败率高
- 下游雪崩
Resilience4j 可以做什么
超时控制
超过阈值直接失败,避免线程长期阻塞。
重试
针对瞬时错误进行有限次重试,但要注意:
- 不能无限重试
- 不能对很慢的服务盲目重试
熔断
如果失败率持续升高,熔断器打开,短时间内不再真实调用下游,防止雪崩。
限流与隔离
限制调用速率,避免下游被压垮。线程池隔离可以防止慢接口拖死整个应用。
可观测性体系
Micrometer暴露指标Prometheus拉取指标Grafana展示看板Jaeger/Zipkin做链路追踪ELK收集日志
这样线上问题能快速定位。
11. AIGC 平台如何做用户认证与安全控制
认证方案
Spring Security + JWT
常见流程:
- 用户登录成功
- 服务端签发 JWT
- 前端请求时带上 Token
- 网关或服务端解析 JWT,识别用户身份
企业级授权
如果是开放平台或企业 SaaS:
OAuth2Keycloak
可支持单点登录、第三方授权、统一身份管理。
还需要哪些安全措施
- 接口签名防篡改
- 请求时间戳防重放
- 敏感数据加密
- 频控和黑白名单
- 风控策略:异常设备、异常 IP、异常行为识别
AIGC 特有风控
- 用户恶意刷生成次数
- 生成违规内容
- Prompt 注入
- 批量注册刷资源
因此需要:
- 配额管理
- 审核系统
- 速率限制
- 行为分析
12. 线上任务卡住如何排查
一条完整排查路径
1)看日志
通过 SLF4J + Logback / Log4j2 搜索 taskId,确认卡在哪一步。
2)看监控
看:
- 接口 RT
- 错误率
- JVM 堆内存
- GC 次数
- 线程池活跃线程数
- Kafka 消费堆积
3)看链路追踪
如果跨多个服务,使用 Jaeger / Zipkin 查看哪一跳慢。
4)看任务状态机
检查任务表:
- 是不是一直停留在
RUNNING - 是否缺少超时回收机制
- 是否消费者处理完没更新状态
5)看中间件
- Kafka 分区是否堆积
- Redis 锁是否过期失效或未释放
- 数据库连接池如
HikariCP是否耗尽
6)看 JVM
使用 jstack、jmap、jstat 等工具:
- 是否死锁
- 是否 Full GC 频繁
- 是否线程阻塞
最终目标
不是只会说“我先看日志”,而是要形成系统化排障思路:
日志 -> 指标 -> 链路 -> 中间件 -> 数据库 -> JVM
七、面试复盘总结
如果你是 Java 求职者,这篇面试实录里最该掌握的是以下能力:
-
能把技术点放进业务场景里回答
不要只背 Spring Boot、Redis、Kafka、MyBatis 的定义,要会结合内容社区、电商、AIGC、支付风控去讲。 -
能区分主链路与异步链路
什么必须同步做,什么可以用消息队列异步做,这是后端设计的核心能力。 -
能说清楚高并发问题
比如缓存一致性、秒杀超卖、幂等、限流、熔断、消息堆积。 -
能回答微服务治理和线上排障
包括 Spring Cloud、OpenFeign、Resilience4j、Prometheus、Grafana、Jaeger、ELK、JVM 排查。 -
不要像谢飞机一样,复杂问题只会说名词
面试官真正想听的是:业务背景、方案设计、技术选型、优缺点、异常处理、落地细节。
如果你能把这篇文章里的问题和答案真正吃透,那么面对大厂 Java 面试中关于 Spring Boot、Redis、Kafka、MySQL、Spring Cloud、AIGC、支付、电商、内容社区等方向的问题,就会有更强的底气。
祝你下次面试时,不做“水货谢飞机”,做一个能把技术讲明白的 Java 工程师。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)