2026 秋招的 Java 后端很多人不是死在算法题上而是死在“八股文背了但讲不透”Spring 三级缓存到底解决什么问题JVM 内存模型和线上 OOM 怎么对应MySQL 明明有索引为什么还是慢Redis 分布式锁到底锁住了什么Netty 为什么能扛住百万连接这些问题不是靠死记硬背能过的。这篇内容把 Spring、JVM、MySQL、Redis、Netty 五条主线串成一个可执行的复习框架从源码级考点到高并发架构实战按大厂面试的提问逻辑拆开讲。文章下面会给出每一块的核心知识点、高频面试题、排查思路和可落地的调优命令适合准备 2026 秋招的应届生也适合想从 CRUD 往上走一层的初中级工程师。先说明一个态度不要迷信“面试背题就能进大厂”。现在大厂面试越来越像一次技术方案评审面试官会顺着你的回答追源码、追生产事故、追系统设计取舍。所以这篇文章不是罗列题库而是帮你建立一条“原理 - 源码 - 调优 - 架构”的复习主线。1. Java 大厂面试核心能力速览先给一个全局视图。大厂 Java 后端的考察内容基本收敛成下面五条线每一条对应一个核心能力维度。复习主线核心考点考察深度实操方向Spring 生态IOC、AOP、Bean 生命周期、三级缓存、事务传播、自动装配源码级理解能画清调用链手写简化 IOC分析 Bean 创建流程JVM内存模型、类加载、垃圾收集器、OOM 排查、参数调优能根据线上症状定位问题用 jstat、jmap、Arthas 分析实例MySQL索引结构、执行计划、事务隔离、锁、MVCC、分库分表能读懂慢 SQL 并给出优化方案Explain 分析、索引设计、锁等待排查Redis数据结构、持久化、缓存穿透/击穿/雪崩、分布式锁、集群能设计一个高可用缓存方案用 SETNX 和 Redisson 实现锁并压测NettyReactor 模型、EventLoop、零拷贝、粘包拆包、编解码能讲清高并发网络通信原理搭建一个简单网关或 IM 服务原型这五条线不是孤立的。面试里最典型的一个串题场景是用户请求经过 Netty 网关打到 Spring Boot 服务服务查 Redis 缓存缓存没命中再查 MySQL过程中遇到性能瓶颈需要 JVM 调优和分库分表。这不是五道题而是一道综合题。2. Spring 源码层高频考点从 Bean 生命周期到三级缓存Spring 是 Java 面试的重头戏难点不在配置而在源码。面试官最常问的切入点有四个。2.1 Bean 的完整生命周期先说结论Bean 的创建过程不是new一下那么简单它经历了 实例化 - 属性填充 - 初始化 - 使用 - 销毁 五个大阶段每个阶段都留了扩展点。实例化构造器 - BeanNameAware / BeanFactoryAware - BeanPostProcessor#postProcessBeforeInitialization - PostConstruct - InitializingBean#afterPropertiesSet - 自定义 init-method - BeanPostProcessor#postProcessAfterInitialization - 使用 - PreDestroy - DisposableBean#destroy - 自定义 destroy-method面试时不要只背这串方法名。要能说清两件事第一BeanPostProcessor是 Spring 所有高级功能的“发动机”。AOP 代理、Autowired注入、Async异步处理都是通过不同BeanPostProcessor在 Bean 初始化前后插入逻辑实现的。第二生命周期接口和注解的执行顺序是可以从源码里验证的。建议自己写一个 Bean把每个回调方法打印出来跑一遍就知道顺序比背十遍都牢。2.2 三级缓存与循环依赖这是 Spring 面试的“顶流”问题。场景是Service public class A { Autowired private B b; } Service public class B { Autowired private A a; }A 依赖 BB 又依赖 A默认单例模式下 Spring 能正常创建。原因就是三级缓存一级缓存singletonObjects 存放完整的单例 Bean 二级缓存earlySingletonObjects 存放早期的 Bean未完成属性填充 三级缓存singletonFactories 存放 Bean 的 ObjectFactory创建 A 时先把 A 的ObjectFactory放入三级缓存然后填充属性 B创建 B 时B 又依赖 A此时从三级缓存拿到 A 的早期引用提前暴露给 BB 创建完成后A 再从缓存中获取 B 完成属性填充。这里要答出三个细节为什么需要三级缓存而不是二级因为三级缓存里放的是ObjectFactory可以在早期暴露时决定是否生成 AOP 代理对象。如果直接用二级缓存存原始对象AOP 代理的时机就会出问题。构造器注入的循环依赖无法解决因为实例化阶段就需要依赖对象。Async注解的 Bean 循环依赖通常会报错因为代理创建时机较早容易提前暴露未代理对象。2.3 AOP 与动态代理AOP 面试题的核心不是“切面怎么写”而是“JDK 动态代理和 CGLIB 有什么区别、Spring 怎么选”。// JDK 动态代理要求目标类实现接口 Proxy.newProxyInstance( classLoader, interfaces, (proxy, method, args) - method.invoke(target, args) ); // CGLIB 代理通过继承目标类生成子类 Enhancer enhancer new Enhancer(); enhancer.setSuperclass(Target.class); enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) - proxy.invokeSuper(obj, args));Spring Boot 2.x 之后默认使用 CGLIB因为很多场景下目标类没有接口而且 CGLIB 性能经过优化后已经足够。回答时还可以补一句Spring AOP 基于运行时代理只能在方法级别拦截如果需要构造器拦截或更细粒度的字节码增强需要了解 AspectJ。2.4 事务传播行为与失效场景事务传播行为是 Spring 面试里最容易被追问细节的考点。核心传播行为REQUIRED默认有事务就加入没有就新建。REQUIRES_NEW挂起当前事务新建一个独立事务。NESTED嵌套事务回滚点是保存点。SUPPORTS有事务就加入没有就以非事务执行。事务失效场景必须能脱口而出方法不是 publicSpring 事务默认基于代理private 方法无法被代理。同类内部方法调用走的是this调用不经过代理对象。异常被 catch 吞掉事务感知不到异常。抛出的是检查异常而事务默认只回滚RuntimeException。数据库引擎不支持事务比如 MyISAM。建议自己写一个“同类调用事务失效”的 Demo打断点看事务是否提交比背列表有效。3. JVM 内存模型与生产级调优实战JVM 考察的不是背参数而是“线上出了问题你怎么办”。要建立一条症状到根因的分析链路。3.1 运行时数据区堆、栈、方法区区域存储内容异常堆对象实例、数组OutOfMemoryError: Java heap space虚拟机栈局部变量表、操作数栈、方法调用StackOverflowError元空间类元数据、字符串常量池JDK 8OutOfMemoryError: Metaspace程序计数器当前线程执行字节码行号无直接内存NIO 使用的堆外内存OutOfMemoryError重点记忆JDK 8 用元空间替代永久代字符串常量池移到堆中元空间使用本地内存默认不受-XX:MaxMetaspaceSize限制但可以手动设置上限。3.2 Java 对象创建过程对象创建不是一个new这么简单类加载检查 - 堆内存分配指针碰撞 / 空闲列表 - 内存空间初始化为零值 - 设置对象头Mark Word、类型指针 - 执行构造方法加分项是答出对象头里的Mark Word存储了锁状态、哈希码、GC 分代年龄这也是 synchronized 锁升级的基础。3.3 垃圾收集器选型大厂现在问 JVM 多会聚焦 G1 和 ZGC。Serial / Parallel年轻代回收器适合单核或吞吐优先场景。CMS老年代收集器标记-清除有并发模式失败和碎片问题JDK 9 后就处于废弃状态。G1JDK 11 默认基于 Region 的堆布局目标是在停顿时间可控的情况下兼顾吞吐量。ZGCJDK 15 引入着色指针和读屏障停顿时间在毫秒级适合超大堆场景。面试 G1 至少要答出-XX:UseG1GC、-XX:MaxGCPauseMillis控制停顿目标、-XX: InitiatingHeapOccupancyPercent控制并发标记触发阈值。3.4 JVM 调优参数模板下面是常见的启动参数模板适合大多数 Spring Boot 服务初步配置java -server \ -Xms4g \ -Xmx4g \ -XX:MetaspaceSize512m \ -XX:MaxMetaspaceSize512m \ -XX:UseG1GC \ -XX:MaxGCPauseMillis200 \ -XX:HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath/data/logs/heapdump.hprof \ -jar app.jar这里的核心是-Xms和-Xmx设置为相同值避免运行时堆扩容HeapDumpOnOutOfMemoryError必须加否则 OOM 后连排查材料都没有。3.5 OOM 排查流程线上出现 OOM按这四步走拿到堆转储文件/data/logs/heapdump.hprof。用 MAT 或 VisualVM 分析看大对象是什么、被谁引用。用jstat -gcutil pid看 GC 频率和耗时判断是否需要调整堆大小。结合业务代码定位是内存泄漏还是高并发压垮了堆。排查命令示例# 查看进程 GC 情况 jstat -gcutil 12345 1000 10 # 查看堆内存分配 jmap -heap 12345 # 导出堆转储文件服务可能停顿谨慎使用 jmap -dump:formatb,fileheap.hprof 12345Arthas 也是大厂常用工具可以用dashboard命令实时查看线程、内存、GC用heapdump命令在线导出堆。能熟练用这些工具的候选人面试官会默认你有生产环境排查经验。4. MySQL 索引、事务与 SQL 优化实战MySQL 的考察重点是“为什么慢、怎么优化、底层原理是什么”。面试官不会只问索引是什么。4.1 InnoDB 为什么用 B 树B 树的核心优势是三层可以支撑千万级数据并且叶子节点形成有序链表适合范围查询。回答时和 B 树对比B 树的数据全部在叶子节点非叶子节点只存索引键所以单节点能存更多索引树更矮。叶子节点有双向指针范围查询不需要中序遍历。InnoDB 的主键索引就是聚簇索引叶子节点保存整行数据普通索引的叶子节点保存主键值这就是回表的原因。记住一个计算方式假设一页 16KB主键是 bigint 占 8 字节大约能存 16KB / (8 6) 约 1000 个键三层 B 树大约能存 2000 万行数据。这个数字能证明你真正理解 B 树的结构。4.2 Explain 执行计划遇到慢 SQL 第一件事就是EXPLAIN。关键字段必须能解释字段关注点type从好到差const eq_ref ref range index ALLkey实际使用到的索引rows预估扫描行数越小越好ExtraUsing index 覆盖索引Using filesort 需要优化Using temporary 需要优化一个典型的优化过程-- 慢 SQL按 create_time 排序分页 EXPLAIN SELECT id, name, create_time FROM t_order WHERE user_id 100 ORDER BY create_time DESC LIMIT 10;如果Extra出现Using filesort常见方案是建联合索引ALTER TABLE t_order ADD INDEX idx_user_id_create_time (user_id, create_time);这样user_id等值过滤create_time已经有顺序排序过程就能省掉。4.3 事务隔离级别与 MVCCMySQL 默认隔离级别是REPEATABLE READ但 InnoDB 通过 MVCC 和 Next-Key Lock 解决了大部分幻读问题。读已提交每次 SELECT 都生成新的 ReadView。可重复读事务第一次 SELECT 生成 ReadView后续复用保证快照读一致性。当前读SELECT ... FOR UPDATE、UPDATE、DELETE是当前读读取最新已提交版本。面试追问“可重复读下还有幻读吗”时要答快照读不会幻读但当前读在极端条件下仍可能出现幻读除非用SERIALIZABLE。4.4 锁机制行锁、间隙锁、Next-Key LockInnoDB 的锁不只是一个“行锁”概念Record Lock锁单条记录。Gap Lock锁间隙防止其他事务在间隙插入数据。Next-Key Lock左开右闭区间(10, 20]是 RR 隔离级别下解决幻读的核心。高频面试题是SELECT * FROM t WHERE id 10 AND id 20 FOR UPDATE会锁什么答案不只是[10, 20]的记录还有对应的间隙避免并发插入id15的数据。这是订单、库存类系统防止超卖的关键机制。4.5 大表优化索引外有哪些思路覆盖索引把查询列都放入索引避免回表。读写分离主库写、从库读注意主从延迟问题。分库分表按user_id哈希或范围拆分分表键必须从查询条件出发反推。冷热分离历史订单归档到冷表或数仓减少热表数据量。分区表适合按时间归档的场景但分区不是万能药查询条件不带分区键还是全分区扫描。分库分表面试要讲取舍ShardingSphere、MyCat 怎么选分布式 ID 用雪花算法全局表广播分页排序要把多个分片结果归并。这些都是架构题的高频延伸。5. Redis 核心机制与高并发缓存架构Redis 面试题已经不再是“五种数据结构是什么”而是和业务场景强绑定。5.1 数据结构背后的底层实现StringSDS 动态字符串。Hash元素少时用 ziplist超过阈值转 hashtable。Listquicklist 结构两端操作复杂度 O(1)。Set整数集合或 hashtable。ZSet跳表 哈希表跳表支持范围查询。常见场景映射ZSet 做排行榜、Set 做去重和抽奖、List 做简单消息队列、String 做分布式锁和计数器、Hash 存对象属性。5.2 持久化RDB、AOF 与混合持久化RDB内存快照文件小恢复快但可能丢数据。AOF追加日志数据更安全但文件大重放慢。Redis 4.0 之后默认开启混合持久化AOF 重写时同时写 RDB 头和增量 AOF 日志。面试追问主进程 fork 子进程生成 RDB用的是写时复制技术fork 瞬间会阻塞主进程大实例要注意 fork 耗时。这也是为什么 Redis 实例不建议放太大内存的原因之一。5.3 缓存穿透、击穿、雪崩这是 Redis 面试的必考题不能只背概念要给出可执行方案问题现象解决方案缓存穿透查一个不存在的 key每次都打到数据库布隆过滤器拦截缓存空值并设置短过期时间缓存击穿某个热点 key 过期瞬间大量请求打到数据库互斥锁重建缓存逻辑过期缓存雪崩大量 key 同一时间过期或 Redis 宕机过期时间加随机值搭建主从或哨兵高可用加分回答是热点 key 可以使用本地缓存 Redis 分布式缓存的双级缓存架构比如 Caffeine Redis本地缓存挡住大部分热点请求Redis 负责多实例间的一致性。5.4 Redis 分布式锁的实现与细节先写最简单的基于单机 Redis 的 SETNXSET lock_key unique_value NX PX 30000重点是两个细节NX保证只有在 key 不存在时才能设置成功。PX设置过期时间防止持有锁的线程挂掉导致死锁。value必须是唯一标识例如 UUID保证释放锁时只能删除自己持有的锁。释放锁不能简单用 DEL要用 Lua 脚本保证原子性if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end生产环境更推荐 RedissonRLock lock redissonClient.getLock(order:1001); try { if (lock.tryLock(3, 30, TimeUnit.SECONDS)) { // 处理业务 } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } }Redisson 的看门狗机制会自动续期避免业务没执行完锁就过期。要能讲清楚这一点面试官才会认为你确实在项目里用过。5.5 Redis 高可用主从、哨兵、Cluster主从复制异步复制主库写、从库读。哨兵监控主节点状态发生故障时自动切换。Cluster分片存储16384 个哈希槽每个节点负责一部分槽位。面试高频Cluster 为什么不支持多 key 操作因为 key 会通过 CRC16 算法映射到不同槽位跨槽位操作需要额外协议支持。这也是大厂经常将热点业务自建 Redis 集群而不是混用公共集群的原因。6. Netty 与高并发网络编程Netty 在很多 Java 后端项目里充当底层通信框架面试问它的目的在于考察候选人对高并发网络模型的理解。6.1 从 BIO、NIO 到 Reactor 模型BIO一个连接一个线程线程数不够时立刻出现拒绝服务。NIOSelector 多路复用一个线程管理多个连接。Netty基于主从 Reactor 模型BossEventLoopGroup负责接受连接WorkerEventLoopGroup负责处理读写事件。EventLoopGroup bossGroup new NioEventLoopGroup(1); EventLoopGroup workerGroup new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()); ServerBootstrap bootstrap new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializerSocketChannel() { Override protected void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new LengthFieldBasedFrameDecoder(...)) .addLast(new StringDecoder()) .addLast(new ServerHandler()); } }); ChannelFuture future bootstrap.bind(8080).sync();回答要点EventLoop一个线程绑定多个 ChannelChannel 上的耗时操作不能阻塞 EventLoop否则会拖累整个线程上的其他连接。这就是为什么业务处理要丢到独立线程池执行。6.2 零拷贝Netty 零拷贝和操作系统零拷贝是两个层次操作系统层面sendfile、mmap减少用户态和内核态之间的数据拷贝。Netty 层面CompositeByteBuf组合多个 ByteBuf避免拼接拷贝FileRegion直接利用sendfile发送文件。通俗说法一条数据从文件到网卡原来经内核读缓冲 - 用户缓冲 - 内核 socket 缓冲 - 网卡零拷贝直接在内核态完成文件到 socket 的传输。6.3 粘包拆包与编解码TCP 是字节流协议没有消息边界所以应用层必须处理粘包拆包。Netty 内置解决方式LineBasedFrameDecoder按换行符拆包。DelimiterBasedFrameDecoder按自定义分隔符拆包。FixedLengthFrameDecoder按固定长度拆包。LengthFieldBasedFrameDecoder在消息头中写入长度字段最通用。生产项目里主流做法是自定义二进制协议消息头包含魔数、版本、序列化方式、长度字段。手写协议时还要考虑大端小端、半包处理、粘包合并。能把这个流程讲清楚Netty 这关基本就过了。6.4 Netty 在高并发系统中的应用Netty 可以用来实现 API 网关、IM 长连接服务、RPC 框架通信层、游戏服务器。比如一个 IM 服务客户端通过 Netty 维持长连接消息通过 ZSet 或 MQ 做离线消息存储多机部署时用 Redis Pub/Sub 或 MQ 广播在线状态。这种设计题要能串起来讲。7. 高并发架构设计与分布式系统进阶到了这一层面试题已经从“知识点”变成“设计题”。常见分类是缓存一致性、异步削峰、分布式事务、限流。7.1 缓存与数据库一致性推荐 Cache Aside 模式读的时候先读缓存缓存未命中再读数据库然后写缓存写的时候先更新数据库再删除缓存。为什么是“删除缓存”而不是“更新缓存”因为写操作频繁时更新缓存会造成大量无意义写入而且并发更新时后写覆盖先写缓存和数据库容易不一致。删除缓存后下次读请求会重新加载。缓存删除失败怎么办可以引入“延迟双删”更新数据库后先删缓存休眠几百毫秒再删一次。更可靠的做法是通过 Binlog 订阅比如 Canal 监听 MySQL Binlog异步构建缓存。7.2 异步化与消息队列高并发系统里MQ 的核心价值是削峰填谷、异步解耦。比如秒杀系统先经过 Redis 库存预扣再把创建订单的消息发给 MQ下游订单服务异步消费。MQ 面试必问的如何保证消息不丢失生产者确认机制失败重试。Broker持久化刷盘机制。消费者手动 ACK处理成功后再确认。还有消息重复消费和顺序消费消费端做幂等唯一订单号、Redis SETNX、数据库唯一索引顺序消息需要把同一个业务 key 发送到同一个队列单消费者消费。7.3 分布式事务分布式事务是一个典型的“取舍”问题不是只有最终一致性一种解法。方案原理适用场景2PC两阶段提交强一致性性能差单写多读、银行转账类TCCTry - Confirm - Cancel业务侵入大订单、库存等强一致性场景本地消息表业务表和消息表同库事务异步投递最终一致性场景Saga长事务拆成多个本地事务失败反向补偿跨服务长流程面试时不要宣称“我用了 2PC 就保证强一致”要主动讲出 2PC 的协调者单点和阻塞问题以及对业务的侵入。能讲出方案之间的 trade-off比列方案名更有说服力。7.4 限流算法与实现固定窗口实现简单但存在窗口边界突发。滑动窗口把时间切分为小格子解决边界问题。漏桶匀速流出适合保护下游。令牌桶允许一定突发流量常见实现是 Guava RateLimiter。生产环境的限流通常是多层Nginx 层限 IP 连接数网关层限接口 QPS业务层用 Redis 分布式限流单机又用 Guava 限流。要能说明为什么要分层因为单靠一层挡不住所有场景。7.5 系统设计题的回答框架遇到“设计一个秒杀系统”“设计一个短链接系统”“设计一个消息推送系统”不要马上写代码。按四步走需求分析QPS、数据规模、一致性要求、可用性要求。架构拆分入口流量怎么挡业务模块怎么拆数据怎么存储。关键链路缓存、MQ、分库分表、分布式锁在哪个节点起作用。风险排查超卖怎么办消息积压怎么办缓存雪崩怎么办。面试官要的是你的思考路径不是唯一正确答案。8. 大厂面试轮次考察重点与项目讲解模板8.1 技术面试四个轮次的重心阶段考察重点准备重心笔试/机试LeetCode 中等题为主考察代码基本功链表、二叉树、动态规划、BFS/DFS技术一面基础八股文 简单场景题Spring、MySQL、JVM、Redis 全覆盖技术二面源码深度 项目细节 设计题深挖一个源码点准备系统设计技术三面/交叉面架构能力、工程素养、沟通表达从需求到上线的完整链路讲述8.2 项目讲解的 STAR 结构不要只讲“我做了个商城系统”。项目讲述要按这个结构背景系统面临什么业务问题为什么需要这个方案。难点高并发、数据一致性、性能瓶颈的量化描述。方案技术选型为什么选 A 不选 B。效果用数据说话比如接口 QPS 从 200 提升到 2000库存超卖率降为 0。一个亮点项目的标准是面试官听完能顺藤摸瓜问出十道技术题而你能闭环。8.3 简历怎么写每个项目写清楚技术水平不要用“熟悉 Java”这种空话。量化指标优先QPS、TP99 延迟、数据量级、GC 停顿时间。技术亮点单独列出来比如“基于 Redisson 实现分布式锁解决秒杀扣减库存的重复下单问题压测下超卖率为 0”。9. 高频面试题自测与常见问题排查9.1 高频面试题自测清单下面这些题如果答不出完整链条说明对应的主线还没吃透方向自测题SpringBean 的完整生命周期是什么三级缓存为什么是三级事务失效有哪些场景JVM对象创建过程是什么G1 和 CMS 的区别OOM 时怎么排查MySQLB 树和 B 树的区别Explain 中 type 有哪些类型RR 隔离级别下如何解决幻读RedisAOF 和 RDB 怎么选缓存击穿和雪崩分别怎么解决Redisson 看门狗原理Netty为什么 Netty 能支持高并发粘包拆包怎么解决零拷贝是什么架构如何设计一个秒杀系统怎么保证消息不丢失分布式事务有哪些方案9.2 复习中常见的问题与调整方案问题现象可能原因调整方案八股文背了但面试答不深只记结论没看源码每个核心知识点再看一篇源码解析跑一个 Demo 验证源码看不进去直接看 Spring 全量源码太大先看一个类如 DefaultListableBeanFactory从 getBean 方法切入项目讲不出来项目技术点没有整理成文档按 STAR 结构重新写项目稿列清每个模块的难点和方案系统设计题没思路缺少架构知识框架从缓存、MQ、分库分表、限流、分布式事务五个维度搭建设计模板调优无从下手只看理论没有实战验证在本地用 JDK 自带工具 jstat、jmap 分析一个内存增长的服务进入 2026 秋招前建议给自己定一个两周冲刺计划第一周围绕 Spring MySQL 过基础题第二周重点攻 JVM 调优 Redis 缓存架构 Netty 高并发项目讲稿每天改一版最后留两到三天做系统设计题的模拟输出。面试本身也是一次技术复盘。每次面完把答不出来的问题记下来回到源码和文档里查清楚比盲目刷题效率高得多。这条复习主线跑完你会发现原本零散的知识点能被一张“请求到存储”的链路图串起来这才是从 Java 面试到架构实战的真实跨越。