第一章 Java基础
基础语法与面向对象
重载与重写的区别
- 重载:同一个类中多个方法方法名相同,但参数列表不同(参数类型、个数、顺序不同)
- 重写:父子类中两个同名方法,方法名相同且参数列表相同
区别在于:
- 重载在编译阶段,由编译器根据参数来区分方法
- 重写在运行阶段,由虚拟机根据引用对象的实际类型来确定调用哪个方法
提示:可以使用 @Override 注解检查是否发生了重写
重写注意事项
- 子类方法的访问修饰符要
>= 父类方法的访问修饰符
- 子类方法抛出的检查异常类型要
<= 父类方法抛出的检查异常类型,或子类不抛异常
- 父子类的方法返回值类型要一样,或子类方法返回值是父类方法返回值的子类
== 与 equals 的区别
- 基本类型:
== 比较两边的值是否相同
- 引用类型:
== 比较两边的引用地址是否相同
equals 要看具体实现:
Object.equals() 内部实现就是 ==,即判断是否引用同一对象
String 内部实现比较两个字符串中每个字符是否相同,比较的是内容
ArrayList 内部实现比较两个集合中每个元素是否 equals
String,StringBuilder 和 StringBuffer 的区别
| 类型 | 可变性 | 线程安全 | 适用场景 |
|---|
| String | 不可变 | 安全 | 大部分场景 |
| StringBuilder | 可变 | 不安全 | 单线程字符串拼接 |
| StringBuffer | 可变 | 安全 | 多线程字符串拼接 |
String 设计为不可变的原因:
final 修饰只是条件之一
- 不可变的好处:线程安全、可以缓存 hashCode 等
Java中的异常
Throwable
├── Error(无法恢复的错误,如 OutOfMemoryError、StackOverflowError)
└── Exception(可恢复的错误)
└── RuntimeException(非检查异常/运行时异常)
Exception 与 RuntimeException 的区别:
- Exception:检查异常,必须在语法层面处理(try-catch 或 throws)
- RuntimeException:非检查异常,语法层面不要求强制处理
常见的非检查异常:
- 空指针异常(NullPointerException)
- 算术异常(ArithmeticException,除零)
- 数组索引越界异常(ArrayIndexOutOfBoundsException)
- 类型转换异常(ClassCastException)
异常处理方式:
- 自己处理:用 catch 捕捉,进行补救(如记录日志)
- 继续抛出:用 throw 抛给上层调用者处理
集合类
常见数据结构
线性结构
| 数据结构 | 特点 | Java实现 |
|---|
| 动态数组 | 元素连续存储,可扩容 | ArrayList |
| 链表 | 元素不连续存储 | LinkedList |
| 栈 | 先进后出(FILO) | LinkedList(push/pop/peek) |
| 队列 | 先进先出(FIFO) | LinkedList(offer/poll) |
非线性结构
| 数据结构 | 特点 | Java实现 |
|---|
| 优先级队列 | 按优先级调整顺序 | PriorityQueue |
| 哈希表 | key-value映射,快速查找 | HashMap、Hashtable |
| 红黑树 | 自平衡二叉查找树 | TreeMap |
| 跳表 | 多级链表结构 | ConcurrentSkipListMap |
| B+树 | 自平衡N叉查找树 | 关系型数据库索引 |
Java常见集合类
接口关系
Collection(父接口)
├── List(有序、可重复)
│ ├── ArrayList(数组实现,随机访问快)
│ ├── LinkedList(链表实现,增删快)
│ └── Vector(数组实现,线程安全)
└── Set(无序、不可重复)
├── HashSet(基于HashMap)
├── LinkedHashSet(保持插入顺序)
└── TreeSet(基于红黑树,有序)
Map(独立接口)
├── HashMap(数组+链表+红黑树)
├── LinkedHashMap(保持插入顺序)
├── TreeMap(红黑树)
├── Hashtable(线程安全)
└── ConcurrentHashMap(高效线程安全)
ArrayList vs LinkedList
| 操作 | ArrayList | LinkedList |
|---|
| 随机访问 | O(1),快 | O(n),慢 |
| 头尾操作 | 涉及元素移动 | O(1),快 |
| 增删 | 涉及元素移动 | O(1),但需先定位 |
HashMap 特点
- 底层:数组 + 链表 + 红黑树
- Key 需要实现 hashCode 和 equals 方法
- 链表过长(长度 >= 8 且数组容量 >= 64)会树化为红黑树
- 树中节点删除过少时会退化为链表
线程安全对比
| 类 | 线程安全实现方式 |
|---|
| Hashtable | synchronized 加在所有方法上 |
| ConcurrentHashMap | synchronized 只锁一个链表/红黑树 |
| Vector | synchronized |
| StringBuffer | synchronized |
HashMap 原理
数据结构
- 数组:利用 key 的 hashCode 计算索引,O(1) 存取
- 冲突:利用链表解决(链地址法)
- 红黑树:链表过长时树化,O(log n) 查询
扩容机制
- 扩容因子:0.75
- 初始容量:16
- 每次扩容:容量翻倍
- 扩容后重新计算桶下标
put 方法执行流程
- 生成 hash:调用 key.hashCode(),进行高低位异或运算
- 创建数组:首次 put 时创建容量为 16 的数组
- 计算桶下标:(n - 1) & hash
- 处理三种情况:
- 桶为空:直接插入
- 桶为链表:遍历查找或追加到尾部
- 桶为红黑树:树新增/更新逻辑
树化条件
网络编程
BIO、NIO、AIO
| 模式 | 特点 | 适用场景 |
|---|
| BIO(阻塞I/O) | 线程阻塞等待连接和数据 | 并发低,代码简单 |
| NIO(非阻塞I/O) | 多路复用,事件驱动 | 高并发 |
| AIO(异步I/O) | 回调函数,Linux下仍用多路复用 | 少用 |
关键概念:
- 阻塞:线程等待,腾不出手干别的
- 非阻塞:线程可以干别的
- 多路复用:以事件方式处理连接和请求
Java 21+ 虚拟线程:
- 以 BIO 方式编写代码
- 虚拟线程廉价,可劲加
- 底层配合多路复用,兼具高性能
I/O流分类
按单位分:
├── 字节流(InputStream/OutputStream)
└── 字符流(Reader/Writer)
按功能分:
├── 转换流(InputStreamReader/OutputStreamWriter)
├── 缓冲流(BufferedInputStream/BufferedOutputStream 等)
└── 对象流(ObjectInputStream/ObjectOutputStream)
线程与并发
ThreadLocal 原理
- 每个线程内部有 ThreadLocalMap
- ThreadLocal 作为 key,要隔离的资源作为 value
ThreadLocal.set():存值
ThreadLocal.get():取值
- 注意:用完后一定要调用
remove() 清空,避免内存泄漏
悲观锁 vs 乐观锁
| 类型 | 代表实现 | 竞争失败处理 | 适用场景 |
|---|
| 悲观锁 | synchronized、Lock | 阻塞 | 竞争多,独占时间长 |
| 乐观锁 | AtomicInteger 等 | 重试 | 竞争少,能快速占有 |
synchronized 原理
- 根据对象头找到/创建 Monitor 对象
- CAS 设置 owner 为当前线程
- 成功:执行同步代码块
- 失败:自旋若干次重试
- 仍失败:进入 Monitor 等待队列阻塞
锁升级
偏向锁 → 轻量级锁 → 重量级锁
- 一个线程加锁:偏向锁
- 多个线程交替加锁但无竞争:轻量级锁
- 多个线程竞争:重量级锁
注意:Java 15 开始偏向锁已废弃
synchronized vs volatile
| 特性 | volatile | synchronized |
|---|
| 原子性 | ❌ | ✅ |
| 可见性 | ✅ | ✅ |
| 有序性 | ✅ | ✅ |
synchronized vs Lock
| 特性 | synchronized | Lock |
|---|
| 性质 | 关键字 | 接口 |
| 实现 | 底层C++ | Java代码 |
| 公平锁 | ❌ | ✅ |
| 超时 | ❌ | ✅ |
| 可打断 | ❌ | ✅ |
| 释放 | 自动释放 | 需手动调用 unlock |
线程池核心参数
- 核心线程数:线程池常驻线程数
- 最大线程数:线程池最大线程数
- 存活时间:超过核心线程数的空闲线程存活时间
- 存活时间单位
- 工作队列:暂时无法处理的任务放入此队列
- 线程工厂:控制线程命名规则、是否守护线程
- 拒绝策略:
- AbortPolicy:抛异常
- CallerRunsPolicy:推脱给提交线程
- DiscardOldestPolicy:抛弃最老任务
- DiscardPolicy:直接抛弃
JVM虚拟机
堆内存结构
传统垃圾回收器
堆内存
├── 年轻代
│ ├── Eden 区
│ └── S0、S1(幸存区)
└── 老年代
G1 垃圾回收器
- 把内存划分为多个 Region
- 每个 Region 可充当 Eden、幸存区、老年代
- 巨型对象单独存放
垃圾回收算法
| 算法 | 优点 | 缺点 |
|---|
| 标记-清除 | 回收快 | 内存碎片 |
| 标记-整理 | 无碎片 | 速度慢 |
| 标记-复制 | 无碎片,适合存活对象少 | 占用空间 |
对象晋升条件
- 默认:经历 15 次新生代回收(可配置
-XX:MaxTenuringThreshold)
- 提前晋升:幸存区中某年龄对象空间占比超过 50%
大对象处理
- Serial/CMS:对象大小超过阈值直接晋升老年代(
-XX:PretenureSizeThreshold)
- G1:对象大小超过 Region 一半存入巨型对象区
Lambda表达式
什么是 Lambda
- 匿名函数,语法:
(参数) -> 表达式
- 本质是函数对象
- 用于行为参数化场景
Lambda vs 匿名内部类
| 特性 | Lambda | 匿名内部类 |
|---|
| 接口限制 | 必须是函数式接口 | 任意接口/抽象类 |
| 语法 | 更简洁 | 较繁琐 |
| 编译/运行 | 运行阶段动态生成 | 编译阶段生成 |
| this | 指代外部类 | 指代匿名内部类本身 |
反射及泛型
反射
- 运行期间根据类名加载类
- 获取类的属性、方法、接口等信息
- 动态创建对象、调用方法
应用场景:Spring bean创建、依赖注入、MyBatis映射
泛型
Tomcat优化
主要配置项
server.tomcat.max-connections=8192 # 最大连接数
server.tomcat.accept-count=100 # 连接队列数
server.tomcat.threads.max=200 # 最大线程数
server.tomcat.threads.min-spare=10 # 最小备用线程
虚拟线程优化(SpringBoot 3.2.x + JDK 21)
spring.threads.virtual.enabled=true
第二章 基础算法
加密算法
加密算法分类
- 对称加密:DES、AES、SM4
- 非对称加密:RSA、ECDSA、SM2
- 哈希摘要:MD5、SHA-2、SHA-3、SM3
- 电子签名:RSA/ECDSA + 哈希摘要、HMAC
- 密码存储:加盐存储、BCrypt
对称加密 vs 非对称加密
| 特性 | 对称加密 | 非对称加密 |
|---|
| 密钥 | 同一个 | 公钥+私钥 |
| 速度 | 快 | 慢 |
| 密钥管理 | 需妥善保管 | 私钥保管,公钥公开 |
哈希摘要
- 提取原始数据的特征
- 用于数据完整性校验
- 单向不可逆
密码存储
- 单纯哈希:易被彩虹表攻击
- 加盐存储:增加破解难度
- BCrypt:多次迭代+加盐+成本因子
算法对比
| 算法 | 密钥长度 | 备注 |
|---|
| DES | 56位 | 已不推荐 |
| AES | 128/192/256位 | 全球广泛使用 |
| SM4 | 128位 | 中国商用密码 |
| RSA | 1024~4096位 | 广泛使用 |
| SM2 | 256位 | 中国国家密码 |
| ECDSA | - | 与SM2原理类似 |
排序算法
排序算法分类
排序算法
├── 比较排序
│ ├── O(n²):冒泡、选择、插入、希尔
│ └── O(nlogn):快排、归并、堆排序
└── 非比较排序
├── 计数排序:O(n+r)
├── 桶排序:O(n)
└── 基数排序:O(w*(n+k))
复杂度对比表
| 算法 | 最好 | 最坏 | 平均 | 空间 | 稳定 | 思想 |
|---|
| 冒泡 | n | n² | n² | 1 | 是 | 比较 |
| 选择 | n² | n² | n² | 1 | 否 | 选择 |
| 插入 | n | n² | n² | 1 | 是 | 比较 |
| 希尔 | nlog n | n^1.5 | n^1.3 | 1 | 否 | 插入 |
| 归并 | nlog n | nlog n | nlog n | n | 是 | 分治 |
| 快速 | nlog n | n² | nlog n | log n | 否 | 分治 |
| 堆 | nlog n | nlog n | nlog n | 1 | 否 | 选择 |
冒泡排序
思路:
- 将数组分成已排序区和未排序区
- 每轮从左向右两两比较,逆序则交换
- 每轮结束,最大值移到已排序区
- 重复直至只剩一个元素
优化:记录最后一次交换位置,减少无效比较
选择排序
思路:
- 分为已排序区和未排序区
- 每轮选出未排序区最大元素,交换到已排序区
- 重复直至只剩一个元素
特点:不稳定排序(相等元素相对位置可能改变)
插入排序
思路:
- 分为已排序区(左边)和未排序区(右边)
- 每次从未排序区最左侧拿元素,与已排序区从右向左比较
- 找到合适位置插入
适用场景:
归并排序
思路:
- 分:数组不断二分,直至只剩一个元素
- 治:小数组已有序
- 合:有序小数组两两合并
特点:稳定排序,时间复杂度稳定 O(nlog n)
快速排序
思路:
- 选择最左侧元素作为基准点
- 将比基准点小的移到左边,大的移到右边
- 基准点到位,对左右分区重复
优化:
堆排序
思路:
- 建立大顶堆
- 堆顶元素(最大)交换到数组尾部
- 对剩余元素下潜调整
- 重复直至只剩一个元素
字符串类
字符串反转
思路:双指针交换
public void reverseString(char[] s) {
int i = 0, j = s.length - 1;
while (i < j) {
char temp = s[i];
s[i++] = s[j];
s[j--] = temp;
}
}
正则表达式应用
- 表单校验(邮箱、手机号、身份证)
- 网页爬取(抽取图片链接)
- 日志处理(提取特定信息)
- 路由规则配置
- 数据清洗
搜索类
二分查找
条件:有序数组
思路:
- 定义左右指针
- 取中间元素比较
- 目标小则左半部分继续,目標大则右半部分继续
- 找到返回索引,未找到返回 -1
复杂度:O(log n)
回溯算法
概念:记录每步状态,不成功时撤销回到上一步,换种方法尝试
常结合递归实现
常见应用:N皇后问题、迷宫问题、组合优化
第三章 Web阶段
HTTP协议
HTTP vs HTTPS
| 特性 | HTTP | HTTPS |
|---|
| 安全性 | 明文传输 | SSL加密 |
| 端口 | 80 | 443 |
| 资源消耗 | 低 | 高 |
GET vs POST
| 特性 | GET | POST |
|---|
| 参数位置 | URL | 请求体 |
| 大小限制 | URL长度限制 | 服务器配置 |
| 安全性 | 低(URL暴露) | 较高 |
| 用途 | 获取数据 | 提交数据 |
RESTful 风格
- URL:定位资源(如
/users/1)
- 请求方式:决定操作(GET查、POST增、PUT改、DELETE删)
常见状态码
| 状态码 | 含义 |
|---|
| 200 | 成功 |
| 302 | 重定向 |
| 401 | 未认证 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
转发 vs 重定向
| 特性 | 转发 | 重定向 |
|---|
| 请求次数 | 1次 | 2次 |
| 发生位置 | 服务器 | 客户端 |
| URL变化 | 不变 | 变化 |
会话跟踪
Cookie
- 客户端会话跟踪方案
- 服务器创建,通过 Set-Cookie 响应头返回
- 浏览器自动存储,后续请求自动携带
- 不安全(用户可操作)
Session
- 服务器端会话跟踪方案
- 服务器创建 Session 对象,生成唯一ID
- 通过 Cookie(JSESSIONID)传递 SessionID
- 相对安全
- 集群环境下需要 Session 共享
第四章 数据库
基础知识
char vs varchar
| 特性 | char | varchar |
|---|
| 存储方式 | 定长 | 变长 |
| 性能 | 快 | 慢 |
| 空间 | 固定占用 | 按需占用 |
| 适用场景 | 固定长度(手机号、身份证) | 不固定长度(用户名、备注) |
事务四大特性(ACID)
| 特性 | 含义 |
|---|
| 原子性 | 不可分割,要么全成功要么全失败 |
| 一致性 | 事务前后数据处于一致状态 |
| 隔离性 | 事务独立运行,不受外部并发影响 |
| 持久性 | 提交后改变永久保存 |
并发事务问题
| 问题 | 含义 |
|---|
| 脏读 | 读取到另一事务未提交的数据 |
| 不可重复读 | 同一事务中两次读取数据不同 |
| 幻读 | 按条件查询无结果,但插入时发现已存在 |
隔离级别
| 级别 | 脏读 | 不可重复读 | 幻读 |
|---|
| READ UNCOMMITED | ❌ | ❌ | ❌ |
| READ COMMITED | ✅ | ❌ | ❌ |
| REPEATABLE READ | ✅ | ✅ | ❌ |
| SERIALIZABLE | ✅ | ✅ | ✅ |
MySQL 默认:REPEATABLE READ
索引基础
索引数据结构
InnoDB 默认:B+Tree
B+Tree 特点:
- 非叶子节点只存索引(key + 指针)
- 叶子节点存所有数据,形成双向链表
- 区间查询高效
聚簇索引 vs 二级索引
| 特性 | 聚簇索引 | 二级索引 |
|---|
| 数据存储 | 叶子节点存整行数据 | 叶子节点存主键 |
| 数量 | 每表一个 | 每表多个 |
| 默认 | 主键索引 | 其他索引 |
回表查询:先查二级索引获取主键,再查聚簇索引获取完整数据
索引失效场景
- 违反最左前缀法则
- 范围查询右侧的列
- 索引列上使用函数或运算
- 隐式类型转换
- 以
% 开头的 like 模糊匹配
索引下推
- MySQL 5.6+ 提供
- 在存储引擎层筛选条件,减少回表次数
SQL优化
定位慢SQL
- SkyWalking:链路追踪查看耗时
- 慢查询日志:配置超过指定时间的SQL记录
执行计划分析(explain)
type 性能排序:
NULL > system > const > eq_ref > ref > range > index > all
优化目标:
- 避免 type 为 all(全表扫描)
- 关注 extra 信息(回表、排序)
第五章 Spring框架
IOC 与 DI
IOC(控制反转)
- 工厂模式创建对象放入容器
- 使用时由容器提供,不用自行 new
DI(依赖注入)
- 容器向 bean 注入依赖对象
- 方式:构造函数注入、成员变量注入
声明Bean注解
| 层级 | 注解 |
|---|
| Controller | @Controller、@RestController |
| Service | @Service |
| Dao | @Repository、@Mapper |
| 其他 | @Component、@Configuration |
依赖注入注解
| 注解 | 特点 |
|---|
| @Autowired | 默认按类型注入 |
| @Resource | 默认按名称注入 |
Bean作用域
| 作用域 | 含义 |
|---|
| singleton | 单例(默认) |
| prototype | 非单例 |
| request | 每个请求一个实例 |
| session | 每个会话一个实例 |
Bean生命周期
- 实例化:调用构造函数
- 依赖注入:属性注入
- 处理Aware接口:BeanNameAware、BeanFactoryAware等
- BeanPostProcessor前置:postProcessBeforeInitialization
- 初始化方法:InitializingBean、@PostConstruct
- BeanPostProcessor后置:postProcessAfterInitialization(可能产生代理)
- 销毁:@PreDestroy、destroy-method
Bean循环依赖
三级缓存
| 缓存 | 作用 |
|---|
| singletonObjects(一级) | 完整生命周期,已初始化 |
| earlySingletonObjects(二级) | 早期引用,半成品 |
| singletonFactories(三级) | ObjectFactory,创建代理对象 |
解决流程
- A 实例化,创建 ObjectFactory 存入三级缓存
- A 依赖注入 B,发现 B 不存在,创建 B
- B 实例化,创建 ObjectFactory 存入三级缓存
- B 依赖注入 A,从三级缓存获取 A(生成代理或原始对象)存入二级缓存
- B 创建成功,存入一级缓存
- A 注入 B 成功,A 创建成功
构造函数的循环依赖
AOP
概念
- 面向切面编程
- 将公共行为抽取复用,降低耦合
- 应用:日志记录、事务控制、权限控制
底层实现
- JDK 动态代理:代理实现接口的类
- Cglib 动态代理:代理任意非 final 类(继承方式)
通知类型
| 通知 | 含义 |
|---|
| @Before | 前置通知 |
| @After | 后置通知 |
| @AfterReturning | 返回通知 |
| @AfterThrowing | 异常通知 |
| @Around | 环绕通知 |
事务
@Transactional
- 本质:AOP 方法前后拦截
- 默认只对 RuntimeException 回滚
- 可配置 rollbackFor 为 Exception.class
传播行为
| 传播行为 | 含义 |
|---|
| REQUIRED | 无事务则新建,有则加入(默认) |
| REQUIRES_NEW | 总是新建事务 |
第六章 SpringMVC
核心组件
| 组件 | 作用 |
|---|
| DispatcherServlet | 核心控制器,分发请求 |
| HandlerMapping | 根据URL匹配处理器 |
| HandlerAdapter | 执行处理器 |
| Handler | Controller中的方法 |
| ViewResolver | 视图解析 |
请求执行流程
- 请求到 DispatcherServlet
- HandlerMapping 查找 Handler
- HandlerAdapter 执行 Handler
- 返回 ModelAndView
- ViewResolver 解析 View
- 渲染视图
- 响应用户
拦截器
使用步骤
- 实现 HandlerInterceptor 接口
- 实现 WebMvcConfigurer 配置拦截路径
拦截器 vs 过滤器
| 特性 | 过滤器 | 拦截器 |
|---|
| 接口 | Filter | HandlerInterceptor |
| 拦截范围 | Web服务器所有资源 | Spring环境(Controller) |
| 实现机制 | 函数回调 | 反射 |
异常处理
- 全局异常处理器:@RestControllerAdvice + @ExceptionHandler
第七章 SpringBoot
核心功能
- starter 起步依赖:简化依赖配置
- 自动配置:条件注解决定是否创建 Bean
- jar 包运行:内嵌 Web 服务器
配置优先级
命令行参数 > Java系统属性 > application.properties > application.yml > application.yaml
自动配置原理
- @SpringBootApplication 包含 @EnableAutoConfiguration
- @EnableAutoConfiguration 导入 ImportSelector
- 读取 META-INF/spring.factories(SpringBoot 3.x 为 .imports)
- 根据 @Conditional 条件决定是否加载
第八章 Mybatis
执行流程
- 加载 mybatis-config.xml
- 构建 SqlSessionFactory
- 创建 SqlSession
- Executor 执行器操作数据库
- MappedStatement 封装 SQL 和参数映射
- 结果映射到 Java 对象
缓存机制
| 缓存 | 范围 | 开启 | 实现 |
|---|
| 一级缓存 | SqlSession | 默认开启 | HashMap |
| 二级缓存 | Mapper | 需手动配置 | - |
分页
- PageHelper:PageHelper.startPage(页号, 页大小)
- MyBatis Plus:IPage = userService.page(new Page<>(页号, 页大小))
第九章 SpringCloud
Nacos
服务注册流程
- 服务启动注册到注册中心
- 调用者订阅服务获取实例列表
- 负载均衡选择实例
- 发起远程调用
- 定时发送心跳
- 注册中心剔除不健康实例
- 变更时主动通知
Nacos vs Eureka
| 特性 | Nacos | Eureka |
|---|
| 心跳间隔 | 5秒 | 30秒 |
| 剔除超时 | 15秒超时,30秒剔除 | 90秒 |
| 服务列表更新 | 定时+推送 | 定时 |
| 功能 | 注册中心+配置中心 | 仅注册中心 |
OpenFeign
服务调用流程
- 获取请求中的 serviceId
- 负载均衡找出可用实例
- 用 IP 和 port 重构 URL
- 发起请求
负载均衡策略
Ribbon
- RoundRobinRule(轮询)
- RandomRule(随机)
- WeightedResponseTimeRule(加权)
- RetryRule(重试)
Spring Cloud LoadBalancer
- RoundRobinLoadBalancer(轮询)
- RandomLoadBalancer(随机)
- NacosLoadBalancer(Nacos特有)
限流
Hystrix vs Sentinel
| 特性 | Hystrix | Sentinel |
|---|
| 实现方式 | 线程池/信号量 | 流量控制、熔断降级 |
| 功能 | 熔断、线程隔离、超时 | 更丰富 |
滑动窗口算法
- 窗口时间跨度固定
- 时间区间 = 窗口跨度 / n
- 窗口随请求时间移动
Gateway
作用
路由断言类型
| 类型 | 说明 |
|---|
| After | 某时间点后 |
| Before | 某时间点前 |
| Between | 两时间点之间 |
| Cookie | Cookie匹配 |
| Header | 请求头匹配 |
| Host | 域名匹配 |
| Method | 请求方式匹配 |
| Path | 路径匹配 |
| Query | 参数匹配 |
过滤器
| 过滤器 | 作用 |
|---|
| AddRequestHeader | 添加请求头 |
| AddRequestParameter | 添加请求参数 |
| RewritePath | 重写路径 |
| StripPrefix | 去除前缀 |
| SetStatus | 设置状态码 |
| AddResponseHeader | 添加响应头 |
第十章 常用组件
Nginx
正向代理 vs 反向代理
| 类型 | 特点 |
|---|
| 正向代理 | 代理客户端,隐藏真实客户端 |
| 反向代理 | 代理服务器,隐藏真实服务器 |
CDN
- 内容分发网络
- 就近访问加速
- 负载均衡
- 减轻源站压力
- 安全防护
负载均衡算法
限流配置
http {
limit_req_zone $binary_remote_addr zone=limit:10m rate=10r/s;
server {
location / {
limit_req zone=limit burst=20 nodelay;
}
}
}
分布式事务
CAP 定理
- Consistency(一致性)
- Availability(可用性)
- Partition tolerance(分区容错性)
- 三者不可同时满足
BASE 理论
- Basically Available(基本可用)
- Soft State(软状态)
- Eventually Consistent(最终一致)
2PC(两阶段提交)
- 准备阶段:协调者发送准备请求,参与者执行本地事务
- 提交阶段:全部成功则提交,否则回滚
Seata 模式
| 模式 | 说明 |
|---|
| AT | 自动补偿,最常用 |
| TCC | Try-Confirm-Cancel |
| SAGA | 状态驱动 |
| XA | 两阶段提交 |
注意:AT 模式是柔性事务,非强一致性
分布式锁
实现方案
| 方案 | 特点 |
|---|
| 数据库 | 唯一性约束或悲观锁 |
| Redis | SETNX,高性能 |
| ZooKeeper | CP模式,高可靠性 |
Redisson 使用
RLock lock = redisson.getLock("myLock");
try {
boolean isLocked = lock.tryLock(100, 30, TimeUnit.SECONDS);
if (isLocked) {
// 业务逻辑
}
} finally {
lock.unlock();
}
可重入实现
- 记录持有锁的线程和计数
- 同一线程重复获取只递增计数
- 释放时递减,计数为0才真正释放
Redis
数据类型
| 类型 | 用途 | 命令示例 |
|---|
| String | 字符串/数字 | SET、GET |
| Hash | 对象属性 | HSET、HGET |
| List | 队列/栈 | LPUSH、RPOP |
| Set | 去重集合 | SADD、SMEMBERS |
| ZSet | 排行榜 | ZADD、ZRANGE |
持久化策略
集群模式
| 模式 | 特点 |
|---|
| 主从 | 读写分离,故障转移 |
| 分片 | 数据分片,横向扩展 |
Redis 挂了怎么办
- 集群+哨兵自动故障转移
- 降级查数据库
- 本地缓存兜底