Java面试应对思路和题库

0. 阅读指南

这篇文章适合谁?

  • ✅ 目标读者:准备 Java 后端面试的同学(校招 / 实习 / 社招初中级)

  • ✅ 适用轮次:一面(基础与理解)/ 二面(原理+场景)/ 三面(项目与取舍)

你应该怎么用它?

① 面试前 1 天:速背路线(30~60 分钟)

按高频顺序刷:

  1. Java 基础速背清单

  2. 集合(HashMap 必背)

  3. 并发(线程池+JMM 必背)

  4. JVM(内存结构+GC)

  5. Spring(IOC/AOP/事务失效)

  6. MySQL(索引+事务隔离+锁)

  7. Redis(缓存三兄弟+分布式锁)

  8. MQ(可靠性+幂等)

目标:把每章的"✅背诵版"都过一遍,确保能说出口。

② 面试前 3 小时:补短板路线(20~30 分钟)

  • 只看你最弱的两章:比如 JVM + MySQL

  • 每题只看:✅背诵版 + 🔍追问点 + ⚠️易错点

③ 面试进行中:快速定位(像查字典)

你被问到某个点时:

  • 先用 ✅背诵版讲结论(10~20 秒)

  • 再用 🧠展开版补原理/过程(30~60 秒)

  • 最后主动带一句 🔍追问点(表现"我知道你还想问什么")

题目标记说明

  • ⭐ 高频必背(80% 会问)

  • ✅ 背诵版(10~20 秒回答)

  • 🧠 展开版(1~2 分钟回答)

  • 🔍 追问点(面试官可能继续问)

  • ⚠️ 易错点(最容易翻车的坑)

  • 💡 加分点(说出来拉开差距)

  • 🧪 场景题(结合项目更稳)

回答问题的"黄金结构"(万能模板)

任何技术题都按这 4 句走,基本不会乱:

  1. 一句话定义/结论(先让对方放心)

  2. 原理/机制(说明你理解而不是背)

  3. 对比/取舍(说明你能做工程决策)

  4. 落地场景/坑点(说明你打过仗)


1. 面试准备篇

这一章的目标:让你开局稳、表达清晰、抗追问,不靠"临场灵感"。


1.1 30 秒 / 60 秒自我介绍模板

✅ 30 秒(适合一面开场)

模板

  • 我主要做 Java 后端开发 ,熟悉 Spring Boot / MyBatis / MySQL / Redis 等常用技术栈。

  • 最近重点在 **(高频方向:并发、缓存、数据库优化、分布式治理)**上做系统学习和实践。

  • 我希望应聘的岗位是 Java 后端开发,期待在 **(业务方向:电商/平台/中台/工具系统)**中负责核心功能开发与性能稳定性优化。

✅ 60 秒(适合二面/三面)

比 30 秒多两块:成果 + 能力特长

  • 我主要做 Java 后端开发,技术栈以 Spring Boot 为主,配合 MyBatis、MySQL、Redis,以及常用的中间件。

  • 我更擅长把需求拆成可落地的模块,关注接口设计、数据模型、异常兜底与日志可观测性。

  • 在项目中我做过:(举 2 个能力标签)

    1. 性能:慢 SQL 排查、索引优化、缓存策略

    2. 稳定性:线程池治理、限流降级、幂等与重试

  • 目前我也在系统整理面试知识体系,希望加入团队后能快速上手并承担核心模块。

🔍 追问点(面试官常问):

  • 你最熟的模块是什么?

  • 你做过的性能/稳定性优化有没有指标?

⚠️ 易错点:

  • 不要讲经历流水账;不要背"技术名词列表"。要讲"你会用它做什么"。

1.2 项目介绍的通用模板(1 分钟讲清一个项目)

✅ 背诵版结构(推荐你每个项目都按这个说):

  1. 背景:这个项目解决什么业务问题?谁在用?

  2. 你的角色:你负责哪些模块?承担什么责任?

  3. 技术方案:核心架构/技术点(Spring、MySQL、Redis、MQ 等)

  4. 难点与取舍:你遇到的最大问题 + 你怎么解决

  5. 结果:上线效果/性能/稳定性/交付质量(尽量量化)

🧠 示例话术(通用版本):

  • 这是一个面向(用户/业务)的系统,核心是(核心链路:下单/签发/调度/审批等)。

  • 我负责(模块A、模块B),主要做接口设计、数据库表结构、缓存、异常兜底和日志追踪。

  • 方案上我用(Spring Boot + MyBatis + MySQL + Redis + MQ),其中(某一块)是核心。

  • 难点是(高并发/一致性/幂等/慢 SQL/链路追踪),我通过(方案)解决,并做了(监控/压测/回归)。

  • 最后效果是(延迟下降/吞吐提升/错误率降低/交付周期缩短)。


1.3 常见追问题的"通用回答策略"

Q:你最擅长什么?

  • ✅ 回答模板:

    "我最擅长把需求落到可维护的后端实现,尤其是 接口设计 + 数据库建模 + 缓存与性能优化。如果要举例,我经常用慢 SQL 分析、索引优化和缓存策略来提升核心链路性能。"

Q:你遇到过线上问题吗?怎么排查?

  • ✅ 回答模板:

    "我一般按 现象→定位→验证→修复→复盘 来排查:

    先看监控/日志定位接口与时间窗口,再看链路追踪,结合 DB 慢查询和线程 dump 验证原因,修复后补充告警与回归测试。"

Q:你怎么看待加班/压力?

  • ✅ 回答模板:

    "我能接受阶段性冲刺,但我更倾向用工程化手段减少无效加班,比如提前做监控告警、自动化测试、灰度发布和可回滚方案。"

⚠️ 易错点:

  • 不要情绪化;回答要"职业化 + 工程化"。

1.4 面试表达:如何把"背的答案"说得像"懂了"

✅ 你每题都可以套用这句:

  • "先给结论:......"

  • "原理是:......(一句话)"

  • "工程上要注意:......(坑点/边界)"

  • "如果在项目里,我一般会:......(落地)"

💡 加分技巧:主动说出一个追问点

比如回答完线程池,你补一句:

"如果你继续问线程池大小怎么设置,我会按 CPU/IO 类型和压测指标来定。"


1.5 反问面试官(强烈建议准备 6 个)

✅ 一面反问(偏岗位与技术栈)

  1. 这个岗位负责的核心业务链路是什么?

  2. 项目当前最大的技术痛点是什么?性能、稳定性还是迭代效率?

  3. 团队现在用哪些技术栈(Spring Cloud / MQ / Redis / 监控)?

  4. 新人进入后 1~2 个月最主要的交付目标是什么?

✅ 二面/三面反问(偏成长与协作)

  1. 团队对工程质量的标准是什么?(代码规范、测试覆盖、上线流程)

  2. 这个岗位的成长路径通常是什么?(业务深耕/技术专项/带人)

⚠️ 易错点:

  • 不要问"你们加班多吗";换成"你们如何保障交付节奏与工程质量"。

1.6 面试复盘模板(面试结束 10 分钟内写完)

复盘写得好,你每面都在进步。

A. 被问到的题目清单

  • Java:

  • 并发:

  • Spring:

  • MySQL:

  • Redis:

  • 场景题:

B. 我答得不好的点(原因)

  • 知识点不完整 / 说不清原理 / 没有落地案例 / 表达结构乱

C. 下次改进动作(可执行)

  • 把(某题)补成:结论 + 原理 + 追问

  • 写 1 次模拟回答(录音 1 分钟)

  • 做 1 次复盘笔记(加入题库)


2. Java 基础

2.1 面向对象与核心概念

Q1:Java 三大特性是什么?怎么理解?

  • ✅ 背诵版:封装 把数据和行为包起来;继承 复用与扩展;多态同一接口不同实现,运行时决定具体方法。

  • 🧠 展开版:

    • 封装:private + getter/setter,隐藏实现细节,减少耦合

    • 继承:is-a 关系,复用父类逻辑,但会带来强耦合

    • 多态:父类引用指向子类对象,编译看左边、运行看右边

  • 🔍 追问点:重载 vs 重写?多态的前提?接口多态怎么体现?

  • ⚠️ 易错点:多态不是"变量也会变",只有方法调用是动态绑定;字段访问看引用类型。


Q2:重载(Overload)和重写(Override)区别?

  • ✅ 背诵版:重载同名不同参(编译期决定);重写子类改父类方法(运行期动态绑定)。

  • 🧠 展开版:

    • 重载:方法名相同,参数列表不同;返回值不同不算重载

    • 重写:方法签名一致;访问权限不能更严格;异常范围不能更大

  • 🔍 追问点:@Override 有什么用?静态方法能重写吗?

  • ⚠️ 易错点:static 方法是隐藏(hide)不是重写


Q3:抽象类 vs 接口怎么选?

  • ✅ 背诵版:抽象类更像"模板/半成品";接口更像"能力/规范",支持多实现。

  • 🧠 展开版:

    • 抽象类:可以有成员变量、构造方法、普通方法;单继承

    • 接口:面向能力;Java8+ 有 default/static 方法;多实现

  • 🔍 追问点:接口 default 方法的冲突怎么解决?

  • ⚠️ 易错点:接口也能有静态方法,但不是"对象调用"。


Q4:thissuper 的区别?

  • ✅ 背诵版:this 指当前对象;super 访问父类成员/构造。

  • 🧠 展开版:super() 必须在构造第一行;若不写默认调用父类无参构造。

  • 🔍 追问点:父类没有无参构造怎么办?

  • ⚠️ 易错点:父类没无参构造且你没显式 super(xxx) 会编译失败。


2.2 基本数据类型与包装类

Q5:Java 基本类型有哪些?各占多少字节?

  • ✅ 背诵版:byte1、short2、int4、long8、float4、double8、char2、boolean(大小与JVM实现相关,常见按1字节处理)。

  • 🧠 展开版:整数默认是 int;浮点默认 double;char 是 UTF-16 code unit。

  • 🔍 追问点:int 最大值多少?为什么 0.1+0.2!=0.3

  • ⚠️ 易错点:浮点比较不要用 ==,用误差范围或 BigDecimal。


Q6:装箱/拆箱是什么?有什么坑?

  • ✅ 背诵版:基本类型与包装类互转;可能触发 NPE、性能开销和 == 判断陷阱。

  • 🧠 展开版:

    • Integer a = 1 是装箱;int b = a 是拆箱

    • 拆箱时 a 为 null → NPE

    • 包装类缓存:Integer 默认缓存 -128~127

  • 🔍 追问点:Integer i1=127; i2=127; i1==i2?128 呢?

  • ⚠️ 易错点:比较包装类用 equals,别用 ==(除非你明确比较引用)。


Q7:==equals() 区别?

  • ✅ 背诵版:== 比引用/基本值;equals 默认也比引用,通常被重写为比内容。

  • 🧠 展开版:String/包装类/集合都重写了 equals,按内容判断。

  • 🔍 追问点:为什么重写 equals 必须重写 hashCode?

  • ⚠️ 易错点:equals 对称性、传递性要满足,否则集合行为异常。


2.3 String 与常用类(高频中的高频)

Q8:String 为什么不可变?好处是什么?

  • ✅ 背诵版:String 内部字符数组不可改;好处:线程安全、可缓存(常量池)、可做 HashMap key。

  • 🧠 展开版:不可变让 hashCode 可缓存,作为 key 更稳定;也能提升安全性(如 URL、文件路径)。

  • 🔍 追问点:String 的 hashCode 怎么算?为什么适合当 key?

  • ⚠️ 易错点:不可变不代表"没有新对象",拼接会创建新对象。


Q9:StringBuilder vs StringBuffer vs String?

  • ✅ 背诵版:String 不可变;Builder 可变非线程安全更快;Buffer 线程安全但更慢。

  • 🧠 展开版:循环拼接用 Builder;多线程共享才考虑 Buffer(现在更多用并发控制而不是 Buffer)。

  • 🔍 追问点:+ 拼接编译器会怎么优化?

  • ⚠️ 易错点:循环里 str = str + x 会产生大量临时对象。


Q10:什么是字符串常量池?new String("a") 创建几个对象?

  • ✅ 背诵版:常量池存字面量;new String("a") 至少创建 1 个堆对象,常量池没有则再放入 1 个字面量对象。

  • 🧠 展开版:字面量 "a" 在常量池;new 一定在堆上。

  • 🔍 追问点:intern() 做了什么?

  • ⚠️ 易错点:不同 JDK 版本对 intern 行为细节有差异,但核心是"指向池中引用"。


2.4 Object 通用方法:equals / hashCode / toString

