Java面试场景题实战:并发扣库存、OOM排查与事务失效全解析
这次我们直接聊 Java 面试里最容易被“场景题”卡住的问题。刷过八股文的人不少,但一到“线上 OOM 怎么排查”“车位相机上报延迟怎么处理”“订单并发扣库存怎么保证不超卖”这类题目,很多人就接不住了。原因不是基础差,而是没有把 Java 知识放到真实项目里串过一遍。这篇文章会用我们经常接触到的真实业务场景,把 2026 年面试逃不掉的 Java 经典真题重新拆一遍——不是背诵答案,而是讲清楚“面试官为什么问、项目里怎么用、回答时怎么说”。
核心内容分成三块:
- 高频场景题拆解:并发编程、JVM 调优、集合源码、Spring 事务、消息队列、接口幂等等。
- 结合项目实战:包括停车场上车牌识别相机对接、前后端分离项目、OOM 排查、批量任务处理等。
- 一套可以直接背的 7 天刷题计划:每天一个专题,把场景题从“看答案”变成“能开口讲”。
如果你正在准备 Java 面试,或者已经有工作经验但面试时容易被项目细节问倒,这篇文章建议直接收藏。
1. 面试场景题,和八股文到底差在哪
很多人准备面试时有一个误区:背了几十道 Java 八股文,就觉得自己准备好了。结果面试官换了个问法,问“你的项目里 Redis 缓存穿透是怎么解决的”,立刻懵住。
八股文的问题是:它是知识点的孤立记忆。
场景题的核心是:用项目里的真实问题来验证你是否真的理解这个知识点。
举一个最常见的例子:
面试官问:HashMap 底层数据结构是什么?
这是八股文。会背的人都能答上来:数组 + 链表 + 红黑树,负载因子 0.75,扩容时重新计算哈希桶位置。
但如果换成场景题:
面试官问:你的项目里用 HashMap 存储数据,结果测试环境 CPU 飙高,你怀疑是哈希冲突严重,你会怎么排查?怎么调整?
这就是场景题。它要求你不仅知道 HashMap 的原理,还要知道:
- HashMap 在并发场景下会有什么问题。
- 什么情况会导致哈希冲突严重。
- 如何通过调整初始容量和负载因子来优化。
- ConcurrentHashMap 和 HashMap 的使用边界。
从面试官的角度看,场景题能过滤掉“背答案”的人。从候选人的角度看,场景题才是真正体现技术深度的机会。
所以这篇文章不会花时间背八股文,而是把高频的 Java 经典面试真题,全部放到项目实战场景里重新过一遍。每个场景都按“题目 -> 问题分析 -> 项目应用 -> 回答思路 -> 代码/配置示例”的结构展开。
2. 高频场景题速览:面试官最爱问的 6 类
根据近两年的面试趋势,Java 面试场景题集中在下面 6 个方向。不管你是应届生还是 3 年左右经验的开发,这 6 类都是必刷项。
| 场景类型 | 典型案例 | 涉及核心知识点 | 常见出题方式 |
|---|---|---|---|
| 并发编程 | 订单并发扣库存 | synchronized、ReentrantLock、CAS、ThreadPoolExecutor | 项目里怎么样保证不超卖 |
| JVM 性能 | 线上 OOM 排查 | 堆内存、GC 日志、MAT、jstack、jmap | 你的项目遇到过 OOM 吗,怎么排查的 |
| 集合源码 | 停车场车牌缓存设计 | HashMap、ConcurrentHashMap、ArrayList、LinkedList | 为什么不直接用 HashMap 存设备状态 |
| Spring 原理 | 事物失效问题 | @Transactional 传播行为、AOP、动态代理 | 一个方法调另一个方法,事务为什么没生效 |
| 分布式与中间件 | MQ 消息丢失/重复消费 | Kafka/RabbitMQ、幂等、重试 | 消息发到 MQ 后消费者挂了怎么办 |
| 项目架构 | 前后端分离接口鉴权 | JWT、Spring Security、拦截器、过滤器 | 你的项目登录态是怎么设计的 |
下面逐个拆解。
3. 并发编程场景题:订单系统扣库存,怎么保证不超卖
3.1 题目还原
面试官:你的项目里有一个秒杀接口,1000 件库存,5000 个人同时抢。你的代码是
if (stock > 0) { stock--; },结果库存变成负数了。你会怎么改?
3.2 问题分析
这是一个非常经典的并发场景题。考点不是 synchronized 的用法,而是你有没有在真实项目里处理过并发问题。
先看原始代码:
这段代码的问题很明显:if (stock > 0) 和 stock-- 不是原子操作。两个线程同时读到 stock=1,都通过了 if 判断,然后都执行了减一,最后 stock 变成 -1。
3.3 项目里的正确解法
在实际项目中,扣库存通常有三种方案:
方案一:数据库乐观锁
执行结果影响行数为 1,说明扣减成功;为 0,说明库存不足或版本冲突,直接返回失败。
方案二:使用 Redis 原子操作
注意:Redis 扣减成功后,数据库落库也要使用乐观锁或唯一约束来兜底,防止 Redis 和数据库数据不一致。
方案三:分布式锁
适合并发量极大且需要强一致的场景,比如使用 Redisson:
3.4 回答思路
回答这类场景题时,不要直接摔代码,按下面这个顺序说:
- 先说问题本质:
check-then-act不是原子的,导致超卖。 - 给出方案对比:数据库乐观锁适合低频、一致性要求高的场景;Redis 原子扣减适合高并发秒杀场景;分布式锁适合强一致性业务。
- 说你在项目里最终用了哪种,以及为什么。
- 补充兜底方案:比如数据库最终一致性校验、定时任务对账。
这套回答思路能覆盖 80% 的并发场景题。
3.5 扩展:线程池为什么不能被无脑用
并发场景里另一个高频点就是线程池。面试官通常会追问:
为什么不直接
new Thread()?线程池的核心参数怎么设置?
回答核心:
new Thread()每次都会创建新线程,线程生命周期不可控,频繁创建销毁开销大。- 线程池可以复用线程、控制并发数、管理队列。
- 核心参数有 7 个:核心线程数、最大线程数、空闲存活时间、时间单位、工作队列、线程工厂、拒绝策略。
在一个实际的项目中,线程池通常配置如下:
拒绝策略这块,面试官很喜欢往深了问:
AbortPolicy:抛出 RejectedExecutionException,默认策略。CallerRunsPolicy:由调用线程直接执行,适合不希望丢弃任务的场景。DiscardPolicy:静默丢弃。DiscardOldestPolicy:丢弃队列中最旧的任务,然后重新尝试提交。
项目里如果任务不能丢,建议用 CallerRunsPolicy 或自定义拒绝策略,配合告警通知。
4. JVM 实战场景题:线上 OOM 了,你第一步做什么
4.1 题目还原
面试官:你的 Spring Boot 项目运行了几天后,突然报
java.lang.OutOfMemoryError: Java heap space,服务直接挂掉。你从哪些方面排查?
4.2 问题分析
OOM 是 Java 面试里最常出现的场景题之一。它考的是你是否真的遇到过线上故障,并且有完整的排查思路。
先看常见的 OOM 类型:
| 错误类型 | 含义 | 常见场景 |
|---|---|---|
| Java heap space | 堆内存溢出 | 大对象过多、内存泄漏 |
| GC overhead limit exceeded | GC 频繁且回收效果差 | 堆太小、对象存活时间过长 |
| Metaspace | 元空间溢出 | 动态生成类过多 |
| Unable to create new native thread | 线程数达到系统上限 | 无限创建线程、线程池参数不合理 |
4.3 完整排查步骤
第一步:保留现场。
在启动脚本中加上 JVM 参数,让 OOM 时自动导出堆转储文件:
第二步:查日志。
先用 dmesg 或系统监控查看进程是否被操作系统杀掉,再用 jmap -heap 看当前堆的使用情况。
第三步:分析堆转储文件。
把 app-oom.hprof 下载到本地,用 MAT 或 VisualVM 打开。重点看:
- 大对象列表:哪些对象占据了 80% 以上的堆内存。
- 支配树:对象的引用链是谁。
- 线程栈:哪些线程在持续创建对象。
第四步:定位代码问题。
比如最常见的场景:用 List 批量查询数据库后,把所有结果一次性 load 到内存,数据量大了就 OOM。
优化方案是分批处理或使用游标查询:
4.4 回答思路
回答 OOM 排查题的推荐结构:
- 先说调整启动参数,保留现场。
- 再说查 GC 日志和系统监控,确认是堆内存还是线程问题。
- 然后说用 MAT 分析堆转储,定位大对象。
- 最后说项目里常见的优化手段:分批处理、升级内存、缩减缓存。
这一套流程说完,面试官能明确感受到你有实战经验。
4.5 扩展:CPU 飙高怎么排查
OOM 场景经常还会带一个兄弟问题:
服务 CPU 使用率 100%,怎么定位是哪个线程的问题?
完整命令流程:
拿到线程栈后,重点看线程状态和堆栈调用:如果是 RUNNABLE 并且一直在执行业务代码,说明是计算密集型任务;如果是 WAITING 且大量堆积,可能是线程池队列过长或死锁。
5. 集合源码场景题:停车场车牌识别相机状态怎么高效缓存
5.1 场景还原
这是一个真实项目里的问题。停车场项目里需要对接海康、大华等主流车牌识别相机,相机通过 MQTT 协议上报车辆入场、出场事件和实时状态。项目需要缓存每台相机的在线状态、最近上报时间、当前抬杆状态等。
面试官问:
你会用什么集合来存这些设备状态?为什么不用 ArrayList?为什么不用 HashMap?
5.2 问题分析
这个题目一举三得:考了集合特性、考了并发安全、考了项目设计。
先看最直接的方案:用 HashMap。
问题来了:
- HashMap 是非线程安全的。MQTT 回调线程和业务查询线程同时操作 map,会出问题。
- 需要频繁读取和更新设备状态,
HashMap在扩容时会重新哈希,性能抖动。 - 如果要按照最后上报时间排序,
HashMap无能为力。
所以项目里的正确选择可能有三种:
方案一:ConcurrentHashMap
优点:线程安全、读性能高。适合高频读写状态,但不支持排序。
方案二:使用带过期时间的本地缓存 Caffeine
优点:自动处理设备离线情况,5 分钟没有上报自动过期,配合定时巡检更合理。
方案三:使用 Redis Hash
优点:分布式部署时多个实例共享状态;缺点:多一次网络 IO,实时性要求极高时可能有延迟。
5.3 回答思路
回答这类集合选型题时,不要只说“用 ConcurrentHashMap”,要把为什么说清楚:
- MQTT 回调是多线程的,HashMap 不安全。
- 设备状态需要频繁读写和过期清理,Caffeine 更合适。
- 如果是分布式部署,需要多个服务共享状态,用 Redis。
- 补充一句:ArrayList 不适合做键值查询,它有顺序,但查询指定设备要遍历,复杂度 O(n)。
把选择过程和思考维度展示出来,面试官会认为你真正做过项目,而不是背了“ArrayList 查询慢,HashMap 查询快”的口诀。
5.4 扩展:HashMap 底层和并发问题
如果继续往下追,面试官一定会问 HashMap 的底层原理:
- JDK 1.7:数组 + 链表,头插法,并发扩容时会成环。
- JDK 1.8:数组 + 链表 + 红黑树,尾插法,链表长度超 8 且数组长度超 64 时转为红黑树。
- 负载因子默认 0.75,扩容后数组长度翻倍。
- HashMap 的 key 为 null 时,存放在数组下标 0 的位置。
高频追问:为什么链表长度超过 8 才转红黑树?
回答思路:源码注释里说明,遵循泊松分布概率,链表长度达到 8 的概率极低(约千万分之六),在绝大多数场景下链表长度远小于 8。转红黑树是为了极端哈希冲突情况下,仍然能保证查询效率从 O(n) 降到 O(log n)。
6. Spring 事务场景题:一个方法里调另一个方法,事务为什么不生效
6.1 题目还原
面试官:你的 Service 里有一个
createOrder()方法加了@Transactional,它调用了同类的deductStock()方法,过程中抛了异常,但库存还是扣了。为什么?怎么解决?
6.2 问题分析
这是一个非常高频的 Spring 事务失效场景。
核心原因是:@Transactional 默认是通过 Spring AOP 代理实现的。同类内部调用时,this.deductStock() 走的是原始对象,不是代理对象,所以事务注解不生效。
6.3 解决方案
方案一:拆分成两个 Bean,单独注入。
方案二:使用 AopContext.currentProxy() 获取代理对象。
注意:使用 AopContext 必须在启动类或配置类中增加 @EnableAspectJAutoProxy(exposeProxy = true)。
方案三:自己注入自己(实际上不推荐,存在循环依赖风险)。
6.4 扩展:事务传播行为
如果面试官继续追问事务传播行为,项目中最常用的有三个:
REQUIRED:默认,如果当前没有事务就新建一个,如果有就加入当前事务。REQUIRES_NEW:挂起当前事务,新建一个独立事务。NESTED:嵌套事务,内层回滚不影响外部事务,外部回滚会连同内层一起回滚。
在项目里一个典型场景:记录操作日志时,即使主业务失败,日志也要记录成功,这时就需要 REQUIRES_NEW:
但要注意:REQUIRES_NEW 会开启新事务,意味着它不参与外部事务的回滚。如果日志和业务数据需要保持一致,就不能用这个传播级别。
6.5 回答思路
关于事务失效,这个知识点涉及 6 个常见场景,可以一次说完:
- 同类内部调用导致代理失效。
@Transactional加在非 public 方法上。- 异常被 try-catch 吞掉。
- 数据库引擎不支持事务(比如 MyISAM)。
- 使用了
this调用而非代理对象。 - 多线程调用,事务无法跨线程传播。
这样回答既有深度,又体现了系统性认知,面试官很容易记住你。
7. 中间件场景题:车位相机通过 MQTT 上报消息,消息积压了怎么处理
7.1 场景还原
停车场项目里,海康、大华等车牌识别相机通过 MQTT 协议上报车辆进出事件,后端服务订阅消息并将事件写入数据库、推送通知等。某次活动期间,大量车辆同时进出,MQTT 消息积压严重,数据库写入延迟,部分消息丢失。
面试官问:
你负责的消息链路出现积压、丢失,会怎么排查和处理?
7.2 问题分析
这是一个完整的消息中间件实战问题,涉及消息队列的三大核心问题:削峰填谷、可靠性、幂等。
先分析积压的原因:
- 生产者的发送速度远大于消费者的处理速度。
- 消费者处理逻辑太重,比如每条消息都同步写数据库。
- 消费者挂了或线程数配置过小。
7.3 项目里的处理方案
方案一:引入消息队列削峰。
如果原本是相机 -> 后端服务直连,可以改为相机 -> MQ -> 后端服务。使用 Kafka 或 RabbitMQ 做缓冲,后端服务按照自己的处理能力消费。
方案二:批量消费,减少数据库 IO。
将 100 条消息攒成一批,再统一写库:
方案三:处理消息丢失问题。
MQTT QoS 等级可以调整为 1 或 2,同时消费端要开启手动 ACK:
方案四:解决重复消费问题。
消息队列保证的是 at least once,也就是至少一次投递,这会导致重复消费。所以消费端必须做幂等处理。最简单的方式是用唯一业务 ID(如车牌号 + 入场时间)做去重表:
每次处理前先查去重表,存在则跳过:
7.4 回答思路
消息中间件场景题的完整思路:
- 先区分是积压、丢失还是重复消费。
- 积压:看消费速度和生产速度的差距,优化消费者逻辑、批量处理、增加分区和消费者数量。
- 丢失:从生产端、MQ 端、消费端三段排查,确认 ACK 机制。
- 重复:数据库唯一约束或业务 ID 去重。
这个套路的适用性很广,不只是 MQTT,Kafka、RabbitMQ 相关题目都可以这么组织。
8. 项目架构场景题:前后端分离项目的登录鉴权怎么设计
8.1 场景还原
目前很多项目都是前后端分离架构,前端用 Vue3 或 Vue2,后端用 Spring Boot。用户登录后,前端需要携带凭证请求后端接口,后端需要校验凭证并返回用户信息。
面试官问:
你的项目登录态是怎么保存的?用 Session 还是 Token?Token 过期了怎么办?
8.2 方案对比
Session 方案:
- 服务端保存 Session,客户端保存 Cookie 中的 JSESSIONID。
- 优点:实现简单,Spring Boot 原生支持。
- 缺点:分布式部署时需要解决 Session 共享问题,需要引入 Spring Session + Redis。
JWT 方案:
- 服务端生成签名字符串,客户端保存,每次请求携带在 Header 里。
- 优点:无状态、适合分布式和微服务。
- 缺点:无法服务端主动失效,token 泄露后只能等过期。
项目里常用的是 JWT + Redis 组合方案:
然后在拦截器或过滤器中校验:
8.3 扩展:权限控制与接口幂等
登录鉴权之后,面试官还会顺着问权限控制:
- RBAC:用户 -> 角色 -> 权限模型。
- Spring Security 的
@PreAuthorize("hasRole('ADMIN')")注解。 - 接口权限:不同角色可以看到不同的接口。
另外,在前后端分离项目中,还有一个高频场景是接口幂等。
用户重复提交订单,导致产生多条重复订单。怎么解决?
常用方案:
- 前端按钮防抖,置灰。
- 后端使用 token 机制:请求前先从服务端获取一个幂等 token,提交时校验并删除,删除成功说明第一次提交,失败说明重复提交。
9. 7 天 Java 面试场景题刷题计划
如果你现在离面试还有一周左右,建议按下面这个计划刷题。每一天都围绕一个核心专题,不仅看答案,还要动手写一写验证一下。
第 1 天:Java 基础与集合
重点场景题:
- HashMap 与 ConcurrentHashMap 在项目中的选型
- ArrayList 扩容机制和实际项目中的坑
- 快速排序和冒泡排序的手写与复杂度比较
- Lambda 表达式和函数式接口在项目中的使用场景
建议动作:手写一个多线程环境下使用 HashMap 出错的 Demo,再改成 ConcurrentHashMap 验证问题解决。
第 2 天:并发编程与线程池
重点场景题:
- 订单并发扣库存怎么保证不超卖
- 线程池参数怎么设置
- 项目中遇到死锁怎么排查
- volatile 和 synchronized 的使用场景区别
建议动作:手动写一个线程池,模拟任务队列堆积,观察拒绝策略触发效果。
第 3 天:JVM 性能调优
重点场景题:
- 线上 OOM 怎么排查
- CPU 100% 怎么定位
- 常用的 JVM 参数有哪些
- GC 日志怎么看
建议动作:本地启动一个 Spring Boot 项目,故意制造内存泄漏场景,用 jmap 导出堆转储,用 MAT 分析。
第 4 天:Spring 与 MyBatis
重点场景题:
- 事务注解为什么不生效
- Bean 的初始化过程
- MyBatis 中 #{} 和 ${} 的区别
- Spring Boot 的自动配置原理
建议动作:写一个 Controller -> Service -> Mapper 三层结构,测试事务回滚和传播行为。
第 5 天:中间件与消息队列
重点场景题:
- 消息丢失怎么处理
- 重复消费怎么处理
- 消息积压怎么解决
- Kafka 分区和消费者的关系
建议动作:搭建一个简单的 Kafka 单机环境,写生产者消费者 Demo,模拟重复消费和手动 ACK。
第 6 天:项目架构与业务设计
重点场景题:
- 前后端分离接口鉴权设计
- 接口幂等怎么做
- 数据库分库分表的场景和方案
- MQTT 对接相机等硬件设备时的心跳与离线设计
建议动作:整理自己项目里的架构图,把登录流程、接口调用链、异常处理流程用文字描述清楚。
第 7 天:全真模拟面试
重点关注题:
- 自我介绍,一定要包含项目职责和亮点。
- 项目中最有挑战的问题是什么,怎么解决的?提前准备一个 OOM 排查或并发扣库存的完整故事。
- 如果重做一次项目,哪些设计会优化?
建议动作:找朋友或同事帮你模拟面试,至少模拟两轮,每轮 30 分钟以上。重点练表达流畅度,不要只背答案。
10. 常见面试场景题自测清单
下面这份清单,你可以在面试前 1 天快速过一遍。任何一条不能顺畅回答超过 5 分钟,就回去补一下。
| 题目 | 核心考点 | 回答关键要点 |
|---|---|---|
| 多线程同时扣库存怎么防止超卖 | 并发安全 | 乐观锁、Redis 原子扣减、分布式锁对比 |
| 项目里遇到 OOM 怎么排查 | JVM 调优 | 保留现场、jmap、MAT 分析、分批处理 |
| HashMap 和 ConcurrentHashMap 区别 | 集合原理 | 线程安全、锁粒度、扩容机制 |
| 事务注解失效的原因有哪些 | Spring 原理 | 同类调用、异常被吞、代理机制 |
| 消息重复消费怎么解决 | 中间件设计 | 业务 ID 去重、数据库唯一约束 |
| JWT 和 Session 怎么选 | 项目架构 | 无状态、分布式、失效机制 |
| 线程池拒绝策略有哪些 | 并发编程 | 四种策略和适用场景 |
| MyBatis 的 #{} 和 ${} 区别 | ORM 框架 | 预编译、SQL 注入 |
| 接口幂等怎么设计 | 业务设计 | 前端防抖、幂等 token、状态机 |
| 设备离线或心跳超时怎么处理 | 物联网/硬件对接 | 心跳机制、过期清理、状态补偿 |
11. 面试答题时最容易踩的 5 个坑
11.1 只答结论,不说过程
比如问“Redis 为什么快”,不能只回答“因为内存操作”。要补充:单线程避免上下文切换、IO 多路复用、高效的数据结构、渐进式 rehash。
11.2 背答案痕迹太重
如果说到 ConcurrentHashMap 时,把源码注释背了一遍,但项目里从来没碰到过并发问题,面试官一眼就能看出来。最好结合自己的项目:在停车场的设备状态缓存场景里,哪些数据需要并发安全,为什么。
11.3 不区分“知道”和“做过”
回答时尽量用“我在项目里做过”“当时遇到了什么问题,我用了什么方案”。即使项目是团队合作或课程实战项目,也能体现你动手验证过,而不只是看资料。
11.4 展开得不够
比如被问“接口幂等怎么实现”,只说“用 token”是不够的。至少要提到:token 的生成时机、存储位置、校验方式、并发场景下的原子性、token 过期时间。
11.5 不会主动收尾
回答完之后,用一两句话总结你的设计思路。例如:“幂等的核心是保证同一个请求只被处理一次,前后端配合,前端做按钮防抖,后端做 token 去重,数据库加唯一约束兜底。”这样会给面试官留下结构化、有工程思维的印象。
12. 结合项目实战:把场景题串起来讲
最后给一个“组合拳”案例,把 8 个高频考点串到一个真实项目场景里。这是你在面试中非常加分的表达方式。
我曾经做过一个停车场车牌识别系统,车辆入场时,海康相机通过 MQTT 上报车辆入场事件。后端订阅消息后,核心业务流程是:解析消息 -> 计算停车时长/费用 -> 更新缓存 -> 推送通知 -> 写入数据库。
围绕这个项目,可以应对下面的连环追问:
追问一:并发上报,怎么保证消息不丢?
回答:通过 MQTT QoS 1 和消费者手动 ACK,消息消费成功后才提交 offset。同时增加死信队列,失败的消息进入死信并告警。
追问二:消息重复上报怎么办?
回答:数据库表加唯一索引 (camera_code, plate_number, entry_time),重复插入直接 SQL 层拦截,业务层再配合 Redis 布隆过滤器做前置判断。
追问三:设备状态缓存用什么数据结构?
回答:使用 Caffeine 本地缓存存储每台相机的在线状态,过期时间 5 分钟。分布式环境切 Redis Hash。缓存与数据库通过异步任务保持最终一致性。
追问四:高峰期大量车辆同时进出,数据库压力大怎么办?
回答:MQ 先削峰,消费者开启批量消费(500 条一批),写库前先聚合,减少 IO 次数。如果数据量更大,按停车场 ID 分库分表。
追问五:如果消息处理时发生 OOM,怎么排查?
回答:启动参数加 -XX:+HeapDumpOnOutOfMemoryError,OOM 时自动导堆转储,用 MAT 分析是哪个对象占用过高。最终定位到日志对象或者一次性加载的数据,改成批量处理。
这样一套串讲下来,你已经把并发、消息队列、JVM、集合选型、幂等设计全部覆盖了。面试官会认为你是一位真正在项目中解决问题的人,而不是只会背答案的候选人。
13. 总结与下一步
Java 面试场景题的核心不是“刷得越多越好”,而是把一个场景从问题出现到方案落地完整讲清楚。如果你时间有限,优先准备下面 5 个:
- 订单并发扣库存怎么保证不超卖。
- 线上 OOM 怎么排查和解决。
- 事务注解失效的原因有哪些。
- 消息队列重复消费和积压怎么处理。
- 前后端分离接口鉴权和幂等怎么设计。
接下来要做的就是行动:周末先把 JVM 排查流程在本地过一遍,再把手头项目里的并发、缓存、消息链路整理成文字。能力强不强,面试官问两个场景题就知道了。把这篇文章里每一道题都自己讲一遍,再去面试,拿 Offer 的概率会大很多。