diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b1dcf06..8b2d224 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,8 +2,8 @@ - + @@ -587,7 +594,8 @@ - @@ -602,10 +610,10 @@ - + - + @@ -656,10 +664,10 @@ - + - + diff --git a/Rocket.md b/Rocket.md index c2577a1..2852d2b 100644 --- a/Rocket.md +++ b/Rocket.md @@ -132,6 +132,10 @@ Redis默认是快照RDB的持久化方式。对于主从同步来说,主从刚 * 第二层是Mysql的服务层,包括SQL的解析分析优化,存储过程触发器视图等也在这一层实现。 * 最后一层是存储引擎的实现,类似于Java接口的实现,Mysql的执行器在执行SQL的时候只会关注API的调用,完全屏蔽了不同引擎实现间的差异。比如Select语句,先会判断当前用户是否拥有权限,其次到缓存(内存)查询是否有相应的结果集,如果没有再执行解析sql,优化生成执行计划,调用API执行。 +### SQL执行顺序 + +SQL的执行顺序:from---where--group by---having---select---order by + ### MVCC,redolog,undolog,binlog * undoLog 也就是我们常说的回滚日志文件 主要用于事务中执行失败,进行回滚,以及MVCC中对于数据历史版本的查看。由引擎层的InnoDB引擎实现,是逻辑日志,记录数据修改被修改前的值,比如"把id='B' 修改为id = 'B2' ,那么undo日志就会用来存放id ='B'的记录”。当一条数据需要更新前,会先把修改前的记录存储在undolog中,如果这个修改出现异常,,则会使用undo日志来实现回滚操作,保证事务的一致性。当事务提交之后,undo log并不能立马被删除,而是会被放到待清理链表中,待判断没有事物用到该版本的信息时才可以清理相应undolog。它保存了事务发生之前的数据的一个版本,用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 @@ -197,6 +201,7 @@ MySQL为了保证ACID中的一致性和持久性,使用了WAL(Write-Ahead Logg 2. Java虚拟机栈:与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧 ,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 3. 本地方法栈:本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。 4. Java堆:对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 + ### 分代回收 HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。 @@ -209,6 +214,7 @@ HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分 1. 引用计数法:引用计数法是一种简单但速度很慢的垃圾回收技术。每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1。虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象引用计数为0时,就释放其占用的空间。 2. 可达性分析算法:这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。 + ### 哪些对象可以作为GC Roots 1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。 @@ -318,14 +324,6 @@ CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换。 AQS内部有3个对象,一个是state(用于计数器,类似gc的回收计数器),一个是线程标记(当前线程是谁加锁的),一个是阻塞队列。 -### 死锁的4个必要条件 - -1. 互斥条件:一个资源每次只能被一个线程使用; -2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放; -3. 不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺; -4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。 -指定获取锁的顺序可避免死锁 - ### 如何指定多个线程的执行顺序 1. 设定一个 orderNum,每个线程执行结束之后,更新 orderNum,指明下一个要执行的线程。并且唤醒所有的等待线程。 @@ -346,6 +344,12 @@ AQS内部有3个对象,一个是state(用于计数器,类似gc的回收计 6. threadFactory:线程工厂,用于创建线程,一般用默认的即可。 7. handler:拒绝策略。当任务太多来不及处理,如何拒绝任务。 +### 线程池的线程数量怎么确定 + +1. 一般来说,如果是CPU密集型应用,则线程池大小设置为N+1。 +2. 一般来说,如果是IO密集型应用,则线程池大小设置为2N+1。 +3. 在IO优化中,线程等待时间所占比例越高,需要越多线程,线程CPU时间所占比例越高,需要越少线程。这样的估算公式可能更适合:最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目 + ### HashSet和HashMap HashSet的value存的是一个static finial PRESENT = newObject()。而HashSet的remove是使用HashMap实现,则是map.remove而map的移除会返回value,如果底层value都是存null,显然将无法分辨是否移除成功。 @@ -463,6 +467,49 @@ Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers 9. 网络传输层:抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec。 10. 数据序列化层:可复用的一些工具,扩展接口为Serialization、 ObjectInput、ObjectOutput和ThreadPool。 +## 操作系统 + +### 进程和线程 + +1. 进程是操作系统资源分配的最小单位,线程是CPU任务调度的最小单位。一个进程可以包含多个线程,所以进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同。 +2. 不同进程间数据很难共享,同一进程下不同线程间数据很易共享。 +3. 每个进程都有独立的代码和数据空间,进程要比线程消耗更多的计算机资源。线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。 +4. 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉。 +5. 系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。 + +### 进程的组成部分 + +进程由进程控制块、程序段、数据段三部分组成。 + +### 进程的通信方式 + +1. 无名管道:半双工的,即数据只能在一个方向上流动,只能用于具有亲缘关系的进程之间的通信,可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。 +2. FIFO命名管道:FIFO是一种文件类型,可以在无关的进程之间交换数据,与无名管道不同,FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。 +3. 消息队列:消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。 +4. 信号量:信号量是一个计数器,信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。 +5. 共享内存:共享内存指两个或多个进程共享一个给定的存储区,一般配合信号量使用。 + +### 进程间五种通信方式的比较 + +1. 管道:速度慢,容量有限,只有父子进程能通讯。 +2. FIFO:任何进程间都能通讯,但速度慢。 +3. 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。 +4. 信号量:不能传递复杂消息,只能用来同步。 +5. 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。 + +### 死锁的4个必要条件 + +1. 互斥条件:一个资源每次只能被一个线程使用; +2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放; +3. 不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺; +4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。 + +### 如何避免(预防)死锁 + +1. 破坏“请求和保持”条件:让进程在申请资源时,一次性申请所有需要用到的资源,不要一次一次来申请,当申请的资源有一些没空,那就让线程等待。不过这个方法比较浪费资源,进程可能经常处于饥饿状态。还有一种方法是,要求进程在申请资源前,要释放自己拥有的资源。 +2. 破坏“不可抢占”条件:允许进程进行抢占,方法一:如果去抢资源,被拒绝,就释放自己的资源。方法二:操作系统允许抢,只要你优先级大,可以抢到。 +3. 破坏“循环等待”条件:将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序提出(指定获取锁的顺序,顺序加锁)。 + ## 计算机网路 ### Get和Post区别 @@ -483,12 +530,12 @@ Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers ### tcp和udp区别 -1. TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接 -2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保 证可靠交付 +1. TCP面向连接,UDP是无连接的,即发送数据之前不需要建立连接。 +2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。 3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流,UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) -4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 -5. TCP首部开销20字节;UDP的首部开销小,只有8个字节 -6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道 +4. 每一条TCP连接只能是点到点的,UDP支持一对一,一对多,多对一和多对多的交互通信。 +5. TCP首部开销20字节,UDP的首部开销小,只有8个字节。 +6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。 ### tcp和udp的优点 @@ -518,6 +565,7 @@ TCP是一个双向通信协议,通信双方都有能力发送信息,并接 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。 + ## 数据结构与算法 ### 排序算法