Q11:为什么重写 equals 必须重写 hashCode?

  • ✅ 背诵版:HashMap/HashSet 先用 hashCode 定桶,再用 equals 精确比较;不一致会导致"明明相等却查不到/去重失败"。

  • 🧠 展开版:契约:若 a.equals(b) 为 true,则 a.hashCode()==b.hashCode() 必须成立。

  • 🔍 追问点:hashCode 相同 equals 一定相同吗?

  • ⚠️ 易错点:hash 冲突是允许的,所以还要 equals 二次比较。


Q12:Comparable 和 Comparator 区别?

  • ✅ 背诵版:Comparable 是类"自然顺序";Comparator 是"外部定制规则"。

  • 🧠 展开版:一个类只能有一个自然顺序,但可以有多个 Comparator。

  • 🔍 追问点:TreeMap/TreeSet 用哪个?

  • ⚠️ 易错点:比较器实现要满足一致性,否则 TreeSet 可能丢元素。


2.5 关键字与类加载相关

Q13:final 用法和含义?

  • ✅ 背诵版:final 修饰类不可继承,方法不可重写,变量不可重新赋值(引用不可变、对象可变)。

  • 🧠 展开版:final 引用指向不变,但对象内部字段仍可改。

  • 🔍 追问点:final 能提高性能吗?

  • ⚠️ 易错点:不要误解为"对象完全不可变"。


Q14:static 的特点?

  • ✅ 背诵版:static 属于类,不属于对象;类加载时初始化一次。

  • 🧠 展开版:静态变量/方法共享;静态代码块在类初始化阶段执行。

  • 🔍 追问点:静态内部类的使用场景?

  • ⚠️ 易错点:静态方法不能直接访问实例成员(没有 this)。


Q15:类加载过程是怎样的?

  • ✅ 背诵版:加载→验证→准备→解析→初始化;初始化执行 <clinit>(静态变量赋值/静态块)。

  • 🧠 展开版:双亲委派保证核心类不被随意替换。

  • 🔍 追问点:什么时候触发类初始化?

  • ⚠️ 易错点:Class.forName() 会触发初始化;ClassLoader.loadClass() 默认不初始化(看实现)。


2.6 异常体系(非常常问)

Q16:Error 和 Exception 区别?

  • ✅ 背诵版:Error 多为 JVM/系统级错误(如 OOM)不建议捕获;Exception 是程序可处理异常。

  • 🧠 展开版:Exception 分为 checked(必须处理)和 unchecked(RuntimeException)。

  • 🔍 追问点:常见 RuntimeException 有哪些?

  • ⚠️ 易错点:不要用大而全的 catch (Exception e) 吞异常不处理。


Q17:finally 一定会执行吗?

  • ✅ 背诵版:通常会执行;但遇到 System.exit()、JVM 崩溃、线程被强杀等可能不执行。

  • 🧠 展开版:return 在 try/catch 中执行前,会先执行 finally,再返回。

  • 🔍 追问点:finally 里 return 会怎样?

  • ⚠️ 易错点:finally 里 return 会覆盖 try 的 return,强烈不建议。


Q18:throw 和 throws 区别?

  • ✅ 背诵版:throw 抛出异常对象;throws 声明可能抛出的异常类型。

  • 🧠 展开版:throws 多用于 checked 异常向上抛。

  • 🔍 追问点:自定义异常怎么写?

  • ⚠️ 易错点:自定义 RuntimeException 更常见(不强制捕获)。


2.7 泛型

Q19:什么是泛型?解决什么问题?

  • ✅ 背诵版:泛型让类型参数化,编译期类型检查,减少强转,提升安全性。

  • 🧠 展开版:核心:List<String> 在编译期检查,运行期擦除为 List

  • 🔍 追问点:什么是类型擦除?有什么影响?

  • ⚠️ 易错点:运行期拿不到 T 的真实类型(常用反射 + Type 解决)。


Q20:? extends? super 怎么用?

  • ✅ 背诵版:extends 适合"读";super 适合"写"。(PECS:Producer Extends, Consumer Super)

  • 🧠 展开版:List<? extends Number> 不能安全 add;List<? super Integer> 能 add Integer。

  • 🔍 追问点:为什么 extends 不能 add?

  • ⚠️ 易错点:? 不是 Object,它是"未知类型"。


2.8 反射与注解(框架题铺垫)

Q21:反射是什么?有什么优缺点?

  • ✅ 背诵版:运行期获取类信息并操作;优点灵活(框架);缺点性能开销、破坏封装、安全风险。

  • 🧠 展开版:Spring 的依赖注入、注解解析都基于反射。

  • 🔍 追问点:反射拿 Method/Field 的流程?

  • ⚠️ 易错点:setAccessible(true) 可能受安全策略限制。


Q22:注解的 RetentionPolicy 有哪些?区别?

  • ✅ 背诵版:SOURCE(编译丢弃)、CLASS(进 class 但运行不可见)、RUNTIME(运行可反射读取)。

  • 🧠 展开版:框架注解通常要 RUNTIME 才能生效。

  • 🔍 追问点:@Target 有哪些值?

  • ⚠️ 易错点:Retention 选错会导致"注解读不到"。


2.9 IO / NIO

Q23:BIO / NIO 区别?

  • ✅ 背诵版:BIO 阻塞、一个连接一个线程;NIO 非阻塞、Selector 轮询,一个线程管理多连接。

  • 🧠 展开版:NIO 用 Channel/Buffer/Selector;适合高并发网络场景。

  • 🔍 追问点:Netty 为什么快?

  • ⚠️ 易错点:NIO 不等于"零阻塞",也可能有阻塞操作(例如磁盘 IO)。


Q24:什么是序列化?有哪些方式?

  • ✅ 背诵版:把对象转字节用于存储/传输;Java Serializable、JSON、ProtoBuf 等。

  • 🧠 展开版:Java 原生序列化可读性差、版本兼容弱、性能一般;生产常用 JSON/ProtoBuf。

  • 🔍 追问点:serialVersionUID 作用?

  • ⚠️ 易错点:字段变更可能反序列化失败或产生兼容问题。


2.10 Java 8+ 常考特性

Q25:Lambda 的本质是什么?

  • ✅ 背诵版:Lambda 是函数式接口的实例(只有一个抽象方法的接口)。

  • 🧠 展开版:常见函数式接口:Supplier/Consumer/Function/Predicate。

  • 🔍 追问点:方法引用 :: 属于什么语法糖?

  • ⚠️ 易错点:接口里多个 default 方法没问题,但抽象方法只能一个。


Q26:Stream 和 for 循环怎么选?

  • ✅ 背诵版:Stream 更表达式、适合链式处理;for 性能可控、调试直观。

  • 🧠 展开版:并行流不一定快,取决于数据量、任务拆分成本、线程池竞争。

  • 🔍 追问点:parallelStream 的坑?

  • ⚠️ 易错点:并行流里不要做有副作用的共享写操作。


Q27:Optional 是为了解决什么?

  • ✅ 背诵版:减少 NPE,显式表达"可能为空"。

  • 🧠 展开版:链式 map/flatMap/orElseGet;但不要把 Optional 当字段类型滥用。

  • 🔍 追问点:orElse vs orElseGet

  • ⚠️ 易错点:orElse 会提前执行参数表达式,可能浪费性能。


2.11 字符集与编码

Q28:UTF-8 和 UTF-16 区别?String 用的是什么?

  • ✅ 背诵版:UTF-8 可变长(1~4字节);UTF-16 多数2字节,部分字符需代理对;String 内部按 UTF-16 语义处理(char 是 2 字节 code unit)。

  • 🧠 展开版:emoji 等可能占两个 char(代理对)。

  • 🔍 追问点:为什么 length() 不等于"字符数"?

  • ⚠️ 易错点:按字节截断字符串会乱码。


2.12 一页速背清单

  • OOP:封装/继承/多态;重载 vs 重写

  • Object:equals/hashCode 规则

  • String:不可变、常量池、Builder/Buffer

  • 包装类:缓存、拆箱 NPE、比较用 equals

  • 异常:Error/Exception/Runtime;finally 特例

  • 泛型:擦除;PECS(extends读,super写)

  • 反射/注解:Retention=RUNTIME 才能运行读到

  • IO:BIO阻塞 vs NIO多路复用

  • 编码:UTF-8/UTF-16;emoji 代理对


3. 集合(Collection / Map)

3.1 知识点速览

3.1.1 Collection vs Map

  • Collection:存"单个元素"的容器(List/Set/Queue...)

  • Map:存"键值对"的容器(HashMap/TreeMap/ConcurrentHashMap...)

3.1.2 List / Set / Map 的核心差异

类型 是否有序 是否可重复 典型实现 典型场景
List 有序(按插入) 可重复 ArrayList、LinkedList 需要顺序、可重复数据
Set 通常无序/有序视实现 不可重复 HashSet、TreeSet 去重、集合运算
Map key 去重 value 可重复 HashMap、TreeMap 通过 key 快速查 value

3.1.3 常用集合的时间复杂度

注意:复杂度和实现&是否扩容有关,这里是典型情况

| 容器 | 查询/随机访问 | 插入/删除(尾部) | 插入/删除(中间) | 备注 |

|---|---|---|---|---|

| ArrayList | O(1) | 均摊 O(1) | O(n) | 中间插入要搬移 |

| LinkedList | O(n) | O(1)(已定位节点) | O(1)(已定位) | 定位成本高 |

| HashMap | 均摊 O(1) | 均摊 O(1) | - | 取决于 hash 分布 |

| TreeMap | O(log n) | O(log n) | - | 红黑树,天然有序 |

3.1.4 fail-fast vs fail-safe(迭代器)

  • fail-fast :迭代时结构被修改会抛 ConcurrentModificationException(ArrayList、HashMap)

  • fail-safe:迭代基于"拷贝/弱一致性",不一定抛异常(CopyOnWriteArrayList、ConcurrentHashMap)


3.2 面试题库(高频)

Q1:ArrayList 和 LinkedList 区别?怎么选?

  • ✅ 背诵版:ArrayList 底层数组,随机访问快 ;LinkedList 底层双向链表,插入删除(已定位)快。大多数场景优先 ArrayList。

  • 🧠 展开版:

    • ArrayList:连续内存、cache 友好;扩容复制有成本

    • LinkedList:节点对象多、内存占用大;定位慢(O(n))

  • 🔍 追问点:ArrayList 扩容机制是什么?

  • ⚠️ 易错点:LinkedList 只有"已定位节点"时插入删除才快,否则先 O(n) 找位置。


Q2:ArrayList 扩容机制?为什么说"均摊 O(1)"?

  • ✅ 背诵版:ArrayList 满了会扩容并复制到新数组;单次扩容成本高,但摊到多次 add 上是均摊 O(1)。

  • 🧠 展开版:

    • 扩容本质:申请更大数组 + System.arraycopy

    • 频繁扩容会很慢 → 预估容量 new ArrayList<>(cap) 是加分点

  • 🔍 追问点:扩容会带来什么问题?(性能抖动、内存峰值)

  • ⚠️ 易错点:扩容不是"每次+1",是按增长策略增长;别把扩容说成"链表追加"。


Q3:HashMap 的底层结构?put/get 过程?

  • ✅ 背诵版:JDK8 HashMap = 数组 + 链表/红黑树。put:算 hash→定位桶→冲突则链表/树查找→必要时扩容;get:同样算 hash→定位桶→在链表/树中查 key。

  • 🧠 展开版:

    • hash:对 key 的 hashCode 做扰动,减少冲突

    • 桶下冲突:链表(少量)或红黑树(冲突多)

    • 负载因子:默认 0.75,平衡空间与冲突

  • 🔍 追问点:

    • 为什么要扰动 hash?

    • 什么时候链表转红黑树?

  • ⚠️ 易错点:HashMap 查找不是"遍历全表",是先定位桶再查局部结构。


Q4:HashMap 为什么线程不安全?会出什么问题?

  • ✅ 背诵版:多线程同时 put/resize 会导致数据覆盖、丢失、结构异常等。并发场景用 ConcurrentHashMap。

  • 🧠 展开版:

    • 竞态:两个线程同时写同一桶,后写覆盖前写

    • 扩容期间:迁移过程被打断可能出现不一致

  • 🔍 追问点:为什么 Hashtable 慢?(全表一把锁)

  • ⚠️ 易错点:不要说成"HashMap 会死循环(JDK8 也会)"------更稳的说法是:并发下可能结构异常/数据丢失


Q5:为什么重写 equals 必须重写 hashCode?和 HashMap 有什么关系?

  • ✅ 背诵版:HashMap 先用 hashCode 定桶,再用 equals 精确比较;若 equals 相等但 hashCode 不等,会导致查不到/去重失败。

  • 🧠 展开版:契约:a.equals(b)==truea.hashCode()==b.hashCode() 必须成立。

  • 🔍 追问点:hashCode 相同 equals 一定相同吗?(不一定,可能冲突)

  • ⚠️ 易错点:把"hashCode 相同"当作"对象相同"是错的。


