20230119
This commit is contained in:
parent
469f395dfe
commit
5cb2aaaae8
|
@ -0,0 +1,4 @@
|
|||
## 垃圾回收器
|
||||
## 垃圾回收策略
|
||||
## 垃圾回收算法
|
||||
## StopTheWorld
|
|
@ -0,0 +1,3 @@
|
|||
类加载器
|
||||
类加载过程
|
||||
双亲委派机制
|
|
@ -0,0 +1 @@
|
|||
正向代理是帮客户端做事情,反向代理是帮服务器做事情
|
|
@ -0,0 +1,6 @@
|
|||
目的是解决分布式缓存的问题。
|
||||
在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系
|
||||
|
||||
## 参考链接
|
||||
|
||||
https://developer.huawei.com/consumer/cn/forum/topic/0203810951415790238
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
## WARO: Write ALl Read One
|
||||
|
||||
当客户端向一个分布式应用发送写请求的时候,只有当所有的副本节点都更新成功之后,这次写操作才算成功。否则视为失败。这降低了写操作的可用性,提高了读操作的可用性。
|
||||
|
||||
## Quorm: 最终一致性
|
||||
|
||||
假设有N个副本,客户端向一个分布式应用发送写请求的时候,如果有W个副本更新成功之后,这次写操作才算成功。则读操作最多需要读N-W个副本就能读取到最新的结果。
|
||||
|
||||
Quorm无法保证强一致性,它是分布式系统中常用的一种机制,用来保证数据冗余的最终一致性的投票算法。Kafka的ISR机制有点类似该机制。
|
||||
|
||||
## **Paxos算法**
|
||||
|
||||
有三类角色节点:
|
||||
|
||||
* Proposer 提案者
|
||||
|
||||
一个或多个提案者提出操作(例如修改值),多个提案者可以提出不同的操作,经过一轮Paxos算法后,只有一个提案者被运行执行
|
||||
|
||||
* Acceptor 批准者
|
||||
|
||||
设有N个批准者,提案者提出的操作,必须获得半数以上的批准者批准后才能通过执行
|
||||
|
||||
* Learner 学习者
|
||||
|
||||
学习者不参与上述行为,而是执行被批准者批准的操作
|
|
@ -0,0 +1,60 @@
|
|||
## 简介
|
||||
|
||||
如果服务A和服务B之间是同步调用,比如服务C需要按流程调服务A和服务B,服务A和服务B要么一起成功,要么一起失败。
|
||||
针对这种情况,目前业内普遍推荐使用TCC事务来解决的
|
||||
TCC的全称是(Try-Confirm-Cancel)
|
||||
|
||||
## 业务场景样例
|
||||
|
||||
支付服务 需要完成以下调用 订单服务(修改订单状态)、账户服务(扣除余额)、库存服务(扣减库存数量)
|
||||
为了达到事务的效果,要么一起成功,要么一起失败
|
||||
|
||||
为了达到这种效果,每个服务提供三种接口
|
||||
```java
|
||||
// 以订单服务为例
|
||||
orderClient.tryUpateStatus(); // T - try
|
||||
orderClient.confirmUpateStatus(); // C - confirm
|
||||
orderClient.cancelUpateStatus(); // C - cancel
|
||||
```
|
||||
|
||||
TCC的缺点主要在于对于代码侵入性大,每套业务逻辑都要这么拆分成三个接口。
|
||||
|
||||
伪代码如下
|
||||
|
||||
```java
|
||||
public class PayServiceImpl{
|
||||
private OrderClient orderClient;
|
||||
private AccountClient accountClient;
|
||||
private RepositoryClient repositoryClient;
|
||||
public void makePayment throws Throwable{
|
||||
try{
|
||||
orderClient.tryUpdateStatus(); // 修改订单状态
|
||||
accountClient.tryDecrease(); // 扣款
|
||||
repositoryClient.tryDesrease(); // 库存减少
|
||||
}catch(Throwable t){
|
||||
// 遇到错误回滚事务
|
||||
orderClient.cancelUpdateStatus();
|
||||
accountClient.cancelDecrease();
|
||||
repositoryClient.cancelDecrease();
|
||||
}
|
||||
// 提交事务
|
||||
orderClient.confirmUpdateStatus();
|
||||
accountClient.confirmDecrease();
|
||||
repositoryClient.confirmDecrease();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这里用了一段简单的代码来描述这个过程,但是这段代码存在很多问题,比如cancel和confirm出现异常如何处理?还有涉及到大量逻辑重复问题。
|
||||
|
||||
## hmily框架
|
||||
|
||||
分布式事务框架
|
||||
|
||||
## Seata框架
|
||||
|
||||
参见`分布式事务 - Seata框架.md`
|
||||
|
||||
## 参考链接
|
||||
|
||||
https://cloud.tencent.com/developer/article/1844341
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
## 2PC - 两阶段提交协议
|
||||
|
||||
* 一个节点为管理者,其他节点为参与者
|
||||
* 协调者要求每个涉及到该事务的服务预提交此操作,并反映是否可以提交
|
||||
* 根据反映,要求每个服务提交或者回滚
|
||||
|
||||
缺点:
|
||||
1. 管理者为单点,故障后整个集群无法使用
|
||||
2. 执行过程中,所有参与事务的节点都是独占状态,其他管理者需要阻塞等待上一个事务完成后才能继续
|
||||
3. 在执行commit过程中,如果只有一部分参与者收到并执行,此时会产生数据不一致
|
||||
|
||||
## 3PC - 三阶段提交协议
|
||||
|
||||
为了解决2PC的独占导致占用阻塞问题,引入了超时机制
|
||||
分为三步
|
||||
1. CanCommit,发生请求询问是否可以调节
|
||||
2. PreCommit,根据CanCommit响应有两种情况。若所有的节点都是Yes,向每个服务发送PreCommit,并要求反馈ACK;
|
||||
若任意一个节点返回No,或者等待超时,则进行中断操作,向每个服务发生Abort,放弃事务的执行。
|
||||
3. DoCommit,根据PreCommit响应有两种情况。若所有都ACK则发生DoCommit请求,并要求反馈ACK;
|
||||
若没收到所有的ACK响应,则中断事务
|
||||
|
||||
缺点:在执行DoCommit过程中,如果只有一部分参与者收到并执行,此时会产生数据不一致
|
||||
|
||||
## TCC
|
||||
|
||||
参考`分布式事务 - TCC事务模型.md`
|
||||
|
||||
优点:
|
||||
1. TCC解决了跨服务的业务操作原子性问题,可以让应用自己定义数据库操作的粒度,降低锁冲突,提高系统的业务吞吐量。
|
||||
2. TCC的每一阶段都由业务自己控制,避免了长事务,提高了性能。
|
||||
|
||||
缺点:
|
||||
1. 业务侵入性强:业务逻辑必须都要实现Try,Confirm,Cancel三个操作
|
|
@ -0,0 +1,32 @@
|
|||
## UUID
|
||||
|
||||
优点:性能好,本地生成,全局唯一。
|
||||
缺点:
|
||||
1. UUID长度固定为32位,对于Mysql索引来说,所有的非主键索引都会包含一个主键,UUID长度过长会不利于MySql的存储和性能。
|
||||
2. UUID是乱序的,每一次UUID数据的插入都会对主键地城的b+树进行很大的修改。
|
||||
3. 信息不安全,UUID里包含了MAC地址,芯片ID码能信息。会造成信息泄露。
|
||||
|
||||
## 数据库自增ID
|
||||
|
||||
对于多台数据库,可以设定不同的起始值以及跨度,可以实现全局自增ID,例如:
|
||||
> 数据库1:起始1 跨度4 -> 1,5,9,...
|
||||
> 数据库2:起始2 跨度4 -> 2,6,10,...
|
||||
> 数据库3:起始3 跨度4 -> 3,7,11,...
|
||||
> 数据库4:起始4 跨度4 -> 4,8,12,...
|
||||
|
||||
优点:容易存储,可以直接用数据库存储。
|
||||
缺点:
|
||||
1. 统水平扩展比较困难,定义好步长和机器台数之后,再增加数据库需要重调整所有的数据库起始值增值和自增值的跨度。
|
||||
2. 数据库压力大,每次获取ID都会写一次数据库。
|
||||
3. 信息不安全,递增性太强。很容根据两个ID的差值判断竞争对手的中间的出单量。
|
||||
|
||||
## Snowflake
|
||||
|
||||
生成一个64bit,由1bit标识位+41bit时间戳+10bit机器位+12bit序列号构成
|
||||
|
||||
优点:趋势递增,不依赖第三方组件(数据库等),性能更高,可以根据自身业务特点动态分配bit位。
|
||||
缺点:强依赖机器时钟,如果出现时钟回拨,那么整个系统生成的ID将会不可用。
|
||||
|
||||
|
||||
|
||||
## nanoid
|
|
@ -0,0 +1,35 @@
|
|||
## CAP
|
||||
|
||||
### C - 一致性
|
||||
|
||||
如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。即所有的节点同时看到相同的数据
|
||||
|
||||
### A - 可用性
|
||||
|
||||
非故障的节点在合理的时间内返回合理的响应。任何时候,读写都是成功的。
|
||||
|
||||
### P - 分区容错性
|
||||
|
||||
当部分节点出现消息丢失或故障的时候,分布式系统仍能正常工作。
|
||||
|
||||
### 结论
|
||||
|
||||
CAP理论认为:一个分布式系统最多只能同时满足,一致性,可用性,分区容错性的三项中的两项。由于分区容错性是必然存在的,所以大部分分布式软件系统都在CP和AP中做取舍
|
||||
|
||||
## BASE
|
||||
|
||||
Base理论:即基本可用(Basically Available),软状态(Soft State),最终一致性(Eventually Consistent)
|
||||
|
||||
既然无法做到强一致性,那么不同的应用可用根据自己的业务特点,采用适当的方式来达到最终一致性。
|
||||
|
||||
Base理论是对CAP理论的实际应用
|
||||
|
||||
* **基本可用性**:不追求强可用性,而且强调系统基本能够一直运行对外提供服务,当分布式系统遇到不可预估的故障时,允许一定程度上的不可用,比如:对请求进行限流排队,使得部分用户响应时间变长,或对非核心服务进行降级。
|
||||
* **软状态**:对于数据库中事务的原子性:要么全部成功,要不全部不成功。软状态允许系统中的数据存在中间状态。
|
||||
* **最终一致性**:数据不可能一直都是软状态,必须在一个时间期限之后达到各个节点的一致性。在此之后,所有的节点的数据都是一致的。系统达到最终一致性。
|
||||
|
||||
|
||||
|
||||
## 参考链接
|
||||
|
||||
https://segmentfault.com/a/1190000022740402
|
|
@ -0,0 +1,58 @@
|
|||
## 基于数据库的分布式锁实现方案
|
||||
|
||||
获得锁:表中插入一条记录
|
||||
释放锁:删除该记录
|
||||
|
||||
问题:
|
||||
1. 为了预防单点故障,数据库可以配置主从
|
||||
2. 为了预防超时问题,可以设置时间戳等方式删除超时数据
|
||||
3. 不可重入:同一个线程在没有释放锁之前不能再次获得该锁。实现可重入需要改造加锁方法,增加存储和判断线程信息
|
||||
4. 阻塞等待问题:使用数据库获取锁的时候,如果获取失败会直接返回,因此需要轮询获取锁
|
||||
5. 主从问题,在高并发的场景下,数据库主从延时增大,线程读取的数据非最新版,导致锁重复。
|
||||
|
||||
## 基于Zookeeper的分布式锁实现方案
|
||||
|
||||
### 独占锁-使用临时节点实现
|
||||
|
||||
获得锁: 当要对某个资源加锁时,Zookeeper在该资源对应的指定的节点目录下,生成一个唯一的临时节点。其他客户端对该节点设置一个Watcher通知。
|
||||
释放锁:Zookeeper删除对应的临时节点,其他客户端可以监听到节点被删除的通知,并重新竞争锁。
|
||||
|
||||
### 读写锁-使用临时有序节点实现
|
||||
|
||||
获得读锁:
|
||||
|
||||
1. 获得临时有序节点,并标记为读锁
|
||||
2. 获取资源路径下所有的子节点,从小到大排序。
|
||||
3. 获取当前临近节点前的临近写锁节点。
|
||||
4. 如果不存在临近写锁节点,则成功获得读锁
|
||||
5. 如果存在临近写锁节点,则设置Water监听该节点的删除事件。
|
||||
6. 一旦监听到删除事件,重复2,3,4,5的步骤。
|
||||
|
||||
获得写锁:
|
||||
|
||||
1. 创建临时有序节点,并标记为写锁。
|
||||
2. 获取路径下的所有子节点,并进行从小到大排序。
|
||||
3. 获取当前节点的临近的写锁节点和读锁节点。
|
||||
4. 如果不存在临近节点,则成功获取锁。
|
||||
5. 如果存在临近节点,对其进行监听删除事件。
|
||||
6. 一旦监听到删除事件,重复2,3,4,5的步骤(递归)。
|
||||
|
||||
释放锁:
|
||||
|
||||
1. 删除对应的临时节点。
|
||||
|
||||
## 基于Redis的分布式锁实现方案
|
||||
|
||||
原理:在获取锁之前,先查询一下以该锁为key对应的value是否存在,若存在,说明该锁被其他客户端获取了。
|
||||
|
||||
改进1:为了防止获取锁的客户端突然宕机,需要在设置key的时候,指定一个过期时间,以确保即使宕机了,锁也能最后释放。通过SETNX命令设置key的值,通过EXPIRE命令设置过期时间。
|
||||
|
||||
改进2:由于SETNX和EXPIRE命令的执行不是原子性的,多个客户端在检验锁是否存在时会导致多个客户端都认为自己能获取到锁。Redis提供了Set原子性命令,在设置值的同时指定过期时间。
|
||||
|
||||
改进3:客户端获取锁以后任务未执行完,但锁已经过期,被别的客户端获取了,这时客户端扔会释放锁,导致锁失效。可以在设置key的时候,设置value为一个随机值r,删除的时候先比较一下redis里的value是否为r再决定删除。
|
||||
|
||||
改进4:客户端先比较一下redis的value是否为r再决定删除,但由于比较后再删除锁不是原子的。在比较过程中,key有可能因过期而被清除了导致一个客户端就可以获取到key。Redis并没有提供相关的比较后删除的原子操作。此时释放锁的过程可以使用lua脚本,redis将lua脚本的命令视为一个原子操作。 **Redis可以原子执行lua脚本**
|
||||
|
||||
## 参考链接
|
||||
|
||||
https://segmentfault.com/a/1190000022740402
|
|
@ -0,0 +1,23 @@
|
|||
## 计数器算法
|
||||
|
||||
设置一个变量存储T时间内的访问量,每当T时间后重置该变量为0,当变量达到阈值后限制访问
|
||||
|
||||
## 滑动窗口算法
|
||||
|
||||
将时间周期划分为N个小周期,分别记录每个小周期内访问次数,并且根据时间滑动删除过期的小周期,滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确
|
||||
|
||||
## 漏桶算法
|
||||
|
||||
算法内部有一个容器,不管上面流量多大,下面流出的速度始终保持不变。
|
||||
|
||||
准备一个队列,用来保存请求,另外通过一个线程池定期从队列中获取请求并执行,可以一次性获取多个并发执行。
|
||||
|
||||
## 令牌桶算法
|
||||
|
||||
以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。
|
||||
|
||||
准备一个队列,用来保存令牌,另外通过一个线程池定期生成令牌放到队列中,每来一个请求,就从队列中获取一个令牌
|
||||
|
||||
## 集群限流
|
||||
|
||||
每次有相关操作的时候,就向redis服务器发送一个incr命令,比如需要限制某个用户访问/index接口的次数,只需要拼接用户id和接口名生成redis的key,每次该用户访问此接口时,只需要对这个key执行incr命令,在这个key带上过期时间,就可以实现指定时间的访问频率。
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
## 页面置换算法
|
||||
|
||||
* 最佳页面置换算法(OPT)
|
||||
* 先进先出置换算法(FIFO)
|
||||
* 最近最久未使用置换算法(LRU)
|
||||
* 时钟页面置换算法
|
||||
跟 LRU 近似,又是对 FIFO 的一种改进
|
||||
思路是,把所有的页面都保存在一个类似钟面的「环形链表」中,一个表针指向最老的页面
|
||||
* 最不常用置换算法
|
||||
当发生缺页中断时,选择「访问次数」最少的那个页面,并将其淘汰
|
|
@ -0,0 +1,7 @@
|
|||
## 时间局部性原理
|
||||
|
||||
如果一个信息项正在被访问,那么在近期它很可能还会被再次访问
|
||||
|
||||
## 空间局部性原理
|
||||
|
||||
在最近的将来将用到的信息很可能与正在使用的信息在空间地址上是临近的
|
|
@ -0,0 +1,5 @@
|
|||
* 处理器管理
|
||||
* 作业管理(进程管理)
|
||||
* 存储器管理
|
||||
* 设备管理
|
||||
* 文件管理
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
|
||||
## 磁盘调度算法
|
||||
|
||||
* 先来先服务算法 FCFS
|
||||
* 最短寻道时间优先算法 SSF
|
||||
优先选择从当前磁头位置所需寻道时间最短的请求
|
||||
* 扫描算法SCAN
|
||||
磁头在一个方向上移动,访问所有未完成的请求,直到磁头到达该方向上的最后的磁道,才调换方向
|
||||
* 循环扫描算法C-SCAN
|
||||
只有磁头朝某个特定方向移动时,才处理磁道访问请求,而返回时直接快速移动至最靠边缘的磁道,也就是复位磁头,这个过程是很快的,并且返回中途不处理任何请求
|
||||
* LOOK与C-LOOK算法
|
||||
相比前两个算法,优化的思路就是磁头在移动到「最远的请求」位置,然后立即反向移动
|
||||
是SCAN和C-SCAN的优化版本
|
|
@ -0,0 +1,75 @@
|
|||
## 进程、线程
|
||||
|
||||
进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发; 线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发;线程是操作系统可识别的最小执行和调度单位。 每个线程都独自占用一个虚拟处理器:独自的寄存器组,指令计数器和处理器状态。
|
||||
|
||||
## 进程通信
|
||||
|
||||
* 管道(pipe)
|
||||
* 有名管道(named pipe)
|
||||
* 信号量(semaphore)
|
||||
* 消息队列(message queue)
|
||||
* 信号(sinal)
|
||||
* 共享内存(shared memory)
|
||||
* 套接字(socket)
|
||||
|
||||
## 线程通信
|
||||
|
||||
* 锁机制:互斥锁、条件变量、读写锁等
|
||||
* wait、notify
|
||||
* volatile:所有volatile修饰的变量一旦被某个线程更改,必须立即刷新到主内存;所有volatile修饰的变量在使用之前必须重新读取主内存的值
|
||||
|
||||
## 进程调度
|
||||
|
||||
发生调度的情况
|
||||
1. 运行态 -> 阻塞态
|
||||
2. 运行态 -> 就绪态
|
||||
3. 阻塞态 -> 就绪态
|
||||
4. 运行态 -> 终止态
|
||||
|
||||
2和3是抢占式调度,1和4是非抢占式调度
|
||||
|
||||
## 进程调度算法
|
||||
|
||||
* FCFS 先来先服务调度算法
|
||||
* SJF 最短作业优先调度算法
|
||||
* HRRN 高相应比优先调度算法
|
||||
`优先权=(等待时间 + 要求服务时间)/要求服务时间`
|
||||
每次进行进程调度时,先计算「响应比优先级」,然后把「响应比优先级」最高的进程投入运行
|
||||
* RR 时间片轮转调度算法
|
||||
每个进程被分配一个时间段,称为时间片(Quantum)
|
||||
如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率
|
||||
如果设得太长又可能引起对短作业进程的响应时间变长
|
||||
* HPF 最高优先级调度算法
|
||||
从就绪队列中选择最高优先级的进程进行运行,这称为最高优先级
|
||||
* 多级反馈队列调度算法
|
||||
多级反馈队列调度算法是「时间片轮转算法」和「最高优先级算法」的综合和发展
|
||||
|
||||
## 进程/线程之间同步方式
|
||||
|
||||
互斥量、读写锁、条件变量、自旋锁、屏障、信号量
|
||||
|
||||
## 进程状态
|
||||
|
||||
创建、就绪、运行、阻塞、就绪挂起、阻塞挂起、终止
|
||||
|
||||
## 线程状态
|
||||
|
||||
* 创建
|
||||
* 就绪
|
||||
* 运行
|
||||
* 阻塞
|
||||
* 终止
|
||||
|
||||
## 死锁
|
||||
|
||||
### 产生条件
|
||||
|
||||
1. 互斥条件
|
||||
2. 请求和保持条件
|
||||
3. 不剥夺条件
|
||||
4. 循环等待条件
|
||||
|
||||
### 预防方法
|
||||
|
||||
1. 锁有序分配
|
||||
2. 银行家算法
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue