Skip to content

Commit 7a7db16

Browse files
committed
change image
1 parent b92d450 commit 7a7db16

19 files changed

+190
-16
lines changed

docs/ArrayList.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static class SynchronizedList<E>
9595
mutex = this;//mutex就是SynchronizedList实例自己,作为同步锁使用
9696
}
9797

98-
public E get(int index) {
98+
public E get(int index) {
9999
synchronized (mutex) {
100100
是父类中的成员变量,在父类中会将list赋值给mutex
101101
return list.get(index);

docs/HTTP.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
#### [3. TCP三次握手和四次挥手是怎么样的?](#TCP三次握手和四次挥手是怎么样的?)
66
#### [4.TCP怎么保证可靠性的?](#TCP怎么保证可靠性的?)
77
#### [5.TCP拥塞控制怎么实现?](#TCP拥塞控制怎么实现?)
8-
#### [6.close_wait 太多怎么处理?为什么会出现这种情况?](#close_wait 太多怎么处理?为什么会出现这种情况?)
9-
8+
#### [6.close_wait太多怎么处理?](#close_wait太多怎么处理?)
109

1110
### HTTPS建立连接的过程是怎么样的?
1211

@@ -183,7 +182,7 @@ TCP连接刚建立,一点一点地提速,试探一下网络的承受能力
183182

184183
如果现在的TCP Reno算发,会将cwnd窗口设置为新的ssthresh值的大小,后续开始进入拥塞避免算法的流程,对cwnd窗口进入线性增长的状态。
185184

186-
### close_wait 太多怎么处理?为什么会出现这种情况?
185+
### close_wait太多怎么处理?
187186

188187
close_wait 主要在TCP四次挥手时,服务端给客户端返回ACK应答后,由于自身还需要给客户端传输数据,所以会进入到close_wait状态,直到不需要给客户端发数据了,才会去给客户端发送FIN包,同时进入LAST_ACK状态。(被动关闭的一方没有及时发出 FIN 包就会导致自己一直处于close_wait状态。)
189188

docs/JavaBasic.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ public String toString() {
515515

516516
#### wait()方法和notify()方法
517517

518-
```
518+
```java
519519
//timeout是超时时间,也就是等待的最大毫秒数,如果为0,代表会一直等待下去
520520
public final native void wait(long timeout) throws InterruptedException;
521521
public final native void notify();
@@ -693,7 +693,7 @@ Error就是一些程序处理不了的错误,代表JVM出现了一些错误,
693693

694694
RuntimeException异常就是应用程序运行时,可能会抛出的异常。这些异常是非受检异常,编译时Java编译器不会去检查,不会强制程序员添加处理异常的代码。程序中可以选择捕获处理,也可以不处理。如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等。
695695

696-
非受检异常以外的异常可以认为是受检异常,从程序语法角度讲是必须进行处理的异常,编译时编译器就会要求有相关的异常捕获处理的代码逻辑。如IOException、SQLException。
696+
非受检异常以外的异常可以认为是受检异常,从程序语法角度讲是必须进行处理的异常,编译时编译器就会要求有相关的异常捕获处理的代码逻辑。如IOException、SQLException,FileNotFoundException
697697

698698
##### PS:
699699

docs/Kafka.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,24 @@ https://blog.csdn.net/choumu8867/article/details/100658332
201201

202202
mmap和write()方案:数据拷贝了3次,会减少一次CPU拷贝,上下文切换了4次。(可以减少1次CPU拷贝)
203203

204-
sendfile方案:数据拷贝了2次,上下文切换了2次。但是用户进程不能修改数据。(可以减少2次CPU拷贝,至少2次上下文切换)
204+
sendfile方案:数据拷贝了2次,上下文切换了2次。但是用户进程不能修改数据。(可以减少2次CPU拷贝,至少2次上下文切换)
205+
206+
### Kafka刷盘时机是怎么样的?
207+
log.flush.interval.messages 最大刷盘消息数量
208+
log.flush.interval.interval.ms 最大刷盘时间间隔
209+
log.flush.scheduler.interval.ms 定期刷盘间隔
210+
可以通过设置 最大刷盘消息数量 和 最大刷盘时间间隔 来控制fsync系统调用的时间,但是Kafka不推荐去设置这些参数,希望让操作系统来决定刷盘的时机,这样可以支持更高的吞吐量。而且Kafka保证可用性是通过多副本来实现的,一个机器挂掉了就会选举副本作为leader。
211+
### Kafka什么时候进行rebalance?
212+
1.topic下分区的数量增加了或者减少了。(这个一般是我们手动触发的)
213+
2.消费者的数量发生了改变,例如新增加了消费者或者有消费者挂掉了。
214+
Kafka有一个session.timeout.ms,最大会话超时时间,最长是10s。就是如果broker与消费者之间的心跳包超过10s还没有收到回应,就会认为消费者掉线了。以及还有一个max.poll.interval.ms参数,消费者两次去broker拉取消息的间隔,默认是5分钟。如果消费者两次拉取消息的间隔超过了5分钟,就会认为消费者掉线了。
215+
216+
一旦发生rebalance了,有可能会导致重复消费的问题,就是消费者A拉取了100条消息,消费时间超过了5分钟,被broker认定下线,就会进行rebalance,把这个分区分配给其他消费者消费,其他消费者就会进行重复消费。
217+
218+
怎么解决rebalance带来的重复消费问题呢?
219+
220+
1.可以减少每批消息的处理时间,让每条消息的处理时间减少,或者是修改max.poll.records,减小每次拉取消息的数量。
221+
222+
2.可以自行在MySQL或者Redis里面存储每个分区消费的offset,然后消费者去一个新的分区拉取消息时先去读取上次消费的offset。
223+
224+
3.为消息分配一个唯一的消息id,通过消息id来判定是否重复消费了。

docs/Lock.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public class SyncTest {
7676

7777
就是Java对象的内存布局其实由对象头+实例数据+对齐填充三部分组成,而对象头主要包含Mark Word+指向对象所属的类的指针组成。Mark Word主要用于存储对象自身的运行时数据,哈希码,GC分代年龄,锁标志等。
7878

79-
![img](../static/640)
79+
![img](../static/640的副本)
8080

8181
下面就是Mark Word的数据映射表
8282

@@ -240,7 +240,11 @@ synchronized是一个Java 关键字,synchronized锁是JVM实现的,底层代
240240

241241
3.功能
242242

243-
synchronized只能修饰方法,或者用于代码块,而ReenTrantLock的加锁和解锁是调用lock和unlock方法,更加灵活。其次是synchronized的等待队列只有一个(调用wait()方法的线程会进入等待队列),而ReenTrantLock可以有多个条件等待队列。可以分组唤醒需要唤醒的线程们,而不是像synchronized要么用notify方法随机唤醒一个线程要么用notifyAll方法唤醒全部线程。ReenTrantLock 提供了一种能够中断等待锁的线程的机制,就是线程通过调用lock.lockInterruptibly()方法来加锁时,一旦线程被中断,就会停止等待。
243+
synchronized只能修饰方法,或者用于代码块,而ReenTrantLock的加锁和解锁是调用lock和unlock方法,更加灵活。
244+
245+
其次是synchronized的等待队列只有一个(调用wait()方法的线程会进入等待队列),而ReenTrantLock可以有多个条件等待队列。可以分组唤醒需要唤醒的线程们,而不是像synchronized要么用notify方法随机唤醒一个线程要么用notifyAll方法唤醒全部线程。ReenTrantLock 提供了一种能够中断等待锁的线程的机制,就是线程通过调用lock.lockInterruptibly()方法来加锁时,一旦线程被中断,就会停止等待。
246+
247+
ReenTrantLock可以使用tryLock(long timeout, TimeUnit unit)方法来尝试申请锁,设置一个超时时间,超过超时时间,就会直接返回false,而不是一直等待锁。
244248

245249
4.公平性
246250

docs/Spring.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#### [1.SpringAOP是怎么实现的?](#SpringAOP是怎么实现的?)
44
### SpringAOP是怎么实现的?
55

6+
Spring Aop是一种可以减少大量重复代码的一种编程技术,可以设置一个切面,比如说是某个包下面的所有方法,这些方法在执行的时候就会调用我们写的拦截方法,我们可以做一些类似于日志打印等一些操作。
7+
68
实现AOP有三种方式:静态代理,使用JDK的Proxy类实现动态代理,使用CGLIB实现动态代理。
79

810
#### 静态代理
@@ -221,7 +223,7 @@ public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationA
221223

222224
2.**属性赋值阶段**-主要是在populateBean()方法中,对Bean的各项属性进行赋值。
223225

224-
3.**Bean的初始化阶段**-主要调用用户自定义的初始化方法InitializingBean(),
226+
3.**Bean的初始化阶段**-主要调用用户自定义的初始化方法init-Method()
225227

226228
用户可以自定义一个类,继承BeanPostProcessor,重写它的两个方法,对Bean的初始化前后做一些额外的操作,例如打印日志。
227229

docs/SystemDesign.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ zookeeper里面会存上次生成id的时间戳,如果上次存储的时间戳
156156

157157
#### 2PC方案(2阶段提交制)
158158

159-
![img](../static/v2-880b5e0866906160b663827f961d8360_b.jpg)
159+
![图片](../static/640-8127488.)
160160

161161
这种方案就是引入了一个协调者,主要分为prepare和commit两个阶段,在第一阶段其实就是协调者给各个业务系统发送命令,业务系统收到后,就会开始执行这个子事务的具体操作,然后给协调者反馈,子事务执行成功还是失败,发送后,业务系统就会同步阻塞等待协调者的第二阶段的指令。
162162

@@ -171,11 +171,43 @@ zookeeper里面会存上次生成id的时间戳,如果上次存储的时间戳
171171

172172
**缺点**
173173

174-
1.就是如果第二阶段网络发生了阻塞,协调者与业务系统断开了连接,协调者就只能一直去进行重试,发生回滚指令给业务系统,而业务系统会一直阻塞等待第二阶段的通知
174+
1.单点问题:就是一旦协调者挂掉,所有子系统都会进入阻塞等待状态
175175

176-
2.假设协调者认定执行成功,在第二阶段给所有子系统发送Commit指令,收到指令的系统对事务进行提交,假设有一个系统与协调者之间的网络断开了,就会保持未提交状态,一直阻塞等待,协调者也只能对它进行一直发送commit指令
176+
2.数据不一致的问题:如果在第二阶段协调者给子系统发送commit指令时,发生了局部网络异常,就会导致接收到commit的指令的子系统提交事务,而没有接收到commit指令的子系统没有提交事务,导致数据不一致
177177

178-
其次是2PC 适用于**数据库层面的分布式事务场景**,如果事务中有上传一张图片或者发送一条短信,这些是没有相应的回滚操作的。
178+
3.同步阻塞:由于子系统在执行阶段都是同步阻塞的,自身没有超时的机制,一旦与协调者之间的网络断开,只能一直阻塞等待,等待协调者的指令。
179+
180+
#### 3PC三段提交制
181+
182+
这种方案就是分为三个阶段,canCommit,preCommit,doCommit三个阶段。
183+
184+
第一阶段是询问阶段
185+
186+
协调者会给参与者发送canCommit指令,询问能否正常执行,如果满足执行的条件的话,参与者就会返回ACK。
187+
188+
第二阶段是预执行阶段
189+
190+
协调者会给参与者发送preCommit指令,让参与者执行事务,但是执行完成不提交,参与者执行成功后会给协调者发送ACK。
191+
192+
第三阶段就是提交阶段
193+
194+
协调者如果收到所有参与者给他返回执行成功的ACK,那么他就会给所有协调者发送doCommit指令,让参与者提交。如果在第二阶段有一个参与者执行失败,给协调返回执行失败的结果,那么在第三阶段,协调者就会给参与者发送Abort指令,让参与者回滚。
195+
196+
![图片](../static/640-8127813.png)
197+
198+
**与2PC的区别:**
199+
200+
1.3pc是一个非阻塞的协议,为参与者引入了超时机制,在第一阶段或者第二阶段,参与者等待协调者的指令超时了,会进行回滚,第三阶段等待协调者的指令超时了,会进行自动提交。而2pc协议,如果协调者一直没有给参与者发指令,导致超时,参与者会一直进行阻塞等待。
201+
202+
2.2pc协议里面,第二阶段协调者挂了,选举出新的协调者是不知道参与者执行的事务是提交事务还是回滚事务。3pc里面到了第三阶段那么一定是执行提交事务。
203+
204+
**3pc的问题:**
205+
206+
第三阶段如果发送的是abort回滚指令,假设有些参与者由于网络原因没有收到指令,超时后会进行自行提交事务,那么也会导致数据不一致的问题。
207+
208+
https://honeypps.com/architect/introduction-of-distributed-transaction/
209+
210+
https://www.infoq.cn/article/2018/08/rocketmq-4.3-release
179211

180212
#### TCC
181213

@@ -209,6 +241,26 @@ https://www.cnblogs.com/jajian/p/10014145.html
209241

210242
并且下游系统是通过消息中操作记录的主键id来防止不重复消费,保证幂等性的。就是消费消息时,发送操作记录的id已经在数据库中存在了,就代表之前已经处理过了,不处理这条消息了。
211243

244+
##### 最大努力通知法(RocketMQ)
245+
246+
RocketMQ在4.3以后,增加了对分布式事务的支持,就是将事务的执行状态保存在RocketMQ中,由RocketMQ去负责将commit状态的消息推送给下游系统。
247+
248+
![img](../static/66b6ae1dec5b96084c3a6d29174a20e3.png)
249+
250+
1.上游系统发送prepare消息到RocketMQ。
251+
252+
2.prepare消息发送到RocketMQ成功后,上游系统开始执行本地事务。
253+
254+
3.如果上游系统本地事务执行成功,会发送commit消息到RocketMQ,RocketMQ会将这个消息提交,推送给消费者(也就是下游系统)。如果上游系统本地事务执行失败,会发送rollback消息到RocketMQ,RocketMQ会将这个消息撤销,不推送给消费者。
255+
256+
4.如果一个prepare消息一直没有接受到上游系统的commit或者rollback指令,这样就判定prepare消息超时了,RocketMQ会去查询上游系统的这个事务的执行状态,是成功了,还是失败,做下一步的处理。
257+
258+
底层实现原理
259+
260+
RocketMQ使用了Half topic来保存所有prepare消息,使用Operation Topic来保存commit消息和rollback消息。这样通过Operation Topic就知道哪些消息commit了,可以推送给消费者,哪些消息rollback了,不需要推送给消费者。以及那些在Half topic中有,在Operation Topic中没有的消息,就是事务超时的消息。
261+
262+
https://www.infoq.cn/article/2018/08/rocketmq-4.3-release
263+
212264
### 如何设计秒杀系统?
213265

214266
1.前端页面

docs/ZooKeeper.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ https://blog.csdn.net/hotchange/article/details/81192122
6969

7070
首先客户端连接zookeeper集群中的任何一个节点,可以是leader节点,也可以是follower节点,一旦连接,节点会给客户端分配会话ID,并向客户端发送确认,如果客户端收到确认,那么连接成功,客户端会有规律地给zookeeper发送心跳包,确保连接没有断开。
7171

72-
* 客户端向zookeeper节点发送读请求,节点会直接从数据库中找到这个节点的数据然后返回。
72+
* 客户端向zookeeper从节点发送读请求,节点会直接从数据库中找到这个节点的数据然后返回。
7373

74-
* 客户端向zookeeper节点发送写请求,节点会将znode路径和数据转发到leader节点,leader会将写请求转换为proposal提案,并且分配一个事务ID zxid,将这个proposal放到每个节点的队列(主节点会给每个从节点分配一个专用队列)中去,然后会根据先进先出的策略,将消息发送给从节点,从节点接收到后会将事务写入到磁盘中去,然后返回ACK响应给主节点,当主节点接收到半数以上的从节点的ACK响应后,主节点会认为这个事务提交成功,完成这个事务提交,同时给所有从节点发送commit消息,从节点接收到消息后,会将这条事务提交。
74+
* 客户端向zookeeper从节点发送写请求,节点会将znode路径和数据转发到leader节点,leader会将写请求转换为proposal提案,并且分配一个事务ID zxid,将这个proposal放到每个节点的队列(主节点会给每个从节点分配一个专用队列)中去,然后会根据先进先出的策略,将消息发送给从节点,从节点接收到后会将事务写入到磁盘中去,然后返回ACK响应给主节点,当主节点接收到半数以上的从节点的ACK响应后,主节点会认为这个事务提交成功,完成这个事务提交,同时给所有从节点发送commit消息,从节点接收到消息后,会将这条事务提交。
7575

7676
由此看来zookeeper没法保证客户端读取的都是最新的数据,
7777

docs/algorithm.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,3 +959,100 @@ dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i])
959959
return dp[prices.length-1][0];
960960
}
961961
```
962+
963+
964+
965+
### 421. 数组中两个数的最大异或值
966+
967+
https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/
968+
969+
给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。
970+
971+
找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, j < n 。
972+
973+
你能在O(n)的时间解决这个问题吗?
974+
975+
示例:
976+
977+
输入: [3, 10, 5, 25, 2, 8]
978+
979+
输出: 28
980+
981+
解释: 最大的结果是 5 ^ 25 = 28
982+
983+
984+
985+
```java
986+
public static class TreeNode {
987+
public int val;
988+
public TreeNode left = null;
989+
public TreeNode right = null;
990+
public TreeNode(int val) {
991+
this.val = val;
992+
}
993+
}
994+
995+
Integer findMaximumXOR(int[] array) {
996+
if (array==null||array.length==0) {
997+
return null;
998+
}
999+
TreeNode root = new TreeNode(-1);
1000+
//构建前缀树
1001+
for (int i = 0; i < array.length; i++) {
1002+
insert(root,array[i]);
1003+
}
1004+
int max =0;
1005+
1006+
for (int i = 0; i < array.length; i++) {
1007+
int result = findMaxForTheValue(root,array[i]);
1008+
if (result>max){
1009+
max= result;
1010+
}
1011+
}
1012+
return max;
1013+
}
1014+
1015+
void insert(TreeNode root, int insertValue) {
1016+
//最大值是是2的31次方
1017+
int bitValue = 1<<30;
1018+
TreeNode currentNode = root;
1019+
while (bitValue!=0) {
1020+
int result = insertValue & bitValue;
1021+
if (result==0) {//array[i]这一位是0,往左创建节点
1022+
if (currentNode.left==null) {
1023+
TreeNode node = new TreeNode(-1);
1024+
currentNode.left = node;
1025+
}
1026+
currentNode = currentNode.left;
1027+
} else {//array[i]这一位是1,往右边创建节点
1028+
if (currentNode.right==null) {
1029+
TreeNode node = new TreeNode(-1);
1030+
currentNode.right = node;
1031+
}
1032+
currentNode = currentNode.right;
1033+
}
1034+
bitValue= bitValue>>1;
1035+
}
1036+
currentNode.val = insertValue;
1037+
}
1038+
1039+
int findMaxForTheValue(TreeNode root, int value) {
1040+
TreeNode currentNode = root;
1041+
int bitValue = 1<<30;
1042+
while (bitValue!=0) {
1043+
int result = value & bitValue;
1044+
if (result==0) {//array[i]这一位是0,往右边找节点
1045+
1046+
currentNode = currentNode.right != null ?
1047+
currentNode.right : currentNode.left;
1048+
1049+
} else {//array[i]这一位是1,往左边找节点
1050+
currentNode = currentNode.left != null ?
1051+
currentNode.left : currentNode.right;
1052+
}
1053+
bitValue= bitValue>>1;
1054+
}
1055+
int result = value^currentNode.val;
1056+
return result;
1057+
}
1058+
```

static/640-1487645.

16.2 KB
Binary file not shown.

static/640-20201128120828308

36.5 KB
Binary file not shown.

static/640-20201128120828359

37.9 KB
Binary file not shown.

static/640-20210124192752928

15.6 KB
Binary file not shown.

static/640-20210124203435521

23.6 KB
Binary file not shown.

static/640-8127488.

36.6 KB
Binary file not shown.

static/640-8127813.png

242 KB
Loading

static/640的副本

15.2 KB
Binary file not shown.
318 KB
Loading

static/qe222wewewqere.jpeg

-505 Bytes
Loading

0 commit comments

Comments
 (0)