Q6:HashSet 底层是什么?为什么能去重?

  • ✅ 背诵版:HashSet 底层是 HashMap,元素作为 key 存储,利用 key 的 equals/hashCode 去重。

  • 🧠 展开版:value 是固定哨兵对象;去重逻辑完全复用 HashMap 的 key 规则。

  • 🔍 追问点:TreeSet 底层是什么?(TreeMap/红黑树)

  • ⚠️ 易错点:TreeSet 的"去重"依赖比较规则(compareTo/Comparator),而不是 equals。


Q7:TreeMap / TreeSet 适合什么场景?

  • ✅ 背诵版:需要有序、范围查询、按 key 排序时用 TreeMap(O(log n))。

  • 🧠 展开版:红黑树保持有序;适合 topN、区间查询、按时间/数值范围查。

  • 🔍 追问点:排序规则冲突会怎样?(compare 结果为 0 会被认为"相同 key/元素")

  • ⚠️ 易错点:Comparator 实现不一致会导致"元素丢失"。


Q8:ConcurrentHashMap 线程安全的核心思路(简答版)

  • ✅ 背诵版:通过更细粒度的同步(CAS + 局部加锁/节点锁),读多场景性能比 Hashtable 好。

  • 🧠 展开版:JDK8 的设计以桶/节点为粒度,减少全表锁竞争;读操作多数无锁。

  • 🔍 追问点:为什么 fail-safe?(弱一致性迭代)

  • ⚠️ 易错点:并发容器也会有竞争,只是比粗锁更好。


3.3 一页速背清单

  • List:ArrayList(快读)优先;LinkedList(已定位插删)

  • Map:HashMap(均摊 O1),TreeMap(有序 Ologn)

  • Set:HashSet=HashMap key 去重;TreeSet=排序去重

  • equals/hashCode 必须一起重写

  • 并发:HashMap 不安全 → 用 ConcurrentHashMap

  • 迭代:fail-fast vs fail-safe


4. 并发编程(JUC 高频面试题库)

4.1 基础概念:线程、并发与线程状态

Q1:并发(Concurrency)和并行(Parallelism)有什么区别?

  • ✅ 背诵版:并发是"同一时间段交替执行"(一个 CPU 也能实现);并行是"同一时刻同时执行"(需要多核/多CPU)。

  • 🧠 展开版:并发更强调处理多个任务的能力 ;并行更强调加速执行速度

  • 🔍 追问点:单核 CPU 能并行吗?(不能,只能并发)

  • ⚠️ 易错点:别把"多线程"直接等同于"更快",线程切换也有成本。


Q2:Java 线程的 6 种状态是什么?

  • ✅ 背诵版:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。

  • 🧠 展开版:

    • RUNNABLE:包含"正在运行"和"就绪等待 CPU"

    • BLOCKED:抢不到 synchronized 的锁

    • WAITING/TIMED_WAITING:等待 notify/超时/park 等

  • 🔍 追问点:sleep() 是什么状态?(TIMED_WAITING)

  • ⚠️ 易错点:wait()释放锁sleep() 不释放锁。


4.2 JMM 与 happens-before

Q3:什么是 JMM(Java 内存模型)?它解决什么问题?

  • ✅ 背诵版:JMM 定义了多线程下可见性、有序性、原子性的规则,保证在不同 CPU/缓存下行为一致。

  • 🧠 展开版:

    • 线程都有"工作内存"(寄存器/缓存),读写可能不直接到主内存

    • 导致:一个线程改了变量,另一个线程可能看不到(可见性问题)

    • 指令可能重排序(有序性问题)

  • 🔍 追问点:JMM 三大特性:原子性、可见性、有序性分别怎么保证?

  • ⚠️ 易错点:JMM 是"规范",不是 JVM 的某块真实内存。


Q4:什么是 happens-before?

  • ✅ 背诵版:happens-before 规定了操作之间的可见性顺序:如果 A happens-before B,那么 A 的结果对 B 可见。

  • 🧠 展开版(常背 4 条就够面试):

    1. 程序次序规则:同线程内,前面 happens-before 后面

    2. 监视器锁规则:unlock happens-before 后续对同一锁的 lock

    3. volatile 规则:写 volatile happens-before 后续读 volatile

    4. 线程启动/终止规则:start() happens-before 线程内动作;线程结束 happens-before join 返回

  • 🔍 追问点:为什么 volatile 能保证可见性和有序性?

  • ⚠️ 易错点:happens-before 不是"时间先后",是"可见性与顺序约束"。


4.3 synchronized、volatile、CAS(并发三件套)

Q5:synchronized 能解决什么问题?

  • ✅ 背诵版:synchronized 通过互斥锁保证原子性 + 可见性 + 有序性(进入/退出临界区有内存语义)。

  • 🧠 展开版:

    • 本质:对象监视器(monitor)加锁

    • 进入临界区:读取主内存最新值(可见性)

    • 退出临界区:刷新写回主内存(可见性)

  • 🔍 追问点:synchronized 修饰实例方法、静态方法、代码块锁对象分别是谁?

  • ⚠️ 易错点:

    • 锁对象不同 → 根本没互斥

    • 锁粒度太大 → 性能差


Q6:volatile 关键字有什么用?能保证原子性吗?

  • ✅ 背诵版:volatile 保证可见性禁止重排序(有序性)不保证原子性

  • 🧠 展开版:

    • 典型场景:状态标记(stop flag)、双重校验单例(配合正确写法)

    • i++ 不是原子操作:读-改-写三步

  • 🔍 追问点:volatile 适用场景?什么时候必须上锁?

  • ⚠️ 易错点:用 volatile 修 i++ 是错的,必须用锁或原子类。


Q7:CAS 是什么?有什么问题?

  • ✅ 背诵版:CAS(Compare And Swap)是"比较并交换",实现无锁原子更新;问题:ABA、自旋开销、只能保证单变量原子性。

  • 🧠 展开版:

    • CAS 常见实现:AtomicInteger 的 compareAndSet

    • ABA 解决:版本号(AtomicStampedReference / AtomicMarkableReference)

  • 🔍 追问点:什么是 ABA?举个例子?

  • ⚠️ 易错点:CAS 在竞争激烈时可能更慢(大量自旋重试)。


4.4 Lock 体系与 AQS(高频核心)

Q8:ReentrantLock 和 synchronized 的区别?

  • ✅ 背诵版:synchronized 是 JVM 层面,简单可靠;ReentrantLock 是 API 层面,更灵活(可中断、可定时、公平锁、多个条件队列)。

  • 🧠 展开版:

    • ReentrantLock:tryLock()lockInterruptibly()、可选公平锁

    • Condition:可实现多个等待队列(比 wait/notify 更灵活)

  • 🔍 追问点:什么是可重入?为什么需要可重入?

  • ⚠️ 易错点:ReentrantLock 必须在 finally 里 unlock,否则死锁。


Q9:AQS 是什么?它的核心思想?

  • ✅ 背诵版:AQS(AbstractQueuedSynchronizer)是 JUC 锁/同步器的基础框架:用一个 state 表示资源状态,用 FIFO 队列管理等待线程。

  • 🧠 展开版:

    • 独占模式:ReentrantLock

    • 共享模式:Semaphore、CountDownLatch(典型)

    • 通过 CAS 修改 state,失败就入队 park,唤醒再抢

  • 🔍 追问点:CountDownLatch 和 Semaphore 的区别?

  • ⚠️ 易错点:面试不要求背源码,但要说清:state + 队列 + CAS + park/unpark。


4.5 JUC 同步工具类(必备)

Q10:CountDownLatch / CyclicBarrier / Semaphore 区别?

  • ✅ 背诵版:

    • CountDownLatch:倒计时门闩,一次性,等 N 个任务完成再继续

    • CyclicBarrier:栅栏,可重复使用,等 N 个线程都到齐再放行

    • Semaphore:信号量,控制并发数量(限流)

  • 🧠 展开版:

    • Latch 常用于主线程等待多个子任务

    • Barrier 常用于多线程分阶段协作

    • Semaphore 常用于连接池/接口限流

  • 🔍 追问点:三者底层多基于 AQS(可点到为止)

  • ⚠️ 易错点:Latch 不可复用;Barrier 可复用但要注意 broken 状态。


4.6 并发容器与线程安全集合(必问)

Q11:ArrayList / HashMap 为什么线程不安全?

  • ✅ 背诵版:多线程下会出现竞态条件,导致数据覆盖、结构破坏、读到脏数据等问题。

  • 🧠 展开版:

    • ArrayList:扩容 + size++ 非原子

    • HashMap:并发 put 可能导致链表/树结构异常(历史上有死循环风险的经典问题)

  • 🔍 追问点:怎么替换?(CopyOnWriteArrayList、ConcurrentHashMap、Collections.synchronizedList)

  • ⚠️ 易错点:Collections.synchronizedXxx 是粗粒度锁,读多写少可能不如 COW。


Q12:ConcurrentHashMap 为什么线程安全?

  • ✅ 背诵版:通过更细粒度的同步(CAS + 局部加锁)保证并发安全,比 Hashtable 粗锁更高效。

  • 🧠 展开版:JDK8 主要是对桶/节点加锁,减少锁竞争;读操作大多无锁。

  • 🔍 追问点:为什么 Hashtable 慢?(全表一把锁)

  • ⚠️ 易错点:并发容器也不是"无敌快",写多场景照样会竞争。


4.7 线程池(面试第一大题)

Q13:为什么要用线程池?解决什么问题?

  • ✅ 背诵版:复用线程,减少频繁创建销毁成本;统一管理线程数量,避免资源耗尽;提供任务队列与拒绝策略。

  • 🧠 展开版:线程池主要解决:性能 + 稳定性 + 可控性

  • 🔍 追问点:线程池核心参数有哪些?

  • ⚠️ 易错点:不要 newCachedThreadPool() 无脑上生产,可能无限扩线程。


Q14:线程池 7 大参数是什么?(ThreadPoolExecutor)

  • ✅ 背诵版:corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。

  • 🧠 展开版(面试常问的执行流程):

    1. 任务来 → 先建到 core

    2. core 满 → 进队列

    3. 队列满 → 扩到 max

    4. max 也满 → 触发拒绝策略

  • 🔍 追问点:队列选型有什么区别?

  • ⚠️ 易错点:只会背参数不够,要能讲清"提交任务流程"。


Q15:常见阻塞队列有哪些?怎么选?

  • ✅ 背诵版:

    • ArrayBlockingQueue:数组有界

    • LinkedBlockingQueue:链表(常用,有界/无界要注意)

    • SynchronousQueue:不存任务,直接交接(常用于 cached)

    • DelayQueue:延迟任务

  • 🧠 展开版:

    • 有界队列更安全(避免 OOM),需要合理拒绝策略

    • 无界队列吞任务能力强,但可能堆积导致内存问题

  • 🔍 追问点:为什么建议用有界队列?

  • ⚠️ 易错点:LinkedBlockingQueue 默认可能很大(相当于无界),容易堆积。


Q16:拒绝策略有哪些?

  • ✅ 背诵版:

    • AbortPolicy:直接抛异常(默认)

    • CallerRunsPolicy:调用者线程执行(削峰)

    • DiscardPolicy:直接丢弃

    • DiscardOldestPolicy:丢最老任务

  • 🧠 展开版:生产中常用 CallerRuns 或自定义(记录日志/打点/降级)。

  • 🔍 追问点:你项目里怎么处理拒绝?怎么告警?

  • ⚠️ 易错点:丢任务一定要可观测(日志/监控),否则线上"静默丢单"。


Q17:线程池大小怎么设置?(面试标准答法)

  • ✅ 背诵版:看任务类型:CPU 密集型接近 CPU 核数;IO 密集型可以更大(但要压测验证)。

  • 🧠 展开版:

    • CPU 密集:Ncpu 或 Ncpu+1

    • IO 密集:可取 2*Ncpu 或基于等待/计算比例估算

    • 最终以:CPU 利用率、队列堆积、响应时间、拒绝率为准

  • 🔍 追问点:怎么做压测与监控?(队列长度、活跃线程、拒绝次数)

  • ⚠️ 易错点:线程越多不一定越快,可能上下文切换炸裂。


4.8 ThreadLocal(必问坑点)

Q18:ThreadLocal 是什么?为什么会内存泄漏?

  • ✅ 背诵版:ThreadLocal 为每个线程提供变量副本;在线程池场景如果不 remove,容易造成"脏数据/内存泄漏"。

  • 🧠 展开版:

    • ThreadLocalMap 的 key 是弱引用,但 value 是强引用

    • 线程长期不结束(线程池)→ value 可能残留

  • 🔍 追问点:怎么正确使用?(try/finally remove)

  • ⚠️ 易错点:ThreadLocal 不是"跨线程传递",它是"线程内隔离"。


