大厂 Java 面试现场面试官怒问三轮谢飞机边答边“露馅”——从发帖系统到 AIGC 架构的 Java 面试全拆解前言今天我们来模拟一场互联网大厂 Java 工程师面试。 主角有两位严肃面试官问题层层递进紧贴真实业务场景不讲废话。搞笑水货程序员谢飞机简单问题能答上来复杂问题开始含糊其辞东拉西扯但偶尔也能碰到点上。为了让文章更有学习价值本文采用3轮面试每轮 3~5 个问题围绕真实业务场景递进最后附上详细答案与代码示例本次业务场景选用内容社区 AIGC 高并发推荐系统。 假设公司正在做一个大型内容平台支持用户发帖、评论、点赞AIGC 自动生成内容摘要热门内容推荐消息通知高并发读写微服务架构部署技术栈会尽量覆盖常见大厂 Java 面试高频点例如Java 8/11/17、JVMSpring Boot、Spring MVC、Spring WebFluxMyBatis / JPA / HibernateRedis、Kafka、RabbitMQSpring Security、JWT、OAuth2Prometheus、Grafana、ELKDocker、Kubernetes、JenkinsElasticsearchJUnit 5、MockitoOpenFeign、Resilience4jJackson、ProtobufGit、Maven 等第一轮基础能力考察 —— 从发帖系统开始场景背景面试官 “假设我们现在做一个内容社区核心功能是用户发帖。你来设计一个发帖接口要求支持文本、标签、作者信息入库并且后续可扩展审核与消息通知。”谢飞机坐直了“这个我会这不就是 CRUD 嘛。”问题1你会如何设计发帖接口的分层结构面试官“用 Spring Boot 说一下 Controller、Service、DAO 的职责划分。”谢飞机“Controller 接参数Service 写业务DAO 查数据库。这个很标准。就是前端发请求后端接住然后存库完事。”面试官“嗯基础是对的。那你继续说说为什么不能把业务都写在 Controller 里”谢飞机“因为……Controller 太胖了不太优雅看起来乱。后面改需求不方便。还有就是大家都这么写。”面试官“可以至少你知道分层是为了维护性和职责清晰。”问题2帖子表怎么设计索引怎么加谢飞机“帖子表嘛id、title、content、user_id、status、create_time、update_time。 索引的话主键一个然后 user_id 一个再加 create_time查最新帖子会快一点。”面试官“如果要按作者分页查询帖子列表同时支持按状态过滤呢”谢飞机“那……加联合索引比如 user_id 和 status 放一起再 maybe 带上 create_time。”面试官“不错这次答得可以。”问题3如果发帖后要异步触发内容审核和消息通知你怎么做谢飞机“这个简单发帖成功后发 MQ。审核服务和通知服务各自消费。比如 Kafka 或 RabbitMQ 都行。”面试官“那为什么不用同步调用”谢飞机“同步会慢啊用户发帖等太久体验不好。而且审核和通知不是主链路可以异步削峰。”面试官“很好这个回答比较完整。”问题4如果用户重复点击提交按钮造成重复发帖怎么办谢飞机“前端按钮点一次后置灰。”面试官“后端呢”谢飞机“后端……也可以做个防重。比如 token或者 Redis 幂等校验。再或者业务唯一 ID。”面试官“可以说明你知道不能只靠前端。”第二轮进阶能力考察 —— 高并发与缓存一致性场景升级面试官 “现在平台日活上来了首页热点帖子访问量特别高。你来处理热点帖子的查询性能问题。”谢飞机擦了擦汗“这个一般就是 Redis。”问题1热点帖子详情怎么做缓存谢飞机“先查 Redis没有就查数据库再写回 Redis。标准 Cache Aside 模式。”面试官“不错。那缓存 key 怎么设计”谢飞机“post:detail:{postId}。比较清楚。”面试官“可以。”问题2缓存击穿、穿透、雪崩分别怎么处理谢飞机“穿透就是查一个不存在的数据总打数据库。可以缓存空值或者布隆过滤器。 击穿就是一个热点 key 过期瞬间大量请求打到数据库可以加分布式锁。 雪崩就是很多 key 同时过期可以把过期时间打散或者做多级缓存、限流降级。”面试官“嗯这个答得挺顺。”谢飞机得意了“这些八股我熟。”问题3点赞数存在 Redis 里最终落库。那 Redis 和 MySQL 不一致怎么办谢飞机“这个……一般最终一致性。先写 Redis然后异步刷库。 不一致嘛……过一会儿就一致了。”面试官“具体一点比如宕机了呢”谢飞机“宕机了就……重启继续刷或者 Kafka 记一下日志再不行人工补。”面试官“你的回答有方向但不够完整。需要考虑可靠消息、批量落库、幂等更新、补偿机制。”谢飞机点点头“对对对我刚才就是这个意思。”问题4如果首页推荐接口响应过慢你会怎么排查谢飞机“先看日志再看数据库慢 SQL再看 Redis 命中率。 如果是微服务调用慢就看链路追踪比如 Jaeger 或 Zipkin。 还可以用 Prometheus Grafana 看接口 RT 和 QPS。”面试官“不错排查思路还算清晰。”第三轮架构设计考察 —— AIGC 内容生成与微服务治理场景再升级面试官 “现在公司加了 AIGC 功能用户发帖后系统要自动生成摘要、标签和推荐词。这个能力由独立 AI 服务提供。你来设计调用链路。”谢飞机表情逐渐凝重“AI 这块我也懂一点点平时看得比较多。”问题1AIGC 摘要服务应该同步调用还是异步调用谢飞机“我觉得要分场景。 如果发帖后必须立刻展示摘要就同步调用。 如果只是后续补全可以异步。 一般为了用户体验我倾向异步。”面试官“这个回答可以。那异步链路怎么设计”谢飞机“发帖成功后发 KafkaAIGC 服务消费消息生成摘要后回写数据库。前端先展示‘摘要生成中’。”面试官“很好。”问题2如果 AI 服务经常超时你怎么做服务治理谢飞机“可以用 OpenFeign 调用再加 Resilience4j 做超时、重试、熔断、限流。 如果服务挂了可以降级返回默认摘要比如取正文前 100 个字。”面试官“不错这个答案比较像线上方案。”问题3如果要保障接口安全防止未登录用户调用发帖接口你怎么做谢飞机“Spring Security JWT。 登录成功发 token请求时带 Authorization。后端过滤器校验 token解析用户身份。 如果要支持第三方登录可以加 OAuth2 或接 Keycloak。”面试官“可以回答比较标准。”问题4如果让你优化 JVM减少接口 Full GC 风险你会怎么做谢飞机“这个……先加内存。 然后看对象是不是创建太多。 再看 GC 日志用 jmap、jstack、jvisualvm 这些工具。 参数的话可以调 G1Java 11、17 的 GC 表现一般更好。”面试官“回答有一些点但深度不够。比如内存分配、对象生命周期、缓存对象数量控制、线程池队列堆积、JSON 序列化对象膨胀这些都要考虑。”谢飞机挠头“对我刚刚其实正要说到这儿。”面试结束面试官合上笔记本语气平静“今天先到这里。你基础知识还可以尤其是常见的缓存、消息队列、接口分层这些内容回答得还行。 但在复杂场景下比如一致性治理、JVM 调优、分布式故障处理方面回答不够深入。 你先回去等通知吧后续有消息 HR 会联系你。”谢飞机起身“好的我回去继续精进顺便看看八股和源码。”附本场面试详细答案与技术拆解下面进入真正适合小白学习的部分。 我们把上面问题里涉及的知识点拆开讲并给出代码案例。一、发帖接口设计1. 分层架构设计标准 Spring Boot 分层Controller接收请求、参数校验、返回响应Service核心业务逻辑Repository / Mapper数据库访问Domain / Entity实体对象DTO / VO数据传输对象、展示对象2. 代码示例ControllerRestController RequestMapping(/api/posts) RequiredArgsConstructor public class PostController { private final PostService postService; PostMapping public ResponseEntityLong createPost(RequestBody Valid CreatePostRequest request) { Long postId postService.createPost(request); return ResponseEntity.ok(postId); } }DTOData public class CreatePostRequest { NotBlank private String title; NotBlank private String content; NotNull private Long userId; private ListString tags; }Servicepublic interface PostService { Long createPost(CreatePostRequest request); }Service RequiredArgsConstructor public class PostServiceImpl implements PostService { private final PostMapper postMapper; private final KafkaTemplateString, String kafkaTemplate; private final ObjectMapper objectMapper; Override Transactional public Long createPost(CreatePostRequest request) { Post post new Post(); post.setTitle(request.getTitle()); post.setContent(request.getContent()); post.setUserId(request.getUserId()); post.setStatus(0); post.setCreateTime(LocalDateTime.now()); post.setUpdateTime(LocalDateTime.now()); postMapper.insert(post); try { kafkaTemplate.send(post-created-topic, objectMapper.writeValueAsString(post)); } catch (Exception e) { throw new RuntimeException(发送消息失败, e); } return post.getId(); } }MyBatis MapperMapper public interface PostMapper { void insert(Post post); Post selectById(Long id); }3. 数据库表设计CREATE TABLE post ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, status TINYINT NOT NULL DEFAULT 0, create_time DATETIME NOT NULL, update_time DATETIME NOT NULL, INDEX idx_user_status_ctime (user_id, status, create_time), INDEX idx_ctime (create_time) );设计说明id主键user_id作者 IDstatus状态0待审核1已发布2下架create_time支持按时间排序联合索引(user_id, status, create_time)适合“按作者状态时间倒序分页查询”二、异步解耦MQ 在发帖后的应用1. 为什么要用消息队列用户发帖后可能还要做内容审核生成摘要推送粉丝通知写搜索索引埋点统计这些都不是主链路必须同步完成的操作。 所以可以把这些动作放到 MQ 中异步处理降低接口响应时间。2. Kafka 消费示例Component RequiredArgsConstructor public class PostCreatedConsumer { private final AuditService auditService; KafkaListener(topics post-created-topic, groupId audit-group) public void consume(String message) { auditService.audit(message); } }三、缓存设计热点帖子详情缓存1. Cache Aside 模式流程先查 RedisRedis 没有再查 MySQL查到后写回 Redis返回结果2. 代码示例Service RequiredArgsConstructor public class PostQueryService { private final StringRedisTemplate redisTemplate; private final PostMapper postMapper; private final ObjectMapper objectMapper; public Post getPostDetail(Long postId) throws Exception { String key post:detail: postId; String cache redisTemplate.opsForValue().get(key); if (cache ! null) { return objectMapper.readValue(cache, Post.class); } Post post postMapper.selectById(postId); if (post null) { redisTemplate.opsForValue().set(key, null, Duration.ofMinutes(5)); return null; } redisTemplate.opsForValue().set( key, objectMapper.writeValueAsString(post), Duration.ofMinutes(30) ); return post; } }3. 三大缓存问题缓存穿透查不存在的数据导致请求打到数据库。 解决缓存空值布隆过滤器缓存击穿热点 key 失效大量请求同时查数据库。 解决分布式锁热点数据永不过期 异步刷新缓存雪崩大量 key 同时过期。 解决过期时间随机化多级缓存限流降级四、点赞系统的一致性设计点赞数是高频写操作常见做法是Redis 记录实时计数Kafka 异步落库定时任务兜底补偿1. Redis 自增public Long likePost(Long postId, Long userId) { String key post:like:count: postId; return redisTemplate.opsForValue().increment(key); }2. 一致性挑战如果只写 Redis不及时落库可能出现Redis 宕机数据丢失消息发送失败消费失败重复消费3. 可靠方案推荐方案用户点赞写 Redis同时发送 Kafka 消息消费者批量更新 MySQL用唯一业务 ID 保证幂等定时对账任务比对 Redis 与 MySQL 差异五、AIGC 摘要生成服务设计1. 为什么建议异步AIGC 调用通常有以下问题网络耗时长依赖第三方模型服务超时率高成本较高如果同步调用用户发帖会很慢。 所以更适合发帖先成功摘要异步生成前端轮询或消息通知更新状态2. 事件驱动流程用户发帖 ↓ 帖子入库 ↓ 发送 Kafka 消息 ↓ AIGC 服务消费 ↓ 调用大模型生成摘要/标签 ↓ 结果回写数据库 ↓ 搜索服务/推荐服务继续消费3. OpenFeign Resilience4j 示例Feign ClientFeignClient(name ai-service, fallback AiSummaryClientFallback.class) public interface AiSummaryClient { PostMapping(/api/summary) SummaryResponse generate(RequestBody SummaryRequest request); }降级实现Component public class AiSummaryClientFallback implements AiSummaryClient { Override public SummaryResponse generate(SummaryRequest request) { SummaryResponse response new SummaryResponse(); String content request.getContent(); response.setSummary(content.length() 100 ? content.substring(0, 100) : content); return response; } }Resilience4j 配置思路超时控制重试熔断限流降级这样 AI 服务故障时不会拖垮主站。六、安全设计Spring Security JWT1. 基本思路登录成功后服务端生成 JWT客户端每次请求带上 token服务端校验 token 并解析用户身份2. JWT 优点无状态适合微服务不需要服务端保存 session3. 注意事项token 设置过期时间使用 HTTPS敏感操作要结合权限校验可配合 Redis 做黑名单或强制下线七、接口性能排查与可观测性1. 排查慢接口的方法从外到内看前端网络耗时网关耗时应用接口 RT数据库慢 SQLRedis 命中率下游服务调用耗时JVM GC 情况线程池堆积情况2. 常用工具Prometheus Grafana监控指标MicrometerSpring Boot 埋点ELK日志检索Jaeger / Zipkin链路追踪3. Micrometer 示例RestController RequiredArgsConstructor public class DemoController { private final MeterRegistry meterRegistry; GetMapping(/hello) public String hello() { meterRegistry.counter(api.hello.count).increment(); return hello; } }八、JVM 调优在面试中的正确回答思路很多候选人一说 JVM 就只会调大堆内存改 GC 参数这远远不够。 正确思路应该是1. 先看现象接口 RT 抖动Full GC 频繁CPU 飙高内存持续上涨OOM2. 再分析原因可能是大对象过多短命对象太多Young GC 频繁缓存无上限线程池任务堆积JSON 序列化创建大量临时对象数据库查询结果集太大Netty/DirectMemory 使用异常3. 常用工具jstat看 GC 情况jmap导出堆jstack分析线程Arthas线上诊断神器GC 日志分析工具4. 优化方向减少对象创建合理设置缓存大小分页查询避免大结果集优化线程池参数使用 G1/ZGC视 JDK 版本升级到 Java 11/17 获得更稳定的 GC 表现九、测试怎么回答更像“会做项目的人”如果面试官追问测试不要只说“写过单元测试”。可以这样答JUnit 5单元测试MockitoMock 外部依赖AssertJ增强断言可读性Selenium前端自动化CucumberBDD 场景测试JUnit 5 Mockito 示例ExtendWith(MockitoExtension.class) class PostServiceTest { Mock private PostMapper postMapper; InjectMocks private PostServiceImpl postService; Test void testCreatePost() { CreatePostRequest request new CreatePostRequest(); request.setTitle(Test Title); request.setContent(Test Content); request.setUserId(1L); Long postId postService.createPost(request); Assertions.assertNotNull(postId); } }注意真实项目里这个测试还应 mock KafkaTemplate 等依赖否则不完整。十、面试总结这场面试考了什么这篇文章表面上是搞笑面试实际上考的是 Java 后端最核心的能力基础编码与分层设计数据库表设计与索引能力缓存设计与高并发处理消息队列异步解耦分布式系统一致性微服务治理与容错接口安全JVM 与性能调优监控排障能力是否真正理解业务场景给小白的学习路线建议如果你想看懂并掌握本文内容推荐按这个顺序学Java SE、集合、多线程、JVM 基础Spring Boot Spring MVCMySQL 索引 事务MyBatis / JPARedisKafka / RabbitMQSpring Security JWT微服务OpenFeign、Spring Cloud监控Prometheus、Grafana、ELKDocker、Kubernetes、CI/CD高并发与分布式一致性专题结语如果你正在准备 Java 后端面试这种“故事化 场景化 技术拆解”的学习方式往往比单纯死背八股更有效。因为真正的大厂面试不只是问你“会不会”而是看你能不能把知识点放进业务场景里讲出设计思路、权衡方案和落地细节。如果你喜欢这种风格后续还可以继续扩展电商场景版 Java 面试故事支付系统版高并发面试题微服务故障排查实战版AIGC 平台架构设计专题欢迎继续交流。
大厂 Java 面试现场:面试官怒问三轮,谢飞机边答边“露馅”——从发帖系统到 AIGC 架构的 Java 面试全拆解
发布时间:2026/6/25 13:38:16
大厂 Java 面试现场面试官怒问三轮谢飞机边答边“露馅”——从发帖系统到 AIGC 架构的 Java 面试全拆解前言今天我们来模拟一场互联网大厂 Java 工程师面试。 主角有两位严肃面试官问题层层递进紧贴真实业务场景不讲废话。搞笑水货程序员谢飞机简单问题能答上来复杂问题开始含糊其辞东拉西扯但偶尔也能碰到点上。为了让文章更有学习价值本文采用3轮面试每轮 3~5 个问题围绕真实业务场景递进最后附上详细答案与代码示例本次业务场景选用内容社区 AIGC 高并发推荐系统。 假设公司正在做一个大型内容平台支持用户发帖、评论、点赞AIGC 自动生成内容摘要热门内容推荐消息通知高并发读写微服务架构部署技术栈会尽量覆盖常见大厂 Java 面试高频点例如Java 8/11/17、JVMSpring Boot、Spring MVC、Spring WebFluxMyBatis / JPA / HibernateRedis、Kafka、RabbitMQSpring Security、JWT、OAuth2Prometheus、Grafana、ELKDocker、Kubernetes、JenkinsElasticsearchJUnit 5、MockitoOpenFeign、Resilience4jJackson、ProtobufGit、Maven 等第一轮基础能力考察 —— 从发帖系统开始场景背景面试官 “假设我们现在做一个内容社区核心功能是用户发帖。你来设计一个发帖接口要求支持文本、标签、作者信息入库并且后续可扩展审核与消息通知。”谢飞机坐直了“这个我会这不就是 CRUD 嘛。”问题1你会如何设计发帖接口的分层结构面试官“用 Spring Boot 说一下 Controller、Service、DAO 的职责划分。”谢飞机“Controller 接参数Service 写业务DAO 查数据库。这个很标准。就是前端发请求后端接住然后存库完事。”面试官“嗯基础是对的。那你继续说说为什么不能把业务都写在 Controller 里”谢飞机“因为……Controller 太胖了不太优雅看起来乱。后面改需求不方便。还有就是大家都这么写。”面试官“可以至少你知道分层是为了维护性和职责清晰。”问题2帖子表怎么设计索引怎么加谢飞机“帖子表嘛id、title、content、user_id、status、create_time、update_time。 索引的话主键一个然后 user_id 一个再加 create_time查最新帖子会快一点。”面试官“如果要按作者分页查询帖子列表同时支持按状态过滤呢”谢飞机“那……加联合索引比如 user_id 和 status 放一起再 maybe 带上 create_time。”面试官“不错这次答得可以。”问题3如果发帖后要异步触发内容审核和消息通知你怎么做谢飞机“这个简单发帖成功后发 MQ。审核服务和通知服务各自消费。比如 Kafka 或 RabbitMQ 都行。”面试官“那为什么不用同步调用”谢飞机“同步会慢啊用户发帖等太久体验不好。而且审核和通知不是主链路可以异步削峰。”面试官“很好这个回答比较完整。”问题4如果用户重复点击提交按钮造成重复发帖怎么办谢飞机“前端按钮点一次后置灰。”面试官“后端呢”谢飞机“后端……也可以做个防重。比如 token或者 Redis 幂等校验。再或者业务唯一 ID。”面试官“可以说明你知道不能只靠前端。”第二轮进阶能力考察 —— 高并发与缓存一致性场景升级面试官 “现在平台日活上来了首页热点帖子访问量特别高。你来处理热点帖子的查询性能问题。”谢飞机擦了擦汗“这个一般就是 Redis。”问题1热点帖子详情怎么做缓存谢飞机“先查 Redis没有就查数据库再写回 Redis。标准 Cache Aside 模式。”面试官“不错。那缓存 key 怎么设计”谢飞机“post:detail:{postId}。比较清楚。”面试官“可以。”问题2缓存击穿、穿透、雪崩分别怎么处理谢飞机“穿透就是查一个不存在的数据总打数据库。可以缓存空值或者布隆过滤器。 击穿就是一个热点 key 过期瞬间大量请求打到数据库可以加分布式锁。 雪崩就是很多 key 同时过期可以把过期时间打散或者做多级缓存、限流降级。”面试官“嗯这个答得挺顺。”谢飞机得意了“这些八股我熟。”问题3点赞数存在 Redis 里最终落库。那 Redis 和 MySQL 不一致怎么办谢飞机“这个……一般最终一致性。先写 Redis然后异步刷库。 不一致嘛……过一会儿就一致了。”面试官“具体一点比如宕机了呢”谢飞机“宕机了就……重启继续刷或者 Kafka 记一下日志再不行人工补。”面试官“你的回答有方向但不够完整。需要考虑可靠消息、批量落库、幂等更新、补偿机制。”谢飞机点点头“对对对我刚才就是这个意思。”问题4如果首页推荐接口响应过慢你会怎么排查谢飞机“先看日志再看数据库慢 SQL再看 Redis 命中率。 如果是微服务调用慢就看链路追踪比如 Jaeger 或 Zipkin。 还可以用 Prometheus Grafana 看接口 RT 和 QPS。”面试官“不错排查思路还算清晰。”第三轮架构设计考察 —— AIGC 内容生成与微服务治理场景再升级面试官 “现在公司加了 AIGC 功能用户发帖后系统要自动生成摘要、标签和推荐词。这个能力由独立 AI 服务提供。你来设计调用链路。”谢飞机表情逐渐凝重“AI 这块我也懂一点点平时看得比较多。”问题1AIGC 摘要服务应该同步调用还是异步调用谢飞机“我觉得要分场景。 如果发帖后必须立刻展示摘要就同步调用。 如果只是后续补全可以异步。 一般为了用户体验我倾向异步。”面试官“这个回答可以。那异步链路怎么设计”谢飞机“发帖成功后发 KafkaAIGC 服务消费消息生成摘要后回写数据库。前端先展示‘摘要生成中’。”面试官“很好。”问题2如果 AI 服务经常超时你怎么做服务治理谢飞机“可以用 OpenFeign 调用再加 Resilience4j 做超时、重试、熔断、限流。 如果服务挂了可以降级返回默认摘要比如取正文前 100 个字。”面试官“不错这个答案比较像线上方案。”问题3如果要保障接口安全防止未登录用户调用发帖接口你怎么做谢飞机“Spring Security JWT。 登录成功发 token请求时带 Authorization。后端过滤器校验 token解析用户身份。 如果要支持第三方登录可以加 OAuth2 或接 Keycloak。”面试官“可以回答比较标准。”问题4如果让你优化 JVM减少接口 Full GC 风险你会怎么做谢飞机“这个……先加内存。 然后看对象是不是创建太多。 再看 GC 日志用 jmap、jstack、jvisualvm 这些工具。 参数的话可以调 G1Java 11、17 的 GC 表现一般更好。”面试官“回答有一些点但深度不够。比如内存分配、对象生命周期、缓存对象数量控制、线程池队列堆积、JSON 序列化对象膨胀这些都要考虑。”谢飞机挠头“对我刚刚其实正要说到这儿。”面试结束面试官合上笔记本语气平静“今天先到这里。你基础知识还可以尤其是常见的缓存、消息队列、接口分层这些内容回答得还行。 但在复杂场景下比如一致性治理、JVM 调优、分布式故障处理方面回答不够深入。 你先回去等通知吧后续有消息 HR 会联系你。”谢飞机起身“好的我回去继续精进顺便看看八股和源码。”附本场面试详细答案与技术拆解下面进入真正适合小白学习的部分。 我们把上面问题里涉及的知识点拆开讲并给出代码案例。一、发帖接口设计1. 分层架构设计标准 Spring Boot 分层Controller接收请求、参数校验、返回响应Service核心业务逻辑Repository / Mapper数据库访问Domain / Entity实体对象DTO / VO数据传输对象、展示对象2. 代码示例ControllerRestController RequestMapping(/api/posts) RequiredArgsConstructor public class PostController { private final PostService postService; PostMapping public ResponseEntityLong createPost(RequestBody Valid CreatePostRequest request) { Long postId postService.createPost(request); return ResponseEntity.ok(postId); } }DTOData public class CreatePostRequest { NotBlank private String title; NotBlank private String content; NotNull private Long userId; private ListString tags; }Servicepublic interface PostService { Long createPost(CreatePostRequest request); }Service RequiredArgsConstructor public class PostServiceImpl implements PostService { private final PostMapper postMapper; private final KafkaTemplateString, String kafkaTemplate; private final ObjectMapper objectMapper; Override Transactional public Long createPost(CreatePostRequest request) { Post post new Post(); post.setTitle(request.getTitle()); post.setContent(request.getContent()); post.setUserId(request.getUserId()); post.setStatus(0); post.setCreateTime(LocalDateTime.now()); post.setUpdateTime(LocalDateTime.now()); postMapper.insert(post); try { kafkaTemplate.send(post-created-topic, objectMapper.writeValueAsString(post)); } catch (Exception e) { throw new RuntimeException(发送消息失败, e); } return post.getId(); } }MyBatis MapperMapper public interface PostMapper { void insert(Post post); Post selectById(Long id); }3. 数据库表设计CREATE TABLE post ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, status TINYINT NOT NULL DEFAULT 0, create_time DATETIME NOT NULL, update_time DATETIME NOT NULL, INDEX idx_user_status_ctime (user_id, status, create_time), INDEX idx_ctime (create_time) );设计说明id主键user_id作者 IDstatus状态0待审核1已发布2下架create_time支持按时间排序联合索引(user_id, status, create_time)适合“按作者状态时间倒序分页查询”二、异步解耦MQ 在发帖后的应用1. 为什么要用消息队列用户发帖后可能还要做内容审核生成摘要推送粉丝通知写搜索索引埋点统计这些都不是主链路必须同步完成的操作。 所以可以把这些动作放到 MQ 中异步处理降低接口响应时间。2. Kafka 消费示例Component RequiredArgsConstructor public class PostCreatedConsumer { private final AuditService auditService; KafkaListener(topics post-created-topic, groupId audit-group) public void consume(String message) { auditService.audit(message); } }三、缓存设计热点帖子详情缓存1. Cache Aside 模式流程先查 RedisRedis 没有再查 MySQL查到后写回 Redis返回结果2. 代码示例Service RequiredArgsConstructor public class PostQueryService { private final StringRedisTemplate redisTemplate; private final PostMapper postMapper; private final ObjectMapper objectMapper; public Post getPostDetail(Long postId) throws Exception { String key post:detail: postId; String cache redisTemplate.opsForValue().get(key); if (cache ! null) { return objectMapper.readValue(cache, Post.class); } Post post postMapper.selectById(postId); if (post null) { redisTemplate.opsForValue().set(key, null, Duration.ofMinutes(5)); return null; } redisTemplate.opsForValue().set( key, objectMapper.writeValueAsString(post), Duration.ofMinutes(30) ); return post; } }3. 三大缓存问题缓存穿透查不存在的数据导致请求打到数据库。 解决缓存空值布隆过滤器缓存击穿热点 key 失效大量请求同时查数据库。 解决分布式锁热点数据永不过期 异步刷新缓存雪崩大量 key 同时过期。 解决过期时间随机化多级缓存限流降级四、点赞系统的一致性设计点赞数是高频写操作常见做法是Redis 记录实时计数Kafka 异步落库定时任务兜底补偿1. Redis 自增public Long likePost(Long postId, Long userId) { String key post:like:count: postId; return redisTemplate.opsForValue().increment(key); }2. 一致性挑战如果只写 Redis不及时落库可能出现Redis 宕机数据丢失消息发送失败消费失败重复消费3. 可靠方案推荐方案用户点赞写 Redis同时发送 Kafka 消息消费者批量更新 MySQL用唯一业务 ID 保证幂等定时对账任务比对 Redis 与 MySQL 差异五、AIGC 摘要生成服务设计1. 为什么建议异步AIGC 调用通常有以下问题网络耗时长依赖第三方模型服务超时率高成本较高如果同步调用用户发帖会很慢。 所以更适合发帖先成功摘要异步生成前端轮询或消息通知更新状态2. 事件驱动流程用户发帖 ↓ 帖子入库 ↓ 发送 Kafka 消息 ↓ AIGC 服务消费 ↓ 调用大模型生成摘要/标签 ↓ 结果回写数据库 ↓ 搜索服务/推荐服务继续消费3. OpenFeign Resilience4j 示例Feign ClientFeignClient(name ai-service, fallback AiSummaryClientFallback.class) public interface AiSummaryClient { PostMapping(/api/summary) SummaryResponse generate(RequestBody SummaryRequest request); }降级实现Component public class AiSummaryClientFallback implements AiSummaryClient { Override public SummaryResponse generate(SummaryRequest request) { SummaryResponse response new SummaryResponse(); String content request.getContent(); response.setSummary(content.length() 100 ? content.substring(0, 100) : content); return response; } }Resilience4j 配置思路超时控制重试熔断限流降级这样 AI 服务故障时不会拖垮主站。六、安全设计Spring Security JWT1. 基本思路登录成功后服务端生成 JWT客户端每次请求带上 token服务端校验 token 并解析用户身份2. JWT 优点无状态适合微服务不需要服务端保存 session3. 注意事项token 设置过期时间使用 HTTPS敏感操作要结合权限校验可配合 Redis 做黑名单或强制下线七、接口性能排查与可观测性1. 排查慢接口的方法从外到内看前端网络耗时网关耗时应用接口 RT数据库慢 SQLRedis 命中率下游服务调用耗时JVM GC 情况线程池堆积情况2. 常用工具Prometheus Grafana监控指标MicrometerSpring Boot 埋点ELK日志检索Jaeger / Zipkin链路追踪3. Micrometer 示例RestController RequiredArgsConstructor public class DemoController { private final MeterRegistry meterRegistry; GetMapping(/hello) public String hello() { meterRegistry.counter(api.hello.count).increment(); return hello; } }八、JVM 调优在面试中的正确回答思路很多候选人一说 JVM 就只会调大堆内存改 GC 参数这远远不够。 正确思路应该是1. 先看现象接口 RT 抖动Full GC 频繁CPU 飙高内存持续上涨OOM2. 再分析原因可能是大对象过多短命对象太多Young GC 频繁缓存无上限线程池任务堆积JSON 序列化创建大量临时对象数据库查询结果集太大Netty/DirectMemory 使用异常3. 常用工具jstat看 GC 情况jmap导出堆jstack分析线程Arthas线上诊断神器GC 日志分析工具4. 优化方向减少对象创建合理设置缓存大小分页查询避免大结果集优化线程池参数使用 G1/ZGC视 JDK 版本升级到 Java 11/17 获得更稳定的 GC 表现九、测试怎么回答更像“会做项目的人”如果面试官追问测试不要只说“写过单元测试”。可以这样答JUnit 5单元测试MockitoMock 外部依赖AssertJ增强断言可读性Selenium前端自动化CucumberBDD 场景测试JUnit 5 Mockito 示例ExtendWith(MockitoExtension.class) class PostServiceTest { Mock private PostMapper postMapper; InjectMocks private PostServiceImpl postService; Test void testCreatePost() { CreatePostRequest request new CreatePostRequest(); request.setTitle(Test Title); request.setContent(Test Content); request.setUserId(1L); Long postId postService.createPost(request); Assertions.assertNotNull(postId); } }注意真实项目里这个测试还应 mock KafkaTemplate 等依赖否则不完整。十、面试总结这场面试考了什么这篇文章表面上是搞笑面试实际上考的是 Java 后端最核心的能力基础编码与分层设计数据库表设计与索引能力缓存设计与高并发处理消息队列异步解耦分布式系统一致性微服务治理与容错接口安全JVM 与性能调优监控排障能力是否真正理解业务场景给小白的学习路线建议如果你想看懂并掌握本文内容推荐按这个顺序学Java SE、集合、多线程、JVM 基础Spring Boot Spring MVCMySQL 索引 事务MyBatis / JPARedisKafka / RabbitMQSpring Security JWT微服务OpenFeign、Spring Cloud监控Prometheus、Grafana、ELKDocker、Kubernetes、CI/CD高并发与分布式一致性专题结语如果你正在准备 Java 后端面试这种“故事化 场景化 技术拆解”的学习方式往往比单纯死背八股更有效。因为真正的大厂面试不只是问你“会不会”而是看你能不能把知识点放进业务场景里讲出设计思路、权衡方案和落地细节。如果你喜欢这种风格后续还可以继续扩展电商场景版 Java 面试故事支付系统版高并发面试题微服务故障排查实战版AIGC 平台架构设计专题欢迎继续交流。