大模型工程师面经(Java+Redis篇)
Java 面试八股手册
用途:面试前速查。风格 = 一句话答案 + 机制解析 + 比喻 + 面试话术。
按出镜率排序。Spring Boot 自动装配示例为高质量模板,其他考点按同样标准整理。
第一章:Spring 核心(必考)
1.1 Spring Boot 自动装配(Auto-Configuration)⭐最高频
一句话:约定优于配置 + 条件化 Bean 注册——引入依赖(starter)自动配置所需 Bean,无需手写 XML。
核心机制:
@SpringBootApplication组合了@EnableAutoConfiguration(开关)AutoConfigurationImportSelector扫描所有 jar 的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Boot 2.7 前是 spring.factories),拿到自动配置类全限定名列表- 用
@Conditional系列注解过滤——只加载满足条件的配置类 XXXAutoConfiguration是执行者:定义 Bean + 应用条件 + 绑定配置@ConfigurationProperties把 yml/properties 绑定到属性类
常见条件注解:
@ConditionalOnClass:类路径存在该类才生效@ConditionalOnMissingBean:容器没有该 Bean 才生效(开发者自定义 Bean 覆盖自动配置的关键)@ConditionalOnProperty:配置属性存在/特定值才生效@ConditionalOnWebApplication:是 Web 应用才生效
比喻:智能咖啡机——你说「要咖啡」(引 starter),咖啡机内置所有配方(imports 文件),检查有没有咖啡豆(OnClass)、你有没有自带豆子(OnMissingBean)、要不要加糖(OnProperty),只执行必要步骤,你直接喝到咖啡(注入 Bean)。
面试话术:「自动装配 = @EnableAutoConfiguration 开开关 + ImportSelector 扫描 imports 文件 + @Conditional 条件过滤 + AutoConfiguration 类执行注册。核心是 @ConditionalOnMissingBean——开发者自定义 Bean 会覆盖自动配置,所以定制很容易。」
1.2 Spring IOC(控制反转)⭐⭐⭐⭐⭐
一句话:对象的创建和依赖管理交给 Spring 容器,而不是自己 new——「不要打电话给我,我会打给你」。
核心:
- 控制反转:对象创建权从开发者反转到容器
- 依赖注入(DI)是 IOC 的实现方式:构造器注入 / Setter 注入 / 字段注入(@Autowired)
- 容器启动:扫描(@ComponentScan)→ 注册 BeanDefinition → 实例化 → 依赖注入 → 初始化
Bean 生命周期:实例化 → 属性填充 → Aware 回调 → BeanPostProcessor 前置 → init-method → BeanPostProcessor 后置 → 使用 → destroy
Bean 作用域:singleton(默认,单例)/ prototype(每次新对象)/ request / session
比喻:以前你饿了要自己去菜市场买菜做饭(new 对象);现在你打电话给餐厅(容器),餐厅做好端给你(注入)。
面试话术:「IOC 把对象创建和依赖管理交给容器,DI 是它的实现。好处是解耦 + 可测试 + 统一管理生命周期。Bean 默认单例,prototype 每次新建。」
1.3 Spring AOP(面向切面编程)⭐⭐⭐⭐⭐
一句话:把横切逻辑(日志/事务/权限)从业务代码中抽出来,动态织入——不改业务代码就增强功能。
核心概念:
- 切面(Aspect):横切逻辑的模块(如日志切面)
- 切点(Pointcut):匹配哪些方法(表达式如 execution(* com.xxx.service..(..)))
- 通知(Advice):前置 @Before / 后置 @After / 环绕 @Around / 异常 @AfterThrowing / 返回 @AfterReturning
- 连接点(JoinPoint):被拦截的方法
实现机制:
- 代理模式:JDK 动态代理(接口)或 CGLIB(类,子类继承)
- Spring Boot 默认 CGLIB(proxyTargetClass=true)
- 事务 @Transactional 就是 AOP 的经典应用
比喻:电影院检票员——你不用每场电影都安排人检票(不改业务代码),检票环节(切面)统一在入场处(切点)执行。
面试话术:「AOP 用动态代理把横切逻辑织入业务方法——接口用 JDK 代理,类用 CGLIB。Spring 事务就是 AOP 实现的:@Transactional 方法进入时开启事务、异常回滚、正常提交。」
第二章:Java 集合(必考)
2.1 HashMap 原理 ⭐⭐⭐⭐⭐(Java 岗最高频)
一句话:数组 + 链表 + 红黑树 的哈希表实现,key 哈希定位,O(1) 查找。
核心机制:
- 存储结构:Node 数组(默认 16),每个槽位是链表或红黑树
- put 流程:hash(key) → 定位槽位 → 无冲突直接放;冲突挂链表(尾插法);链表长度 ≥8 转红黑树;数组扩容(默认 0.75 负载因子)
- get 流程:hash(key) → 定位 → 链表/红黑树遍历找 key
- 扩容:数组满 75% 扩容 2 倍,重新哈希(rehash)
- 线程不安全:并发 put 可能丢数据/死循环(JDK7 头插法扩容死循环)——用 ConcurrentHashMap
关键点:
- 为什么负载因子 0.75:空间和时间折中
- 为什么转红黑树阈值 8:链表查找 O(n),红黑树 O(log n),泊松分布下 8 个冲突概率极低
- key 必须不可变且正确实现 equals/hashCode
比喻:图书馆索引卡(数组槽位)——同一首字母的书放同一个抽屉(链表),抽屉书太多就升级成更快的检索方式(红黑树),抽屉满了换更大的索引柜(扩容)。
面试话术:「HashMap 是数组+链表+红黑树:哈希定位 O(1),冲突链化,链表超 8 转红黑树,负载因子 0.75 触发扩容。线程不安全——并发用 ConcurrentHashMap(分段锁/CAS+ synchronized)。」
2.2 ConcurrentHashMap 线程安全原理 ⭐⭐⭐⭐
一句话:JDK8 用 CAS + synchronized 锁桶(链表头),并发度 = 桶数量。
- JDK7:分段锁(Segment 继承 ReentrantLock)
- JDK8:放弃分段锁——CAS 检查空桶,synchronized 锁非空桶头节点,细粒度到桶
- size() 用 baseCount + CounterCell 数组累加(无锁统计)
- 不允许 null key/value(HashMap 允许一个 null)
2.3 ArrayList vs LinkedList vs Vector ⭐⭐⭐⭐
| ArrayList | LinkedList | Vector | |
|---|---|---|---|
| 底层 | 动态数组 | 双向链表 | 动态数组(同步) |
| 随机访问 | O(1) | O(n) | O(1) |
| 插入删除 | 尾部 O(1),中间 O(n) 移位 | 头尾 O(1),中间 O(n) 遍历 | 同 ArrayList |
| 线程安全 | 否 | 否 | 是(方法同步,性能差) |
| 扩容 | 1.5 倍 | 无 | 2 倍 |
面试话术:「查多用 ArrayList,频繁头尾增删用 LinkedList。Vector 已过时——需要线程安全用 CopyOnWriteArrayList(读多写少)。」
2.4 集合的 fail-fast vs fail-safe ⭐⭐⭐
- fail-fast:遍历时修改集合抛 ConcurrentModificationException(ArrayList,modCount 检查)
- fail-safe:遍历的是副本,不抛异常(CopyOnWriteArrayList/ConcurrentHashMap)
- 面试话术:「ArrayList 遍历时增删抛 ConcurrentModificationException(modCount 变化检测);CopyOnWriteArrayList 遍历的是快照,安全但写时复制代价高——适合读多写少。」
第三章:JVM(必考)
3.1 JVM 内存区域 ⭐⭐⭐⭐⭐
一句话:线程私有(虚拟机栈/本地方法栈/程序计数器)+ 线程共享(堆/方法区)。
| 区域 | 内容 | 异常 |
|---|---|---|
| 程序计数器 | 当前字节码执行行号 | 无 |
| 虚拟机栈 | 方法调用栈帧(局部变量表/操作数栈) | StackOverflowError |
| 本地方法栈 | native 方法 | StackOverflowError |
| 堆 | 对象实例(GC 主战场) | OutOfMemoryError |
| 方法区(元空间) | 类信息/常量/静态变量(JDK8 后元空间用本地内存) | OutOfMemoryError |
JDK8 变化:永久代 → 元空间(本地内存),字符串常量池移入堆。
3.2 垃圾回收(GC)⭐⭐⭐⭐⭐
一句话:找垃圾(可达性分析)+ 清垃圾(分代回收:新生代复制、老年代标记清除/整理)。
判断垃圾:可达性分析——GC Roots(栈引用/静态变量/常量)不可达的对象即垃圾。
分代:
- 新生代:Eden + 两个 Survivor(8:1:1),对象优先 Eden,Minor GC 用复制算法,存活对象在 Survivor 间复制,age 到 15 进老年代
- 老年代:Major GC 用标记-清除(有碎片)或标记-整理(无碎片)
收集器:CMS(并发标记清除,低停顿但有碎片)→ G1(分区化,可预测停顿,JDK9+ 默认)→ ZGC(超低停顿,JDK15+)
比喻:宿舍扔垃圾——新生代像每天清垃圾桶(快、复制保留有用的),老年代像期末大扫除(标记后整理)。
面试话术:「GC 分代:新生代复制算法(Eden+S0+S1,存活率低所以复制划算),老年代标记-整理(存活率高)。判断垃圾用可达性分析(GC Roots)。G1 是 JDK9 默认——分区 + 可预测停顿。」
3.3 类加载机制 ⭐⭐⭐⭐
一句话:加载 → 验证 → 准备 → 解析 → 初始化。
双亲委派模型:类加载请求先给父加载器,父加载不了才自己加载(BootStrap → Ext/Platform → App → 自定义)——保证核心类不被篡改(Object 永远由 Bootstrap 加载)。
打破双亲委派:Tomcat(每个 webapp 独立 classloader)、SPI(线程上下文类加载器)。
第四章:并发(必考)
4.1 线程池 ⭐⭐⭐⭐⭐
一句话:复用线程,避免频繁创建销毁——核心线程 + 阻塞队列 + 非核心线程 + 拒绝策略。
七大参数:corePoolSize(核心线程)/ maximumPoolSize(最大线程)/ keepAliveTime(非核心空闲存活)/ workQueue(任务队列)/ threadFactory / handler(拒绝策略)。
执行流程:
- 线程数 < 核心 → 新建核心线程
- 核心满 → 任务进队列
- 队列满 → 新建非核心线程(直到最大)
- 都满 → 拒绝策略(AbortPolicy 抛异常 / CallerRuns 调用者执行 / Discard 丢弃 / DiscardOldest 丢最旧)
推荐:不要用 Executors(无界队列 OOM 风险),用 ThreadPoolExecutor 手动配置。
面试话术:「线程池流程:核心 → 队列 → 非核心 → 拒绝。核心参数 7 个。Executors.newFixedThreadPool 用无界队列会 OOM——生产用 ThreadPoolExecutor 显式配置,队列有界。」
4.2 synchronized vs ReentrantLock vs volatile ⭐⭐⭐⭐⭐
| synchronized | ReentrantLock | volatile | |
|---|---|---|---|
| 级别 | JVM 关键字(Monitor 锁) | JDK 类(AQS) | 变量可见性 |
| 锁获取 | 自动 | 手动 lock/unlock | 无锁 |
| 可中断 | 否 | 可(lockInterruptibly) | — |
| 公平锁 | 非公平 | 可公平 | — |
| 条件 | wait/notify | Condition 多条件 | — |
volatile 作用:① 可见性(读主存,写立即刷新)② 禁止指令重排(DCL 单例的经典应用)。不保证原子性。
锁升级(synchronized):无锁 → 偏向锁 → 轻量级锁(CAS 自旋)→ 重量级锁(OS 互斥)。
面试话术:「volatile 只保证可见性和有序性,不保证原子性——i++ 需要原子类/锁。synchronized 有锁升级(偏向→轻量→重量)。ReentrantLock 可中断、可公平、Condition 多条件——灵活但必须手动解锁(finally)。」
4.3 JMM(Java 内存模型)⭐⭐⭐⭐
一句话:线程工作内存 + 主内存,volatile/synchronized 保证可见性,happens-before 规则定义顺序。
happens-before 关键规则:程序顺序 / 锁(解锁 happens-before 加锁)/ volatile 写 happens-before 读 / 传递性。
4.4 CAS ⭐⭐⭐⭐
一句话:比较并交换——期望值 = 当前值才更新,失败重试(乐观锁)。
- 实现:Unsafe 类 + 底层原子指令
- ABA 问题:版本号解决(AtomicStampedReference)
- 自旋会消耗 CPU:竞争激烈时退化为锁
第五章:MyBatis(常见)
5.1 MyBatis 原理 ⭐⭐⭐⭐
一句话:半自动 ORM——SQL 写 XML/注解,动态代理生成 Mapper 实现。
流程:加载配置 → SqlSessionFactory → SqlSession → Mapper 动态代理 → 解析 SQL → 参数映射 → 执行 JDBC → 结果映射(ResultMap)。
**#{} vs {}**:`#{}` 预编译(PreparedStatement 占位符,防 SQL 注入)✅;`{}` 字符串拼接(有注入风险,仅表名/排序用)。
一级缓存(SqlSession 内,默认开)二级缓存(namespace 级,可配)。
面试话术:「#{} 预编译防注入,${} 拼接有风险。MyBatis 用动态代理把 Mapper 接口和 XML SQL 绑定,参数用 PreparedStatement 占位,结果用 ResultMap 映射。」
第六章:MySQL 深挖(Java 岗必考,Python 八股附录有基础版)
6.1 索引 ⭐⭐⭐⭐⭐
见《Python面试八股.md》附录 B1——补充:
- 最左前缀原则:联合索引 (a,b,c) 只能用 a、a,b、a,b,c
- 覆盖索引:查询字段全在索引,不用回表
- 索引失效:对索引列函数/运算、左模糊 %xx、隐式类型转换、or 连接非索引列、不等于/not in
6.2 事务隔离级别 + MVCC ⭐⭐⭐⭐⭐(Java 岗深挖点)
隔离级别:读未提交(脏读)/ 读已提交(不可重复读)/ 可重复读(MySQL 默认,幻读)/ 串行化。
MVCC(多版本并发控制):InnoDB 实现可重复读的核心——每行有隐藏字段(事务版本号),读操作通过 undo log 读历史版本,写操作加锁。
快照读 vs 当前读:
- 快照读(普通 SELECT):读 MVCC 版本链,无锁
- 当前读(UPDATE/INSERT/DELETE/SELECT FOR UPDATE):读最新版本,加行锁
幻读解决:可重复读下 InnoDB 用间隙锁(Gap Lock)+ 临键锁(Next-Key Lock)——锁住范围防止插入。
面试话术:「MVCC 让快照读无锁读历史版本(undo log 版本链),当前读加锁。可重复读下 InnoDB 用 Next-Key Lock(记录锁+间隙锁)解决幻读——所以 MySQL 的可重复读比标准隔离级别更强。」
6.3 慢 SQL 优化 ⭐⭐⭐⭐
排查链路:EXPLAIN 看 type(all=全表扫)/ key(走没走索引)/ rows(扫多少行)→ 优化:
- 加索引(注意最左前缀、覆盖索引)
- 避免索引失效(函数/模糊/隐式转换)
- 分页优化(深分页用子查询/游标)
- 大表拆分(分表分库)
第七章:Redis 补充(Java 岗视角)
见《Python面试八股.md》附录 B2——Java 岗补充:
- 分布式锁:SETNX + 过期时间(防死锁)+ Lua 脚本保证原子性 + Redisson 看门狗续期
- 缓存一致性:先更新 DB 再删缓存(延迟双删);不能先删缓存再更新(并发下脏数据)
- 持久化选择:RDB 快照恢复快但丢数据,AOF 安全但慢——混合用
第八章:高频场景题(Java 岗)
8.1 设计一个秒杀系统 ⭐⭐⭐⭐
前端限流(验证码/按钮置灰)→ 网关限流(令牌桶)→ Redis 预扣库存(原子 DECR)→ 队列削峰(MQ 异步下单)→ 数据库最终扣减 + 事务 → 超卖防护(Redis 原子减 + DB 乐观锁 version)。
8.2 分布式锁怎么实现 ⭐⭐⭐⭐
Redis SETNX + 过期时间 + Lua 原子释放(校验 value 是自己的)+ Redisson 看门狗自动续期。高可用用 RedLock(多节点)但争议大——实际工程单节点 + 合理过期足够。
8.3 接口幂等怎么保证 ⭐⭐⭐
唯一订单号 + 数据库唯一索引;Redis setnx 防重;状态机校验(已支付不能重复支付)。
8.4 线上 OOM 排查 ⭐⭐⭐
日志报 OutOfMemoryError → jps 找 PID → jmap 导出堆 → MAT 分析大对象/泄漏链 → 定位代码。常见:大 List 缓存、连接未关闭、静态集合无限增长。
第九章:Java 基础易错点
9.1 String 相关 ⭐⭐⭐⭐⭐
- String 不可变(final char[])——线程安全、可缓存 hash
- == 比引用,equals 比值
- String s1 = "abc"(常量池)vs String s2 = new String("abc")(堆)
- StringBuilder(线程不安全,快)vs StringBuffer(同步,慢)
- 大量拼接用 StringBuilder 不用 +
9.2 equals 和 hashCode ⭐⭐⭐⭐⭐
- 重写 equals 必须重写 hashCode(HashMap 先比 hash 再比 equals)
- equals 约定:自反/对称/传递/一致/与 null 比较为 false
9.3 泛型 / 反射 / 注解 ⭐⭐⭐
- 泛型擦除:编译期检查,运行期擦除(List → List)
- 反射:Class.forName / getMethod / invoke——框架基础(Spring 依赖注入就是反射)
- 注解:@interface + 反射读取——@Transactional/@Autowired 的本质
9.4 异常体系 ⭐⭐⭐
- Throwable → Error(不可控,OOM/StackOverflow)+ Exception(可控)
- Exception → 受检(IOException 必须 try) + 非受检(RuntimeException 不用)
- try-with-resources:自动关闭资源(AutoCloseable)
面试答题技巧(Java 版)
- 概念题:「一句话 + 机制 + 我的项目里怎么用的」
- 原理题:按「是什么 → 为什么 → 怎么做」三步
- 对比题(synchronized vs lock):先列维度再逐项比
- 场景题(秒杀/分布式锁):给「整体链路 + 关键点 + 兜底」
- 不会的:「这个我没深入,但按我的理解…… + 拉回我会的」
第十章:设计模式(完整版)⭐Java 岗必考
10.1 六大设计原则(先背这个——「遵守什么规则」答这个)
- 开闭原则:对扩展开放、对修改关闭——加功能不改老代码(最重要)
- 单一职责:一个类只干一件事
- 里氏替换:子类必须能替换父类
- 依赖倒置:依赖抽象不依赖具体
- 接口隔离:接口要小而专
- 迪米特法则:最少知道原则
10.2 工厂模式(你被问住的——重点背)
一句话:把创建对象的逻辑集中到工厂,调用方不直接 new,工厂根据参数返回合适对象。
为什么用:解耦创建和使用;新增类型只改工厂,调用方不动——符合开闭原则。
三种工厂:
| 类型 | 说明 |
|---|---|
| 简单工厂 | 一个工厂方法,根据参数返回不同对象(最常用) |
| 工厂方法 | 每个产品一个工厂类,扩展性好 |
| 抽象工厂 | 一族产品,用于产品族(如 UI 组件) |
你的实战(面试讲这个):
「我的智康云 LLM Provider 工厂就是工厂模式:统一管理 12 家厂商 API(DeepSeek/通义/Kimi/GLM),根据配置返回对应 LLM 客户端,带重试熔断。新增厂商只改工厂,调用方代码不动——符合开闭原则。」
10.3 单例模式
// 双重检查锁(面试标准答案)public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { // 第一次检查 synchronized (Singleton.class) { if (instance == null) { // 第二次检查 instance = new Singleton(); } } } return instance; }}
复制
volatile 防止指令重排(new 不是原子的:分配内存→初始化→赋值,可能重排);饿汉式(类加载就建)简单但浪费,懒汉式(用才建)要双重检查。
10.4 策略模式
一句话:同一接口不同实现,运行时切换算法。
你的实战:检索策略——BM25/向量/混合可切换(企智通 RAG)。
10.5 模板方法
一句话:父类定流程骨架,子类实现具体步骤。
你的实战:BaseReActAgent 基类——推理流程固定,工具逻辑子类实现。
10.6 观察者模式
一句话:状态变化通知所有订阅者(发布-订阅)。
你的实战:小乐AI Agent 通信总线(订阅/发布/请求-响应)。
10.7 装饰器模式
一句话:不修改原类,动态增强功能(Python 装饰器就是)。
第十一章:消息队列(Kafka)⭐高频
11.1 为什么用消息队列
一句话:异步、解耦、削峰。
- 异步:订单创建→发短信/邮件不阻塞主流程
- 解耦:A 系统发消息,B/C/D 系统各自订阅,互不依赖
- 削峰:秒杀请求先进队列,慢慢消费
11.2 Kafka 核心概念
| 概念 | 说明 |
|---|---|
| Producer/Consumer | 生产者/消费者 |
| Topic | 消息主题(分类) |
| Partition | 分区——消息有序的载体,一个 topic 多个分区并行 |
| Consumer Group | 消费组——组内竞争消费(一个消息只给组内一个消费者),组间广播 |
| Offset | 消费位移——记录消费到哪了,重启继续 |
11.3 面试话术(你有真实经验!)
「我在 Spark-Shopping 用过 Kafka 做事件驱动——订单创建、支付成功这些事件通过 Kafka 异步流转,解耦业务系统,秒杀场景下请求先进队列再慢慢消费,做削峰。Kafka 是分区有序、Consumer Group 负载均衡。」
第十二章:微服务与限流熔断 ⭐⭐⭐⭐
12.1 微服务核心组件
| 组件 | 作用 | 类比 |
|---|---|---|
| 注册中心(Nacos/Eureka) | 服务发现——谁在哪 | 电话簿 |
| 配置中心(Nacos Config) | 统一管理配置 | 中央文件柜 |
| 网关(Gateway) | 统一入口、路由、鉴权 | 前台保安 |
| 熔断降级(Sentinel/Hystrix) | 下游挂了快速失败,不拖垮自己 | 保险丝 |
| 负载均衡 | 请求分发到多个实例 | 分诊台 |
12.2 服务雪崩
一句话:一个服务挂了→依赖它的服务也挂→连锁反应全挂。
解决:超时、熔断、降级、限流、隔离(线程池隔离)。
12.3 限流算法(Sentinel 你实战过)
| 算法 | 原理 |
|---|---|
| 计数器 | 固定窗口计数,超限拒绝——简单但有临界问题 |
| 滑动窗口 | 细粒度计数,解决临界 |
| 令牌桶 | 匀速放令牌,突发可消费(允许一定突发) |
| 漏桶 | 匀速流出,平滑流量(强制匀速) |
你的实战:智康云用了 Sentinel 限流(登录/AI/上传接口)——面试直接讲。
12.4 面试话术
「微服务的核心是服务拆分 + 注册发现 + 熔断降级。我用过 Sentinel 做限流熔断——智康云的 AI 接口配置了登录/AI/上传的限流,429/5xx 自动重试与快速失败。服务雪崩的解法:超时、熔断、降级、限流四件套。」
第十三章:缓存一致性 ⭐⭐⭐⭐
13.1 缓存更新策略(Cache Aside 模式)
一句话:读——先查缓存,没有查 DB 再回填;写——先更新 DB,再删缓存。
为什么删缓存不是更新缓存:并发下更新缓存会有脏数据,删除让下次读重建,更简单安全。
13.2 延迟双删(解决删除缓存失败)
// 1. 更新 DB// 2. 删缓存// 3. 延迟 500ms(异步)再删一次——防止并发下旧缓存被写回
复制
13.3 面试话术
「缓存一致性我用 Cache Aside:读先查缓存未命中查 DB 回填,写先更新 DB 再删缓存。极端并发场景用延迟双删——先删缓存、延迟再删一次,防止旧值被写回。」
第十四章:JVM 追问补充 ⭐⭐⭐
14.1 OOM 排查(线上实战题)
流程:日志看到 OutOfMemoryError → jps 找 PID → jmap -dump 导出堆 → MAT 分析大对象/泄漏链 → 定位代码。
常见原因:大 List 缓存无限增长、连接未关闭、静态集合泄漏、大对象(如图片)堆积。
14.2 JVM 调优参数
| 参数 | 作用 |
|---|---|
| -Xms/-Xmx | 初始/最大堆大小(一般设相同避免扩容) |
| -Xmn | 新生代大小 |
| -XX:+HeapDumpOnOutOfMemoryError | OOM 时自动导出堆 |
| -XX:MaxMetaspaceSize | 元空间上限 |
B2. Redis
| 问题 | 一句话答案 |
|---|---|
| 是什么? | 内存数据库(KV),微秒级,用于缓存/会话/排行榜 |
| 五种数据类型? | String / Hash / List / Set / ZSet |
| 为什么快? | 纯内存 + 单线程(无锁竞争)+ IO 多路复用 |
| 穿透/击穿/雪崩? | 穿透=查不存在(布隆过滤器);击穿=热点 key 过期(互斥锁);雪崩=大量同时过期(过期时间加随机值) |
| 持久化? | RDB 快照(快但可能丢)/ AOF 日志(安全但慢) |
| 缓存一致性? | Cache Aside:先读缓存,未命中读库再回填;更新时先更新库再删缓存 |
B3. Linux
| 问题 | 一句话答案 |
|---|---|
| 常用命令? | ls / cd / grep / find / ps / top / kill / chmod / tar |
| 看 CPU/内存? | top;free -h 内存;df -h 磁盘 |
| 查日志? | tail -f 实时;grep 'error' 过滤 |
| 权限 rwx? | r=4 w=2 x=1;chmod 755 |
| 查端口? | netstat -tlnp 或 lsof -i:8080 |
| 后台跑 jar? | nohup java -jar app.jar > log.txt 2>&1 & |
B4. Docker
| 问题 | 一句话答案 |
|---|---|
| 是什么? | 容器化:应用+依赖打包成镜像,一处构建到处运行 |
| 镜像 vs 容器? | 镜像=只读模板;容器=镜像的实例 |
| 常用命令? | build / run / ps / exec -it / logs |
| 端口映射? | docker run -p 8080:80 |
| 数据持久化? | -v /宿主机:/容器 |
| Dockerfile? | FROM / COPY / RUN / EXPOSE / CMD |
| 和虚拟机区别? | 虚拟机虚拟硬件(重);容器共享宿主内核(轻、秒级启动) |
C1. Linux 补漏
| 考点 | 一句话答案 |
|---|---|
| grep 常用参数 | -v 排除 / -i 忽略大小写 / -E 正则 / -A 3 后3行上下文 |
| awk | 文本处理:awk '{print $1, $3}' file 按空格取第1、3列 |
| sed | 流编辑器:sed -i 's/旧/新/g' file 替换 |
| tar | 打包 tar -czvf a.tar.gz dir;解压 tar -xzvf a.tar.gz |
| 软链接 | ln -s 目标 链接名(类似快捷方式) |
| 查看大小 | du -sh dir;ls -lh file |
| ps | ps -ef 全进程;ps aux | grep python 找进程 |
| kill | kill PID 正常终止;kill -9 PID 强制杀 |
| crontab | crontab -e 编辑;格式:分 时 日 月 周 命令 |
| 管道 | | 前命令输出作后命令输入:ps -ef | grep java |
| 环境变量 | export PATH=$PATH:/xxx;echo $PATH 查看 |
| 网络 | ip addr / ifconfig;ping 测连通 |
| wc/sort/uniq | wc -l 行数;sort;sort | uniq -c 统计去重 |
C2. MySQL 补漏
| 考点 | 一句话答案 |
|---|---|
| GROUP BY / HAVING | GROUP BY 分组;HAVING 过滤分组后结果(WHERE 不能配聚合函数) |
| WHERE vs HAVING | WHERE 分组前过滤行;HAVING 分组后过滤组 |
| JOIN 类型 | INNER(交集)/ LEFT(左表全保留)/ RIGHT(右表全保留) |
| 分页 | LIMIT offset, count:LIMIT 0, 10 第一页 |
| char vs varchar | char 定长(快/浪费);varchar 变长(省空间) |
| 存储引擎 | InnoDB(事务/外键/行锁,默认)/ MyISAM(无事务,表锁) |
| delete/truncate/drop | delete 删行可回滚;truncate 清表不可回滚;drop 删表结构 |
| 脏读/不可重复读/幻读 | 脏读=读未提交;不可重复读=行变;幻读=多了行 |
| 连接池 | 复用连接避免频繁创建(Druid/HikariCP) |
| 建索引 | CREATE INDEX idx_name ON table(column) |
| 覆盖索引 | 查询字段全在索引里,不用回表 |
| explain 关键列 | type(all=全表扫)/ key(实际索引)/ rows(扫描行数) |
C3. Python 补漏
| 考点 | 一句话答案 |
|---|---|
| 类/对象 | class Dog:;__init__ 构造函数;self 指实例自身 |
| 继承 | class Cat(Dog):;super().__init__() 调父类构造 |
| 三大特性 | 封装 / 继承 / 多态 |
| 异常 | try/except/else/finally;raise 主动抛 |
| 类型转换 | int("123") / str(123) / float("1.5") |
| 递归 | 函数调自己,必须终止条件:return 1 if n<=1 else n*f(n-1) |
| json | json.dumps() 转字符串 / json.loads() 转字典(API 天天用) |
| datetime | datetime.now();strftime("%Y-%m-%d") |
| re 正则 | re.search / re.findall / re.sub |
| 多线程 | threading.Thread(target=fn).start();共享数据加 Lock() |
| 虚拟环境 | python -m venv env 隔离依赖 |
| 模块导入 | import math;if __name__ == "__main__": 主入口 |
| 三元表达式 | a if 条件 else b |
| 断言 | assert 条件, "提示" 用于测试/调试 |
C4. 面试保命流程(遇到没答上来的)
第 1 秒:不慌,不沉默超过 3 秒
第 2 秒:「这个概念我了解一些,但可能讲不全——按我的理解是……」
第 3 秒:讲方向,然后拉回你会的:「我在项目里实际用过类似的,是……」
第 4 秒:完全不会就说:「这块我确实没深入,我回去会补——补的方式是……」
更多推荐

所有评论(0)