4.9 常见并发问题与排查(面试加分项)

Q19:死锁怎么产生?怎么排查?

  • ✅ 背诵版:死锁四条件:互斥、占有且等待、不可剥夺、循环等待;排查用 jstack 看线程互相等待的锁。

  • 🧠 展开版:避免策略:固定加锁顺序、tryLock 超时、减少锁嵌套。

  • 🔍 追问点:线上 CPU 100% 怎么查?(top → jstack / 火焰图思路)

  • ⚠️ 易错点:不要用 sleep() 解决并发问题,那是"碰运气"。


Q20:如何保证"只执行一次"?(经典题)

  • ✅ 背诵版:用 synchronized/Lock、AtomicBoolean、或 DCL 单例(volatile + 双重校验)。

  • 🧠 展开版:

    • 简单可靠:synchronized

    • 轻量:AtomicBoolean.compareAndSet

    • 单例:DCL 必须加 volatile 防止重排序

  • 🔍 追问点:DCL 为什么要 volatile?

  • ⚠️ 易错点:不加 volatile 可能看到"半初始化对象"。


4.10 一页速背清单

  • JMM 三性:原子性/可见性/有序性

  • happens-before:锁、volatile、start/join

  • synchronized:互斥 + 内存语义

  • volatile:可见 + 禁重排,不保原子

  • CAS:无锁原子,ABA/自旋问题

  • AQS:state + 队列 + park/unpark

  • 工具类:Latch(一次)、Barrier(可复用)、Semaphore(限流)

  • 并发容器:CHM 替代 HashMap,COW 适合读多写少

  • 线程池:参数+执行流程+队列+拒绝+大小设置

  • ThreadLocal:线程池要 remove


5. JVM

5.1 知识点速览

5.1.1 JVM 内存结构(经典:运行时数据区)

  • 线程私有:程序计数器、虚拟机栈、本地方法栈

  • 线程共享:堆(Heap)、方法区(JDK8+ 常叫 Metaspace/元空间)

面试常见考点:堆=对象、栈=栈帧、方法区=类元数据;以及各种 OOM 对应哪块区域。

5.1.2 对象创建与访问(大概知道即可)

  • new 对象 → 可能 TLAB 分配 → 初始化 → 引用指向对象

  • 访问:引用指向堆对象(细节不深挖也能过)

5.1.3 GC 基本概念

  • 为什么要 GC:自动回收不可达对象

  • 怎么判断垃圾:可达性分析(GC Roots)

  • 常见算法:标记-清除、复制、标记-整理

  • 分代思想:新生代(复制)/老年代(整理/标记清除)

5.1.4 常见排查工具(加分项)

  • jps(看进程)/ jstack(线程栈)/ jmap(堆)/ jstat(GC 状态)

  • 日志:GC log(看频繁 GC、停顿)


5.2 面试题库

Q1:JVM 运行时内存区域有哪些?各自存什么?

  • ✅ 背诵版:栈存栈帧(局部变量/方法调用),堆存对象实例,方法区存类元数据;程序计数器记录执行位置。

  • 🧠 展开版:

    • 栈:每次方法调用创建栈帧(局部变量表、操作数栈、返回地址...)

    • 堆:几乎所有对象

    • 方法区/元空间:类信息、常量池、方法元数据等

  • 🔍 追问点:哪些区域线程私有?(PC/栈/本地栈)

  • ⚠️ 易错点:把"常量池"都说成在堆里不严谨------更稳:运行时常量池属于方法区逻辑范畴


Q2:对象什么时候会被 GC 回收?怎么判断"垃圾"?

  • ✅ 背诵版:不可达对象会被回收,判断用可达性分析,从 GC Roots 出发找不到的对象就是垃圾。

  • 🧠 展开版:GC Roots 常见:线程栈引用、静态引用、常量引用等(点到为止)

  • 🔍 追问点:引用类型有哪些?强/软/弱/虚各自用途?

  • ⚠️ 易错点:不要只说"引用计数",Java 主流是可达性分析(引用计数有循环引用问题)。


Q3:强/软/弱/虚引用有什么区别?常见使用场景?

  • ✅ 背诵版:

    • 强引用:默认引用,不回收

    • 软引用:内存紧张才回收(缓存)

    • 弱引用:下一次 GC 就回收(ThreadLocal key 等)

    • 虚引用:跟回收通知相关(配合 ReferenceQueue)

  • 🧠 展开版:软引用做"可回收缓存";弱引用用于避免强持有导致泄漏。

  • 🔍 追问点:ThreadLocal 为什么会"内存泄漏"?(key 弱引用、value 强引用、线程池不结束)

  • ⚠️ 易错点:软引用并不等于"永不回收"。


Q4:JVM 的垃圾回收算法有哪些?

  • ✅ 背诵版:标记-清除、复制、标记-整理;分代收集是组合策略。

  • 🧠 展开版:

    • 标记-清除:会产生碎片

    • 复制:适合新生代,速度快但需要额外空间

    • 标记-整理:适合老年代,减少碎片但开销更大

  • 🔍 追问点:为什么要分代?(对象"朝生夕死")

  • ⚠️ 易错点:别说"老年代用复制",典型是整理/标记清除类。


Q5:Minor GC / Full GC 有什么区别?

  • ✅ 背诵版:Minor GC 回收新生代;Full GC 通常回收整个堆(含老年代)以及可能的类元数据,停顿更重。

  • 🧠 展开版:Full GC 频繁通常是内存配置不合理、泄漏、晋升过快等信号。

  • 🔍 追问点:什么会触发 Full GC?(老年代不足、元空间不足等)

  • ⚠️ 易错点:不要把 Full GC 说成"只回收老年代",它通常更"全"。


Q6:常见垃圾收集器你了解哪些?

  • ✅ 背诵版:常见有 CMS、G1;它们核心目标是降低停顿、提升吞吐,选择取决于延迟与吞吐的权衡。

  • 🧠 展开版(不必背太细):

    • CMS:以低停顿为目标,但会有碎片问题

    • G1:按 Region 管理,尽量可预测停顿(更现代常用)

  • 🔍 追问点:G1 为什么叫 Garbage First?(优先回收收益最大的 Region)

  • ⚠️ 易错点:别在面试里胡报参数,只要讲清"目标/特点/适用场景"。


Q7:类加载过程是怎样的?双亲委派模型是什么?

  • ✅ 背诵版:类加载:加载→验证→准备→解析→初始化;双亲委派:优先父加载器,避免核心类被篡改、保证一致性。

  • 🧠 展开版:

    • 启动类加载器/扩展/应用类加载器(点到为止)

    • 破坏双亲委派:常见于 SPI/容器化加载(了解即可)

  • 🔍 追问点:什么时候触发类初始化?(new、static 访问、反射等)

  • ⚠️ 易错点:把"加载"和"初始化"混为一谈。


Q8:线上 OOM 常见有哪些?怎么定位?

  • ✅ 背诵版:常见 OOM:堆 OOM、元空间 OOM、线程栈 OOM;定位靠日志、堆 dump、分析引用链。

  • 🧠 展开版:

    • 堆 OOM:对象太多/泄漏/缓存无界

    • 元空间 OOM:动态生成类过多(反射/代理/脚本)

    • 栈 OOM:线程开太多或递归过深

  • 🔍 追问点:怎么拿到 dump?(OOM 时自动 dump / 手动 jmap)

  • ⚠️ 易错点:只会说"加内存"是低级回答,更好:先定位增长点与引用链


Q9:CPU 100% / 接口变慢,你会怎么排查?

  • ✅ 背诵版:先定位进程与线程,再看线程栈,结合 GC/日志/慢 SQL 判断瓶颈。

  • 🧠 展开版(标准排查套路):

    1. top / 监控:确认是哪个进程

    2. jstack:看是否死循环/死锁/大量阻塞

    3. jstat / GC log:是否频繁 GC

    4. DB/外部依赖:慢 SQL、超时重试

  • 🔍 追问点:死锁怎么查?(jstack 能看到锁等待链)

  • ⚠️ 易错点:别直接上来"重启",先定位原因再给修复方案+复盘措施。


Q10:JVM 调优你会怎么做?

  • ✅ 背诵版:调优目标先确定(吞吐/延迟),再用数据驱动:GC 日志+监控→找问题→调整参数/代码/缓存策略→压测验证。

  • 🧠 展开版:

    • 先看:GC 次数、停顿、晋升、堆使用曲线

    • 常见方向:堆大小、年轻代比例、避免频繁 Full GC、减少大对象

  • 🔍 追问点:你会关注哪些指标?(P99、GC pause、吞吐、错误率)

  • ⚠️ 易错点:背参数不如讲"方法论",参数要在"有证据"时才调整。


5.3 一页速背清单

  • 内存:栈(栈帧)/ 堆(对象)/ 方法区(类元数据)

  • 垃圾判断:可达性分析(GC Roots)

  • 算法:标记清除、复制、标记整理

  • GC:Minor(新生代)/ Full(全堆更重)

  • 常见故障:堆 OOM、元空间 OOM、线程栈 OOM

  • 排查:jps/jstack/jmap/jstat + GC log

  • 调优:先目标→看数据→再调整→压测验证


6. Spring/Spring MVC / Spring Boot

6.1 Spring 核心:IOC / DI / Bean

Q1:什么是 IOC?什么是 DI?

  • ✅ 背诵版:IOC 是把对象创建和管理交给容器;DI 是容器把依赖注入到对象里(构造注入/Setter 注入等)。

  • 🧠 展开版:

    • IOC:反转控制,业务不再 new 对象,统一由容器维护生命周期

    • DI:依赖注入是实现 IOC 的方式(通过配置/注解把依赖"注入"进来)

  • 🔍 追问点:你项目里常用哪种注入?(推荐构造注入)

  • ⚠️ 易错点:把 IOC 和 DI 当成同一个东西说也能过,但最好区分:IOC 是思想,DI 是实现手段。


Q2:Spring Bean 的生命周期(面试必问)

  • ✅ 背诵版:实例化 → 属性填充 → Aware 回调 → BeanPostProcessor 前置 → 初始化(@PostConstruct / InitializingBean)→ BPP 后置 → 使用 → 销毁(@PreDestroy / DisposableBean)。

  • 🧠 展开版(能讲清 1 分钟就够):

    1. 创建对象(构造方法)

    2. 依赖注入(populate)

    3. Aware:BeanNameAware、BeanFactoryAware...

    4. BeanPostProcessor:前置/后置(AOP 代理就常在这里发生)

    5. init:@PostConstructafterPropertiesSet、自定义 init-method

    6. destroy:@PreDestroydestroy、自定义 destroy-method

  • 🔍 追问点:AOP 代理是在生命周期哪个阶段生成的?

  • ⚠️ 易错点:只背"初始化、销毁"太虚,面试官常追问:BPP 是干什么的(扩展点!)。


Q3:Bean 的作用域有哪些?默认是什么?

  • ✅ 背诵版:默认 singleton ;还有 prototype、request、session、application(web 环境)。

  • 🧠 展开版:

    • singleton:容器内单例(不是 JVM 单例)

    • prototype:每次获取都 new 一个,不走完整销毁回调(通常)

  • 🔍 追问点:prototype 的销毁为什么容器不管?

  • ⚠️ 易错点:singleton 是"Spring 容器维度",不是"全局唯一"。


Q4:@Autowired 注入原理?按类型还是按名称?

  • ✅ 背诵版:默认按 类型 找;同类型多个时结合 @Qualifier / @Primary 决策;必要时按名称匹配。

  • 🧠 展开版:

    • 先按类型找候选 Bean

    • 如果多个候选:@Primary 优先、@Qualifier 精确指定、或字段名/参数名匹配

  • 🔍 追问点:@Resource 呢?(默认按名称)

  • ⚠️ 易错点:多实现类不处理会直接启动失败(NoUniqueBeanDefinitionException)。


6.2 循环依赖(高频难点)

Q5:Spring 如何解决循环依赖?

  • ✅ 背诵版:单例 + setter 注入 的循环依赖,Spring 通过 三级缓存(提前暴露"早期引用")解决;构造器循环依赖通常不行。

  • 🧠 展开版(面试说到这就很稳):

    • 一级缓存:成品 Bean

    • 二级缓存:早期 Bean 引用(可能是代理)

    • 三级缓存:ObjectFactory(用于生成早期引用,支持 AOP 场景)

  • 🔍 追问点:为什么构造器循环依赖解决不了?

  • ⚠️ 易错点:

    • prototype 循环依赖一般不解决

    • AOP 场景如果提前暴露不是代理可能出问题,所以需要三级缓存。


6.3 AOP(切面编程)

