diff --git a/notes/学习路线 - 面试冲刺.md b/notes/学习路线 - 面试冲刺.md new file mode 100644 index 00000000..9d152fe3 --- /dev/null +++ b/notes/学习路线 - 面试冲刺.md @@ -0,0 +1,266 @@ +# 学习路线 - 面试冲刺 + +* [学习路线 - 面试冲刺](#学习路线---面试冲刺) + * [一、说明](#一说明) + * [二、每天的安排](#二每天的安排) + * [三、Java](#三java) + * [第 1 天:集合](#第-1-天集合) + * [第 2 天:线程池、锁与 volatile](#第-2-天线程池锁与-volatile) + * [第 3 天:CAS、锁升级与 ThreadLocal](#第-3-天cas锁升级与-threadlocal) + * [第 4 天:JVM](#第-4-天jvm) + * [四、MySQL](#四mysql) + * [第 5 天:索引](#第-5-天索引) + * [第 6 天:事务、MVCC 与锁](#第-6-天事务mvcc-与锁) + * [第 7 天:SQL 优化、日志与分库分表](#第-7-天sql-优化日志与分库分表) + * [五、Redis 与缓存](#五redis-与缓存) + * [第 8 天:Redis](#第-8-天redis) + * [第 9 天:缓存问题与 Redis 集群](#第-9-天缓存问题与-redis-集群) + * [六、网络与操作系统](#六网络与操作系统) + * [第 10 天:TCP 与 HTTPS](#第-10-天tcp-与-https) + * [第 11 天:进程、死锁与 I/O 多路复用](#第-11-天进程死锁与-io-多路复用) + * [七、框架、分布式与大模型](#七框架分布式与大模型) + * [第 12 天:Spring 与设计模式](#第-12-天spring-与设计模式) + * [第 13 天:分布式锁、消息队列与秒杀](#第-13-天分布式锁消息队列与秒杀) + * [第 14 天:大模型应用](#第-14-天大模型应用) + + + +## 一、说明 + +适合两三周内就要面试、已经学过这些内容的读者,每天 1.5~2 小时,覆盖约 40 个核心考点,最后 1 天是大模型应用。应聘大模型应用岗位的读者,用[大模型应用开发](学习路线%20-%20大模型应用开发.md)每天的自测题复习。 + +每天先不看笔记,把 3 个自测题各口述 1~2 分钟,答得不完整的再读链接的小节;然后做两道算法题,每题限时 30 分钟。 + +## 二、每天的安排 + +| 天 | 主题 | 阅读 | 算法 | +| :-: | --- | --- | --- | +| | **Java** | | | +| [1](#第-1-天集合) | 集合 | HashMap、ConcurrentHashMap、与 ArrayList 的比较 | 1. 两数之和、56. 合并区间 | +| [2](#第-2-天线程池锁与-volatile) | 线程池、锁与 volatile | ThreadPoolExecutor、synchronized 与 ReentrantLock 的比较、内存模型三大特性、volatile | 88. 合并两个有序数组、15. 三数之和 | +| [3](#第-3-天cas锁升级与-threadlocal) | CAS、锁升级与 ThreadLocal | 非阻塞同步、锁升级的过程、线程本地存储(Thread Local Storage) | 3. 无重复字符的最长子串、206. 反转链表 | +| [4](#第-4-天jvm) | JVM | 运行时数据区域、判断一个对象是否可被回收、垃圾收集算法、CMS 收集器、G1 收集器、内存溢出与内存泄漏 | 21. 合并两个有序链表、141. 环形链表 | +| | **MySQL** | | | +| [5](#第-5-天索引) | 索引 | B+ Tree 原理、MySQL 索引、索引优化、索引失效 | 92. 反转链表 II、146. LRU 缓存 | +| [6](#第-6-天事务mvcc-与锁) | 事务、MVCC 与锁 | 并发一致性问题、隔离级别、多版本并发控制、封锁类型、Next-Key Locks | 20. 有效的括号、33. 搜索旋转排序数组 | +| [7](#第-7-天sql-优化日志与分库分表) | SQL 优化、日志与分库分表 | 查询性能优化、MySQL 的日志、分库分表 | 215. 数组中的第 K 个最大元素、912. 排序数组(手写快速排序) | +| | **Redis 与缓存** | | | +| [8](#第-8-天redis) | Redis | Redis 的数据类型、Redis 的数据结构、Redis 持久化、单线程为什么快 | 102. 二叉树的层序遍历、103. 二叉树的锯齿形层序遍历 | +| [9](#第-9-天缓存问题与-redis-集群) | 缓存问题与 Redis 集群 | 缓存问题、Sentinel、Redis 分片 | 236. 二叉树的最近公共祖先、200. 岛屿数量 | +| | **网络与操作系统** | | | +| [10](#第-10-天tcp-与-https) | TCP 与 HTTPS | UDP 和 TCP 的特点、TCP 的三次握手、TCP 的四次挥手、TCP 可靠传输、HTTPS | 46. 全排列、121. 买卖股票的最佳时机 | +| [11](#第-11-天进程死锁与-io-多路复用) | 进程、死锁与 I/O 多路复用 | 进程与线程的区别、协程、必要条件、死锁预防、I/O 复用 | 53. 最大子数组和、5. 最长回文子串 | +| | **框架、分布式与大模型** | | | +| [12](#第-12-天spring-与设计模式) | Spring 与设计模式 | AOP、Bean 的生命周期、循环依赖、事务失效、设计模式前言、实现 | 300. 最长递增子序列、1143. 最长公共子序列 | +| [13](#第-13-天分布式锁消息队列与秒杀) | 分布式锁、消息队列与秒杀 | 分布式锁、消息队列的可靠性、秒杀系统、限流、降级与熔断 | 42. 接雨水、25. K 个一组翻转链表 | +| [14](#第-14-天大模型应用) | 大模型应用 | RAG 的流程、Agent 是什么、工具调用、MCP | 23. 合并 K 个升序链表、72. 编辑距离 | + +## 三、Java + +### 第 1 天:集合 + +必学:[HashMap](Java%20容器.md#hashmap)、[ConcurrentHashMap](Java%20容器.md#concurrenthashmap)、[与 ArrayList 的比较](Java%20容器.md#2-与-arraylist-的比较)。 + +自测: + +1. HashMap 的 put() 过程是怎样的?什么时候扩容、什么时候转成红黑树?(见[put 操作](Java%20容器.md#3-put-操作)、[扩容-基本原理](Java%20容器.md#5-扩容-基本原理)、[链表转红黑树](Java%20容器.md#8-链表转红黑树)) +2. ConcurrentHashMap 怎样保证线程安全?JDK 1.7 和 1.8 有什么区别?(见[JDK 1.8 的改动](Java%20容器.md#3-jdk-18-的改动)) +3. ArrayList 和 LinkedList 有什么区别?(见[与 ArrayList 的比较](Java%20容器.md#2-与-arraylist-的比较)) + +算法(哈希表,简单):[1. 两数之和](https://leetcode.cn/problems/two-sum/),题解见[数组中两个数的和为给定值](Leetcode%20题解%20-%20哈希表.md#1-数组中两个数的和为给定值)。 + +算法(数组,中等):[56. 合并区间](https://leetcode.cn/problems/merge-intervals/),题解见[合并区间](Leetcode%20题解%20-%20数组与矩阵.md#13-合并区间)。 + +### 第 2 天:线程池、锁与 volatile + +必学:[ThreadPoolExecutor](Java%20并发.md#threadpoolexecutor)、[synchronized 与 ReentrantLock 的比较](Java%20并发.md#比较)、[内存模型三大特性](Java%20并发.md#内存模型三大特性)、[volatile](Java%20并发.md#volatile)。 + +自测: + +1. 线程池的核心参数有哪些?提交任务后是怎样执行的?(见[ThreadPoolExecutor](Java%20并发.md#threadpoolexecutor)) +2. synchronized 和 ReentrantLock 有什么区别?(见[synchronized 与 ReentrantLock 的比较](Java%20并发.md#比较)) +3. volatile 能保证什么,不能保证什么?(见[volatile](Java%20并发.md#volatile)) + +算法(双指针,简单):[88. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/),题解见[归并两个有序数组](Leetcode%20题解%20-%20双指针.md#5-归并两个有序数组)。 + +算法(双指针,中等):[15. 三数之和](https://leetcode.cn/problems/3sum/),题解见[三数之和](Leetcode%20题解%20-%20双指针.md#8-三数之和)。 + +### 第 3 天:CAS、锁升级与 ThreadLocal + +必学:[非阻塞同步](Java%20并发.md#非阻塞同步)、[锁升级的过程](Java%20并发.md#锁升级的过程)、[线程本地存储(Thread Local Storage)](Java%20并发.md#2-线程本地存储thread-local-storage)。 + +自测: + +1. CAS 的原理是什么?ABA 问题怎么解决?(见[CAS](Java%20并发.md#1-cas)、[ABA](Java%20并发.md#3-aba)) +2. synchronized 的锁升级过程是怎样的?(见[锁升级的过程](Java%20并发.md#锁升级的过程)) +3. ThreadLocal 为什么可能导致内存泄漏?(见[线程本地存储(Thread Local Storage)](Java%20并发.md#2-线程本地存储thread-local-storage)) + +算法(滑动窗口,中等):[3. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/),题解见[剑指 Offer 48](48.%20最长不含重复字符的子字符串.md)。 + +算法(链表,简单):[206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/),题解见[链表反转](Leetcode%20题解%20-%20链表.md#2-链表反转)。 + +### 第 4 天:JVM + +必学:[运行时数据区域](Java%20虚拟机.md#一运行时数据区域)、[判断一个对象是否可被回收](Java%20虚拟机.md#判断一个对象是否可被回收)、[垃圾收集算法](Java%20虚拟机.md#垃圾收集算法)、[CMS 收集器](Java%20虚拟机.md#6-cms-收集器)、[G1 收集器](Java%20虚拟机.md#7-g1-收集器)、[内存溢出与内存泄漏](Java%20虚拟机.md#内存溢出与内存泄漏)。 + +自测: + +1. JVM 的内存区域有哪些?(见[运行时数据区域](Java%20虚拟机.md#一运行时数据区域)) +2. CMS 和 G1 有什么区别?(见[G1 收集器](Java%20虚拟机.md#7-g1-收集器)) +3. 线上出现 OOM 怎样排查?(见[内存溢出与内存泄漏](Java%20虚拟机.md#内存溢出与内存泄漏)) + +算法(链表,简单):[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/),题解见[归并两个有序的链表](Leetcode%20题解%20-%20链表.md#3-归并两个有序的链表)。 + +算法(链表,简单):[141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/),题解见[判断链表是否存在环](Leetcode%20题解%20-%20双指针.md#6-判断链表是否存在环)。 + +## 四、MySQL + +### 第 5 天:索引 + +必学:[B+ Tree 原理](MySQL.md#b-tree-原理)、[MySQL 索引](MySQL.md#mysql-索引)、[索引优化](MySQL.md#索引优化)、[索引失效](MySQL.md#索引失效)。 + +自测: + +1. MySQL 为什么用 B+ 树做索引?(见[B+ Tree 原理](MySQL.md#b-tree-原理)) +2. 什么是聚簇索引、回表和覆盖索引?(见[B+Tree 索引](MySQL.md#1-btree-索引)、[覆盖索引](MySQL.md#5-覆盖索引)) +3. 联合索引的最左前缀是什么?哪些情况下索引会失效?(见[多列索引](MySQL.md#2-多列索引)、[索引失效](MySQL.md#索引失效)) + +算法(链表,中等):[92. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/)。 + +算法(设计,中等):[146. LRU 缓存](https://leetcode.cn/problems/lru-cache/),题解见[LRU](缓存.md#七lru)。 + +### 第 6 天:事务、MVCC 与锁 + +必学:[并发一致性问题](数据库系统原理.md#二并发一致性问题)、[隔离级别](数据库系统原理.md#四隔离级别)、[多版本并发控制](数据库系统原理.md#五多版本并发控制)、[封锁类型](数据库系统原理.md#封锁类型)、[Next-Key Locks](数据库系统原理.md#六next-key-locks)。 + +自测: + +1. 四种隔离级别分别解决了脏读、不可重复读、幻读中的哪些?(见[隔离级别](数据库系统原理.md#四隔离级别)) +2. MVCC 的原理是什么?(见[ReadView](数据库系统原理.md#readview)) +3. InnoDB 在可重复读级别下怎样避免幻读?(见[Next-Key Locks](数据库系统原理.md#next-key-locks)) + +算法(栈和队列,简单):[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/),题解见[用栈实现括号匹配](Leetcode%20题解%20-%20栈和队列.md#4-用栈实现括号匹配)。 + +算法(二分查找,中等):[33. 搜索旋转排序数组](https://leetcode.cn/problems/search-in-rotated-sorted-array/)。 + +### 第 7 天:SQL 优化、日志与分库分表 + +必学:[查询性能优化](MySQL.md#二查询性能优化)、[MySQL 的日志](MySQL.md#七日志)、[分库分表](MySQL.md#五切分)。 + +自测: + +1. 线上出现慢 SQL,怎样排查和优化?(见[慢查询的定位与优化](MySQL.md#慢查询的定位与优化)) +2. redo log、undo log 和 binlog 有什么区别?为什么需要两阶段提交?(见[MySQL 的日志](MySQL.md#七日志)、[两阶段提交](MySQL.md#两阶段提交)) +3. 分库分表之后会遇到哪些问题?(见[Sharding 存在的问题](MySQL.md#sharding-存在的问题)) + +算法(排序与堆,中等):[215. 数组中的第 K 个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/),题解见[Kth Element](Leetcode%20题解%20-%20排序.md#1-kth-element)。 + +算法(排序与堆,中等):[912. 排序数组(手写快速排序)](https://leetcode.cn/problems/sort-an-array/),题解见[快速排序](算法%20-%20排序.md#快速排序)。 + +综合题:订单表有 2000 万行,按用户查询最近的订单很慢,同时下单高峰期还出现了死锁:分别怎样分析和解决?(见[使用 Explain 进行分析](MySQL.md#使用-explain-进行分析)、[索引优化](MySQL.md#索引优化)、[MySQL 死锁](计算机操作系统%20-%20死锁.md#2-mysql-死锁)) + +## 五、Redis 与缓存 + +### 第 8 天:Redis + +必学:[Redis 的数据类型](Redis.md#二数据类型)、[Redis 的数据结构](Redis.md#四数据结构)、[Redis 持久化](Redis.md#八持久化)、[单线程为什么快](Redis.md#单线程为什么快)。 + +自测: + +1. Redis 有哪些数据类型?ZSET 的底层为什么用跳表?(见[Redis 的数据类型](Redis.md#二数据类型)、[跳跃表](Redis.md#跳跃表)) +2. RDB 和 AOF 有什么区别?(见[Redis 持久化](Redis.md#八持久化)) +3. Redis 为什么快?(见[单线程为什么快](Redis.md#单线程为什么快)) + +算法(二叉树,中等):[102. 二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/),题解见[剑指 Offer 32.2](32.2%20把二叉树打印成多行.md)。 + +算法(二叉树,中等):[103. 二叉树的锯齿形层序遍历](https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/),题解见[剑指 Offer 32.3](32.3%20按之字形顺序打印二叉树.md)。 + +### 第 9 天:缓存问题与 Redis 集群 + +必学:[缓存问题](缓存.md#四缓存问题)、[Sentinel](Redis.md#十二sentinel)、[Redis 分片](Redis.md#十三分片)。 + +自测: + +1. 缓存穿透、击穿和雪崩有什么区别?分别怎样解决?(见[缓存问题](缓存.md#四缓存问题)) +2. 怎样保证缓存与数据库的一致性?(见[缓存一致性](缓存.md#缓存一致性)) +3. 哨兵和 Redis Cluster 分别解决什么问题?(见[Sentinel](Redis.md#十二sentinel)、[Redis Cluster](Redis.md#redis-cluster)) + +算法(二叉树,中等):[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/),题解见[二叉树的最近公共祖先](Leetcode%20题解%20-%20树.md#5-二叉树的最近公共祖先)。 + +算法(回溯与搜索,中等):[200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/),题解见[矩阵中的连通分量数目](Leetcode%20题解%20-%20搜索.md#2-矩阵中的连通分量数目)。 + +## 六、网络与操作系统 + +### 第 10 天:TCP 与 HTTPS + +必学:[UDP 和 TCP 的特点](计算机网络%20-%20传输层.md#udp-和-tcp-的特点)、[TCP 的三次握手](计算机网络%20-%20传输层.md#tcp-的三次握手)、[TCP 的四次挥手](计算机网络%20-%20传输层.md#tcp-的四次挥手)、[TCP 可靠传输](计算机网络%20-%20传输层.md#tcp-可靠传输)、[HTTPS](HTTP.md#六https)。 + +自测: + +1. 三次握手和四次挥手的过程是怎样的?为什么 TIME_WAIT 要等 2MSL?(见[三次握手的原因](计算机网络%20-%20传输层.md#三次握手的原因)、[TIME_WAIT](计算机网络%20-%20传输层.md#time_wait)) +2. TCP 和 UDP 有什么区别?TCP 怎样保证可靠传输?(见[UDP 和 TCP 的特点](计算机网络%20-%20传输层.md#udp-和-tcp-的特点)、[TCP 可靠传输](计算机网络%20-%20传输层.md#tcp-可靠传输)) +3. HTTPS 的握手过程是怎样的?(见[TLS 握手](HTTP.md#tls-握手)) + +算法(回溯与搜索,中等):[46. 全排列](https://leetcode.cn/problems/permutations/),题解见[排列](Leetcode%20题解%20-%20搜索.md#5-排列)。 + +算法(动态规划,简单):[121. 买卖股票的最佳时机](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/),题解见[买卖股票最大的收益](Leetcode%20题解%20-%20贪心思想.md#5-买卖股票最大的收益)。 + +### 第 11 天:进程、死锁与 I/O 多路复用 + +必学:[进程与线程的区别](计算机操作系统%20-%20进程管理.md#3-区别)、[协程](计算机操作系统%20-%20进程管理.md#5-协程)、[必要条件](计算机操作系统%20-%20死锁.md#必要条件)、[死锁预防](计算机操作系统%20-%20死锁.md#死锁预防)、[I/O 复用](Socket.md#二io-复用)。 + +自测: + +1. 进程、线程和协程有什么区别?(见[进程与线程的区别](计算机操作系统%20-%20进程管理.md#3-区别)、[协程](计算机操作系统%20-%20进程管理.md#5-协程)) +2. 死锁的必要条件是什么?怎样避免?(见[必要条件](计算机操作系统%20-%20死锁.md#必要条件)、[死锁预防](计算机操作系统%20-%20死锁.md#死锁预防)) +3. select、poll 和 epoll 有什么区别?(见[select、poll 与 epoll 的比较](Socket.md#比较)) + +算法(动态规划,中等):[53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/),题解见[子数组最大的和](Leetcode%20题解%20-%20贪心思想.md#10-子数组最大的和)。 + +算法(动态规划,中等):[5. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/),题解见[最长回文子串](Leetcode%20题解%20-%20字符串.md#10-最长回文子串)。 + +## 七、框架、分布式与大模型 + +### 第 12 天:Spring 与设计模式 + +必学:[AOP](Spring.md#二aop)、[Bean 的生命周期](Spring.md#bean-的生命周期)、[循环依赖](Spring.md#循环依赖)、[事务失效](Spring.md#事务失效)、[设计模式前言](设计模式%20-%20目录.md#一前言)、[单例](设计模式%20%20-%20单例.md#实现)。 + +自测: + +1. AOP 的原理是什么?JDK 动态代理和 CGLIB 有什么区别?(见[动态代理](Spring.md#动态代理)) +2. Spring 怎样解决循环依赖?(见[循环依赖](Spring.md#循环依赖)) +3. 单例模式有哪几种写法?项目中还用过哪些设计模式?(见[实现](设计模式%20%20-%20单例.md#实现)、[设计模式前言](设计模式%20-%20目录.md#一前言)) + +算法(动态规划,中等):[300. 最长递增子序列](https://leetcode.cn/problems/longest-increasing-subsequence/),题解见[最长递增子序列](Leetcode%20题解%20-%20动态规划.md#1-最长递增子序列)。 + +算法(动态规划,中等):[1143. 最长公共子序列](https://leetcode.cn/problems/longest-common-subsequence/),题解见[最长公共子序列](Leetcode%20题解%20-%20动态规划.md#1-最长公共子序列)。 + +### 第 13 天:分布式锁、消息队列与秒杀 + +必学:[分布式锁](分布式.md#一分布式锁)、[消息队列的可靠性](消息队列.md#三可靠性)、[秒杀系统](系统设计基础.md#六秒杀系统)、[限流、降级与熔断](系统设计基础.md#限流降级与熔断)。 + +自测: + +1. 用 Redis 怎样实现分布式锁?有哪些问题?(见[Redis 的 SET NX 指令](分布式.md#redis-的-set-nx-指令)) +2. 怎样保证消息不丢失、不重复消费?(见[消息队列的可靠性](消息队列.md#三可靠性)、[接收端的可靠性](消息队列.md#接收端的可靠性)) +3. 秒杀系统怎样防止超卖?(见[防止超卖的几种做法](系统设计基础.md#防止超卖的几种做法)) + +算法(双指针,困难):[42. 接雨水](https://leetcode.cn/problems/trapping-rain-water/),题解见[接雨水](Leetcode%20题解%20-%20双指针.md#9-接雨水)。 + +算法(链表,困难):[25. K 个一组翻转链表](https://leetcode.cn/problems/reverse-nodes-in-k-group/),题解见[K 个一组翻转链表](Leetcode%20题解%20-%20链表.md#11-k-个一组翻转链表)。 + +综合题:设计一个秒杀系统:从页面、网关、服务、缓存、消息队列到数据库,每一层分别做什么来扛住流量、防止超卖?出现故障时怎样降级?(见[秒杀系统](系统设计基础.md#六秒杀系统)、[限流、降级与熔断](系统设计基础.md#限流降级与熔断)、[消息队列的可靠性](消息队列.md#三可靠性)) + +### 第 14 天:大模型应用 + +必学:[RAG 的流程](大模型应用.md#流程)、[Agent 是什么](大模型应用.md#agent-是什么)、[工具调用](大模型应用.md#工具调用)、[MCP](大模型应用.md#mcp)。 + +自测: + +1. RAG 的流程是怎样的?(见[RAG 的流程](大模型应用.md#流程)) +2. Agent 由哪些部分组成?Function Calling 的原理是什么?(见[Agent 是什么](大模型应用.md#agent-是什么)、[工具调用](大模型应用.md#工具调用)) +3. MCP 和 Function Calling 有什么区别?(见[MCP](大模型应用.md#mcp)) + +算法(链表,困难):[23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/),题解见[合并 K 个有序链表](Leetcode%20题解%20-%20链表.md#13-合并-k-个有序链表)。 + +算法(动态规划,困难):[72. 编辑距离](https://leetcode.cn/problems/edit-distance/),题解见[编辑距离](Leetcode%20题解%20-%20动态规划.md#2-编辑距离)。