Q6:AOP 是什么?解决什么问题?

  • ✅ 背诵版:AOP 把"日志、事务、权限、监控"等横切逻辑从业务中剥离,通过代理在方法前后织入,降低重复代码和耦合。

  • 🧠 展开版:核心概念:切面(Aspect)、连接点(JoinPoint)、切点(Pointcut)、通知(Advice)。

  • 🔍 追问点:AOP 底层怎么实现?(动态代理)

  • ⚠️ 易错点:AOP 不是"只为了日志",最常见的是 事务监控


Q7:JDK 动态代理 vs CGLIB 代理区别?

  • ✅ 背诵版:JDK 代理基于 接口 ;CGLIB 基于 继承生成子类,没有接口也能代理。

  • 🧠 展开版:

    • JDK:更轻量,但必须有接口

    • CGLIB:可代理普通类,但 final 类/方法无法代理

  • 🔍 追问点:Spring 默认用哪个?(有接口优先 JDK,否则 CGLIB)

  • ⚠️ 易错点:final 方法不能被增强(CGLIB 也不行)。


Q8:AOP 的通知类型有哪些?

  • ✅ 背诵版:@Before、@After、@AfterReturning、@AfterThrowing、@Around。

  • 🧠 展开版:@Around 最强,可决定是否执行目标方法,也能统一处理耗时/异常。

  • 🔍 追问点:@Around 里 proceed() 不调用会怎样?

  • ⚠️ 易错点:Around 写错容易导致目标方法根本不执行。


6.4 事务

Q9:Spring 事务是怎么实现的?

  • ✅ 背诵版:基于 AOP 代理,方法调用前开启事务,成功提交,异常回滚。

  • 🧠 展开版:事务管理器(PlatformTransactionManager)+ AOP 拦截器协作完成。

  • 🔍 追问点:声明式事务 vs 编程式事务?

  • ⚠️ 易错点:事务边界是"代理方法调用",不是你以为的"代码块"。


Q10:事务传播行为有哪些?最常用的是哪个?

  • ✅ 背诵版:默认 REQUIRED(有就加入,没有就新建);常见还有 REQUIRES_NEW、NESTED。

  • 🧠 展开版:

    • REQUIRED:主流程最常用

    • REQUIRES_NEW:强制新事务(常用于"日志/审计必须落库")

    • NESTED:嵌套事务(依赖 savepoint,数据库支持相关)

  • 🔍 追问点:REQUIRES_NEW 会挂起外层事务吗?(会)

  • ⚠️ 易错点:传播行为说一堆不如把 REQUIRED / REQUIRES_NEW 讲透。


Q11:哪些异常会触发回滚?怎么自定义?

  • ✅ 背诵版:默认只回滚 RuntimeException / Error ;checked 异常默认不回滚,可用 rollbackFor 指定。

  • 🧠 展开版:@Transactional(rollbackFor = Exception.class) 可扩大回滚范围。

  • 🔍 追问点:为什么默认不回滚 checked?

  • ⚠️ 易错点:很多人以为"抛异常就回滚",其实默认不是


Q12:事务为什么会失效?

  • ✅ 背诵版(记住这 5 条基本就过):

    1. 同类内部自调用(没走代理)

    2. 方法不是 public(代理可能不生效)

    3. 异常被 catch 吃掉 / 没抛出去

    4. 回滚异常类型不对(checked 未配置 rollbackFor)

    5. 数据源/事务管理器没配对(多数据源场景)

  • 🧠 展开版:本质都是"没有被代理拦截到"或"回滚条件不满足"。

  • 🔍 追问点:怎么解决(自调用问题)?(拆到另一个 Bean、AopContext、注入自己代理等)

  • ⚠️ 易错点:最常见就是自调用,一定要会解释清楚"代理边界"。


6.5 Spring MVC(Web 请求链路必问)

Q13:Spring MVC 的执行流程?

  • ✅ 背诵版:请求 → DispatcherServlet → HandlerMapping 找 Handler → HandlerAdapter 调用 Controller → 返回 ModelAndView/ResponseBody → ViewResolver 渲染或直接写回响应。

  • 🧠 展开版:

    • DispatcherServlet 是前端控制器

    • HandlerInterceptor 在调用前后增强

    • @ResponseBody / RestController 走消息转换器(HttpMessageConverter)

  • 🔍 追问点:拦截器和过滤器区别?

  • ⚠️ 易错点:过滤器是 Servlet 规范(更底层);拦截器是 Spring 体系(能拿到 Handler)。


Q14:过滤器(Filter) vs 拦截器(Interceptor) vs AOP 区别?

  • ✅ 背诵版:

    • Filter:Servlet 层,URL 级别,最早进入

    • Interceptor:Spring MVC 层,基于 Handler

    • AOP:Spring 容器层,方法级别(Service 常用)

  • 🧠 展开版:权限/鉴权常在 Filter;登录态/统一参数校验常在 Interceptor;事务/日志常在 AOP。

  • 🔍 追问点:执行顺序?(Filter → Interceptor → Controller → AOP(方法))

  • ⚠️ 易错点:三者不是互相替代,看"层级"和"粒度"。


Q15:@RequestBody 和 @RequestParam 区别?

  • ✅ 背诵版:@RequestParam 取 query/form 参数;@RequestBody 读请求体(常用于 JSON)。

  • 🧠 展开版:@RequestBody 依赖 HttpMessageConverter(Jackson 等)。

  • 🔍 追问点:为什么有时候 @RequestBody 读不到?(Content-Type 不对)

  • ⚠️ 易错点:GET 请求一般不建议用 @RequestBody(兼容性/规范问题)。


6.6 Spring Boot(自动配置高频)

Q16:Spring Boot 为什么能"开箱即用"?

  • ✅ 背诵版:核心是 自动配置 + starter 依赖管理 + 约定优于配置

  • 🧠 展开版:

    • starter:把常用依赖"一揽子打包"

    • auto-config:根据 classpath 和配置条件加载 Bean(Conditional)

  • 🔍 追问点:自动配置是怎么生效的?(@SpringBootApplication 组合注解)

  • ⚠️ 易错点:别把 Boot 说成"替代 Spring",它是 Spring 生态的增强封装。


Q17:@SpringBootApplication 做了什么?

  • ✅ 背诵版:相当于 @Configuration + @EnableAutoConfiguration + @ComponentScan

  • 🧠 展开版:扫描组件 + 开启自动配置 + 配置类能力。

  • 🔍 追问点:扫描范围怎么控制?(启动类包路径、scanBasePackages)

  • ⚠️ 易错点:启动类放错包,会导致组件扫不到。


Q18:配置优先级(你自己复习很实用)

  • ✅ 背诵版:命令行参数 > 环境变量 > 配置文件(application.yml/properties)> 默认配置。

  • 🧠 展开版:同一项配置"越靠近运行时越优先",多环境用 profile。

  • 🔍 追问点:多环境怎么做?(application-dev.yml + spring.profiles.active)

  • ⚠️ 易错点:同名配置多处出现要知道到底谁覆盖谁。


6.7 一页速背清单

  • IOC/DI:容器管对象,依赖注入实现

  • 生命周期:实例化→注入→Aware→BPP→init→destroy

  • Scope:singleton 默认;prototype 每次 new

  • 循环依赖:单例 setter + 三级缓存;构造器不行

  • AOP:代理织入;JDK(接口)/CGLIB(子类)

  • 事务:默认回滚 RuntimeException;传播 REQUIRED / REQUIRES_NEW;失效=没走代理/异常吃掉

  • MVC 流程:DispatcherServlet → mapping → adapter → controller → converter/view

  • Boot:starter + auto-config + conditional;@SpringBootApplication 三合一


7. MyBatis

7.1 知识点速览

7.1.1 MyBatis 是什么?解决什么问题?

  • MyBatis 是 持久层框架 :帮你把 Java 对象 ↔ SQL ↔ 数据库结果集 的映射、参数绑定、执行、结果封装做掉。

  • 核心价值:SQL 可控、学习成本低、适合复杂 SQL(对比 JPA 更灵活)。

7.1.2 关键组件

  • SqlSessionFactory / SqlSession:会话与执行入口

  • Mapper:接口代理对象(你写接口,运行时生成实现)

  • Executor:执行器(Simple/Reuse/Batch)

  • MappedStatement:一条 SQL 的"配置对象"

  • TypeHandler:Java 类型 ↔ JDBC 类型转换

  • Cache:一级/二级缓存

7.1.3 预编译与防注入

  • #{}PreparedStatement 预编译、安全、自动加引号

  • ${}字符串拼接、有 SQL 注入风险(慎用)


7.2 面试题库

Q1:MyBatis 的工作流程是怎样的?

  • ✅ 背诵版:读取配置→创建 SqlSessionFactory→获取 SqlSession→获取 Mapper 代理→执行 SQL(Executor)→参数绑定→结果映射→返回对象。

  • 🧠 展开版:

    • Mapper 接口本身没有实现,MyBatis 用 动态代理生成实现

    • 每个 SQL 会被解析成 MappedStatement

    • 执行器负责:缓存、Statement 复用、批量执行等

  • 🔍 追问点:Mapper 为什么能直接注入并调用?(代理)

  • ⚠️ 易错点:别把"SqlSession"当成线程安全对象,它通常不建议跨线程共享。


Q2:#{}${} 的区别?什么时候用?

  • ✅ 背诵版:#{} 走预编译,安全;${} 是直接拼接字符串,可能注入。一般都用 #{}${} 只在动态表名/列名等无法预编译的场景谨慎使用。

  • 🧠 展开版:

    • #{}:会变成 ? 占位符,MyBatis 负责 set 参数

    • ${}:拼成最终 SQL 文本,数据库看到的就是拼接后的完整字符串

  • 🔍 追问点:order by 动态字段怎么办?(白名单校验 + ${}

  • ⚠️ 易错点:${} 一旦拼接用户输入,非常容易 SQL 注入。


Q3:MyBatis 的一级缓存和二级缓存是什么?

  • ✅ 背诵版:

    • 一级缓存:SqlSession 级别,默认开启

    • 二级缓存:Mapper namespace 级别,需要配置开启

  • 🧠 展开版:

    • 一级缓存:同一个 SqlSession 内重复查询可能直接命中缓存

    • 二级缓存:跨 SqlSession 共享,但会带来一致性问题

    • 更新/提交可能会清理缓存(依配置和操作而定)

  • 🔍 追问点:什么时候缓存不生效?(不同 SqlSession、手动清缓存、同一会话但参数不同等)

  • ⚠️ 易错点:二级缓存不是"默认就安全好用",生产要谨慎评估一致性和内存占用。


Q4:MyBatis 如何防止 SQL 注入?

  • ✅ 背诵版:核心是用 #{} 走预编译;对必须 ${} 的动态表/列名做 白名单校验;禁用直接拼接用户输入。

  • 🧠 展开版:

    • 参数一律 #{}(PreparedStatement)

    • 动态排序字段:只允许固定几个字段(白名单)

  • 🔍 追问点:MyBatis 本身能完全防注入吗?(不能,${} + 用户输入仍会注入)

  • ⚠️ 易错点:把"用 MyBatis"当成"天然安全"是错的,关键是你怎么写 SQL。


Q5:动态 SQL 常用标签有哪些?

  • ✅ 背诵版:<if><where><trim><choose><foreach><set>

  • 🧠 展开版:

    • where/trim:避免多余 AND/OR

    • foreach:IN 查询、批量插入

  • 🔍 追问点:foreach 批量插入怎么写?有什么限制?

  • ⚠️ 易错点:where/trim 用不好会生成非法 SQL(多余逗号/AND)。


Q6:resultType 和 resultMap 区别?什么时候用 resultMap?

  • ✅ 背诵版:resultType 适合字段与属性名能直接映射;resultMap 适合字段名不一致/复杂映射/多表关联/嵌套对象

  • 🧠 展开版:

    • resultMap 可做:别名、字段映射、association、collection
  • 🔍 追问点:一对多映射怎么做?(collection)

  • ⚠️ 易错点:多表 join + resultType 容易映射错/丢字段,复杂场景用 resultMap 更稳。


Q7:MyBatis 分页怎么做?你推荐哪种?

  • ✅ 背诵版:常见:SQL 级分页(limit/offset)、PageHelper 插件、MyBatis-Plus 分页;生产更推荐 SQL 级分页或成熟插件。

  • 🧠 展开版:

    • offset 深分页性能差(扫很多行)→ 可用"基于 id/时间游标"的方式优化
  • 🔍 追问点:深分页怎么优化?(游标/延迟关联/覆盖索引)

  • ⚠️ 易错点:深分页别硬上 offset=1000000,会非常慢。


Q8:MyBatis 插件(Interceptor)能做什么?

  • ✅ 背诵版:插件可拦截 Executor/StatementHandler/ParameterHandler/ResultSetHandler,用于分页、审计、SQL 打印、加密脱敏等。

  • 🧠 展开版:常见分页插件就是拦截 StatementHandler 改写 SQL。

  • 🔍 追问点:插件会影响性能吗?(会,尤其是打印 SQL/参数)

  • ⚠️ 易错点:插件过多会增加链路复杂度,注意可观测与开关。


7.3 一页速背清单

  • #{}:预编译安全;${}:拼接有注入风险

  • 一级缓存:SqlSession;二级缓存:namespace

  • 动态 SQL:if/where/trim/foreach/set

  • resultMap:复杂映射/多表/嵌套对象

  • 分页:深分页要优化(游标)

  • 插件:分页/审计/加密等(注意性能)



8. MySQL

8.1 知识点速览

8.1.1 为什么 InnoDB 是默认引擎?

  • 支持 事务(ACID)行级锁MVCC、崩溃恢复能力强(redo/undo)。

8.1.2 索引核心:B+Tree & 聚簇索引

  • InnoDB 主键索引是 聚簇索引:叶子节点存整行数据

  • 二级索引叶子节点存:二级索引 key + 主键值(回表靠主键)

8.1.3 事务核心:隔离级别 + MVCC + 锁

  • 事务隔离级别:RU / RC / RR / Serializable

  • InnoDB 常用 RR + MVCC + Next-Key Lock 防幻读

8.1.4 慢 SQL 优化基本套路

  • EXPLAIN → 看索引是否命中/扫描行数

  • 重点优化:where 条件、索引设计、避免函数/隐式转换、减少回表、控制返回行数


8.2 面试题库

Q1:MySQL 常用存储引擎有哪些?InnoDB 和 MyISAM 区别?

  • ✅ 背诵版:常用 InnoDB;InnoDB 支持事务/行锁/MVCC,MyISAM 不支持事务,锁粒度更粗。

  • 🧠 展开版:

    • InnoDB:适合 OLTP(高并发读写)

    • MyISAM:更偏读多写少、历史场景(现在用得少)

  • 🔍 追问点:为什么线上几乎都用 InnoDB?

  • ⚠️ 易错点:别把"性能"简单归因到引擎,还是看业务与设计。


Q2:索引是什么?为什么 B+Tree 适合做索引?

  • ✅ 背诵版:索引是加速查询的数据结构;B+Tree 适合范围查询、磁盘友好、树高低,查询稳定。

  • 🧠 展开版:

    • B+Tree 叶子节点有序且相连,范围查询效率高

    • 树高低意味着磁盘 IO 次数少

  • 🔍 追问点:BTree vs B+Tree 区别?

  • ⚠️ 易错点:别说"索引一定加速",写入会变慢(维护成本)。


Q3:什么是聚簇索引?什么是回表?怎么避免?

  • ✅ 背诵版:聚簇索引(主键)叶子存整行;二级索引叶子存主键,查询整行需要再查主键(回表)。用覆盖索引可减少回表。

  • 🧠 展开版:

    • 覆盖索引:查询字段都在索引里(select 列被索引覆盖)

    • 设计联合索引时把"常用返回列"纳入索引可减少回表(但注意索引膨胀)

  • 🔍 追问点:using index 是什么意思?(覆盖索引)

  • ⚠️ 易错点:为了覆盖索引塞太多列,可能导致索引过大、写入更慢。


Q4:联合索引最左前缀原则是什么?

  • ✅ 背诵版:联合索引按字段顺序建立,查询条件从最左开始连续命中才能充分利用索引(范围条件后面的列通常难以继续利用)。

  • 🧠 展开版:

    • 例:索引 (a,b,c)

      • where a=? ✅

      • where a=? and b=? ✅

      • where b=? ❌(缺最左)

      • where a>? and b=?:a 范围后 b 难充分利用(看优化器)

  • 🔍 追问点:联合索引顺序怎么设计?(高选择性/常用过滤/排序分组需求)

  • ⚠️ 易错点:把"最左前缀"理解成"只用第一列"是不对的。


Q5:EXPLAIN 你会看哪些字段?

  • ✅ 背诵版:重点看 type、key、rows、Extra(Using index/Using filesort/Using temporary)。

  • 🧠 展开版:

    • type:是否全表扫描(ALL 最差)

    • key:是否命中索引

    • rows:预计扫描行数

    • Extra:

      • Using index:覆盖索引

      • Using filesort:需要额外排序(可能慢)

      • Using temporary:临时表(可能慢)

  • 🔍 追问点:filesort 一定慢吗?(不一定,但大数据量会慢)

  • ⚠️ 易错点:只看 key 不看 rows,很容易误判(命中索引但扫描依旧大)。


Q6:事务四大特性 ACID 是什么?

  • ✅ 背诵版:原子性(要么全成功要么全失败)、一致性、隔离性、持久性。

  • 🧠 展开版:InnoDB 通过 redo/undo、锁、MVCC 等机制实现。

  • 🔍 追问点:redo/undo 各自作用?

  • ⚠️ 易错点:一致性更多是"业务+约束+事务机制"的共同结果,不只是数据库单方面。


Q7:隔离级别有哪些?分别解决什么问题?

  • ✅ 背诵版:

    • RU:可能脏读

    • RC:解决脏读,可能不可重复读

    • RR:解决不可重复读,并通过锁机制避免幻读(InnoDB)

    • Serializable:最强,性能最低

  • 🧠 展开版:企业常用 RC 或 RR(看业务取舍)。

  • 🔍 追问点:什么是幻读?RR 为什么能避免幻读?

  • ⚠️ 易错点:幻读和不可重复读别混:幻读强调"多了一些行"。


Q8:MVCC 是什么?解决了什么问题?

  • ✅ 背诵版:MVCC 通过版本链 + Read View,让读写不互相阻塞,提高并发(主要用于一致性读)。

  • 🧠 展开版:

    • 一致性读:读旧版本,不加锁(或少加锁)

    • 写操作通过 undo 保留旧版本

  • 🔍 追问点:RC 和 RR 的 Read View 生成时机有什么差异?(理解层面回答即可:RC 每次读可能新视图,RR 事务内视图更稳定)

  • ⚠️ 易错点:MVCC 不是"万能不加锁",写写冲突仍需要锁。


Q9:MySQL 锁有哪些?行锁、间隙锁、Next-Key Lock 是什么?

  • ✅ 背诵版:InnoDB 有行锁;在 RR 下为防幻读会有间隙锁/Next-Key Lock(锁住范围)。

  • 🧠 展开版:

    • 行锁:锁具体记录

    • 间隙锁:锁记录之间的"区间"

    • Next-Key:行锁 + 间隙锁(范围锁)

  • 🔍 追问点:什么时候会加间隙锁?(范围查询、非唯一索引等场景常见)

  • ⚠️ 易错点:锁问题经常来自"索引没用好导致锁范围变大"。


Q10:慢 SQL 常见原因有哪些?怎么优化?

  • ✅ 背诵版:常见原因:索引未命中、扫描行数大、回表多、排序/分组导致临时表或 filesort、锁等待。优化:建/调索引、改 SQL、减少返回、避免深分页、拆分与缓存。

  • 🧠 展开版(标准套路):

    1. EXPLAIN 看扫描行数/索引

    2. 重点优化 where 条件与索引设计(联合索引顺序)

    3. 避免函数、隐式转换(导致索引失效)

    4. 控制返回行数(limit、分页优化)

  • 🔍 追问点:深分页怎么优化?(基于游标/延迟关联/覆盖索引)

  • ⚠️ 易错点:只会说"加索引",不会说"为什么没命中索引/怎么设计联合索引"。


8.3 一页速背清单

  • InnoDB:事务/行锁/MVCC

  • 索引:B+Tree;主键=聚簇索引;二级索引会回表

  • 覆盖索引:减少回表(Extra: Using index)

  • 联合索引:最左前缀;范围后列难继续利用

  • 事务:ACID;隔离级别 RU/RC/RR/Ser

  • MVCC:版本链 + Read View,提高并发读

  • 锁:行锁/间隙锁/Next-Key;索引不当会锁范围扩大

  • 慢 SQL:EXPLAIN 看 type/key/rows/extra

  • ⚠️ 易错点:只会说"加索引",不会说"为什么没命中索引/怎么设计联合索引"。

9. Redis

9.1 知识点速览

9.1.1 Redis 是什么?适合干什么?

  • Redis 是内存型 Key-Value 数据库,常用于:缓存、计数器、排行榜、分布式锁、会话、消息队列(轻量)、限流、延迟任务(视方案)。

  • 核心优势:读写快、数据结构丰富、生态成熟

9.1.2 为什么 Redis 快?

  • 内存读写 + 高效数据结构

  • 单线程(传统命令执行模型)避免复杂锁竞争(同时也有 IO/多线程等辅助机制,不影响你面试的核心解释)

  • 网络模型高效、命令简单、序列化开销可控

9.1.3 Redis 常用数据结构 & 场景

结构 典型命令 场景
String get/set/incr 缓存、计数器、分布式锁
Hash hget/hset 对象缓存(用户信息)
List lpush/rpop 消息队列(轻量)、时间线
Set sadd/smembers 去重、共同好友
ZSet zadd/zrange 排行榜、延迟队列(按 score)

面试加分:提一句"Redis 底层会根据数据量选择不同编码(如 ziplist/hashtable 等)",点到为止即可。

9.1.4 持久化与高可用

  • 持久化:RDB(快照)/ AOF(追加日志)/ 混合(可选)

  • 高可用:主从复制、哨兵、集群(Cluster)

  • 核心工程目标:不丢数据、能恢复、能扩容、能故障转移


9.2 面试题库

Q1:Redis 和 MySQL 缓存怎么配合?

  • ✅ 背诵版:Redis 做热点数据缓存,MySQL 做最终存储;关键是缓存一致性、过期策略和兜底降级。

  • 🧠 展开版:

    • 读:先查缓存,miss 再查 DB,回填缓存

    • 写:要考虑一致性(见后面双写策略)

    • 兜底:缓存不可用时要降级/限流,避免 DB 被打爆

  • 🔍 追问点:缓存一致性怎么保证?(见 Q6)

  • ⚠️ 易错点:只说"加缓存就快了"不够,要说"怎么防穿透/击穿/雪崩"。


Q2:缓存穿透 / 击穿 / 雪崩分别是什么?怎么解决?

  • ✅ 背诵版:

    • 穿透:查不存在的数据 → 每次都打到 DB

    • 击穿:某个热点 key 过期 → 大量请求同时打 DB

    • 雪崩:大量 key 同时过期/Redis 故障 → DB 被打爆

  • 🧠 展开版(标准解法):

    • 穿透:缓存空值、布隆过滤器、参数校验

    • 击穿:互斥锁(单飞)、逻辑过期、热点 key 永不过期+异步刷新

    • 雪崩:过期时间加随机、分批过期、多级缓存、限流降级、主从/哨兵保障

  • 🔍 追问点:布隆过滤器会误判吗?(会,有误判但无漏判)

  • ⚠️ 易错点:只会背概念不会落地;要能说"你会选哪种方案 + 为什么"。


Q3:Redis 的过期策略和淘汰策略是什么?

  • ✅ 背诵版:过期键删除包括定期删除 + 惰性删除;内存不足会按淘汰策略(如 LRU/LFU/随机/只淘汰过期等)移除数据。

  • 🧠 展开版:

    • 惰性删除:访问时发现过期才删

    • 定期删除:周期扫描一部分 key

    • 淘汰策略:看配置(常见 allkeys-lru / allkeys-lfu / volatile-lru 等)

  • 🔍 追问点:LRU 和 LFU 区别?(最近使用 vs 使用频率)

  • ⚠️ 易错点:过期策略≠淘汰策略;淘汰只在内存不足触发。


Q4:RDB 和 AOF 区别?怎么选?

  • ✅ 背诵版:RDB 是快照,恢复快但可能丢最近数据;AOF 记录写命令,数据更完整但文件更大,恢复更慢。生产常结合使用。

  • 🧠 展开版:

    • RDB:适合做全量备份、重启恢复快

    • AOF:追加写更安全,可重写压缩

    • 选择:看业务对"丢数据容忍度"和"恢复速度"的权衡

  • 🔍 追问点:AOF 重写是干什么?(压缩/合并命令,减少文件体积)

  • ⚠️ 易错点:AOF 也不是"完全不丢",仍取决于刷盘策略与宕机时机。


Q5:Redis 主从复制、哨兵、集群分别解决什么?

  • ✅ 背诵版:

    • 主从:读写分离、冗余

    • 哨兵:自动故障转移(选主)

    • 集群:分片扩容(水平扩展)+ 高可用

  • 🧠 展开版:

    • 主从:主写从读;复制延迟要关注

    • 哨兵:监控主从,主挂了自动切主

    • 集群:slot 分片,key 分布到不同节点

  • 🔍 追问点:主从延迟带来什么问题?(读到旧数据)

  • ⚠️ 易错点:读写分离不是银弹,延迟一致性要说明白。


Q6:缓存一致性怎么做?(双写一致性高频)

  • ✅ 背诵版:常见做法是 先更新 DB,再删除缓存(或延迟双删);读写都要考虑并发与重试,必要时引入消息队列/订阅通知保证最终一致。

  • 🧠 展开版(面试稳答法):

    • 推荐:写 DB → 删除缓存(让下一次读从 DB 回填新值)

    • 延迟双删:删除缓存 → 写 DB → 延迟再删一次(处理并发读回填旧值)

    • 高一致场景:用 MQ/CDC 订阅变更来驱动缓存更新(最终一致)

  • 🔍 追问点:为什么不是"更新缓存"?(并发下容易出现覆盖、顺序问题,复杂度更高)

  • ⚠️ 易错点:只说"删缓存"不提失败重试/补偿,面试官会追问可靠性。


Q7:Redis 分布式锁怎么实现?有什么坑?

  • ✅ 背诵版:用 SET key value NX PX ttl 加锁,value 用唯一标识;释放锁用 Lua 脚本校验 value 再删,避免误删别人的锁。

  • 🧠 展开版:

    • 加锁:SET NX + 过期时间(避免死锁)

    • 解锁:必须"校验持有者"再删除(Lua 原子性)

    • 续期:看业务是否需要(长任务)

  • 🔍 追问点:锁过期但任务没完成怎么办?(续期/看门狗/合理 TTL)

  • ⚠️ 易错点:

    • setnx 后再 expire 分两步是坑(非原子)

    • 不校验 value 直接 del 会误删别人的锁

备注:关于 RedLock 是否"强一致"在业界存在讨论。面试里建议说:单 Redis 实例锁适合大多数工程场景;强一致分布式锁要结合业务与更强协调机制评估。


Q8:什么是大 key / 热 key?怎么治理?

  • ✅ 背诵版:大 key 是单个 value 过大导致阻塞与内存压力;热 key 是访问过于集中导致单点压力。治理:拆分、分片、异步、限流、预热、本地缓存。

  • 🧠 展开版:

    • 大 key:hash/list/set 元素过多或大字符串;操作会阻塞主线程

    • 热 key:集中在一个 key 上(比如秒杀库存)

    • 治理:拆 key、分桶(key 加后缀)、读写分离、本地缓存、热点永不过期+异步刷新

  • 🔍 追问点:如何发现?(监控 QPS、慢查询、bigkey 工具/采样)

  • ⚠️ 易错点:热 key 不能只靠扩容解决,需要"打散访问"。


9.3 一页速背清单

  • 数据结构:String/Hash/List/Set/ZSet + 场景

  • 三大问题:穿透/击穿/雪崩 + 对应解法

  • 一致性:写 DB → 删缓存(延迟双删/订阅驱动)

  • 持久化:RDB 快照、AOF 更完整、组合更稳

  • 高可用:主从/哨兵/集群(分片)

  • 分布式锁:SET NX PX + Lua 校验释放

  • 治理:大 key / 热 key 拆分与限流


10. MQ(RabbitMQ)

10.1 知识点速览

10.1.1 为什么要用 MQ?

  • 削峰填谷:扛住瞬时流量

  • 异步解耦:下游慢/不稳定不拖垮主链路

  • 广播通知:多系统订阅同一事件

面试加分:顺带说一句代价:引入最终一致、消息丢失/重复/积压的治理成本

10.1.2 RabbitMQ 的核心组件(一定要会)

  • Producer:生产者

  • Exchange:交换机(路由规则)

  • Queue:队列(存消息)

  • Binding:绑定(exchange → queue 的规则)

  • RoutingKey:路由键

  • Consumer:消费者

10.1.3 常见交换机类型(面试高频)

  • Direct:精确匹配 routingKey

  • Topic:通配符匹配(最常用)

  • Fanout:广播

  • Headers:按 header 匹配(少用)


10.2 面试题库

Q1:RabbitMQ 的消息流转过程?

  • ✅ 背诵版:Producer 发消息到 Exchange → 按 routingKey/binding 路由到 Queue → Consumer 从 Queue 拉取/推送消费并 ack。

  • 🧠 展开版:Exchange 不存消息,只负责路由;Queue 才存消息。

  • 🔍 追问点:如果路由不到任何队列怎么办?(mandatory、备份交换机等机制)

  • ⚠️ 易错点:把 Exchange 当成"队列"说会直接扣分。


Q2:MQ 如何保证消息"不丢"?(生产者/队列/消费者三段都要答)

  • ✅ 背诵版:生产者用 confirm;队列端消息持久化;消费者手动 ack + 失败重试/死信队列。

  • 🧠 展开版(标准三段式):

    1. 生产者不丢:Publisher Confirm(确认机制),失败重发/记录

    2. Broker 不丢:Exchange/Queue durable、消息 persistent、落盘策略

    3. 消费者不丢:手动 ack;消费失败重试(限次数)→ 入 DLQ(死信队列)

  • 🔍 追问点:confirm 和事务机制有什么区别?(confirm 更常用、性能更好)

  • ⚠️ 易错点:只说"消息持久化"不够,生产者没 confirm 一样可能丢。


Q3:如何处理"重复消费"?怎么做到幂等?

  • ✅ 背诵版:MQ 语义通常是"至少一次",重复消费靠幂等解决:业务唯一键去重、幂等表/状态机、去重缓存、分布式锁等。

  • 🧠 展开版(常用方案):

    • 唯一业务 ID(orderId、requestId)+ 幂等表:已处理直接返回

    • Redis 去重:SETNX 记录已消费(注意过期与补偿)

    • 数据库唯一约束:插入冲突即认为已处理

  • 🔍 追问点:幂等表怎么设计?(message_id + status + processed_time)

  • ⚠️ 易错点:别说"MQ 保证 exactly-once"------多数情况下做不到,只能"至少一次 + 幂等"。


Q4:如何保证"顺序消费"?

  • ✅ 背诵版:顺序需要"同一业务 key 的消息进入同一队列",并且队列内通常单线程/单消费者按序处理。

  • 🧠 展开版:

    • 单队列单消费者:最简单,但吞吐受限

    • 多队列分片:按 orderId hash 到固定队列,实现"分区内有序"

  • 🔍 追问点:并发消费者会怎样?(可能乱序)

  • ⚠️ 易错点:RabbitMQ 默认不保证跨队列顺序;顺序是"设计出来的"。


Q5:消息积压怎么办?怎么治理?

  • ✅ 背诵版:先定位原因(生产太快/消费太慢/下游慢),再扩容消费者、限流、优化处理、必要时转移堆积消息。

  • 🧠 展开版(治理套路):

    1. 监控队列深度、消费 TPS、处理耗时、失败率

    2. 提升消费能力:增加消费者实例、优化逻辑、批量处理

    3. 限流削峰:生产侧限流/降级、消费侧 prefetch 控制

    4. 兜底:死信队列/隔离队列,避免拖垮主链路

  • 🔍 追问点:prefetch 是什么?(控制一次推送给消费者的未 ack 消息数量)

  • ⚠️ 易错点:盲目加消费者可能压垮 DB/下游(要联动下游容量)。


Q6:死信队列(DLQ)是什么?什么时候会进入?

  • ✅ 背诵版:消息无法正常投递或消费失败后进入 DLQ;常见原因:拒绝(reject/nack)、过期 TTL、队列满等。

  • 🧠 展开版:

    • 消费失败:nack 并设置 requeue=false → DLQ

    • TTL 过期:进入 DLQ 做补偿/人工处理

  • 🔍 追问点:DLQ 常用来做什么?(失败隔离、延迟重试、人工补偿)

  • ⚠️ 易错点:不要让 DLQ 变成"垃圾桶",需要配套告警与处理流程。


Q7:RabbitMQ 的推/拉模型与 ACK 机制?

  • ✅ 背诵版:RabbitMQ 多为推送给消费者;消费者处理成功后 ack,失败可 nack/reject 并决定是否 requeue。

  • 🧠 展开版:

    • 自动 ack:吞吐高但风险大(崩溃会丢)

    • 手动 ack:可靠但要注意积压和超时

  • 🔍 追问点:requeue=true 有什么风险?(消息反复失败导致"毒消息"循环)

  • ⚠️ 易错点:毒消息必须有限次重试,超过次数进 DLQ。


Q8:延迟消息怎么做?

  • ✅ 背诵版:常见方案:TTL + DLQ 转发实现延迟;或用延迟插件(视环境支持)。

  • 🧠 展开版:

    • TTL 到期进入 DLQ,再由 DLQ 消费者转发到目标队列

    • 适用于:超时未支付关闭订单、定时重试

  • 🔍 追问点:TTL 是队列级还是消息级?(都可以,实际看配置)

  • ⚠️ 易错点:延迟堆太多会导致队列膨胀,需评估容量。


10.3 一页速背清单

  • 用 MQ:削峰/解耦/异步(代价:一致性与治理)

  • 模型:Producer → Exchange → Queue → Consumer

  • 交换机:Direct/Topic/Fanout

  • 不丢:confirm + 持久化 + 手动 ack + DLQ

  • 幂等:业务唯一键 + 幂等表/唯一约束/Redis 去重

  • 顺序:同 key 同队列 + 单消费者(或分片队列)

  • 积压:扩消费/限流/优化/隔离失败

  • 延迟:TTL + DLQ(或插件)


11. Linux / 网络 / Nginx

11.1 知识点速览

11.1.1 Linux 排查"三板斧"

  1. 看资源:CPU / 内存 / 磁盘 / 网络

  2. 看进程线程:是谁在占资源?卡在哪?

  3. 看日志链路:应用日志 / Nginx 日志 / 慢 SQL / 依赖超时

11.1.2 常用命令速查

  • 系统:top/htop uptime free -m vmstat iostat df -h du -sh

  • 进程:ps -ef pstree pidstat lsof -p lsof -i:PORT

  • 网络:ss -lntp ss -s curl -v ping traceroute tcpdump

  • 日志:tail -f grep awk sed less zless

  • 服务:systemctl status journalctl -u xxx -f

11.1.3 Nginx 常见职责

  • 反向代理、负载均衡、静态资源、TLS 终止、限流、缓存、灰度发布

11.2 面试题库:Linux

Q1:Linux 下怎么查看 CPU/内存/磁盘/负载?

  • ✅ 背诵版:

    • CPU/负载:top / uptime

    • 内存:free -m

    • 磁盘:df -h(容量)+ du -sh(目录占用)

  • 🧠 展开版:

    • load average 看 1/5/15 分钟队列压力(不是"CPU使用率")

    • 内存要看:available、swap(swap 大量使用通常性能会抖)

  • 🔍 追问点:load 很高但 CPU 不高可能是什么?(IO 等待、锁竞争、线程阻塞)

  • ⚠️ 易错点:把 load 当作 CPU 使用率,这是典型误解。


Q2:怎么查某个端口被谁占用?

  • ✅ 背诵版:ss -lntp | grep 8080lsof -i:8080

  • 🧠 展开版:拿到 PID 后 ps -ef | grep PID 查看进程信息。

  • 🔍 追问点:如何优雅重启服务?(systemctl / 发送信号)

  • ⚠️ 易错点:线上别随便 kill -9,除非确认无解且有兜底。


Q3:日志太大怎么快速定位错误?

  • ✅ 背诵版:tail -n 200 看最新、grep "ERROR" 过滤、less 分页搜索。

  • 🧠 展开版:

    • 按时间范围过滤(配合日志格式)

    • 看"请求ID/traceId"串联链路(如果有)

  • 🔍 追问点:怎么统计某接口报错次数?(grep + wc/awk)

  • ⚠️ 易错点:直接打开超大日志文件(会卡),用 less / zless


Q4:线上 CPU 100% 你怎么排查?

  • ✅ 背诵版:top 找进程 → 看线程 → 抓栈(jstack)→ 定位死循环/热点方法。

  • 🧠 展开版(标准套路):

    1. top/监控:确认 PID

    2. top -H -p PID:找最耗 CPU 的线程

    3. 把线程 ID 转 16 进制,对照 jstack 找栈

    4. 判断:死循环、频繁 GC、锁竞争、正则灾难、日志风暴等

  • 🔍 追问点:如果是 GC 引起的 CPU 高怎么办?(看 GC log / jstat)

  • ⚠️ 易错点:只会说"重启",不讲定位过程会被扣分。


Q5:线上内存一直涨(疑似内存泄漏)怎么排查?

  • ✅ 背诵版:先确认是否缓存无界/对象堆积 → 导出堆 dump 分析引用链 → 修复并加监控。

  • 🧠 展开版:Java 常见手段:OOM 自动 dump、jmap dump、MAT/IDEA 分析(讲思路即可)。

  • 🔍 追问点:Redis/本地缓存导致的"逻辑泄漏"怎么识别?

  • ⚠️ 易错点:内存涨不一定是泄漏,也可能是"缓存策略/峰值流量"。


11.3 面试题库:网络

Q6:TCP 三次握手/四次挥手?为什么要三次?

  • ✅ 背诵版:三次握手建立连接确认双方收发能力;四次挥手因为 TCP 全双工,关闭要双方分别确认。

  • 🧠 展开版:

    • 三次:SYN → SYN+ACK → ACK

    • 四次:FIN → ACK → FIN → ACK

  • 🔍 追问点:TIME_WAIT 是什么?为什么会很多?

  • ⚠️ 易错点:把 TIME_WAIT 说成"异常",它是协议设计的一部分。


Q7:TIME_WAIT 太多会怎样?怎么缓解?

  • ✅ 背诵版:短连接高频会导致 TIME_WAIT 多;缓解:连接复用(keep-alive)、合理端口/内核参数、反向代理层优化。

  • 🧠 展开版:

    • 优先策略:业务层复用连接(HTTP keep-alive、连接池)

    • Nginx/网关层可承接大量短连接

  • 🔍 追问点:CLOSE_WAIT 多意味着什么?(应用没正确 close)

  • ⚠️ 易错点:只会调内核参数,不考虑"连接模型"与"上游行为"。


Q8:HTTP 和 HTTPS 区别?TLS 在解决什么?

  • ✅ 背诵版:HTTPS = HTTP + TLS,加密/防篡改/身份认证。

  • 🧠 展开版:

    • 证书验证服务器身份

    • 对称加密传数据,非对称协商密钥

  • 🔍 追问点:为什么 HTTPS 仍可能被抓包?(终端信任根证书/代理、或应用层明文日志)

  • ⚠️ 易错点:HTTPS 不是"绝对安全",还要配合安全配置与证书管理。


Q9:DNS 解析流程你了解吗?

  • ✅ 背诵版:浏览器/系统缓存 → 本地 DNS → 递归解析(根→顶级→权威)→ 返回 IP 并缓存。

  • 🧠 展开版:线上常见问题:DNS 缓存、解析超时、域名劫持(点到为止)。

  • 🔍 追问点:怎么快速验证 DNS 问题?(nslookup/dig/curl)

  • ⚠️ 易错点:把"访问慢"只归因应用,DNS 也可能是瓶颈之一。


11.4 面试题库:Nginx

Q10:什么是反向代理?和正向代理区别?

  • ✅ 背诵版:反向代理代理服务器端,对客户端透明;正向代理代理客户端,对服务端透明。

  • 🧠 展开版:

    • Nginx 常做反向代理:统一入口、隐藏内部服务、做负载均衡与 TLS
  • 🔍 追问点:为什么反代能保护后端?(隔离、统一鉴权/限流)

  • ⚠️ 易错点:反向代理≠负载均衡,但它常承载负载均衡能力。


Q11:Nginx 负载均衡策略有哪些?怎么选?

  • ✅ 背诵版:轮询、权重、ip_hash、最少连接等;一般默认轮询,粘性会话可用 ip_hash 或业务层 token。

  • 🧠 展开版:

    • 轮询:通用

    • 权重:按机器性能分配

    • ip_hash:简单粘性,但会导致不均衡

    • 最少连接:连接耗时差异大时更稳

  • 🔍 追问点:健康检查怎么做?(应用层探活/网关探活/容器编排)

  • ⚠️ 易错点:粘性会话不是万能,更推荐"无状态服务 + session 外置(Redis)"。


Q12:Nginx 常用来做哪些事情?

  • ✅ 背诵版:反代、负载均衡、静态资源、TLS 终止、限流、缓存、灰度。

  • 🧠 展开版:

    • 限流:保护后端(连接数/QPS)

    • 缓存:热点静态资源(或 API 缓存,需谨慎一致性)

  • 🔍 追问点:限流是在哪一层做更合理?(网关/Nginx 优先,应用层兜底)

  • ⚠️ 易错点:缓存动态接口要考虑"鉴权、个性化、失效"。


Nginx 反代配置示例(你放文章里很实用)

复制代码
upstream app_upstream {
    server 10.0.0.1:8080 weight=2;
    server 10.0.0.2:8080 weight=1;
    keepalive 64;
}

server {
    listen 80;
    server_name example.com;

    location /api/ {
        proxy_pass http://app_upstream;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_connect_timeout 2s;
        proxy_read_timeout 10s;
    }
}

11.5 一页速背清单

  • Linux:top/free/df/du/ps/ss/lsof/tail/grep

  • 排查:现象→资源→进程线程→日志链路→验证修复

  • 网络:TCP 握手挥手、TIME_WAIT/CLOSE_WAIT、HTTPS/TLS、DNS

  • Nginx:反代/负载/静态/TLS/限流/缓存/灰度


12. 分布式 / 高并发场景题

12.1 通用答题模板

面试官问场景题,你按这 6 步答,基本不会乱:

  1. 目标:一致性优先还是可用性优先?吞吐/延迟指标?

  2. 边界:峰值 QPS、数据量、允许延迟、允许丢失吗?

  3. 核心链路:读写路径怎么走(缓存/DB/MQ)

  4. 关键保障:限流/降级/熔断/重试/幂等/监控

  5. 数据一致性策略:最终一致 or 强一致(选方案并说明取舍)

  6. 故障预案:积压、超时、回滚、补偿、告警


12.2 高频场景题库

场景 1:秒杀/抢购如何设计?

  • ✅ 背诵版:前置限流+库存预扣+异步下单+削峰填谷+最终一致+兜底补偿。

  • 🧠 展开版(经典架构):

    1. 网关/Nginx 限流(令牌桶/漏桶)+ 黑白名单

    2. Redis 预热库存:原子扣减(Lua)防超卖

    3. 下单写 MQ:异步创建订单(削峰)

    4. 消费端落库:幂等(订单号/请求ID)

    5. 失败重试 + DLQ,最终对账补偿

  • 🔍 追问点:怎么防止机器人?(验证码/风控/滑块/限频)

  • ⚠️ 易错点:只说"加 Redis",不讲"原子扣减 + 异步削峰"。


场景 2:库存扣减如何防超卖?

  • ✅ 背诵版:核心是原子性:DB 乐观锁/行锁 或 Redis Lua 原子扣减;配合补偿与对账。

  • 🧠 展开版:

    • DB 方案:update stock set cnt=cnt-1 where id=? and cnt>0(原子条件更新)

    • Redis 方案:Lua 扣减 + MQ 落库(最终一致)

  • 🔍 追问点:高并发下用哪种更稳?(Redis 扛并发,DB 做最终落地)

  • ⚠️ 易错点:先查库存再扣减(非原子)会超卖。


场景 3:下单后要通知库存/物流,怎么做异步?

  • ✅ 背诵版:用 MQ 事件驱动:下单成功发消息,库存/物流订阅;保证不丢+幂等+失败重试。

  • 🧠 展开版:

    • 事件:OrderCreated

    • 可靠性:生产 confirm + 持久化 + 消费 ack

    • 幂等:用业务 ID(orderId)去重

  • 🔍 追问点:如何保证"本地事务 + 发消息"一致?(见场景 4)

  • ⚠️ 易错点:同步调用多个下游导致主链路变慢且易雪崩。


场景 4:如何保证"写 DB + 发 MQ"不丢不重?

  • ✅ 背诵版:推荐 Outbox 本地消息表:同一事务写业务表+消息表,异步投递 MQ,失败可重试,最终一致。

  • 🧠 展开版(面试很加分):

    1. 事务内:写订单 + 写 outbox(msg, status=NEW)

    2. 后台任务/CDC:扫描 NEW → 发 MQ → 标记 SENT

    3. 消费端幂等:按 msgId/orderId 去重

  • 🔍 追问点:不用分布式事务也能做一致吗?(可以,最终一致)

  • ⚠️ 易错点:业务写成功但发消息失败(或反过来)= 经典不一致坑。


场景 5:分布式锁怎么选?怎么避免死锁/误删?

  • ✅ 背诵版:常用 Redis 锁:SET NX PX + 唯一 value + Lua 校验释放;长任务要续期;失败要退避重试。

  • 🧠 展开版:锁是"降低并发冲突"的手段,不是万能;能用 DB 唯一约束/幂等表就别强上锁。

  • 🔍 追问点:锁过期任务未完成?(续期/看门狗/拆分任务)

  • ⚠️ 易错点:不校验 value 直接 del,会误删别人锁。


场景 6:接口幂等怎么设计?

  • ✅ 背诵版:给请求一个唯一 requestId,服务端做"只处理一次":幂等表/唯一约束/Redis SETNX。

  • 🧠 展开版:

    • 幂等表:requestId + status + result

    • 唯一索引:插入冲突即认为重复

    • 返回一致:重复请求返回相同结果

  • 🔍 追问点:幂等键怎么生成?(客户端生成/网关生成/服务端返回)

  • ⚠️ 易错点:只做"去重",不保证"重复返回同结果"。


场景 7:如何做限流、降级、熔断?

  • ✅ 背诵版:入口限流(Nginx/网关)优先;服务内降级兜底;依赖超时与熔断保护;监控告警闭环。

  • 🧠 展开版:

    • 限流:令牌桶/漏桶(保护系统容量)

    • 降级:返回兜底数据/关闭非核心功能

    • 熔断:依赖失败率高时快速失败,避免雪崩

  • 🔍 追问点:你会看哪些指标?(QPS、RT、错误率、拒绝率、队列长度)

  • ⚠️ 易错点:只在服务里做限流,入口不控流 DB 仍会被打爆。


场景 8:缓存一致性如何保证?

  • ✅ 背诵版:常用"写 DB → 删缓存"(必要时延迟双删),并给删除失败做重试补偿;更强一致可用订阅变更驱动缓存更新。

  • 🧠 展开版:读写并发下,删除缓存比更新缓存更稳;关键是补偿机制与监控。

  • 🔍 追问点:缓存雪崩/击穿怎么防?(随机过期、互斥锁、逻辑过期)

  • ⚠️ 易错点:删缓存失败不补偿,会出现长期脏数据。


场景 9:数据库读写分离/分库分表怎么落地?

  • ✅ 背诵版:读写分离:主写从读,注意延迟;分库分表:按业务键分片,配合全局 ID、路由、中间件与扩容方案。

  • 🧠 展开版:

    • 读写分离:对一致性敏感读走主库

    • 分片:选分片键(userId/orderId),避免跨分片查询

  • 🔍 追问点:跨分片分页/排序怎么办?(尽量避免;或汇总服务/ES)

  • ⚠️ 易错点:分库分表不是性能万能药,会显著增加复杂度。


场景 10:消息积压怎么处理?(MQ 必考)

  • ✅ 背诵版:先定位瓶颈(消费慢/下游慢/失败重试),再扩容消费、批处理、限流、隔离失败、DLQ 告警。

  • 🧠 展开版:增加消费者之前先评估 DB/下游承载,防止"扩容把 DB 打挂"。

  • 🔍 追问点:毒消息怎么办?(限次重试→DLQ→人工/补偿)

  • ⚠️ 易错点:无限重试导致积压更严重。


12.3 一页速背清单

  • 高并发核心:限流削峰 + 异步解耦 + 幂等一致 + 可观测兜底

  • 秒杀:Redis 原子扣减 + MQ 异步下单 + 对账补偿

  • 一致性:Outbox / 最终一致(别硬上强分布式事务)

  • 幂等:requestId / 幂等表 / 唯一约束

  • 可靠性:重试要有上限 + DLQ + 告警

  • 扩展:读写分离/分片要考虑延迟与复杂度

相关推荐
I_LPL2 小时前
day32 代码随想录算法训练营 动态规划专题1
java·数据结构·算法·动态规划·hot100·求职面试
Forget_85502 小时前
RHEL——web应用服务器TOMCAT
java·前端·tomcat
v沙加v2 小时前
Java Rendering Engine Unknown
java·开发语言
努力学算法的蒟蒻2 小时前
day86(2.15)——leetcode面试经典150
数据结构·leetcode·面试
识君啊2 小时前
Java双指针 - 附LeetCode 经典题解
java·算法·leetcode·java基础·双指针
java1234_小锋2 小时前
分享一套优质的SpringBoot4+Vue3学生信息管理系统
java·vue.js·spring boot·学生信息
g***27992 小时前
knife4j+springboot3.4异常无法正确展示文档
java
weisian1512 小时前
JVM--10-JVM实战部署全指南:从`java -jar`到生产级高可用
java·jvm·jar·gc