From 75801c53fe4162b5b615edb91101666607eea014 Mon Sep 17 00:00:00 2001 From: tyson Date: Tue, 10 May 2022 21:02:30 +0800 Subject: [PATCH 01/84] update --- ...00\351\235\242\350\257\225\351\242\230.md" | 118 +++++++++++++++++- ...10\351\235\242\350\257\225\351\242\230.md" | 14 ++- ...is\351\235\242\350\257\225\351\242\230.md" | 45 ++----- ...27\351\235\242\350\257\225\351\242\230.md" | 4 +- ...76\350\256\241\346\250\241\345\274\217.md" | 9 ++ ...37\351\235\242\350\257\225\351\242\230.md" | 17 ++- ...21\351\235\242\350\257\225\351\242\230.md" | 14 ++- ...43\347\240\201\345\256\236\347\216\260.md" | 15 ++- ...60\346\215\256\347\273\223\346\236\204.md" | 38 +----- .../SpringBoot\345\256\236\346\210\230.md" | 8 +- ...25\351\242\230\346\200\273\347\273\223.md" | 68 ++++------ ...15\345\212\241\345\256\236\346\210\230.md" | 4 +- ...ng\351\235\242\350\257\225\351\242\230.md" | 45 +++++-- 13 files changed, 248 insertions(+), 151 deletions(-) diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 8e229cd..5fa2390 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -95,15 +95,53 @@ 黑白双方负责接受用户的输入,并告知棋盘系统棋子布局发生变化,棋盘系统接收到了棋子的变化的信息就负责在屏幕上面显示出这种变化,同时利用规则系统来对棋局进行判定。 -## JKD和JRE的区别? +## JKD/JRE/JVM三者的关系 -JDK和JRE是Java开发和运行工具,其中JDK包含了JRE,而JRE是可以独立安装的。 +### JVM -**JDK**:Java Development Kit,JAVA语言的软件工具开发包,是整个JAVA开发的核心,它包含了JAVA的运行(JVM+JAVA类库)环境和JAVA工具。 +**JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -**JRE**:Java Runtime Environment,Java运行环境,包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)。 +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) -JRE是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。 +所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 + +针对不同的系统有不同的 jvm 实现,有 Linux 版本的 jvm 实现,也有Windows 版本的 jvm 实现,但是同一段代码在编译后的字节码是一样的。这就是Java能够跨平台,实现一次编写,多处运行的原因所在。 + +### JRE + +英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) + +JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 + +如果你只是想运行Java程序,而不是开发Java程序的话,那么你只需要安装JRE即可。 + +### JDK + +英文名称(Java Development Kit),就是 Java 开发工具包 + +学过Java的同学,都应该安装过JDK。当我们安装完JDK之后,目录结构是这样的 + +![](https://cdn.jsdelivr.net/gh/Tyson0314/img/20220404120509.png) + +可以看到,JDK目录下有个JRE,也就是JDK中已经集成了 JRE,不用单独安装JRE。 + +另外,JDK中还有一些好用的工具,如jinfo,jps,jstack等。 + +![](https://cdn.jsdelivr.net/gh/Tyson0314/img/20220404120507.png) + + + +### 总结 + +最后,总结一下JDK/JRE/JVM,他们三者的关系 + +JRE = JVM + Java 核心类库 + +JDK = JRE + Java工具 + 编译器 + 调试器 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) ## 面向对象有哪些特性? @@ -944,6 +982,76 @@ unchecked Exception: - **throws**:用在方法签名中,用于声明该方法可能抛出的异常。子类方法抛出的异常范围更加小,或者根本不抛异常。 +## 通过故事讲清楚NIO + +下面通过一个例子来讲解下。 + +假设某银行只有10个职员。该银行的业务流程分为以下4个步骤: + +1) 顾客填申请表(5分钟); + +2) 职员审核(1分钟); + +3) 职员叫保安去金库取钱(3分钟); + +4) 职员打印票据,并将钱和票据返回给顾客(1分钟)。 + +下面我们看看银行不同的工作方式对其工作效率到底有何影响。 + +首先是BIO方式。 + +每来一个顾客,马上由一位职员来接待处理,并且这个职员需要负责以上4个完整流程。当超过10个顾客时,剩余的顾客需要排队等候。 + +一个职员处理一个顾客需要10分钟(5+1+3+1)时间。一个小时(60分钟)能处理6个顾客,一共10个职员,那就是只能处理60个顾客。 + +可以看到银行职员的工作状态并不饱和,比如在第1步,其实是处于等待中。 + +这种工作其实就是BIO,每次来一个请求(顾客),就分配到线程池中由一个线程(职员)处理,如果超出了线程池的最大上限(10个),就扔到队列等待 。 + +那么如何提高银行的吞吐量呢? + +思路就是:**分而治之**,将任务拆分开来,由专门的人负责专门的任务。 + +具体来讲,银行专门指派一名职员A,A的工作就是每当有顾客到银行,他就递上表格让顾客填写。每当有顾客填好表后,A就将其随机指派给剩余的9名职员完成后续步骤。 + +这种方式下,假设顾客非常多,职员A的工作处于饱和中,他不断的将填好表的顾客带到柜台处理。 + +柜台一个职员5分钟能处理完一个顾客,一个小时9名职员能处理:9*(60/5)=108。 + +可见工作方式的转变能带来效率的极大提升。 + +这种工作方式其实就NIO的思路。 + +下图是非常经典的NIO说明图,`mainReactor`线程负责监听server socket,接收新连接,并将建立的socket分派给`subReactor` + +`subReactor`可以是一个线程,也可以是线程池,负责多路分离已连接的socket,读写网络数据。这里的读写网络数据可类比顾客填表这一耗时动作,对具体的业务处理功能,其扔给worker线程池完成 + +可以看到典型NIO有三类线程,分别是`mainReactor`线程、`subReactor`线程、`work`线程。 + +不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。 + +![](https://gitee.com/tysondai/img/raw/master/20220423154450.png) + + + +**那这个流程还有没有什么可以提高的地方呢?** + +可以看到,在这个业务流程里边第3个步骤,职员叫保安去金库取钱(3分钟)。这3分钟柜台职员是在等待中度过的,可以把这3分钟利用起来。 + +还是分而治之的思路,指派1个职员B来专门负责第3步骤。 + +每当柜台员工完成第2步时,就通知职员B来负责与保安沟通取钱。这时候柜台员工可以继续处理下一个顾客。 + +当职员B拿到钱之后,通知顾客钱已经到柜台了,让顾客重新排队处理,当柜台职员再次服务该顾客时,发现该顾客前3步已经完成,直接执行第4步即可。 + +在当今web服务中,经常需要通过RPC或者Http等方式调用第三方服务,这里对应的就是第3步,如果这步耗时较长,通过异步方式将能极大降低资源使用率。 + +NIO+异步的方式能让少量的线程做大量的事情。这适用于很多应用场景,比如代理服务、api服务、长连接服务等等。这些应用如果用同步方式将耗费大量机器资源。 + +不过虽然NIO+异步能提高系统吞吐量,但其并不能让一个请求的等待时间下降,相反可能会增加等待时间。 + +最后,NIO基本思想总结起来就是:**分而治之,将任务拆分开来,由专门的人负责专门的任务** + ## BIO/NIO/AIO区别的区别? **同步阻塞IO** : 用户进程发起一个IO操作以后,必须等待IO操作的真正完成后,才能继续运行。 diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index bfec451..14acae6 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -141,7 +141,7 @@ while(itr.hasNext()) { ## Arraylist 和 Vector 的区别 -1. ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。 +1. ArrayList在内存不够时扩容为原来的1.5倍,Vector是扩容为原来的2倍。 2. Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为操作Vector效率比较低。 ## Arraylist 与 LinkedList的区别 @@ -422,7 +422,7 @@ put 操作流程: ### CopyOnWrite -写时复制。当我们往容器添加元素时,不直接往容器添加,而是先将当前容器进行复制,复制出一个新的容器,然后往新的容器添加元素,添加完元素之后,再将原容器的引用指向新容器。这样做的好处就是可以对`CopyOnWrite`容器进行并发的读而不需要加锁,因为当前容器不会被修改。 +Copy-On-Write,写时复制。当我们往容器添加元素时,不直接往容器添加,而是先将当前容器进行复制,复制出一个新的容器,然后往新的容器添加元素,添加完元素之后,再将原容器的引用指向新容器。这样做的好处就是可以对`CopyOnWrite`容器进行并发的读而不需要加锁,因为当前容器不会被修改。 ```java public boolean add(E e) { @@ -443,13 +443,19 @@ put 操作流程: 从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是`CopyOnWriteArrayList`和`CopyOnWriteArraySet`。 -`CopyOnWriteArrayList`中add方法添加的时候是需要加锁的,保证同步,避免了多线程写的时候复制出多个副本。读的时候不需要加锁,如果读的时候有其他线程正在向`CopyOnWriteArrayList`添加数据,还是可以读到旧的数据。 - **缺点:** - 内存占用问题。由于CopyOnWrite的写时复制机制,在进行写操作的时候,内存里会同时驻扎两个对象的内存。 - CopyOnWrite容器不能保证数据的实时一致性,可能读取到旧数据。 +### CopyOnWriteArrayList + +CopyOnWriteArrayList相当于线程安全的ArrayList,CopyOnWriteArrayList使用了一种叫写时复制的方法,当有新元素add到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组。 + +`CopyOnWriteArrayList`中add方法添加的时候是需要加锁的,保证同步,避免了多线程写的时候复制出多个副本。读的时候不需要加锁,如果读的时候有其他线程正在向`CopyOnWriteArrayList`添加数据,还是可以读到旧的数据。 + +CopyOnWrite并发容器用于读多写少的并发场景。 + ### ConcurrentLinkedQueue 非阻塞队列。高效的并发队列,使用链表实现。可以看做一个线程安全的 `LinkedList`,通过 CAS 操作实现。 diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index c7fe523..d5704d2 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -35,14 +35,6 @@ -> 首先给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - ## Redis是什么? Redis(`Remote Dictionary Server`)是一个使用 C 语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis 的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。 @@ -52,11 +44,11 @@ Redis(`Remote Dictionary Server`)是一个使用 C 语言编写的,高性 **优点**: 1. **基于内存操作**,内存读写速度快。 -2. Redis是**单线程**的,避免线程切换开销及多线程的竞争问题。单线程是指网络请求使用一个线程来处理,即一个线程处理所有网络请求,Redis 运行时不止有一个线程,比如数据持久化的过程会另起线程。 -3. **支持多种数据类型**,包括String、Hash、List、Set、ZSet等。 -4. **支持持久化**。Redis支持RDB和AOF两种持久化机制,持久化功能可以有效地避免数据丢失问题。 -5. **支持事务**。Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。 +2. **支持多种数据类型**,包括String、Hash、List、Set、ZSet等。 +3. **支持持久化**。Redis支持RDB和AOF两种持久化机制,持久化功能可以有效地避免数据丢失问题。 +4. **支持事务**。Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。 6. **支持主从复制**。主节点会自动将数据同步到从节点,可以进行读写分离。 +6. Redis命令的处理是**单线程**的。Redis6.0引入了多线程,需要注意的是,**多线程用于处理网络数据的读写和协议解析**,Redis命令执行还是单线程的。 **缺点**: @@ -67,10 +59,7 @@ Redis(`Remote Dictionary Server`)是一个使用 C 语言编写的,高性 ## Redis为什么这么快? - **基于内存**:Redis是使用内存存储,没有磁盘IO上的开销。数据存在内存中,读写速度快。 -- **单线程实现**( Redis 6.0以前):Redis使用单个线程处理请求,避免了多个线程之间线程切换和锁资源争用的开销。 - - **IO多路复用模型**:Redis 采用 IO 多路复用技术。Redis 使用单线程来轮询描述符,将数据库的操作都转换成了事件,不在网络I/O上浪费过多的时间。 - - **高效的数据结构**:Redis 每种数据类型底层都做了优化,目的就是为了追求更快的速度。 ## 讲讲Redis的线程模型? @@ -82,20 +71,6 @@ Redis基于Reactor模式开发了网络事件处理器,这个处理器被称 虽然文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性。 -## Redis为何选择单线程模型? - -* 避免过多的**上下文切换开销**。程序始终运行在进程中单个线程内,没有多线程切换的场景。 -* **避免同步机制的开销**:如果 Redis选择多线程模型,需要考虑数据同步的问题,则必然会引入某些同步机制,会导致在操作数据过程中带来更多的开销,增加程序复杂度的同时还会降低性能。 -* **实现简单,方便维护**:如果 Redis使用多线程模式,那么所有的底层数据结构的设计都必须考虑线程安全问题,那么 Redis 的实现将会变得更加复杂。 - -## Redis6.0为何引入多线程? - -Redis支持多线程主要有两个原因: - -* 可以充分利用服务器 CPU 资源,单线程模型的主线程只能利用一个cpu; - -* 多线程任务可以分摊 Redis 同步 IO 读写的负荷。 - ## Redis应用场景有哪些? 1. **缓存热点数据**,缓解数据库的压力。 @@ -106,12 +81,12 @@ Redis支持多线程主要有两个原因: ## Memcached和Redis的区别? -1. Redis 只使用**单核**,而 Memcached 可以使用多核。 -2. MemCached 数据结构单一,仅用来缓存数据,而 **Redis 支持多种数据类型**。 -3. MemCached 不支持数据持久化,重启后数据会消失。**Redis 支持数据持久化**。 -4. **Redis 提供主从同步机制和 cluster 集群部署能力**,能够提供高可用服务。Memcached 没有提供原生的集群模式,需要依靠客户端实现往集群中分片写入数据。 -5. Redis 的速度比 Memcached 快很多。 -6. Redis 使用**单线程的多路 IO 复用模型**,Memcached使用多线程的非阻塞 IO 模型。 +1. MemCached 数据结构单一,仅用来缓存数据,而 **Redis 支持多种数据类型**。 +2. MemCached 不支持数据持久化,重启后数据会消失。**Redis 支持数据持久化**。 +3. **Redis 提供主从同步机制和 cluster 集群部署能力**,能够提供高可用服务。Memcached 没有提供原生的集群模式,需要依靠客户端实现往集群中分片写入数据。 +4. Redis 的速度比 Memcached 快很多。 +5. Redis 使用**单线程的多路 IO 复用模型**,Memcached使用多线程的非阻塞 IO 模型。(Redis6.0引入了多线程IO,**用来处理网络数据的读写和协议解析**,但是命令的执行仍然是单线程) +6. value 值大小不同:Redis 最大可以达到 512M;memcache 只有 1mb。 ## 为什么要用 Redis 而不用 map/guava 做缓存? diff --git "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" index bf71231..adbb65e 100644 --- "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" @@ -25,9 +25,7 @@ ## RabbitMQ如何保证消息的顺序性? -当生产者只有1个,消费者有多个,每个consumer依次从mq中拿数据取数据消费,这种时候,即使mq中的消息不乱序,但由于消费者处理消息的速度不同,最终产生结果的顺序会不同(比如消费者逻辑是插入数据到数据库) - -解决办法: 保证顺序的消息都放到1个queue里,同时只被1个消费者消费。 +单线程消费保证消息的顺序性;对消息进行编号,消费者根据编号处理消息。 ## 如何避免消息重复消费? diff --git "a/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" index e8f37eb..3808e3a 100644 --- "a/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -22,6 +22,15 @@ +## 设计模式的六大原则 + +- 开闭原则:对扩展开放,对修改关闭,多使用抽象类和接口。 +- 里氏替换原则:基类可以被子类替换,使用抽象类继承,不使用具体类继承。 +- 依赖倒转原则:要依赖于抽象,不要依赖于具体,针对接口编程,不针对实现编程。 +- 接口隔离原则:使用多个隔离的接口,比使用单个接口好,建立最小的接口。 +- 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用,通过中间类建立联系。 +- 合成复用原则:尽量使用合成/聚合,而不是使用继承。 + ## 单例模式 需要对实例字段使用线程安全的延迟初始化,使用双重检查锁定的方案;需要对静态字段使用线程安全的延迟初始化,使用静态内部类的方案。 diff --git "a/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" "b/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" index aab0c1a..c068c14 100644 --- "a/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" @@ -38,4 +38,19 @@ ## 线程和协程有什么区别呢? 1、线程是抢占式,而协程是非抢占式的,所以需要用户自己释放使用权来切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。 -2、线程是协程的资源。协程通过 可以关联任意线程或线程池的执行器(Interceptor)来间接使用线程的资源的。 \ No newline at end of file +2、线程是协程的资源。协程通过 可以关联任意线程或线程池的执行器(Interceptor)来间接使用线程的资源的。 + +## 进程通信 + +进程间通信方式有以下几种: + +1、**管道通信** + + 匿名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 + 有名管道是半双工的通信方式,数据只能单向流动。 + +2、**消息队列** + +3、**共享内存**。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 + +4、**信号量**。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 8d7fee4..72a67a0 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -70,7 +70,7 @@ 举个例子。假定选课关系表为`student_course`(student_no, student_name, age, course_name, grade, credit),主键为(student_no, course_name)。其中学分完全依赖于课程名称,姓名年龄完全依赖学号,不符合第二范式,会导致数据冗余(学生选n门课,姓名年龄有n条记录)、插入异常(插入一门新课,因为没有学号,无法保存新课记录)等问题。 -可以拆分成三个表:学生:`student`(stuent_no, student_name, 年龄);课程:`course`(course_name, credit);选课关系:`student_course_relation`(student_no, course_name, grade)。 +应该拆分成三个表:学生:`student`(stuent_no, student_name, 年龄);课程:`course`(course_name, credit);选课关系:`student_course_relation`(student_no, course_name, grade)。 **第三范式3NF** @@ -302,6 +302,10 @@ explain select user_id from user_like where blog_id = 1; ALTER TABLE table_name ADD KEY(column_name(prefix_length)); ``` +### 索引下推 + +参考我的另一篇文章:[图解索引下推!](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247486661&idx=1&sn=4771369fd5c624c96647696ae76eca4a&chksm=ce98f183f9ef789562ac15c02b0d0dfdf3d2f178ea26667f5aded5d24c1004f049b951e85b33&scene=126&&sessionid=1650167859#rd) + ## 常见的存储引擎有哪些? MySQL中常用的四种存储引擎分别是: **MyISAM**、**InnoDB**、**MEMORY**、**ARCHIVE**。MySQL 5.5版本后默认的存储引擎为`InnoDB`。 @@ -571,13 +575,15 @@ MySQL主要分为 Server 层和存储引擎层: ## 什么是分区表? -分区表是一个独立的逻辑表,但是底层由多个物理子表组成。 +分区是把一张表的数据分成N多个区块。分区表是一个独立的逻辑表,但是底层由多个物理子表组成。 当查询条件的数据分布在某一个分区的时候,查询引擎只会去某一个分区查询,而不是遍历整个表。在管理层面,如果需要删除某一个分区的数据,只需要删除对应的分区即可。 +分区一般都是放在单机里的,用的比较多的是时间范围分区,方便归档。只不过分库分表需要代码实现,分区则是mysql内部实现。分库分表和分区并不冲突,可以结合使用。 + ## 分区表类型 -**按照范围分区。** +**range分区**,按照范围分区。比如按照时间范围分区 ```java CREATE TABLE test_range_partition( @@ -614,7 +620,7 @@ CREATE TABLE test_range_partition( **list分区** -对于`List`分区,分区字段必须是已知的,如果插入的字段不在分区时枚举值中,将无法插入。 +list分区和range分区相似,主要区别在于list是枚举值列表的集合,range是连续的区间值的集合。对于list分区,分区字段必须是已知的,如果插入的字段不在分区时的枚举值中,将无法插入。 ```java create table test_list_partiotion diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" index d8eef1a..9ad4fb0 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -1,6 +1,5 @@ -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - [冒泡排序](#%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F) - [插入排序](#%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F) @@ -16,7 +15,7 @@ ![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) -# 冒泡排序 +## 冒泡排序 ```java public void bubbleSort(int[] arr) { @@ -41,7 +40,7 @@ } ``` -# 插入排序 +## 插入排序 ```java public void insertSort(int[] arr) { @@ -59,7 +58,7 @@ } ``` -# 选择排序 +## 选择排序 ```java public void selectionSort(int[] arr) { @@ -78,12 +77,12 @@ } ``` -# 基数排序 +## 基数排序 在基数排序中,因为没有比较操作,所以在时间复杂上,最好的情况与最坏的情况在时间上是一致的,均为 O(d * (n + r))。d 为位数,r 为基数,n 为原数组个数。 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMzExMDYyOTY4Ni00MDU0Mjk5NjkucG5n?x-oss-process=image/format,png) -# 快速排序 +## 快速排序 ```java public void quickSort(int[] arr) { @@ -126,7 +125,7 @@ } ``` -# 归并排序 +## 归并排序 ![归并排序图](https://images2015.cnblogs.com/blog/1024555/201612/1024555-20161218163120151-452283750.png) @@ -179,7 +178,7 @@ public class MergeSort { } ``` -# 堆排序 +## 堆排序 堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" index 19ab566..6f5ed74 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" @@ -11,7 +11,7 @@ -# 各种数据结构应用场景 +## 各种数据结构应用场景 - 栈:逆序输出;语法检查,符号成对判断;方法调用 - 二叉树:表达式树 @@ -22,7 +22,7 @@ - # AVL树 + ## AVL树 平衡二叉搜索树,它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1。 @@ -38,7 +38,7 @@ -# B树 +## B树 也称B-树,属于多叉树又名平衡多路查找树。 @@ -66,7 +66,7 @@ B-和B+树的区别 -# 红黑树 +## 红黑树 红黑树是对AVL树的优化,只要求部分平衡,用非严格的平衡来换取增删节点时候旋转次数的降低,提高了插入和删除的性能。查找性能并没有提高,查找的时间复杂度是O(logn)。红黑树通过左旋、右旋和变色维持平衡。 @@ -85,7 +85,7 @@ B-和B+树的区别 -# 图 +## 图 图由顶点集(vertex set)和边集(edge set)所组成。 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMDE4NDk0NjAyOC0xNTY4NzUzODc1LnBuZw?x-oss-process=image/format,png) @@ -180,31 +180,3 @@ public interface Graph -# 二分查找 - -```java - public int binarySearch(int[] arr, int target) { - if (arr == null || arr.length <= 1) { - return -1; - } - - int left = 0; - int right = arr.length - 1; - - while (left <= right) { - int mid = (left + right) >>> 1; - if (arr[mid] > target) { - right = mid - 1; - } else if (arr[mid] < target) { - left = mid + 1; - } else { - return mid; - } - } - - return -1; - } -``` - - - diff --git "a/\346\241\206\346\236\266/SpringBoot\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringBoot\345\256\236\346\210\230.md" index 72e6551..2c1a423 100644 --- "a/\346\241\206\346\236\266/SpringBoot\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringBoot\345\256\236\346\210\230.md" @@ -38,10 +38,10 @@ ## Spring Boot基础 理念:习惯优于配置,内置习惯性配置,无需手动进行配置。使用Spring boot可以很快创建一个独立运行、准生产级别的基于Spring框架的项目,不需要或者只需很少的Spring配置。 ### 特点 -- 内置servlet容器,不需要在服务器部署 tomcat。只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目; -- SpringBoot提供了starter,把常用库聚合在一起,简化复杂的环境配置,快速搭建spring应用环境。 - - +- 内置servlet容器,不需要在服务器部署 tomcat。只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目 +- SpringBoot提供了starter,把常用库聚合在一起,简化复杂的环境配置,快速搭建spring应用环境 +- 可以快速创建独立运行的spring项目,集成主流框架 +- 准生产环境的运行应用监控 ## Spring Boot核心 diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index 9df8bdd..e9ddb23 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -1,16 +1,33 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* +## Springboot的优点 -- [自动配置原理](#%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86) -- [实现自动配置](#%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE) +- 内置servlet容器,不需要在服务器部署 tomcat。只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目 +- SpringBoot提供了starter,把常用库聚合在一起,简化复杂的环境配置,快速搭建spring应用环境 +- 可以快速创建独立运行的spring项目,集成主流框架 +- 准生产环境的运行应用监控 - +## SpringBoot 中的 starter 到底是什么 ? + +starter提供了一个自动化配置类,一般命名为 XXXAutoConfiguration ,在这个配置类中通过条件注解来决定一个配置是否生效(条件注解就是 Spring 中原本就有的),然后它还会提供一系列的默认配置,也允许开发者根据实际情况自定义相关配置,然后通过类型安全的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。正因为如此,很多第三方框架,我们只需要引入依赖就可以直接使用了。 + +## 运行 SpringBoot 有哪几种方式? + +1. 打包用命令或者者放到容器中运行 +2. 用 Maven/Gradle 插件运行 +3. 直接执行 main 方法运行 + +## SpringBoot 常用的 Starter 有哪些? + +1. spring-boot-starter-web :提供 Spring MVC + 内嵌的 Tomcat 。 +2. spring-boot-starter-data-jpa :提供 Spring JPA + Hibernate 。 +3. spring-boot-starter-data-Redis :提供 Redis 。 +4. mybatis-spring-boot-starter :提供 MyBatis 。 ## 自动配置原理 SpringBoot实现自动配置原理图解: +> 公众号【程序员大彬】,回复【自动配置】下载高清图片 + ![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 @@ -274,43 +291,6 @@ public class SpringbootDemoApplication { hello.msg=大彬 ``` - - - - ## @Value原理 -@Value的解析就是在bean初始化阶段。BeanPostProcessor定义了bean初始化前后用户可以对bean进行操作的接口方法,它的一个重要实现类AutowiredAnnotationBeanPostProcessor为bean中的@Autowired和@Value注解的注入功能提供支持。 - - - -## 启动过程 - -准备Environment——发布事件——创建上下文、bean——刷新上下文——结束。 - -构造SpringApplication的时候会进行初始化的工作,初始化的时候会做以下几件事: -判断运行环境类型,有三种运行环境:NONE 非 web 的运行环境、SERVLET 普通 web 的运行环境、REACTIVE 响应式 web 的运行环境 -加载 spring.factories 配置文件, 并设置 ApplicationContextInitializer -加载配置文件, 设置 ApplicationListener - - -SpringApplication构造完成之后调用run方法,启动SpringApplication,run方法执行的时候会做以下几件事: -构造一个StopWatch,观察SpringApplication的执行 -找出SpringApplicationRunListener,用于监听SpringApplication run方法的执行。监听的过程中会封装SpringApplicationEvent事件,然后使用ApplicationEventMulticaster广播出去,应用程序监听器ApplicationListener会监听到这些事件 -发布starting事件 -加载配置资源到environment,包括命令行参数、application.yml等 -发布environmentPrepared事件 -创建并初始化ApplicationContext,设置environment,加载配置 -refresh ApplicationContext - -- 设置beanFactory -- 调用BeanFactoryPostProcessors -- 初始化消息源 -- 初始化事件广播器(initApplicationEventMulticaster) -- 调用onRefresh()方法,默认是空实现 -- 注册监听器 -- 实例化non-lazy-init单例 -- 完成refresh -- 发布ContextRefreshedEvent事件 - -发布started事件,启动结束 +@Value的解析就是在bean初始化阶段。BeanPostProcessor定义了bean初始化前后用户可以对bean进行操作的接口方法,它的一个重要实现类`AutowiredAnnotationBeanPostProcessor`为bean中的@Autowired和@Value注解的注入功能提供支持。 diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" index ce0d58b..ed70b24 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" @@ -58,7 +58,7 @@ ## 基础知识 -微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间通过基于HTTP的RESTful API进行通信协作。 +微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行。 [从单体应用到微服务](https://www.zhihu.com/question/65502802/answer/802678798) @@ -354,7 +354,7 @@ com.tyson.helloservice.HelloController : /hello, host:DESKTOP-8F30VS1, service ## Spring Cloud Hystrix -在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于长时间得不到响应而占用线程,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。 +在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于**长时间得不到响应而占用线程**,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。 ### 代码实例 diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index 9f7b047..a85f845 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -32,11 +32,11 @@ ## Spring的优点 -- **轻量**,基本版本大约2MB。 - 通过控制反转和依赖注入实现**松耦合**。 - 支持**面向切面**的编程,并且把应用业务逻辑和系统服务分开。 - 通过切面和模板减少样板式代码。 -- 方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hibernate、MyBatis等)。 +- 声明事物的支持。可以从单调繁冗的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 +- 方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hessian、Quartz、MyBatis等)。 - 方便程序的测试。Spring支持Junit4,添加注解便可以测试Spring程序。 ## Spring 用到了哪些设计模式? @@ -177,13 +177,15 @@ Spring切面可以应用5种类型的通知: IOC:**控制反转**,由Spring容器管理bean的整个生命周期。通过反射实现对其他对象的控制,包括初始化、创建、销毁等,解放手动创建对象的过程,同时降低类之间的耦合度。 -IOC的好处:降低了类之间的耦合,对象创建和初始化交给Spring容器管理,在需要的时候只需向容器进行申请。 +## IOC的好处? -## IOC的优点是什么? +ioc的思想最核心的地方在于,资源不由使用资源者管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。 -- IOC 和依赖注入降低了应用的代码量。 -- 松耦合。 -- 支持加载服务时的饿汉式初始化和懒加载。 +也就是说,甲方要达成某种目的不需要直接依赖乙方,它只需要达到的目的告诉第三方机构就可以了,比如甲方需要一双袜子,而乙方它卖一双袜子,它要把袜子卖出去,并不需要自己去直接找到一个卖家来完成袜子的卖出。它也只需要找第三方,告诉别人我要卖一双袜子。这下好了,甲乙双方进行交易活动,都不需要自己直接去找卖家,相当于程序内部开放接口,卖家由第三方作为参数传入。甲乙互相不依赖,而且只有在进行交易活动的时候,甲才和乙产生联系。反之亦然。这样做什么好处么呢,甲乙可以在对方不真实存在的情况下独立存在,而且保证不交易时候无联系,想交易的时候可以很容易的产生联系。甲乙交易活动不需要双方见面,避免了双方的互不信任造成交易失败的问题。因为交易由第三方来负责联系,而且甲乙都认为第三方可靠。那么交易就能很可靠很灵活的产生和进行了。 + +这就是ioc的核心思想。生活中这种例子比比皆是,支付宝在整个淘宝体系里就是庞大的ioc容器,交易双方之外的第三方,提供可靠性可依赖可灵活变更交易方的资源管理中心。另外人事代理也是,雇佣机构和个人之外的第三方。 + +参考链接:https://www.zhihu.com/question/23277575/answer/24259844 ## 什么是依赖注入? @@ -570,7 +572,7 @@ protected void addSingletonFactory(String beanName, ObjectFactory singletonFa -## Spring 的单例 Bean 是否有线程安全问题? +## Spring 的单例 Bean 是否有并发安全问题? 当多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑,如果业务逻辑有对单例状态的修改(体现为此单例的成员属性),则必须考虑线程安全问题。 @@ -581,3 +583,30 @@ protected void addSingletonFactory(String beanName, ObjectFactory singletonFa 在Spring中无状态的Bean适合用单例模式,这样可以共享实例提高性能。有状态的Bean在多线程环境下不安全,一般用`Prototype`模式或者使用`ThreadLocal`解决线程安全问题。 +## Spring Bean如何保证并发安全? + +Spring的Bean默认都是单例的,某些情况下,单例是并发不安全的。 + +以 `Controller` 举例,假如我们在 `Controller` 中定义了成员变量。当多个请求来临,进入的都是同一个单例的 `Controller` 对象,并对此成员变量的值进行修改操作,因此会互相影响,会有并发安全的问题。 + +应该怎么解决呢? + +为了让多个HTTP请求之间不互相影响,可以采取以下措施: + +**1、单例变原型** + +对 web 项目,可以 `Controller` 类上加注解 @`Scope("prototype")` 或 `@Scope("request")`,对非 web 项目,在 `Component` 类上添加注解 `@Scope("prototype")` 。 + +这种方式实现起来非常简单,但是很大程度上增大了 Bean 创建实例化销毁的服务器资源开销。 + +**2、尽量避免使用成员变量** + +在业务允许的条件下,可以将成员变量替换为方法中的局部变量。这种方式个人认为是最恰当的。 + +**3、使用并发安全的类** + +如果非要在单例Bean中使用成员变量,可以考虑使用并发安全的容器,如 `ConcurrentHashMap`、`ConcurrentHashSet` 等等,将我们的成员变量包装到这些并发安全的容器中进行管理即可。 + +**4、分布式或微服务的并发安全** + +如果还要进一步考虑到微服务或分布式服务的影响,方式3便不合适了。这种情况下可以借助于可以共享某些信息的分布式缓存中间件,如Redis等。这样即可保证同一种服务的不同服务实例都拥有同一份共享信息了。 From 14844a8d7c1441c5184ef02cab7ce54f41a2d4be Mon Sep 17 00:00:00 2001 From: tyson Date: Wed, 18 May 2022 21:15:06 +0800 Subject: [PATCH 02/84] update img url --- Java/JVM.md | 32 ++++---- ...21\351\235\242\350\257\225\351\242\230.md" | 14 ++-- "Java/Java\345\237\272\347\241\200.md" | 10 +-- ...00\351\235\242\350\257\225\351\242\230.md" | 6 +- ...21\351\235\242\350\257\225\351\242\230.md" | 12 +-- ...10\351\235\242\350\257\225\351\242\230.md" | 8 +- "Java/\345\271\266\345\217\221.md" | 22 +++--- "Java/\351\233\206\345\220\210.md" | 8 +- .../RabbitMQ.md" | 10 +-- ...07\345\215\227\346\200\273\347\273\223.md" | 16 ++-- ...is\351\235\242\350\257\225\351\242\230.md" | 10 +-- "\345\205\266\344\273\226/note.md" | 73 ------------------- .../GitHub\346\214\207\345\215\227.md" | 18 ++--- "\345\267\245\345\205\267/progit2.md" | 10 +-- ...47\350\241\214\350\256\241\345\210\222.md" | 44 +++++------ .../MySQL\350\277\233\351\230\266.md" | 24 +++--- ...21\351\235\242\350\257\225\351\242\230.md" | 46 ++++++++---- ...43\347\240\201\345\256\236\347\216\260.md" | 2 +- ...25\351\242\230\346\200\273\347\273\223.md" | 2 +- ...ng\351\235\242\350\257\225\351\242\230.md" | 8 +- .../\347\275\221\347\273\234.md" | 2 +- ...21\351\235\242\350\257\225\351\242\230.md" | 34 ++++----- 22 files changed, 179 insertions(+), 232 deletions(-) diff --git a/Java/JVM.md b/Java/JVM.md index 05f5634..74430f8 100644 --- a/Java/JVM.md +++ b/Java/JVM.md @@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。 JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 -![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png) +![image-20210905150636105](https://gitee.com/tysondai/img/raw/master/image-20210905150636105.png) > 图片来源:深入理解Java虚拟机-周志明 @@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png) +![](https://gitee.com/tysondai/img/raw/master/string-new.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png) +![](https://gitee.com/tysondai/img/raw/master/string-intern.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png) +![](https://gitee.com/tysondai/img/raw/master/string-equal.png) > 图片来源:https://blog.csdn.net/soonfly @@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对 - 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png) +![](https://gitee.com/tysondai/img/raw/master/object-handle.png) - 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png) +![](https://gitee.com/tysondai/img/raw/master/direct-pointer.png) @@ -245,7 +245,7 @@ ClassFile { 加载、验证、准备、解析、初始化、使用和卸载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905002423703.png) ## 类加载的过程 @@ -281,7 +281,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905002827546.png) 双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 @@ -339,7 +339,7 @@ public abstract class ClassLoader { 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png) +![](https://gitee.com/tysondai/img/raw/master/object-dead.png) ### 引用计数法 @@ -365,7 +365,7 @@ public class ReferenceCountingGc { 通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png) +![](https://gitee.com/tysondai/img/raw/master/gc-root-refer.png) #### 可作为GC Roots的对象 @@ -469,13 +469,13 @@ public class ReferenceCountingGc { 标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905003458130.png) ### 复制清除算法 半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905003714551.png) 特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 @@ -534,7 +534,7 @@ java -XX:+PrintCommandLineFlags -version 单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png) +![](https://gitee.com/tysondai/img/raw/master/serial-collector.png) 特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 @@ -542,7 +542,7 @@ java -XX:+PrintCommandLineFlags -version Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png) +![](https://gitee.com/tysondai/img/raw/master/parnew-collector.png) 除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 @@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时 - 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 - 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png) +![](https://gitee.com/tysondai/img/raw/master/cms-collector.png) 由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 @@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应 G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg) +![](https://gitee.com/tysondai/img/raw/master/g1-region.jpg) G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index e4bddb5..7ccae91 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -49,7 +49,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png) +![](https://gitee.com/tysondai/img/raw/master/jvm内存结构0.png) ### 程序计数器 @@ -185,7 +185,7 @@ ClassFile { 类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png) +![](https://gitee.com/tysondai/img/raw/master/类加载.png) **加载** @@ -213,7 +213,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png) +![](https://gitee.com/tysondai/img/raw/master/双亲委派.png) 双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下: @@ -312,7 +312,7 @@ public class ReferenceCount { 通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png) +![](https://gitee.com/tysondai/img/raw/master/可达性分析0.png) ## 可作为GC Roots的对象有哪些? @@ -413,7 +413,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png) +![](https://gitee.com/tysondai/img/raw/master/标记清除.png) **复制清除算法** @@ -425,7 +425,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png) +![](https://gitee.com/tysondai/img/raw/master/标记整理.png) **分类收集算法** @@ -508,7 +508,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低 G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png) +![](https://gitee.com/tysondai/img/raw/master/g1分区.png) G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。 diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" index 72cff97..0f3e5c8 100644 --- "a/Java/Java\345\237\272\347\241\200.md" +++ "b/Java/Java\345\237\272\347\241\200.md" @@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接 Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 -![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png) +![field-method](https://gitee.com/tysondai/img/raw/master/field-method.png) ## Method类 @@ -1101,7 +1101,7 @@ public class GenericMethod { Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: -![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png) +![exception](https://gitee.com/tysondai/img/raw/master/exception.png) - Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 @@ -1198,7 +1198,7 @@ public class ExceptionTest { Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 -![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg) +![io](https://gitee.com/tysondai/img/raw/master/io.jpg) > 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) @@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 -![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png) +![bio](https://gitee.com/tysondai/img/raw/master/bio.png) ## NIO NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 -![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png) +![nio](https://gitee.com/tysondai/img/raw/master/nio.png) NIO与IO区别: diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 5fa2390..095093c 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -101,7 +101,7 @@ **JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) +![](https://gitee.com/tysondai/img/raw/master/20220402230447.png) 所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 @@ -111,7 +111,7 @@ 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) +![](https://gitee.com/tysondai/img/raw/master/20220401234008.png) JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 @@ -141,7 +141,7 @@ JRE = JVM + Java 核心类库 JDK = JRE + Java工具 + 编译器 + 调试器 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) +![](https://gitee.com/tysondai/img/raw/master/20220402230613.png) ## 面向对象有哪些特性? diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index a65d22c..cfcb15d 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -64,7 +64,7 @@ ### 线程池执行原理? -![线程池执行流程](https://raw.githubusercontent.com/Tyson0314/img/master/线程池执行流程.png) +![线程池执行流程](https://gitee.com/tysondai/img/raw/master/线程池执行流程.png) 1. 当线程池里存活的线程数小于核心线程数`corePoolSize`时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数`corePoolSize`时,线程池里面的线程会一直存活着,就算空闲时间超过了`keepAliveTime`,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。 2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。 @@ -199,7 +199,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -225,7 +225,7 @@ public static ExecutorService newCachedThreadPool() { **终止(TERMINATED)**:表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -401,7 +401,7 @@ class RunnableDemo implements Runnable { 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) +![死锁](https://gitee.com/tysondai/img/raw/master/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -686,7 +686,7 @@ class SeasonThreadTask implements Runnable{ 每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/threadlocal.png) +![](https://gitee.com/tysondai/img/raw/master/threadlocal.png) 调用`threadLocal.set()`-->调用`getMap(Thread)`-->返回当前线程的`ThreadLocalMap`-->`map.set(this, value)`,this是`threadLocal`本身。源码如下: @@ -783,7 +783,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节点中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/aqs.png) +![](https://gitee.com/tysondai/img/raw/master/aqs.png) ## ReentrantLock 是如何实现可重入性的? diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index 14acae6..4a011e4 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -54,9 +54,9 @@ Java集合类主要由两个接口**Collection**和**Map**派生出来的,Coll Java集合框架图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/collections2.png) +![](https://gitee.com/tysondai/img/raw/master/collections2.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/map.png) +![](https://gitee.com/tysondai/img/raw/master/map.png) List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合。Map代表的是存储key-value对的集合,可根据元素的key来访问value。 @@ -197,7 +197,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![图片来源网络](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) ### 红黑树的特点? @@ -271,7 +271,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" index 1f35396..c9734f5 100644 --- "a/Java/\345\271\266\345\217\221.md" +++ "b/Java/\345\271\266\345\217\221.md" @@ -87,7 +87,7 @@ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveT 创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/thread-pool.png) +![](https://gitee.com/tysondai/img/raw/master/thread-pool.png) ThreadPoolExecutor 的通用构造函数: @@ -326,7 +326,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -340,7 +340,7 @@ FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VAL CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/executors-ali.png) +![](https://gitee.com/tysondai/img/raw/master/executors-ali.png) 正确示例(阿里巴巴编码规范): @@ -369,7 +369,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909233258929.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909233258929.png) 本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 @@ -392,7 +392,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 终止(TERMINATED):表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -680,7 +680,7 @@ public class SynchronizedDemo { Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-block.png) +![](https://gitee.com/tysondai/img/raw/master/synchronized-block.png) **方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 @@ -692,7 +692,7 @@ public class SynchronizedMethod { } ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-method.png) +![](https://gitee.com/tysondai/img/raw/master/synchronized-method.png) #### 锁的状态 @@ -1077,7 +1077,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210910000456607.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210910000456607.png) @@ -1112,19 +1112,19 @@ public void conditionSignal() throws InterruptedException { 每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-await.png) +![](https://gitee.com/tysondai/img/raw/master/condition-await.png) > 图片来源:Java并发编程的艺术 在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-wait-queue.png) +![](https://gitee.com/tysondai/img/raw/master/condition-wait-queue.png) > 图片来源:Java并发编程的艺术 线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-signal.png) +![](https://gitee.com/tysondai/img/raw/master/condition-signal.png) > 图片来源:Java并发编程的艺术 diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" index 83fecae..c7283d5 100644 --- "a/Java/\351\233\206\345\220\210.md" +++ "b/Java/\351\233\206\345\220\210.md" @@ -51,7 +51,7 @@ 以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/Java-Collections.jpeg) +![](https://gitee.com/tysondai/img/raw/master/Java-Collections.jpeg) ### HashMap @@ -88,7 +88,7 @@ put方法流程: 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) > 参考链接: > @@ -121,7 +121,7 @@ HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初 LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 -![linkedhashmap](https://raw.githubusercontent.com/Tyson0314/img/master/linkedhashmap.png) +![linkedhashmap](https://gitee.com/tysondai/img/raw/master/linkedhashmap.png) ### TreeMap @@ -136,7 +136,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" index e5ba58b..2042d70 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" @@ -39,13 +39,13 @@ 文章目录: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914234334988.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210914234334988.png) # 简介 RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq.png) ## 基本概念 @@ -94,19 +94,19 @@ Exchange规则。 direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-direct.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-direct.png) ## fanout 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-fanout.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-fanout.png) ## topic topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-topic.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-topic.png) ## headers diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index 8d4e0d7..f329ea8 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -71,7 +71,7 @@ 目录结构如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914000822843.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210914000822843.png) ## 简介 @@ -503,7 +503,7 @@ ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的 - 最底层的链表包含所有的元素 - 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-skiplist.png) +![](https://gitee.com/tysondai/img/raw/master/redis-skiplist.png) #### 对象 @@ -545,7 +545,7 @@ hash类型内部编码有两种: Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/list-api.png) +![](https://gitee.com/tysondai/img/raw/master/list-api.png) 使用场景: @@ -630,7 +630,7 @@ GET #返回文章ID。 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) DISCARD:放弃事务,即该事务内的所有命令都将取消 @@ -653,7 +653,7 @@ QUEUED 事务里的命令执行时会读取最新的值: -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-transaction.png) +![](https://gitee.com/tysondai/img/raw/master/redis-transaction.png) ### WATCH命令 @@ -800,7 +800,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-replication.png) +![](https://gitee.com/tysondai/img/raw/master/redis-replication.png) Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 @@ -932,7 +932,7 @@ redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 使用evalsha执行Lua脚本过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/evalsha.png) +![](https://gitee.com/tysondai/img/raw/master/evalsha.png) ### lua脚本作用 @@ -1075,7 +1075,7 @@ public void write(String key,Object data){ 解决方法: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210913235221410.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210913235221410.png) > 图片来源:https://tech.it168.com diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index d5704d2..8a0e0d6 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -153,7 +153,7 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) 一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: @@ -224,7 +224,7 @@ Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF` `bgsave`是主流的触发 RDB 持久化的方式,执行过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/rdb持久化过程.png) +![](https://gitee.com/tysondai/img/raw/master/rdb持久化过程.png) - 执行`BGSAVE`命令 - Redis 父进程判断当前**是否存在正在执行的子进程**,如果存在,`BGSAVE`命令直接返回。 @@ -269,7 +269,7 @@ appendfsync no //由操作系统决定何时进行同步操作 接下来看一下 AOF 持久化执行流程: -![](https://raw.githubusercontent.com/Tyson0314/img/master/aof工作流程0.png) +![](https://gitee.com/tysondai/img/raw/master/aof工作流程0.png) 1. 所有的写入命令会追加到 AOP 缓冲区中。 2. AOF 缓冲区根据对应的策略向硬盘同步。 @@ -334,7 +334,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 客户端连接Redis的时候,先连接哨兵,哨兵会告诉客户端Redis主节点的地址,然后客户端连接上Redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/sentinel.png) +![](https://gitee.com/tysondai/img/raw/master/sentinel.png) **工作原理** @@ -353,7 +353,7 @@ Redis cluster集群节点最小配置6个节点以上(3主3从),其中主 Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) +![](https://gitee.com/tysondai/img/raw/master/cluster_slots.png) **哈希槽是如何映射到 Redis 实例上的?** diff --git "a/\345\205\266\344\273\226/note.md" "b/\345\205\266\344\273\226/note.md" index dd2906f..dad41bf 100644 --- "a/\345\205\266\344\273\226/note.md" +++ "b/\345\205\266\344\273\226/note.md" @@ -146,15 +146,6 @@ HMACSHA256( -## 秒杀系统 - -rabbitmq是为了削峰,如果是有1000件商品参与秒杀,每个商品有10件,那么系统的最大并发就是1万,db扛不住这么大的并发的,如果商品数量更大,这个并发量会更大。 -通过Redis预减库存减少到DB的请求,通过消息队列异步写库缓解数据库的压力。用消息队列来缓冲瞬时流量,把同步的直接调用转换成异步操作。 - -把判断库存扣减库存的操作封装成lua脚本,实现原子性操作,避免超卖。 - -![](../img/others/seckill.jpg) - ## shiro @@ -271,31 +262,6 @@ select、poll和epoll都是IO多路复用的机制。 -## 超卖问题 - -先到数据库查询库存,在减库存。不是原子操作,会有超卖问题。 - -通过加排他锁解决该问题。 - -- 开始事务。 -- 查询库存,并显式的设置排他锁:SELECT * FROM table_name WHERE … FOR UPDATE -- 生成订单。 -- 去库存,update会隐式的设置排他锁:UPDATE products SET count=count-1 WHERE id=1 -- commit,释放锁。 - -也可以通过乐观锁实现。使用版本号实现乐观锁。 - -假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。 - -然后直接update的时候,只有其中一个先update了,同时更新了版本号。 - -那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了,则放弃此次update,重试直到成功。 - -```mysql -select version from goods WHERE id= 1001 -update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version); -``` - ## TPS和QPS @@ -318,42 +284,3 @@ Tps即每秒处理事务数,包括了三个过程: -## 微服务 - -单体应用:将所有功能都打包成在一个独立单元的应用程序。 - -微服务将单一应用程序划分成一组小的服务,服务之间相互协调、互相配合。每个服务运行在其独立的进程中,服务和服务之间采用轻量级的通信机制相互沟通。每个服务可以被独立的部署到生产环境。 - - - -## 进程通信 - -进程间通信方式: -1、管道通信 - 匿名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 - 有名管道是半双工的通信方式,数据只能单向流动。 -2、消息队列 -3、共享内存。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 -4、信号量。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 - - - -## 分布式事务 - -分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务的特性。 -CAP理论 -Consistency(一致性):数据一致更新,所有数据变动都是同步的(强一致性)。 -Availability(可用性):好的响应性能 -Partition tolerance(分区容错性) :可靠性 - -定理:任何分布式系统只可同时满足二点,没法三者兼顾。 - -CA系统(放弃P):指将所有数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上,就不会存在网络分区。所以强一致性以及可用性得到满足。 -CP系统(放弃A):如果要求数据在各个服务器上是强一致的,然而网络分区会导致同步时间无限延长,那么如此一来可用性就得不到保障了。坚持事务ACID(原子性、一致性、隔离性和持久性)的传统数据库以及对结果一致性非常敏感的应用通常会做出这样的选择。 -AP系统(放弃C):这里所说的放弃一致性,并不是完全放弃数据一致性,而是放弃数据的强一致性,而保留数据的最终一致性。如果即要求系统高可用又要求分区容错,那么就要放弃一致性了。因为一旦发生网络分区,节点之间将无法通信,为了满足高可用,每个节点只能用本地数据提供服务,这样就会导致数据不一致。一些遵守BASE原则数据库,(如:Cassandra、CouchDB等)往往会放宽对一致性的要求(满足最终一致性即可),一次来获取基本的可用性。 - -BASE理论 -Basically Available基本可用:指分布式系统在出现不可预知的故障的时候,允许损失部分可用性——但不是系统不可用。 -响应时间上的损失:假如正常一个在线搜索0.5秒之内返回,但由于故障(机房断电或网络不通),查询结果的响应时间增加到1—2秒。功能上的损失:如果流量激增或者一个请求需要多个服务间配合,而此时有的服务发生了故障,这时需要进行服务降级,进而保护系统稳定性。 -Soft state软状态:允许系统在不同节点的数据副本之间进行数据同步的过程存在延迟。Eventually consistent最终一致:最终数据是一致的就可以了,而不是时时高一致。 -BASE思想主要强调基本的可用性,如果你需要High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲。 \ No newline at end of file diff --git "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" index a125d4b..cca4277 100644 --- "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" +++ "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" @@ -22,15 +22,15 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 创建一个新的仓库,用来存放项目。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822154700616.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210822154700616.png) - 或者你在GitHub上看到别人有一个超级无敌有趣的项目,可以直接fork过来,可以理解成复制过来,变成你自己的。之后你想怎么改就怎么改! - ![image-20210822155107839](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155107839.png) + ![image-20210822155107839](https://gitee.com/tysondai/img/raw/master/image-20210822155107839.png) - 然后你可以通过Git命令行`git clone xxx`把项目clone到本地,在本地进行创作。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155359118.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210822155359118.png) - 最后,在本地创作完成,可以使用`git commit -m xxx`提交到本地库,然后使用`git push`把修改推送到GitHub仓库。之后就可以在GitHub上面看到你修改的内容啦~ @@ -42,23 +42,23 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 评价GitHub项目的两个重要的参数:star和fork。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161003170.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161003170.png) 比较优秀和热门的项目,star数目和fork数目都会比较多。我们可以根据这两个参数筛选出比较好的项目。使用`关键字 stars:>=xxx forks:>=xxx` 可以筛选出star和fork数目大于xxx的相关项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161122586.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161122586.png) - 使用 `awesome 关键字`,可以筛选出比较高质量的学习、书籍、工具类或者插件类的集合。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161608599.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161608599.png) - 在特定位置搜索关键词。有些关键词出现在项目的不同位置,比如项目名称、项目描述和README等。使用`关键词 in name/description/Readme`,可以搜索到相关的内容。比如使用`spring in name`,可以搜索到在项目名中包含spring的项目。 -![image-20210822162144086](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822162144086.png) +![image-20210822162144086](https://gitee.com/tysondai/img/raw/master/image-20210822162144086.png) - 指定条件搜索关键词。如`tool language:java`搜索到的是包含关键字tool的Java项目,`tool followers:>1000`可以搜索到包含关键字tool,且follower数量大于1000的项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822163111390.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822163111390.png) @@ -72,7 +72,7 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 文档神器。可以为自己的项目建立wiki,可以用markdown语法写wiki; -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822172419760.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822172419760.png) - 使用GitHub pages建立个人静态网站,搞一个有自己域名的独立博客,想想都觉得开心。使用GitHub pages的好处是搭建简单而且免费,支持静态脚本,并且可以绑定自己的域名。具体可以参考:[GitHub Pages 建立个人网站详细教程 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/58229299) diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/progit2.md" index 68b8c2b..6dde18b 100644 --- "a/\345\267\245\345\205\267/progit2.md" +++ "b/\345\267\245\345\205\267/progit2.md" @@ -85,7 +85,7 @@ Git工作流程如下: Git 的工作流程图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-work-flow.png) +![](https://gitee.com/tysondai/img/raw/master/git-work-flow.png) > 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 @@ -103,11 +103,11 @@ Git 的三种状态:已修改(modified)、已暂存(staged)和已提 基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/git工作流程.png) +![](https://gitee.com/tysondai/img/raw/master/git工作流程.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-status.png) +![](https://gitee.com/tysondai/img/raw/master/git-status.png) ## 配置 @@ -156,7 +156,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](https://raw.githubusercontent.com/Tyson0314/img/master/git生命周期.png) +![git生命周期](https://gitee.com/tysondai/img/raw/master/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -262,7 +262,7 @@ git commit -m "add readme.md" 单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210830225020753.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210830225020753.png) 此时应该这么操作: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" index e9f255a..2378225 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" @@ -91,7 +91,7 @@ where blog_id = ( 三个表依次嵌套,发现最里层的子查询 `id`最大,最先执行。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-id.png) +![](https://gitee.com/tysondai/img/raw/master/explain-id.png) ## select_type @@ -107,13 +107,13 @@ where blog_id = ( 查询的表名,并不一定是真实存在的表,有别名显示别名,也可能为临时表。当from子句中有子查询时,table列是 ``的格式,表示当前查询依赖 id为N的查询,会先执行 id为N的查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804083523885.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210804083523885.png) ## partitions 查询时匹配到的分区信息,对于非分区表值为`NULL`,当查询的是分区表时,`partitions`显示分区表命中的分区情况。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802022931773.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802022931773.png) ## type @@ -123,25 +123,25 @@ where blog_id = ( 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快。比如,Mysql系统表proxies_priv在Mysql服务启动时候已经加载在内存中,对这个表进行查询不需要进行磁盘 IO。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801233419732.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210801233419732.png) ### const 单表操作的时候,查询使用了主键或者唯一索引。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-const.png) +![](https://gitee.com/tysondai/img/raw/master/explain-const.png) ### eq_ref **多表关联**查询的时候,主键和唯一索引作为关联条件。如下图的sql,对于user表(外循环)的每一行,user_role表(内循环)只有一行满足join条件,只要查找到这行记录,就会跳出内循环,继续外循环的下一轮查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801232638027.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210801232638027.png) ### ref 查找条件列使用了索引而且不为主键和唯一索引。虽然使用了索引,但该索引列的值并不唯一,这样即使使用索引查找到了第一条数据,仍然不能停止,要在目标值附近进行小范围扫描。但它的好处是不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内做扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-ref.png) +![](https://gitee.com/tysondai/img/raw/master/explain-ref.png) ### ref_or_null @@ -151,13 +151,13 @@ where blog_id = ( 使用了索引合并优化方法,查询使用了两个以上的索引。新建comment表,id为主键,value_id为非唯一索引,执行`explain select content from comment where value_id = 1181000 and id > 1000;`,执行结果显示查询同时使用了id和value_id索引,type列的值为index_merge。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802001215614.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802001215614.png) ### range 有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。像between、and、'>'、'<'、in和or都是范围索引扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-range.png) +![](https://gitee.com/tysondai/img/raw/master/explain-range.png) ### index @@ -165,17 +165,17 @@ index包括select索引列,order by主键两种情况。 1. order by主键。这种情况会按照索引顺序全表扫描数据,拿到的数据是按照主键排好序的,不需要额外进行排序。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225045980.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210801225045980.png) 2. select索引列。type为index,而且extra字段为using index,也称这种情况为索引覆盖。所需要取的数据都在索引列,无需回表查询。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225942948.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210801225942948.png) ### all 全表扫描,查询没有用到索引,性能最差。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-all.png) +![](https://gitee.com/tysondai/img/raw/master/explain-all.png) ## possible_keys @@ -249,13 +249,13 @@ CREATE TABLE `t_orderdetail` ( 查询的列未被索引覆盖,where筛选条件非索引的前导列。对存储引擎返回的结果进行过滤(Post-filter,后过滤),一般发生在MySQL服务器,而不是存储引擎层。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232729417.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802232729417.png) ### using index 查询的列被索引覆盖,并且where筛选条件符合最左前缀原则,通过**索引查找**就能直接找到符合条件的数据,不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232357282.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802232357282.png) ### Using where&Using index @@ -265,17 +265,17 @@ CREATE TABLE `t_orderdetail` ( - where筛选条件不符合最左前缀原则 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233120283.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210802233120283.png) - where筛选条件是索引列前导列的一个范围 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233455880.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210802233455880.png) ### null 查询的列未被索引覆盖,并且where筛选条件是索引的前导列,也就是用到了索引,但是部分字段未被索引覆盖,必须回表查询这些字段,Extra中为NULL。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802234122321.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802234122321.png) ### using index condition @@ -283,11 +283,11 @@ CREATE TABLE `t_orderdetail` ( 不使用ICP的情况(`set optimizer_switch='index_condition_pushdown=off'`),如下图,在步骤4中,没有使用where条件过滤索引: -![](https://raw.githubusercontent.com/Tyson0314/img/master/no-icp.png) +![](https://gitee.com/tysondai/img/raw/master/no-icp.png) 使用ICP的情况(`set optimizer_switch='index_condition_pushdown=on'`): -![](https://raw.githubusercontent.com/Tyson0314/img/master/icp.png) +![](https://gitee.com/tysondai/img/raw/master/icp.png) 下面的例子使用了ICP: @@ -296,11 +296,11 @@ explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G; ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084617433.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210803084617433.png) 关掉ICP之后(`set optimizer_switch='index_condition_pushdown=off'`),可以看到extra列为using where,不会使用索引下推。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084815503.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210803084815503.png) ### using temporary @@ -314,7 +314,7 @@ from t_order where user_id > 1 and user_id < 5\G; - select 查询字段不全是索引字段 - select 查询字段都是索引字段,但是 order by 字段和索引字段的顺序不一致 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804084029239.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210804084029239.png) ### using join buffer diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" index 7caa4e5..4ff8a64 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" @@ -138,7 +138,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821165019147.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210821165019147.png) 进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的数据项。 @@ -170,15 +170,15 @@ Index_comment: 如下图,col1 是主键,col2和col3是普通字段。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234137916.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234137916.png) 下图是主键索引对应的 B+树结构,每个节点对应磁盘的一页。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234200868.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234200868.png) 对col3 建立一个单列索引,对应的B+树结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234231001.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234231001.png) ### 索引分类 1. 主键索引:名为primary的唯一非空索引,不允许有空值。 @@ -208,7 +208,7 @@ Index_comment: 对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会对b进行比较排序)。直接执行`b = 2`这种查询条件没有办法利用索引。 -![最左匹配](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821103313578.png) +![最左匹配](https://gitee.com/tysondai/img/raw/master/image-20210821103313578.png) 从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行`a = 1 and b = 2`是a,b字段能用到索引的。而你执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。 @@ -218,7 +218,7 @@ InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的 聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-clustered-index.png) +![](https://gitee.com/tysondai/img/raw/master/mysql-clustered-index.png) 对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。 @@ -244,7 +244,7 @@ explain select user_id from user_like where blog_id = 1; Extra中为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](https://gitee.com/tysondai/img/raw/master/cover-index.png) ### 索引失效 @@ -322,7 +322,7 @@ MEMORY引擎默认使用哈希索引,将键的哈希值和指向数据行的 myisam引擎主键索引和其他索引区别不大,叶子节点都包含索引值和行指针。 innodb引擎二级索引叶子存储的是索引值和主键值(不是行指针),这样可以减少行移动和数据页分裂时二级索引的维护工作。 - ![myisam-innodb-index](https://raw.githubusercontent.com/Tyson0314/img/master/myisam-innodb-index.png) + ![myisam-innodb-index](https://gitee.com/tysondai/img/raw/master/myisam-innodb-index.png) @@ -351,7 +351,7 @@ mvcc实现依赖于版本链,版本链是通过表的三个隐藏字段实现 3. 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链; 4. 记录redo log; -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc-impl.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc-impl.png) ### read view @@ -388,14 +388,14 @@ repeatable read:在一个事务范围内,第一次select时更新这个read_ 事务a和事务b同时开启事务,事务a插入数据然后提交,事务b执行全表的update,然后执行查询,查到了事务A中添加的数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](https://gitee.com/tysondai/img/raw/master/幻读1.png) MySQL如何实现避免幻读: - 在快照读情况下,MySQL通过mvcc来避免幻读。 - 在当前读情况下,MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/current-read.png) +![](https://gitee.com/tysondai/img/raw/master/current-read.png) next-key包括两部分:行锁和间隙锁。行锁是加在索引上的锁,间隙锁是加在索引之间的。 @@ -531,7 +531,7 @@ MySQL主要分为 Server 层和存储引擎层: - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 - **存储引擎**: 主要负责数据的存储和读取。server 层通过api与存储引擎进行通信。 -![MySQL-archpng](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-archpng.png) +![MySQL-archpng](https://gitee.com/tysondai/img/raw/master/mysql-archpng.png) ### Server 层基本组件 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 72a67a0..61ed2f8 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -116,6 +116,22 @@ select @@transaction_isolation; set session transaction isolation level read uncommitted; ``` +## 生产环境数据库一般用的什么隔离级别呢? + +**生产环境大多使用RC**。为什么不是RR呢? + +> 可重复读(Repeatable Read),简称为RR +> 读已提交(Read Commited),简称为RC + +缘由一:在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多! +缘由二:在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行! + +也就是说,RC的并发性高于RR。 + +并且大部分场景下,不可重复读问题是可以接受的。毕竟数据都已经提交了,读出来本身就没有太大问题! + +[互联网项目中mysql应该选什么事务隔离级别](https://zhuanlan.zhihu.com/p/59061106) + ## 索引 ### 什么是索引? @@ -148,10 +164,10 @@ set session transaction isolation level read uncommitted; ### 什么情况下不建索引? 1. `where`条件中用不到的字段不适合建立索引 -2. 表记录较少 -3. 需要经常增删改 +2. 表记录较少。比如只有几百条数据,没必要加索引。 +3. 需要经常增删改。需要评估是否适合加索引 4. **参与列计算**的列不适合建索引 -5. **区分度不高**的字段不适合建立索引,如性别等 +5. **区分度不高**的字段不适合建立索引,如性别,只有男/女/未知三个值。加了索引,查询效率也不会提高。 ### 索引的数据结构 @@ -163,7 +179,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 `key` 从左到右递增排列,如果某个指针的左右相邻 `key` 分别是 keyi 和 keyi+1,则该指针指向节点的所有 `key` 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/B+树索引0.png) +![](https://gitee.com/tysondai/img/raw/master/B+树索引0.png) 进行查找操作时,首先在根节点进行二分查找,找到`key`所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出`key`所对应的数据项。 @@ -233,7 +249,7 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 如下图,对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会根据b进行排序)。直接执行`b = 2`这种查询条件无法使用索引。 -![最左前缀](https://raw.githubusercontent.com/Tyson0314/img/master/最左前缀.png) +![最左前缀](https://gitee.com/tysondai/img/raw/master/最左前缀.png) 当a的值确定的时候,b是有序的。例如`a = 1`时,b值为1,2是有序的状态。当`a = 2`时候,b的值为1,4也是有序状态。 当执行`a = 1 and b = 2`时a和b字段能用到索引。而执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段无法使用索引。 @@ -267,7 +283,7 @@ explain select user_id from user_like where blog_id = 1; `explain`结果的`Extra`列为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](https://gitee.com/tysondai/img/raw/master/cover-index.png) ### 索引的设计原则? @@ -377,7 +393,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 每条表记录大概是这样的: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc9.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc9.png) 使用事务更新行记录的时候,就会生成版本链,执行过程如下: @@ -389,15 +405,15 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、初始数据如下,其中`DB_ROW_ID`和`DB_ROLL_PTR`为空。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc2.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc2.png) 2、事务A对该行数据做了修改,将`age`修改为12,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc7.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc7.png) 3、之后事务B也对该行记录做了修改,将`age`修改为8,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc11.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc11.png) 4、此时undo log有两行记录,并且通过回滚指针连在一起。 @@ -417,7 +433,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 **前提**:`DATA_TRX_ID` 表示每个数据行的最新的事务ID;`up_limit_id`表示当前快照中的最先开始的事务;`low_limit_id`表示当前快照中的最慢开始的事务,即最后一个事务。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/read_view10.png) +![](https://gitee.com/tysondai/img/raw/master/read_view10.png) - 如果`DATA_TRX_ID` < `up_limit_id`:说明在创建`read view`时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。 - 如果`DATA_TRX_ID` >= `low_limit_id`:说明当前版本的记录的事务是在创建`read view`之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。 @@ -442,7 +458,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、首先,user表只有两条记录,具体如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210922232259664.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210922232259664.png) 2、事务a和事务b同时开启事务`start transaction`; @@ -460,7 +476,7 @@ update user set user_name = 'a'; 5、事务b然后执行查询,查到了事务a中插入的数据。(下图左边是事务b,右边是事务a。事务开始之前只有两条记录,事务a插入一条数据之后,事务b查询出来是三条数据) -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](https://gitee.com/tysondai/img/raw/master/幻读1.png) 以上就是当前读出现的幻读现象。 @@ -549,7 +565,7 @@ MySQL主要分为 Server 层和存储引擎层: 垂直划分数据库是根据业务进行划分,例如购物场景,可以将库中涉及商品、订单、用户的表分别划分出成一个库,通过降低单库的大小来提高性能。同样的,分表的情况就是将一个大表根据业务功能拆分成一个个子表,例如商品基本信息和商品描述,商品基本信息一般会展示在商品列表,商品描述在商品详情页,可以将商品基本信息和商品描述拆分成两张表。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/垂直划分.png) +![](https://gitee.com/tysondai/img/raw/master/垂直划分.png) **优点**:行记录变小,数据页可以存放更多记录,在查询时减少I/O次数。 @@ -563,7 +579,7 @@ MySQL主要分为 Server 层和存储引擎层: 水平划分是根据一定规则,例如时间或id序列值等进行数据的拆分。比如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,从而提升性能。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/水平划分.png) +![](https://gitee.com/tysondai/img/raw/master/水平划分.png) **优点**:单库(表)的数据量得以减少,提高性能;切分出的表结构相同,程序改动较少。 diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" index 9ad4fb0..9a99fb1 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -13,7 +13,7 @@ 常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) +![](https://gitee.com/tysondai/img/raw/master/排序算法.png) ## 冒泡排序 diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index e9ddb23..dd8b7fb 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -28,7 +28,7 @@ SpringBoot实现自动配置原理图解: > 公众号【程序员大彬】,回复【自动配置】下载高清图片 -![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) +![](https://gitee.com/tysondai/img/raw/master/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index a85f845..ae4a031 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -112,6 +112,10 @@ AOP有两种实现方式:静态代理和动态代理。 动态代理:代理类在程序运行时创建,AOP框架不会去修改字节码,而是在内存中临时生成一个代理对象,在运行期间对业务方法进行增强,不会生成新类。 +## Spring AOP的实现原理 + +`Spring`的`AOP`实现原理其实很简单,就是通过**动态代理**实现的。如果我们为`Spring`的某个`bean`配置了切面,那么`Spring`在创建这个`bean`的时候,实际上创建的是这个`bean`的一个代理对象,我们后续对`bean`中方法的调用,实际上调用的是代理类重写的代理方法。而`Spring`的`AOP`使用了两种动态代理,分别是**JDK的动态代理**,以及**CGLib的动态代理**。 + ## JDK动态代理和CGLIB动态代理的区别? Spring AOP中的动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。 @@ -122,7 +126,7 @@ Spring AOP中的动态代理主要有两种方式:JDK动态代理和CGLIB动 缺点:**目标类必须有实现的接口**。如果某个类没有实现接口,那么这个类就不能用JDK动态代理。 -**CGLIB来动态代理** +**CGLIB动态代理** **通过继承实现**。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library)可以在运行时动态生成类的字节码,动态创建目标类的子类对象,在子类对象中增强目标类。 @@ -212,7 +216,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](https://raw.githubusercontent.com/Tyson0314/img/master/bean生命周期.png) +![](https://gitee.com/tysondai/img/raw/master/bean生命周期.png) 1.调用bean的构造方法创建Bean diff --git "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" index 60a94c1..0320b99 100644 --- "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" +++ "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" @@ -333,7 +333,7 @@ HTTP长连接,指的是复用TCP连接。多个HTTP请求可以复用同一个 CDN用户访问流程: -![cdn](https://raw.githubusercontent.com/Tyson0314/img/master/cdn.png) +![cdn](https://gitee.com/tysondai/img/raw/master/cdn.png) 1.用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有dns缓存,则向网站的DNS服务器请求; diff --git "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 48969f2..2fb8b79 100644 --- "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -38,7 +38,7 @@ 计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/tcp5layer2.png) +![](https://gitee.com/tysondai/img/raw/master/tcp5layer2.png) 五层模型:应用层、传输层、网络层、数据链路层、物理层。 @@ -52,7 +52,7 @@ 假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是`CLOSED`。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/三次握手图解.png) +![](https://gitee.com/tysondai/img/raw/master/三次握手图解.png) 1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位`SYN=1`,序列号`seq=x`。第一次握手前客户端的状态为`CLOSE`,第一次握手后客户端的状态为`SYN-SENT`。此时服务端的状态为`LISTEN`。 2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位`SYN=1`,`ACK=1`,序列号`seq=y`,确认号`ack=x+1`。第二次握手前服务端的状态为`LISTEN`,第二次握手后服务端的状态为`SYN-RCVD`,此时客户端的状态为`SYN-SENT`。(其中`SYN=1`表示要和客户端建立一个连接,`ACK=1`表示确认序号有效) @@ -69,7 +69,7 @@ ## 四次挥手 -![](https://raw.githubusercontent.com/Tyson0314/img/master/四次挥手0.png) +![](https://gitee.com/tysondai/img/raw/master/四次挥手0.png) 1. A的应用进程先向其TCP发出连接释放报文段(`FIN=1,seq=u`),并停止再发送数据,主动关闭TCP连接,进入`FIN-WAIT-1`(终止等待1)状态,等待B的确认。 2. B收到连接释放报文段后即发出确认报文段(`ACK=1,ack=u+1,seq=v`),B进入`CLOSE-WAIT`(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 @@ -152,7 +152,7 @@ Content-Length:112 ## HTTP状态码有哪些? -![](https://raw.githubusercontent.com/Tyson0314/img/master/http-status-code.png) +![](https://gitee.com/tysondai/img/raw/master/http-status-code.png) ## POST和GET的区别? @@ -194,7 +194,7 @@ HTTP2.0相比HTTP1.1支持的特性: 服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:**证书内容、证书签名算法和签名**,签名是为了验证身份。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004111441594.png) +![](https://gitee.com/tysondai/img/raw/master/image-20211004111441594.png) 服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。 @@ -216,29 +216,29 @@ HTTP2.0相比HTTP1.1支持的特性: 1. **协商加密算法** 。在`Client Hello`里面客户端会告知服务端自己当前的一些信息,包括客户端要使用的TLS版本,支持的加密算法,要访问的域名,给服务端生成的一个随机数(Nonce)等。需要提前告知服务器想要访问的域名以便服务器发送相应的域名的证书过来。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921104210833.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921104210833.png) 2. 服务端响应`Server Hello`,告诉客户端服务端**选中的加密算法**。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105450791.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921105450791.png) 3. 接着服务端给客户端发来了2个证书。第二个证书是第一个证书的签发机构(CA)的证书。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004172007102.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20211004172007102.png) 4. 客户端使用证书的认证机构CA公开发布的RSA公钥**对该证书进行验证**,下图表明证书认证成功。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105929268.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921105929268.png) 5. 验证通过之后,浏览器和服务器通过**密钥交换算法**产生共享的**对称密钥**。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110025197.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110025197.png) - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110155075.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110155075.png) 6. 开始传输数据,使用同一个对称密钥来加解密。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110315068.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110315068.png) ## DNS 的解析过程? @@ -257,7 +257,7 @@ HTTP2.0相比HTTP1.1支持的特性: 4. 服务器**响应请求**,返回响应数据。 5. 浏览器**解析响应内容,进行渲染**,呈现给用户。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/输入url返回页面过程1.png) +![](https://gitee.com/tysondai/img/raw/master/输入url返回页面过程1.png) ## 什么是cookie和session? @@ -265,7 +265,7 @@ HTTP2.0相比HTTP1.1支持的特性: 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 **cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cookie.png) +![](https://gitee.com/tysondai/img/raw/master/cookie.png) **cookie工作流程**: @@ -274,7 +274,7 @@ HTTP2.0相比HTTP1.1支持的特性: 3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 **session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/session.png) +![](https://gitee.com/tysondai/img/raw/master/session.png) ## Cookie和Session的区别? @@ -293,7 +293,7 @@ HTTP2.0相比HTTP1.1支持的特性: TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921112213523.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210921112213523.png) TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。 @@ -302,7 +302,7 @@ TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最 防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/拥塞控制.jpg) +![](https://gitee.com/tysondai/img/raw/master/拥塞控制.jpg) ### 慢开始 From 415bd82b7b98c8e75e60a4f70c32d4a081a84493 Mon Sep 17 00:00:00 2001 From: tyson Date: Wed, 18 May 2022 21:20:58 +0800 Subject: [PATCH 03/84] update img url --- Java/JVM.md | 32 +++++++------- ...21\351\235\242\350\257\225\351\242\230.md" | 14 +++--- "Java/Java\345\237\272\347\241\200.md" | 10 ++--- ...00\351\235\242\350\257\225\351\242\230.md" | 8 ++-- ...21\351\235\242\350\257\225\351\242\230.md" | 12 ++--- ...10\351\235\242\350\257\225\351\242\230.md" | 8 ++-- "Java/\345\271\266\345\217\221.md" | 22 +++++----- "Java/\351\233\206\345\220\210.md" | 8 ++-- .../RabbitMQ.md" | 10 ++--- ...07\345\215\227\346\200\273\347\273\223.md" | 16 +++---- ...is\351\235\242\350\257\225\351\242\230.md" | 10 ++--- .../GitHub\346\214\207\345\215\227.md" | 18 ++++---- "\345\267\245\345\205\267/progit2.md" | 10 ++--- ...47\350\241\214\350\256\241\345\210\222.md" | 44 +++++++++---------- .../MySQL\350\277\233\351\230\266.md" | 24 +++++----- ...21\351\235\242\350\257\225\351\242\230.md" | 24 +++++----- ...43\347\240\201\345\256\236\347\216\260.md" | 2 +- ...25\351\242\230\346\200\273\347\273\223.md" | 2 +- ...ng\351\235\242\350\257\225\351\242\230.md" | 2 +- .../\347\275\221\347\273\234.md" | 2 +- ...21\351\235\242\350\257\225\351\242\230.md" | 34 +++++++------- 21 files changed, 156 insertions(+), 156 deletions(-) diff --git a/Java/JVM.md b/Java/JVM.md index 74430f8..05f5634 100644 --- a/Java/JVM.md +++ b/Java/JVM.md @@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。 JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 -![image-20210905150636105](https://gitee.com/tysondai/img/raw/master/image-20210905150636105.png) +![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png) > 图片来源:深入理解Java虚拟机-周志明 @@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -![](https://gitee.com/tysondai/img/raw/master/string-new.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png) -![](https://gitee.com/tysondai/img/raw/master/string-intern.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png) -![](https://gitee.com/tysondai/img/raw/master/string-equal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png) > 图片来源:https://blog.csdn.net/soonfly @@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对 - 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 -![](https://gitee.com/tysondai/img/raw/master/object-handle.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png) - 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 -![](https://gitee.com/tysondai/img/raw/master/direct-pointer.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png) @@ -245,7 +245,7 @@ ClassFile { 加载、验证、准备、解析、初始化、使用和卸载。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905002423703.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png) ## 类加载的过程 @@ -281,7 +281,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905002827546.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png) 双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 @@ -339,7 +339,7 @@ public abstract class ClassLoader { 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 -![](https://gitee.com/tysondai/img/raw/master/object-dead.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png) ### 引用计数法 @@ -365,7 +365,7 @@ public class ReferenceCountingGc { 通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://gitee.com/tysondai/img/raw/master/gc-root-refer.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png) #### 可作为GC Roots的对象 @@ -469,13 +469,13 @@ public class ReferenceCountingGc { 标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905003458130.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png) ### 复制清除算法 半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905003714551.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png) 特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 @@ -534,7 +534,7 @@ java -XX:+PrintCommandLineFlags -version 单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 -![](https://gitee.com/tysondai/img/raw/master/serial-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png) 特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 @@ -542,7 +542,7 @@ java -XX:+PrintCommandLineFlags -version Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 -![](https://gitee.com/tysondai/img/raw/master/parnew-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png) 除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 @@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时 - 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 - 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 -![](https://gitee.com/tysondai/img/raw/master/cms-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png) 由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 @@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应 G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 -![](https://gitee.com/tysondai/img/raw/master/g1-region.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg) G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 7ccae91..e4bddb5 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -49,7 +49,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 -![](https://gitee.com/tysondai/img/raw/master/jvm内存结构0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png) ### 程序计数器 @@ -185,7 +185,7 @@ ClassFile { 类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。 -![](https://gitee.com/tysondai/img/raw/master/类加载.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png) **加载** @@ -213,7 +213,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://gitee.com/tysondai/img/raw/master/双亲委派.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png) 双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下: @@ -312,7 +312,7 @@ public class ReferenceCount { 通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://gitee.com/tysondai/img/raw/master/可达性分析0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png) ## 可作为GC Roots的对象有哪些? @@ -413,7 +413,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**。 -![](https://gitee.com/tysondai/img/raw/master/标记清除.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png) **复制清除算法** @@ -425,7 +425,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 -![](https://gitee.com/tysondai/img/raw/master/标记整理.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png) **分类收集算法** @@ -508,7 +508,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低 G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。 -![](https://gitee.com/tysondai/img/raw/master/g1分区.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png) G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。 diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" index 0f3e5c8..72cff97 100644 --- "a/Java/Java\345\237\272\347\241\200.md" +++ "b/Java/Java\345\237\272\347\241\200.md" @@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接 Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 -![field-method](https://gitee.com/tysondai/img/raw/master/field-method.png) +![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png) ## Method类 @@ -1101,7 +1101,7 @@ public class GenericMethod { Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: -![exception](https://gitee.com/tysondai/img/raw/master/exception.png) +![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png) - Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 @@ -1198,7 +1198,7 @@ public class ExceptionTest { Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 -![io](https://gitee.com/tysondai/img/raw/master/io.jpg) +![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg) > 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) @@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 -![bio](https://gitee.com/tysondai/img/raw/master/bio.png) +![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png) ## NIO NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 -![nio](https://gitee.com/tysondai/img/raw/master/nio.png) +![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png) NIO与IO区别: diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 095093c..758e026 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -101,7 +101,7 @@ **JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -![](https://gitee.com/tysondai/img/raw/master/20220402230447.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) 所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 @@ -111,7 +111,7 @@ 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 -![](https://gitee.com/tysondai/img/raw/master/20220401234008.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 @@ -141,7 +141,7 @@ JRE = JVM + Java 核心类库 JDK = JRE + Java工具 + 编译器 + 调试器 -![](https://gitee.com/tysondai/img/raw/master/20220402230613.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) ## 面向对象有哪些特性? @@ -1030,7 +1030,7 @@ unchecked Exception: 不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。 -![](https://gitee.com/tysondai/img/raw/master/20220423154450.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423154450.png) diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index cfcb15d..a65d22c 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -64,7 +64,7 @@ ### 线程池执行原理? -![线程池执行流程](https://gitee.com/tysondai/img/raw/master/线程池执行流程.png) +![线程池执行流程](https://raw.githubusercontent.com/Tyson0314/img/master/线程池执行流程.png) 1. 当线程池里存活的线程数小于核心线程数`corePoolSize`时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数`corePoolSize`时,线程池里面的线程会一直存活着,就算空闲时间超过了`keepAliveTime`,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。 2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。 @@ -199,7 +199,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -225,7 +225,7 @@ public static ExecutorService newCachedThreadPool() { **终止(TERMINATED)**:表示该线程已经执行完毕。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -401,7 +401,7 @@ class RunnableDemo implements Runnable { 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://gitee.com/tysondai/img/raw/master/死锁.png) +![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -686,7 +686,7 @@ class SeasonThreadTask implements Runnable{ 每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。 -![](https://gitee.com/tysondai/img/raw/master/threadlocal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/threadlocal.png) 调用`threadLocal.set()`-->调用`getMap(Thread)`-->返回当前线程的`ThreadLocalMap`-->`map.set(this, value)`,this是`threadLocal`本身。源码如下: @@ -783,7 +783,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节点中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://gitee.com/tysondai/img/raw/master/aqs.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/aqs.png) ## ReentrantLock 是如何实现可重入性的? diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index 4a011e4..14acae6 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -54,9 +54,9 @@ Java集合类主要由两个接口**Collection**和**Map**派生出来的,Coll Java集合框架图如下: -![](https://gitee.com/tysondai/img/raw/master/collections2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/collections2.png) -![](https://gitee.com/tysondai/img/raw/master/map.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/map.png) List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合。Map代表的是存储key-value对的集合,可根据元素的key来访问value。 @@ -197,7 +197,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) +![图片来源网络](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) ### 红黑树的特点? @@ -271,7 +271,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" index c9734f5..1f35396 100644 --- "a/Java/\345\271\266\345\217\221.md" +++ "b/Java/\345\271\266\345\217\221.md" @@ -87,7 +87,7 @@ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveT 创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 -![](https://gitee.com/tysondai/img/raw/master/thread-pool.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/thread-pool.png) ThreadPoolExecutor 的通用构造函数: @@ -326,7 +326,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -340,7 +340,7 @@ FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VAL CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 -![](https://gitee.com/tysondai/img/raw/master/executors-ali.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/executors-ali.png) 正确示例(阿里巴巴编码规范): @@ -369,7 +369,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909233258929.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909233258929.png) 本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 @@ -392,7 +392,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 终止(TERMINATED):表示该线程已经执行完毕。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -680,7 +680,7 @@ public class SynchronizedDemo { Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 -![](https://gitee.com/tysondai/img/raw/master/synchronized-block.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-block.png) **方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 @@ -692,7 +692,7 @@ public class SynchronizedMethod { } ``` -![](https://gitee.com/tysondai/img/raw/master/synchronized-method.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-method.png) #### 锁的状态 @@ -1077,7 +1077,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://gitee.com/tysondai/img/raw/master/image-20210910000456607.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210910000456607.png) @@ -1112,19 +1112,19 @@ public void conditionSignal() throws InterruptedException { 每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 -![](https://gitee.com/tysondai/img/raw/master/condition-await.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-await.png) > 图片来源:Java并发编程的艺术 在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 -![](https://gitee.com/tysondai/img/raw/master/condition-wait-queue.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-wait-queue.png) > 图片来源:Java并发编程的艺术 线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 -![](https://gitee.com/tysondai/img/raw/master/condition-signal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-signal.png) > 图片来源:Java并发编程的艺术 diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" index c7283d5..83fecae 100644 --- "a/Java/\351\233\206\345\220\210.md" +++ "b/Java/\351\233\206\345\220\210.md" @@ -51,7 +51,7 @@ 以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 -![](https://gitee.com/tysondai/img/raw/master/Java-Collections.jpeg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/Java-Collections.jpeg) ### HashMap @@ -88,7 +88,7 @@ put方法流程: 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) > 参考链接: > @@ -121,7 +121,7 @@ HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初 LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 -![linkedhashmap](https://gitee.com/tysondai/img/raw/master/linkedhashmap.png) +![linkedhashmap](https://raw.githubusercontent.com/Tyson0314/img/master/linkedhashmap.png) ### TreeMap @@ -136,7 +136,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" index 2042d70..e5ba58b 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" @@ -39,13 +39,13 @@ 文章目录: -![](https://gitee.com/tysondai/img/raw/master/image-20210914234334988.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914234334988.png) # 简介 RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq.png) ## 基本概念 @@ -94,19 +94,19 @@ Exchange规则。 direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-direct.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-direct.png) ## fanout 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-fanout.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-fanout.png) ## topic topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-topic.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-topic.png) ## headers diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index f329ea8..8d4e0d7 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -71,7 +71,7 @@ 目录结构如下: -![](https://gitee.com/tysondai/img/raw/master/image-20210914000822843.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914000822843.png) ## 简介 @@ -503,7 +503,7 @@ ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的 - 最底层的链表包含所有的元素 - 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) -![](https://gitee.com/tysondai/img/raw/master/redis-skiplist.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-skiplist.png) #### 对象 @@ -545,7 +545,7 @@ hash类型内部编码有两种: Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 -![](https://gitee.com/tysondai/img/raw/master/list-api.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/list-api.png) 使用场景: @@ -630,7 +630,7 @@ GET #返回文章ID。 3. EXEC命令进行提交事务 -![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) DISCARD:放弃事务,即该事务内的所有命令都将取消 @@ -653,7 +653,7 @@ QUEUED 事务里的命令执行时会读取最新的值: -![](https://gitee.com/tysondai/img/raw/master/redis-transaction.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-transaction.png) ### WATCH命令 @@ -800,7 +800,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 -![](https://gitee.com/tysondai/img/raw/master/redis-replication.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-replication.png) Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 @@ -932,7 +932,7 @@ redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 使用evalsha执行Lua脚本过程如下: -![](https://gitee.com/tysondai/img/raw/master/evalsha.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/evalsha.png) ### lua脚本作用 @@ -1075,7 +1075,7 @@ public void write(String key,Object data){ 解决方法: -![](https://gitee.com/tysondai/img/raw/master/image-20210913235221410.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210913235221410.png) > 图片来源:https://tech.it168.com diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index 8a0e0d6..d5704d2 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -153,7 +153,7 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. EXEC命令进行提交事务 -![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) 一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: @@ -224,7 +224,7 @@ Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF` `bgsave`是主流的触发 RDB 持久化的方式,执行过程如下: -![](https://gitee.com/tysondai/img/raw/master/rdb持久化过程.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rdb持久化过程.png) - 执行`BGSAVE`命令 - Redis 父进程判断当前**是否存在正在执行的子进程**,如果存在,`BGSAVE`命令直接返回。 @@ -269,7 +269,7 @@ appendfsync no //由操作系统决定何时进行同步操作 接下来看一下 AOF 持久化执行流程: -![](https://gitee.com/tysondai/img/raw/master/aof工作流程0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/aof工作流程0.png) 1. 所有的写入命令会追加到 AOP 缓冲区中。 2. AOF 缓冲区根据对应的策略向硬盘同步。 @@ -334,7 +334,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 客户端连接Redis的时候,先连接哨兵,哨兵会告诉客户端Redis主节点的地址,然后客户端连接上Redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 -![](https://gitee.com/tysondai/img/raw/master/sentinel.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/sentinel.png) **工作原理** @@ -353,7 +353,7 @@ Redis cluster集群节点最小配置6个节点以上(3主3从),其中主 Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。 -![](https://gitee.com/tysondai/img/raw/master/cluster_slots.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) **哈希槽是如何映射到 Redis 实例上的?** diff --git "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" index cca4277..a125d4b 100644 --- "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" +++ "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" @@ -22,15 +22,15 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 创建一个新的仓库,用来存放项目。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210822154700616.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822154700616.png) - 或者你在GitHub上看到别人有一个超级无敌有趣的项目,可以直接fork过来,可以理解成复制过来,变成你自己的。之后你想怎么改就怎么改! - ![image-20210822155107839](https://gitee.com/tysondai/img/raw/master/image-20210822155107839.png) + ![image-20210822155107839](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155107839.png) - 然后你可以通过Git命令行`git clone xxx`把项目clone到本地,在本地进行创作。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210822155359118.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155359118.png) - 最后,在本地创作完成,可以使用`git commit -m xxx`提交到本地库,然后使用`git push`把修改推送到GitHub仓库。之后就可以在GitHub上面看到你修改的内容啦~ @@ -42,23 +42,23 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 评价GitHub项目的两个重要的参数:star和fork。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161003170.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161003170.png) 比较优秀和热门的项目,star数目和fork数目都会比较多。我们可以根据这两个参数筛选出比较好的项目。使用`关键字 stars:>=xxx forks:>=xxx` 可以筛选出star和fork数目大于xxx的相关项目。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161122586.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161122586.png) - 使用 `awesome 关键字`,可以筛选出比较高质量的学习、书籍、工具类或者插件类的集合。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161608599.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161608599.png) - 在特定位置搜索关键词。有些关键词出现在项目的不同位置,比如项目名称、项目描述和README等。使用`关键词 in name/description/Readme`,可以搜索到相关的内容。比如使用`spring in name`,可以搜索到在项目名中包含spring的项目。 -![image-20210822162144086](https://gitee.com/tysondai/img/raw/master/image-20210822162144086.png) +![image-20210822162144086](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822162144086.png) - 指定条件搜索关键词。如`tool language:java`搜索到的是包含关键字tool的Java项目,`tool followers:>1000`可以搜索到包含关键字tool,且follower数量大于1000的项目。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822163111390.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822163111390.png) @@ -72,7 +72,7 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 文档神器。可以为自己的项目建立wiki,可以用markdown语法写wiki; -![](https://gitee.com/tysondai/img/raw/master/image-20210822172419760.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822172419760.png) - 使用GitHub pages建立个人静态网站,搞一个有自己域名的独立博客,想想都觉得开心。使用GitHub pages的好处是搭建简单而且免费,支持静态脚本,并且可以绑定自己的域名。具体可以参考:[GitHub Pages 建立个人网站详细教程 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/58229299) diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/progit2.md" index 6dde18b..68b8c2b 100644 --- "a/\345\267\245\345\205\267/progit2.md" +++ "b/\345\267\245\345\205\267/progit2.md" @@ -85,7 +85,7 @@ Git工作流程如下: Git 的工作流程图如下: -![](https://gitee.com/tysondai/img/raw/master/git-work-flow.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git-work-flow.png) > 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 @@ -103,11 +103,11 @@ Git 的三种状态:已修改(modified)、已暂存(staged)和已提 基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 -![](https://gitee.com/tysondai/img/raw/master/git工作流程.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git工作流程.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` -![](https://gitee.com/tysondai/img/raw/master/git-status.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git-status.png) ## 配置 @@ -156,7 +156,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](https://gitee.com/tysondai/img/raw/master/git生命周期.png) +![git生命周期](https://raw.githubusercontent.com/Tyson0314/img/master/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -262,7 +262,7 @@ git commit -m "add readme.md" 单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: -![](https://gitee.com/tysondai/img/raw/master/image-20210830225020753.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210830225020753.png) 此时应该这么操作: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" index 2378225..e9f255a 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" @@ -91,7 +91,7 @@ where blog_id = ( 三个表依次嵌套,发现最里层的子查询 `id`最大,最先执行。 -![](https://gitee.com/tysondai/img/raw/master/explain-id.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-id.png) ## select_type @@ -107,13 +107,13 @@ where blog_id = ( 查询的表名,并不一定是真实存在的表,有别名显示别名,也可能为临时表。当from子句中有子查询时,table列是 ``的格式,表示当前查询依赖 id为N的查询,会先执行 id为N的查询。 -![](https://gitee.com/tysondai/img/raw/master/image-20210804083523885.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804083523885.png) ## partitions 查询时匹配到的分区信息,对于非分区表值为`NULL`,当查询的是分区表时,`partitions`显示分区表命中的分区情况。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802022931773.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802022931773.png) ## type @@ -123,25 +123,25 @@ where blog_id = ( 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快。比如,Mysql系统表proxies_priv在Mysql服务启动时候已经加载在内存中,对这个表进行查询不需要进行磁盘 IO。 -![](https://gitee.com/tysondai/img/raw/master/image-20210801233419732.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801233419732.png) ### const 单表操作的时候,查询使用了主键或者唯一索引。 -![](https://gitee.com/tysondai/img/raw/master/explain-const.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-const.png) ### eq_ref **多表关联**查询的时候,主键和唯一索引作为关联条件。如下图的sql,对于user表(外循环)的每一行,user_role表(内循环)只有一行满足join条件,只要查找到这行记录,就会跳出内循环,继续外循环的下一轮查询。 -![](https://gitee.com/tysondai/img/raw/master/image-20210801232638027.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801232638027.png) ### ref 查找条件列使用了索引而且不为主键和唯一索引。虽然使用了索引,但该索引列的值并不唯一,这样即使使用索引查找到了第一条数据,仍然不能停止,要在目标值附近进行小范围扫描。但它的好处是不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内做扫描。 -![](https://gitee.com/tysondai/img/raw/master/explain-ref.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-ref.png) ### ref_or_null @@ -151,13 +151,13 @@ where blog_id = ( 使用了索引合并优化方法,查询使用了两个以上的索引。新建comment表,id为主键,value_id为非唯一索引,执行`explain select content from comment where value_id = 1181000 and id > 1000;`,执行结果显示查询同时使用了id和value_id索引,type列的值为index_merge。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802001215614.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802001215614.png) ### range 有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。像between、and、'>'、'<'、in和or都是范围索引扫描。 -![](https://gitee.com/tysondai/img/raw/master/explain-range.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-range.png) ### index @@ -165,17 +165,17 @@ index包括select索引列,order by主键两种情况。 1. order by主键。这种情况会按照索引顺序全表扫描数据,拿到的数据是按照主键排好序的,不需要额外进行排序。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210801225045980.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225045980.png) 2. select索引列。type为index,而且extra字段为using index,也称这种情况为索引覆盖。所需要取的数据都在索引列,无需回表查询。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210801225942948.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225942948.png) ### all 全表扫描,查询没有用到索引,性能最差。 -![](https://gitee.com/tysondai/img/raw/master/explain-all.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-all.png) ## possible_keys @@ -249,13 +249,13 @@ CREATE TABLE `t_orderdetail` ( 查询的列未被索引覆盖,where筛选条件非索引的前导列。对存储引擎返回的结果进行过滤(Post-filter,后过滤),一般发生在MySQL服务器,而不是存储引擎层。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802232729417.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232729417.png) ### using index 查询的列被索引覆盖,并且where筛选条件符合最左前缀原则,通过**索引查找**就能直接找到符合条件的数据,不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802232357282.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232357282.png) ### Using where&Using index @@ -265,17 +265,17 @@ CREATE TABLE `t_orderdetail` ( - where筛选条件不符合最左前缀原则 - ![](https://gitee.com/tysondai/img/raw/master/image-20210802233120283.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233120283.png) - where筛选条件是索引列前导列的一个范围 - ![](https://gitee.com/tysondai/img/raw/master/image-20210802233455880.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233455880.png) ### null 查询的列未被索引覆盖,并且where筛选条件是索引的前导列,也就是用到了索引,但是部分字段未被索引覆盖,必须回表查询这些字段,Extra中为NULL。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802234122321.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802234122321.png) ### using index condition @@ -283,11 +283,11 @@ CREATE TABLE `t_orderdetail` ( 不使用ICP的情况(`set optimizer_switch='index_condition_pushdown=off'`),如下图,在步骤4中,没有使用where条件过滤索引: -![](https://gitee.com/tysondai/img/raw/master/no-icp.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/no-icp.png) 使用ICP的情况(`set optimizer_switch='index_condition_pushdown=on'`): -![](https://gitee.com/tysondai/img/raw/master/icp.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/icp.png) 下面的例子使用了ICP: @@ -296,11 +296,11 @@ explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G; ``` -![](https://gitee.com/tysondai/img/raw/master/image-20210803084617433.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084617433.png) 关掉ICP之后(`set optimizer_switch='index_condition_pushdown=off'`),可以看到extra列为using where,不会使用索引下推。 -![](https://gitee.com/tysondai/img/raw/master/image-20210803084815503.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084815503.png) ### using temporary @@ -314,7 +314,7 @@ from t_order where user_id > 1 and user_id < 5\G; - select 查询字段不全是索引字段 - select 查询字段都是索引字段,但是 order by 字段和索引字段的顺序不一致 -![](https://gitee.com/tysondai/img/raw/master/image-20210804084029239.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804084029239.png) ### using join buffer diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" index 4ff8a64..7caa4e5 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" @@ -138,7 +138,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。 -![](https://gitee.com/tysondai/img/raw/master/image-20210821165019147.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821165019147.png) 进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的数据项。 @@ -170,15 +170,15 @@ Index_comment: 如下图,col1 是主键,col2和col3是普通字段。 -![](https://gitee.com/tysondai/img/raw/master/image-20200520234137916.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234137916.png) 下图是主键索引对应的 B+树结构,每个节点对应磁盘的一页。 -![](https://gitee.com/tysondai/img/raw/master/image-20200520234200868.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234200868.png) 对col3 建立一个单列索引,对应的B+树结构: -![](https://gitee.com/tysondai/img/raw/master/image-20200520234231001.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234231001.png) ### 索引分类 1. 主键索引:名为primary的唯一非空索引,不允许有空值。 @@ -208,7 +208,7 @@ Index_comment: 对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会对b进行比较排序)。直接执行`b = 2`这种查询条件没有办法利用索引。 -![最左匹配](https://gitee.com/tysondai/img/raw/master/image-20210821103313578.png) +![最左匹配](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821103313578.png) 从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行`a = 1 and b = 2`是a,b字段能用到索引的。而你执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。 @@ -218,7 +218,7 @@ InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的 聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。 -![](https://gitee.com/tysondai/img/raw/master/mysql-clustered-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-clustered-index.png) 对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。 @@ -244,7 +244,7 @@ explain select user_id from user_like where blog_id = 1; Extra中为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/cover-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) ### 索引失效 @@ -322,7 +322,7 @@ MEMORY引擎默认使用哈希索引,将键的哈希值和指向数据行的 myisam引擎主键索引和其他索引区别不大,叶子节点都包含索引值和行指针。 innodb引擎二级索引叶子存储的是索引值和主键值(不是行指针),这样可以减少行移动和数据页分裂时二级索引的维护工作。 - ![myisam-innodb-index](https://gitee.com/tysondai/img/raw/master/myisam-innodb-index.png) + ![myisam-innodb-index](https://raw.githubusercontent.com/Tyson0314/img/master/myisam-innodb-index.png) @@ -351,7 +351,7 @@ mvcc实现依赖于版本链,版本链是通过表的三个隐藏字段实现 3. 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链; 4. 记录redo log; -![](https://gitee.com/tysondai/img/raw/master/mvcc-impl.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc-impl.png) ### read view @@ -388,14 +388,14 @@ repeatable read:在一个事务范围内,第一次select时更新这个read_ 事务a和事务b同时开启事务,事务a插入数据然后提交,事务b执行全表的update,然后执行查询,查到了事务A中添加的数据。 -![](https://gitee.com/tysondai/img/raw/master/幻读1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) MySQL如何实现避免幻读: - 在快照读情况下,MySQL通过mvcc来避免幻读。 - 在当前读情况下,MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的)。 -![](https://gitee.com/tysondai/img/raw/master/current-read.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/current-read.png) next-key包括两部分:行锁和间隙锁。行锁是加在索引上的锁,间隙锁是加在索引之间的。 @@ -531,7 +531,7 @@ MySQL主要分为 Server 层和存储引擎层: - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 - **存储引擎**: 主要负责数据的存储和读取。server 层通过api与存储引擎进行通信。 -![MySQL-archpng](https://gitee.com/tysondai/img/raw/master/mysql-archpng.png) +![MySQL-archpng](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-archpng.png) ### Server 层基本组件 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 61ed2f8..2a8d716 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -179,7 +179,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 `key` 从左到右递增排列,如果某个指针的左右相邻 `key` 分别是 keyi 和 keyi+1,则该指针指向节点的所有 `key` 大于等于 keyi 且小于等于 keyi+1。 -![](https://gitee.com/tysondai/img/raw/master/B+树索引0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/B+树索引0.png) 进行查找操作时,首先在根节点进行二分查找,找到`key`所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出`key`所对应的数据项。 @@ -249,7 +249,7 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 如下图,对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会根据b进行排序)。直接执行`b = 2`这种查询条件无法使用索引。 -![最左前缀](https://gitee.com/tysondai/img/raw/master/最左前缀.png) +![最左前缀](https://raw.githubusercontent.com/Tyson0314/img/master/最左前缀.png) 当a的值确定的时候,b是有序的。例如`a = 1`时,b值为1,2是有序的状态。当`a = 2`时候,b的值为1,4也是有序状态。 当执行`a = 1 and b = 2`时a和b字段能用到索引。而执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段无法使用索引。 @@ -283,7 +283,7 @@ explain select user_id from user_like where blog_id = 1; `explain`结果的`Extra`列为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/cover-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) ### 索引的设计原则? @@ -393,7 +393,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 每条表记录大概是这样的: -![](https://gitee.com/tysondai/img/raw/master/mvcc9.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc9.png) 使用事务更新行记录的时候,就会生成版本链,执行过程如下: @@ -405,15 +405,15 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、初始数据如下,其中`DB_ROW_ID`和`DB_ROLL_PTR`为空。 -![](https://gitee.com/tysondai/img/raw/master/mvcc2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc2.png) 2、事务A对该行数据做了修改,将`age`修改为12,效果如下: -![](https://gitee.com/tysondai/img/raw/master/mvcc7.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc7.png) 3、之后事务B也对该行记录做了修改,将`age`修改为8,效果如下: -![](https://gitee.com/tysondai/img/raw/master/mvcc11.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc11.png) 4、此时undo log有两行记录,并且通过回滚指针连在一起。 @@ -433,7 +433,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 **前提**:`DATA_TRX_ID` 表示每个数据行的最新的事务ID;`up_limit_id`表示当前快照中的最先开始的事务;`low_limit_id`表示当前快照中的最慢开始的事务,即最后一个事务。 -![](https://gitee.com/tysondai/img/raw/master/read_view10.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/read_view10.png) - 如果`DATA_TRX_ID` < `up_limit_id`:说明在创建`read view`时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。 - 如果`DATA_TRX_ID` >= `low_limit_id`:说明当前版本的记录的事务是在创建`read view`之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。 @@ -458,7 +458,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、首先,user表只有两条记录,具体如下: -![](https://gitee.com/tysondai/img/raw/master/image-20210922232259664.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210922232259664.png) 2、事务a和事务b同时开启事务`start transaction`; @@ -476,7 +476,7 @@ update user set user_name = 'a'; 5、事务b然后执行查询,查到了事务a中插入的数据。(下图左边是事务b,右边是事务a。事务开始之前只有两条记录,事务a插入一条数据之后,事务b查询出来是三条数据) -![](https://gitee.com/tysondai/img/raw/master/幻读1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) 以上就是当前读出现的幻读现象。 @@ -565,7 +565,7 @@ MySQL主要分为 Server 层和存储引擎层: 垂直划分数据库是根据业务进行划分,例如购物场景,可以将库中涉及商品、订单、用户的表分别划分出成一个库,通过降低单库的大小来提高性能。同样的,分表的情况就是将一个大表根据业务功能拆分成一个个子表,例如商品基本信息和商品描述,商品基本信息一般会展示在商品列表,商品描述在商品详情页,可以将商品基本信息和商品描述拆分成两张表。 -![](https://gitee.com/tysondai/img/raw/master/垂直划分.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/垂直划分.png) **优点**:行记录变小,数据页可以存放更多记录,在查询时减少I/O次数。 @@ -579,7 +579,7 @@ MySQL主要分为 Server 层和存储引擎层: 水平划分是根据一定规则,例如时间或id序列值等进行数据的拆分。比如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,从而提升性能。 -![](https://gitee.com/tysondai/img/raw/master/水平划分.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/水平划分.png) **优点**:单库(表)的数据量得以减少,提高性能;切分出的表结构相同,程序改动较少。 diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" index 9a99fb1..9ad4fb0 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -13,7 +13,7 @@ 常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 -![](https://gitee.com/tysondai/img/raw/master/排序算法.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) ## 冒泡排序 diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index dd8b7fb..e9ddb23 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -28,7 +28,7 @@ SpringBoot实现自动配置原理图解: > 公众号【程序员大彬】,回复【自动配置】下载高清图片 -![](https://gitee.com/tysondai/img/raw/master/SpringBoot的自动配置原理.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index ae4a031..641525e 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -216,7 +216,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](https://gitee.com/tysondai/img/raw/master/bean生命周期.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/bean生命周期.png) 1.调用bean的构造方法创建Bean diff --git "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" index 0320b99..60a94c1 100644 --- "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" +++ "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" @@ -333,7 +333,7 @@ HTTP长连接,指的是复用TCP连接。多个HTTP请求可以复用同一个 CDN用户访问流程: -![cdn](https://gitee.com/tysondai/img/raw/master/cdn.png) +![cdn](https://raw.githubusercontent.com/Tyson0314/img/master/cdn.png) 1.用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有dns缓存,则向网站的DNS服务器请求; diff --git "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 2fb8b79..48969f2 100644 --- "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -38,7 +38,7 @@ 计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 -![](https://gitee.com/tysondai/img/raw/master/tcp5layer2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/tcp5layer2.png) 五层模型:应用层、传输层、网络层、数据链路层、物理层。 @@ -52,7 +52,7 @@ 假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是`CLOSED`。 -![](https://gitee.com/tysondai/img/raw/master/三次握手图解.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/三次握手图解.png) 1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位`SYN=1`,序列号`seq=x`。第一次握手前客户端的状态为`CLOSE`,第一次握手后客户端的状态为`SYN-SENT`。此时服务端的状态为`LISTEN`。 2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位`SYN=1`,`ACK=1`,序列号`seq=y`,确认号`ack=x+1`。第二次握手前服务端的状态为`LISTEN`,第二次握手后服务端的状态为`SYN-RCVD`,此时客户端的状态为`SYN-SENT`。(其中`SYN=1`表示要和客户端建立一个连接,`ACK=1`表示确认序号有效) @@ -69,7 +69,7 @@ ## 四次挥手 -![](https://gitee.com/tysondai/img/raw/master/四次挥手0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/四次挥手0.png) 1. A的应用进程先向其TCP发出连接释放报文段(`FIN=1,seq=u`),并停止再发送数据,主动关闭TCP连接,进入`FIN-WAIT-1`(终止等待1)状态,等待B的确认。 2. B收到连接释放报文段后即发出确认报文段(`ACK=1,ack=u+1,seq=v`),B进入`CLOSE-WAIT`(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 @@ -152,7 +152,7 @@ Content-Length:112 ## HTTP状态码有哪些? -![](https://gitee.com/tysondai/img/raw/master/http-status-code.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/http-status-code.png) ## POST和GET的区别? @@ -194,7 +194,7 @@ HTTP2.0相比HTTP1.1支持的特性: 服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:**证书内容、证书签名算法和签名**,签名是为了验证身份。 -![](https://gitee.com/tysondai/img/raw/master/image-20211004111441594.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004111441594.png) 服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。 @@ -216,29 +216,29 @@ HTTP2.0相比HTTP1.1支持的特性: 1. **协商加密算法** 。在`Client Hello`里面客户端会告知服务端自己当前的一些信息,包括客户端要使用的TLS版本,支持的加密算法,要访问的域名,给服务端生成的一个随机数(Nonce)等。需要提前告知服务器想要访问的域名以便服务器发送相应的域名的证书过来。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921104210833.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921104210833.png) 2. 服务端响应`Server Hello`,告诉客户端服务端**选中的加密算法**。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921105450791.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105450791.png) 3. 接着服务端给客户端发来了2个证书。第二个证书是第一个证书的签发机构(CA)的证书。 - ![](https://gitee.com/tysondai/img/raw/master/image-20211004172007102.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004172007102.png) 4. 客户端使用证书的认证机构CA公开发布的RSA公钥**对该证书进行验证**,下图表明证书认证成功。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921105929268.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105929268.png) 5. 验证通过之后,浏览器和服务器通过**密钥交换算法**产生共享的**对称密钥**。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110025197.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110025197.png) - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110155075.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110155075.png) 6. 开始传输数据,使用同一个对称密钥来加解密。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110315068.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110315068.png) ## DNS 的解析过程? @@ -257,7 +257,7 @@ HTTP2.0相比HTTP1.1支持的特性: 4. 服务器**响应请求**,返回响应数据。 5. 浏览器**解析响应内容,进行渲染**,呈现给用户。 -![](https://gitee.com/tysondai/img/raw/master/输入url返回页面过程1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/输入url返回页面过程1.png) ## 什么是cookie和session? @@ -265,7 +265,7 @@ HTTP2.0相比HTTP1.1支持的特性: 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 **cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 -![](https://gitee.com/tysondai/img/raw/master/cookie.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cookie.png) **cookie工作流程**: @@ -274,7 +274,7 @@ HTTP2.0相比HTTP1.1支持的特性: 3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 **session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 -![](https://gitee.com/tysondai/img/raw/master/session.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/session.png) ## Cookie和Session的区别? @@ -293,7 +293,7 @@ HTTP2.0相比HTTP1.1支持的特性: TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据。 -![](https://gitee.com/tysondai/img/raw/master/image-20210921112213523.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921112213523.png) TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。 @@ -302,7 +302,7 @@ TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最 防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。 -![](https://gitee.com/tysondai/img/raw/master/拥塞控制.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/拥塞控制.jpg) ### 慢开始 From bc29969701ab5354886331a1c405cd0975e96be8 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 22 May 2022 16:57:41 +0800 Subject: [PATCH 04/84] update --- Java/JVM.md | 32 +- ...21\351\235\242\350\257\225\351\242\230.md" | 14 +- "Java/Java\345\237\272\347\241\200.md" | 10 +- ...00\351\235\242\350\257\225\351\242\230.md" | 8 +- ...21\351\235\242\350\257\225\351\242\230.md" | 12 +- ...10\351\235\242\350\257\225\351\242\230.md" | 8 +- "Java/\345\271\266\345\217\221.md" | 22 +- "Java/\351\233\206\345\220\210.md" | 8 +- README.md | 10 +- .../RabbitMQ.md" | 13 +- ...07\345\215\227\346\200\273\347\273\223.md" | 16 +- ...06\345\270\203\345\274\217\351\224\201.md" | 159 -- ...is\351\235\242\350\257\225\351\242\230.md" | 10 +- .../elasticsearch.md" | 2438 ----------------- ...27\351\235\242\350\257\225\351\242\230.md" | 46 +- .../GitHub\346\214\207\345\215\227.md" | 18 +- "\345\267\245\345\205\267/progit2.md" | 10 +- ...47\350\241\214\350\256\241\345\210\222.md" | 44 +- .../MySQL\350\277\233\351\230\266.md" | 24 +- ...21\351\235\242\350\257\225\351\242\230.md" | 126 +- ...43\347\240\201\345\256\236\347\216\260.md" | 2 +- ...is\351\235\242\350\257\225\351\242\230.md" | 117 + ...25\351\242\230\346\200\273\347\273\223.md" | 2 +- ...15\345\212\241\345\256\236\346\210\230.md" | 10 + ...VC\351\235\242\350\257\225\351\242\230.md" | 88 + ...ng\351\235\242\350\257\225\351\242\230.md" | 2 +- .../\347\275\221\347\273\234.md" | 2 +- ...21\351\235\242\350\257\225\351\242\230.md" | 34 +- 28 files changed, 519 insertions(+), 2766 deletions(-) delete mode 100644 "\344\270\255\351\227\264\344\273\266/Redis\345\210\206\345\270\203\345\274\217\351\224\201.md" delete mode 100644 "\344\270\255\351\227\264\344\273\266/elasticsearch.md" create mode 100644 "\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" create mode 100644 "\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" diff --git a/Java/JVM.md b/Java/JVM.md index 05f5634..74430f8 100644 --- a/Java/JVM.md +++ b/Java/JVM.md @@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。 JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 -![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png) +![image-20210905150636105](https://gitee.com/tysondai/img/raw/master/image-20210905150636105.png) > 图片来源:深入理解Java虚拟机-周志明 @@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png) +![](https://gitee.com/tysondai/img/raw/master/string-new.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png) +![](https://gitee.com/tysondai/img/raw/master/string-intern.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png) +![](https://gitee.com/tysondai/img/raw/master/string-equal.png) > 图片来源:https://blog.csdn.net/soonfly @@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对 - 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png) +![](https://gitee.com/tysondai/img/raw/master/object-handle.png) - 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png) +![](https://gitee.com/tysondai/img/raw/master/direct-pointer.png) @@ -245,7 +245,7 @@ ClassFile { 加载、验证、准备、解析、初始化、使用和卸载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905002423703.png) ## 类加载的过程 @@ -281,7 +281,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905002827546.png) 双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 @@ -339,7 +339,7 @@ public abstract class ClassLoader { 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png) +![](https://gitee.com/tysondai/img/raw/master/object-dead.png) ### 引用计数法 @@ -365,7 +365,7 @@ public class ReferenceCountingGc { 通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png) +![](https://gitee.com/tysondai/img/raw/master/gc-root-refer.png) #### 可作为GC Roots的对象 @@ -469,13 +469,13 @@ public class ReferenceCountingGc { 标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905003458130.png) ### 复制清除算法 半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905003714551.png) 特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 @@ -534,7 +534,7 @@ java -XX:+PrintCommandLineFlags -version 单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png) +![](https://gitee.com/tysondai/img/raw/master/serial-collector.png) 特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 @@ -542,7 +542,7 @@ java -XX:+PrintCommandLineFlags -version Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png) +![](https://gitee.com/tysondai/img/raw/master/parnew-collector.png) 除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 @@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时 - 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 - 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png) +![](https://gitee.com/tysondai/img/raw/master/cms-collector.png) 由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 @@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应 G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg) +![](https://gitee.com/tysondai/img/raw/master/g1-region.jpg) G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index e4bddb5..7ccae91 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -49,7 +49,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png) +![](https://gitee.com/tysondai/img/raw/master/jvm内存结构0.png) ### 程序计数器 @@ -185,7 +185,7 @@ ClassFile { 类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png) +![](https://gitee.com/tysondai/img/raw/master/类加载.png) **加载** @@ -213,7 +213,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png) +![](https://gitee.com/tysondai/img/raw/master/双亲委派.png) 双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下: @@ -312,7 +312,7 @@ public class ReferenceCount { 通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png) +![](https://gitee.com/tysondai/img/raw/master/可达性分析0.png) ## 可作为GC Roots的对象有哪些? @@ -413,7 +413,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png) +![](https://gitee.com/tysondai/img/raw/master/标记清除.png) **复制清除算法** @@ -425,7 +425,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png) +![](https://gitee.com/tysondai/img/raw/master/标记整理.png) **分类收集算法** @@ -508,7 +508,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低 G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png) +![](https://gitee.com/tysondai/img/raw/master/g1分区.png) G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。 diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" index 72cff97..0f3e5c8 100644 --- "a/Java/Java\345\237\272\347\241\200.md" +++ "b/Java/Java\345\237\272\347\241\200.md" @@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接 Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 -![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png) +![field-method](https://gitee.com/tysondai/img/raw/master/field-method.png) ## Method类 @@ -1101,7 +1101,7 @@ public class GenericMethod { Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: -![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png) +![exception](https://gitee.com/tysondai/img/raw/master/exception.png) - Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 @@ -1198,7 +1198,7 @@ public class ExceptionTest { Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 -![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg) +![io](https://gitee.com/tysondai/img/raw/master/io.jpg) > 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) @@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 -![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png) +![bio](https://gitee.com/tysondai/img/raw/master/bio.png) ## NIO NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 -![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png) +![nio](https://gitee.com/tysondai/img/raw/master/nio.png) NIO与IO区别: diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 758e026..095093c 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -101,7 +101,7 @@ **JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) +![](https://gitee.com/tysondai/img/raw/master/20220402230447.png) 所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 @@ -111,7 +111,7 @@ 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) +![](https://gitee.com/tysondai/img/raw/master/20220401234008.png) JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 @@ -141,7 +141,7 @@ JRE = JVM + Java 核心类库 JDK = JRE + Java工具 + 编译器 + 调试器 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) +![](https://gitee.com/tysondai/img/raw/master/20220402230613.png) ## 面向对象有哪些特性? @@ -1030,7 +1030,7 @@ unchecked Exception: 不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423154450.png) +![](https://gitee.com/tysondai/img/raw/master/20220423154450.png) diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index a65d22c..cfcb15d 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -64,7 +64,7 @@ ### 线程池执行原理? -![线程池执行流程](https://raw.githubusercontent.com/Tyson0314/img/master/线程池执行流程.png) +![线程池执行流程](https://gitee.com/tysondai/img/raw/master/线程池执行流程.png) 1. 当线程池里存活的线程数小于核心线程数`corePoolSize`时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数`corePoolSize`时,线程池里面的线程会一直存活着,就算空闲时间超过了`keepAliveTime`,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。 2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。 @@ -199,7 +199,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -225,7 +225,7 @@ public static ExecutorService newCachedThreadPool() { **终止(TERMINATED)**:表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -401,7 +401,7 @@ class RunnableDemo implements Runnable { 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) +![死锁](https://gitee.com/tysondai/img/raw/master/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -686,7 +686,7 @@ class SeasonThreadTask implements Runnable{ 每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/threadlocal.png) +![](https://gitee.com/tysondai/img/raw/master/threadlocal.png) 调用`threadLocal.set()`-->调用`getMap(Thread)`-->返回当前线程的`ThreadLocalMap`-->`map.set(this, value)`,this是`threadLocal`本身。源码如下: @@ -783,7 +783,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节点中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/aqs.png) +![](https://gitee.com/tysondai/img/raw/master/aqs.png) ## ReentrantLock 是如何实现可重入性的? diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index 14acae6..4a011e4 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -54,9 +54,9 @@ Java集合类主要由两个接口**Collection**和**Map**派生出来的,Coll Java集合框架图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/collections2.png) +![](https://gitee.com/tysondai/img/raw/master/collections2.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/map.png) +![](https://gitee.com/tysondai/img/raw/master/map.png) List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合。Map代表的是存储key-value对的集合,可根据元素的key来访问value。 @@ -197,7 +197,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![图片来源网络](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) ### 红黑树的特点? @@ -271,7 +271,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" index 1f35396..c9734f5 100644 --- "a/Java/\345\271\266\345\217\221.md" +++ "b/Java/\345\271\266\345\217\221.md" @@ -87,7 +87,7 @@ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveT 创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/thread-pool.png) +![](https://gitee.com/tysondai/img/raw/master/thread-pool.png) ThreadPoolExecutor 的通用构造函数: @@ -326,7 +326,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -340,7 +340,7 @@ FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VAL CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/executors-ali.png) +![](https://gitee.com/tysondai/img/raw/master/executors-ali.png) 正确示例(阿里巴巴编码规范): @@ -369,7 +369,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909233258929.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909233258929.png) 本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 @@ -392,7 +392,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 终止(TERMINATED):表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -680,7 +680,7 @@ public class SynchronizedDemo { Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-block.png) +![](https://gitee.com/tysondai/img/raw/master/synchronized-block.png) **方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 @@ -692,7 +692,7 @@ public class SynchronizedMethod { } ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-method.png) +![](https://gitee.com/tysondai/img/raw/master/synchronized-method.png) #### 锁的状态 @@ -1077,7 +1077,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210910000456607.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210910000456607.png) @@ -1112,19 +1112,19 @@ public void conditionSignal() throws InterruptedException { 每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-await.png) +![](https://gitee.com/tysondai/img/raw/master/condition-await.png) > 图片来源:Java并发编程的艺术 在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-wait-queue.png) +![](https://gitee.com/tysondai/img/raw/master/condition-wait-queue.png) > 图片来源:Java并发编程的艺术 线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-signal.png) +![](https://gitee.com/tysondai/img/raw/master/condition-signal.png) > 图片来源:Java并发编程的艺术 diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" index 83fecae..c7283d5 100644 --- "a/Java/\351\233\206\345\220\210.md" +++ "b/Java/\351\233\206\345\220\210.md" @@ -51,7 +51,7 @@ 以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/Java-Collections.jpeg) +![](https://gitee.com/tysondai/img/raw/master/Java-Collections.jpeg) ### HashMap @@ -88,7 +88,7 @@ put方法流程: 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) > 参考链接: > @@ -121,7 +121,7 @@ HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初 LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 -![linkedhashmap](https://raw.githubusercontent.com/Tyson0314/img/master/linkedhashmap.png) +![linkedhashmap](https://gitee.com/tysondai/img/raw/master/linkedhashmap.png) ### TreeMap @@ -136,7 +136,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) **TreeMap的特点:** diff --git a/README.md b/README.md index c0d36c4..79ae7ad 100644 --- a/README.md +++ b/README.md @@ -109,11 +109,15 @@ ## Spring MVC -[Spring MVC知识点总结](框架/SpringMVC.md) +[Spring MVC入门知识点](框架/SpringMVC.md) + +[Spring MVC面试题总结](框架/SpringMVC面试题.md) ## Mybatis -[Mybatis知识点总结](框架/深入浅出Mybatis技术原理与实战.md) +[Mybatis入门知识点](框架/深入浅出Mybatis技术原理与实战.md) + +[Mybatis面试题总结](框架/Mybatis面试题.md) ## SpringCloud @@ -127,8 +131,8 @@ ## RabbitMQ -1. [RabbitMQ核心知识总结](中间件/RabbitMQ.md) (推荐 :+1:) 1. [消息队列面试题](中间件/消息队列面试题.md) +1. [RabbitMQ核心知识总结](中间件/RabbitMQ.md) (推荐 :+1:) 2. [死信队列](中间件/死信队列.md) # 计算机网络 diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" index e5ba58b..e57f2b1 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" @@ -39,13 +39,13 @@ 文章目录: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914234334988.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210914234334988.png) # 简介 RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq.png) ## 基本概念 @@ -94,26 +94,24 @@ Exchange规则。 direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-direct.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-direct.png) ## fanout 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-fanout.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-fanout.png) ## topic topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-topic.png) +![](https://gitee.com/tysondai/img/raw/master/rabbitmq-topic.png) ## headers headers交换机是根据发送的消息内容中的headers属性进行路由的。在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。 - - # 消息丢失 消息丢失场景:生产者生产消息到RabbitMQ Server消息丢失、RabbitMQ Server存储的消息丢失和RabbitMQ Server到消费者消息丢失。 @@ -432,4 +430,3 @@ msg.getMessageProperties().setExpiration("3000"); [线上rabbitmq问题](https://juejin.im/post/6844904088212094983#heading-0) - diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index 8d4e0d7..f329ea8 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -71,7 +71,7 @@ 目录结构如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914000822843.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210914000822843.png) ## 简介 @@ -503,7 +503,7 @@ ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的 - 最底层的链表包含所有的元素 - 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-skiplist.png) +![](https://gitee.com/tysondai/img/raw/master/redis-skiplist.png) #### 对象 @@ -545,7 +545,7 @@ hash类型内部编码有两种: Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/list-api.png) +![](https://gitee.com/tysondai/img/raw/master/list-api.png) 使用场景: @@ -630,7 +630,7 @@ GET #返回文章ID。 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) DISCARD:放弃事务,即该事务内的所有命令都将取消 @@ -653,7 +653,7 @@ QUEUED 事务里的命令执行时会读取最新的值: -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-transaction.png) +![](https://gitee.com/tysondai/img/raw/master/redis-transaction.png) ### WATCH命令 @@ -800,7 +800,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-replication.png) +![](https://gitee.com/tysondai/img/raw/master/redis-replication.png) Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 @@ -932,7 +932,7 @@ redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 使用evalsha执行Lua脚本过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/evalsha.png) +![](https://gitee.com/tysondai/img/raw/master/evalsha.png) ### lua脚本作用 @@ -1075,7 +1075,7 @@ public void write(String key,Object data){ 解决方法: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210913235221410.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210913235221410.png) > 图片来源:https://tech.it168.com diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\210\206\345\270\203\345\274\217\351\224\201.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\210\206\345\270\203\345\274\217\351\224\201.md" deleted file mode 100644 index d7536ac..0000000 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\210\206\345\270\203\345\274\217\351\224\201.md" +++ /dev/null @@ -1,159 +0,0 @@ - - - - -- [Redis分布式锁](#redis%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81) - - [Jedis实现分布式锁](#jedis%E5%AE%9E%E7%8E%B0%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81) - - [加锁](#%E5%8A%A0%E9%94%81) - - [解锁](#%E8%A7%A3%E9%94%81) - - - -在单机环境下,当存在多个线程可以同时改变某个变量(可变共享变量)时,就会出现线程安全问题。这个问题可以通过 JAVA 提供的 volatile、ReentrantLock、synchronized 以及 concurrent 并发包下一些线程安全的类等来避免。 - -而在多机部署环境,需要在多进程下保证线程的安全性,Java提供的这些API仅能保证在单个JVM进程内对多线程访问共享资源的线程安全,已经不满足需求了。这时候就需要使用分布式锁来保证线程安全。通过分布式锁,可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。 - -分布式锁需要满足四个条件: - -1. 互斥性。在任意时刻,只有一个客户端能持有锁。 -2. 不会死锁。即使有客户端在持有锁的期间崩溃而没有主动解锁,也要保证后续其他客户端能加锁。 -3. 加锁和解锁必须是同一个客户端。客户端a不能将客户端b的锁解开,即不能误解锁。 -4. 容错性。只要大多数Redis节点正常运行,客户端就能够获取和释放锁。 - -# Redis分布式锁 - -常见的实现分布式锁的方式有:数据库、Redis、Zookeeper。下面主要介绍使用Redis实现分布式锁。 - -Redis 2.6.12 之前的版本中采用 setnx + expire 方式实现分布式锁,在 Redis 2.6.12 版本后 setnx 增加了过期时间参数: - -```java -SET lockKey value NX PX expire-time -``` - -所以在Redis 2.6.12 版本后,只需要使用setnx就可以实现分布式锁了。 - -加锁逻辑: - -1. setnx争抢key的锁,如果已有key存在,则不作操作,过段时间继续重试,保证只有一个客户端能持有锁。 -2. value设置为 requestId(可以使用机器ip拼接当前线程名称),表示这把锁是哪个请求加的,在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 -3. 再用expire给锁加一个过期时间,防止异常导致锁没有释放。 - -解锁逻辑: - -首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。使用lua脚本实现原子操作,保证线程安全。 - -下面我们通过Jedis(基于java语言的redis客户端)来演示分布式锁的实现。 - -## Jedis实现分布式锁 - -引入Jedis jar包,在pom.xml文件增加代码: - -```xml - - redis.clients - jedis - 2.9.0 - -``` - -### 加锁 - -调用jedis的set()实现加锁,加锁代码如下: - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-01 17:13 - */ -public class RedisTest { - - private static final String LOCK_SUCCESS = "OK"; - private static final String SET_IF_NOT_EXIST = "NX"; - private static final String SET_EXPIRE_TIME = "PX"; - - @Autowired - private JedisPool jedisPool; - - public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { - Jedis jedis = jedisPool.getResource(); - String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_EXPIRE_TIME, expireTime); - - if (LOCK_SUCCESS.equals(result)) { - return true; - } - return false; - } -} -``` - -各参数说明: - -- lockKey:使用key来当锁,需要保证key是唯一的。可以使用系统号拼接自定义的key。 -- requestId:表示这把锁是哪个请求加的,可以使用机器ip拼接当前线程名称。在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 -- NX:意思是SET IF NOT EXIST,保证如果已有key存在,则不作操作,过段时间继续重试。NX参数保证只有一个客户端能持有锁。 -- PX:给key加一个过期的设置,具体时间由expireTime决定。 -- expireTime:设置key的过期时间,防止异常导致锁没有释放。 - -### 解锁 - -首先需要获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。这里使用lua脚本实现原子操作,保证线程安全。 - -使用eval命令执行Lua脚本的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。lua脚本如下: - -``` -//KEYS[1]是lockKey,ARGV[1]是requestId -String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; -Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); -``` - -Jedis的eval()方法源码如下: - -```java -public Object eval(String script, List keys, List args) { - return this.eval(script, keys.size(), getParams(keys, args)); -} -``` - -lua脚本的意思是:调用get获取锁(KEYS[1])对应的value值,检查是否与requestId(ARGV[1])相等,如果相等则调用del删除锁。否则返回0。 - -完整的解锁代码如下: - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-01 17:13 - */ -public class RedisTest { - private static final Long RELEASE_SUCCESS = 1L; - - @Autowired - private JedisPool jedisPool; - - public boolean releaseDistributedLock(String lockKey, String requestId) { - Jedis jedis = jedisPool.getResource(); - ////KEYS[1]是lockKey,ARGV[1]是requestId - String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; - Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); - - if (RELEASE_SUCCESS.equals(result)) { - return true; - } - return false; - } -} -``` - - - -以上是使用Redis实现分布式锁的全部内容,希望对你有帮助。 - -> 本文已经收录到github/gitee仓库,欢迎大家围观、star -> -> github仓库: https://github.com/Tyson0314/Java-learning -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee仓库:https://gitee.com/tysondai/Java-learning - diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index d5704d2..8a0e0d6 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -153,7 +153,7 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) 一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: @@ -224,7 +224,7 @@ Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF` `bgsave`是主流的触发 RDB 持久化的方式,执行过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/rdb持久化过程.png) +![](https://gitee.com/tysondai/img/raw/master/rdb持久化过程.png) - 执行`BGSAVE`命令 - Redis 父进程判断当前**是否存在正在执行的子进程**,如果存在,`BGSAVE`命令直接返回。 @@ -269,7 +269,7 @@ appendfsync no //由操作系统决定何时进行同步操作 接下来看一下 AOF 持久化执行流程: -![](https://raw.githubusercontent.com/Tyson0314/img/master/aof工作流程0.png) +![](https://gitee.com/tysondai/img/raw/master/aof工作流程0.png) 1. 所有的写入命令会追加到 AOP 缓冲区中。 2. AOF 缓冲区根据对应的策略向硬盘同步。 @@ -334,7 +334,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 客户端连接Redis的时候,先连接哨兵,哨兵会告诉客户端Redis主节点的地址,然后客户端连接上Redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/sentinel.png) +![](https://gitee.com/tysondai/img/raw/master/sentinel.png) **工作原理** @@ -353,7 +353,7 @@ Redis cluster集群节点最小配置6个节点以上(3主3从),其中主 Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) +![](https://gitee.com/tysondai/img/raw/master/cluster_slots.png) **哈希槽是如何映射到 Redis 实例上的?** diff --git "a/\344\270\255\351\227\264\344\273\266/elasticsearch.md" "b/\344\270\255\351\227\264\344\273\266/elasticsearch.md" deleted file mode 100644 index 7e2b094..0000000 --- "a/\344\270\255\351\227\264\344\273\266/elasticsearch.md" +++ /dev/null @@ -1,2438 +0,0 @@ - - - - -- [基础](#%E5%9F%BA%E7%A1%80) - - [概念](#%E6%A6%82%E5%BF%B5) - - [启动和关闭](#%E5%90%AF%E5%8A%A8%E5%92%8C%E5%85%B3%E9%97%AD) - - [配置文件](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) - - [PUT](#put) - - [GET](#get) - - [全文搜索](#%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2) - - [高亮搜索](#%E9%AB%98%E4%BA%AE%E6%90%9C%E7%B4%A2) - - [分析](#%E5%88%86%E6%9E%90) - - [分布式特性](#%E5%88%86%E5%B8%83%E5%BC%8F%E7%89%B9%E6%80%A7) -- [集群原理](#%E9%9B%86%E7%BE%A4%E5%8E%9F%E7%90%86) - - [术语](#%E6%9C%AF%E8%AF%AD) - - [节点](#%E8%8A%82%E7%82%B9) - - [分片](#%E5%88%86%E7%89%87) - - [集群健康](#%E9%9B%86%E7%BE%A4%E5%81%A5%E5%BA%B7) - - [索引](#%E7%B4%A2%E5%BC%95) - - [故障转移](#%E6%95%85%E9%9A%9C%E8%BD%AC%E7%A7%BB) - - [单机多节点](#%E5%8D%95%E6%9C%BA%E5%A4%9A%E8%8A%82%E7%82%B9) -- [数据输入与输出](#%E6%95%B0%E6%8D%AE%E8%BE%93%E5%85%A5%E4%B8%8E%E8%BE%93%E5%87%BA) - - [文档元数据](#%E6%96%87%E6%A1%A3%E5%85%83%E6%95%B0%E6%8D%AE) - - [创建新文档](#%E5%88%9B%E5%BB%BA%E6%96%B0%E6%96%87%E6%A1%A3) - - [取回文档](#%E5%8F%96%E5%9B%9E%E6%96%87%E6%A1%A3) - - [取回多个文档](#%E5%8F%96%E5%9B%9E%E5%A4%9A%E4%B8%AA%E6%96%87%E6%A1%A3) - - [删除文档](#%E5%88%A0%E9%99%A4%E6%96%87%E6%A1%A3) - - [检查文档是否存在](#%E6%A3%80%E6%9F%A5%E6%96%87%E6%A1%A3%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8) - - [更新文档](#%E6%9B%B4%E6%96%B0%E6%96%87%E6%A1%A3) - - [更新和冲突](#%E6%9B%B4%E6%96%B0%E5%92%8C%E5%86%B2%E7%AA%81) - - [批量操作](#%E6%89%B9%E9%87%8F%E6%93%8D%E4%BD%9C) -- [分布式文档存储](#%E5%88%86%E5%B8%83%E5%BC%8F%E6%96%87%E6%A1%A3%E5%AD%98%E5%82%A8) - - [路由文档到分片](#%E8%B7%AF%E7%94%B1%E6%96%87%E6%A1%A3%E5%88%B0%E5%88%86%E7%89%87) -- [映射和分析](#%E6%98%A0%E5%B0%84%E5%92%8C%E5%88%86%E6%9E%90) - - [核心简单域类型](#%E6%A0%B8%E5%BF%83%E7%AE%80%E5%8D%95%E5%9F%9F%E7%B1%BB%E5%9E%8B) - - [查看映射](#%E6%9F%A5%E7%9C%8B%E6%98%A0%E5%B0%84) - - [自定义映射器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%98%A0%E5%B0%84%E5%99%A8) - - [index](#index) - - [analyzer](#analyzer) - - [更新映射](#%E6%9B%B4%E6%96%B0%E6%98%A0%E5%B0%84) - - [测试映射](#%E6%B5%8B%E8%AF%95%E6%98%A0%E5%B0%84) - - [分析器](#%E5%88%86%E6%9E%90%E5%99%A8) - - [测试分析器](#%E6%B5%8B%E8%AF%95%E5%88%86%E6%9E%90%E5%99%A8) - - [复杂核心域类型](#%E5%A4%8D%E6%9D%82%E6%A0%B8%E5%BF%83%E5%9F%9F%E7%B1%BB%E5%9E%8B) - - [多值域](#%E5%A4%9A%E5%80%BC%E5%9F%9F) - - [内部对象](#%E5%86%85%E9%83%A8%E5%AF%B9%E8%B1%A1) -- [搜索](#%E6%90%9C%E7%B4%A2) - - [空搜索](#%E7%A9%BA%E6%90%9C%E7%B4%A2) - - [多索引多类型](#%E5%A4%9A%E7%B4%A2%E5%BC%95%E5%A4%9A%E7%B1%BB%E5%9E%8B) - - [轻量搜索](#%E8%BD%BB%E9%87%8F%E6%90%9C%E7%B4%A2) -- [请求体查询](#%E8%AF%B7%E6%B1%82%E4%BD%93%E6%9F%A5%E8%AF%A2) - - [空查询](#%E7%A9%BA%E6%9F%A5%E8%AF%A2) - - [提升权重](#%E6%8F%90%E5%8D%87%E6%9D%83%E9%87%8D) - - [explain](#explain) - - [查询和过滤器的区别](#%E6%9F%A5%E8%AF%A2%E5%92%8C%E8%BF%87%E6%BB%A4%E5%99%A8%E7%9A%84%E5%8C%BA%E5%88%AB) -- [排序与相关性](#%E6%8E%92%E5%BA%8F%E4%B8%8E%E7%9B%B8%E5%85%B3%E6%80%A7) - - [按照字段的值排序](#%E6%8C%89%E7%85%A7%E5%AD%97%E6%AE%B5%E7%9A%84%E5%80%BC%E6%8E%92%E5%BA%8F) - - [多级排序](#%E5%A4%9A%E7%BA%A7%E6%8E%92%E5%BA%8F) - - [多值字段的排序](#%E5%A4%9A%E5%80%BC%E5%AD%97%E6%AE%B5%E7%9A%84%E6%8E%92%E5%BA%8F) - - [字符串排序](#%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8E%92%E5%BA%8F) -- [索引管理](#%E7%B4%A2%E5%BC%95%E7%AE%A1%E7%90%86) - - [创建索引](#%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95) - - [删除索引](#%E5%88%A0%E9%99%A4%E7%B4%A2%E5%BC%95) - - [索引设置](#%E7%B4%A2%E5%BC%95%E8%AE%BE%E7%BD%AE) - - [配置分析器](#%E9%85%8D%E7%BD%AE%E5%88%86%E6%9E%90%E5%99%A8) - - [自定义分析器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%88%86%E6%9E%90%E5%99%A8) - - [类型和映射](#%E7%B1%BB%E5%9E%8B%E5%92%8C%E6%98%A0%E5%B0%84) - - [根对象](#%E6%A0%B9%E5%AF%B9%E8%B1%A1) -- [分片内部原理](#%E5%88%86%E7%89%87%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86) - - [倒排索引](#%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95) -- [深入搜索](#%E6%B7%B1%E5%85%A5%E6%90%9C%E7%B4%A2) - - [精确值查找](#%E7%B2%BE%E7%A1%AE%E5%80%BC%E6%9F%A5%E6%89%BE) - - [term 查询文本](#term-%E6%9F%A5%E8%AF%A2%E6%96%87%E6%9C%AC) - - [terms 查询](#terms-%E6%9F%A5%E8%AF%A2) - - [全文搜索](#%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2-1) - - [match 查询](#match-%E6%9F%A5%E8%AF%A2) - - [range 查询](#range-%E6%9F%A5%E8%AF%A2) - - [数字范围](#%E6%95%B0%E5%AD%97%E8%8C%83%E5%9B%B4) - - [日期范围](#%E6%97%A5%E6%9C%9F%E8%8C%83%E5%9B%B4) - - [分页](#%E5%88%86%E9%A1%B5) - - [exists 查询](#exists-%E6%9F%A5%E8%AF%A2) - - [bool 组合查询](#bool-%E7%BB%84%E5%90%88%E6%9F%A5%E8%AF%A2) - - [如何使用 bool 查询](#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-bool-%E6%9F%A5%E8%AF%A2) - - [constant_score 查询](#constant_score-%E6%9F%A5%E8%AF%A2) - - [多字段搜索](#%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%90%9C%E7%B4%A2) - - [多字符串查询](#%E5%A4%9A%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9F%A5%E8%AF%A2) - - [multi_match 查询](#multi_match-%E6%9F%A5%E8%AF%A2) - - [多字段映射](#%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%98%A0%E5%B0%84) - - [copy_to 定制组合 field](#copy_to-%E5%AE%9A%E5%88%B6%E7%BB%84%E5%90%88-field) -- [springboot 集成 es](#springboot-%E9%9B%86%E6%88%90-es) -- [mall](#mall) - - - -[Elasticsearch 权威指南](https://www.elastic.co/guide/cn/elasticsearch/guide/current/_talking_to_elasticsearch.html) - -## 基础 - -Elasticsearch 是一个开源的搜索引擎,建立在全文搜索引擎库 lucene 基础之上。Elasticsearch 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。 - -ES与mysql的对应关系: - -- index –> DB -- type –> Table -- Document –> row - -### 概念 - -[参考--阮一峰es教程](http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html) - -1. node 和 cluster - - Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。 - -2. Index - - 数据库的同义词。每个 Index (即数据库)的名字必须是小写。查看当前节点的所有index:`GET _cat/indices` - -3. Type - - 类似于表结构。不同的 Type 应该有相似的结构(schema),举例来说,`id`字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的区别。性质完全不同的数据(比如`products`和`logs`)应该存成两个 Index,而不是一个 Index 里面的两个 Type。 - -4. Document - - 单条的记录称为 Document。Document 可以分组,比如`weather`这个 Index 里面,可以按城市分组(北京和上海),这种分组就是 Type。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。 - - -### 启动和关闭 - -不用安装,解压即可。 - -启动:`bin\elasticsearch.bat` - -关闭:ctrl+c/`curl -XPOST http://localhost:9200/_cluster/nodes/_shutdown `关掉整个集群 - -启动 head 插件:到 head 安装目录下运行`grunt server` - -### 配置文件 - -安装目录config下的 elasticsearch.yml 可以配置集群的信息,如cluster.name 和 node.name。 - -```yaml -# ---------------------------------- MyConfig ---------------------------------- -#cluster.name: xxx -node.name: node-2 -#指明该节点可以是主节点,也可以是数据节点 -node.master: true -node.data: true -network.host: 127.0.0.1 -http.port: 9200 -transport.tcp.port: 9300 -``` - -http.port 是elasticsearch对外提供服务的http端口配置。 - -transport.tcp.port 指定了elasticsearch集群内数据通讯使用的端口,默认情况下为9300。 - - -### PUT - -```json -PUT /company/employee/1 -{ - "first_name" : "Tyson", - "last_name" : "dai", - "age" : 23, - "interests" : ["sport", "music"], - "hire_date" : "2014-01-01" -} -``` - -company:索引名称,employee:类型名称,1是 ID。 - -### GET - -```json -GET /company/employee/1 -``` - -搜索所有雇员: - -```json -GET /company/employee/_search -``` - -搜索结果如下,雇员数据放在 hits 数组中: - -```json -{ - "took": 413, - "timed_out": false, - "_shards": { - "total": 5, - "successful": 5, - "skipped": 0, - "failed": 0 - }, - "hits": { - "total": 2, - "max_score": 1, - "hits": [ - { - "_index": "company", - "_type": "employee", - "_id": "2", - "_score": 1, - "_source": { - "first_name": "Lily", - "last_name": "dai", - "age": 23, - "interests": [ - "sport", - "music" - ] - } - }, - { - "_index": "company", - "_type": "employee", - "_id": "1", - "_score": 1, - "_source": { - "first_name": "Tyson", - "last_name": "dai", - "age": 23, - "interests": [ - "sport", - "music" - ] - } - } - ] - } -} -``` - -按特定条件搜索: - -```json -GET /company/employee/_search?q=first_name:Tyson -``` - -使用查询表达式搜索: - -```json -GET /company/employee/_search -{ - "query": { - "match": { - "first_name": "Tyson" - } - } -} -``` - -复杂查询: - -姓氏为 Dai的雇员,但这次我们只需要年龄大于 20 的。 - -```json -GET /company/employee/_search -{ - "query": { - "bool" : { - "must" : { - "match" : { - "last_name" : "dai" - } - }, - "filter": { - "range": { - "age": {"gt" : 20} - } - } - } - } -} -``` - -### 全文搜索 - -传统数据库确实很难搞定的任务。 - -```json -GET /company/employee/_search -{ - "query": { - "match": { - "about": "rock climbing" - } - } -} -``` - -返回`"about": "rock climbing"`和`"about": "rock albums"`两条记录,默认按照每个文档跟查询的匹配程度排序。 - -### 高亮搜索 - -```json -GET /company/employee/_search -{ - "query": { - "match_phrase": { - "about": "climbing" - } - }, - "highlight": { - "fields": { - "about": {} - } - } -} -``` - -返回结果多 `highlight` 的部分。这个部分包含了 `about` 属性匹配的文本片段,并以 HTML 标签 `` 封装。 - -```json -{ - "took": 43, - "timed_out": false, - "_shards": { - "total": 5, - "successful": 5, - "skipped": 0, - "failed": 0 - }, - "hits": { - "total": 1, - "max_score": 0.2876821, - "hits": [ - { - "_index": "company", - "_type": "employee", - "_id": "3", - "_score": 0.2876821, - "_source": { - "first_name": "Tyson", - "last_name": "dai", - "age": 23, - "interests": [ - "sport", - "music" - ], - "about": "rock climbing" - }, - "highlight": { - "about": [ - "rock climbing" - ] - } - } - ] - } -} -``` - -### 分析 - -Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 `GROUP BY` 类似但更强大。 - -```json -GET /company/employee/_search -{ - "aggs": { - "all_interests": { - "terms": { "field": "interests" } - } - } -} -``` - -直接执行上面的代码会报错,原因是5.x后对排序,聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启。 - -```json -PUT company/_mapping/employee/ -{ - "properties": { - "interests": { - "type": "text", - "fielddata": true - } - } -} -``` - -搜索结果: - -```json -{ - ... - "hits": { ... }, - "aggregations": { - "all_interests": { - "doc_count_error_upper_bound": 0, - "sum_other_doc_count": 0, - "buckets": [ - { - "key": "music", - "doc_count": 4 - }, - { - "key": "sport", - "doc_count": 4 - } - ] - } - } -} -``` - -如果想知道叫 Tyson的雇员中最受欢迎的兴趣爱好,可以直接添加适当的查询来组合查询: - -```json -GET company/employee/_search -{ - "query": { - "match": { - "first_name": "Tyson" - } - }, - "aggs": { - "all_interests": { - "terms": { - "field": "interests" - } - } - } -} -``` - -搜索结果: - -```json -{ - "took": 33, - "timed_out": false, - "_shards": { - "total": 5, - "successful": 5, - "skipped": 0, - "failed": 0 - }, - "hits": { - "total": 1, - "max_score": 0.2876821, - "hits": [ - { - "_index": "company", - "_type": "employee", - "_id": "3", - "_score": 0.2876821, - "_source": { - "first_name": "Tyson", - "last_name": "dai", - "age": 23, - "interests": [ - "sport", - "music" - ], - "about": "rock climbing" - } - } - ] - }, - "aggregations": { - "all_interests": { - "doc_count_error_upper_bound": 0, - "sum_other_doc_count": 0, - "buckets": [ - { - "key": "music", - "doc_count": 1 - }, - { - "key": "sport", - "doc_count": 1 - } - ] - } - } -} -``` - -聚合还支持分级汇总 。比如,查询特定兴趣爱好员工的平均年龄: - -```java -GET company/employee/_search -{ - "aggs": { - "all_interests": { - "terms": { - "field": "interests" - }, - "aggs": { - "avg_age": { - "avg": { - "field": "age" - } - } - } - } - } -} -``` - -搜索结果: - -```json -"aggregations": { - "all_interests": { - "doc_count_error_upper_bound": 0, - "sum_other_doc_count": 0, - "buckets": [ - { - "key": "music", - "doc_count": 4, - "avg_age": { - "value": 18.5 - } - }, - { - "key": "sport", - "doc_count": 4, - "avg_age": { - "value": 18.5 - } - } - ] - } - } -``` - -### 分布式特性 - -Elasticsearch 可以横向扩展至数百(甚至数千)的服务器节点,同时可以处理PB级数据。 - -## 集群原理 - -ElasticSearch 的主旨是随时可用和按需扩容。扩容可以通过购买性能更强大( *垂直扩容* ) 或者数量更多的服务器( *水平扩容* )来实现。 - -### 术语 - -#### 节点 - -一个运行中的 Elasticsearch 实例称为节点,而集群是由一个或者多个拥有相同 `cluster.name` 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。 - -当一个节点被选举成为主节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。 - -我们可以将请求发送到集群中的任何节点,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。 - -获取节点信息:`http://localhost:9200/_cluster/state/nodes?pretty`,pretty 用于换行。 - -#### 分片 - -每个节点可以分配一个或多个分片。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。 - -一个分片可以是 *主* 分片或者 *副本* 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。 - -一个副本分片只是一个主分片的拷贝。 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。 - -### 集群健康 - -`GET /_cluster/health` - -返回内容: - -```json -{ - "cluster_name": "elasticsearch", - "status": "yellow", - "timed_out": false, - "number_of_nodes": 1, - "number_of_data_nodes": 1, - "active_primary_shards": 6, - "active_shards": 6, - "relocating_shards": 0, - "initializing_shards": 0, - "unassigned_shards": 5, - "delayed_unassigned_shards": 0, - "number_of_pending_tasks": 0, - "number_of_in_flight_fetch": 0, - "task_max_waiting_in_queue_millis": 0, - "active_shards_percent_as_number": 54.54545454545454 -} -``` - -status 字段表示当前集群总体是否正常,它有三个值: - -1. green,所有的主分片和副本分片都正常运行。 - -2. yellow,所有的主分片都正常运行,但不是所有的副本分片都正常运行。 -3. red,有主分片不能正常运行。 - -### 索引 - -往 elasticsearch 添加数据时需要用到索引,索引是指向一个或多个分片的逻辑命名空间。一个分片是一个 Lucene 的实例,以及它本身就是一个完整的搜索引擎。 - -当我们只开启一个节点时,索引在默认情况下会被分配5个主分片,每个主分片拥有一个副本分片。主分片会被分配到这个节点上,而副本分片不会被分配到任何节点。 - -```json -{ - "cluster_name": "elasticsearch", - "status": "yellow", - ... - "unassigned_shards": 5,//5个副本分片都是 unassigned,都没有被分配到任何节点 - ... -} -``` - -当前我们的集群是正常运行的,但是在硬件故障时有丢失数据的风险。 - -### 故障转移 - -可以在同一个目录下开启另一个节点,副本分片会被分配到这个节点上,此时计算有硬件故障也不会丢失数据。 - -### 单机多节点 - -node1 的 elasticsearch.yml 做如下配置: - -```yaml -# ---------------------------------- MyConfig ---------------------------------- -#cluster.name: xxx -node.name: node-1 -#指明该节点可以是主节点,也可以是数据节点 -#node.master: true -#node.data: true -network.host: 127.0.0.1 -http.port: 9200 -transport.tcp.port: 9300 -discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"] - -# 解决elasticsearch-head 集群健康值: 未连接问题 -http.cors.enabled: true -http.cors.allow-origin: "*" -``` - -node2 的 elasticsearch.yml 做如下配置: - -```yaml -# ---------------------------------- MyConfig ---------------------------------- -#cluster.name: xxx -node.name: node-2 -#指明该节点可以是主节点,也可以是数据节点 -#node.master: true -#node.data: true -network.host: 127.0.0.1 -http.port: 9201 -transport.tcp.port: 9301 -discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"] - -# 解决elasticsearch-head 集群健康值: 未连接问题 -http.cors.enabled: true -http.cors.allow-origin: "*" -``` - -同理 node3 也做好配置。然后重启 elasticsearch 节点,就可以实现单机多节点集群搭建。 - - - -## 数据输入与输出 - -### 文档元数据 - -一个文档不仅包含数据,也包含元数据。三个必须的元数据元素如下:\_index、\_type和_id。 - -索引名字必须小写,不能以下划线开头,不能包含逗号。 - -\_type在索引中对数据进行逻辑分区,如产品下面还可以分为很多子类。一个 `_type` 命名可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符。 - -### 创建新文档 - -使用 PUT 请求,需要定义 _id: - -```json -PUT /{index}/{type}/{id} -{ - "field": "value", - ... -} -``` - -id 为2的文档存在时会报错: document already exists - -```json -PUT company/employee/2/_create -{ - "first_name" : "Tyson", - "last_name" : "dai", - "age" : 23, - "interests" : ["sport", "music"] -} -``` - -不存在时才创建: - -```json -PUT company/employee/2?op_type=create -{ - "first_name" : "Tyson", - "last_name" : "dai", - "age" : 23, - "interests" : ["sport", "music"] -} -``` - -使用 `POST` 可以让 Elasticsearch 自动生成唯一 的_id。 - -```json -POST company/employee -{ - "first_name" : "Tyson", - "last_name" : "dai", - "age" : 23, - "interests" : ["sport", "music"] -} -``` - -### 取回文档 - -返回文档的一部分: - -```json -GET /company/employee/1?_source=first_name,interests -``` - -只得到_source 字段(即id为1的整个文档): - -```json -GET /company/employee/1/_source -``` - - -### 取回多个文档 - -mget api 要求传入一个 docs 数组作为参数,可以通过 _source 指定返回字段。 - -```json -GET /_mget -{ - "docs": [ - { - "_index": "company", - "_type": "employee", - "_id": 2 - }, - { - "_index": "class", - "_type": "student", - "_id": 1, - "_source": "about" - } - ] -} -``` - -如果获取的文档 _index 和 _type 相同,可以在 url 指定默认的 _index 和 _type,传入一个 ids 数组。 - -```json -GET /company/employee/_mget -{ - "ids": ["1", "2"] -} -``` - -通过单独请求可以覆盖默认的 _index 和 _type。 - -```json -GET /company/employee/_mget -{ - "docs" : [ - { "_id" : 2 }, - { "_index" : "class", "_type" : "student", "_id" : 1 } - ] -} -``` - -### 删除文档 - -`DELETE company/employee/1`,删除文档,版本号会增加。 - -```json -{ - "_index": "company", - "_type": "employee", - "_id": "1", - "_version": 2, - "result": "deleted", - "_shards": { - "total": 2, - "successful": 1, - "failed": 0 - }, - "_seq_no": 1, - "_primary_term": 4 -} -``` - -### 检查文档是否存在 - -`HEAD /company/employee/1` - -返回结果:`200 - OK` - -### 更新文档 - -文档是不可变的,不能被修改,只能被替换。 `update` API 必须遵循同样的规则。 从外部来看,我们在一个文档的某个位置进行部分更新。然而在内部, `update` API 简单使用 *检索-修改-重建索引* 的处理过程。 - -```json -POST company/employee/1/_update -{ - "doc": { - "first_name": "sophia", - "interests": ["sport", "chess"] - } -} -``` - -#### 更新和冲突 - -```json -POST company/employee/1/_update?retry_on_conflict=5 -{ - "doc": { - "first_name": "sophia", - "interests": ["sport", "chess"] - } -} -``` - -### 批量操作 - -语法: - -```json -{ action: { metadata }}\n -{ request body }\n -{ action: { metadata }}\n -{ request body }\n -... -``` - -action 有 create、delete、index 和 update。metadata 定义了\_index,\_type,_id 等信息。 - -create:如果文档不存在,那么就创建它。index:创建一个新文档或者替换一个现有的文档。create 和 index 不指定 `_id`的话 ,将会自动生成一个 ID 。 - -```json -POST /_bulk -{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} -{ "create": { "_index": "website", "_type": "blog", "_id": "123" }} -{ "title": "My first blog post" } -{ "index": { "_index": "website", "_type": "blog" }} -{ "title": "My second blog post" } -{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} } -{ "doc" : {"title" : "My updated blog post"} } -``` - -bulk 请求不是原子的,不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求。 - -**默认的 index 和 type** - -```json -POST /website/_bulk -{ "index": { "_type": "log" }} -{ "event": "User logged in" } -``` - - - -## 分布式文档存储 - -### 路由文档到分片 - -文档所在分片的位置通过这个公式计算:`shard = hash(routing) % number_of_primary_shards`,rounting 默认是文档的 _id,可以设置成自定义的值。创建索引的时候就确定好主分片的数量,并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。 - - - - -## 映射和分析 - -映射:为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。 - -分析:将一块文本分成适合于倒排索引的独立的词条,然后将这些词条统一化为标准格式以提高它们的可搜索性。 - -### 核心简单域类型 - -Elasticsearch 支持 如下简单域类型: - -- 字符串: `string` -- 整数 : `byte`, `short`, `integer`, `long` -- 浮点数: `float`, `double` -- 布尔型: `boolean` -- 日期: `date` - -当你索引一个新的文档,elasticsearch 会使用动态映射,通过 json 中的基本数据类型,尝试猜测域的类型。 - -| **JSON type** | **域 type** | -| ------------------------------ | ----------- | -| 布尔型: `true` 或者 `false` | `boolean` | -| 整数: `123` | `long` | -| 浮点数: `123.45` | `double` | -| 字符串,有效日期: `2014-09-15` | `date` | -| 字符串: `foo bar` | `string` | - -如果你通过引号( `"123"` )索引一个数字,它会被映射为 `string` 类型,而不是 `long` 。但是,如果这个域已经映射为 `long` ,那么 Elasticsearch 会尝试将这个字符串转化为 long ,如果无法转化,则抛出一个异常。 - -### 查看映射 - -`GET /company/_mapping/employee` - -返回结果: - -```json -{ - "company": { - "mappings": { - "employee": { - "properties": { - "age": { - "type": "long" - }, - "first_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "hire_date": { - "type": "date" - }, - "interests": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "last_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - } - } - } -} -``` - -### 自定义映射器 - -`string` 类型域会被认为包含全文。它们的值在索引前,会通过 一个分析器,针对于这个域的查询在搜索前也会经过一个分析器。string 域映射的两个最重要的属性是 index 和 analyzer。 - -#### index - -`index` 属性控制怎样索引字符串。它有三个值: - -- analyzed:默认,首先分析这个域,然后索引它; -- not_analyzed:索引这个域,索引的是精确值,不会对它进行分析; -- no:不要索引这个域,这个域不会被搜索到。 - -设置 tag 域的 index 为 not_analyzed: - -```json -{ - "tag": { - "type": "string", - "index": "not_analyzed" - } -} -``` - -其他简单类型(例如 `long` , `double` , `date` 等)也接受 `index` 参数,但有意义的值只有 `no` 和 `not_analyzed` , 因为它们永远不会被分析。 - -#### analyzer - -对于 `analyzed` 字符串域,用 `analyzer` 属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 `standard` 分析器, 但你可以指定一个内置的分析器替代它,例如 `whitespace` 、 `simple` 和 `english`: - -```json -{ - "tweet": { - "type": "string", - "analyzer": "english" - } -} -``` - - -### 更新映射 - -我们可以更新一个映射来添加一个新域,但不能将一个存在的域从 `analyzed` 改为 `not_analyzed` ,否则索引的数据可能会出错,数据不能被正常的搜索。 - -增加名为 tag 的 not_analyzed 的文本域: - -```json -PUT /gb/_mapping/tweet -{ - "properties" : { - "tag" : { - "type" : "text", - "index": "not_analyzed" - } - } -} -``` - -指定中文分词器: - -```json -PUT /gb/_mapping/tweet -{ - "properties" : { - "user": { - "type": "text", - "analyzer": "ik_max_word", - "search_analyzer": "ik_max_word" - } - } -} -``` - -`analyzer`是字段文本的分词器,`search_analyzer`是搜索词的分词器。`ik_max_word`分词器是插件`ik`提供的,可以对文本进行最大数量的分词。 - - -### 测试映射 - -```json -GET /gb/_analyze -{ - "field": "tag", - "text": "Black-cats" -} -``` - - `tag` 域产生单独的词条 `Black-cats` 。 - -### 分析器 - -分析器的三个功能: - -- 字符过滤。字符串按顺序通过每个字符过滤器。它们在分词前整理字符串。一个字符过滤器可以用来去掉HTML或者将 & 转化为 and。 -- 字符串被分词器分成单个的词条 -- token 过滤器。改变词条(Quick 小写),删除词条(a/the/and),增加词条(leap/jump这种同义词) - -对特定域和全文域_all 查询字符串时可能会返回不同的结果。 - -当你查询一个 *全文* 域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。 - -当你查询一个 *精确值* 域时,不会分析查询字符串, 而是搜索你指定的精确值。 - -```json -GET /_search?q=2014 # 12 results -GET /_search?q=2014-09-15 # 12 results -GET /_search?q=date:2014-09-15 # 1 result -GET /_search?q=date:2014 # 0 results 没有"2014",只有"2014-09-15" -``` - -date 域包含一个精确值:单独的词条 `2014-09-15`。 - -_all 域是一个全文域,所以分词进程将日期转化为三个词条: `2014`, `09`, 和 `15`。 - -#### 测试分析器 - -```json -GET /_analyze -{ - "analyzer": "standard", - "text": "Text to analyze" -} -``` - -结果: - -```json -{ - "tokens": [ - { - "token": "text", - "start_offset": 0, - "end_offset": 4, - "type": "", - "position": 0 - }, - { - "token": "to", - "start_offset": 5, - "end_offset": 7, - "type": "", - "position": 1 - }, - { - "token": "analyze", - "start_offset": 8, - "end_offset": 15, - "type": "", - "position": 2 - } - ] -} -``` - -### 复杂核心域类型 - -#### 多值域 - -`{ "tag": [ "search", "nosql" ]}` - -### 内部对象 - -```json -{ - "tweet": "Elasticsearch is very flexible", - "user": { - "id": "@johnsmith", - "gender": "male", - "age": 26, - "name": { - "full": "John Smith", - "first": "John", - "last": "Smith" - } - } -} -``` - -Lucene 不理解内部对象。 Lucene 文档是由一组键值对列表组成的。为了能让 Elasticsearch 有效地索引内部类,它把我们的文档转化成这样: - -```json -{ - "tweet": [elasticsearch, flexible, very], - "user.id": [@johnsmith], - "user.gender": [male], - "user.age": [26], - "user.name.full": [john, smith], - "user.name.first": [john], - "user.name.last": [smith] -} -``` - - - - -## 搜索 - -### 空搜索 - -`GET /_search`,返回的 hits 数组包含所查询结果的前十个文档。 - -`GET /_search?timeout=10ms`,在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。 - - -### 多索引多类型 - -`GET /c*,g*/_search`,在以 c 开头和 g 开头的索引中搜索所有的类型。 - -`GET /_all/employee,student/_search?size=1&from=1`,在所有索引中搜索 employee 和 student 类型。elasticsearch 默认一次返回10条结果,size 可以指定返回返回结果数量,from 指定位移。 - - -### 轻量搜索 - -查询 employee 类型的 last_name 字段为 dai 的所有文档:`GET company/employee/_search?q=last_name:dai` - -查询包含 dai 的所有文档:`GET /_search?q=dai` - - - -## 请求体查询 - -### 空查询 - -```json -GET _search -{ - "query" : { - "match_all": {} - } -} -``` - - - - -### 提升权重 - -我们可以通过指定 `boost` 来控制任何查询语句的相对的权重, `boost` 的默认值为 `1` ,大于 `1` 会提升一个语句的相对权重。 - -```json -GET /company/employee/_search -{ - "query": { - "bool": { - "must": { - "match": { - "interests": { - "query": "sport music", - "operator": "and" - } - } - }, - "should": [ - { "match": { - "first_name": { - "query": "tyson", - "boost": 3 - } - }}, - { "match": { - "first_name": { - "query": "sophia", - "boost": 2 - } - }} - ] - } - } -} -``` - -### explain - -查询结果说明。 - -```json -GET /_validate/query?explain -{ - "query": { - "match" : { - "interests" : "sport shoes" - } - } -} -``` - -结果: - -```json -{ - "valid": true, - "_shards": { - "total": 3, - "successful": 3, - "failed": 0 - }, - "explanations": [ - { - "index": "class", - "valid": true, - "explanation": "interests:sport interests:shoes" - }, - { - "index": "company", - "valid": true, - "explanation": "interests:sport interests:shoes" - } - ] -} -``` - -### 查询和过滤器的区别 - -查询会计算得分,而过滤不计算得分,过滤器所需处理更少,所以过滤器可以比普通查询更快。而且过滤器可以被缓存。 - - - -## 排序与相关性 - -有时,_score 相关性评分对你来说并没有意义。例如,下面的查询返回所有 `user_id` 字段包含 `1` 的结果: - -```json -GET /_search -{ - "query" : { - "constant_score" : { - "filter" : { - "term" : { - "id" : 1 - } - } - } - } -} -``` - -### 按照字段的值排序 - -按照 hire_date 排序。 - -```json -GET _search -{ - "query" : { - "bool" : { - "filter" : { - "match" : { - "first_name" : "tyson" - } - } - } - }, - "sort" : { - "hire_date" : { "order" : "desc" } - } -} -``` - -### 多级排序 - -首先按第一个条件排序,仅当结果集的第一个 `sort` 值完全相同时才会按照第二个条件进行排序,以此类推。 - -```json -GET _search -{ - "query" : { - "bool" : { - "filter" : { - "match" : { - "first_name" : "tyson" - } - } - } - }, - "sort" : { - "hire_date" : { "order" : "desc" }, - "_score" : { "order" : "desc" } - } -} -``` - -Query-string 搜索 也支持自定义排序,可以在查询字符串中使用 `sort` 参数: - -```js -GET /_search?sort=hire_date:desc&sort=_score -``` - -### 多值字段的排序 - -对于数字或日期,你可以将多值字段减为单值,这可以通过使用 `min` 、 `max` 、 `avg` 或是 `sum` 排序模式。 例如你可以按照每个 hire_date 字段中的最早日期进行排序,通过以下方法: - -```json -"sort": { - "hire_date": { - "order": "asc", - "mode": "min" - } -} -``` - -### 字符串排序 - -为了对字符串字段进行排序,需要用两种方式对同一个字符串进行索引: `analyzed` 用于搜索, `not_analyzed` 用于排序。 - -用两种方式索引一个单字段: - -```json -"interests": { - "type": "string", - "analyzer": "english", - "fields": { - "raw": { - "type": "string", - "index": "not_analyzed" - } - } -} -``` - -interests.raw 子字段是 not_analyzed。interests 字段只在 _source 中出现一次。 - -使用 interests 字段用于搜索,interests.raw 字段用于排序: - -```json -GET /_search -{ - "query": { - "match": { - "interests": "elasticsearch" - } - }, - "sort": "interests.raw" -} -``` - -备注:以全文 `analyzed` 字段排序会消耗大量的内存。 - - - -## 索引管理 - -### 创建索引 - -```json -PUT /my_index -{ - "settings": { ... any settings ... }, - "mappings": { - "type_one": { ... any mappings ... }, - "type_two": { ... any mappings ... }, - ... - } -} -``` - -禁止自动创建索引,你 可以通过在 `config/elasticsearch.yml` 的每个节点下添加下面的配置: - -`action.auto_create_index: false` - -### 删除索引 - -`DELETE /company,student` - -`DELETE /index_*` - -`DELETE /_all` 或 `DELETE /*` - -### 索引设置 - -number_of_shards:每个索引的主分片数,默认值是 `5` 。这个配置在索引创建后不能修改。 - -number_of_replicas:每个主分片的副本数,默认值是 `1` 。对于活动的索引库,这个配置可以随时修改。 - -创建只有 一个主分片,没有副本的小索引: - -```json -PUT /my_temp_index -{ - "settings": { - "number_of_shards" : 1, - "number_of_replicas" : 0 - } -} -``` - - 动态修改副本数: - -```json -PUT /my_temp_index/_settings -{ - "number_of_replicas": 1 -} -``` - -### 配置分析器 - -#### 自定义分析器 - -,一个分析器组合了三种函数:字符过滤器、分词器和词单元过滤器, 三种函数按照顺序被执行。 - -```json -PUT /my_index -{ - "settings": { - "analysis": { - "char_filter": { - "&_to_and" : { - "type" : "mapping", - "mappings" : ["&=>and"] - } - }, - "filter": { - "my_stopwords" : { - "type" : "stop", - "stopwords" : ["the", "a"] - } - }, - "analyzer": { - "my_analyzer" : { - "type" : "custom", - "char_filter" : ["html_strip", "&_to_and"], - "tokenizer" : "standard", - "filter" : ["lowercase", "my_stopwords"] - } - } - } - } -} -``` - -测试: - -```json -GET /my_index/_analyze -{ - "analyzer" : "my_analyzer", - "text" : "The quick & brown fox" -} -``` - -结果: - -```json -{ - "tokens": [ - { - "token": "quick", - "start_offset": 4, - "end_offset": 9, - "type": "", - "position": 1 - }, - { - "token": "and", - "start_offset": 10, - "end_offset": 11, - "type": "", - "position": 2 - }, - { - "token": "brown", - "start_offset": 12, - "end_offset": 17, - "type": "", - "position": 3 - }, - { - "token": "fox", - "start_offset": 18, - "end_offset": 21, - "type": "", - "position": 4 - } - ] -} -``` - -把分析器应用在 string 字段上: - -```json -PUT /my_index/_mapping/my_type -{ - "properties": { - "title": { - "type": "string", - "analyzer": "my_analyzer" - } - } -} -``` - -### 类型和映射 - -同一个索引下,不同的类型type应该有相同的结构,映射也应该相同。因为 Lucene 会将同一个索引下的所有字段的映射扁平化,相同字段不同映射会导致冲突。 - -```json -{ - "data": { - "mappings": { - "people": { - "properties": { - "name": { - "type": "string", - }, - "address": { - "type": "string" - } - } - }, - "transactions": { - "properties": { - "timestamp": { - "type": "date", - "format": "strict_date_optional_time" - }, - "message": { - "type": "string" - } - } - } - } - } -} -``` - -后台 Lucene 将创建一个映射: - -```json -{ - "data": { - "mappings": { - "_type": { - "type": "string", - "index": "not_analyzed" - }, - "name": { - "type": "string" - } - "address": { - "type": "string" - } - "timestamp": { - "type": "long" - } - "message": { - "type": "string" - } - } - } -} -``` - -因此,类型不适合 *完全不同类型的数据* 。如果两个类型的字段集是互不相同的,这就意味着索引中将有一半的数据是空的(字段将是 *稀疏的* ),最终将导致性能问题。在这种情况下,最好是使用两个单独的索引。 - - -### 根对象 - -映射最高的一层被称为根对象。它可能包含以下几项: - -- properties 节点,列出文档每个字段的映射 -- 下划线开头的元数据字段,如 \_type,_id 和 \_source -- 设置项,控制如何动态处理新的字段,例如 `analyzer` 、 `dynamic_date_formats` 和`dynamic_templates` -- 其他设置,可以同时应用在根对象和其他 `object` 类型的字段上,例如 `enabled` 、 `dynamic` 和 `include_in_all` - - - -## 分片内部原理 - -### 倒排索引 - -倒排索引包含一个有序列表,列表包含所有文档出现过的不重复个体,或称为 *词项* ,对于每一个词项,包含了它所有曾出现过文档的列表。 - -| Term | doc1 | doc2 | doc3 | -| ----- | ---- | ---- | ---- | -| sport | x | | x | -| music | | x | | -| chess | x | x | x | - - - -## 深入搜索 - -### 精确值查找 - -term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 `not_analyzed` 的字符串。 - -```json -GET /company/employee/_search -{ - "query" : { - "term" : { - "interests" : "listen" - } - } -} -``` - -hire_date 在过去四年内的文档: - -```json -GET company/employee/_search -{ - "query": { - "constant_score": { - "filter": { - "range": { - "hire_date": { - "gt": "now-4y" - } - } - } - } - } -} -``` - -#### term 查询文本 - -删除旧索引(因为旧索引字段都是 analyzed 的,它的映射不正确)然后创建一个能正确映射的新索引: - -```json -PUT /my_store -{ - "mappings" : { - "products" : { - "properties": { - "productID" : { - "type" : "keyword",//es6废除了string,index是boolean值,keyword不分词,text分词 - } - } - } - } -} -``` - -放进数据: - -```json -POST /my_store/products/_bulk -{ "index": { "_id": 1 }} -{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" } -{ "index": { "_id": 2 }} -{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" } -{ "index": { "_id": 3 }} -{ "price" : 30, "productID" : "JODL-X-1937-#pV7" } -{ "index": { "_id": 4 }} -{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" } -``` - -查询文本: - -```json -GET /my_store/products/_search -{ - "query" : { - "constant_score" : { - "filter" : { - "term" : { - "productID" : "XHDK-A-1293-#fJ3" - } - } - } - } -} -``` - -#### terms 查询 - -允许指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件。 - -```json -GET /company/employee/_search -{ - "query" : { - "terms" : { - "interests" : ["listen", "music", "sport"] - } - } -} -``` - -置入 `filter` 语句的常量评分查询: - -```json -GET /my_store/products/_search -{ - "query": { - "constant_score": { - "filter": { - "terms" : { - "interests" : ["listen", "music", "sport"] - } - }, - "boost": 1.2 - } - } -} -``` - -interests 为 listen、music 和 sport 的文档会被匹配。 - -### 全文搜索 - -#### match 查询 - -match 查询是对全文进行查询。 - -如果有多个搜索关键字, Elastic 认为它们是`or`关系。下面例子返回 interests 为 sport 或者 music 的文档。 - -```json -GET _search -{ - "query" : { - "match": { - "interests": "sport music" - } - } -} -``` - -指定词都必须匹配: - -```json -GET _search -{ - "query" : { - "match": { - "interests": { - "query": "sport music", - "operator": "and" - } - } - } -} -``` - -控制匹配的字段数目: - -```json -GET _search -{ - "query" : { - "match": { - "interests": { - "query": "sport music", - "minimum_should_match": 2 - } - } - } -} -``` - -### range 查询 - -查询找出那些落在指定区间内的数字或者时间。 - -#### 数字范围 - -```json -GET company/employee/_search -{ - "query": { - "constant_score": { - "filter": { - "range": { - "age": { - "gt": 20, - "lt": 100 - } - } - } - } - } -} -``` - -`gt`:大于;`gte`:大于或等于;`lt`:小于;`lte`:小于或等于。 - -#### 日期范围 - -```json -GET company/employee/_search -{ - "query": { - "constant_score": { - "filter": { - "range": { - "hire_date": { - "gt": "2015-01-01", - "lt": "2019-01-01" - } - } - } - } - } -} -``` - -### 分页 - -请求得到 1 到 3 页的结果: - -```json -GET /_search?size=5 -GET /_search?size=5&from=5 -GET /_search?size=5&from=10 -``` - -### exists 查询 - -查询字段 interests 中不为空的文档: - -```json -GET /company/employee/_search -{ - "query": { - "constant_score": { - "filter": { - "exists": { - "field": "interests" - } - } - } - } -} -``` - -字段 interests 为空的文档。es6 没有 missing api,直接用 bool 和 exists 实现。 - -```json -GET /company/employee/_search -{ - "query": { - "bool": { - "must_not": { - "exists": { - "field": "interests" - } - } - } - } -} -``` - -### bool 组合查询 - -bool 查询允许在单独的查询中组合任意数量的查询,适用于将不同查询字符串映射到不同字段的情况。bool 查询接收如下参数: - -- must:文档必须匹配这些条件才能被包含进来 -- must_not:文档必须不匹配这些条件才能被包含进来 -- should:如果满足这些语句中的任意语句,将增加 _score,否则没有影响。主要用来修正每个文档的相关性得分 -- filter:必须匹配,但是不影响评分 - -如果没有 `must` 语句,那么至少需要能够匹配其中的一条 `should` 语句。但,如果存在至少一条 `must` 语句,则对 `should` 语句的匹配没有要求。 - -```json -GET /company/employee/_search -{ - "query" : { - "bool" : { - "must" : { "match" : {"first_name" : "tyson"}}, - "must_not" : { "match" : {"last_name" : "tang"}}, - "should" : [ - {"match" : {"interest" : "music"}}, - {"range" : {"age" : { "gte" : 30 }}} - ] - } - } -} -``` - -如果不想因为文档的时间而影响得分,可以添加 filter 过滤掉某个时间段。 - -```json -GET _search -{ - "query" : { - "bool" : { - "must" : { - "match" : { "first_name" : "tyson"} - }, - "must_not" : { - "match" : {"last_name" : "tang"} - }, - "should" : [ - {"match" : { "interests": "sport"}}, - {"range" : { "age" : { "gt" : 20 }}} - ], - "filter" : { - "range" : { "hire_date" : { "gt" : "2015-01-01" }} - } - } - } -} -``` - -可以将查询移到 `bool` 查询的 `filter` 语句中,这样它就自动的转成一个不评分的查询了。 - -```json -{ - "bool": { - "must": { "match": { "title": "how to make millions" }}, - "must_not": { "match": { "tag": "spam" }}, - "should": [ - { "match": { "tag": "starred" }} - ], - "filter": { - "bool": { - "must": [ - { "range": { "date": { "gte": "2014-01-01" }}}, - { "range": { "price": { "lte": 29.99 }}} - ], - "must_not": [ - { "term": { "category": "ebooks" }} - ] - } - } - } -} -``` - -bool 查询使用`minimum_should_match`控制需要匹配的 should 语句的数量: - -```json -GET /my_index/my_type/_search -{ - "query": { - "bool": { - "should": [ - { "match": { "title": "brown" }}, - { "match": { "title": "fox" }}, - { "match": { "title": "dog" }} - ], - "minimum_should_match": 2 - } - } -} -``` - -### 如何使用 bool 查询 - -多次 match 查询: - -```json -GET /company/employee/_search -{ - "query": { - "match": { - "interests": "sport music" - } - } -} -``` - -等价的 bool 查询(存在`must`,则对 `should` 语句的匹配没有要求,否则至少需要能够匹配其中的一条 `should` 语句): - -```json -GET /company/employee/_search -{ - "query": { - "bool": { - "should": [ - { "term" : { "interests": "sport" } }, - { "term" : { "interests" : "music" } } - ] - } - } -} -``` - -使用 and 操作符,返回所有字段都匹配到的文档: - -```json -GET /company/employee/_search -{ - "query": { - "match": { - "interests": { - "query": "sport music", - "operator": "and" - } - } - } -} -``` - -等价的 bool 查询: - -```json -GET /company/employee/_search -{ - "query": { - "bool": { - "must": [ - { "term": { "interests": "sport" }}, - { "term": { "interests": "music" }} - ] - } - } -} -``` - -指定参数 minimum_should_match: - -```json -GET /company/employee/_search -{ - "query": { - "match": { - "interests": { - "query": "sport music chess", - "minimum_should_match" : 2 - } - } - } -} -``` - -等价的 bool 查询: - -```json -GET /company/employee/_search -{ - "query": { - "bool": { - "should": [ - {"term": { "interests": "sport" }}, - {"term": { "interests": "music" }}, - {"term": { "interests": "chess" }} - ], - "minimum_should_match": 2 - } - } -} -``` - -### constant_score 查询 - -constant_score 查询返回的文档`score`都是1。它经常用于只需要执行一个 filter 而没有其它查询的情况下。`score`会受到`boost`影响,出现 tyson 的文档`score`为1.2。 - -```json -GET _search -{ - "query" : { - "constant_score": { - "filter": { - "match" : { "first_name" : "tyson"} - }, - "boost": 1.2 - } - } -} -``` - - - - -### 多字段搜索 - -参考自:[best_fields most_fields cross_fields从内在实现看区别——本质就是前两者是以field为中心,后者是词条为中心](https://www.cnblogs.com/bonelee/p/6827068.html) - -最佳字段 best_fields:搜索结果中应该返回某一个字段匹配到了最多的关键词的文档。 - -多数字段 most_fields:返回匹配了更多的字段的文档,尽可能多地匹配文档。ES会为每个字段生成一个match查询,然后将它们包含在一个bool查询中。 - -跨字段 cross_fields:每个查询的单词都出现在不同的字段中。*cross_fields类型采用了一种以词条为中心(Term-centric)的方法,这种方法和best_fields及most_fields采用的以字段为中心(Field-centric)的方法有很大的区别。它将所有的字段视为一个大的字段,然后在任一字段中搜索每个词条。 - -#### 多字符串查询 - -```json -GET /_search -{ - "query": { - "bool": { - "should": [ - { "match": { // 权重:1/3 - "title": { - "query": "War and Peace", - "boost": 2 - }}}, - { "match": { // 权重:1/3 - "author": { - "query": "Leo Tolstoy", - "boost": 2 - }}}, - { "bool": { //译者信息用布尔查询,降低评分权重 权重:1/3 - "should": [ - { "match": { "translator": "Constance Garnett" }}, - { "match": { "translator": "Louise Maude" }} - ] - }} - ] - } - } -} -``` - -#### multi_match 查询 - -multi_match 查询可以在多个字段上执行相同的 match 查询。`multi_match` 多匹配查询的类型有三种:`best_fields` 、 `most_fields` 和 `cross_fields` (最佳字段、多数字段、跨字段)。 - -```json -GET company/employee/_search -{ - "query" : { - "multi_match": { - "query": "sport shoes", - "type": "best_fields", - "fields": [ "interests", "first_name" ], - "tie_breaker": 0.3, - "minimum_should_match": 1 - } - } -} -``` - -模糊匹配: - -```json -GET company/employee/_search -{ - "query" : { - "multi_match": { - "query": "tyson dai", - "type": "best_fields", - "fields": "*_name", - "tie_breaker": 0.3, - "minimum_should_match": "30%" - } - } -} -``` - -提升字段的权重,first_name 字段的 `boost` 值为 `2` : - -```json -GET company/employee/_search -{ - "query" : { - "multi_match": { - "query": "tyson dai", - "type": "best_fields", - "fields": ["*_name", "first_name^3"], - "tie_breaker": 0.3, - "minimum_should_match": "30%" - } - } -} -``` - -#### 多字段映射 - -对字段索引两次: 一次使用词干模式以及一次非词干模式。 - -```json -DELETE /my_index - -PUT /my_index -{ - "settings": { "number_of_shards": 1 }, - "mappings": { - "my_type": { - "properties": { - "title": { - "type": "string", - "analyzer": "english",//提取词干 - "fields": { - "std": { - "type": "string", - "analyzer": "standard" - } - } - } - } - } - } -} -``` - -`title` 字段使用 `english` 分析器来提取词干;`title.std` 字段使用 `standard` 标准分析器,所以没有词干提取。 - -索引文档: - -```json -PUT /my_index/my_type/1 -{ "title": "My rabbit jumps" } - -PUT /my_index/my_type/2 -{ "title": "Jumping jack rabbits" } -``` - -multi_match 查询: - -```json -GET /my_index/_search -{ - "query": { - "multi_match": { - "query": "jumping rabbits", - "type": "most_fields", - "fields": [ "title", "title.std" ] - } - } -} -``` - -文档2匹配度更高,因为 title.std 不会提取词干,只有文档2是匹配的。 - -设置`title` 字段的 `boost` 的值为 `10`,提升 title 字段的权重: - -```json -GET /my_index/_search -{ - "query": { - "multi_match": { - "query": "jumping rabbits", - "type": "most_fields", - "fields": [ "title^10", "title.std" ] - } - } -} -``` - -#### copy_to 定制组合 field - -定制组合 field 与 cross_field 跨字段查询类似,根据两者的实际性能选择具体方案。 - -创建映射: - -```json -PUT my_index1 -{ - "mappings": { - "my_type": { - "properties": { - "first_name": { - "type": "keyword", - "copy_to": "full_name" - }, - "last_name": { - "type": "keyword", - "copy_to": "full_name" - }, - "full_name": { - "type": "text", - "fielddata": true - } - } - } - } -} -``` - -插入数据: - -```json -PUT my_index1/my_type/1 -{ - "first_name": "John", - "last_name": "Smith" -} -``` - -校验查询: - -```json -GET my_index1/_search -{ - "query": { - "match": { - "full_name": { - "query": "John Smith", - "operator": "and" - } - } - } -} - -``` - -`copy_to` 设置对 multi-field 无效。如果尝试这样配置映射,Elasticsearch 会抛异常。多字段只是以不同方式简单索引主字段;它们没有自己的数据源。 - -```json -PUT /my_index -{ - "mappings": { - "person": { - "properties": { - "first_name": { - "type": "string", - "copy_to": "full_name", - "fields": { - "raw": { - "type": "string", - "index": "not_analyzed" - } - } - }, - "full_name": { - "type": "string" - } - } - } - } -} -``` - -first_name 是主字段,first_name.raw 是多字段。 - - - -## springboot 集成 es - -[springboot 集成 es](https://blog.csdn.net/cwenao/article/details/54943505) - -[springboot整合elasticsearch5.x以及IK分词器做全文检索](https://blog.csdn.net/chenxihua1/article/details/94546282) - - - -## mall - -创建文档: - -```json -POST /pms/product -{ - "productSn": "HNTBJ2E080A", - "brandId": 50, - "brandName": "海澜之家", - "productCategoryId": 8, - "productCategoryName": "T恤", - "pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5ac98b64N70acd82f.jpg!cc_350x449.jpg", - "name": "HLA海澜之家蓝灰花纹圆领针织布短袖T恤", - "subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 蓝灰花纹80 175/92A/L80A 蓝灰花纹80 175/92A/L", - "keywords": "", - "price": 98, - "sale": 0, - "newStatus": 0, - "recommandStatus": 0, - "stock": 100, - "promotionType": 0, - "sort": 0, - "attrValueList": [ - { - "id": 183, - "productAttributeId": 24, - "value": null, - "type": 1, - "name": "商品编号" - }, - { - "id": 184, - "productAttributeId": 25, - "value": "夏季", - "type": 1, - "name": "适用季节" - } - ] -} -``` - -获取文档映射:`GET /pms/_mapping/product` - -按字段查询:`GET /pms/product/_search?q=subTitle:2018` - -match查询: - -```json -GET /pms/product/_search -{ - "query": { - "match": { - "brandName": "小米" - } - } -} -``` - - - - - diff --git "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" index adbb65e..633f860 100644 --- "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" @@ -13,17 +13,51 @@ - 系统可用性降低。引入消息队列之后,如果消息队列挂了,可能会影响到业务系统的可用性。 - 系统复杂性增加。加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。 -## RabbitMQ消息怎么路由? +## 常见的消息队列对比 -消息路由必须有三部分:**交换器、路由、绑定**。生产者把消息发布到交换器上;绑定决定了消息如何从路由器路由到特定的队列;消息最终到达队列,并被消费者接收。 +| 对比方向 | 概要 | +| -------- | ------------------------------------------------------------ | +| 吞吐量 | 万级的 ActiveMQ 和 RabbitMQ 的吞吐量(ActiveMQ 的性能最差)要比 十万级甚至是百万级的 RocketMQ 和 Kafka 低一个数量级。 | +| 可用性 | 都可以实现高可用。ActiveMQ 和 RabbitMQ 都是基于主从架构实现高可用性。RocketMQ 基于分布式架构。 kafka 也是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 | +| 时效性 | RabbitMQ 基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。其他三个都是 ms 级。 | +| 功能支持 | 除了 Kafka,其他三个功能都较为完备。 Kafka 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准 | +| 消息丢失 | ActiveMQ 和 RabbitMQ 丢失的可能性非常低, RocketMQ 和 Kafka 理论上不会丢失。 | -1、消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。 +**总结:** -2、通过队列路由键,可以把队列绑定到交换器上。 +- ActiveMQ 的社区算是比较成熟,但是较目前来说,ActiveMQ 的性能比较差,而且版本迭代很慢,不推荐使用。 +- RabbitMQ 在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,但是由于它基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。但是也因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做 erlang 源码级别的研究和定制。如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。 +- RocketMQ 阿里出品,Java 系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的 MQ,并且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。RocketMQ 社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准 JMS 规范走的有些系统要迁移需要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用 RocketMQ 挺好的 +- Kafka 的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。同时 kafka 最好是支撑较少的 topic 数量即可,保证其超高吞吐量。kafka 唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集。 -3、消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中。 +## MQ常用协议 -## RabbitMQ如何保证消息的顺序性? +- **AMQP协议** AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。 + + > 优点:可靠、通用 + +- **MQTT协议** MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。 + + > 优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统 + +- **STOMP协议** STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。 + + > 优点:命令模式(非topic/queue模式) + +- **XMPP协议** XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。 + + > 优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大 + +- **其他基于TCP/IP自定义的协议**:有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。 + +## MQ的通讯模式 + +1. **点对点通讯**:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。 +2. **多点广播**:MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。 +3. **发布/订阅(Publish/Subscribe)模式**:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。 +4. **集群(Cluster)**:为了简化点对点通讯模式中的系统配置,MQ提供 Cluster 的解决方案。集群类似于一个 域(Domain) ,集群内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用 Cluster 通道与其它成员通讯,从而大大简化了系统配置。此外,集群中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性 + +## 如何保证消息的顺序性? 单线程消费保证消息的顺序性;对消息进行编号,消费者根据编号处理消息。 diff --git "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" index a125d4b..cca4277 100644 --- "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" +++ "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" @@ -22,15 +22,15 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 创建一个新的仓库,用来存放项目。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822154700616.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210822154700616.png) - 或者你在GitHub上看到别人有一个超级无敌有趣的项目,可以直接fork过来,可以理解成复制过来,变成你自己的。之后你想怎么改就怎么改! - ![image-20210822155107839](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155107839.png) + ![image-20210822155107839](https://gitee.com/tysondai/img/raw/master/image-20210822155107839.png) - 然后你可以通过Git命令行`git clone xxx`把项目clone到本地,在本地进行创作。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155359118.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210822155359118.png) - 最后,在本地创作完成,可以使用`git commit -m xxx`提交到本地库,然后使用`git push`把修改推送到GitHub仓库。之后就可以在GitHub上面看到你修改的内容啦~ @@ -42,23 +42,23 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 评价GitHub项目的两个重要的参数:star和fork。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161003170.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161003170.png) 比较优秀和热门的项目,star数目和fork数目都会比较多。我们可以根据这两个参数筛选出比较好的项目。使用`关键字 stars:>=xxx forks:>=xxx` 可以筛选出star和fork数目大于xxx的相关项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161122586.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161122586.png) - 使用 `awesome 关键字`,可以筛选出比较高质量的学习、书籍、工具类或者插件类的集合。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161608599.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822161608599.png) - 在特定位置搜索关键词。有些关键词出现在项目的不同位置,比如项目名称、项目描述和README等。使用`关键词 in name/description/Readme`,可以搜索到相关的内容。比如使用`spring in name`,可以搜索到在项目名中包含spring的项目。 -![image-20210822162144086](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822162144086.png) +![image-20210822162144086](https://gitee.com/tysondai/img/raw/master/image-20210822162144086.png) - 指定条件搜索关键词。如`tool language:java`搜索到的是包含关键字tool的Java项目,`tool followers:>1000`可以搜索到包含关键字tool,且follower数量大于1000的项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822163111390.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822163111390.png) @@ -72,7 +72,7 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 文档神器。可以为自己的项目建立wiki,可以用markdown语法写wiki; -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822172419760.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210822172419760.png) - 使用GitHub pages建立个人静态网站,搞一个有自己域名的独立博客,想想都觉得开心。使用GitHub pages的好处是搭建简单而且免费,支持静态脚本,并且可以绑定自己的域名。具体可以参考:[GitHub Pages 建立个人网站详细教程 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/58229299) diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/progit2.md" index 68b8c2b..6dde18b 100644 --- "a/\345\267\245\345\205\267/progit2.md" +++ "b/\345\267\245\345\205\267/progit2.md" @@ -85,7 +85,7 @@ Git工作流程如下: Git 的工作流程图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-work-flow.png) +![](https://gitee.com/tysondai/img/raw/master/git-work-flow.png) > 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 @@ -103,11 +103,11 @@ Git 的三种状态:已修改(modified)、已暂存(staged)和已提 基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/git工作流程.png) +![](https://gitee.com/tysondai/img/raw/master/git工作流程.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-status.png) +![](https://gitee.com/tysondai/img/raw/master/git-status.png) ## 配置 @@ -156,7 +156,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](https://raw.githubusercontent.com/Tyson0314/img/master/git生命周期.png) +![git生命周期](https://gitee.com/tysondai/img/raw/master/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -262,7 +262,7 @@ git commit -m "add readme.md" 单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210830225020753.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210830225020753.png) 此时应该这么操作: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" index e9f255a..2378225 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" @@ -91,7 +91,7 @@ where blog_id = ( 三个表依次嵌套,发现最里层的子查询 `id`最大,最先执行。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-id.png) +![](https://gitee.com/tysondai/img/raw/master/explain-id.png) ## select_type @@ -107,13 +107,13 @@ where blog_id = ( 查询的表名,并不一定是真实存在的表,有别名显示别名,也可能为临时表。当from子句中有子查询时,table列是 ``的格式,表示当前查询依赖 id为N的查询,会先执行 id为N的查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804083523885.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210804083523885.png) ## partitions 查询时匹配到的分区信息,对于非分区表值为`NULL`,当查询的是分区表时,`partitions`显示分区表命中的分区情况。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802022931773.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802022931773.png) ## type @@ -123,25 +123,25 @@ where blog_id = ( 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快。比如,Mysql系统表proxies_priv在Mysql服务启动时候已经加载在内存中,对这个表进行查询不需要进行磁盘 IO。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801233419732.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210801233419732.png) ### const 单表操作的时候,查询使用了主键或者唯一索引。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-const.png) +![](https://gitee.com/tysondai/img/raw/master/explain-const.png) ### eq_ref **多表关联**查询的时候,主键和唯一索引作为关联条件。如下图的sql,对于user表(外循环)的每一行,user_role表(内循环)只有一行满足join条件,只要查找到这行记录,就会跳出内循环,继续外循环的下一轮查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801232638027.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210801232638027.png) ### ref 查找条件列使用了索引而且不为主键和唯一索引。虽然使用了索引,但该索引列的值并不唯一,这样即使使用索引查找到了第一条数据,仍然不能停止,要在目标值附近进行小范围扫描。但它的好处是不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内做扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-ref.png) +![](https://gitee.com/tysondai/img/raw/master/explain-ref.png) ### ref_or_null @@ -151,13 +151,13 @@ where blog_id = ( 使用了索引合并优化方法,查询使用了两个以上的索引。新建comment表,id为主键,value_id为非唯一索引,执行`explain select content from comment where value_id = 1181000 and id > 1000;`,执行结果显示查询同时使用了id和value_id索引,type列的值为index_merge。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802001215614.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802001215614.png) ### range 有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。像between、and、'>'、'<'、in和or都是范围索引扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-range.png) +![](https://gitee.com/tysondai/img/raw/master/explain-range.png) ### index @@ -165,17 +165,17 @@ index包括select索引列,order by主键两种情况。 1. order by主键。这种情况会按照索引顺序全表扫描数据,拿到的数据是按照主键排好序的,不需要额外进行排序。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225045980.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210801225045980.png) 2. select索引列。type为index,而且extra字段为using index,也称这种情况为索引覆盖。所需要取的数据都在索引列,无需回表查询。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225942948.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210801225942948.png) ### all 全表扫描,查询没有用到索引,性能最差。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-all.png) +![](https://gitee.com/tysondai/img/raw/master/explain-all.png) ## possible_keys @@ -249,13 +249,13 @@ CREATE TABLE `t_orderdetail` ( 查询的列未被索引覆盖,where筛选条件非索引的前导列。对存储引擎返回的结果进行过滤(Post-filter,后过滤),一般发生在MySQL服务器,而不是存储引擎层。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232729417.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802232729417.png) ### using index 查询的列被索引覆盖,并且where筛选条件符合最左前缀原则,通过**索引查找**就能直接找到符合条件的数据,不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232357282.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802232357282.png) ### Using where&Using index @@ -265,17 +265,17 @@ CREATE TABLE `t_orderdetail` ( - where筛选条件不符合最左前缀原则 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233120283.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210802233120283.png) - where筛选条件是索引列前导列的一个范围 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233455880.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210802233455880.png) ### null 查询的列未被索引覆盖,并且where筛选条件是索引的前导列,也就是用到了索引,但是部分字段未被索引覆盖,必须回表查询这些字段,Extra中为NULL。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802234122321.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210802234122321.png) ### using index condition @@ -283,11 +283,11 @@ CREATE TABLE `t_orderdetail` ( 不使用ICP的情况(`set optimizer_switch='index_condition_pushdown=off'`),如下图,在步骤4中,没有使用where条件过滤索引: -![](https://raw.githubusercontent.com/Tyson0314/img/master/no-icp.png) +![](https://gitee.com/tysondai/img/raw/master/no-icp.png) 使用ICP的情况(`set optimizer_switch='index_condition_pushdown=on'`): -![](https://raw.githubusercontent.com/Tyson0314/img/master/icp.png) +![](https://gitee.com/tysondai/img/raw/master/icp.png) 下面的例子使用了ICP: @@ -296,11 +296,11 @@ explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G; ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084617433.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210803084617433.png) 关掉ICP之后(`set optimizer_switch='index_condition_pushdown=off'`),可以看到extra列为using where,不会使用索引下推。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084815503.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210803084815503.png) ### using temporary @@ -314,7 +314,7 @@ from t_order where user_id > 1 and user_id < 5\G; - select 查询字段不全是索引字段 - select 查询字段都是索引字段,但是 order by 字段和索引字段的顺序不一致 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804084029239.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210804084029239.png) ### using join buffer diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" index 7caa4e5..4ff8a64 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" @@ -138,7 +138,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821165019147.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210821165019147.png) 进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的数据项。 @@ -170,15 +170,15 @@ Index_comment: 如下图,col1 是主键,col2和col3是普通字段。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234137916.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234137916.png) 下图是主键索引对应的 B+树结构,每个节点对应磁盘的一页。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234200868.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234200868.png) 对col3 建立一个单列索引,对应的B+树结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234231001.png) +![](https://gitee.com/tysondai/img/raw/master/image-20200520234231001.png) ### 索引分类 1. 主键索引:名为primary的唯一非空索引,不允许有空值。 @@ -208,7 +208,7 @@ Index_comment: 对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会对b进行比较排序)。直接执行`b = 2`这种查询条件没有办法利用索引。 -![最左匹配](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821103313578.png) +![最左匹配](https://gitee.com/tysondai/img/raw/master/image-20210821103313578.png) 从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行`a = 1 and b = 2`是a,b字段能用到索引的。而你执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。 @@ -218,7 +218,7 @@ InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的 聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-clustered-index.png) +![](https://gitee.com/tysondai/img/raw/master/mysql-clustered-index.png) 对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。 @@ -244,7 +244,7 @@ explain select user_id from user_like where blog_id = 1; Extra中为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](https://gitee.com/tysondai/img/raw/master/cover-index.png) ### 索引失效 @@ -322,7 +322,7 @@ MEMORY引擎默认使用哈希索引,将键的哈希值和指向数据行的 myisam引擎主键索引和其他索引区别不大,叶子节点都包含索引值和行指针。 innodb引擎二级索引叶子存储的是索引值和主键值(不是行指针),这样可以减少行移动和数据页分裂时二级索引的维护工作。 - ![myisam-innodb-index](https://raw.githubusercontent.com/Tyson0314/img/master/myisam-innodb-index.png) + ![myisam-innodb-index](https://gitee.com/tysondai/img/raw/master/myisam-innodb-index.png) @@ -351,7 +351,7 @@ mvcc实现依赖于版本链,版本链是通过表的三个隐藏字段实现 3. 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链; 4. 记录redo log; -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc-impl.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc-impl.png) ### read view @@ -388,14 +388,14 @@ repeatable read:在一个事务范围内,第一次select时更新这个read_ 事务a和事务b同时开启事务,事务a插入数据然后提交,事务b执行全表的update,然后执行查询,查到了事务A中添加的数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](https://gitee.com/tysondai/img/raw/master/幻读1.png) MySQL如何实现避免幻读: - 在快照读情况下,MySQL通过mvcc来避免幻读。 - 在当前读情况下,MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/current-read.png) +![](https://gitee.com/tysondai/img/raw/master/current-read.png) next-key包括两部分:行锁和间隙锁。行锁是加在索引上的锁,间隙锁是加在索引之间的。 @@ -531,7 +531,7 @@ MySQL主要分为 Server 层和存储引擎层: - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 - **存储引擎**: 主要负责数据的存储和读取。server 层通过api与存储引擎进行通信。 -![MySQL-archpng](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-archpng.png) +![MySQL-archpng](https://gitee.com/tysondai/img/raw/master/mysql-archpng.png) ### Server 层基本组件 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 2a8d716..f872daa 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -179,7 +179,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 `key` 从左到右递增排列,如果某个指针的左右相邻 `key` 分别是 keyi 和 keyi+1,则该指针指向节点的所有 `key` 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/B+树索引0.png) +![](https://gitee.com/tysondai/img/raw/master/B+树索引0.png) 进行查找操作时,首先在根节点进行二分查找,找到`key`所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出`key`所对应的数据项。 @@ -228,7 +228,7 @@ Index_comment: 1、**主键索引**:名为primary的唯一非空索引,不允许有空值。 -2、**唯一索引**:索引列中的值必须是唯一的,但是允许为空值。唯一索引和主键索引的区别是:唯一约束的列可以为`null`且可以存在多个`null`值。唯一索引的用途:唯一标识数据库表中的每条记录,主要是用来防止数据重复插入。创建唯一索引的SQL语句如下: +2、**唯一索引**:索引列中的值必须是唯一的,但是允许为空值。唯一索引和主键索引的区别是:唯一索引字段可以为null且可以存在多个null值,而主键索引字段不可以为null。唯一索引的用途:唯一标识数据库表中的每条记录,主要是用来防止数据重复插入。创建唯一索引的SQL语句如下: ```mysql ALTER TABLE table_name @@ -239,6 +239,8 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 4、**全文索引**:只能在`CHAR`、`VARCHAR`和`TEXT`类型字段上使用全文索引。 +5、**普通索引**:普通索引是最基本的索引,它没有任何限制,值可以为空。 + ### 什么是最左匹配原则? 如果 SQL 语句中用到了组合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个组合索引去进行匹配。当遇到范围查询(`>`、`<`、`between`、`like`)就会停止匹配,后面的字段不会用到索引。 @@ -249,7 +251,7 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 如下图,对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会根据b进行排序)。直接执行`b = 2`这种查询条件无法使用索引。 -![最左前缀](https://raw.githubusercontent.com/Tyson0314/img/master/最左前缀.png) +![最左前缀](https://gitee.com/tysondai/img/raw/master/最左前缀.png) 当a的值确定的时候,b是有序的。例如`a = 1`时,b值为1,2是有序的状态。当`a = 2`时候,b的值为1,4也是有序状态。 当执行`a = 1 and b = 2`时a和b字段能用到索引。而执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段无法使用索引。 @@ -283,7 +285,7 @@ explain select user_id from user_like where blog_id = 1; `explain`结果的`Extra`列为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](https://gitee.com/tysondai/img/raw/master/cover-index.png) ### 索引的设计原则? @@ -393,7 +395,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 每条表记录大概是这样的: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc9.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc9.png) 使用事务更新行记录的时候,就会生成版本链,执行过程如下: @@ -405,15 +407,15 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、初始数据如下,其中`DB_ROW_ID`和`DB_ROLL_PTR`为空。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc2.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc2.png) 2、事务A对该行数据做了修改,将`age`修改为12,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc7.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc7.png) 3、之后事务B也对该行记录做了修改,将`age`修改为8,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc11.png) +![](https://gitee.com/tysondai/img/raw/master/mvcc11.png) 4、此时undo log有两行记录,并且通过回滚指针连在一起。 @@ -433,7 +435,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 **前提**:`DATA_TRX_ID` 表示每个数据行的最新的事务ID;`up_limit_id`表示当前快照中的最先开始的事务;`low_limit_id`表示当前快照中的最慢开始的事务,即最后一个事务。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/read_view10.png) +![](https://gitee.com/tysondai/img/raw/master/read_view10.png) - 如果`DATA_TRX_ID` < `up_limit_id`:说明在创建`read view`时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。 - 如果`DATA_TRX_ID` >= `low_limit_id`:说明当前版本的记录的事务是在创建`read view`之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。 @@ -458,7 +460,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、首先,user表只有两条记录,具体如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210922232259664.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210922232259664.png) 2、事务a和事务b同时开启事务`start transaction`; @@ -476,7 +478,7 @@ update user set user_name = 'a'; 5、事务b然后执行查询,查到了事务a中插入的数据。(下图左边是事务b,右边是事务a。事务开始之前只有两条记录,事务a插入一条数据之后,事务b查询出来是三条数据) -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](https://gitee.com/tysondai/img/raw/master/幻读1.png) 以上就是当前读出现的幻读现象。 @@ -565,7 +567,7 @@ MySQL主要分为 Server 层和存储引擎层: 垂直划分数据库是根据业务进行划分,例如购物场景,可以将库中涉及商品、订单、用户的表分别划分出成一个库,通过降低单库的大小来提高性能。同样的,分表的情况就是将一个大表根据业务功能拆分成一个个子表,例如商品基本信息和商品描述,商品基本信息一般会展示在商品列表,商品描述在商品详情页,可以将商品基本信息和商品描述拆分成两张表。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/垂直划分.png) +![](https://gitee.com/tysondai/img/raw/master/垂直划分.png) **优点**:行记录变小,数据页可以存放更多记录,在查询时减少I/O次数。 @@ -579,7 +581,7 @@ MySQL主要分为 Server 层和存储引擎层: 水平划分是根据一定规则,例如时间或id序列值等进行数据的拆分。比如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,从而提升性能。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/水平划分.png) +![](https://gitee.com/tysondai/img/raw/master/水平划分.png) **优点**:单库(表)的数据量得以减少,提高性能;切分出的表结构相同,程序改动较少。 @@ -784,3 +786,101 @@ int(10)中的10表示的是显示数据的长度,而char(10)表示的是存储 - Sorting for order,正在为`ORDER BY`做排序 8. **info**:正在执行的`SQL`语句 +## MySQL查询 limit 1000,10 和limit 10 速度一样快吗? + +两种查询方式。对应 `limit offset, size` 和 `limit size` 两种方式。 + +而其实 `limit size` ,相当于 `limit 0, size`。也就是从0开始取size条数据。 + +也就是说,两种方式的**区别在于offset是否为0。** + +先来看下limit sql的内部执行逻辑。 + +MySQL内部分为**server层**和**存储引擎层**。一般情况下存储引擎都用innodb。 + +server层有很多模块,其中需要关注的是**执行器**是用于跟存储引擎打交道的组件。 + +执行器可以通过调用存储引擎提供的接口,将一行行数据取出,当这些数据完全符合要求(比如满足其他where条件),则会放到**结果集**中,最后返回给调用mysql的**客户端**。 + +以主键索引的limit执行过程为例: + +执行`select * from page order by id limit 0, 10;`,select后面带的是**星号**,也就是要求获得行数据的**所有字段信息。** + +server层会调用innodb的接口,在innodb里的主键索引中获取到第0到10条**完整行数据**,依次返回给server层,并放到server层的结果集中,返回给客户端。 + +把offset搞大点,比如执行的是:`select * from page order by id limit 500000, 10;` + +server层会调用innodb的接口,由于这次的offset=500000,会在innodb里的主键索引中获取到第0到(500000 + 10)条**完整行数据**,**返回给server层之后根据offset的值挨个抛弃,最后只留下最后面的size条**,也就是10条数据,放到server层的结果集中,返回给客户端。 + +可以看出,当offset非0时,server层会从引擎层获取到**很多无用的数据**,而获取的这些无用数据都是要耗时的。 + +因此,mysql查询中 limit 1000,10 会比 limit 10 更慢。原因是 limit 1000,10 会取出1000+10条数据,并抛弃前1000条,这部分耗时更大。 + +## 深分页怎么优化? + +还是以上面的SQL为空:`select * from page order by id limit 500000, 10;` + +**方法一**: + +从上面的分析可以看出,当offset非常大时,server层会从引擎层获取到很多无用的数据,而当select后面是*号时,就需要拷贝完整的行信息,**拷贝完整数据**相比**只拷贝行数据里的其中一两个列字段**更耗费时间。 + +因为前面的offset条数据最后都是不要的,没有必要拷贝完整字段,所以可以将sql语句修改成: + +```mysql +select * from page where id >=(select id from page order by id limit 500000, 1) order by id limit 10; +``` + +先执行子查询 `select id from page order by id limit 500000, 1`, 这个操作,其实也是将在innodb中的主键索引中获取到`500000+1`条数据,然后server层会抛弃前500000条,只保留最后一条数据的id。 + +但不同的地方在于,在返回server层的过程中,只会拷贝数据行内的id这一列,而不会拷贝数据行的所有列,当数据量较大时,这部分的耗时还是比较明显的。 + +在拿到了上面的id之后,假设这个id正好等于500000,那sql就变成了 + +```mysql +select * from page where id >=500000 order by id limit 10; +``` + +这样innodb再走一次**主键索引**,通过B+树快速定位到id=500000的行数据,时间复杂度是lg(n),然后向后取10条数据。 + +**方法二:** + +将所有的数据**根据id主键进行排序**,然后分批次取,将当前批次的最大id作为下次筛选的条件进行查询。 + +```mysql +select * from page where id > start_id order by id limit 10; +``` + +通过主键索引,每次定位到start_id的位置,然后往后遍历10个数据,这样不管数据多大,查询性能都较为稳定。 + +## B+树一个节点有多大?一千万条数据,B+树多高? + +InnoDB存储引擎有自己的最小储存单元——页(Page),一个页的大小是16K。 + +B+树一个节点的大小设为一页或页的倍数最为合适。因为如果一个节点的大小 < 1页,那么读取这个节点的时候其实读取的还是一页,这样就造成了资源的浪费。 + +在 MySQL 中 B+ 树的一个节点大小为“1页”,也就是16k。之所以设置为一页,是因为对于大部分业务,一页就足够了: + +首先InnoDB的B+树中,**非叶子节点存的是key + 指针**;**叶子节点存的是数据行**。 + +对于叶子节点,如果一行数据大小为1k,那么一页就能存16条数据。 + +对于非叶子节点,如果key使用的是bigint,则为8字节,指针在mysql中为6字节,一共是14字节,则16k能存放 16 * 1024 / 14 = 1170 个索引指针。 + +于是可以算出,对于一颗高度为2的B+树,根节点存储索引指针节点,那么它有1170个叶子节点存储数据,每个叶子节点可以存储16条数据,一共 1170 x 16 = 18720 条数据。而对于高度为3的B+树,就可以存放 1170 x 1170 x 16 = 21902400 条数据(**两千多万条数据**),也就是对于两千多万条的数据,我们只需要**高度为3**的B+树就可以完成,通过主键查询只需要3次IO操作就能查到对应数据。 + +所以在 InnoDB 中B+树高度一般为3层时,就能满足千万级的数据存储,所以一个节点为1页,也就是16k是比较合理的。 + +参考:https://www.cnblogs.com/leefreeman/p/8315844.html + +## MySQL单表多大进行分库分表? + +目前主流的有两种说法: + +1. MySQL 单表数据量大于 2000 万行,性能会明显下降,考虑进行分库分表。 +2. 阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 + +事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为,MySQL 为了提高性能,会将表的索引装载到内存中。InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。 + +因此,对于分库分表,需要结合实际需求,不宜过度设计,在项目一开始不采用分库与分表设计,而是随着业务的增长,在无法继续优化的情况下,再考虑分库与分表提高系统的性能。对此,阿里巴巴《Java 开发手册》补充到:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 + +至于MySQL单表多大进行分库分表,应当根据机器资源进行评估。 diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" index 9ad4fb0..9a99fb1 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -13,7 +13,7 @@ 常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) +![](https://gitee.com/tysondai/img/raw/master/排序算法.png) ## 冒泡排序 diff --git "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" new file mode 100644 index 0000000..21e911b --- /dev/null +++ "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" @@ -0,0 +1,117 @@ +## Mybatis框架简介 + +- MyBatis框架是一个开源的数据持久层框架。 +- 它的内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。 +- MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在配置文件当中,实现SQL的灵活配置。 +- 这样做的好处是将SQL与程序代码分离,可以在不修改代码的情况下,直接在配置文件当中修改SQL。 + +## MyBatis框架的优缺点及其适用的场合 + +**优点** + +1. 与JDBC相比,减少了50%以上的代码量。 +2. MyBatis是易学的持久层框架,小巧并且简单易学。 +3. MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML文件里,从程序代码中彻底分离,降低耦合度,便于统一的管理和优化,并可重用。 +4. 提供XML标签,支持编写动态的SQL,满足不同的业务需求。 +5. 提供映射标签,支持对象与数据库的ORM字段关系映射。 + +**缺点** + +1. SQL语句的编写工作量较大,对开发人员编写SQL的能力有一定的要求。 +2. SQL语句依赖于数据库,导致数据库不具有好的移植性,不可以随便更换数据库。 + +**适用场景** + +MyBatis专注于SQL自身,是一个足够灵活的DAO层解决方案。对性能的要求很高,或者需求变化较多的项目,例如Web项目,那么MyBatis是不二的选择。 + +## Mybatis的工作原理 + +- 读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。 +- 加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。 +- 构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。 +- 创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。 +- Executor执行器:MyBatis底层定义了一个Executor 接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。 +- MappedStatement 对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。 +- 输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于 JDBC对preparedStatement对象设置参数的过程。 +- 输出结果映射:输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于 JDBC对结果集的解析过程。 + +## Mybatis都有哪些Executor执行器?它们之间的区别是什么? + +Mybatis有三种基本的Executor执行器,`SimpleExecutor`、`ReuseExecutor`、`BatchExecutor`。 + +`SimpleExecutor`:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。 + +`ReuseExecutor`:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。 + +`BatchExecutor`:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。 + +作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。 + +## MyBatis中接口绑定有几种实现方式? + +1. 通过注解绑定,在接口的方法上面加上 @Select@Update等注解里面包含Sql语句来绑定(SQL语句比较简单的时候,推荐注解绑定) +2. 通过xml里面写SQL来绑定, 指定xml映射文件里面的namespace必须为接口的全路径名(SQL语句比较复杂的时候,推荐xml绑定) + +## 简述Mybatis的插件运行原理 + +Mybatis仅可以编写针对 `ParameterHandler`、`ResultSetHandler`、`StatementHandler`、`Executor`这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是`InvocationHandler`的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。 + +编写插件:实现Mybatis的Interceptor接口并复写`intercept()`方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。 + +## #{}和${}的区别是什么? + +#{ } 被解析成预编译语句,预编译之后可以直接执行,不需要重新编译sql。 + +```mysql +//sqlMap 中如下的 sql 语句 +select * from user where name = #{name}; +//解析成为预编译语句;编译好SQL语句再取值 +select * from user where name = ?; +``` + +${ } 仅仅为一个字符串替换,每次执行sql之前需要进行编译,存在 sql 注入问题。 + +```mysql +select * from user where name = '${name}' +//传递的参数为 "ruhua" 时,解析为如下,然后发送数据库服务器进行编译。取值以后再去编译SQL语句。 +select * from user where name = "ruhua"; +``` + +## Mybatis的预编译 + +数据库接受到sql语句之后,需要词法和语义解析,优化sql语句,制定执行计划。这需要花费一些时间。如果一条sql语句需要反复执行,每次都进行语法检查和优化,会浪费很多时间。预编译语句就是将sql语句中的`值用占位符替代`,即将`sql语句模板化`。一次编译、多次运行,省去了解析优化等过程。 + +mybatis是通过`PreparedStatement`和占位符来实现预编译的。 + +mybatis底层使用`PreparedStatement`,默认情况下,将对所有的 sql 进行预编译,将#{}替换为?,然后将带有占位符?的sql模板发送至mysql服务器,由服务器对此无参数的sql进行编译后,将编译结果缓存,然后直接执行带有真实参数的sql。 + +预编译的作用: + +1. 预编译阶段可以优化 sql 的执行。预编译之后的 sql 多数情况下可以直接执行,数据库服务器不需要再次编译,可以提升性能。 +2. 预编译语句对象可以重复利用。把一个 sql 预编译后产生的 `PreparedStatement` 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。 +3. 防止SQL注入。使用预编译,而其后注入的参数将`不会再进行SQL编译`。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数。 + + ## 一级缓存和二级缓存 + +缓存:合理使用缓存是优化中最常见的方法之一,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。 + +**一级缓存是SqlSession级别的缓存**:Mybatis对缓存提供支持,默认情况下只开启一级缓存,一级缓存作用范围为同一个SqlSession。在SQL和参数相同的情况下,我们使用同一个SqlSession对象调用同一个Mapper方法,往往只会执行一次SQL。因为在使用SqlSession第一次查询后,Mybatis会将结果放到缓存中,以后再次查询时,如果没有声明需要刷新,并且缓存没超时的情况下,SqlSession只会取出当前缓存的数据,不会再次发送SQL到数据库。若使用不同的SqlSession,因为不同的SqlSession是相互隔离的,不会使用一级缓存。 + +**二级缓存是mapper级别的缓存**:可以使缓存在各个SqlSession之间共享。二级缓存默认不开启,需要在mybatis-config.xml开启二级缓存: + +```xml + + + + +``` + +并在相应的Mapper.xml文件添加cache标签,表示对哪个mapper 开启缓存: + +```xml + +``` + +二级缓存要求返回的POJO必须是可序列化的,即要求实现Serializable接口。 + +当开启二级缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。 diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index e9ddb23..dd8b7fb 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -28,7 +28,7 @@ SpringBoot实现自动配置原理图解: > 公众号【程序员大彬】,回复【自动配置】下载高清图片 -![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) +![](https://gitee.com/tysondai/img/raw/master/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" index ed70b24..6d305f7 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" @@ -98,10 +98,20 @@ springcloud是一个基于Spring Boot实现的微服务架构开发工具。spri - Spring Cloud Cluster: 针对ZooKeeper、Redis、Hazelcast、Consul 的选举算法和通用状态模式的实现。 - Spring Cloud Consul: 服务发现与配置管理工具。 - Spring Cloud ZooKeeper: 基于ZooKeeper 的服务发现与配置管理组件。 +- Spring Cloud Security:Spring Security组件封装,提供用户验证和权限验证,一般与Spring Security OAuth2 组一起使用,通过搭建授权服务,验证Token或者JWT这种形式对整个微服务系统进行安全验证 +- Spring Cloud Sleuth:分布式链路追踪组件,他分封装了Dapper、Zipkin、Kibana 的组件 +- Spring Cloud Stream:Spring Cloud框架的数据流操作包,可以封装RabbitMq,ActiveMq,Kafka,Redis等消息组件,利用Spring Cloud Stream可以实现消息的接收和发送 spring-boot-starter-actuator:该模块能够自动为Spring Boot 构建的应用提供一系列用于监控的端点。 +## 说说对SpringBoot 和SpringCloud的理解 +- SpringBoot专注于快速方便的开发单个个体微服务。 +- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 +- SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系。 +- SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。 + +Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。 ## Spring Cloud Eureka diff --git "a/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" new file mode 100644 index 0000000..82ac987 --- /dev/null +++ "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" @@ -0,0 +1,88 @@ +## 说说你对 SpringMVC 的理解 + +SpringMVC是一种基于 Java 的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring框架的一个模块。 + +它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。 + +## 什么是MVC模式? + +MVC的全名是`Model View Controller`,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。 + +View,视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。 + +model,模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。 + +controller,控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。 + +## SpringMVC 有哪些优点? + +1. 与 Spring 集成使用非常方便,生态好。 +2. 配置简单,快速上手。 +3. 支持 RESTful 风格。 +4. 支持各种视图技术,支持各种请求资源映射策略。 + +## Spring MVC和Struts的区别 + +1. Spring MVC是基于方法开发,Struts2是基于类开发的。 + - Spring MVC会将用户请求的URL路径信息与Controller的某个方法进行映射,所有请求参数会注入到对应方法的形参上,生成Handler对象,对象中只有一个方法; + - Struts每处理一次请求都会实例一个Action,Action类的所有方法使用的请求参数都是Action类中的成员变量,随着方法增多,整个Action也会变得混乱。 +2. Spring MVC支持单例开发模式,Struts只能使用多例 + + - Struts由于只能通过类的成员变量接收参数,故只能使用多例。 +3. Struts2 的核心是基于一个Filter即StrutsPreparedAndExcuteFilter,Spring MVC的核心是基于一个Servlet即DispatcherServlet(前端控制器)。 +4. Struts处理速度稍微比Spring MVC慢,Struts使用了Struts标签,加载数据较慢。 + +## Spring MVC的工作原理 + +Spring MVC的工作原理如下: + +1. DispatcherServlet 接收用户的请求 +2. 找到用于处理request的 handler 和 Interceptors,构造成 HandlerExecutionChain 执行链 +3. 找到 handler 相对应的 HandlerAdapter +4. 执行所有注册拦截器的preHandler方法 +5. 调用 HandlerAdapter 的 handle() 方法处理请求,返回 ModelAndView +6. 倒序执行所有注册拦截器的postHandler方法 +7. 请求视图解析和视图渲染 + +![Spring MVC处理流程](https://img-blog.csdnimg.cn/20190125180502787.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==,size_16,color_FFFFFF,t_70) + +## Spring MVC的主要组件? + +- 前端控制器(DispatcherServlet):接收用户请求,给用户返回结果。 +- 处理器映射器(HandlerMapping):根据请求的url路径,通过注解或者xml配置,寻找匹配的Handler。 +- 处理器适配器(HandlerAdapter):Handler 的适配器,调用 handler 的方法处理请求。 +- 处理器(Handler):执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装到ModelAndView对象中。 +- 视图解析器(ViewResolver):将逻辑视图名解析成真正的视图View。 +- 视图(View):接口类,实现类可支持不同的View类型(JSP、FreeMarker、Excel等)。 + +## Spring MVC的常用注解由有哪些? +- @Controller:用于标识此类的实例是一个控制器。 +- @RequestMapping:映射Web请求(访问路径和参数)。 +- @ResponseBody:注解返回数据而不是返回页面 +- @RequestBody:注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。 +- @PathVariable:获得URL中路径变量中的值 +- @RestController:@Controller+@ResponseBody + +## Spring MVC的异常处理 + +可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。 + +- 使用系统定义好的异常处理器 SimpleMappingExceptionResolver +- 使用自定义异常处理器 +- 使用异常处理注解 + +## SpringMVC 用什么对象从后台向前台传递数据的? + +1. 将数据绑定到 request; +2. 返回 ModelAndView; +3. 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前端就可以通过el表达式拿到; +4. 绑定数据到 Session中。 + +## RequestBody和RequestParam的区别 + +@RequestBody一般处理的是在ajax请求中声明contentType: "application/json; charset=utf-8"时候。也就是json数据或者xml数据。 + +@RequestParam一般就是在ajax里面没有声明contentType的时候,为默认的`x-www-form-urlencoded`格式时。 + + + diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index 641525e..ae4a031 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -216,7 +216,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](https://raw.githubusercontent.com/Tyson0314/img/master/bean生命周期.png) +![](https://gitee.com/tysondai/img/raw/master/bean生命周期.png) 1.调用bean的构造方法创建Bean diff --git "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" index 60a94c1..0320b99 100644 --- "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" +++ "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" @@ -333,7 +333,7 @@ HTTP长连接,指的是复用TCP连接。多个HTTP请求可以复用同一个 CDN用户访问流程: -![cdn](https://raw.githubusercontent.com/Tyson0314/img/master/cdn.png) +![cdn](https://gitee.com/tysondai/img/raw/master/cdn.png) 1.用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有dns缓存,则向网站的DNS服务器请求; diff --git "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 48969f2..2fb8b79 100644 --- "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -38,7 +38,7 @@ 计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/tcp5layer2.png) +![](https://gitee.com/tysondai/img/raw/master/tcp5layer2.png) 五层模型:应用层、传输层、网络层、数据链路层、物理层。 @@ -52,7 +52,7 @@ 假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是`CLOSED`。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/三次握手图解.png) +![](https://gitee.com/tysondai/img/raw/master/三次握手图解.png) 1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位`SYN=1`,序列号`seq=x`。第一次握手前客户端的状态为`CLOSE`,第一次握手后客户端的状态为`SYN-SENT`。此时服务端的状态为`LISTEN`。 2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位`SYN=1`,`ACK=1`,序列号`seq=y`,确认号`ack=x+1`。第二次握手前服务端的状态为`LISTEN`,第二次握手后服务端的状态为`SYN-RCVD`,此时客户端的状态为`SYN-SENT`。(其中`SYN=1`表示要和客户端建立一个连接,`ACK=1`表示确认序号有效) @@ -69,7 +69,7 @@ ## 四次挥手 -![](https://raw.githubusercontent.com/Tyson0314/img/master/四次挥手0.png) +![](https://gitee.com/tysondai/img/raw/master/四次挥手0.png) 1. A的应用进程先向其TCP发出连接释放报文段(`FIN=1,seq=u`),并停止再发送数据,主动关闭TCP连接,进入`FIN-WAIT-1`(终止等待1)状态,等待B的确认。 2. B收到连接释放报文段后即发出确认报文段(`ACK=1,ack=u+1,seq=v`),B进入`CLOSE-WAIT`(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 @@ -152,7 +152,7 @@ Content-Length:112 ## HTTP状态码有哪些? -![](https://raw.githubusercontent.com/Tyson0314/img/master/http-status-code.png) +![](https://gitee.com/tysondai/img/raw/master/http-status-code.png) ## POST和GET的区别? @@ -194,7 +194,7 @@ HTTP2.0相比HTTP1.1支持的特性: 服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:**证书内容、证书签名算法和签名**,签名是为了验证身份。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004111441594.png) +![](https://gitee.com/tysondai/img/raw/master/image-20211004111441594.png) 服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。 @@ -216,29 +216,29 @@ HTTP2.0相比HTTP1.1支持的特性: 1. **协商加密算法** 。在`Client Hello`里面客户端会告知服务端自己当前的一些信息,包括客户端要使用的TLS版本,支持的加密算法,要访问的域名,给服务端生成的一个随机数(Nonce)等。需要提前告知服务器想要访问的域名以便服务器发送相应的域名的证书过来。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921104210833.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921104210833.png) 2. 服务端响应`Server Hello`,告诉客户端服务端**选中的加密算法**。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105450791.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921105450791.png) 3. 接着服务端给客户端发来了2个证书。第二个证书是第一个证书的签发机构(CA)的证书。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004172007102.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20211004172007102.png) 4. 客户端使用证书的认证机构CA公开发布的RSA公钥**对该证书进行验证**,下图表明证书认证成功。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105929268.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921105929268.png) 5. 验证通过之后,浏览器和服务器通过**密钥交换算法**产生共享的**对称密钥**。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110025197.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110025197.png) - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110155075.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110155075.png) 6. 开始传输数据,使用同一个对称密钥来加解密。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110315068.png) + ![](https://gitee.com/tysondai/img/raw/master/image-20210921110315068.png) ## DNS 的解析过程? @@ -257,7 +257,7 @@ HTTP2.0相比HTTP1.1支持的特性: 4. 服务器**响应请求**,返回响应数据。 5. 浏览器**解析响应内容,进行渲染**,呈现给用户。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/输入url返回页面过程1.png) +![](https://gitee.com/tysondai/img/raw/master/输入url返回页面过程1.png) ## 什么是cookie和session? @@ -265,7 +265,7 @@ HTTP2.0相比HTTP1.1支持的特性: 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 **cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cookie.png) +![](https://gitee.com/tysondai/img/raw/master/cookie.png) **cookie工作流程**: @@ -274,7 +274,7 @@ HTTP2.0相比HTTP1.1支持的特性: 3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 **session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/session.png) +![](https://gitee.com/tysondai/img/raw/master/session.png) ## Cookie和Session的区别? @@ -293,7 +293,7 @@ HTTP2.0相比HTTP1.1支持的特性: TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921112213523.png) +![](https://gitee.com/tysondai/img/raw/master/image-20210921112213523.png) TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。 @@ -302,7 +302,7 @@ TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最 防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/拥塞控制.jpg) +![](https://gitee.com/tysondai/img/raw/master/拥塞控制.jpg) ### 慢开始 From 156db24662d9c971173edfdf1c30c36662976135 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 22 May 2022 20:14:47 +0800 Subject: [PATCH 05/84] update --- Java/JVM.md | 32 ++++++------ ...21\351\235\242\350\257\225\351\242\230.md" | 14 +++--- "Java/Java\345\237\272\347\241\200.md" | 10 ++-- ...00\351\235\242\350\257\225\351\242\230.md" | 8 +-- ...21\351\235\242\350\257\225\351\242\230.md" | 12 ++--- ...10\351\235\242\350\257\225\351\242\230.md" | 8 +-- "Java/\345\271\266\345\217\221.md" | 22 ++++----- "Java/\351\233\206\345\220\210.md" | 8 +-- .../RabbitMQ.md" | 10 ++-- ...07\345\215\227\346\200\273\347\273\223.md" | 16 +++--- ...is\351\235\242\350\257\225\351\242\230.md" | 10 ++-- .../GitHub\346\214\207\345\215\227.md" | 18 +++---- "\345\267\245\345\205\267/progit2.md" | 10 ++-- ...47\350\241\214\350\256\241\345\210\222.md" | 44 ++++++++--------- .../MySQL\350\277\233\351\230\266.md" | 24 ++++----- ...21\351\235\242\350\257\225\351\242\230.md" | 49 ++++++++++++------- ...43\347\240\201\345\256\236\347\216\260.md" | 2 +- ...25\351\242\230\346\200\273\347\273\223.md" | 2 +- ...ng\351\235\242\350\257\225\351\242\230.md" | 2 +- .../\347\275\221\347\273\234.md" | 2 +- ...21\351\235\242\350\257\225\351\242\230.md" | 34 ++++++------- 21 files changed, 174 insertions(+), 163 deletions(-) diff --git a/Java/JVM.md b/Java/JVM.md index 74430f8..05f5634 100644 --- a/Java/JVM.md +++ b/Java/JVM.md @@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。 JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 -![image-20210905150636105](https://gitee.com/tysondai/img/raw/master/image-20210905150636105.png) +![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png) > 图片来源:深入理解Java虚拟机-周志明 @@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -![](https://gitee.com/tysondai/img/raw/master/string-new.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png) -![](https://gitee.com/tysondai/img/raw/master/string-intern.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png) -![](https://gitee.com/tysondai/img/raw/master/string-equal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png) > 图片来源:https://blog.csdn.net/soonfly @@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对 - 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 -![](https://gitee.com/tysondai/img/raw/master/object-handle.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png) - 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 -![](https://gitee.com/tysondai/img/raw/master/direct-pointer.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png) @@ -245,7 +245,7 @@ ClassFile { 加载、验证、准备、解析、初始化、使用和卸载。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905002423703.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png) ## 类加载的过程 @@ -281,7 +281,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905002827546.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png) 双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 @@ -339,7 +339,7 @@ public abstract class ClassLoader { 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 -![](https://gitee.com/tysondai/img/raw/master/object-dead.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png) ### 引用计数法 @@ -365,7 +365,7 @@ public class ReferenceCountingGc { 通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://gitee.com/tysondai/img/raw/master/gc-root-refer.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png) #### 可作为GC Roots的对象 @@ -469,13 +469,13 @@ public class ReferenceCountingGc { 标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905003458130.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png) ### 复制清除算法 半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 -![](https://gitee.com/tysondai/img/raw/master/image-20210905003714551.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png) 特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 @@ -534,7 +534,7 @@ java -XX:+PrintCommandLineFlags -version 单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 -![](https://gitee.com/tysondai/img/raw/master/serial-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png) 特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 @@ -542,7 +542,7 @@ java -XX:+PrintCommandLineFlags -version Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 -![](https://gitee.com/tysondai/img/raw/master/parnew-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png) 除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 @@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时 - 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 - 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 -![](https://gitee.com/tysondai/img/raw/master/cms-collector.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png) 由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 @@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应 G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 -![](https://gitee.com/tysondai/img/raw/master/g1-region.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg) G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 7ccae91..e4bddb5 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -49,7 +49,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 -![](https://gitee.com/tysondai/img/raw/master/jvm内存结构0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png) ### 程序计数器 @@ -185,7 +185,7 @@ ClassFile { 类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。 -![](https://gitee.com/tysondai/img/raw/master/类加载.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png) **加载** @@ -213,7 +213,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://gitee.com/tysondai/img/raw/master/双亲委派.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png) 双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下: @@ -312,7 +312,7 @@ public class ReferenceCount { 通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://gitee.com/tysondai/img/raw/master/可达性分析0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png) ## 可作为GC Roots的对象有哪些? @@ -413,7 +413,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**。 -![](https://gitee.com/tysondai/img/raw/master/标记清除.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png) **复制清除算法** @@ -425,7 +425,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 -![](https://gitee.com/tysondai/img/raw/master/标记整理.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png) **分类收集算法** @@ -508,7 +508,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低 G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。 -![](https://gitee.com/tysondai/img/raw/master/g1分区.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png) G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。 diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" index 0f3e5c8..72cff97 100644 --- "a/Java/Java\345\237\272\347\241\200.md" +++ "b/Java/Java\345\237\272\347\241\200.md" @@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接 Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 -![field-method](https://gitee.com/tysondai/img/raw/master/field-method.png) +![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png) ## Method类 @@ -1101,7 +1101,7 @@ public class GenericMethod { Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: -![exception](https://gitee.com/tysondai/img/raw/master/exception.png) +![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png) - Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 @@ -1198,7 +1198,7 @@ public class ExceptionTest { Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 -![io](https://gitee.com/tysondai/img/raw/master/io.jpg) +![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg) > 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) @@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 -![bio](https://gitee.com/tysondai/img/raw/master/bio.png) +![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png) ## NIO NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 -![nio](https://gitee.com/tysondai/img/raw/master/nio.png) +![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png) NIO与IO区别: diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 095093c..758e026 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -101,7 +101,7 @@ **JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -![](https://gitee.com/tysondai/img/raw/master/20220402230447.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) 所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 @@ -111,7 +111,7 @@ 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 -![](https://gitee.com/tysondai/img/raw/master/20220401234008.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 @@ -141,7 +141,7 @@ JRE = JVM + Java 核心类库 JDK = JRE + Java工具 + 编译器 + 调试器 -![](https://gitee.com/tysondai/img/raw/master/20220402230613.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) ## 面向对象有哪些特性? @@ -1030,7 +1030,7 @@ unchecked Exception: 不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。 -![](https://gitee.com/tysondai/img/raw/master/20220423154450.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423154450.png) diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index cfcb15d..a65d22c 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -64,7 +64,7 @@ ### 线程池执行原理? -![线程池执行流程](https://gitee.com/tysondai/img/raw/master/线程池执行流程.png) +![线程池执行流程](https://raw.githubusercontent.com/Tyson0314/img/master/线程池执行流程.png) 1. 当线程池里存活的线程数小于核心线程数`corePoolSize`时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数`corePoolSize`时,线程池里面的线程会一直存活着,就算空闲时间超过了`keepAliveTime`,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。 2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。 @@ -199,7 +199,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -225,7 +225,7 @@ public static ExecutorService newCachedThreadPool() { **终止(TERMINATED)**:表示该线程已经执行完毕。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -401,7 +401,7 @@ class RunnableDemo implements Runnable { 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://gitee.com/tysondai/img/raw/master/死锁.png) +![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -686,7 +686,7 @@ class SeasonThreadTask implements Runnable{ 每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。 -![](https://gitee.com/tysondai/img/raw/master/threadlocal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/threadlocal.png) 调用`threadLocal.set()`-->调用`getMap(Thread)`-->返回当前线程的`ThreadLocalMap`-->`map.set(this, value)`,this是`threadLocal`本身。源码如下: @@ -783,7 +783,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节点中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://gitee.com/tysondai/img/raw/master/aqs.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/aqs.png) ## ReentrantLock 是如何实现可重入性的? diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index 4a011e4..14acae6 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -54,9 +54,9 @@ Java集合类主要由两个接口**Collection**和**Map**派生出来的,Coll Java集合框架图如下: -![](https://gitee.com/tysondai/img/raw/master/collections2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/collections2.png) -![](https://gitee.com/tysondai/img/raw/master/map.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/map.png) List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合。Map代表的是存储key-value对的集合,可根据元素的key来访问value。 @@ -197,7 +197,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) +![图片来源网络](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) ### 红黑树的特点? @@ -271,7 +271,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" index c9734f5..1f35396 100644 --- "a/Java/\345\271\266\345\217\221.md" +++ "b/Java/\345\271\266\345\217\221.md" @@ -87,7 +87,7 @@ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveT 创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 -![](https://gitee.com/tysondai/img/raw/master/thread-pool.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/thread-pool.png) ThreadPoolExecutor 的通用构造函数: @@ -326,7 +326,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://gitee.com/tysondai/img/raw/master/scheduled-task.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -340,7 +340,7 @@ FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VAL CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 -![](https://gitee.com/tysondai/img/raw/master/executors-ali.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/executors-ali.png) 正确示例(阿里巴巴编码规范): @@ -369,7 +369,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909233258929.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909233258929.png) 本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 @@ -392,7 +392,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 终止(TERMINATED):表示该线程已经执行完毕。 -![](https://gitee.com/tysondai/img/raw/master/image-20210909235618175.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -680,7 +680,7 @@ public class SynchronizedDemo { Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 -![](https://gitee.com/tysondai/img/raw/master/synchronized-block.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-block.png) **方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 @@ -692,7 +692,7 @@ public class SynchronizedMethod { } ``` -![](https://gitee.com/tysondai/img/raw/master/synchronized-method.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-method.png) #### 锁的状态 @@ -1077,7 +1077,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://gitee.com/tysondai/img/raw/master/image-20210910000456607.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210910000456607.png) @@ -1112,19 +1112,19 @@ public void conditionSignal() throws InterruptedException { 每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 -![](https://gitee.com/tysondai/img/raw/master/condition-await.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-await.png) > 图片来源:Java并发编程的艺术 在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 -![](https://gitee.com/tysondai/img/raw/master/condition-wait-queue.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-wait-queue.png) > 图片来源:Java并发编程的艺术 线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 -![](https://gitee.com/tysondai/img/raw/master/condition-signal.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-signal.png) > 图片来源:Java并发编程的艺术 diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" index c7283d5..83fecae 100644 --- "a/Java/\351\233\206\345\220\210.md" +++ "b/Java/\351\233\206\345\220\210.md" @@ -51,7 +51,7 @@ 以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 -![](https://gitee.com/tysondai/img/raw/master/Java-Collections.jpeg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/Java-Collections.jpeg) ### HashMap @@ -88,7 +88,7 @@ put方法流程: 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![](https://gitee.com/tysondai/img/raw/master/hashmap-put.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) > 参考链接: > @@ -121,7 +121,7 @@ HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初 LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 -![linkedhashmap](https://gitee.com/tysondai/img/raw/master/linkedhashmap.png) +![linkedhashmap](https://raw.githubusercontent.com/Tyson0314/img/master/linkedhashmap.png) ### TreeMap @@ -136,7 +136,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://gitee.com/tysondai/img/raw/master/image-20210905215046510.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) **TreeMap的特点:** diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" index e57f2b1..cc43200 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" @@ -39,13 +39,13 @@ 文章目录: -![](https://gitee.com/tysondai/img/raw/master/image-20210914234334988.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914234334988.png) # 简介 RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq.png) ## 基本概念 @@ -94,19 +94,19 @@ Exchange规则。 direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-direct.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-direct.png) ## fanout 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-fanout.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-fanout.png) ## topic topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 -![](https://gitee.com/tysondai/img/raw/master/rabbitmq-topic.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-topic.png) ## headers diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index f329ea8..8d4e0d7 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -71,7 +71,7 @@ 目录结构如下: -![](https://gitee.com/tysondai/img/raw/master/image-20210914000822843.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914000822843.png) ## 简介 @@ -503,7 +503,7 @@ ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的 - 最底层的链表包含所有的元素 - 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) -![](https://gitee.com/tysondai/img/raw/master/redis-skiplist.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-skiplist.png) #### 对象 @@ -545,7 +545,7 @@ hash类型内部编码有两种: Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 -![](https://gitee.com/tysondai/img/raw/master/list-api.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/list-api.png) 使用场景: @@ -630,7 +630,7 @@ GET #返回文章ID。 3. EXEC命令进行提交事务 -![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) DISCARD:放弃事务,即该事务内的所有命令都将取消 @@ -653,7 +653,7 @@ QUEUED 事务里的命令执行时会读取最新的值: -![](https://gitee.com/tysondai/img/raw/master/redis-transaction.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-transaction.png) ### WATCH命令 @@ -800,7 +800,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 -![](https://gitee.com/tysondai/img/raw/master/redis-replication.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-replication.png) Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 @@ -932,7 +932,7 @@ redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 使用evalsha执行Lua脚本过程如下: -![](https://gitee.com/tysondai/img/raw/master/evalsha.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/evalsha.png) ### lua脚本作用 @@ -1075,7 +1075,7 @@ public void write(String key,Object data){ 解决方法: -![](https://gitee.com/tysondai/img/raw/master/image-20210913235221410.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210913235221410.png) > 图片来源:https://tech.it168.com diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index 8a0e0d6..d5704d2 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -153,7 +153,7 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. EXEC命令进行提交事务 -![](https://gitee.com/tysondai/img/raw/master/redis-multi.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) 一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: @@ -224,7 +224,7 @@ Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF` `bgsave`是主流的触发 RDB 持久化的方式,执行过程如下: -![](https://gitee.com/tysondai/img/raw/master/rdb持久化过程.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/rdb持久化过程.png) - 执行`BGSAVE`命令 - Redis 父进程判断当前**是否存在正在执行的子进程**,如果存在,`BGSAVE`命令直接返回。 @@ -269,7 +269,7 @@ appendfsync no //由操作系统决定何时进行同步操作 接下来看一下 AOF 持久化执行流程: -![](https://gitee.com/tysondai/img/raw/master/aof工作流程0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/aof工作流程0.png) 1. 所有的写入命令会追加到 AOP 缓冲区中。 2. AOF 缓冲区根据对应的策略向硬盘同步。 @@ -334,7 +334,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 客户端连接Redis的时候,先连接哨兵,哨兵会告诉客户端Redis主节点的地址,然后客户端连接上Redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 -![](https://gitee.com/tysondai/img/raw/master/sentinel.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/sentinel.png) **工作原理** @@ -353,7 +353,7 @@ Redis cluster集群节点最小配置6个节点以上(3主3从),其中主 Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。 -![](https://gitee.com/tysondai/img/raw/master/cluster_slots.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) **哈希槽是如何映射到 Redis 实例上的?** diff --git "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" index cca4277..a125d4b 100644 --- "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" +++ "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" @@ -22,15 +22,15 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 创建一个新的仓库,用来存放项目。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210822154700616.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822154700616.png) - 或者你在GitHub上看到别人有一个超级无敌有趣的项目,可以直接fork过来,可以理解成复制过来,变成你自己的。之后你想怎么改就怎么改! - ![image-20210822155107839](https://gitee.com/tysondai/img/raw/master/image-20210822155107839.png) + ![image-20210822155107839](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155107839.png) - 然后你可以通过Git命令行`git clone xxx`把项目clone到本地,在本地进行创作。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210822155359118.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155359118.png) - 最后,在本地创作完成,可以使用`git commit -m xxx`提交到本地库,然后使用`git push`把修改推送到GitHub仓库。之后就可以在GitHub上面看到你修改的内容啦~ @@ -42,23 +42,23 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 评价GitHub项目的两个重要的参数:star和fork。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161003170.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161003170.png) 比较优秀和热门的项目,star数目和fork数目都会比较多。我们可以根据这两个参数筛选出比较好的项目。使用`关键字 stars:>=xxx forks:>=xxx` 可以筛选出star和fork数目大于xxx的相关项目。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161122586.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161122586.png) - 使用 `awesome 关键字`,可以筛选出比较高质量的学习、书籍、工具类或者插件类的集合。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822161608599.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161608599.png) - 在特定位置搜索关键词。有些关键词出现在项目的不同位置,比如项目名称、项目描述和README等。使用`关键词 in name/description/Readme`,可以搜索到相关的内容。比如使用`spring in name`,可以搜索到在项目名中包含spring的项目。 -![image-20210822162144086](https://gitee.com/tysondai/img/raw/master/image-20210822162144086.png) +![image-20210822162144086](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822162144086.png) - 指定条件搜索关键词。如`tool language:java`搜索到的是包含关键字tool的Java项目,`tool followers:>1000`可以搜索到包含关键字tool,且follower数量大于1000的项目。 -![](https://gitee.com/tysondai/img/raw/master/image-20210822163111390.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822163111390.png) @@ -72,7 +72,7 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 文档神器。可以为自己的项目建立wiki,可以用markdown语法写wiki; -![](https://gitee.com/tysondai/img/raw/master/image-20210822172419760.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822172419760.png) - 使用GitHub pages建立个人静态网站,搞一个有自己域名的独立博客,想想都觉得开心。使用GitHub pages的好处是搭建简单而且免费,支持静态脚本,并且可以绑定自己的域名。具体可以参考:[GitHub Pages 建立个人网站详细教程 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/58229299) diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/progit2.md" index 6dde18b..68b8c2b 100644 --- "a/\345\267\245\345\205\267/progit2.md" +++ "b/\345\267\245\345\205\267/progit2.md" @@ -85,7 +85,7 @@ Git工作流程如下: Git 的工作流程图如下: -![](https://gitee.com/tysondai/img/raw/master/git-work-flow.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git-work-flow.png) > 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 @@ -103,11 +103,11 @@ Git 的三种状态:已修改(modified)、已暂存(staged)和已提 基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 -![](https://gitee.com/tysondai/img/raw/master/git工作流程.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git工作流程.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` -![](https://gitee.com/tysondai/img/raw/master/git-status.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/git-status.png) ## 配置 @@ -156,7 +156,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](https://gitee.com/tysondai/img/raw/master/git生命周期.png) +![git生命周期](https://raw.githubusercontent.com/Tyson0314/img/master/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -262,7 +262,7 @@ git commit -m "add readme.md" 单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: -![](https://gitee.com/tysondai/img/raw/master/image-20210830225020753.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210830225020753.png) 此时应该这么操作: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" index 2378225..e9f255a 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" @@ -91,7 +91,7 @@ where blog_id = ( 三个表依次嵌套,发现最里层的子查询 `id`最大,最先执行。 -![](https://gitee.com/tysondai/img/raw/master/explain-id.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-id.png) ## select_type @@ -107,13 +107,13 @@ where blog_id = ( 查询的表名,并不一定是真实存在的表,有别名显示别名,也可能为临时表。当from子句中有子查询时,table列是 ``的格式,表示当前查询依赖 id为N的查询,会先执行 id为N的查询。 -![](https://gitee.com/tysondai/img/raw/master/image-20210804083523885.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804083523885.png) ## partitions 查询时匹配到的分区信息,对于非分区表值为`NULL`,当查询的是分区表时,`partitions`显示分区表命中的分区情况。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802022931773.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802022931773.png) ## type @@ -123,25 +123,25 @@ where blog_id = ( 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快。比如,Mysql系统表proxies_priv在Mysql服务启动时候已经加载在内存中,对这个表进行查询不需要进行磁盘 IO。 -![](https://gitee.com/tysondai/img/raw/master/image-20210801233419732.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801233419732.png) ### const 单表操作的时候,查询使用了主键或者唯一索引。 -![](https://gitee.com/tysondai/img/raw/master/explain-const.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-const.png) ### eq_ref **多表关联**查询的时候,主键和唯一索引作为关联条件。如下图的sql,对于user表(外循环)的每一行,user_role表(内循环)只有一行满足join条件,只要查找到这行记录,就会跳出内循环,继续外循环的下一轮查询。 -![](https://gitee.com/tysondai/img/raw/master/image-20210801232638027.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801232638027.png) ### ref 查找条件列使用了索引而且不为主键和唯一索引。虽然使用了索引,但该索引列的值并不唯一,这样即使使用索引查找到了第一条数据,仍然不能停止,要在目标值附近进行小范围扫描。但它的好处是不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内做扫描。 -![](https://gitee.com/tysondai/img/raw/master/explain-ref.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-ref.png) ### ref_or_null @@ -151,13 +151,13 @@ where blog_id = ( 使用了索引合并优化方法,查询使用了两个以上的索引。新建comment表,id为主键,value_id为非唯一索引,执行`explain select content from comment where value_id = 1181000 and id > 1000;`,执行结果显示查询同时使用了id和value_id索引,type列的值为index_merge。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802001215614.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802001215614.png) ### range 有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。像between、and、'>'、'<'、in和or都是范围索引扫描。 -![](https://gitee.com/tysondai/img/raw/master/explain-range.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-range.png) ### index @@ -165,17 +165,17 @@ index包括select索引列,order by主键两种情况。 1. order by主键。这种情况会按照索引顺序全表扫描数据,拿到的数据是按照主键排好序的,不需要额外进行排序。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210801225045980.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225045980.png) 2. select索引列。type为index,而且extra字段为using index,也称这种情况为索引覆盖。所需要取的数据都在索引列,无需回表查询。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210801225942948.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225942948.png) ### all 全表扫描,查询没有用到索引,性能最差。 -![](https://gitee.com/tysondai/img/raw/master/explain-all.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-all.png) ## possible_keys @@ -249,13 +249,13 @@ CREATE TABLE `t_orderdetail` ( 查询的列未被索引覆盖,where筛选条件非索引的前导列。对存储引擎返回的结果进行过滤(Post-filter,后过滤),一般发生在MySQL服务器,而不是存储引擎层。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802232729417.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232729417.png) ### using index 查询的列被索引覆盖,并且where筛选条件符合最左前缀原则,通过**索引查找**就能直接找到符合条件的数据,不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802232357282.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232357282.png) ### Using where&Using index @@ -265,17 +265,17 @@ CREATE TABLE `t_orderdetail` ( - where筛选条件不符合最左前缀原则 - ![](https://gitee.com/tysondai/img/raw/master/image-20210802233120283.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233120283.png) - where筛选条件是索引列前导列的一个范围 - ![](https://gitee.com/tysondai/img/raw/master/image-20210802233455880.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233455880.png) ### null 查询的列未被索引覆盖,并且where筛选条件是索引的前导列,也就是用到了索引,但是部分字段未被索引覆盖,必须回表查询这些字段,Extra中为NULL。 -![](https://gitee.com/tysondai/img/raw/master/image-20210802234122321.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802234122321.png) ### using index condition @@ -283,11 +283,11 @@ CREATE TABLE `t_orderdetail` ( 不使用ICP的情况(`set optimizer_switch='index_condition_pushdown=off'`),如下图,在步骤4中,没有使用where条件过滤索引: -![](https://gitee.com/tysondai/img/raw/master/no-icp.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/no-icp.png) 使用ICP的情况(`set optimizer_switch='index_condition_pushdown=on'`): -![](https://gitee.com/tysondai/img/raw/master/icp.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/icp.png) 下面的例子使用了ICP: @@ -296,11 +296,11 @@ explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G; ``` -![](https://gitee.com/tysondai/img/raw/master/image-20210803084617433.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084617433.png) 关掉ICP之后(`set optimizer_switch='index_condition_pushdown=off'`),可以看到extra列为using where,不会使用索引下推。 -![](https://gitee.com/tysondai/img/raw/master/image-20210803084815503.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084815503.png) ### using temporary @@ -314,7 +314,7 @@ from t_order where user_id > 1 and user_id < 5\G; - select 查询字段不全是索引字段 - select 查询字段都是索引字段,但是 order by 字段和索引字段的顺序不一致 -![](https://gitee.com/tysondai/img/raw/master/image-20210804084029239.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804084029239.png) ### using join buffer diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" index 4ff8a64..7caa4e5 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" @@ -138,7 +138,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。 -![](https://gitee.com/tysondai/img/raw/master/image-20210821165019147.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821165019147.png) 进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的数据项。 @@ -170,15 +170,15 @@ Index_comment: 如下图,col1 是主键,col2和col3是普通字段。 -![](https://gitee.com/tysondai/img/raw/master/image-20200520234137916.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234137916.png) 下图是主键索引对应的 B+树结构,每个节点对应磁盘的一页。 -![](https://gitee.com/tysondai/img/raw/master/image-20200520234200868.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234200868.png) 对col3 建立一个单列索引,对应的B+树结构: -![](https://gitee.com/tysondai/img/raw/master/image-20200520234231001.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234231001.png) ### 索引分类 1. 主键索引:名为primary的唯一非空索引,不允许有空值。 @@ -208,7 +208,7 @@ Index_comment: 对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会对b进行比较排序)。直接执行`b = 2`这种查询条件没有办法利用索引。 -![最左匹配](https://gitee.com/tysondai/img/raw/master/image-20210821103313578.png) +![最左匹配](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821103313578.png) 从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行`a = 1 and b = 2`是a,b字段能用到索引的。而你执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。 @@ -218,7 +218,7 @@ InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的 聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。 -![](https://gitee.com/tysondai/img/raw/master/mysql-clustered-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-clustered-index.png) 对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。 @@ -244,7 +244,7 @@ explain select user_id from user_like where blog_id = 1; Extra中为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/cover-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) ### 索引失效 @@ -322,7 +322,7 @@ MEMORY引擎默认使用哈希索引,将键的哈希值和指向数据行的 myisam引擎主键索引和其他索引区别不大,叶子节点都包含索引值和行指针。 innodb引擎二级索引叶子存储的是索引值和主键值(不是行指针),这样可以减少行移动和数据页分裂时二级索引的维护工作。 - ![myisam-innodb-index](https://gitee.com/tysondai/img/raw/master/myisam-innodb-index.png) + ![myisam-innodb-index](https://raw.githubusercontent.com/Tyson0314/img/master/myisam-innodb-index.png) @@ -351,7 +351,7 @@ mvcc实现依赖于版本链,版本链是通过表的三个隐藏字段实现 3. 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链; 4. 记录redo log; -![](https://gitee.com/tysondai/img/raw/master/mvcc-impl.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc-impl.png) ### read view @@ -388,14 +388,14 @@ repeatable read:在一个事务范围内,第一次select时更新这个read_ 事务a和事务b同时开启事务,事务a插入数据然后提交,事务b执行全表的update,然后执行查询,查到了事务A中添加的数据。 -![](https://gitee.com/tysondai/img/raw/master/幻读1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) MySQL如何实现避免幻读: - 在快照读情况下,MySQL通过mvcc来避免幻读。 - 在当前读情况下,MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的)。 -![](https://gitee.com/tysondai/img/raw/master/current-read.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/current-read.png) next-key包括两部分:行锁和间隙锁。行锁是加在索引上的锁,间隙锁是加在索引之间的。 @@ -531,7 +531,7 @@ MySQL主要分为 Server 层和存储引擎层: - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 - **存储引擎**: 主要负责数据的存储和读取。server 层通过api与存储引擎进行通信。 -![MySQL-archpng](https://gitee.com/tysondai/img/raw/master/mysql-archpng.png) +![MySQL-archpng](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-archpng.png) ### Server 层基本组件 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index f872daa..8ec0b08 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -179,7 +179,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 `key` 从左到右递增排列,如果某个指针的左右相邻 `key` 分别是 keyi 和 keyi+1,则该指针指向节点的所有 `key` 大于等于 keyi 且小于等于 keyi+1。 -![](https://gitee.com/tysondai/img/raw/master/B+树索引0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/B+树索引0.png) 进行查找操作时,首先在根节点进行二分查找,找到`key`所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出`key`所对应的数据项。 @@ -251,7 +251,7 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 如下图,对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会根据b进行排序)。直接执行`b = 2`这种查询条件无法使用索引。 -![最左前缀](https://gitee.com/tysondai/img/raw/master/最左前缀.png) +![最左前缀](https://raw.githubusercontent.com/Tyson0314/img/master/最左前缀.png) 当a的值确定的时候,b是有序的。例如`a = 1`时,b值为1,2是有序的状态。当`a = 2`时候,b的值为1,4也是有序状态。 当执行`a = 1 and b = 2`时a和b字段能用到索引。而执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段无法使用索引。 @@ -285,7 +285,7 @@ explain select user_id from user_like where blog_id = 1; `explain`结果的`Extra`列为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://gitee.com/tysondai/img/raw/master/cover-index.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) ### 索引的设计原则? @@ -395,7 +395,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 每条表记录大概是这样的: -![](https://gitee.com/tysondai/img/raw/master/mvcc9.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc9.png) 使用事务更新行记录的时候,就会生成版本链,执行过程如下: @@ -407,15 +407,15 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、初始数据如下,其中`DB_ROW_ID`和`DB_ROLL_PTR`为空。 -![](https://gitee.com/tysondai/img/raw/master/mvcc2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc2.png) 2、事务A对该行数据做了修改,将`age`修改为12,效果如下: -![](https://gitee.com/tysondai/img/raw/master/mvcc7.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc7.png) 3、之后事务B也对该行记录做了修改,将`age`修改为8,效果如下: -![](https://gitee.com/tysondai/img/raw/master/mvcc11.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc11.png) 4、此时undo log有两行记录,并且通过回滚指针连在一起。 @@ -435,7 +435,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 **前提**:`DATA_TRX_ID` 表示每个数据行的最新的事务ID;`up_limit_id`表示当前快照中的最先开始的事务;`low_limit_id`表示当前快照中的最慢开始的事务,即最后一个事务。 -![](https://gitee.com/tysondai/img/raw/master/read_view10.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/read_view10.png) - 如果`DATA_TRX_ID` < `up_limit_id`:说明在创建`read view`时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。 - 如果`DATA_TRX_ID` >= `low_limit_id`:说明当前版本的记录的事务是在创建`read view`之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。 @@ -460,7 +460,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、首先,user表只有两条记录,具体如下: -![](https://gitee.com/tysondai/img/raw/master/image-20210922232259664.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210922232259664.png) 2、事务a和事务b同时开启事务`start transaction`; @@ -478,7 +478,7 @@ update user set user_name = 'a'; 5、事务b然后执行查询,查到了事务a中插入的数据。(下图左边是事务b,右边是事务a。事务开始之前只有两条记录,事务a插入一条数据之后,事务b查询出来是三条数据) -![](https://gitee.com/tysondai/img/raw/master/幻读1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) 以上就是当前读出现的幻读现象。 @@ -567,7 +567,7 @@ MySQL主要分为 Server 层和存储引擎层: 垂直划分数据库是根据业务进行划分,例如购物场景,可以将库中涉及商品、订单、用户的表分别划分出成一个库,通过降低单库的大小来提高性能。同样的,分表的情况就是将一个大表根据业务功能拆分成一个个子表,例如商品基本信息和商品描述,商品基本信息一般会展示在商品列表,商品描述在商品详情页,可以将商品基本信息和商品描述拆分成两张表。 -![](https://gitee.com/tysondai/img/raw/master/垂直划分.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/垂直划分.png) **优点**:行记录变小,数据页可以存放更多记录,在查询时减少I/O次数。 @@ -581,7 +581,7 @@ MySQL主要分为 Server 层和存储引擎层: 水平划分是根据一定规则,例如时间或id序列值等进行数据的拆分。比如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,从而提升性能。 -![](https://gitee.com/tysondai/img/raw/master/水平划分.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/水平划分.png) **优点**:单库(表)的数据量得以减少,提高性能;切分出的表结构相同,程序改动较少。 @@ -852,23 +852,34 @@ select * from page where id > start_id order by id limit 10; 通过主键索引,每次定位到start_id的位置,然后往后遍历10个数据,这样不管数据多大,查询性能都较为稳定。 -## B+树一个节点有多大?一千万条数据,B+树多高? +## 高度为3的B+树,可以存放多少数据? -InnoDB存储引擎有自己的最小储存单元——页(Page),一个页的大小是16K。 +InnoDB存储引擎有自己的最小储存单元——页(Page)。 -B+树一个节点的大小设为一页或页的倍数最为合适。因为如果一个节点的大小 < 1页,那么读取这个节点的时候其实读取的还是一页,这样就造成了资源的浪费。 +查询InnoDB页大小的命令如下: -在 MySQL 中 B+ 树的一个节点大小为“1页”,也就是16k。之所以设置为一页,是因为对于大部分业务,一页就足够了: +```mysql +mysql> show global status like 'innodb_page_size'; ++------------------+-------+ +| Variable_name | Value | ++------------------+-------+ +| Innodb_page_size | 16384 | ++------------------+-------+ +``` + +可以看出 innodb 默认的一页大小为 16384B = 16384/1024 = 16kb。 + +在MySQL中,B+树一个节点的大小设为一页或页的倍数最为合适。因为如果一个节点的大小 < 1页,那么读取这个节点的时候其实读取的还是一页,这样就造成了资源的浪费。 -首先InnoDB的B+树中,**非叶子节点存的是key + 指针**;**叶子节点存的是数据行**。 +B+树中**非叶子节点存的是key + 指针**;**叶子节点存的是数据行**。 对于叶子节点,如果一行数据大小为1k,那么一页就能存16条数据。 -对于非叶子节点,如果key使用的是bigint,则为8字节,指针在mysql中为6字节,一共是14字节,则16k能存放 16 * 1024 / 14 = 1170 个索引指针。 +对于非叶子节点,如果key使用的是bigint,则为8字节,指针在MySQL中为6字节,一共是14字节,则16k能存放 16 * 1024 / 14 = 1170 个索引指针。 于是可以算出,对于一颗高度为2的B+树,根节点存储索引指针节点,那么它有1170个叶子节点存储数据,每个叶子节点可以存储16条数据,一共 1170 x 16 = 18720 条数据。而对于高度为3的B+树,就可以存放 1170 x 1170 x 16 = 21902400 条数据(**两千多万条数据**),也就是对于两千多万条的数据,我们只需要**高度为3**的B+树就可以完成,通过主键查询只需要3次IO操作就能查到对应数据。 -所以在 InnoDB 中B+树高度一般为3层时,就能满足千万级的数据存储,所以一个节点为1页,也就是16k是比较合理的。 +所以在 InnoDB 中B+树高度一般为3层时,就能满足千万级的数据存储。 参考:https://www.cnblogs.com/leefreeman/p/8315844.html diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" index 9a99fb1..9ad4fb0 100644 --- "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ "b/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -13,7 +13,7 @@ 常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 -![](https://gitee.com/tysondai/img/raw/master/排序算法.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) ## 冒泡排序 diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index dd8b7fb..e9ddb23 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -28,7 +28,7 @@ SpringBoot实现自动配置原理图解: > 公众号【程序员大彬】,回复【自动配置】下载高清图片 -![](https://gitee.com/tysondai/img/raw/master/SpringBoot的自动配置原理.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index ae4a031..641525e 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -216,7 +216,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](https://gitee.com/tysondai/img/raw/master/bean生命周期.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/bean生命周期.png) 1.调用bean的构造方法创建Bean diff --git "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" index 0320b99..60a94c1 100644 --- "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" +++ "b/\347\275\221\347\273\234/\347\275\221\347\273\234.md" @@ -333,7 +333,7 @@ HTTP长连接,指的是复用TCP连接。多个HTTP请求可以复用同一个 CDN用户访问流程: -![cdn](https://gitee.com/tysondai/img/raw/master/cdn.png) +![cdn](https://raw.githubusercontent.com/Tyson0314/img/master/cdn.png) 1.用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有dns缓存,则向网站的DNS服务器请求; diff --git "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 2fb8b79..48969f2 100644 --- "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -38,7 +38,7 @@ 计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 -![](https://gitee.com/tysondai/img/raw/master/tcp5layer2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/tcp5layer2.png) 五层模型:应用层、传输层、网络层、数据链路层、物理层。 @@ -52,7 +52,7 @@ 假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是`CLOSED`。 -![](https://gitee.com/tysondai/img/raw/master/三次握手图解.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/三次握手图解.png) 1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位`SYN=1`,序列号`seq=x`。第一次握手前客户端的状态为`CLOSE`,第一次握手后客户端的状态为`SYN-SENT`。此时服务端的状态为`LISTEN`。 2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位`SYN=1`,`ACK=1`,序列号`seq=y`,确认号`ack=x+1`。第二次握手前服务端的状态为`LISTEN`,第二次握手后服务端的状态为`SYN-RCVD`,此时客户端的状态为`SYN-SENT`。(其中`SYN=1`表示要和客户端建立一个连接,`ACK=1`表示确认序号有效) @@ -69,7 +69,7 @@ ## 四次挥手 -![](https://gitee.com/tysondai/img/raw/master/四次挥手0.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/四次挥手0.png) 1. A的应用进程先向其TCP发出连接释放报文段(`FIN=1,seq=u`),并停止再发送数据,主动关闭TCP连接,进入`FIN-WAIT-1`(终止等待1)状态,等待B的确认。 2. B收到连接释放报文段后即发出确认报文段(`ACK=1,ack=u+1,seq=v`),B进入`CLOSE-WAIT`(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 @@ -152,7 +152,7 @@ Content-Length:112 ## HTTP状态码有哪些? -![](https://gitee.com/tysondai/img/raw/master/http-status-code.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/http-status-code.png) ## POST和GET的区别? @@ -194,7 +194,7 @@ HTTP2.0相比HTTP1.1支持的特性: 服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:**证书内容、证书签名算法和签名**,签名是为了验证身份。 -![](https://gitee.com/tysondai/img/raw/master/image-20211004111441594.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004111441594.png) 服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。 @@ -216,29 +216,29 @@ HTTP2.0相比HTTP1.1支持的特性: 1. **协商加密算法** 。在`Client Hello`里面客户端会告知服务端自己当前的一些信息,包括客户端要使用的TLS版本,支持的加密算法,要访问的域名,给服务端生成的一个随机数(Nonce)等。需要提前告知服务器想要访问的域名以便服务器发送相应的域名的证书过来。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921104210833.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921104210833.png) 2. 服务端响应`Server Hello`,告诉客户端服务端**选中的加密算法**。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921105450791.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105450791.png) 3. 接着服务端给客户端发来了2个证书。第二个证书是第一个证书的签发机构(CA)的证书。 - ![](https://gitee.com/tysondai/img/raw/master/image-20211004172007102.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20211004172007102.png) 4. 客户端使用证书的认证机构CA公开发布的RSA公钥**对该证书进行验证**,下图表明证书认证成功。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921105929268.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921105929268.png) 5. 验证通过之后,浏览器和服务器通过**密钥交换算法**产生共享的**对称密钥**。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110025197.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110025197.png) - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110155075.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110155075.png) 6. 开始传输数据,使用同一个对称密钥来加解密。 - ![](https://gitee.com/tysondai/img/raw/master/image-20210921110315068.png) + ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921110315068.png) ## DNS 的解析过程? @@ -257,7 +257,7 @@ HTTP2.0相比HTTP1.1支持的特性: 4. 服务器**响应请求**,返回响应数据。 5. 浏览器**解析响应内容,进行渲染**,呈现给用户。 -![](https://gitee.com/tysondai/img/raw/master/输入url返回页面过程1.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/输入url返回页面过程1.png) ## 什么是cookie和session? @@ -265,7 +265,7 @@ HTTP2.0相比HTTP1.1支持的特性: 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 **cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 -![](https://gitee.com/tysondai/img/raw/master/cookie.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/cookie.png) **cookie工作流程**: @@ -274,7 +274,7 @@ HTTP2.0相比HTTP1.1支持的特性: 3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 **session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 -![](https://gitee.com/tysondai/img/raw/master/session.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/session.png) ## Cookie和Session的区别? @@ -293,7 +293,7 @@ HTTP2.0相比HTTP1.1支持的特性: TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据。 -![](https://gitee.com/tysondai/img/raw/master/image-20210921112213523.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210921112213523.png) TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。 @@ -302,7 +302,7 @@ TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最 防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。 -![](https://gitee.com/tysondai/img/raw/master/拥塞控制.jpg) +![](https://raw.githubusercontent.com/Tyson0314/img/master/拥塞控制.jpg) ### 慢开始 From 1afc40b4f82950c3153ab2753d0bc3a3bfaf30e1 Mon Sep 17 00:00:00 2001 From: tyson Date: Fri, 3 Jun 2022 14:38:18 +0800 Subject: [PATCH 06/84] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Elasticsearch\345\205\245\351\227\250.md" | 2438 +++++++++++++++++ ...is\351\235\242\350\257\225\351\242\230.md" | 2 + .../\345\256\236\346\210\230\347\257\207.md" | 93 + ...PC\347\232\204\345\216\237\347\220\206.md" | 49 + ...\345\261\200\345\224\257\344\270\200ID.md" | 485 ++++ ...03\345\274\217\344\272\213\345\212\241.md" | 77 + ...03\345\274\217\347\274\223\345\255\230.md" | 98 + ...06\345\270\203\345\274\217\351\224\201.md" | 253 ++ .../\345\276\256\346\234\215\345\212\241.md" | 194 ++ ...34\347\250\213\350\260\203\347\224\250.md" | 119 + .../MySQL\345\237\272\347\241\200.md" | 12 +- ...21\351\235\242\350\257\225\351\242\230.md" | 120 +- ...15\347\275\256\344\270\255\345\277\203.md" | 44 + ...15\345\212\241\345\256\236\346\210\230.md" | 2 +- ...72\351\253\230\351\242\221\350\257\215.md" | 65 + ...1\253\230\351\242\221\350\257\215 - wx.md" | 66 + ...65\350\257\235\345\217\267\347\240\201.md" | 82 + ...73\345\275\225\345\216\237\347\220\206.md" | 85 + ...73\347\273\237\350\256\276\350\256\241.md" | 176 ++ ...347\273\237\350\256\276\350\256\241old.md" | 24 + ...37\351\235\242\350\257\225\351\242\230.md" | 0 ...43\347\240\201\345\256\236\347\216\260.md" | 0 ...43\347\240\201\345\256\236\347\216\260.md" | 0 ...60\346\215\256\347\273\223\346\236\204.md" | 0 .../\347\256\227\346\263\225.md" | 169 ++ .../TCP IP\345\215\217\350\256\256.md" | 0 .../session\345\222\214cookie.md" | 0 .../\345\233\276\350\247\243HTTP.md" | 0 .../\347\275\221\347\273\234.md" | 0 ...21\351\235\242\350\257\225\351\242\230.md" | 0 30 files changed, 4624 insertions(+), 29 deletions(-) create mode 100644 "\344\270\255\351\227\264\344\273\266/Elasticsearch\345\205\245\351\227\250.md" create mode 100644 "\345\205\266\344\273\226/\345\256\236\346\210\230\347\257\207.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" create mode 100644 "\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" create mode 100644 "\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" create mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" create mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" create mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" create mode 100644 "\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" create mode 100644 "\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" create mode 100644 "\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241old.md" rename "\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" (100%) rename "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" (100%) rename "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" (100%) rename "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" (100%) create mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" rename "\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" (100%) rename "\347\275\221\347\273\234/session\345\222\214cookie.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" (100%) rename "\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" (100%) rename "\347\275\221\347\273\234/\347\275\221\347\273\234.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\347\275\221\347\273\234.md" (100%) rename "\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" => "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" (100%) diff --git "a/\344\270\255\351\227\264\344\273\266/Elasticsearch\345\205\245\351\227\250.md" "b/\344\270\255\351\227\264\344\273\266/Elasticsearch\345\205\245\351\227\250.md" new file mode 100644 index 0000000..7e2b094 --- /dev/null +++ "b/\344\270\255\351\227\264\344\273\266/Elasticsearch\345\205\245\351\227\250.md" @@ -0,0 +1,2438 @@ + + + + +- [基础](#%E5%9F%BA%E7%A1%80) + - [概念](#%E6%A6%82%E5%BF%B5) + - [启动和关闭](#%E5%90%AF%E5%8A%A8%E5%92%8C%E5%85%B3%E9%97%AD) + - [配置文件](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) + - [PUT](#put) + - [GET](#get) + - [全文搜索](#%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2) + - [高亮搜索](#%E9%AB%98%E4%BA%AE%E6%90%9C%E7%B4%A2) + - [分析](#%E5%88%86%E6%9E%90) + - [分布式特性](#%E5%88%86%E5%B8%83%E5%BC%8F%E7%89%B9%E6%80%A7) +- [集群原理](#%E9%9B%86%E7%BE%A4%E5%8E%9F%E7%90%86) + - [术语](#%E6%9C%AF%E8%AF%AD) + - [节点](#%E8%8A%82%E7%82%B9) + - [分片](#%E5%88%86%E7%89%87) + - [集群健康](#%E9%9B%86%E7%BE%A4%E5%81%A5%E5%BA%B7) + - [索引](#%E7%B4%A2%E5%BC%95) + - [故障转移](#%E6%95%85%E9%9A%9C%E8%BD%AC%E7%A7%BB) + - [单机多节点](#%E5%8D%95%E6%9C%BA%E5%A4%9A%E8%8A%82%E7%82%B9) +- [数据输入与输出](#%E6%95%B0%E6%8D%AE%E8%BE%93%E5%85%A5%E4%B8%8E%E8%BE%93%E5%87%BA) + - [文档元数据](#%E6%96%87%E6%A1%A3%E5%85%83%E6%95%B0%E6%8D%AE) + - [创建新文档](#%E5%88%9B%E5%BB%BA%E6%96%B0%E6%96%87%E6%A1%A3) + - [取回文档](#%E5%8F%96%E5%9B%9E%E6%96%87%E6%A1%A3) + - [取回多个文档](#%E5%8F%96%E5%9B%9E%E5%A4%9A%E4%B8%AA%E6%96%87%E6%A1%A3) + - [删除文档](#%E5%88%A0%E9%99%A4%E6%96%87%E6%A1%A3) + - [检查文档是否存在](#%E6%A3%80%E6%9F%A5%E6%96%87%E6%A1%A3%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8) + - [更新文档](#%E6%9B%B4%E6%96%B0%E6%96%87%E6%A1%A3) + - [更新和冲突](#%E6%9B%B4%E6%96%B0%E5%92%8C%E5%86%B2%E7%AA%81) + - [批量操作](#%E6%89%B9%E9%87%8F%E6%93%8D%E4%BD%9C) +- [分布式文档存储](#%E5%88%86%E5%B8%83%E5%BC%8F%E6%96%87%E6%A1%A3%E5%AD%98%E5%82%A8) + - [路由文档到分片](#%E8%B7%AF%E7%94%B1%E6%96%87%E6%A1%A3%E5%88%B0%E5%88%86%E7%89%87) +- [映射和分析](#%E6%98%A0%E5%B0%84%E5%92%8C%E5%88%86%E6%9E%90) + - [核心简单域类型](#%E6%A0%B8%E5%BF%83%E7%AE%80%E5%8D%95%E5%9F%9F%E7%B1%BB%E5%9E%8B) + - [查看映射](#%E6%9F%A5%E7%9C%8B%E6%98%A0%E5%B0%84) + - [自定义映射器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%98%A0%E5%B0%84%E5%99%A8) + - [index](#index) + - [analyzer](#analyzer) + - [更新映射](#%E6%9B%B4%E6%96%B0%E6%98%A0%E5%B0%84) + - [测试映射](#%E6%B5%8B%E8%AF%95%E6%98%A0%E5%B0%84) + - [分析器](#%E5%88%86%E6%9E%90%E5%99%A8) + - [测试分析器](#%E6%B5%8B%E8%AF%95%E5%88%86%E6%9E%90%E5%99%A8) + - [复杂核心域类型](#%E5%A4%8D%E6%9D%82%E6%A0%B8%E5%BF%83%E5%9F%9F%E7%B1%BB%E5%9E%8B) + - [多值域](#%E5%A4%9A%E5%80%BC%E5%9F%9F) + - [内部对象](#%E5%86%85%E9%83%A8%E5%AF%B9%E8%B1%A1) +- [搜索](#%E6%90%9C%E7%B4%A2) + - [空搜索](#%E7%A9%BA%E6%90%9C%E7%B4%A2) + - [多索引多类型](#%E5%A4%9A%E7%B4%A2%E5%BC%95%E5%A4%9A%E7%B1%BB%E5%9E%8B) + - [轻量搜索](#%E8%BD%BB%E9%87%8F%E6%90%9C%E7%B4%A2) +- [请求体查询](#%E8%AF%B7%E6%B1%82%E4%BD%93%E6%9F%A5%E8%AF%A2) + - [空查询](#%E7%A9%BA%E6%9F%A5%E8%AF%A2) + - [提升权重](#%E6%8F%90%E5%8D%87%E6%9D%83%E9%87%8D) + - [explain](#explain) + - [查询和过滤器的区别](#%E6%9F%A5%E8%AF%A2%E5%92%8C%E8%BF%87%E6%BB%A4%E5%99%A8%E7%9A%84%E5%8C%BA%E5%88%AB) +- [排序与相关性](#%E6%8E%92%E5%BA%8F%E4%B8%8E%E7%9B%B8%E5%85%B3%E6%80%A7) + - [按照字段的值排序](#%E6%8C%89%E7%85%A7%E5%AD%97%E6%AE%B5%E7%9A%84%E5%80%BC%E6%8E%92%E5%BA%8F) + - [多级排序](#%E5%A4%9A%E7%BA%A7%E6%8E%92%E5%BA%8F) + - [多值字段的排序](#%E5%A4%9A%E5%80%BC%E5%AD%97%E6%AE%B5%E7%9A%84%E6%8E%92%E5%BA%8F) + - [字符串排序](#%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8E%92%E5%BA%8F) +- [索引管理](#%E7%B4%A2%E5%BC%95%E7%AE%A1%E7%90%86) + - [创建索引](#%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95) + - [删除索引](#%E5%88%A0%E9%99%A4%E7%B4%A2%E5%BC%95) + - [索引设置](#%E7%B4%A2%E5%BC%95%E8%AE%BE%E7%BD%AE) + - [配置分析器](#%E9%85%8D%E7%BD%AE%E5%88%86%E6%9E%90%E5%99%A8) + - [自定义分析器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%88%86%E6%9E%90%E5%99%A8) + - [类型和映射](#%E7%B1%BB%E5%9E%8B%E5%92%8C%E6%98%A0%E5%B0%84) + - [根对象](#%E6%A0%B9%E5%AF%B9%E8%B1%A1) +- [分片内部原理](#%E5%88%86%E7%89%87%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86) + - [倒排索引](#%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95) +- [深入搜索](#%E6%B7%B1%E5%85%A5%E6%90%9C%E7%B4%A2) + - [精确值查找](#%E7%B2%BE%E7%A1%AE%E5%80%BC%E6%9F%A5%E6%89%BE) + - [term 查询文本](#term-%E6%9F%A5%E8%AF%A2%E6%96%87%E6%9C%AC) + - [terms 查询](#terms-%E6%9F%A5%E8%AF%A2) + - [全文搜索](#%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2-1) + - [match 查询](#match-%E6%9F%A5%E8%AF%A2) + - [range 查询](#range-%E6%9F%A5%E8%AF%A2) + - [数字范围](#%E6%95%B0%E5%AD%97%E8%8C%83%E5%9B%B4) + - [日期范围](#%E6%97%A5%E6%9C%9F%E8%8C%83%E5%9B%B4) + - [分页](#%E5%88%86%E9%A1%B5) + - [exists 查询](#exists-%E6%9F%A5%E8%AF%A2) + - [bool 组合查询](#bool-%E7%BB%84%E5%90%88%E6%9F%A5%E8%AF%A2) + - [如何使用 bool 查询](#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-bool-%E6%9F%A5%E8%AF%A2) + - [constant_score 查询](#constant_score-%E6%9F%A5%E8%AF%A2) + - [多字段搜索](#%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%90%9C%E7%B4%A2) + - [多字符串查询](#%E5%A4%9A%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9F%A5%E8%AF%A2) + - [multi_match 查询](#multi_match-%E6%9F%A5%E8%AF%A2) + - [多字段映射](#%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%98%A0%E5%B0%84) + - [copy_to 定制组合 field](#copy_to-%E5%AE%9A%E5%88%B6%E7%BB%84%E5%90%88-field) +- [springboot 集成 es](#springboot-%E9%9B%86%E6%88%90-es) +- [mall](#mall) + + + +[Elasticsearch 权威指南](https://www.elastic.co/guide/cn/elasticsearch/guide/current/_talking_to_elasticsearch.html) + +## 基础 + +Elasticsearch 是一个开源的搜索引擎,建立在全文搜索引擎库 lucene 基础之上。Elasticsearch 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。 + +ES与mysql的对应关系: + +- index –> DB +- type –> Table +- Document –> row + +### 概念 + +[参考--阮一峰es教程](http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html) + +1. node 和 cluster + + Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。 + +2. Index + + 数据库的同义词。每个 Index (即数据库)的名字必须是小写。查看当前节点的所有index:`GET _cat/indices` + +3. Type + + 类似于表结构。不同的 Type 应该有相似的结构(schema),举例来说,`id`字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的区别。性质完全不同的数据(比如`products`和`logs`)应该存成两个 Index,而不是一个 Index 里面的两个 Type。 + +4. Document + + 单条的记录称为 Document。Document 可以分组,比如`weather`这个 Index 里面,可以按城市分组(北京和上海),这种分组就是 Type。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。 + + +### 启动和关闭 + +不用安装,解压即可。 + +启动:`bin\elasticsearch.bat` + +关闭:ctrl+c/`curl -XPOST http://localhost:9200/_cluster/nodes/_shutdown `关掉整个集群 + +启动 head 插件:到 head 安装目录下运行`grunt server` + +### 配置文件 + +安装目录config下的 elasticsearch.yml 可以配置集群的信息,如cluster.name 和 node.name。 + +```yaml +# ---------------------------------- MyConfig ---------------------------------- +#cluster.name: xxx +node.name: node-2 +#指明该节点可以是主节点,也可以是数据节点 +node.master: true +node.data: true +network.host: 127.0.0.1 +http.port: 9200 +transport.tcp.port: 9300 +``` + +http.port 是elasticsearch对外提供服务的http端口配置。 + +transport.tcp.port 指定了elasticsearch集群内数据通讯使用的端口,默认情况下为9300。 + + +### PUT + +```json +PUT /company/employee/1 +{ + "first_name" : "Tyson", + "last_name" : "dai", + "age" : 23, + "interests" : ["sport", "music"], + "hire_date" : "2014-01-01" +} +``` + +company:索引名称,employee:类型名称,1是 ID。 + +### GET + +```json +GET /company/employee/1 +``` + +搜索所有雇员: + +```json +GET /company/employee/_search +``` + +搜索结果如下,雇员数据放在 hits 数组中: + +```json +{ + "took": 413, + "timed_out": false, + "_shards": { + "total": 5, + "successful": 5, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": 2, + "max_score": 1, + "hits": [ + { + "_index": "company", + "_type": "employee", + "_id": "2", + "_score": 1, + "_source": { + "first_name": "Lily", + "last_name": "dai", + "age": 23, + "interests": [ + "sport", + "music" + ] + } + }, + { + "_index": "company", + "_type": "employee", + "_id": "1", + "_score": 1, + "_source": { + "first_name": "Tyson", + "last_name": "dai", + "age": 23, + "interests": [ + "sport", + "music" + ] + } + } + ] + } +} +``` + +按特定条件搜索: + +```json +GET /company/employee/_search?q=first_name:Tyson +``` + +使用查询表达式搜索: + +```json +GET /company/employee/_search +{ + "query": { + "match": { + "first_name": "Tyson" + } + } +} +``` + +复杂查询: + +姓氏为 Dai的雇员,但这次我们只需要年龄大于 20 的。 + +```json +GET /company/employee/_search +{ + "query": { + "bool" : { + "must" : { + "match" : { + "last_name" : "dai" + } + }, + "filter": { + "range": { + "age": {"gt" : 20} + } + } + } + } +} +``` + +### 全文搜索 + +传统数据库确实很难搞定的任务。 + +```json +GET /company/employee/_search +{ + "query": { + "match": { + "about": "rock climbing" + } + } +} +``` + +返回`"about": "rock climbing"`和`"about": "rock albums"`两条记录,默认按照每个文档跟查询的匹配程度排序。 + +### 高亮搜索 + +```json +GET /company/employee/_search +{ + "query": { + "match_phrase": { + "about": "climbing" + } + }, + "highlight": { + "fields": { + "about": {} + } + } +} +``` + +返回结果多 `highlight` 的部分。这个部分包含了 `about` 属性匹配的文本片段,并以 HTML 标签 `` 封装。 + +```json +{ + "took": 43, + "timed_out": false, + "_shards": { + "total": 5, + "successful": 5, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": 1, + "max_score": 0.2876821, + "hits": [ + { + "_index": "company", + "_type": "employee", + "_id": "3", + "_score": 0.2876821, + "_source": { + "first_name": "Tyson", + "last_name": "dai", + "age": 23, + "interests": [ + "sport", + "music" + ], + "about": "rock climbing" + }, + "highlight": { + "about": [ + "rock climbing" + ] + } + } + ] + } +} +``` + +### 分析 + +Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 `GROUP BY` 类似但更强大。 + +```json +GET /company/employee/_search +{ + "aggs": { + "all_interests": { + "terms": { "field": "interests" } + } + } +} +``` + +直接执行上面的代码会报错,原因是5.x后对排序,聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启。 + +```json +PUT company/_mapping/employee/ +{ + "properties": { + "interests": { + "type": "text", + "fielddata": true + } + } +} +``` + +搜索结果: + +```json +{ + ... + "hits": { ... }, + "aggregations": { + "all_interests": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "music", + "doc_count": 4 + }, + { + "key": "sport", + "doc_count": 4 + } + ] + } + } +} +``` + +如果想知道叫 Tyson的雇员中最受欢迎的兴趣爱好,可以直接添加适当的查询来组合查询: + +```json +GET company/employee/_search +{ + "query": { + "match": { + "first_name": "Tyson" + } + }, + "aggs": { + "all_interests": { + "terms": { + "field": "interests" + } + } + } +} +``` + +搜索结果: + +```json +{ + "took": 33, + "timed_out": false, + "_shards": { + "total": 5, + "successful": 5, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": 1, + "max_score": 0.2876821, + "hits": [ + { + "_index": "company", + "_type": "employee", + "_id": "3", + "_score": 0.2876821, + "_source": { + "first_name": "Tyson", + "last_name": "dai", + "age": 23, + "interests": [ + "sport", + "music" + ], + "about": "rock climbing" + } + } + ] + }, + "aggregations": { + "all_interests": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "music", + "doc_count": 1 + }, + { + "key": "sport", + "doc_count": 1 + } + ] + } + } +} +``` + +聚合还支持分级汇总 。比如,查询特定兴趣爱好员工的平均年龄: + +```java +GET company/employee/_search +{ + "aggs": { + "all_interests": { + "terms": { + "field": "interests" + }, + "aggs": { + "avg_age": { + "avg": { + "field": "age" + } + } + } + } + } +} +``` + +搜索结果: + +```json +"aggregations": { + "all_interests": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "music", + "doc_count": 4, + "avg_age": { + "value": 18.5 + } + }, + { + "key": "sport", + "doc_count": 4, + "avg_age": { + "value": 18.5 + } + } + ] + } + } +``` + +### 分布式特性 + +Elasticsearch 可以横向扩展至数百(甚至数千)的服务器节点,同时可以处理PB级数据。 + +## 集群原理 + +ElasticSearch 的主旨是随时可用和按需扩容。扩容可以通过购买性能更强大( *垂直扩容* ) 或者数量更多的服务器( *水平扩容* )来实现。 + +### 术语 + +#### 节点 + +一个运行中的 Elasticsearch 实例称为节点,而集群是由一个或者多个拥有相同 `cluster.name` 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。 + +当一个节点被选举成为主节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。 + +我们可以将请求发送到集群中的任何节点,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。 + +获取节点信息:`http://localhost:9200/_cluster/state/nodes?pretty`,pretty 用于换行。 + +#### 分片 + +每个节点可以分配一个或多个分片。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。 + +一个分片可以是 *主* 分片或者 *副本* 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。 + +一个副本分片只是一个主分片的拷贝。 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。 + +### 集群健康 + +`GET /_cluster/health` + +返回内容: + +```json +{ + "cluster_name": "elasticsearch", + "status": "yellow", + "timed_out": false, + "number_of_nodes": 1, + "number_of_data_nodes": 1, + "active_primary_shards": 6, + "active_shards": 6, + "relocating_shards": 0, + "initializing_shards": 0, + "unassigned_shards": 5, + "delayed_unassigned_shards": 0, + "number_of_pending_tasks": 0, + "number_of_in_flight_fetch": 0, + "task_max_waiting_in_queue_millis": 0, + "active_shards_percent_as_number": 54.54545454545454 +} +``` + +status 字段表示当前集群总体是否正常,它有三个值: + +1. green,所有的主分片和副本分片都正常运行。 + +2. yellow,所有的主分片都正常运行,但不是所有的副本分片都正常运行。 +3. red,有主分片不能正常运行。 + +### 索引 + +往 elasticsearch 添加数据时需要用到索引,索引是指向一个或多个分片的逻辑命名空间。一个分片是一个 Lucene 的实例,以及它本身就是一个完整的搜索引擎。 + +当我们只开启一个节点时,索引在默认情况下会被分配5个主分片,每个主分片拥有一个副本分片。主分片会被分配到这个节点上,而副本分片不会被分配到任何节点。 + +```json +{ + "cluster_name": "elasticsearch", + "status": "yellow", + ... + "unassigned_shards": 5,//5个副本分片都是 unassigned,都没有被分配到任何节点 + ... +} +``` + +当前我们的集群是正常运行的,但是在硬件故障时有丢失数据的风险。 + +### 故障转移 + +可以在同一个目录下开启另一个节点,副本分片会被分配到这个节点上,此时计算有硬件故障也不会丢失数据。 + +### 单机多节点 + +node1 的 elasticsearch.yml 做如下配置: + +```yaml +# ---------------------------------- MyConfig ---------------------------------- +#cluster.name: xxx +node.name: node-1 +#指明该节点可以是主节点,也可以是数据节点 +#node.master: true +#node.data: true +network.host: 127.0.0.1 +http.port: 9200 +transport.tcp.port: 9300 +discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"] + +# 解决elasticsearch-head 集群健康值: 未连接问题 +http.cors.enabled: true +http.cors.allow-origin: "*" +``` + +node2 的 elasticsearch.yml 做如下配置: + +```yaml +# ---------------------------------- MyConfig ---------------------------------- +#cluster.name: xxx +node.name: node-2 +#指明该节点可以是主节点,也可以是数据节点 +#node.master: true +#node.data: true +network.host: 127.0.0.1 +http.port: 9201 +transport.tcp.port: 9301 +discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"] + +# 解决elasticsearch-head 集群健康值: 未连接问题 +http.cors.enabled: true +http.cors.allow-origin: "*" +``` + +同理 node3 也做好配置。然后重启 elasticsearch 节点,就可以实现单机多节点集群搭建。 + + + +## 数据输入与输出 + +### 文档元数据 + +一个文档不仅包含数据,也包含元数据。三个必须的元数据元素如下:\_index、\_type和_id。 + +索引名字必须小写,不能以下划线开头,不能包含逗号。 + +\_type在索引中对数据进行逻辑分区,如产品下面还可以分为很多子类。一个 `_type` 命名可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符。 + +### 创建新文档 + +使用 PUT 请求,需要定义 _id: + +```json +PUT /{index}/{type}/{id} +{ + "field": "value", + ... +} +``` + +id 为2的文档存在时会报错: document already exists + +```json +PUT company/employee/2/_create +{ + "first_name" : "Tyson", + "last_name" : "dai", + "age" : 23, + "interests" : ["sport", "music"] +} +``` + +不存在时才创建: + +```json +PUT company/employee/2?op_type=create +{ + "first_name" : "Tyson", + "last_name" : "dai", + "age" : 23, + "interests" : ["sport", "music"] +} +``` + +使用 `POST` 可以让 Elasticsearch 自动生成唯一 的_id。 + +```json +POST company/employee +{ + "first_name" : "Tyson", + "last_name" : "dai", + "age" : 23, + "interests" : ["sport", "music"] +} +``` + +### 取回文档 + +返回文档的一部分: + +```json +GET /company/employee/1?_source=first_name,interests +``` + +只得到_source 字段(即id为1的整个文档): + +```json +GET /company/employee/1/_source +``` + + +### 取回多个文档 + +mget api 要求传入一个 docs 数组作为参数,可以通过 _source 指定返回字段。 + +```json +GET /_mget +{ + "docs": [ + { + "_index": "company", + "_type": "employee", + "_id": 2 + }, + { + "_index": "class", + "_type": "student", + "_id": 1, + "_source": "about" + } + ] +} +``` + +如果获取的文档 _index 和 _type 相同,可以在 url 指定默认的 _index 和 _type,传入一个 ids 数组。 + +```json +GET /company/employee/_mget +{ + "ids": ["1", "2"] +} +``` + +通过单独请求可以覆盖默认的 _index 和 _type。 + +```json +GET /company/employee/_mget +{ + "docs" : [ + { "_id" : 2 }, + { "_index" : "class", "_type" : "student", "_id" : 1 } + ] +} +``` + +### 删除文档 + +`DELETE company/employee/1`,删除文档,版本号会增加。 + +```json +{ + "_index": "company", + "_type": "employee", + "_id": "1", + "_version": 2, + "result": "deleted", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 1, + "_primary_term": 4 +} +``` + +### 检查文档是否存在 + +`HEAD /company/employee/1` + +返回结果:`200 - OK` + +### 更新文档 + +文档是不可变的,不能被修改,只能被替换。 `update` API 必须遵循同样的规则。 从外部来看,我们在一个文档的某个位置进行部分更新。然而在内部, `update` API 简单使用 *检索-修改-重建索引* 的处理过程。 + +```json +POST company/employee/1/_update +{ + "doc": { + "first_name": "sophia", + "interests": ["sport", "chess"] + } +} +``` + +#### 更新和冲突 + +```json +POST company/employee/1/_update?retry_on_conflict=5 +{ + "doc": { + "first_name": "sophia", + "interests": ["sport", "chess"] + } +} +``` + +### 批量操作 + +语法: + +```json +{ action: { metadata }}\n +{ request body }\n +{ action: { metadata }}\n +{ request body }\n +... +``` + +action 有 create、delete、index 和 update。metadata 定义了\_index,\_type,_id 等信息。 + +create:如果文档不存在,那么就创建它。index:创建一个新文档或者替换一个现有的文档。create 和 index 不指定 `_id`的话 ,将会自动生成一个 ID 。 + +```json +POST /_bulk +{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} +{ "create": { "_index": "website", "_type": "blog", "_id": "123" }} +{ "title": "My first blog post" } +{ "index": { "_index": "website", "_type": "blog" }} +{ "title": "My second blog post" } +{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} } +{ "doc" : {"title" : "My updated blog post"} } +``` + +bulk 请求不是原子的,不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求。 + +**默认的 index 和 type** + +```json +POST /website/_bulk +{ "index": { "_type": "log" }} +{ "event": "User logged in" } +``` + + + +## 分布式文档存储 + +### 路由文档到分片 + +文档所在分片的位置通过这个公式计算:`shard = hash(routing) % number_of_primary_shards`,rounting 默认是文档的 _id,可以设置成自定义的值。创建索引的时候就确定好主分片的数量,并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。 + + + + +## 映射和分析 + +映射:为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。 + +分析:将一块文本分成适合于倒排索引的独立的词条,然后将这些词条统一化为标准格式以提高它们的可搜索性。 + +### 核心简单域类型 + +Elasticsearch 支持 如下简单域类型: + +- 字符串: `string` +- 整数 : `byte`, `short`, `integer`, `long` +- 浮点数: `float`, `double` +- 布尔型: `boolean` +- 日期: `date` + +当你索引一个新的文档,elasticsearch 会使用动态映射,通过 json 中的基本数据类型,尝试猜测域的类型。 + +| **JSON type** | **域 type** | +| ------------------------------ | ----------- | +| 布尔型: `true` 或者 `false` | `boolean` | +| 整数: `123` | `long` | +| 浮点数: `123.45` | `double` | +| 字符串,有效日期: `2014-09-15` | `date` | +| 字符串: `foo bar` | `string` | + +如果你通过引号( `"123"` )索引一个数字,它会被映射为 `string` 类型,而不是 `long` 。但是,如果这个域已经映射为 `long` ,那么 Elasticsearch 会尝试将这个字符串转化为 long ,如果无法转化,则抛出一个异常。 + +### 查看映射 + +`GET /company/_mapping/employee` + +返回结果: + +```json +{ + "company": { + "mappings": { + "employee": { + "properties": { + "age": { + "type": "long" + }, + "first_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "hire_date": { + "type": "date" + }, + "interests": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "last_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + } + } +} +``` + +### 自定义映射器 + +`string` 类型域会被认为包含全文。它们的值在索引前,会通过 一个分析器,针对于这个域的查询在搜索前也会经过一个分析器。string 域映射的两个最重要的属性是 index 和 analyzer。 + +#### index + +`index` 属性控制怎样索引字符串。它有三个值: + +- analyzed:默认,首先分析这个域,然后索引它; +- not_analyzed:索引这个域,索引的是精确值,不会对它进行分析; +- no:不要索引这个域,这个域不会被搜索到。 + +设置 tag 域的 index 为 not_analyzed: + +```json +{ + "tag": { + "type": "string", + "index": "not_analyzed" + } +} +``` + +其他简单类型(例如 `long` , `double` , `date` 等)也接受 `index` 参数,但有意义的值只有 `no` 和 `not_analyzed` , 因为它们永远不会被分析。 + +#### analyzer + +对于 `analyzed` 字符串域,用 `analyzer` 属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 `standard` 分析器, 但你可以指定一个内置的分析器替代它,例如 `whitespace` 、 `simple` 和 `english`: + +```json +{ + "tweet": { + "type": "string", + "analyzer": "english" + } +} +``` + + +### 更新映射 + +我们可以更新一个映射来添加一个新域,但不能将一个存在的域从 `analyzed` 改为 `not_analyzed` ,否则索引的数据可能会出错,数据不能被正常的搜索。 + +增加名为 tag 的 not_analyzed 的文本域: + +```json +PUT /gb/_mapping/tweet +{ + "properties" : { + "tag" : { + "type" : "text", + "index": "not_analyzed" + } + } +} +``` + +指定中文分词器: + +```json +PUT /gb/_mapping/tweet +{ + "properties" : { + "user": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_max_word" + } + } +} +``` + +`analyzer`是字段文本的分词器,`search_analyzer`是搜索词的分词器。`ik_max_word`分词器是插件`ik`提供的,可以对文本进行最大数量的分词。 + + +### 测试映射 + +```json +GET /gb/_analyze +{ + "field": "tag", + "text": "Black-cats" +} +``` + + `tag` 域产生单独的词条 `Black-cats` 。 + +### 分析器 + +分析器的三个功能: + +- 字符过滤。字符串按顺序通过每个字符过滤器。它们在分词前整理字符串。一个字符过滤器可以用来去掉HTML或者将 & 转化为 and。 +- 字符串被分词器分成单个的词条 +- token 过滤器。改变词条(Quick 小写),删除词条(a/the/and),增加词条(leap/jump这种同义词) + +对特定域和全文域_all 查询字符串时可能会返回不同的结果。 + +当你查询一个 *全文* 域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。 + +当你查询一个 *精确值* 域时,不会分析查询字符串, 而是搜索你指定的精确值。 + +```json +GET /_search?q=2014 # 12 results +GET /_search?q=2014-09-15 # 12 results +GET /_search?q=date:2014-09-15 # 1 result +GET /_search?q=date:2014 # 0 results 没有"2014",只有"2014-09-15" +``` + +date 域包含一个精确值:单独的词条 `2014-09-15`。 + +_all 域是一个全文域,所以分词进程将日期转化为三个词条: `2014`, `09`, 和 `15`。 + +#### 测试分析器 + +```json +GET /_analyze +{ + "analyzer": "standard", + "text": "Text to analyze" +} +``` + +结果: + +```json +{ + "tokens": [ + { + "token": "text", + "start_offset": 0, + "end_offset": 4, + "type": "", + "position": 0 + }, + { + "token": "to", + "start_offset": 5, + "end_offset": 7, + "type": "", + "position": 1 + }, + { + "token": "analyze", + "start_offset": 8, + "end_offset": 15, + "type": "", + "position": 2 + } + ] +} +``` + +### 复杂核心域类型 + +#### 多值域 + +`{ "tag": [ "search", "nosql" ]}` + +### 内部对象 + +```json +{ + "tweet": "Elasticsearch is very flexible", + "user": { + "id": "@johnsmith", + "gender": "male", + "age": 26, + "name": { + "full": "John Smith", + "first": "John", + "last": "Smith" + } + } +} +``` + +Lucene 不理解内部对象。 Lucene 文档是由一组键值对列表组成的。为了能让 Elasticsearch 有效地索引内部类,它把我们的文档转化成这样: + +```json +{ + "tweet": [elasticsearch, flexible, very], + "user.id": [@johnsmith], + "user.gender": [male], + "user.age": [26], + "user.name.full": [john, smith], + "user.name.first": [john], + "user.name.last": [smith] +} +``` + + + + +## 搜索 + +### 空搜索 + +`GET /_search`,返回的 hits 数组包含所查询结果的前十个文档。 + +`GET /_search?timeout=10ms`,在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。 + + +### 多索引多类型 + +`GET /c*,g*/_search`,在以 c 开头和 g 开头的索引中搜索所有的类型。 + +`GET /_all/employee,student/_search?size=1&from=1`,在所有索引中搜索 employee 和 student 类型。elasticsearch 默认一次返回10条结果,size 可以指定返回返回结果数量,from 指定位移。 + + +### 轻量搜索 + +查询 employee 类型的 last_name 字段为 dai 的所有文档:`GET company/employee/_search?q=last_name:dai` + +查询包含 dai 的所有文档:`GET /_search?q=dai` + + + +## 请求体查询 + +### 空查询 + +```json +GET _search +{ + "query" : { + "match_all": {} + } +} +``` + + + + +### 提升权重 + +我们可以通过指定 `boost` 来控制任何查询语句的相对的权重, `boost` 的默认值为 `1` ,大于 `1` 会提升一个语句的相对权重。 + +```json +GET /company/employee/_search +{ + "query": { + "bool": { + "must": { + "match": { + "interests": { + "query": "sport music", + "operator": "and" + } + } + }, + "should": [ + { "match": { + "first_name": { + "query": "tyson", + "boost": 3 + } + }}, + { "match": { + "first_name": { + "query": "sophia", + "boost": 2 + } + }} + ] + } + } +} +``` + +### explain + +查询结果说明。 + +```json +GET /_validate/query?explain +{ + "query": { + "match" : { + "interests" : "sport shoes" + } + } +} +``` + +结果: + +```json +{ + "valid": true, + "_shards": { + "total": 3, + "successful": 3, + "failed": 0 + }, + "explanations": [ + { + "index": "class", + "valid": true, + "explanation": "interests:sport interests:shoes" + }, + { + "index": "company", + "valid": true, + "explanation": "interests:sport interests:shoes" + } + ] +} +``` + +### 查询和过滤器的区别 + +查询会计算得分,而过滤不计算得分,过滤器所需处理更少,所以过滤器可以比普通查询更快。而且过滤器可以被缓存。 + + + +## 排序与相关性 + +有时,_score 相关性评分对你来说并没有意义。例如,下面的查询返回所有 `user_id` 字段包含 `1` 的结果: + +```json +GET /_search +{ + "query" : { + "constant_score" : { + "filter" : { + "term" : { + "id" : 1 + } + } + } + } +} +``` + +### 按照字段的值排序 + +按照 hire_date 排序。 + +```json +GET _search +{ + "query" : { + "bool" : { + "filter" : { + "match" : { + "first_name" : "tyson" + } + } + } + }, + "sort" : { + "hire_date" : { "order" : "desc" } + } +} +``` + +### 多级排序 + +首先按第一个条件排序,仅当结果集的第一个 `sort` 值完全相同时才会按照第二个条件进行排序,以此类推。 + +```json +GET _search +{ + "query" : { + "bool" : { + "filter" : { + "match" : { + "first_name" : "tyson" + } + } + } + }, + "sort" : { + "hire_date" : { "order" : "desc" }, + "_score" : { "order" : "desc" } + } +} +``` + +Query-string 搜索 也支持自定义排序,可以在查询字符串中使用 `sort` 参数: + +```js +GET /_search?sort=hire_date:desc&sort=_score +``` + +### 多值字段的排序 + +对于数字或日期,你可以将多值字段减为单值,这可以通过使用 `min` 、 `max` 、 `avg` 或是 `sum` 排序模式。 例如你可以按照每个 hire_date 字段中的最早日期进行排序,通过以下方法: + +```json +"sort": { + "hire_date": { + "order": "asc", + "mode": "min" + } +} +``` + +### 字符串排序 + +为了对字符串字段进行排序,需要用两种方式对同一个字符串进行索引: `analyzed` 用于搜索, `not_analyzed` 用于排序。 + +用两种方式索引一个单字段: + +```json +"interests": { + "type": "string", + "analyzer": "english", + "fields": { + "raw": { + "type": "string", + "index": "not_analyzed" + } + } +} +``` + +interests.raw 子字段是 not_analyzed。interests 字段只在 _source 中出现一次。 + +使用 interests 字段用于搜索,interests.raw 字段用于排序: + +```json +GET /_search +{ + "query": { + "match": { + "interests": "elasticsearch" + } + }, + "sort": "interests.raw" +} +``` + +备注:以全文 `analyzed` 字段排序会消耗大量的内存。 + + + +## 索引管理 + +### 创建索引 + +```json +PUT /my_index +{ + "settings": { ... any settings ... }, + "mappings": { + "type_one": { ... any mappings ... }, + "type_two": { ... any mappings ... }, + ... + } +} +``` + +禁止自动创建索引,你 可以通过在 `config/elasticsearch.yml` 的每个节点下添加下面的配置: + +`action.auto_create_index: false` + +### 删除索引 + +`DELETE /company,student` + +`DELETE /index_*` + +`DELETE /_all` 或 `DELETE /*` + +### 索引设置 + +number_of_shards:每个索引的主分片数,默认值是 `5` 。这个配置在索引创建后不能修改。 + +number_of_replicas:每个主分片的副本数,默认值是 `1` 。对于活动的索引库,这个配置可以随时修改。 + +创建只有 一个主分片,没有副本的小索引: + +```json +PUT /my_temp_index +{ + "settings": { + "number_of_shards" : 1, + "number_of_replicas" : 0 + } +} +``` + + 动态修改副本数: + +```json +PUT /my_temp_index/_settings +{ + "number_of_replicas": 1 +} +``` + +### 配置分析器 + +#### 自定义分析器 + +,一个分析器组合了三种函数:字符过滤器、分词器和词单元过滤器, 三种函数按照顺序被执行。 + +```json +PUT /my_index +{ + "settings": { + "analysis": { + "char_filter": { + "&_to_and" : { + "type" : "mapping", + "mappings" : ["&=>and"] + } + }, + "filter": { + "my_stopwords" : { + "type" : "stop", + "stopwords" : ["the", "a"] + } + }, + "analyzer": { + "my_analyzer" : { + "type" : "custom", + "char_filter" : ["html_strip", "&_to_and"], + "tokenizer" : "standard", + "filter" : ["lowercase", "my_stopwords"] + } + } + } + } +} +``` + +测试: + +```json +GET /my_index/_analyze +{ + "analyzer" : "my_analyzer", + "text" : "The quick & brown fox" +} +``` + +结果: + +```json +{ + "tokens": [ + { + "token": "quick", + "start_offset": 4, + "end_offset": 9, + "type": "", + "position": 1 + }, + { + "token": "and", + "start_offset": 10, + "end_offset": 11, + "type": "", + "position": 2 + }, + { + "token": "brown", + "start_offset": 12, + "end_offset": 17, + "type": "", + "position": 3 + }, + { + "token": "fox", + "start_offset": 18, + "end_offset": 21, + "type": "", + "position": 4 + } + ] +} +``` + +把分析器应用在 string 字段上: + +```json +PUT /my_index/_mapping/my_type +{ + "properties": { + "title": { + "type": "string", + "analyzer": "my_analyzer" + } + } +} +``` + +### 类型和映射 + +同一个索引下,不同的类型type应该有相同的结构,映射也应该相同。因为 Lucene 会将同一个索引下的所有字段的映射扁平化,相同字段不同映射会导致冲突。 + +```json +{ + "data": { + "mappings": { + "people": { + "properties": { + "name": { + "type": "string", + }, + "address": { + "type": "string" + } + } + }, + "transactions": { + "properties": { + "timestamp": { + "type": "date", + "format": "strict_date_optional_time" + }, + "message": { + "type": "string" + } + } + } + } + } +} +``` + +后台 Lucene 将创建一个映射: + +```json +{ + "data": { + "mappings": { + "_type": { + "type": "string", + "index": "not_analyzed" + }, + "name": { + "type": "string" + } + "address": { + "type": "string" + } + "timestamp": { + "type": "long" + } + "message": { + "type": "string" + } + } + } +} +``` + +因此,类型不适合 *完全不同类型的数据* 。如果两个类型的字段集是互不相同的,这就意味着索引中将有一半的数据是空的(字段将是 *稀疏的* ),最终将导致性能问题。在这种情况下,最好是使用两个单独的索引。 + + +### 根对象 + +映射最高的一层被称为根对象。它可能包含以下几项: + +- properties 节点,列出文档每个字段的映射 +- 下划线开头的元数据字段,如 \_type,_id 和 \_source +- 设置项,控制如何动态处理新的字段,例如 `analyzer` 、 `dynamic_date_formats` 和`dynamic_templates` +- 其他设置,可以同时应用在根对象和其他 `object` 类型的字段上,例如 `enabled` 、 `dynamic` 和 `include_in_all` + + + +## 分片内部原理 + +### 倒排索引 + +倒排索引包含一个有序列表,列表包含所有文档出现过的不重复个体,或称为 *词项* ,对于每一个词项,包含了它所有曾出现过文档的列表。 + +| Term | doc1 | doc2 | doc3 | +| ----- | ---- | ---- | ---- | +| sport | x | | x | +| music | | x | | +| chess | x | x | x | + + + +## 深入搜索 + +### 精确值查找 + +term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 `not_analyzed` 的字符串。 + +```json +GET /company/employee/_search +{ + "query" : { + "term" : { + "interests" : "listen" + } + } +} +``` + +hire_date 在过去四年内的文档: + +```json +GET company/employee/_search +{ + "query": { + "constant_score": { + "filter": { + "range": { + "hire_date": { + "gt": "now-4y" + } + } + } + } + } +} +``` + +#### term 查询文本 + +删除旧索引(因为旧索引字段都是 analyzed 的,它的映射不正确)然后创建一个能正确映射的新索引: + +```json +PUT /my_store +{ + "mappings" : { + "products" : { + "properties": { + "productID" : { + "type" : "keyword",//es6废除了string,index是boolean值,keyword不分词,text分词 + } + } + } + } +} +``` + +放进数据: + +```json +POST /my_store/products/_bulk +{ "index": { "_id": 1 }} +{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" } +{ "index": { "_id": 2 }} +{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" } +{ "index": { "_id": 3 }} +{ "price" : 30, "productID" : "JODL-X-1937-#pV7" } +{ "index": { "_id": 4 }} +{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" } +``` + +查询文本: + +```json +GET /my_store/products/_search +{ + "query" : { + "constant_score" : { + "filter" : { + "term" : { + "productID" : "XHDK-A-1293-#fJ3" + } + } + } + } +} +``` + +#### terms 查询 + +允许指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件。 + +```json +GET /company/employee/_search +{ + "query" : { + "terms" : { + "interests" : ["listen", "music", "sport"] + } + } +} +``` + +置入 `filter` 语句的常量评分查询: + +```json +GET /my_store/products/_search +{ + "query": { + "constant_score": { + "filter": { + "terms" : { + "interests" : ["listen", "music", "sport"] + } + }, + "boost": 1.2 + } + } +} +``` + +interests 为 listen、music 和 sport 的文档会被匹配。 + +### 全文搜索 + +#### match 查询 + +match 查询是对全文进行查询。 + +如果有多个搜索关键字, Elastic 认为它们是`or`关系。下面例子返回 interests 为 sport 或者 music 的文档。 + +```json +GET _search +{ + "query" : { + "match": { + "interests": "sport music" + } + } +} +``` + +指定词都必须匹配: + +```json +GET _search +{ + "query" : { + "match": { + "interests": { + "query": "sport music", + "operator": "and" + } + } + } +} +``` + +控制匹配的字段数目: + +```json +GET _search +{ + "query" : { + "match": { + "interests": { + "query": "sport music", + "minimum_should_match": 2 + } + } + } +} +``` + +### range 查询 + +查询找出那些落在指定区间内的数字或者时间。 + +#### 数字范围 + +```json +GET company/employee/_search +{ + "query": { + "constant_score": { + "filter": { + "range": { + "age": { + "gt": 20, + "lt": 100 + } + } + } + } + } +} +``` + +`gt`:大于;`gte`:大于或等于;`lt`:小于;`lte`:小于或等于。 + +#### 日期范围 + +```json +GET company/employee/_search +{ + "query": { + "constant_score": { + "filter": { + "range": { + "hire_date": { + "gt": "2015-01-01", + "lt": "2019-01-01" + } + } + } + } + } +} +``` + +### 分页 + +请求得到 1 到 3 页的结果: + +```json +GET /_search?size=5 +GET /_search?size=5&from=5 +GET /_search?size=5&from=10 +``` + +### exists 查询 + +查询字段 interests 中不为空的文档: + +```json +GET /company/employee/_search +{ + "query": { + "constant_score": { + "filter": { + "exists": { + "field": "interests" + } + } + } + } +} +``` + +字段 interests 为空的文档。es6 没有 missing api,直接用 bool 和 exists 实现。 + +```json +GET /company/employee/_search +{ + "query": { + "bool": { + "must_not": { + "exists": { + "field": "interests" + } + } + } + } +} +``` + +### bool 组合查询 + +bool 查询允许在单独的查询中组合任意数量的查询,适用于将不同查询字符串映射到不同字段的情况。bool 查询接收如下参数: + +- must:文档必须匹配这些条件才能被包含进来 +- must_not:文档必须不匹配这些条件才能被包含进来 +- should:如果满足这些语句中的任意语句,将增加 _score,否则没有影响。主要用来修正每个文档的相关性得分 +- filter:必须匹配,但是不影响评分 + +如果没有 `must` 语句,那么至少需要能够匹配其中的一条 `should` 语句。但,如果存在至少一条 `must` 语句,则对 `should` 语句的匹配没有要求。 + +```json +GET /company/employee/_search +{ + "query" : { + "bool" : { + "must" : { "match" : {"first_name" : "tyson"}}, + "must_not" : { "match" : {"last_name" : "tang"}}, + "should" : [ + {"match" : {"interest" : "music"}}, + {"range" : {"age" : { "gte" : 30 }}} + ] + } + } +} +``` + +如果不想因为文档的时间而影响得分,可以添加 filter 过滤掉某个时间段。 + +```json +GET _search +{ + "query" : { + "bool" : { + "must" : { + "match" : { "first_name" : "tyson"} + }, + "must_not" : { + "match" : {"last_name" : "tang"} + }, + "should" : [ + {"match" : { "interests": "sport"}}, + {"range" : { "age" : { "gt" : 20 }}} + ], + "filter" : { + "range" : { "hire_date" : { "gt" : "2015-01-01" }} + } + } + } +} +``` + +可以将查询移到 `bool` 查询的 `filter` 语句中,这样它就自动的转成一个不评分的查询了。 + +```json +{ + "bool": { + "must": { "match": { "title": "how to make millions" }}, + "must_not": { "match": { "tag": "spam" }}, + "should": [ + { "match": { "tag": "starred" }} + ], + "filter": { + "bool": { + "must": [ + { "range": { "date": { "gte": "2014-01-01" }}}, + { "range": { "price": { "lte": 29.99 }}} + ], + "must_not": [ + { "term": { "category": "ebooks" }} + ] + } + } + } +} +``` + +bool 查询使用`minimum_should_match`控制需要匹配的 should 语句的数量: + +```json +GET /my_index/my_type/_search +{ + "query": { + "bool": { + "should": [ + { "match": { "title": "brown" }}, + { "match": { "title": "fox" }}, + { "match": { "title": "dog" }} + ], + "minimum_should_match": 2 + } + } +} +``` + +### 如何使用 bool 查询 + +多次 match 查询: + +```json +GET /company/employee/_search +{ + "query": { + "match": { + "interests": "sport music" + } + } +} +``` + +等价的 bool 查询(存在`must`,则对 `should` 语句的匹配没有要求,否则至少需要能够匹配其中的一条 `should` 语句): + +```json +GET /company/employee/_search +{ + "query": { + "bool": { + "should": [ + { "term" : { "interests": "sport" } }, + { "term" : { "interests" : "music" } } + ] + } + } +} +``` + +使用 and 操作符,返回所有字段都匹配到的文档: + +```json +GET /company/employee/_search +{ + "query": { + "match": { + "interests": { + "query": "sport music", + "operator": "and" + } + } + } +} +``` + +等价的 bool 查询: + +```json +GET /company/employee/_search +{ + "query": { + "bool": { + "must": [ + { "term": { "interests": "sport" }}, + { "term": { "interests": "music" }} + ] + } + } +} +``` + +指定参数 minimum_should_match: + +```json +GET /company/employee/_search +{ + "query": { + "match": { + "interests": { + "query": "sport music chess", + "minimum_should_match" : 2 + } + } + } +} +``` + +等价的 bool 查询: + +```json +GET /company/employee/_search +{ + "query": { + "bool": { + "should": [ + {"term": { "interests": "sport" }}, + {"term": { "interests": "music" }}, + {"term": { "interests": "chess" }} + ], + "minimum_should_match": 2 + } + } +} +``` + +### constant_score 查询 + +constant_score 查询返回的文档`score`都是1。它经常用于只需要执行一个 filter 而没有其它查询的情况下。`score`会受到`boost`影响,出现 tyson 的文档`score`为1.2。 + +```json +GET _search +{ + "query" : { + "constant_score": { + "filter": { + "match" : { "first_name" : "tyson"} + }, + "boost": 1.2 + } + } +} +``` + + + + +### 多字段搜索 + +参考自:[best_fields most_fields cross_fields从内在实现看区别——本质就是前两者是以field为中心,后者是词条为中心](https://www.cnblogs.com/bonelee/p/6827068.html) + +最佳字段 best_fields:搜索结果中应该返回某一个字段匹配到了最多的关键词的文档。 + +多数字段 most_fields:返回匹配了更多的字段的文档,尽可能多地匹配文档。ES会为每个字段生成一个match查询,然后将它们包含在一个bool查询中。 + +跨字段 cross_fields:每个查询的单词都出现在不同的字段中。*cross_fields类型采用了一种以词条为中心(Term-centric)的方法,这种方法和best_fields及most_fields采用的以字段为中心(Field-centric)的方法有很大的区别。它将所有的字段视为一个大的字段,然后在任一字段中搜索每个词条。 + +#### 多字符串查询 + +```json +GET /_search +{ + "query": { + "bool": { + "should": [ + { "match": { // 权重:1/3 + "title": { + "query": "War and Peace", + "boost": 2 + }}}, + { "match": { // 权重:1/3 + "author": { + "query": "Leo Tolstoy", + "boost": 2 + }}}, + { "bool": { //译者信息用布尔查询,降低评分权重 权重:1/3 + "should": [ + { "match": { "translator": "Constance Garnett" }}, + { "match": { "translator": "Louise Maude" }} + ] + }} + ] + } + } +} +``` + +#### multi_match 查询 + +multi_match 查询可以在多个字段上执行相同的 match 查询。`multi_match` 多匹配查询的类型有三种:`best_fields` 、 `most_fields` 和 `cross_fields` (最佳字段、多数字段、跨字段)。 + +```json +GET company/employee/_search +{ + "query" : { + "multi_match": { + "query": "sport shoes", + "type": "best_fields", + "fields": [ "interests", "first_name" ], + "tie_breaker": 0.3, + "minimum_should_match": 1 + } + } +} +``` + +模糊匹配: + +```json +GET company/employee/_search +{ + "query" : { + "multi_match": { + "query": "tyson dai", + "type": "best_fields", + "fields": "*_name", + "tie_breaker": 0.3, + "minimum_should_match": "30%" + } + } +} +``` + +提升字段的权重,first_name 字段的 `boost` 值为 `2` : + +```json +GET company/employee/_search +{ + "query" : { + "multi_match": { + "query": "tyson dai", + "type": "best_fields", + "fields": ["*_name", "first_name^3"], + "tie_breaker": 0.3, + "minimum_should_match": "30%" + } + } +} +``` + +#### 多字段映射 + +对字段索引两次: 一次使用词干模式以及一次非词干模式。 + +```json +DELETE /my_index + +PUT /my_index +{ + "settings": { "number_of_shards": 1 }, + "mappings": { + "my_type": { + "properties": { + "title": { + "type": "string", + "analyzer": "english",//提取词干 + "fields": { + "std": { + "type": "string", + "analyzer": "standard" + } + } + } + } + } + } +} +``` + +`title` 字段使用 `english` 分析器来提取词干;`title.std` 字段使用 `standard` 标准分析器,所以没有词干提取。 + +索引文档: + +```json +PUT /my_index/my_type/1 +{ "title": "My rabbit jumps" } + +PUT /my_index/my_type/2 +{ "title": "Jumping jack rabbits" } +``` + +multi_match 查询: + +```json +GET /my_index/_search +{ + "query": { + "multi_match": { + "query": "jumping rabbits", + "type": "most_fields", + "fields": [ "title", "title.std" ] + } + } +} +``` + +文档2匹配度更高,因为 title.std 不会提取词干,只有文档2是匹配的。 + +设置`title` 字段的 `boost` 的值为 `10`,提升 title 字段的权重: + +```json +GET /my_index/_search +{ + "query": { + "multi_match": { + "query": "jumping rabbits", + "type": "most_fields", + "fields": [ "title^10", "title.std" ] + } + } +} +``` + +#### copy_to 定制组合 field + +定制组合 field 与 cross_field 跨字段查询类似,根据两者的实际性能选择具体方案。 + +创建映射: + +```json +PUT my_index1 +{ + "mappings": { + "my_type": { + "properties": { + "first_name": { + "type": "keyword", + "copy_to": "full_name" + }, + "last_name": { + "type": "keyword", + "copy_to": "full_name" + }, + "full_name": { + "type": "text", + "fielddata": true + } + } + } + } +} +``` + +插入数据: + +```json +PUT my_index1/my_type/1 +{ + "first_name": "John", + "last_name": "Smith" +} +``` + +校验查询: + +```json +GET my_index1/_search +{ + "query": { + "match": { + "full_name": { + "query": "John Smith", + "operator": "and" + } + } + } +} + +``` + +`copy_to` 设置对 multi-field 无效。如果尝试这样配置映射,Elasticsearch 会抛异常。多字段只是以不同方式简单索引主字段;它们没有自己的数据源。 + +```json +PUT /my_index +{ + "mappings": { + "person": { + "properties": { + "first_name": { + "type": "string", + "copy_to": "full_name", + "fields": { + "raw": { + "type": "string", + "index": "not_analyzed" + } + } + }, + "full_name": { + "type": "string" + } + } + } + } +} +``` + +first_name 是主字段,first_name.raw 是多字段。 + + + +## springboot 集成 es + +[springboot 集成 es](https://blog.csdn.net/cwenao/article/details/54943505) + +[springboot整合elasticsearch5.x以及IK分词器做全文检索](https://blog.csdn.net/chenxihua1/article/details/94546282) + + + +## mall + +创建文档: + +```json +POST /pms/product +{ + "productSn": "HNTBJ2E080A", + "brandId": 50, + "brandName": "海澜之家", + "productCategoryId": 8, + "productCategoryName": "T恤", + "pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5ac98b64N70acd82f.jpg!cc_350x449.jpg", + "name": "HLA海澜之家蓝灰花纹圆领针织布短袖T恤", + "subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 蓝灰花纹80 175/92A/L80A 蓝灰花纹80 175/92A/L", + "keywords": "", + "price": 98, + "sale": 0, + "newStatus": 0, + "recommandStatus": 0, + "stock": 100, + "promotionType": 0, + "sort": 0, + "attrValueList": [ + { + "id": 183, + "productAttributeId": 24, + "value": null, + "type": 1, + "name": "商品编号" + }, + { + "id": 184, + "productAttributeId": 25, + "value": "夏季", + "type": 1, + "name": "适用季节" + } + ] +} +``` + +获取文档映射:`GET /pms/_mapping/product` + +按字段查询:`GET /pms/product/_search?q=subTitle:2018` + +match查询: + +```json +GET /pms/product/_search +{ + "query": { + "match": { + "brandName": "小米" + } + } +} +``` + + + + + diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index d5704d2..914796d 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -435,6 +435,8 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 缓存穿透是指查询一个**不存在的数据**,由于缓存是不命中时被动写的,如果从DB查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了。 +怎么解决? + 1. **缓存空值**,不会查数据库。 2. 采用**布隆过滤器**,将所有可能存在的数据哈希到一个足够大的`bitmap`中,查询不存在的数据会被这个`bitmap`拦截掉,从而避免了对`DB`的查询压力。 diff --git "a/\345\205\266\344\273\226/\345\256\236\346\210\230\347\257\207.md" "b/\345\205\266\344\273\226/\345\256\236\346\210\230\347\257\207.md" new file mode 100644 index 0000000..7d5164d --- /dev/null +++ "b/\345\205\266\344\273\226/\345\256\236\346\210\230\347\257\207.md" @@ -0,0 +1,93 @@ +## OOM问题排查 + +[记一次OOM问题排查!](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247486106&idx=1&sn=0d528efad06f0a1440e02983bf336bca&chksm=ce98f7dcf9ef7ecafee10115f1d29bfba56dd8bf694122dd2cb69a53f333b2242522f88aa92e&token=1360123733&lang=zh_CN#rd) + + + +## RT过长,排查思路 + +[Java诊断工具Arthas](https://mp.weixin.qq.com/s/TnLl2OW9XJLSZihcpgP7VQ) + + + +## 限流算法 + +限流是指在系统面临高并发、大流量请求的情况下,限制新的流量对系统的访问,从而保证系统服务的安全性。常用的限流算法有计数器固定窗口算法、滑动窗口算法、漏斗算法和令牌桶算法。 + +### 计数器固定窗口算法 + +计数器固定窗口算法是最基础也是最简单的一种限流算法。原理就是对一段固定时间窗口内的请求进行计数,如果请求数超过了阈值,则舍弃该请求;如果没有达到设定的阈值,则接受该请求,且计数加1。当时间窗口结束时,重置计数器为0。 + +**优点**:实现简单,容易理解。 + +**缺点**:流量曲线可能不够平滑,有“突刺现象”,这样会有两个问题: + +1. **一段时间内(不超过时间窗口)系统服务不可用**。比如窗口大小为1s,限流大小为100,然后恰好在某个窗口的第1ms来了100个请求,然后第2ms-999ms的请求就都会被拒绝,这段时间用户会感觉系统服务不可用。 +2. **窗口切换时可能会产生两倍于阈值流量的请求**。比如窗口大小为1s,限流大小为100,然后恰好在某个窗口的第999ms来了100个请求,窗口前期没有请求,所以这100个请求都会通过。再恰好,下一个窗口的第1ms有来了100个请求,也全部通过了,那也就是在2ms之内通过了200个请求,而我们设定的阈值是100,通过的请求达到了阈值的两倍。 + +### 计数器滑动窗口算法 + +计数器滑动窗口算法是计数器固定窗口算法的改进,解决了固定窗口切换时可能会产生两倍于阈值流量请求的缺点。 + +滑动窗口算法在固定窗口的基础上,将一个计时窗口分成了若干个小窗口,然后每个小窗口维护一个独立的计数器。当请求的时间大于当前窗口的最大时间时,则将计时窗口向前平移一个小窗口。平移时,将第一个小窗口的数据丢弃,然后将第二个小窗口设置为第一个小窗口,同时在最后面新增一个小窗口,将新的请求放在新增的小窗口中。同时要保证整个窗口中所有小窗口的请求数目之后不能超过设定的阈值。 + +将计时窗口划分成一个小窗口,滑动窗口算法就退化成了固定窗口算法。而滑动窗口算法其实就是对请求数进行了更细粒度的限流,窗口划分的越多,则限流越精准。 + +**特点分析** + +1. 避免了计数器固定窗口算法固定窗口切换时可能会产生两倍于阈值流量请求的问题; +2. 和漏斗算法相比,新来的请求也能够被处理到,避免了漏斗算法的饥饿问题。 + +### 漏斗算法 + +漏斗算法的原理也很容易理解。请求来了之后会首先进到漏斗里,然后漏斗以恒定的速率将请求流出进行处理,从而起到平滑流量的作用。当请求的流量过大时,漏斗达到最大容量时会溢出,此时请求被丢弃。从系统的角度来看,我们不知道什么时候会有请求来,也不知道请求会以多大的速率来,这就给系统的安全性埋下了隐患。但是如果加了一层漏斗算法限流之后,就能够保证请求以恒定的速率流出。在系统看来,请求永远是以平滑的传输速率过来,从而起到了保护系统的作用。 + +**特点分析** + +1. **漏桶的漏出速率是固定的,可以起到整流的作用**。即虽然请求的流量可能具有随机性,忽大忽小,但是经过漏斗算法之后,变成了有固定速率的稳定流量,从而对下游的系统起到保护作用。 +2. **不能解决流量突发的问题**。假如设定的漏斗速率是2个/秒,漏斗限流算法的容量是5。然后突然来了10个请求,受限于漏斗的容量,只有5个请求被接受,另外5个被拒绝。你可能会说,漏斗速率是2个/秒,然后瞬间接受了5个请求,这不就解决了流量突发的问题吗?不,这5个请求只是被接受了,但是没有马上被处理,处理的速度仍然是我们设定的2个/秒,所以没有解决流量突发的问题。而接下来我们要谈的令牌桶算法能够在一定程度上解决流量突发的问题。 + +### 令牌桶算法 + +令牌桶算法是对漏斗算法的一种改进,除了能够起到限流的作用外,还允许一定程度的流量突发。在令牌桶算法中,存在一个令牌桶,算法中存在一种机制以恒定的速率向令牌桶中放入令牌。令牌桶也有一定的容量,如果满了令牌就无法放进去了。当请求来时,会首先到令牌桶中去拿令牌,如果拿到了令牌,则该请求会被处理,并消耗掉拿到的令牌;如果令牌桶为空,则该请求会被丢弃。 + +比如过来10个请求,令牌桶算法和漏斗算法一样,都是接受了5个请求,拒绝了5个请求。与漏斗算法不同的是,令牌桶算法马上处理了这5个请求,处理速度可以认为是5个/秒,超过了我们设定的2个/秒的速率,即**允许一定程度的流量突发**。这一点也是和漏斗算法的主要区别。 + +**特点分析** + +令牌桶算法是对漏桶算法的一种改进,除了能够在限制调用的平均速率的同时还允许一定程度的流量突发。 + +### 小结 + +**计数器固定窗口算法**实现简单,容易理解。和漏斗算法相比,新来的请求也能够被马上处理到。但是流量曲线可能不够平滑,有“突刺现象”,在窗口切换时可能会产生两倍于阈值流量的请求。而**计数器滑动窗口算法**作为计数器固定窗口算法的一种改进,有效解决了窗口切换时可能会产生两倍于阈值流量请求的问题。 + +**漏斗算法**能够对流量起到整流的作用,让随机不稳定的流量以固定的速率流出,但是不能解决**流量突发**的问题。**令牌桶算法**作为漏斗算法的一种改进,除了能够起到平滑流量的作用,还允许一定程度的流量突发。 + +令牌桶算法一般用于保护自身的系统,对调用者进行限流,保护自身的系统不被突发的流量打垮。如果自身的系统实际的处理能力强于配置的流量限制时,可以允许一定程度的流量突发,使得实际的处理速率高于配置的速率,充分利用系统资源。而漏斗算法一般用于保护第三方的系统,比如自身的系统需要调用第三方的接口,为了保护第三方的系统不被自身的调用打垮,便可以通过漏斗算法进行限流,保证自身的流量平稳的打到第三方的接口上。 + +参考:https://zhuanlan.zhihu.com/p/228412634 + + + +## 亿级数据分页查询难怎么解决? + +无深翻页需求的实时在线应用:禁止深翻页,数据库 offset < N。 + +确有深翻页需求的离线分析应用:es搜scroll,jdbc自己维护这个读取游标的长链接,持续流式读取。 + + + +## 秒杀场景 + +并发修改库存,会加行锁。rt较高,tps上不去。两种方案: + +1. 分库分表。减小锁粒度 +2. 降低锁的持有时间 + +可以在内存起一个队列,将用户请求放进队列。起一个异步线程,每200ms处理队列数据,批量扣库存。这样就不用每个请求都去扣减库存,减少行锁持有时间。 + +每个请求封装一个锁对象(锁里面包含购买数量),丢进队列,调用wait(200)。当扣库存完成后拿到锁对象执行notify,通知用户请求线程继续往下执行。即每个用户线程都会有一个锁对象,用来阻塞和通知,阻塞是最多200ms + + + +## MySQL表数据量大 diff --git "a/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" "b/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" new file mode 100644 index 0000000..383686b --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" @@ -0,0 +1,49 @@ +一、背景 +基于RokcetMQ可以实现异步处理、流量削锋、业务解耦,通常是依赖RocketMQ的发布订阅模式。今天分享RocketMQ的新特性,基于Request/Reply模式来实现RPC的功能。该模式是在v4.6作为RocketMQ新特性引入,但在在v4.7.1上才比较完善。 + +二、设计思路 +从整个数据流的角度上来说,发布/订阅模式中生产者和消费者之间是异步处理的,生产者负责把消息投递到RocketMQ上,而消费者负责处理数据,如果把生产者当做上游系统,消费者是下游系统,那么上下游系统之间是没有任何的状态交流的。而我们知道,RPC上下游系统之间是需要状态交互的,简单来说,要想实现RPC功能,在整个数据链路上,原先上下游系统之间是异步交互的模式,首先需要把异步模式换成同步模式。 + +异步模式: + +把异步模式换成同步模式,需要在生产者发送消息到MQ之后,保持原有的状态,比如可以用一个Map集合去统一维护,等到消费者处理完数据返回响应后,再从Map集合中拿到对应的请求进行处理。其中涉及到怎么去标识一个请求,这里可以用UUID或者雪花id去标记。 + +同步模式: + +RocketMQ整体的处理思路跟上面是类似的,DefaultMQProducerImpl#request负责RPC消息的下发,而DefaultMQPushConsumer中负责消息的消费。具体用法可以看RocketMQ源码example中的RPC部分。 + + +三、结构定义 +RocketMQ中是依赖于Message的Properties来区分不同的请求,在调用DefaultMQProducerImpl#request进行消息下发之间会先给消息设置不同的属性,通过属性来保证上下游之间的处理是同一个请求。 + +设置的属性有: + +CORRELATION_ID:消息的标识Id,这里对应是一个UUID +REPLY_TO_CLIENT:消息下发的客户端Id +TTL:消息下发的超时时间,单位ms + +其实就类似于HTTP请求中的头部内容一样。 + +之后还会校验一下消息中对应Topic的一个合法性。 + +四、消息下发 +RocketMQ将下发的客户端封装成RequestResponseFuture,包含客户端Id,请求超时时间,同时根据客户端Id维护在ConcurrentHashMap,调用DefaultMQProducerImpl#sendDefaultImpl下发消息,根据下发消息的回调函数确认消息下发的状态。 + +消息下发后会调用waitResponse,waitResponse调用CountDownLatch进入阻塞状态,等待消息消费之后的响应。 + +CountDownLatch中的计数器是1,说明每个请求都会独立隔离阻塞。 + + +五、消息响应 +当服务端(消费者)收到消息处理完返回响应时,会调用ReplyMessageProcessor#pushReplyMessage封装响应的内容,处理响应的头部信息和返回body的参数,最终封装成一个PUSH_REPLY_MESSAGE_TO_CLIENT的请求命令发给客户端。 + +客户端(生产者)收到请求后,会调用ClientRemotingProcessor#processRequest,判断是PUSH_REPLY_MESSAGE_TO_CLIENT命令会调用receiveReplyMessage,将接收到的数据封装成新的消息,接着调用响应处理的处理器。 + +ClientRemotingProcessor#processReplyMessage中主要做的从消息中获取消息的Id,从ConcurrentHashMap中定位到具体的请求,将返回消息封装到RequestResponseFuture中,同时CountDownLatch的计数值减1,此时线程阻塞状态被释放,之后便将消息响应给到客户端。 + +六、总结 +所以整体上看来,RocketMQ的Request/Reply模式,其实是利用客户端线程阻塞来换取请求异步变同步以及RocketMQ的回调机制从而间接的实现了RPC效果,但是相比直接RPC调用,数据的链路更长,性能肯定是会有损耗,但是请求会持久化,所以给了重复下发提供了可能。 + +———————————————— +版权声明:本文为CSDN博主「林风自在」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 +原文链接:https://blog.csdn.net/lveex/article/details/122514893 \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" "b/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" new file mode 100644 index 0000000..59b6f58 --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" @@ -0,0 +1,485 @@ +传统的单体架构的时候,我们基本是单库然后业务单表的结构。每个业务表的ID一般我们都是从1增,通过`AUTO_INCREMENT=1`设置自增起始值,但是在分布式服务架构模式下分库分表的设计,使得多个库或多个表存储相同的业务数据。这种情况根据数据库的自增ID就会产生相同ID的情况,不能保证主键的唯一性。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508235751.png) + +如上图,如果第一个订单存储在 DB1 上则订单 ID 为1,当一个新订单又入库了存储在 DB2 上订单 ID 也为1。我们系统的架构虽然是分布式的,但是在用户层应是无感知的,重复的订单主键显而易见是不被允许的。那么针对分布式系统如何做到主键唯一性呢? + +# UUID + +UUID (Universally Unique Identifier),通用唯一识别码的缩写。UUID是由一组32位数的16进制数字所构成,所以UUID理论上的总数为 1632=2128,约等于 3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。 + +生成的UUID是由 `8-4-4-4-12`格式的数据组成,其中32个字符和4个连字符' - ',一般我们使用的时候会将连字符删除 `uuid.toString().replaceAll("-","")`。 + +目前UUID的产生方式有5种版本,每个版本的算法不同,应用范围也不同。 + +- **基于时间的UUID - 版本1**: + 这个一般是通过当前时间,随机数,和本地Mac地址来计算出来,可以通过 `org.apache.logging.log4j.core.util`包中的 `UuidUtil.getTimeBasedUuid()`来使用或者其他包中工具。由于使用了MAC地址,因此能够确保唯一性,但是同时也暴露了MAC地址,私密性不够好。 +- **DCE安全的UUID - 版本2** + DCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少用到。 +- **基于名字的UUID(MD5)- 版本3** + 基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。 +- **随机UUID - 版本4** + 根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但是重复的可能性可以忽略不计,因此该版本也是被经常使用的版本。JDK中使用的就是这个版本。 +- **基于名字的UUID(SHA1) - 版本5** + 和基于名字的UUID算法类似,只是散列值计算使用SHA1(Secure Hash Algorithm 1)算法。 + +我们 Java中 JDK自带的 UUID产生方式就是版本4根据随机数生成的 UUID 和版本3基于名字的 UUID,有兴趣的可以去看看它的源码。 + +```java +public static void main(String[] args) { + + //获取一个版本4根据随机字节数组的UUID。 + UUID uuid = UUID.randomUUID(); + System.out.println(uuid.toString().replaceAll("-","")); + + //获取一个版本3(基于名称)根据指定的字节数组的UUID。 + byte[] nbyte = {10, 20, 30}; + UUID uuidFromBytes = UUID.nameUUIDFromBytes(nbyte); + System.out.println(uuidFromBytes.toString().replaceAll("-","")); +} +``` + +得到的UUID结果, + +```undefined +59f51e7ea5ca453bbfaf2c1579f09f1d +7f49b84d0bbc38e9a493718013baace6 +``` + +虽然 UUID 生成方便,本地生成没有网络消耗,但是使用起来也有一些缺点, + +- 不易于存储:UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。 +- 信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,暴露使用者的位置。 +- 对MySQL索引不利:如果作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能,可以查阅 Mysql 索引原理 B+树的知识。 + +# 数据库生成 + +是不是一定要基于外界的条件才能满足分布式唯一ID的需求呢,我们能不能在我们分布式数据库的基础上获取我们需要的ID? + +由于分布式数据库的起始自增值一样所以才会有冲突的情况发生,那么我们将分布式系统中数据库的同一个业务表的自增ID设计成不一样的起始值,然后设置固定的步长,步长的值即为分库的数量或分表的数量。 + +以MySQL举例,利用给字段设置`auto_increment_increment`和`auto_increment_offset`来保证ID自增。 + +- auto_increment_offset:表示自增长字段从那个数开始,他的取值范围是1 .. 65535。 +- auto_increment_increment:表示自增长字段每次递增的量,其默认值是1,取值范围是1 .. 65535。 + +假设有三台机器,则DB1中order表的起始ID值为1,DB2中order表的起始值为2,DB3中order表的起始值为3,它们自增的步长都为3,则它们的ID生成范围如下图所示: + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000004.png) + +通过这种方式明显的优势就是依赖于数据库自身不需要其他资源,并且ID号单调自增,可以实现一些对ID有特殊要求的业务。 + +但是缺点也很明显,首先它强依赖DB,当DB异常时整个系统不可用。虽然配置主从复制可以尽可能的增加可用性,但是数据一致性在特殊情况下难以保证。主从切换时的不一致可能会导致重复发号。还有就是ID发号性能瓶颈限制在单台MySQL的读写性能。 + +# 使用redis实现 + +Redis实现分布式唯一ID主要是通过提供像 *INCR* 和 *INCRBY* 这样的自增原子命令,由于Redis自身的单线程的特点所以能保证生成的 ID 肯定是唯一有序的。 + +但是单机存在性能瓶颈,无法满足高并发的业务需求,所以可以采用集群的方式来实现。集群的方式又会涉及到和数据库集群同样的问题,所以也需要设置分段和步长来实现。 + +为了避免长期自增后数字过大可以通过与当前时间戳组合起来使用,另外为了保证并发和业务多线程的问题可以采用 Redis + Lua的方式进行编码,保证安全。 + +Redis 实现分布式全局唯一ID,它的性能比较高,生成的数据是有序的,对排序业务有利,但是同样它依赖于redis,需要系统引进redis组件,增加了系统的配置复杂性。 + +当然现在Redis的使用性很普遍,所以如果其他业务已经引进了Redis集群,则可以资源利用考虑使用Redis来实现。 + +# 雪花算法-Snowflake + +Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。 + +- 第1位占用1bit,其值始终是0,可看做是符号位不使用。 +- 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是(1L<<41)/(1000L*3600*24*365)=69 年的时间。 +- 中间的10-bit位可表示机器数,即2^10 = 1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将 10-bit 分 5-bit 给 IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。 +- 最后12-bit位是自增序列,可表示2^12 = 4096个数。 + +这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508235958.png) + +Snowflake 的[Twitter官方原版](https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala)是用Scala写的,对Scala语言有研究的同学可以去阅读下,以下是 Java 版本的写法。 + +```java +package com.jajian.demo.distribute; + +/** + * Twitter_Snowflake
+ * SnowFlake的结构如下(每部分用-分开):
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) + * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
+ * 加起来刚好64位,为一个Long型。
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 + */ +public class SnowflakeDistributeId { + + + // ==============================Fields=========================================== + /** + * 开始时间截 (2015-01-01) + */ + private final long twepoch = 1420041600000L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long datacenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private long workerId; + + /** + * 数据中心ID(0~31) + */ + private long datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + //==============================Constructors===================================== + + /** + * 构造函数 + * + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeDistributeId(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } +} +``` + +测试的代码如下 + +```java +public static void main(String[] args) { + SnowflakeDistributeId idWorker = new SnowflakeDistributeId(0, 0); + for (int i = 0; i < 1000; i++) { + long id = idWorker.nextId(); +// System.out.println(Long.toBinaryString(id)); + System.out.println(id); + } +} +``` + +雪花算法提供了一个很好的设计思想,雪花算法生成的ID是趋势递增,不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的,而且可以根据自身业务特性分配bit位,非常灵活。 + +但是雪花算法强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。如果恰巧回退前生成过一些ID,而时间回退后,生成的ID就有可能重复。官方对于此并没有给出解决方案,而是简单的抛错处理,这样会造成在时间被追回之前的这段时间服务不可用。 + +很多其他类雪花算法也是在此思想上的设计然后改进规避它的缺陷,后面介绍的百度 UidGenerator 和 美团分布式ID生成系统 Leaf 中snowflake模式都是在 snowflake 的基础上演进出来的。 + +# 百度-UidGenerator + +[百度的 UidGenerator](https://github.com/baidu/uid-generator) 是百度开源基于Java语言实现的唯一ID生成器,是在雪花算法 snowflake 的基础上做了一些改进。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略,适用于docker等虚拟化环境下实例自动重启、漂移等场景。 + +在实现上,UidGenerator 提供了两种生成唯一ID方式,分别是 DefaultUidGenerator 和 CachedUidGenerator,官方建议如果有性能考虑的话使用 CachedUidGenerator 方式实现。 + +UidGenerator 依然是以划分命名空间的方式将 64-bit位分割成多个部分,只不过它的默认划分方式有别于雪花算法 snowflake。它默认是由 1-28-22-13 的格式进行划分。可根据你的业务的情况和特点,自己调整各个字段占用的位数。 + +- 第1位仍然占用1bit,其值始终是0。 +- 第2位开始的28位是时间戳,28-bit位可表示2^28个数,**这里不再是以毫秒而是以秒为单位**,每个数代表秒则可用(1L<<28)/ (3600*24*365) ≈ 8.51 年的时间。 +- 中间的 workId (数据中心+工作机器,可以其他组成方式)则由 22-bit位组成,可表示 2^22 = 4194304个工作ID。 +- 最后由13-bit位构成自增序列,可表示2^13 = 8192个数。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000004.png) + +其中 workId (机器 id),最多可支持约420w次机器启动。内置实现为在启动时由数据库分配(表名为 WORKER_NODE),默认分配策略为用后即弃,后续可提供复用策略。 + +```sql +DROP TABLE IF EXISTS WORKER_NODE; +CREATE TABLE WORKER_NODE +( +ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id', +HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name', +PORT VARCHAR(64) NOT NULL COMMENT 'port', +TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER', +LAUNCH_DATE DATE NOT NULL COMMENT 'launch date', +MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time', +CREATED TIMESTAMP NOT NULL COMMENT 'created time', +PRIMARY KEY(ID) +) + COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB; +``` + +## DefaultUidGenerator 实现 + +DefaultUidGenerator 就是正常的根据时间戳和机器位还有序列号的生成方式,和雪花算法很相似,对于时钟回拨也只是抛异常处理。仅有一些不同,如以秒为为单位而不再是毫秒和支持Docker等虚拟化环境。 + +```java +protected synchronized long nextId() { + long currentSecond = getCurrentSecond(); + + // Clock moved backwards, refuse to generate uid + if (currentSecond < lastSecond) { + long refusedSeconds = lastSecond - currentSecond; + throw new UidGenerateException("Clock moved backwards. Refusing for %d seconds", refusedSeconds); + } + + // At the same second, increase sequence + if (currentSecond == lastSecond) { + sequence = (sequence + 1) & bitsAllocator.getMaxSequence(); + // Exceed the max sequence, we wait the next second to generate uid + if (sequence == 0) { + currentSecond = getNextSecond(lastSecond); + } + + // At the different second, sequence restart from zero + } else { + sequence = 0L; + } + + lastSecond = currentSecond; + + // Allocate bits for UID + return bitsAllocator.allocate(currentSecond - epochSeconds, workerId, sequence); +} +``` + +如果你要使用 DefaultUidGenerator 的实现方式的话,以上划分的占用位数可通过 spring 进行参数配置。 + +```xml + + + + + + + + + +``` + +## CachedUidGenerator 实现 + +而官方建议的性能较高的 CachedUidGenerator 生成方式,是使用 RingBuffer 缓存生成的id。数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值(2^13 = 8192)。可通过 boostPower 配置进行扩容,以提高 RingBuffer 读写吞吐量。 + +Tail指针、Cursor指针用于环形数组上读写slot: + +- Tail指针 + 表示Producer生产的最大序号(此序号从0开始,持续递增)。Tail不能超过Cursor,即生产者不能覆盖未消费的slot。当Tail已赶上curosr,此时可通过rejectedPutBufferHandler指定PutRejectPolicy +- Cursor指针 + 表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过rejectedTakeBufferHandler指定TakeRejectPolicy + +[![img](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142503899-1530677221.png)](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142503899-1530677221.png) + +CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)。 + +由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。 + +[![img](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142450492-1894906450.png)](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142450492-1894906450.png) + +RingBuffer填充时机 + +- 初始化预填充 + RingBuffer初始化时,预先填充满整个RingBuffer。 +- 即时填充 + Take消费时,即时检查剩余可用slot量(tail - cursor),如小于设定阈值,则补全空闲slots。阈值可通过paddingFactor来进行配置,请参考Quick Start中CachedUidGenerator配置。 +- 周期填充 + 通过Schedule线程,定时补全空闲slots。可通过scheduleInterval配置,以应用定时填充功能,并指定Schedule时间间隔。 + +# 美团Leaf + +Leaf是美团基础研发平台推出的一个分布式ID生成服务,名字取自德国哲学家、数学家莱布尼茨的著名的一句话:“There are no two identical leaves in the world”,世间不可能存在两片相同的叶子。 + +Leaf 也提供了两种ID生成的方式,分别是 Leaf-segment 数据库方案和 Leaf-snowflake 方案。 + +## Leaf-segment 数据库方案 + +Leaf-segment 数据库方案,是在上文描述的在使用数据库的方案上,做了如下改变: + +- 原方案每次获取ID都得读写一次数据库,造成数据库压力大。改为利用proxy server批量获取,每次获取一个segment(step决定大小)号段的值。用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力。 +- 各个业务不同的发号需求用 `biz_tag`字段来区分,每个biz-tag的ID获取相互隔离,互不影响。如果以后有性能需求需要对数据库扩容,不需要上述描述的复杂的扩容操作,只需要对biz_tag分库分表就行。 + +数据库表设计如下: + +```sql +CREATE TABLE `leaf_alloc` ( + `biz_tag` varchar(128) NOT NULL DEFAULT '' COMMENT '业务key', + `max_id` bigint(20) NOT NULL DEFAULT '1' COMMENT '当前已经分配了的最大id', + `step` int(11) NOT NULL COMMENT '初始步长,也是动态调整的最小步长', + `description` varchar(256) DEFAULT NULL COMMENT '业务key的描述', + `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`biz_tag`) +) ENGINE=InnoDB; +``` + +原来获取ID每次都需要写数据库,现在只需要把step设置得足够大,比如1000。那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。读写数据库的频率从1减小到了1/step,大致架构如下图所示: + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000142.png) + +同时Leaf-segment 为了解决 TP999(满足千分之九百九十九的网络请求所需要的最低耗时)数据波动大,当号段使用完之后还是会hang在更新数据库的I/O上,TP999 数据会出现偶尔的尖刺的问题,提供了双buffer优化。 + +简单的说就是,Leaf 取号段的时机是在号段消耗完的时候进行的,也就意味着号段临界点的ID下发时间取决于下一次从DB取回号段的时间,并且在这期间进来的请求也会因为DB号段没有取回来,导致线程阻塞。如果请求DB的网络和DB的性能稳定,这种情况对系统的影响是不大的,但是假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢。 + +为了DB取号段的过程能够做到无阻塞,不需要在DB取号段的时候阻塞请求线程,即当号段消费到某个点时就异步的把下一个号段加载到内存中,而不需要等到号段用尽的时候才去更新号段。这样做就可以很大程度上的降低系统的 TP999 指标。详细实现如下图所示: + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000258.png) + +采用双buffer的方式,Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复。 + +- 每个biz-tag都有消费速度监控,通常推荐segment长度设置为服务高峰期发号QPS的600倍(10分钟),这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响。 +- 每次请求来临时都会判断下个号段的状态,从而更新此号段,所以偶尔的网络抖动不会影响下个号段的更新。 + +对于这种方案依然存在一些问题,它仍然依赖 DB的稳定性,需要采用主从备份的方式提高 DB的可用性,还有 Leaf-segment方案生成的ID是趋势递增的,这样ID号是可被计算的,例如订单ID生成场景,通过订单id号相减就能大致计算出公司一天的订单量,这个是不能忍受的。 + +## Leaf-snowflake方案 + +Leaf-snowflake方案完全沿用 snowflake 方案的bit位设计,对于workerID的分配引入了Zookeeper持久顺序节点的特性自动对snowflake节点配置 wokerID。避免了服务规模较大时,动手配置成本太高的问题。 + +Leaf-snowflake是按照下面几个步骤启动的: + +- 启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下检查自己是否已经注册过(是否有该顺序子节点)。 +- 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。 +- 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000333.png) + +为了减少对 Zookeeper的依赖性,会在本机文件系统上缓存一个workerID文件。当ZooKeeper出现问题,恰好机器出现问题需要重启时,能保证服务能够正常启动。 + +上文阐述过在类 snowflake算法上都存在时钟回拨的问题,Leaf-snowflake在解决时钟回拨的问题上是通过校验自身系统时间与 `leaf_forever/${self}`节点记录时间做比较然后启动报警的措施。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000708.png) + +美团官方建议是由于强依赖时钟,对时间的要求比较敏感,在机器工作时NTP同步也会造成秒级别的回退,建议可以直接关闭NTP同步。要么在时钟回拨的时候直接不提供服务直接返回ERROR_CODE,等时钟追上即可。或者做一层重试,然后上报报警系统,更或者是发现有时钟回拨之后自动摘除本身节点并报警。 + +在性能上官方提供的数据目前 Leaf 的性能在4C8G 的机器上QPS能压测到近5w/s,TP999 1ms。 + +# 总结 + +以上基本列出了所有常用的分布式ID生成方式,其实大致分类的话可以分为两类: + +一种是类DB型的,根据设置不同起始值和步长来实现趋势递增,需要考虑服务的容错性和可用性。 + +另一种是类snowflake型,这种就是将64位划分为不同的段,每段代表不同的涵义,基本就是时间戳、机器ID和序列数。这种方案就是需要考虑时钟回拨的问题以及做一些 buffer的缓冲设计提高性能。 + +而且可通过将三者(时间戳,机器ID,序列数)划分不同的位数来改变使用寿命和并发数。 + +例如对于并发数要求不高、期望长期使用的应用,可增加时间戳位数,减少序列数的位数. 例如配置成{"workerBits":23,"timeBits":31,"seqBits":9}时, 可支持28个节点以整体并发量14400 UID/s的速度持续运行68年。 + +对于节点重启频率频繁、期望长期使用的应用, 可增加工作机器位数和时间戳位数, 减少序列数位数. 例如配置成{"workerBits":27,"timeBits":30,"seqBits":6}时, 可支持37个节点以整体并发量2400 UID/s的速度持续运行34年。 + + + +[参考链接](https://www.cnblogs.com/jajian/p/11101213.html) \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" new file mode 100644 index 0000000..2f9cfa0 --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" @@ -0,0 +1,77 @@ +分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务的特性。 + +## CAP理论 + +Consistency(一致性):数据一致更新,所有数据变动都是同步的(强一致性)。 + +Availability(可用性):好的响应性能 + +Partition tolerance(分区容错性) :可靠性 + +定理:任何分布式系统只可同时满足二点,没法三者兼顾。 + +CA系统(放弃P):指将所有数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上,就不会存在网络分区。所以强一致性以及可用性得到满足。 + +CP系统(放弃A):如果要求数据在各个服务器上是强一致的,然而网络分区会导致同步时间无限延长,那么如此一来可用性就得不到保障了。坚持事务ACID(原子性、一致性、隔离性和持久性)的传统数据库以及对结果一致性非常敏感的应用通常会做出这样的选择。 + +AP系统(放弃C):这里所说的放弃一致性,并不是完全放弃数据一致性,而是放弃数据的强一致性,而保留数据的最终一致性。如果即要求系统高可用又要求分区容错,那么就要放弃一致性了。因为一旦发生网络分区,节点之间将无法通信,为了满足高可用,每个节点只能用本地数据提供服务,这样就会导致数据不一致。一些遵守BASE原则数据库,(如:Cassandra、CouchDB等)往往会放宽对一致性的要求(满足最终一致性即可),一次来获取基本的可用性。 + +## BASE理论 + +Basically Available基本可用:指分布式系统在出现不可预知的故障的时候,允许损失部分可用性——但不是系统不可用。 + +响应时间上的损失:假如正常一个在线搜索0.5秒之内返回,但由于故障(机房断电或网络不通),查询结果的响应时间增加到1—2秒。功能上的损失:如果流量激增或者一个请求需要多个服务间配合,而此时有的服务发生了故障,这时需要进行服务降级,进而保护系统稳定性。 + +Soft state软状态:允许系统在不同节点的数据副本之间进行数据同步的过程存在延迟。Eventually consistent最终一致:最终数据是一致的就可以了,而不是时时高一致。 + +BASE思想主要强调基本的可用性,如果你需要High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲。 + +## 实现方案 + +分布式事务的实现主要有以下 5 种方案: + +- XA 方案 +- TCC 方案 +- 可靠消息最终一致性方案 +- 最大努力通知方案 + +## 2PC/XA方案 + +所谓的 XA 方案,即:两阶段提交,有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。 + +这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。 + +一般来说某个系统内部如果出现跨多个库的这么一个操作,是不合规的。如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。 + +## TCC强一致性方案 + +TCC 的全称是:`Try`、`Confirm`、`Cancel`。 + +- **Try 阶段**:这个阶段说的是对各个服务的资源做检测以及对资源进行 **锁定或者预留**。 +- **Confirm 阶段**:这个阶段说的是在各个服务中执行实际的操作。 +- **Cancel 阶段**:如果任何一个服务的业务方法执行出错,那么这里就需要 **进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚) +- + +这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个 **事务回滚实际上是严重依赖于你自己写代码来回滚和补偿** 了,会造成补偿代码巨大,非常之恶心。 + +![img](https://hadyang.com/interview/docs/architecture/distributed/transaction/images/distributed-transaction-TCC.png) + +## 可靠消息最终一致性方案 + +基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。大概的意思就是: + +1. A 系统先发送一个 prepared 消息到 MQ,如果这个 prepared 消息发送失败那么就直接取消操作别执行了; +2. 如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉 MQ 发送确认消息,如果失败就告诉 MQ 回滚消息; +3. 如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务; +4. mq 会自动定时轮询所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。 +5. 这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。 + +这个还是比较合适的,目前国内互联网公司大都是这么玩儿的,要不你举用 RocketMQ 支持的,要不你就自己基于类似 ActiveMQ?RabbitMQ?自己封装一套类似的逻辑出来,总之思路就是这样子的。 + +## 最大努力通知方案 + +这个方案的大致意思就是: + +1. 系统 A 本地事务执行完之后,发送个消息到 MQ; +2. 这里会有个专门消费 MQ 的最大努力通知服务,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口; +3. 要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。 \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" new file mode 100644 index 0000000..bd1f578 --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" @@ -0,0 +1,98 @@ +高并发环境下,例如典型的淘宝双11秒杀,几分钟内上亿的用户涌入淘宝,这个时候如果访问不加拦截,让大量的读写请求涌向数据库,由于磁盘的处理速度与内存显然不在一个量级,服务器马上就要宕机。**从减轻数据库的压力和提高系统响应速度两个角度来考虑,都会在数据库之前加一层缓存**,访问压力越大的,在缓存之前就开始 CDN 拦截图片等访问请求。 + +并且由于最早的单台机器的内存资源以及承载能力有限,如果大量使用本地缓存,也会使相同的数据被不同的节点存储多份,对内存资源造成较大的浪费,因此,才催生出了分布式缓存。 + +![](https://hadyang.com/interview/docs/architecture/distributed/cache/images/36bb3e9d1be0ea97b3e836dc467a9c87.png) + +## 应用场景 + +1. **页面缓存**:用来缓存Web 页面的内容片段,包括HTML、CSS 和图片等; +2. **应用对象缓存**:缓存系统作为ORM 框架的二级缓存对外提供服务,目的是减轻数据库的负载压力,加速应用访问;解决分布式Web部署的 session 同步问题,状态缓存.缓存包括Session 会话状态及应用横向扩展时的状态数据等,这类数据一般是难以恢复的,对可用性要求较高,多应用于高可用集群。 +3. **并行处理**:通常涉及大量中间计算结果需要共享; +4. **云计算领域提供分布式缓存服务** + +## 缓存常见的问题 + +### 缓存穿透 + +缓存穿透是指查询一个**不存在的数据**,由于缓存是不命中时被动写的,如果从DB查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了。 + +1. **缓存空值**,不会查数据库。 +2. 采用**布隆过滤器**,将所有可能存在的数据哈希到一个足够大的`bitmap`中,查询不存在的数据会被这个`bitmap`拦截掉,从而避免了对`DB`的查询压力。 + +布隆过滤器的原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,将元素通过散列函数映射之后会得到k个点,如果这些点有任何一个0,则被检元素一定不在,直接返回;如果都是1,则查询元素很可能存在,就会去查询Redis和数据库。 + +### 缓存雪崩 + +缓存雪崩是指在我们设置缓存时采用了相同的过期时间,**导致缓存在某一时刻同时失效**,请求全部转发到DB,DB瞬时压力过重挂掉。 + +解决方法:在原有的失效时间基础上**增加一个随机值**,使得过期时间分散一些。 + +### 缓存击穿 + +缓存击穿:大量的请求同时查询一个 key 时,此时这个 key 正好失效了,就会导致大量的请求都落到数据库。**缓存击穿是查询缓存中失效的 key,而缓存穿透是查询不存在的 key。** + +解决方法:加分布式锁,第一个请求的线程可以拿到锁,拿到锁的线程查询到了数据之后设置缓存,其他的线程获取锁失败会等待50ms然后重新到缓存取数据,这样便可以避免大量的请求落到数据库。 + +```java +public String get(String key) { + String value = redis.get(key); + if (value == null) { //缓存值过期 + String unique_key = systemId + ":" + key; + //设置30s的超时 + if (redis.set(unique_key, 1, 'NX', 'PX', 30000) == 1) { //设置成功 + value = db.get(key); + redis.set(key, value, expire_secs); + redis.del(unique_key); + } else { //其他线程已经到数据库取值并回写到缓存了,可以重试获取缓存值 + sleep(50); + get(key); //重试 + } + } else { + return value; + } +} +``` + +### 缓存预热 + +缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据! + +解决方案: + +1. 直接写个缓存刷新页面,上线时手工操作一下; +2. 数据量不大,可以在项目启动的时候自动进行加载; +3. 定时刷新缓存; + +### 缓存降级 + +当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。 + +缓存降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 + +在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案: + +1. 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级; +2. 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警; +3. 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级; +4. 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。 + +服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户。 + +### 如何保证缓存与数据库双写时的数据一致性? + +**1、先删除缓存再更新数据库** + +进行更新操作时,先删除缓存,然后更新数据库,后续的请求再次读取时,会从数据库读取后再将新数据更新到缓存。 + +存在的问题:删除缓存数据之后,更新数据库完成之前,这个时间段内如果有新的读请求过来,就会从数据库读取旧数据重新写到缓存中,再次造成不一致,并且后续读的都是旧数据。 + +**2、先更新数据库再删除缓存** + +进行更新操作时,先更新MySQL,成功之后,删除缓存,后续读取请求时再将新数据回写缓存。 + +存在的问题:更新MySQL和删除缓存这段时间内,请求读取的还是缓存的旧数据,不过等数据库更新完成,就会恢复一致,影响相对比较小。 + +**3、异步更新缓存** + +数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由Redis自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。 \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" new file mode 100644 index 0000000..5645b0b --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" @@ -0,0 +1,253 @@ +## 为什么要使用分布式锁 + +在单机环境下,当存在多个线程可以同时改变某个变量(可变共享变量)时,就会出现线程安全问题。这个问题可以通过 JAVA 提供的 volatile、ReentrantLock、synchronized 以及 concurrent 并发包下一些线程安全的类等来避免。 + +而在多机部署环境,需要在多进程下保证线程的安全性,Java提供的这些API仅能保证在单个JVM进程内对多线程访问共享资源的线程安全,已经不满足需求了。这时候就需要使用分布式锁来保证线程安全。通过分布式锁,可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。 + +## 分布式锁应该具备哪些条件 + +在分析分布式锁的三种实现方式之前,先了解一下分布式锁应该具备哪些条件: + +1. 互斥性。在任意时刻,只有一个客户端能持有锁。 +2. 不会死锁。具备锁失效机制,防止死锁。即使有客户端在持有锁的期间崩溃而没有主动解锁,也要保证后续其他客户端能加锁。 +3. 加锁和解锁必须是同一个客户端。客户端a不能将客户端b的锁解开,即不能误解锁。 +4. 高性能、高可用的获取锁与释放锁。 +5. 具备可重入特性。 +6. 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。 + +## 分布式锁的三种实现方式 + +1. 基于数据库实现分布式锁; +2. 基于缓存(Redis等)实现分布式锁; +3. 基于Zookeeper实现分布式锁。 + +### 基于数据库的实现方式 + +**悲观锁** + +创建一张锁表,然后通过操作该表中的数据来实现加锁和解锁。当要锁住某个方法或资源时,就向该表插入一条记录,表中设置方法名为唯一键,这样多个请求同时提交数据库时,只有一个操作可以成功,判定操作成功的线程获得该方法的锁,可以执行方法内容;想要释放锁的时候就删除这条记录,其他线程就可以继续往数据库中插入数据获取锁。 + +**乐观锁** + +每次更新操作,都觉得不会存在并发冲突,只有更新失败后,才重试。 + +扣减余额就可以使用这种方案。 + +具体实现:增加个version字段,每次更新修改,都会自增加一,然后去更新余额时,把查出来的那个版本号,带上条件去更新,如果是上次那个版本号,就更新,如果不是,表示别人并发修改过了,就继续重试。 + +### 基于Redis的实现方式 + +#### 简单实现 + +Redis 2.6.12 之前的版本中采用 setnx + expire 方式实现分布式锁,在 Redis 2.6.12 版本后 setnx 增加了过期时间参数: + +```java +SET lockKey value NX PX expire-time +``` + +所以在Redis 2.6.12 版本后,只需要使用setnx就可以实现分布式锁了。 + +加锁逻辑: + +1. setnx争抢key的锁,如果已有key存在,则不作操作,过段时间继续重试,保证只有一个客户端能持有锁。 +2. value设置为 requestId(可以使用机器ip拼接当前线程名称),表示这把锁是哪个请求加的,在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 +3. 再用expire给锁加一个过期时间,防止异常导致锁没有释放。 + +解锁逻辑: + +首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。使用lua脚本实现原子操作,保证线程安全。 + +下面我们通过Jedis(基于java语言的redis客户端)来演示分布式锁的实现。 + +**Jedis实现分布式锁** + +引入Jedis jar包,在pom.xml文件增加代码: + +```xml + + redis.clients + jedis + 2.9.0 + +``` + +**加锁** + +调用jedis的set()实现加锁,加锁代码如下: + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-08-01 17:13 + */ +public class RedisTest { + + private static final String LOCK_SUCCESS = "OK"; + private static final String SET_IF_NOT_EXIST = "NX"; + private static final String SET_EXPIRE_TIME = "PX"; + + @Autowired + private JedisPool jedisPool; + + public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { + Jedis jedis = jedisPool.getResource(); + String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_EXPIRE_TIME, expireTime); + + if (LOCK_SUCCESS.equals(result)) { + return true; + } + return false; + } +} +``` + +各参数说明: + +- lockKey:使用key来当锁,需要保证key是唯一的。可以使用系统号拼接自定义的key。 +- requestId:表示这把锁是哪个请求加的,可以使用机器ip拼接当前线程名称。在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 +- NX:意思是SET IF NOT EXIST,保证如果已有key存在,则不作操作,过段时间继续重试。NX参数保证只有一个客户端能持有锁。 +- PX:给key加一个过期的设置,具体时间由expireTime决定。 +- expireTime:设置key的过期时间,防止异常导致锁没有释放。 + +**解锁** + +首先需要获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。这里使用lua脚本实现原子操作,保证线程安全。 + +使用eval命令执行Lua脚本的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。lua脚本如下: + +``` +//KEYS[1]是lockKey,ARGV[1]是requestId +String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; +Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); +``` + +Jedis的eval()方法源码如下: + +```java +public Object eval(String script, List keys, List args) { + return this.eval(script, keys.size(), getParams(keys, args)); +} +``` + +lua脚本的意思是:调用get获取锁(KEYS[1])对应的value值,检查是否与requestId(ARGV[1])相等,如果相等则调用del删除锁。否则返回0。 + +完整的解锁代码如下: + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-08-01 17:13 + */ +public class RedisTest { + private static final Long RELEASE_SUCCESS = 1L; + + @Autowired + private JedisPool jedisPool; + + public boolean releaseDistributedLock(String lockKey, String requestId) { + Jedis jedis = jedisPool.getResource(); + ////KEYS[1]是lockKey,ARGV[1]是requestId + String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; + Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); + + if (RELEASE_SUCCESS.equals(result)) { + return true; + } + return false; + } +} +``` + +#### RedLock + +前面的方案是基于**Redis单机版**的分布式锁讨论,还不是很完美。因为Redis一般都是集群部署的。 + +如果线程一在`Redis`的`master`节点上拿到了锁,但是加锁的`key`还没同步到`slave`节点。恰好这时,`master`节点发生故障,一个`slave`节点就会升级为`master`节点。线程二就可以顺理成章获取同个`key`的锁啦,但线程一也已经拿到锁了,锁的安全性就没了。 + +为了解决这个问题,Redis作者antirez提出一种高级的分布式锁算法:**Redlock**。它的核心思想是这样的: + +部署多个Redis master,以保证它们不会同时宕掉。并且这些master节点是完全相互独立的,相互之间不存在数据同步。同时,需要确保在这多个master实例上,是与在Redis单实例,使用相同方法来获取和释放锁。 + +我们假设当前有5个Redis master节点,在5台服务器上面运行这些Redis实例。 + +RedLock的实现步骤: + +1. 获取当前时间,以毫秒为单位。 +2. 按顺序向5个master节点请求加锁。客户端设置网络连接和响应超时时间,并且超时时间要小于锁的失效时间。(假设锁自动失效时间为10秒,则超时时间一般在5-50毫秒之间,我们就假设超时时间是50ms吧)。如果超时,跳过该master节点,尽快去尝试下一个master节点。 +3. 客户端使用当前时间减去开始获取锁时间(即步骤1记录的时间),得到获取锁使用的时间。当且仅当超过一半(N/2+1,这里是5/2+1=3个节点)的Redis master节点都获得锁,并且使用的时间小于锁失效时间时,锁才算获取成功。(如上图,10s> 30ms+40ms+50ms+4m0s+50ms) +4. 如果取到了锁,key的真正有效时间就变啦,需要减去获取锁所使用的时间。 +5. 如果获取锁失败(没有在至少N/2+1个master实例取到锁,有或者获取锁时间已经超过了有效时间),客户端要在所有的master节点上解锁(即便有些master节点根本就没有加锁成功,也需要解锁,以防止有些漏网之鱼)。 + +简化下步骤就是: + +- 按顺序向5个master节点请求加锁 +- 根据设置的超时时间来判断,是不是要跳过该master节点。 +- 如果大于等于3个节点加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功啦。 +- 如果获取锁失败,解锁! + +### 基于ZooKeeper的实现方式 + +ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下: + +(1)创建一个目录mylock; +(2)线程A想获取锁就在mylock目录下创建临时顺序节点; +(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁; +(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点; +(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。 + +这里推荐一个Apache的开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。 + +优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。 + +缺点:因为需要频繁的创建和删除节点,性能上不如Redis方式。 + +## 三种实现方式对比 + +**数据库分布式锁实现** + +优点: + +- 简单,使用方便,不需要引入`Redis、zookeeper`等中间件。 + +缺点: + +- 不适合高并发的场景 +- db操作性能较差; + +**Redis分布式锁实现** + +优点: + +- 性能好,适合高并发场景 +- 较轻量级 +- 有较好的框架支持,如Redisson + +缺点: + +- 过期时间不好控制 +- 需要考虑锁被别的线程误删场景 + +**Zookeeper分布式锁实现** + +缺点: + +- 性能不如redis实现的分布式锁 +- 比较重的分布式锁。 + +优点: + +- 有较好的性能和可靠性 +- 有封装较好的框架,如Curator + +**对比汇总** + +- 从性能角度(从高到低)Redis > Zookeeper >= 数据库; +- 从理解的难易程度角度(从低到高)数据库 > Redis > Zookeeper; +- 从实现的复杂性角度(从低到高)Zookeeper > Redis > 数据库; +- 从可靠性角度(从高到低)Zookeeper > Redis > 数据库。 + +## 参考链接 + +https://mp.weixin.qq.com/s/xQknd6xsVDPBr4TbETTk2A \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" new file mode 100644 index 0000000..99ffb31 --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" @@ -0,0 +1,194 @@ +## 简介 + +微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务和服务之间采用轻量级的通信机制进行协作。每个服务可以被独立的部署到生产环境。 + +[从单体应用到微服务](https://www.zhihu.com/question/65502802/answer/802678798) + +单体系统的缺点: + +1. 修改一个小功能,就需要将整个系统重新部署上线,影响其他功能的运行; +2. 功能模块互相依赖,强耦合,扩展困难。如果出现性能瓶颈,需要对整体应用进行升级,虽然影响性能的可能只是其中一个小模块; + +单体系统的优点: + +1. 容易部署,程序单一,不存在分布式集群的复杂部署环境; +2. 容易测试,没有复杂的服务调用关系。 + +微服务的**优点**: + +1. 不同的服务可以使用不同的技术; +2. 隔离性。一个服务不可用不会导致其他服务不可用; +3. 可扩展性。某个服务出现性能瓶颈,只需对此服务进行升级即可; +4. 简化部署。服务的部署是独立的,哪个服务出现问题,只需对此服务进行修改重新部署; + +微服务的**缺点**: + +1. 网络调用频繁。性能相对函数调用较差。 +2. 运维成本增加。系统由多个独立运行的微服务构成,需要设计一个良好的监控系统对各个微服务的运行状态进行监控。 + + + +## 分布式和微服务的区别 + +从概念理解,分布式服务架构强调的是服务化以及服务的**分散化**,微服务则更强调服务的**专业化和精细分工**; + +从实践的角度来看,**微服务架构通常是分布式服务架构**,反之则未必成立。 + +一句话概括:分布式:分散部署;微服务:分散能力。 + + + +## 服务划分 + +横向拆分:按照不同的业务域进行拆分,例如订单、营销、风控、积分资源等。形成独立的业务领域微服务集群。 + +纵向拆分:把一个业务功能里的不同模块或者组件进行拆分。例如把公共组件拆分成独立的原子服务,下沉到底层,形成相对独立的原子服务层。这样一纵一横,就可以实现业务的服务化拆分。 + +要做好微服务的分层:梳理和抽取核心应用、公共应用,作为独立的服务下沉到核心和公共能力层,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求 + +总之,微服务的设计一定要 **渐进式** 的,总的原则是 **服务内部高内聚,服务之间低耦合。** + + ## 微服务设计原则 +**单一职责原则** + +意思是每个微服务只需要实现自己的业务逻辑就可以了,比如订单管理模块,它只需要处理订单的业务逻辑就可以了,其它的不必考虑。 + +**服务自治原则** + +意思是每个微服务从开发、测试、运维等都是独立的,包括存储的数据库也都是独立的,自己就有一套完整的流程,我们完全可以把它当成一个项目来对待。不必依赖于其它模块。 + +**轻量级通信原则** + +首先是通信的语言非常的轻量,第二,该通信方式需要是跨语言、跨平台的,之所以要跨平台、跨语言就是为了让每个微服务都有足够的独立性,可以不受技术的钳制。 + +**接口明确原则** + +由于微服务之间可能存在着调用关系,为了尽量避免以后由于某个微服务的接口变化而导致其它微服务都做调整,在设计之初就要考虑到所有情况,让接口尽量做的更通用,更灵活,从而尽量避免其它模块也做调整。 + + + +## 微服务之间是如何通讯的? + +**1、RPC** + +优点:简单,常见。因为没有中间件代理,系统更简单 + +缺点: + +1. 只支持请求/响应的模式,不支持别的,比如通知、发布/订阅 +2. 降低了可用性,因为客户端和服务端在请求过程中必须都是可用的 + +**2、消息队列** + +除了标准的基于RPC通信的微服务架构,还有基于消息队列通信的微服务架构,这种架构下的微服务采用发送消息(Publish Message)与监听消息(Subscribe Message)的方式来实现彼此之间的交互。 + +网易的蜂巢平台就采用了基于消息队列的微服务架构设计思路,如下图所示,微服务之间通过RabbitMQ传递消息,实现通信。 + +与上面几种微服务架构相比,基于消息队列的微服务架构并不多,案例也相对较少,更多地体现为一种与业务相关的设计经验,各家有各家的实现方式,缺乏公认的设计思路与参考架构,也没有形成一个知名的开源平台。因此,如果需要实施这种微服务架构,则基本上需要项目组自己从零开始去设计实现一个微服务架构基础平台,其代价是成本高、风险大。 + +**优点**: + +- 把客户端和服务端解耦,更松耦合提高可用性,因为消息中间件缓存了消息,直到消费者可以消费 +- 支持很多通信机制比如通知、发布/订阅等 + +**缺点**: + +- 缺乏公认的设计思路与参考架构,也没有形成一个知名的开源平台 +- 成本高、风险大 + +## 熔断器 + +雪崩效应:假如存在这样的调用链路,a服务->b服务->c服务,当c服务挂了的时候,b服务调用c服务会等待超时,a服务调用b服务也会等待超时,调用方长时间等不到相应而占用线程,如果有大量的请求过来,就会造成线程池打满,导致整个链路的服务奔溃。 + +为了解决分布式系统的雪崩效应,分布式系统引进了**熔断器机制** 。 + +当一个服务的处理用户请求的失败次数在一定时间内小于设定的阀值时,熔断器出于关闭状态,服务正常。 + +当服务处理用户请求失败次数在一定时间内大于设定的阀值时,说明服务出现故障,打开熔断器,这时所有的请求会快速返回失败的错误信息,不执行业务逻辑,从而防止故障的蔓延。 + +当处于打开状态的熔断器时,一段时间后出于半打开状态,并执行一定数量的请求,剩余的请求会执行快速失败,若执行请求失败了,则继续打开熔断器,若成功了,则将熔断器关闭。 + +## 服务网关 + +### 何为网关? + +通俗一点的讲:网关就是要去别的网络的时候,把报文首先发送到的那台设备。稍微专业一点的术语,网关就是当前主机的默认路由。 + +网关一般就是一台路由器,有点像“一个小区中的一个邮局”,小区里面的住户互相是知道怎么走,但是要向外地投递东西就不知道了,怎么办?把地址写好送到本小区的邮局就好了。 + +那么,怎么区分是“本小区”和“外地小区”的呢?根据IP地址 + 掩码。如果是在一个范围内的,就是本小区(局域网内部),如果掩不住的,就是外地的。 + +例如,你的机器的IP地址是:192.168.0.2/24,网关是192.168.0.1 + +如果机器访问的IP地址范围是:192.168.0.1~192.168.0.254的,说明是一个小区的邻居,你的机器就直接发送了(和网关没任何关系)。如果你访问的IP地址不是这个范围的,则就投递到192.168.0.1上,让这台设备来转发。 + +参考:https://www.zhihu.com/question/362842680/answer/951412213 + +### 何为API网关 + +假设你正在开发一个电商网站,那么这里会涉及到很多后端的微服务,比如会员、商品、推荐服务等等。 + +那么这里就会遇到一个问题,APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话,可以给每个业务都分配一个独立的域名(`https://service.api.company.com`),但这种方式会有几个问题: + +- 每个业务都会需要鉴权、限流、权限校验等逻辑,如果每个业务都各自为战,自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。 +- 如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝、亚马逊打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微服务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名 +- 每上线一个新的服务,都需要运维参与,申请域名、配置Nginx等,当上线、下线服务器时,同样也需要运维参与,另外采用域名这种方式,对于环境的隔离也不太友好,调用者需要自己根据域名自己进行判断。 +- 另外还有一个问题,后端每个微服务可能采用了不同的协议,比如HTTP、AMQP、自定义TCP协议等,但是你不可能要求客户端去适配这么多种协议,这是一项非常有挑战的工作,项目会变的非常复杂且很难维护。 + +更好的方式是采用API网关(也叫做服务网关),实现一个API网关**接管所有的入口流量**,类似Nginx的作用,将所有用户的请求转发给后端的服务器,但网关做的不仅仅只是简单的转发,也会针对流量做一些扩展,比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等,这样将通用的逻辑抽出来,由网关统一去做,业务方也能够更专注于业务逻辑,提升迭代的效率。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508185101.jpg) + +通过引入API网关,客户端只需要与API网关交互,而不用与各个业务方的接口分别通讯,但多引入一个组件就多引入了一个潜在的故障点,因此要实现一个高性能、稳定的网关,也会涉及到很多点。 + +网关层通常以集群的形式存在。并在服务网关层前通常会加上Nginx 用来负载均衡。 + +**服务网关基本功能**: + +![服务网关](https://raw.githubusercontent.com/Tyson0314/img/master/20220508120340.png) + +- 智能路由:接收**外部**一切请求,并转发到后端的对外服务。注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。 +- 权限校验:网关可以做一些用户身份认证,权限认证,防止非法请求操作API 接口,对内部服务起到保护作用 +- API监控:监控经过网关的请求,以及网关本身的一些性能指标(gc等) +- 限流:与监控配合,进行限流操作 +- API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志 + +当然,网关实现这些功能,需要做高可用,否则网关很可能成为架构的瓶颈,最常用的网关组件Zuul、Nginx + +## 服务配置统一管理 + +在微服务架构中,需要有统一管理配置文件的组件,例如:SpringCloud Config组件、阿里的Diamond、百度的Disconf、携程的Apollo等 + +## 服务链路追踪 + +在微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与、参与顺序,是每个请求链路清晰可见,便于问题快速定位。 + +常用链路追踪组件有Google的Dapper、Twitter 的Zipkin,以及阿里Eagleeye。 + + + +## 微服务框架 + +市面常用微服务框架有:Spring Cloud 、Dubbo 、kubernetes + +- 从功能模块上考虑,Dubbo缺少很多功能模块,例如网关、链路追踪等 +- 从学习成本上考虑,Dubbo 版本趋于稳定,稳定完善、可以即学即用,难度简单,Spring cloud 基于Spring Boot,需要先掌握Spring Boot ,例外Spring cloud 大多为英文文档,要求学习者有一定的英文阅读能力 +- 从开发风格考虑,Dubbo倾向于xml的配置方式,Spring cloud 基于Spring Boot ,采用基于注解和JavaBean配置方式的敏捷开发 +- 从开发速度上考虑,Spring cloud 具有更高的开发和部署速度 +- 从通信方式上考虑,Spring cloud 基于HTTP Restful 风格,服务于服务之间完全无关、无耦合。Dubbo 基于远程调用,对接口、平台和语言有强依赖性,如果需要实现跨平台,需要有额外的中间件。 + +所以Dubbo专注于服务治理;Spring Cloud关注于微服务架构生态。 + +## 其他 + +### Spring Cloud基础知识 + +[Spring Cloud基础知识](../框架/SpringCloud微服务实战.md) + +### 什么是Service Mesh? + +Service Mesh 是微服务时代的 TCP/IP 协议。 + +参考:https://zhuanlan.zhihu.com/p/61901608 + + diff --git "a/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" "b/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" new file mode 100644 index 0000000..4f38569 --- /dev/null +++ "b/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" @@ -0,0 +1,119 @@ +## RPC简介 + +RPC,英文全名remote procedure call,即远程过程调用。就是说一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。 + +可以这么说,RPC就是要像调用本地的函数一样去调远程函数。 + +RPC是一个完整的远程调用方案,它通常包括通信协议和序列化协议。 + +其中,通信协议包含**http协议**(如gRPC使用http2)、**自定义报文的tcp协议**(如dubbo)。序列化协议包含**基于文本编码**的xml、json,**基于二进制编码**的protobuf、hessian等。 + +> protobuf 即 Protocol Buffers,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。protobuf 性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式。protobuf 是以二进制方式存储,占用空间小,但也带来了可读性差的缺点(二进制协议,因为不可读而难以调试,不好定位问题)。 +> +> Protobuf序列化协议相比JSON有什么优点? +> +> 1:序列化后体积相比Json和XML很小,适合网络传输 +> +> 2:支持跨平台多语言 +> +> 3:序列化反序列化速度很快,快于Json的处理速速 + +**一个完整的RPC过程,都可以用下面这张图来描述**: + +> stub说的都是“一小块代码”,通常是有个caller要调用callee的时候,中间需要一些特殊处理的逻辑,就会用这种“小块代码”去做。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508160414.png) + +1. 服务消费端(client)以本地调用的方式调用远程服务; +2. 客户端 Stub(client stub) 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(序列化):`RpcRequest`; +3. 客户端 Stub(client stub) 找到远程服务的地址,并将消息发送到服务提供端; +4. 服务端 Stub(桩)收到消息将消息反序列化为Java对象: `RpcRequest`; +5. 服务端 Stub(桩)根据`RpcRequest`中的类、方法、方法参数等信息调用本地的方法; +6. 服务端 Stub(桩)得到方法执行结果并将组装成能够进行网络传输的消息体:`RpcResponse`(序列化)发送至消费方; +7. 客户端 Stub(client stub)接收到消息并将消息反序列化为Java对象:`RpcResponse` ,这样也就得到了最终结果。 + +## RPC 解决了什么问题? + +让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。 + +## 常见的 RPC 框架有哪些? + +- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件。 +- **gRPC** :基于HTTP2。gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。 +- **Hessian:** Hessian是一个轻量级的remoting on http工具,使用简单的方法提供了RMI的功能。 采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。 +- **Thrift:** Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。 + +## 有了HTTP ,为啥还要用RPC进行服务调用? + +首先,RPC是一个完整的远程调用方案,它通常包括通信协议和序列化协议。而HTTP只是一个通信协议,不是一个完整的远程调用方案。这两者不是对等的概念,用来比较不太合适。 + +RPC框架可以使用 **HTTP协议**作为传输协议或者直接使用**自定义的TCP协议**作为传输协议,使用不同的协议一般也是为了适应不同的场景。 + +HTTP+Restful,其优势很大。它**可读性好**,且**应用广、跨语言的支持**。 + +但是使用该方案也有其缺点,这是与其优点相对应的: + +- 首先是**有用信息占比少**,毕竟HTTP工作在第七层,包含了大量的HTTP头等信息。 +- 其次是**效率低**,还是因为第七层的缘故,必须按照HTTP协议进行层层封装。 + +而使用**自定义tcp协议**的话,可以极大地精简了传输内容,这也是为什么有些后端服务之间会采用自定义tcp协议的rpc来进行通信的原因。 + +## 各种序列化技术 + +### XML + +XML序列化的好处在于可读性好,方便阅读和调试。但是序列化以后的字节码文件比较大,而且效率不高,适用于对性能要求不高,而且QPS较低的企业级内部系统之间的数据交换场景。同时XML又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。比如我们熟知的WebService,就是采用XML格式对数据进行序列化的。XML序列化/反序列化的实现方式有很多,熟知的方式有XStream和Java自带的XML序列化和反序列化两种。 + +### JSON + +JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于XML来说,JSON的字节流更小,而且可读性也非常好。现在JSON数据格式在企业运用是最普遍的。 + +JSON序列化常用的开源工具有很多: + +1. Jackson(https://github.com/FasterXML/jackson ) +2. 阿里开源的FastJson(https://github.com/alibaba/fastjon) +3. 谷歌的GSON(https://github.com/google/gson) + +这几种json的序列化工具中,jackson与fastjson要比GSON的性能好,但是jackson、GSON的稳定性腰比Fastjson好。而fastjson的优势在于提供的api非常容易使用。 + +### Hession + +Hessian是一个支持跨语言传输的二进制序列化协议,相对于Java默认的序列化机制来说,Hession具有更好的性能和易读性,而且支持多种不同的语言。 + +实际上Dubbo采用的就是Hessian序列化来实现,只不过Dubbo对Hessian进行了重构,性能更高。 + +### Avro + +Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据。动态语言友好,Avro提供的机制是动态语言可以方便的处理Avro数据。 + +### Kryo + +Kryo是一种非常成熟的序列化实现,已经在Hive、Storm中使用的比较广泛,不过它不能夸语言。目前Dubbo已经在2.6版本支持kyro的序列化机制。它的性能要由于之前的hessian2。 + +### Protobuf + +Protobuf是Google的一种数据交换格式,它独立于语言、独立于平台。Google提供了多种语言来实现,比如Java、C、Go、Python,每一种实现都包含了相应语言的编译器和库文件,Protobuf是一个纯粹的表示层协议,可以和各种传输层协议一起使用。 + +Protobuf使用比较广泛,主要是空间开销小和性能比较好,非常适合用于公司内部对性能要求高的RPC调用。另外由于解析性能比较高,序列化以后数据量相对较少,所以也可以应用在对象的持久化场景中。 + +但是要使用Protobuf会相对来说麻烦些,因为他有自己的语法,有自己的编译器,如果需要用到的话必须要去投入成本在这个技术的学习中。 + +Protobuf有个缺点就是要传输每一个类的结构都要生成对应的proto文件,如果某个类发生修改,还得重新生成该类对应的proto文件。 + +## 序列化技术的选型 + +### 技术层面 + +1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输性能。 +2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间。 +3. 序列化协议是否支持夸平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信需求,那么这个是必须要考虑的。 +4. 可扩展性、兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,这就要求我们来采用序列化协议具有良好的可扩展性、兼容性,比如现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务。 +5. 技术的流行程度,越流行的技术意味着使用的公司越多,那么很多坑都已经淌过并且得到了解决,技术解决方案也相对成熟。 +6. 学习难度和易用性。 + +### 选型建议 + +1. 对性能要求不高的场景,可以采用基于XML的SOAP协议 +2. 性能和间接性有比较高要求的场景,那么Hessian、Protobuf、Thrift、Avro都可以。 +3. 基于前后端分离,或者独立的对外API服务,选用JSON是比较好的,对于调试、可读性都很不错。 +4. Avro设计理念偏于动态类型语言,那么这类的场景使用Avro是可以的。 \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" index b569ffc..111ea22 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" @@ -457,7 +457,7 @@ WHERE Soundex(cust_contact) = Soundex('Y Lie'); ### 日期处理函数 -![在这里插入图片描述](https://img-blog.csdnimg.cn/20200504231137490.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==,size_16,color_FFFFFF,t_70) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235607.png) 查找2005年9月的所有订单: ```mysql @@ -476,7 +476,7 @@ WHERE Year(order_date) = 2005 AND Month(order_date) = 9; ### 数值处理函数 -![在这里插入图片描述](https://img-blog.csdnimg.cn/20200504234157154.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==,size_16,color_FFFFFF,t_70) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233617.png) ## 汇总数据 @@ -511,7 +511,7 @@ SELECT * FROM orders GROUP BY cust_id; ``` -![](../img/mysql/orderby.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233523.png) 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。 @@ -630,7 +630,7 @@ SELECT * FROM role NATURAL JOIN user_role; 返回结果: -![image-20200608232951873](..\img\image-20200608232951873.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235619.png) ### 内连接 @@ -642,7 +642,7 @@ SELECT * FROM role INNNER JOIN user_role 返回结果: -![image-20200608232749393](..\img\image-20200608232749393.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235640.png) join…using(column)按指定的属性做等值连接。 join…on tableA.column1 = tableB.column2 指定条件。 @@ -653,7 +653,7 @@ SELECT * FROM role INNER JOIN user_role ON role.role_id = user_role.role_id 返回结果: -![image-20200608233400458](..\img\image-20200608233400458.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235654.png) ### 外连接 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 8ec0b08..d829b99 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -132,6 +132,77 @@ set session transaction isolation level read uncommitted; [互联网项目中mysql应该选什么事务隔离级别](https://zhuanlan.zhihu.com/p/59061106) +## 编码和字符集的关系 + +我们平时可以在编辑器上输入各种中文英文字母,但这些都是给人读的,不是给计算机读的,其实计算机真正保存和传输数据都是以**二进制**0101的格式进行的。 + +那么就需要有一个规则,把中文和英文字母转化为二进制。其中d对应十六进制下的64,它可以转换为01二进制的格式。于是字母和数字就这样一一对应起来了,这就是**ASCII编码**格式。 + +它用**一个字节**,也就是`8位`来标识字符,基础符号有128个,扩展符号也是128个。也就只能表示下**英文字母和数字**。 + +这明显不够用。于是,为了标识**中文**,出现了**GB2312**的编码格式。为了标识**希腊语**,出现了**greek**编码格式,为了标识**俄语**,整了**cp866**编码格式。 + +为了统一它们,于是出现了**Unicode编码格式**,它用了2~4个字节来表示字符,这样理论上所有符号都能被收录进去,并且它还完全兼容ASCII的编码,也就是说,同样是字母d,在ASCII用64表示,在Unicode里还是用64来表示。 + +但**不同的地方是ASCII编码用1个字节来表示,而Unicode用则两个字节来表示。** + +同样都是字母d,unicode比ascii多使用了一个字节,如下: + +```mysql +D ASCII: 01100100 +D Unicode: 00000000 01100100 +``` + +可以看到,上面的unicode编码,前面的都是0,其实用不上,但还占了个字节,有点浪费。如果我们能做到该隐藏时隐藏,这样就能省下不少空间,按这个思路,就是就有了**UTF-8编码**。 + +总结一下,按照一定规则把符号和二进制码对应起来,这就是**编码**。而把n多这种已经编码的字符聚在一起,就是我们常说的**字符集**。 + +比如utf-8字符集就是所有utf-8编码格式的字符的合集。 + +想看下mysql支持哪些字符集。可以执行 `show charset;` + +## utf8和utf8mb4的区别 + +上面提到utf-8是在unicode的基础上做的优化,既然unicode有办法表示所有字符,那utf-8也一样可以表示所有字符,为了避免混淆,我在后面叫它**大utf8**。 + +mysql支持的字符集中有utf8和utf8mb4。 + +先说**utf8mb4**编码,mb4就是**most bytes 4**的意思,从上图最右边的`Maxlen`可以看到,它最大支持用**4个字节**来表示字符,它几乎可以用来表示目前已知的所有的字符。 + +再说mysql字符集里的**utf8**,它是数据库的**默认字符集**。但注意,**此utf8非彼utf8**,我们叫它**小utf8**字符集。为什么这么说,因为从Maxlen可以看出,它最多支持用3个字节去表示字符,按utf8mb4的命名方式,准确点应该叫它**utf8mb3**。 + +utf8 就像是阉割版的utf8mb4,只支持部分字符。比如`emoji`表情,它就不支持。 + +而mysql支持的字符集里,第三列,**collation**,它是指**字符集的比较规则**。 + +比如,**"debug"和"Debug"**是同一个单词,但它们大小写不同,该不该判为同一个单词呢。 + +这时候就需要用到collation了。 + +通过`SHOW COLLATION WHERE Charset = 'utf8mb4';`可以查看到`utf8mb4`下支持什么比较规则。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220527084528.png) + +如果`collation = utf8mb4_general_ci`,是指使用utf8mb4字符集的前提下,**挨个字符进行比较**(`general`),并且不区分大小写(`_ci,case insensitice`)。 + +这种情况下,**"debug"和"Debug"是同一个单词**。 + +如果改成`collation=utf8mb4_bin`,就是指**挨个比较二进制位大小**。 + +于是**"debug"和"Debug"就不是同一个单词。** + +如果改成`collation=utf8mb4_bin`,就是指**挨个比较二进制位大小**。 + +于是**"debug"和"Debug"就不是同一个单词。** + +**那utf8mb4对比utf8有什么劣势吗?** + +我们知道数据库表里,字段类型如果是`char(2)`的话,里面的`2`是指**字符个数**,也就是说**不管这张表用的是什么编码的字符集**,都能放上2个字符。 + +而char又是**固定长度**,为了能放下2个utf8mb4的字符,char会默认保留`2*4(maxlen=4)= 8`个字节的空间。 + +如果是utf8mb3,则会默认保留 `2 * 3 (maxlen=3) = 6`个字节的空间。也就是说,在这种情况下,**utf8mb4会比utf8mb3多使用一些空间。** + ## 索引 ### 什么是索引? @@ -510,16 +581,6 @@ select * from table where id<6 for update;--排他锁 2. 根据主键进行查询,查询条件为`like`或者不等于,主键字段产生**表锁**。 3. 根据非索引字段进行查询,会产生**表锁**。 -## 大表怎么优化? - -某个表有近千万数据,查询比较慢,如何优化? - -当MySQL单表记录数过大时,数据库的性能会明显下降,一些常见的优化措施如下: - -* 限定数据的范围。比如:用户在查询历史信息的时候,可以控制在一个月的时间范围内; -* 读写分离: 经典的数据库拆分方案,主库负责写,从库负责读; -* 通过分库分表的方式进行优化,主要有垂直拆分和水平拆分。 - ## bin log/redo log/undo log MySQL日志主要包括查询日志、慢查询日志、事务日志、错误日志、二进制日志等。其中比较重要的是 `bin log`(二进制日志)和 `redo log`(重做日志)和 `undo log`(回滚日志)。 @@ -762,7 +823,7 @@ int(10)中的10表示的是显示数据的长度,而char(10)表示的是存储 数据库中的并发控制是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观锁和悲观锁是并发控制主要采用的技术手段。 -* 悲观锁:假定会发生并发冲突,在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制。 +* 悲观锁:假定会发生并发冲突,会对操作的数据进行加锁,直到提交事务,才会释放锁,其他事务才能进行修改。实现方式:使用数据库中的锁机制。 * 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否数据是否被修改过。给表增加`version`字段,在修改提交之前检查`version`与原来取到的`version`值是否相等,若相等,表示数据没有被修改,可以更新,否则,数据为脏数据,不能更新。实现方式:乐观锁一般使用版本号机制或`CAS`算法实现。 ## 用过processlist吗? @@ -804,11 +865,11 @@ server层有很多模块,其中需要关注的是**执行器**是用于跟存 以主键索引的limit执行过程为例: -执行`select * from page order by id limit 0, 10;`,select后面带的是**星号**,也就是要求获得行数据的**所有字段信息。** +执行`select * from xxx order by id limit 0, 10;`,select后面带的是**星号**,也就是要求获得行数据的**所有字段信息。** server层会调用innodb的接口,在innodb里的主键索引中获取到第0到10条**完整行数据**,依次返回给server层,并放到server层的结果集中,返回给客户端。 -把offset搞大点,比如执行的是:`select * from page order by id limit 500000, 10;` +把offset搞大点,比如执行的是:`select * from xxx order by id limit 500000, 10;` server层会调用innodb的接口,由于这次的offset=500000,会在innodb里的主键索引中获取到第0到(500000 + 10)条**完整行数据**,**返回给server层之后根据offset的值挨个抛弃,最后只留下最后面的size条**,也就是10条数据,放到server层的结果集中,返回给客户端。 @@ -818,7 +879,7 @@ server层会调用innodb的接口,由于这次的offset=500000,会在innodb ## 深分页怎么优化? -还是以上面的SQL为空:`select * from page order by id limit 500000, 10;` +还是以上面的SQL为空:`select * from xxx order by id limit 500000, 10;` **方法一**: @@ -826,18 +887,18 @@ server层会调用innodb的接口,由于这次的offset=500000,会在innodb 因为前面的offset条数据最后都是不要的,没有必要拷贝完整字段,所以可以将sql语句修改成: -```mysql -select * from page where id >=(select id from page order by id limit 500000, 1) order by id limit 10; +``` +select * from xxx where id >=(select id from xxx order by id limit 500000, 1) order by id limit 10; ``` -先执行子查询 `select id from page order by id limit 500000, 1`, 这个操作,其实也是将在innodb中的主键索引中获取到`500000+1`条数据,然后server层会抛弃前500000条,只保留最后一条数据的id。 +先执行子查询 `select id from xxx by id limit 500000, 1`, 这个操作,其实也是将在innodb中的主键索引中获取到`500000+1`条数据,然后server层会抛弃前500000条,只保留最后一条数据的id。 但不同的地方在于,在返回server层的过程中,只会拷贝数据行内的id这一列,而不会拷贝数据行的所有列,当数据量较大时,这部分的耗时还是比较明显的。 在拿到了上面的id之后,假设这个id正好等于500000,那sql就变成了 -```mysql -select * from page where id >=500000 order by id limit 10; +``` +select * from xxx where id >=500000 order by id limit 10; ``` 这样innodb再走一次**主键索引**,通过B+树快速定位到id=500000的行数据,时间复杂度是lg(n),然后向后取10条数据。 @@ -846,9 +907,11 @@ select * from page where id >=500000 order by id limit 10; 将所有的数据**根据id主键进行排序**,然后分批次取,将当前批次的最大id作为下次筛选的条件进行查询。 -```mysql -select * from page where id > start_id order by id limit 10; ``` +select * from xxx where id > start_id order by id limit 10; +``` + +mysql 通过主键索引,每次定位到start_id的位置,然后往后遍历10个数据,这样不管数据多大,查询性能都较为稳定。 @@ -890,8 +953,21 @@ B+树中**非叶子节点存的是key + 指针**;**叶子节点存的是数据 1. MySQL 单表数据量大于 2000 万行,性能会明显下降,考虑进行分库分表。 2. 阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 -事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为,MySQL 为了提高性能,会将表的索引装载到内存中。InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。 +事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为MySQL为了提高性能,会将表的索引装载到内存中。在InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。 因此,对于分库分表,需要结合实际需求,不宜过度设计,在项目一开始不采用分库与分表设计,而是随着业务的增长,在无法继续优化的情况下,再考虑分库与分表提高系统的性能。对此,阿里巴巴《Java 开发手册》补充到:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 至于MySQL单表多大进行分库分表,应当根据机器资源进行评估。 + +## 大表查询慢怎么优化? + +某个表有近千万数据,查询比较慢,如何优化? + +当MySQL单表记录数过大时,数据库的性能会明显下降,一些常见的优化措施如下: + +* 合理建立索引。在合适的字段上建立索引,例如在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描 +* 建立分区。对关键字段建立水平分区,比如时间字段,若查询条件往往通过时间范围来进行查询,能提升不少性能 +* 利用缓存。利用Redis等缓存热点数据,提高查询效率 +* 限定数据的范围。比如:用户在查询历史信息的时候,可以控制在一个月的时间范围内 +* 读写分离。经典的数据库拆分方案,主库负责写,从库负责读 +* 通过分库分表的方式进行优化,主要有垂直拆分和水平拆分 diff --git "a/\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" "b/\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" new file mode 100644 index 0000000..bd248f4 --- /dev/null +++ "b/\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" @@ -0,0 +1,44 @@ +Apollo从设计之初就立志于成为一个有治理能力的配置发布平台,目前提供了以下的特性 + +- **统一管理不同环境、不同集群的配置** + +- - Apollo提供了一个统一界面集中式管理不同环境(Environment)、不同集群(Cluster)、不同命名空间(Namespace)的配置 + - 同一份代码部署在不同的集群,可以有不同的配置 + - 通过命名空间可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖 + +- **热发布--配置修改实时生效** 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序 + +- **版本发布管理** 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚 + +- **灰度发布** 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例 + +- **权限管理、发布审核、操作审计** + +- - 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误 + - 所有的操作都有审计日志,可以方便地追踪问题 + +- **客户端配置信息监控** 可以在界面上方便地看到配置在被哪些实例使用 + +- **提供Java和.Net原生客户端** + +- - 提供了Java和.Net的原生客户端,方便应用集成 + - 支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties,方便应用使用(需要Spring 3.1.1+) + - 同时提供了Http接口,非Java和.Net应用也可以方便地使用 + +- 提供开放平台API + +- 部署简单 + + + +**基础模型** + +- 用户在配置中心对配置进行修改并发布 +- 配置中心通知Apollo客户端有配置更新 +- Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用 + + + + + +**配置中心如何做到实时更新并且通知到客户端的?** \ No newline at end of file diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" index 6d305f7..f1f910b 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" @@ -1543,7 +1543,7 @@ OAuth在"客户端"(云冲印)与"服务提供商"(谷歌)之间,设 "客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。 -![](../img/oauth2.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233149.png) (A)用户打开客户端以后,客户端要求用户给予授权。 diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" new file mode 100644 index 0000000..c6ec6e8 --- /dev/null +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" @@ -0,0 +1,65 @@ +本期是【**大厂面试**】系列文章的第**34**期 + +回复【**手册**】获取大彬精心整理的**大厂面试手册**。 + +## 面试开始 + +旁白:通过微信聊天方式模拟现场面试,题目出自腾讯PCG一面 + +**面试官**:**上回考了你一道场景题,还记得不?** + +**面试官**:**题目是这样的,一个1G大小的文件,文件里每一行是一个词,每个词的大小不超过16byte,要求返回出现频率最高的100个词** + +**面试官**:**内存大小限制是10M** + +**面试官**:**当时你给的解法有问题啊,还好我回去查了下,不然就给蒙混过关了。。** + +**面试官**:**你用的是分治的思想,进行哈希取余,放进小文件。** + +**面试官**:**但是在极端情况,比如都是同一个词或者某一个词超过10m,小文件会超过10m内存限制啊** + +大彬:是的哦,上次的解法不严谨,今天给你介绍另一种解法: + +**第一步**,对大文件的单词进行排序,排序之后,相同的单词会紧挨着 + +排序的步骤如下: + +1.1 将文件按照顺序切分成大小不超过2m的小文件,总共500个小文件 + +1.2 使用10m内存**分别**对500个小文件中的单词进行**排序** + +1.3 使用一个大小为500大小的堆,对500个小文件进行**多路排序**,结果写到一个大文件中 + +其中1.3步骤中,对500个小文件进行多路排序的思路如下: + +- 初始化一个最小堆,大小就是小文件的个数500。堆中的每个节点存放每个有序小文件对应的输入流。 +- 按照每个有序文件中的下一行数据对所有文件输入流进行排序,单词小的输入文件流放在堆顶。 +- 拿出堆顶的输入流,并其下一行数据写入到最终排序的文件中,如果拿出来的输入流中还有数据的话,那么将这个输入流再一次添加到堆中。否则说明该文件输入流中没有数据了,那么可以关闭这个流。 +- 循环这个过程,直到所有文件输入流都没有数据为止。 + +**第二步**: + +2.1 初始化一个100个节点的**小顶堆**,用于保存100个出现频率最多的单词 + +2.2 遍历整个文件,一个单词一个单词的从文件中取出来,并计数 + +2.3 等到遍历的单词和上一个单词不同的话,那么上一个单词及其频率如果大于堆顶的词的频率,那么放在堆中,否则不放 + +最终,小顶堆中就是出现频率前100的单词了。 + +可以看出,这种解法相对之前的解法,更为严谨,就算整个文件都是同一个词,此解法同样有效。 + +**面试官**:行吧,今天面试就到这里吧 + + + +## 点关注,不迷路 + +大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 + +希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ + +后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) + diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" new file mode 100644 index 0000000..02d5b41 --- /dev/null +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" @@ -0,0 +1,66 @@ +本期是【**大厂面试**】系列文章的第**26**期 + +回复【**手册**】获取大彬精心整理的**大厂面试手册**。 + +## 面试开始 + +旁白:通过微信聊天方式模拟现场面试,题目出自腾讯PCG一面 + +**面试官**:**今天来道场景题** + +**面试官**:假如有一个1G大小的文件,文件里每一行是一个词,每个词的大小不超过16byte,要求返回出现频率最高的100个词 + +**面试官**:内存大小限制是10M + +旁白:由于内存限制,我们无法直接将大文件的所有词一次性读到内存中 + +旁白:可以采用**分治策略**,把一个大文件分解成多个小文件,保证每个文件的大小小于10M,进而直接将单个小文件读取到内存中进行处理 + +**大彬**:第一步,首先遍历大文件,对遍历到的每个词x,执行 `hash(x) % 500`,将结果为i的词存放到文件f(i)中 + +**大彬**:遍历结束后,可以得到500个小文件 + +**大彬**:之所以使用500个小文件,是因为原文件大小为1G,1G/500=2M,每个小文件的大小为2M左右,基本不会超过内存大小10M的限制 + +**大彬**:第二步,接着统计每个小文件中出现频数最高的100个词 + +**大彬**:可以使用HashMap来实现,其中key为词,value为该词出现的频率 + +**大彬**:对于遍历到的词x,如果在map中不存在,则执行 `map.put(x, 1)` + +**大彬**:若存在,则执行 `map.put(x, map.get(x)+1)`,将该词出现的次数加1 + +**大彬**:第三步,在第二步中找出了每个文件出现频率最高的100个词之后,通过维护一个小顶堆来找出所有小文件中出现频率最高的100个词 + +**大彬**:具体方法是,遍历第一个文件,把第一个文件中出现频率最高的100个词构建成一个小顶堆 + +**大彬**:如果第一个文件中词的个数小于100,可以继续遍历第二个文件,直到构建好有100个结点的小顶堆为止 + +**大彬**:继续遍历其他小文件,如果遍历到的词的出现次数大于堆顶上词的出现次数,可以用新遍历到的词替换堆顶的词,然后重新调整这个堆为小顶堆 + +**大彬**:当遍历完所有小文件后,这个小顶堆中的词就是出现频率最高的100个词 + +**大彬**:最后总结一下 + +1. 采用**分治**的思想,进行哈希取余 +2. 使用**HashMap**统计每个小文件单词出现的次数 +3. 使用**小顶堆**,遍历步骤2中的小文件,找出出现频率Top100的单词 + +面试官:在第二步中,将1G的文件分解到500个小文件,小文件的大小可能超过10M吧?怎么处理? + +大彬:如果某个小文件的大小超过10MB了,可以采用相同的方法对这个文件继续分解成g(1)...g(x),直到文件的大小小于10MB为止 + +**面试官**:good!今天面试就到这吧 + + + +## 点关注,不迷路 + +大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 + +希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ + +后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) + diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" new file mode 100644 index 0000000..7a452aa --- /dev/null +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" @@ -0,0 +1,82 @@ +本期是【**大厂面试**】系列文章的第**35**期 + +回复【**手册**】获取大彬精心整理的**大厂面试手册**。 + +## 面试开始 + +旁白:通过微信聊天方式模拟现场面试,题目出自百度一面 + +**面试官**:**已知某个文件内包含大量电话号码,每个号码为8位数字,如何统计不同号码的个数?** + +旁白:这类题目其实是求解数据重复的问题 + +大彬:对于这类问题,可以使用**位图法**处理 + +大彬:8位电话号码可以表示的范围为00000000~99999999。 + +大彬:如果用 bit表示一个号码,那么总共需要1亿个bit,总共需要大约100MB的内存。 + +大彬:申请一个位图并初始化为0,然后遍历所有电话号码,把遍历到的电话号码对应的位图中的bit设置为1。 + +大彬:当遍历完成后,如果bit值为1,则表示这个电话号码在文件中存在,否则这个bit对应的电话号码在文件中不存在。 + +大彬:所以这个位图中bit值为1的数量就是不同电话号码的个数了。 + +面试官:那么如何确定电话号码对应的是位图中的哪一位呢? + +大彬:嗯,可以使用下面的方法来做电话号码和位图的映射。 + +```java +00000000 对应位图最后一位:0×0000…000001。 +00000001 对应位图倒数第二位:0×0000…0000010(1 向左移 1 位)。 +00000002 对应位图倒数第三位:0×0000…0000100(1 向左移 2 位)。 +…… +00000012 对应位图的倒数第十三位:0×0000…0001 0000 0000 0000(1 向左移 12 位)。 +``` + +大彬:也就是说,电话号码就是1这个数字左移的次数。 + +**面试官:那用代码怎么实现呢?** + +大彬:首先位图可以使用一个int数组来实现。 + +旁白:在Java中int占用**4byte** + +大彬:假设电话号码为 P,而通过电话号码获取位图中对应位置的方法为: + +大彬:第一步,因为int整数占用4*8=32bit,通过 **P/32** 就可以计算出该电话号码在 bitmap 数组中的下标,从而可以确定它对应的 bit 在数组中的位置。 + +大彬:第二步,通过 P%32 就可以计算出这个电话号码在这个int数字中具体的bit的位置。 + +大彬:只要把1向左移 **P%32** 位,然后把得到的值与这个数组中的值做或运算,就可以把这个电话号码在位图中对应的位设置为1。 + +大彬:以00000100号码为例 + +大彬:首先计算数组下标,100 / 32 = 3,得到数组下标位3 + +大彬:然后计算电话号码在这个int数字中具体的bit的位置,100 % 32 = 4 + +大彬:取余为0左移1位,故取余为4左移5位,得到000...000100000 + +大彬:将位图中对应的位设置为 1,即arr[2] = arr[2] **|** 000..00100000 + +大彬:这就将电话号码映射到了位图的某一位了。 + +![原理1-1](https://gitee.com/tysondai/img/raw/master/20220423094735.png) + +**面试官**:点赞 + +**面试官**:今天面试就到这里吧 + + + +## 点关注,不迷路 + +大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 + +希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ + +后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 + +![](https://gitee.com/tysondai/img/raw/master/公众号.jpg) + diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" new file mode 100644 index 0000000..01224d9 --- /dev/null +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" @@ -0,0 +1,85 @@ +本期是【**大厂面试**】系列文章的第**31**期 + +回复【**手册**】获取大彬精心整理的**大厂面试手册**。 + +## 面试开始 + +旁白:通过微信聊天方式模拟现场面试 + +**面试官**:**看你简历上写了做过扫码登录的功能** + +**面试官**:**详细介绍下怎么设计的?** + +大彬:嗯,扫码登录功能主要分为三个阶段:**待扫描、已扫描待确认、已确认**。 + +大彬:整体流程图如下图。 + +![](E:\b站\视频素材\图片\二维码扫描\整个流程.png) + +大彬:下面分阶段来看看设计原理。 + +**1、待扫描阶段** + +首先是待扫描阶段,这个阶段是 PC 端跟服务端的交互过程。 + +每次用户打开PC端登陆请求,系统返回一个**唯一的二维码ID**,并将二维码ID的信息绘制成二维码返回给用户。 + +这里的二维码ID一定是唯一的,后续流程会将二维码ID跟身份信息绑定,不唯一的话就会造成你登陆了其他用户的账号或者其他用户登陆你的账号。 + +此时在 PC 端会启动一个定时器,**轮询查询二维码是否被扫描**。 + +如果移动端未扫描的话,那么一段时间后二维码将会失效。 + +这个阶段的交互过程如下图所示。 + +![](E:\b站\视频素材\图片\二维码扫描\第一阶段.png) + +**2、已扫描待确认阶段** + +第二个阶段是已扫描待确认阶段,主要是移动端跟服务端交互的过程。 + +首先移动端扫描二维码,获取二维码 ID,然后**将手机端登录的凭证(token)和 二维码 ID 作为参数发送给服务端** + +此时的手机在之前已经是登录的,不存在没登录的情况。 + +服务端接受请求后,会将 token 与二维码 ID 关联,然后会生成一个临时token,这个 token 会返回给移动端,临时 token 用作确认登录的凭证。 + +PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 PC 端的二维码更新为已扫描,请在手机端确认。 + +**面试官**:**打断一下,这里为什么要有手机端确认的操作?** + +大彬:假设没有确认这个环节,很容易就会被坏人拦截token去冒充登录。所以二维码扫描一定要有这个确认的页面,让用户去确认是否进行登录。 + +大彬:另外,二维码扫描确认之后,再往用户app或手机等发送登录提醒的通知,告知如果不是本人登录的,则建议用户立即修改密码。 + +大彬:这个阶段是交互过程如下图所示。 + +![](https://gitee.com/tysondai/img/raw/master/20220411002823.png) + +**3、已确认** + +扫码登录的最后阶段,用户点击确认登录,移动端携带上一步骤中获取的临时 token访问服务端。 + +服务端校对完成后,会更新二维码状态,并且给 PC 端生成一个正式的 token。 + +后续 PC 端就是持有这个 token 访问服务端。 + +这个阶段是交互过程如下图所示。 + +![](https://gitee.com/tysondai/img/raw/master/20220411002832.png) + +大彬:以上就是整个扫码登录功能的详细设计! + +**面试官**:**点赞!** + + + +## 点关注,不迷路 + +大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 + +希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ + +后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" new file mode 100644 index 0000000..036738f --- /dev/null +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" @@ -0,0 +1,176 @@ +# 超卖问题 + +先到数据库查询库存,在减库存。不是原子操作,会有超卖问题。 + +通过加排他锁解决该问题。 + +- 开始事务。 +- 查询库存,并显式的设置排他锁:SELECT * FROM table_name WHERE … FOR UPDATE +- 生成订单。 +- 去库存,update会隐式的设置排他锁:UPDATE products SET count=count-1 WHERE id=1 +- commit,释放锁。 + +也可以通过乐观锁实现。使用版本号实现乐观锁。 + +假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。 + +然后直接update的时候,只有其中一个先update了,同时更新了版本号。 + +那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了,则放弃此次update,重试直到成功。 + +```mysql +select version from goods WHERE id= 1001 +update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version); +``` + +# 秒杀系统 + +## 系统的特点 + +- 高性能:秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键 +- 一致性:秒杀商品减库存的实现方式同样关键,有限数量的商品在同一时刻被很多倍的请求同时来减库存,在大并发更新的过程中都要保证数据的准确性。 +- 高可用:秒杀时会在一瞬间涌入大量的流量,为了避免系统宕机,保证高可用,需要做好流量限制 + +## 优化思路 + +- 后端优化:将请求尽量拦截在系统上游 + - 限流:屏蔽掉无用的流量,允许少部分流量走后端。假设现在库存为 10,有 1000 个购买请求,最终只有 10 个可以成功,99% 的请求都是无效请求 + - 削峰:秒杀请求在时间上高度集中于某一个时间点,瞬时流量容易压垮系统,因此需要对流量进行削峰处理,缓冲瞬时流量,尽量让服务器对资源进行平缓处理 + - 异步:将同步请求转换为异步请求,来提高并发量,本质也是削峰处理。在真实的秒杀场景中,有三个核心流程:而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。 + - 利用缓存:创建订单时,每次都需要先查询判断库存,只有少部分成功的请求才会创建订单,因此可以将商品信息放在缓存中,减少数据库查询 + - 负载均衡:利用 Nginx 做负载均衡,使用多个服务器并发处理请求,减少单个服务器压力 +- 前端优化: + - 限流:使用验证码等,来分散用户的请求 + - 禁止重复提交:限定每个用户发起一次秒杀后,需等待才可以发起另一次请求,从而减少用户的重复请求 + - 本地标记:用户成功秒杀到商品后,将提交按钮置灰,禁止用户再次提交请求 + - 动静分离:使用CDN缓存静态页面资源,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率 +- 防作弊优化: + - 隐藏秒杀接口:如果秒杀地址直接暴露,在秒杀开始前可能会被恶意用户来刷接口,因此需要在没到秒杀开始时间不能获取秒杀接口,只有秒杀开始了,才返回秒杀地址 url 和验证 MD5,用户拿到这两个数据才可以进行秒杀 + - 同一个账号多次发出请求:在前端优化的禁止重复提交可以进行优化;也可以使用 Redis 标志位,每个用户的所有请求都尝试在 Redis 中插入一个 `userId_secondsKill` 标志位,成功插入的才可以执行后续的秒杀逻辑,其他被过滤掉,执行完秒杀逻辑后,删除标志位 + - 多个账号一次性发出多个请求:一般这种请求都来自同一个 IP 地址,可以检测 IP 的请求频率,如果过于频繁则弹出一个验证码 + - 多个账号不同 IP 发起不同请求:这种一般都是僵尸账号,检测账号的活跃度或者等级等信息,来进行限制。比如微博抽奖,用 iphone 的年轻女性用户中奖几率更大。通过用户画像限制僵尸号无法参与秒杀或秒杀不能成功 + + + +## 参考资料 + +[如何设计一个秒杀系统](https://gongfukangee.github.io/2019/06/09/SecondsKill/#%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%89%B9%E7%82%B9) + +[秒杀系统如何设计](https://www.teqng.com/2021/09/07/%E9%9D%A2%E9%9C%B8%EF%BC%9A%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%EF%BC%9F/) + +# 短链系统 + +短链服务的鼻祖是TinyURL,是最早提供短链服务的网站,目前国内也有很多短链服务:新浪(t.cn)、百度(dwz.cn)、腾讯(url.cn)等等。 + +## 短链的好处 + +- 太长的链接容易被限制长度 +- 短链接看着简洁,长链接看着容易懵 +- 安全,不想暴露参数 +- 可以统一链接转换,当然也可以实现统计点击次数等操作 + +## 短链的原理 + +短链是通过服务器重定向到原始链接实现的。 + +控制台执行命令`curl -i http://t.cn/A6ULvJho`,结果如下: + +```html +HTTP/1.1 302 Found +Date: Thu, 30 Jul 2020 13:59:13 GMT +Content-Type: text/html;charset=UTF-8 +Content-Length: 328 +Connection: keep-alive +Set-Cookie: aliyungf_tc=AQAAAJuaDFpOdQYARlNadFi502DO2kaj; Path=/; HttpOnly +Server: nginx +Location: https://www.howardliu.cn/how-to-use-branch-efficiently-in-git/index.html??spm=5176.12825654.gzwmvexct.d118.e9392c4aP1UUdv&scm=20140722.2007.2.1989 + + + +Moved Temporarily + + +

Moved Temporarily

+The document has moved here. + + +``` + +从上面的信息可以看出来,新浪做了 302 跳转,同时为了兼容性,还返回用于手动调整的 HTML 内容。整个交互流程如下: + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220522153248.png) + +## 短链生成方式 + +据统计,目前全球有 58 亿的网页,Java 中 int 取值最多是 2^32 = 4294967296 < 43 亿 < 58 亿,long 取值是 2^64 > 58 亿。所以如果是用数字的话,int 勉强能够支撑(毕竟不是所有网址都会调用短链服务创建短链),使用 long 就比较保险,但会造成空间浪费。 + +新浪微博使用 8 位字符串表示原始链接,这种字符串可以理解为数字的 62 进制表示,62^8 = 3521614606208 > 3521 亿 > 58 亿,也就是可以解决目前全球已知的网址。62 进制就是由 10 个数字 + (a-z)26 个小写字母 + (A-Z)26 个大写字母组成的数。 + +### 哈希算法 + +对原始链接取 Hash 值,是一种比较简单的思路。有很多现成的算法可以实现,但是有个避不开的问题就是:Hash 碰撞,所以选一个碰撞率低的算法比较重要。 + +推荐MurmurHash 算法,这种算法是一种非加密型哈希函数,适用于一般的哈希检索操作,目前 Redis,Memcached,Cassandra,HBase,Lucene 都在用这种算法。 + +对于碰撞问题,最简单的一种思路是,如果发生碰撞,就给原始 URL 附加上特殊字符串,直到躲开碰撞为止。具体操作如下图: + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220522154823.png) + +### 发号器 + +这个就是不管来的是什么,通过集中的统一发号器,分配一个 ID,这个 ID 就是短链的内容,比如第一个来的就是[https://tinyurl.com/1](https://xie.infoq.cn/link?target=https%3A%2F%2Ftinyurl.com%2F1),第二个就是[https://tinyurl.com/2](https://xie.infoq.cn/link?target=https%3A%2F%2Ftinyurl.com%2F2),以此类推。当然可能一些分布式 ID 算法上来就是很长的一个序号了。为了获取更短路,还可以将其转为 62 进制字符串。 + +1. Redis 自增:Redis 性能好,单机就能支撑 10W+请求,如果作为发号器,需要考虑 Redis 持久化和灾备。 +2. MySQL 自增主键:这种方案和 Redis 的方案类似,是利用数据库自增主键的提醒实现,保证 ID 不重复且连续自动创建。 +3. Snowflake:这是一种目前应用比较广的 ID 序列生成算法,美团的 Leaf 是对这种算法的封装升级服务。但是这个算法依赖于服务器时钟,如果有时钟回拨,可能会有 ID 冲突。(有人会较真毫秒中的序列值是这个算法的瓶颈,话说回来了,这个算法只是提供了一种思路,如果觉得序列长度不够,自己加就好,但是每秒百万级的服务真的又这么多吗?) + +对于统一发号器这种方式,还需要解决的一个问题是:如果同一个原始链接,应该返回相同的短链还是不同的短链? + +答案是根据用户、地点等维度,相同的原始链接,返回不同的短链。如果判断维度都相同,则返回相同短链。这样做的好处是,我们可以根据短链的点击、请求信息,做数据统计。对于短链,我们牺牲的只是一些存储和运算,但是收集的信息却是无价的。 + +## 短链存储 + +一般这种数据的存储无非就两种:关系型数据库或 NoSQL 数据库。有了上面的创建逻辑,存储就是水到渠成的了。下面给出 MySQL 存储的建表语句: + +```mysql +CREATE TABLE IF NOT EXISTS tiny_url +( + sid INT AUTO_INCREMENT PRIMARY KEY, + create_time DATETIME DEFAULT CURRENT_TIMESTAMP NULL, + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP, + version INT DEFAULT 0 NULL COMMENT '版本号', + tiny_url VARCHAR(10) NULL COMMENT '短链', + original_url TEXT NOT NULL COMMENT '原始链接', + # 其他附加信息 + creator_ip INT DEFAULT 0 NOT NULL, + creator_user_agent TEXT NOT NULL, + # 用户其他信息,用于后续统计,对于这些数据,只要存储影响创建短链的必要字段就行,其他的都可以直接发送到数据服务中 + instance_id INT DEFAULT 0 NOT NULL, + # 创建短链服务实例ID + state TINYINT DEFAULT 1 NULL COMMENT '-1无效 1有效' +); +``` + +## 短链请求 + +存储完成后,接下来就该使用了。 + +通常的做法是会根据请求的短链字符串,从存储中找到数据,然后返回 HTTP 重定向到原始地址。如果存储使用关系型数据库,对于短链字段一般需要创建索引,而且为了避免数据库成为瓶颈,数据库前面还会通过缓存铺路。而且为了提高缓存合理使用,一般通过 LRU 算法淘汰非热点短链数据。流程如下: + +短链请求 -> 布隆过滤器 -> 缓存 -> 数据库 + +图中的布隆过滤器是为了防止缓存击穿,造成服务器压力过大。 + +这里还有一个问题:HTTP 返回重定向编码时使用 301 还是 302,为什么新浪微博会返回 302,而不是更加符合语义的 301 跳转? + +来看看HTTP状态码中301和302分别是什么含义: + +- 301,代表永久重定向。也就是说,浏览器第一次请求拿到重定向地址后,以后的请求,都是直接从浏览器缓存中获取重定向地址,不会再请求短链服务。这样可以有效减少服务请求数,降低服务器负载,但是因为后续浏览器不再向后端发送请求,因此获取不到真实的点击数。 +- 302,代表临时重定向。也就是说,每次浏览器都会向服务器发起请求获取新的地址,虽然会给服务器增加压力,但在硬件过剩的今天,这点压力比起数据简直不值一提。所以,302 重定向才是短链服务的首选。 + +## 参考链接 + +[短 URL 系统是怎么设计的?](https://www.zhihu.com/question/29270034) + +[系统设计系列之如何设计一个短链服务](https://xie.infoq.cn/article/483fcfbe3f942cb1fa9d9ce20) + diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241old.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241old.md" new file mode 100644 index 0000000..ef3fb83 --- /dev/null +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241old.md" @@ -0,0 +1,24 @@ +1. 设计一个聊天服务 +2. 设计拼车服务 +3. 设计一个URL缩短服务 +4. 设计一个社交媒体服务 +5. 设计一个社交留言板 +6. 设计文件存储服务 +7. 设计一个视频流媒体服务 +8. 设计一个API速率限制器 +9. 设计一个邻近服务器 +10. 设计一个预输入服务 + + + +## 秒杀系统 + +rabbitmq是为了削峰,如果是有1000件商品参与秒杀,每个商品有10件,那么系统的最大并发就是1万,db扛不住这么大的并发的,如果商品数量更大,这个并发量会更大。 +通过Redis预减库存减少到DB的请求,通过消息队列异步写库缓解数据库的压力。用消息队列来缓冲瞬时流量,把同步的直接调用转换成异步操作。 + +把判断库存扣减库存的操作封装成lua脚本,实现原子性操作,避免超卖。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509004840.jpg) + + + diff --git "a/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" similarity index 100% rename from "\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" similarity index 100% rename from "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" similarity index 100% rename from "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" diff --git "a/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" similarity index 100% rename from "\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" new file mode 100644 index 0000000..7325e6a --- /dev/null +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" @@ -0,0 +1,169 @@ +# 二分查找 + +```java + public int binarySearch(int[] arr, int target) { + if (arr == null || arr.length <= 1) { + return -1; + } + + int left = 0; + int right = arr.length - 1; + + while (left <= right) { + int mid = (left + right) >>> 1; + if (arr[mid] > target) { + right = mid - 1; + } else if (arr[mid] < target) { + left = mid + 1; + } else { + return mid; + } + } + + return -1; + } +``` + +# 归并排序 + + + +## 简单讲下归并排序? + +归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。 + +## 说说归并排序怎么实现的? + +两路归并排序算法思路是递归处理。每个递归过程涉及三个步骤 + +- 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素 +- 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作 +- 合并: 合并两个排好序的子序列,生成排序结果 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220327151830.png) + +代码实现: + +```java +public class MergeSort { + public void mergeSort(int[] arr) { + if (arr == null || arr.length == 0) { + return; + } + //辅助数组 + int[] tmpArr = new int[arr.length]; + mergeSort(arr, tmpArr, 0, arr.length - 1); + } + + private void mergeSort(int[] arr, int[] tmpArr, int left, int right) { + if (left < right) { + int mid = (left + right) >> 1; + mergeSort(arr, tmpArr, left, mid); + mergeSort(arr, tmpArr, mid + 1, right); + merge(arr, tmpArr, left, mid, right); + } + } + + private void merge(int[] arr, int[] tmpArr, int left, int mid, int right) { + int i = left; + int j = mid + 1; + int tmpIndex = left; + while (i <= mid && j <= right) { + if (arr[i] < arr[j]) { + tmpArr[tmpIndex++] = arr[i]; + i++; + } else { + tmpArr[tmpIndex++] = arr[j]; + j++; + } + } + + while (i <= mid) { + tmpArr[tmpIndex++] = arr[i++]; + } + + while (j <= right) { + tmpArr[tmpIndex++] = arr[j++]; + } + + for (int m = left; m <= right; m++) { + arr[m] = tmpArr[m]; + } + } +} +``` + +## 时间复杂度是多少? + +对长度为n的序列,需进行logn次二路归并,每次归并的时间为O(n),故时间复杂度是O(nlgn)。 + +## 空间复杂度是多少? + +归并排序需要辅助空间来暂存两个有序子序列归并的结果,故其辅助空间复杂度为O(n) + +# 快速排序 + +## 了解快速排序吗? + +快速排序是由**冒泡排序**改进而得到的,是一种排序执行效率很高的排序算法,它利用**分治法**来对待排序序列进行分治排序,它的思想主要是通过一趟排序将待排记录分隔成独立的两部分,其中的一部分比关键字小,后面一部分比关键字大,然后再对这前后的两部分分别采用这种方式进行排序,通过递归的运算最终达到整个序列有序。 + +## 快速排序的过程? + +1. 在待排序的N个记录中任取一个元素(通常取第一个记录)作为基准,称为基准记录; +2. 定义两个索引 left 和 right 分别表示首索引和尾索引,key 表示基准值; +3. 首先,尾索引向前扫描,直到找到比基准值小的记录,并替换首索引对应的值; +4. 然后,首索引向后扫描,直到找到比基准值大于的记录,并替换尾索引对应的值; +5. 若在扫描过程中首索引等于尾索引(left = right),则一趟排序结束;将基准值(key)替换首索引所对应的值; +6. 再进行下一趟排序时,待排序列被分成两个区:[0,left-1]和[righ+1,end] +7. 对每一个分区重复以上步骤,直到所有分区中的记录都有序,排序完成 + +代码实现: + +```java + public void quickSort(int[] arr) { + if (arr == null) { + return; + } + quickSortHelper(arr, 0, arr.length - 1); + } + private void quickSortHelper(int[] arr, int left, int right) { + if (left > right) { + return; + } + int tmp = arr[left]; + int i = left; + int j = right; + while (i < j) { + //j先走,最终循环终止时,j停留的位置就是arr[left]的正确位置 + //改为i<=j,则会进入死循环,[1,5,5,5,5]->[1] 5 [5,5,5]->[5,5,5],会死循环 + while (i < j && arr[j] >= tmp) { + j--; + } + while (i < j && arr[i] <= tmp) { + i++; + } + if (i < j) { + int tmp1 = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp1; + } else { + break; + } + } + + //当循环终止的时候,i=j,因为是j先走的,j所在位置的值小于arr[left],交换arr[j]和arr[left] + arr[left] = arr[j]; + arr[j] = tmp; + + quickSortHelper(arr, left, j - 1); + quickSortHelper(arr, j + 1, right); + } +``` + +## 快排为什么比冒泡效率高? + +快速排序之所以比较快,是因为相比冒泡排序,每次的交换都是跳跃式的,每次设置一个基准值,将小于基准值的都交换到左边,大于基准值的都交换到右边,这样不会像冒泡一样每次都只交换相邻的两个数,因此比较和交换的此数都变少了,速度自然更高。 + +## 快排的时间复杂度是多少? + +快速排序的平均时间复杂度是O(nlgn),最坏时间复杂度是O(n^2)。 \ No newline at end of file diff --git "a/\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" similarity index 100% rename from "\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" diff --git "a/\347\275\221\347\273\234/session\345\222\214cookie.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" similarity index 100% rename from "\347\275\221\347\273\234/session\345\222\214cookie.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" diff --git "a/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" similarity index 100% rename from "\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" diff --git "a/\347\275\221\347\273\234/\347\275\221\347\273\234.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\347\275\221\347\273\234.md" similarity index 100% rename from "\347\275\221\347\273\234/\347\275\221\347\273\234.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\347\275\221\347\273\234.md" diff --git "a/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" similarity index 100% rename from "\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" rename to "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" From 8ef828dd4e63fd24fa28b06b2334ec0f863b1715 Mon Sep 17 00:00:00 2001 From: tyson Date: Thu, 16 Jun 2022 23:32:40 +0800 Subject: [PATCH 07/84] update --- ...21\351\235\242\350\257\225\351\242\230.md" | 3 + ...00\351\235\242\350\257\225\351\242\230.md" | 8 +- ...21\351\235\242\350\257\225\351\242\230.md" | 8 +- ...10\351\235\242\350\257\225\351\242\230.md" | 4 + README.md | 12 +- .../RabbitMQ.md" | 15 +- ...is\351\235\242\350\257\225\351\242\230.md" | 139 +++++++---- ...27\351\235\242\350\257\225\351\242\230.md" | 6 +- ...21\351\235\242\350\257\225\351\242\230.md" | 4 + ...is\351\235\242\350\257\225\351\242\230.md" | 42 +++- ...25\351\242\230\346\200\273\347\273\223.md" | 4 + ...VC\351\235\242\350\257\225\351\242\230.md" | 1 + ...ng\351\235\242\350\257\225\351\242\230.md" | 4 + ...37\351\235\242\350\257\225\351\242\230.md" | 232 +++++++++++++++++- ...60\346\215\256\347\273\223\346\236\204.md" | 31 +++ ...21\351\235\242\350\257\225\351\242\230.md" | 3 + 16 files changed, 442 insertions(+), 74 deletions(-) diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index e4bddb5..49892fd 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -748,3 +748,6 @@ class Person { - 周志明. 深入理解 Java 虚拟机 [M]. 机械工业出版社 + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 758e026..f477f15 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -924,7 +924,7 @@ public class Student extends Person { 1、**语法层面**上的区别 -- 抽象类可以有方法实现,而接口的方法中只能是抽象方法; +- 抽象类可以有方法实现,而接口的方法中只能是抽象方法(Java 8 开始接口方法可以有默认实现); - 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型; - 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法; - 一个类只能继承一个抽象类,而一个类却可以实现多个接口。 @@ -1163,3 +1163,9 @@ Java语言的关键字,变量修饰符,如果用transient声明一个实例 Java泛型是JDK 5中引⼊的⼀个新特性, 允许在定义类和接口的时候使⽤类型参数。声明的类型参数在使⽤时⽤具体的类型来替换。 泛型最⼤的好处是可以提⾼代码的复⽤性。以List接口为例,我们可以将String、 Integer等类型放⼊List中, 如不⽤泛型, 存放String类型要写⼀个List接口, 存放Integer要写另外⼀个List接口, 泛型可以很好的解决这个问题。 + +## String为什么不可变? + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index a65d22c..cf0911c 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -569,8 +569,8 @@ synchronized 修饰的方法并没有 `monitorenter` 指令和 `monitorexit` 指 **相同点**: -1. 使当前线程暂停运行,把机会交给其他线程 -2. 任何线程在等待期间被中断都会抛出`InterruptedException` +1. 它们都可以使当前线程暂停运行,把机会交给其他线程 +2. 任何线程在调用wait()和sleep()之后,在等待期间被中断都会抛出`InterruptedException` **不同点**: @@ -1146,3 +1146,7 @@ SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能 JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,支持并发访问、修改。 另外ConcurrentHashMap使用了一种不同的迭代方式。当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index 14acae6..f5b3209 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -595,3 +595,7 @@ http://www.importnew.com/20386.html https://www.cnblogs.com/yangming1996/p/7997468.html https://coolshell.cn/articles/9606.htm(HashMap 死循环) + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git a/README.md b/README.md index 79ae7ad..eed60e3 100644 --- a/README.md +++ b/README.md @@ -137,19 +137,19 @@ # 计算机网络 -[【大厂面试】—— 计算机网络常见面试题总结](网络/计算机网络高频面试题.md) (**知乎1k+收藏!推荐 :+1:**) +[【大厂面试】—— 计算机网络常见面试题总结](计算机基础/网络/计算机网络高频面试题.md) (**知乎1k+收藏!推荐 :+1:**) -[session和cookie详解](网络/session和cookie.md) +[session和cookie详解](计算机基础/网络/session和cookie.md) # 数据结构与算法 [如何高效的刷LeetCode?](https://www.zhihu.com/question/280279208/answer/2377906738) -[7种常见的排序算法Java代码实现](数据结构与算法/常见的排序算法Java代码实现.md) +[7种常见的排序算法Java代码实现](计算机基础/数据结构与算法/常见的排序算法Java代码实现.md) -[二叉树前序、中序、后序、层序遍历代码实现](数据结构与算法/二叉树前序、中序、后序、层序遍历代码实现.md) +[二叉树前序、中序、后序、层序遍历代码实现](计算机基础/数据结构与算法/二叉树前序、中序、后序、层序遍历代码实现.md) -[常见数据结构总结](数据结构与算法/数据结构.md) +[常见数据结构总结](计算机基础/数据结构与算法/数据结构.md) # 设计模式 @@ -201,6 +201,8 @@ | 2021.11.25 | 支付宝收款码 | *海 | 1元 | | | 2021.12.10 | 微信收款码 | 浩*y | 10元 | | | 2021.12.15 | 微信收款码 | biubiu* | 6.66元 | 好 | +| 2022.02.17 | 微信收款码 | *齐 | 8元 | | +| 2022.05.03 | 微信收款码 | *哈 | 2元 | | diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" index cc43200..4c51d3e 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" @@ -29,18 +29,6 @@ -> 本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础、MySQL、Spring Boot、MyBatis、Redis、RabbitMQ、计算机网络、数据结构与算法等等,欢迎大家提pr和star! -> -> github地址:https://github.com/Tyson0314/Java-learning -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/Java-learning - -文章目录: - -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914234334988.png) - # 简介 RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 @@ -430,3 +418,6 @@ msg.getMessageProperties().setExpiration("3000"); [线上rabbitmq问题](https://juejin.im/post/6844904088212094983#heading-0) + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index 914796d..03a9618 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -94,12 +94,6 @@ Redis基于Reactor模式开发了网络事件处理器,这个处理器被称 使用 redis 或 memcached 之类的称为**分布式缓存**,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。 -## Redis的内存用完了会怎样? - -如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回)。 - -也可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。 - ## Redis 数据类型有哪些? **基本数据类型**: @@ -122,12 +116,6 @@ Redis基于Reactor模式开发了网络事件处理器,这个处理器被称 3、**Geospatial** :主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如定位、附近的人等。 -## keys命令存在的问题? - -redis的单线程的。keys指令会导致线程阻塞一段时间,直到执行完毕,服务才能恢复。scan采用渐进式遍历的方式来解决keys命令可能带来的阻塞问题,每次scan命令的时间复杂度是`O(1)`,但是要真正实现keys的功能,需要执行多次scan。 - -scan的缺点:在scan的过程中如果有键的变化(增加、删除、修改),遍历过程可能会有以下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键。 - ## SortedSet和List异同点? **相同点**: @@ -142,6 +130,22 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. 列表不能简单的调整某个元素的位置,有序列表可以(更改元素的分数); 4. 有序集合更耗内存。 +## Redis的内存用完了会怎样? + +如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回)。 + +也可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。 + +## Redis如何做内存优化? + +可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面。 + +## keys命令存在的问题? + +redis的单线程的。keys指令会导致线程阻塞一段时间,直到执行完毕,服务才能恢复。scan采用渐进式遍历的方式来解决keys命令可能带来的阻塞问题,每次scan命令的时间复杂度是`O(1)`,但是要真正实现keys的功能,需要执行多次scan。 + +scan的缺点:在scan的过程中如果有键的变化(增加、删除、修改),遍历过程可能会有以下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键。 + ## Redis事务 事务的原理是将一个事务范围内的若干命令发送给Redis,然后再让Redis依次执行这些命令。 @@ -286,7 +290,7 @@ appendfsync no //由操作系统决定何时进行同步操作 1. 对于同一份文件AOF文件比RDB数据快照要大。 2. 数据恢复比较慢。 -## RDB和AOF如何选择? +### RDB和AOF如何选择? 通常来说,应该同时使用两种持久化方案,以保证数据安全。 @@ -307,16 +311,11 @@ appendfsync no //由操作系统决定何时进行同步操作 **Redis cluster**:服务端分片技术,3.0版本开始正式提供。Redis Cluster并没有使用一致性hash,而是采用slot(槽)的概念,一共分成16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行。主要是针对海量数据+高并发+高可用的场景,如果是海量数据,如果你的数据量很大,那么建议就用Redis cluster,所有主节点的容量总和就是Redis cluster可缓存的数据容量。 -## 主从复制 +## 主从架构 -Redis的复制功能是支持多个数据库之间的数据同步。主数据库可以进行读写操作,当主数据库的数据发生变化时会自动将数据同步到从数据库。从数据库一般是只读的,它会接收主数据库同步过来的数据。一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。 +单机的 redis,能够承载的 QPS 大概就在上万到几万不等。对于缓存来说,一般都是用来支撑读高并发的。因此架构做成主从(master-slave)架构,一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读请求全部走从节点。这样也可以很轻松实现水平扩容,支撑读高并发。 -```java -redis-server //启动Redis实例作为主数据库 -redis-server --port 6380 --slaveof 127.0.0.1 6379 //启动另一个实例作为从数据库 -slaveof 127.0.0.1 6379 -SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 -``` +Redis的复制功能是支持多个数据库之间的数据同步。主数据库可以进行读写操作,当主数据库的数据发生变化时会自动将数据同步到从数据库。从数据库一般是只读的,它会接收主数据库同步过来的数据。一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。 **主从复制的原理?** @@ -355,11 +354,18 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 ![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) -**哈希槽是如何映射到 Redis 实例上的?** +**工作原理:** + +1. 通过哈希的方式,将数据分片,每个节点均分存储一定哈希槽(哈希值)区间的数据,默认分配了16384 个槽位 +2. 每份数据分片会存储在多个互为主从的多节点上 +3. 数据写入先写主节点,再同步到从节点(支持配置为阻塞同步) +4. 同一分片多个节点间的数据不保持一致性 +5. 读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点 +6. 扩容时时需要需要把旧节点的数据迁移一部分到新节点 -1. 对键值对的`key`使用 `crc16` 算法计算一个结果 -2. 将结果对 16384 取余,得到的值表示 `key` 对应的哈希槽 -3. 根据该槽信息定位到对应的实例 +在 redis cluster 架构下,每个 redis 要放开两个端口号,比如一个是 6379,另外一个就是 加1w 的端口号,比如 16379。 + +16379 端口号是用来进行节点间通信的,也就是 cluster bus 的东西,cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一种二进制的协议,`gossip` 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。 **优点:** @@ -374,8 +380,9 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 * **事务操作支持有限**,只支持多`key`在同一节点上的事务操作,当多个`key`分布于不同的节点上时无法使用事务功能。 * `key`作为数据分区的最小粒度,不能将一个很大的键值对象如`hash`、`list`等映射到不同的节点。 * **不支持多数据库空间**,单机下的Redis可以支持到16个数据库,集群模式下只能使用1个数据库空间。 +* 只能使用0号数据库。 -### 哈希分区算法有哪些? +**哈希分区算法有哪些?** 节点取余分区。使用特定的数据,如Redis的键或用户ID,对节点数量N取余:hash(key)%N计算出哈希值,用来决定数据映射到哪一个节点上。 优点是简单性。扩容时通常采用翻倍扩容,避免数据映射全部被打乱导致全量迁移的情况。 @@ -431,7 +438,9 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由Redis自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。 -## 缓存穿透 +## 缓存常见问题 + +### 缓存穿透 缓存穿透是指查询一个**不存在的数据**,由于缓存是不命中时被动写的,如果从DB查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了。 @@ -440,19 +449,27 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 1. **缓存空值**,不会查数据库。 2. 采用**布隆过滤器**,将所有可能存在的数据哈希到一个足够大的`bitmap`中,查询不存在的数据会被这个`bitmap`拦截掉,从而避免了对`DB`的查询压力。 -布隆过滤器的原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,将元素通过散列函数映射之后会得到k个点,如果这些点有任何一个0,则被检元素一定不在,直接返回;如果都是1,则查询元素很可能存在,就会去查询Redis和数据库。 +布隆过滤器的原理:当一个元素被加入集合时,通过K个哈希函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,将元素通过哈希函数映射之后会得到k个点,如果这些点有任何一个0,则被检元素一定不在,直接返回;如果都是1,则查询元素很可能存在,就会去查询Redis和数据库。 + +布隆过滤器一般用于在大数据量的集合中判定某元素是否存在。 -## 缓存雪崩 +### 缓存雪崩 缓存雪崩是指在我们设置缓存时采用了相同的过期时间,**导致缓存在某一时刻同时失效**,请求全部转发到DB,DB瞬时压力过重挂掉。 -解决方法:在原有的失效时间基础上**增加一个随机值**,使得过期时间分散一些。 +解决方法: -## 缓存击穿 +1. 在原有的失效时间基础上**增加一个随机值**,使得过期时间分散一些。这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。 +2. **加锁排队可以起到缓冲的作用**,防止大量的请求同时操作数据库,但它的缺点是**增加了系统的响应时间**,**降低了系统的吞吐量**,牺牲了一部分用户体验。当缓存未查询到时,对要请求的 key 进行加锁,只允许一个线程去数据库中查,其他线程等候排队。 +3. 设置二级缓存。二级缓存指的是除了 Redis 本身的缓存,**再设置一层缓存**,当 Redis 失效之后,先去查询二级缓存。例如可以设置一个本地缓存,在 Redis 缓存失效的时候先去查询本地缓存而非查询数据库。 + +### 缓存击穿 缓存击穿:大量的请求同时查询一个 key 时,此时这个 key 正好失效了,就会导致大量的请求都落到数据库。**缓存击穿是查询缓存中失效的 key,而缓存穿透是查询不存在的 key。** -解决方法:加分布式锁,第一个请求的线程可以拿到锁,拿到锁的线程查询到了数据之后设置缓存,其他的线程获取锁失败会等待50ms然后重新到缓存取数据,这样便可以避免大量的请求落到数据库。 +解决方法: + +1、**加互斥锁**。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。可以使用Redis分布式锁实现,代码如下: ```java public String get(String key) { @@ -474,7 +491,9 @@ public String get(String key) { } ``` -## 缓存预热 +2、**热点数据不过期**。直接将缓存设置为不过期,然后由定时任务去异步加载数据,更新缓存。这种方式适用于比较极端的场景,例如流量特别特别大的场景,使用时需要考虑业务能接受数据不一致的时间,还有就是异常情况的处理,保证缓存可以定时刷新。 + +### 缓存预热 缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据! @@ -484,7 +503,7 @@ public String get(String key) { 2. 数据量不大,可以在项目启动的时候自动进行加载; 3. 定时刷新缓存; -## 缓存降级 +### 缓存降级 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。 @@ -501,26 +520,15 @@ public String get(String key) { ## Redis 怎么实现消息队列? -使用一个列表,让生产者将任务使用LPUSH命令放进列表,消费者不断用RPOP从列表取出任务。 - -> BRPOP和RPOP命令相似,唯一的区别就是当列表没有元素时BRPOP命令会一直阻塞连接,直到有新元素加入。 +使用list类型保存数据信息,rpush生产消息,lpop消费消息,当lpop没有消息时,可以sleep一段时间,然后再检查有没有信息,如果不想sleep的话,可以使用blpop, 在没有信息的时候,会一直阻塞,直到信息的到来。 ```java -BRPOP queue 0 //0表示不限制等待时间 +BLPOP queue 0 //0表示不限制等待时间 ``` -**优先级队列** +> BLPOP和LPOP命令相似,唯一的区别就是当列表没有元素时BLPOP命令会一直阻塞连接,直到有新元素加入。 -如果多个键都有元素,则按照从左到右的顺序取元素。 - -```java -BLPOP queue:1 queue:2 queue:3 0 -``` - -**发布/订阅模式** - -`PSUBSCRIBE channel?*` 按照规则订阅。 -`PUNSUBSCRIBE channel?*` 退订通过PSUBSCRIBE命令按照某种规则订阅的频道。其中订阅规则要进行严格的字符串匹配,`PUNSUBSCRIBE *`无法退订`channel?*`规则。 +redis可以通过pub/sub**主题订阅模式**实现一个生产者,多个消费者,当然也存在一定的缺点,当消费者下线时,生产的消息会丢失。 ```java PUBLISH channel1 hi @@ -528,9 +536,10 @@ SUBSCRIBE channel1 UNSUBSCRIBE channel1 //退订通过SUBSCRIBE命令订阅的频道。 ``` -缺点:在消费者下线的情况下,生产的消息会丢失。 +> `PSUBSCRIBE channel?*` 按照规则订阅。 +> `PUNSUBSCRIBE channel?*` 退订通过PSUBSCRIBE命令按照某种规则订阅的频道。其中订阅规则要进行严格的字符串匹配,`PUNSUBSCRIBE *`无法退订`channel?*`规则。 -**延时队列** +## Redis 怎么实现延时队列 使用sortedset,拿时间戳作为score,消息内容作为key,调用zadd来生产消息,消费者用`zrangebyscore`指令获取N秒之前的数据轮询进行处理。 @@ -606,3 +615,31 @@ Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式 2. 避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client 挂掉了 3. 容错性:只要大部分 Redis 节点存活就可以正常提供服务 +## Redis大key怎么处理? + +通常我们会将含有较大数据或含有大量成员、列表数的Key称之为大Key。 + +以下是对各个数据类型大key的描述: + +- value是STRING类型,它的值超过5MB +- value是ZSET、Hash、List、Set等集合类型时,它的成员数量超过1w个 + +上述的定义并不绝对,主要是根据value的成员数量和大小来确定,根据业务场景确定标准。 + +怎么处理: + +1. 当vaule是string时,可以使用序列化、压缩算法将key的大小控制在合理范围内,但是序列化和反序列化都会带来更多时间上的消耗。或者将key进行拆分,一个大key分为不同的部分,记录每个部分的key,使用multiget等操作实现事务读取。 +2. 当value是list/set等集合类型时,根据预估的数据规模来进行分片,不同的元素计算后分到不同的片。 + +## Redis常见性能问题和解决方案? + +1. Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。 +2. 如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。 +3. 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。 +4. 尽量避免在压力较大的主库上增加从库 +5. Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。 +6. 为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" index 633f860..bfbacf6 100644 --- "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" @@ -65,4 +65,8 @@ 在消息生产时,MQ内部针对每条生产者发送的消息生成一个唯一id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。 -在消息消费时,要求消息体中也要有一全局唯一id作为去重和幂等的依据,避免同一条消息被重复消费。 \ No newline at end of file +在消息消费时,要求消息体中也要有一全局唯一id作为去重和幂等的依据,避免同一条消息被重复消费。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index d829b99..e7bfe2d 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -971,3 +971,7 @@ B+树中**非叶子节点存的是key + 指针**;**叶子节点存的是数据 * 限定数据的范围。比如:用户在查询历史信息的时候,可以控制在一个月的时间范围内 * 读写分离。经典的数据库拆分方案,主库负责写,从库负责读 * 通过分库分表的方式进行优化,主要有垂直拆分和水平拆分 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" index 21e911b..174db08 100644 --- "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" @@ -1,10 +1,20 @@ -## Mybatis框架简介 +## Mybatis是什么? - MyBatis框架是一个开源的数据持久层框架。 - 它的内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。 - MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在配置文件当中,实现SQL的灵活配置。 - 这样做的好处是将SQL与程序代码分离,可以在不修改代码的情况下,直接在配置文件当中修改SQL。 +## **ORM是什么** + +ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。 + +## 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里? + +Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。 + +而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。 + ## MyBatis框架的优缺点及其适用的场合 **优点** @@ -52,12 +62,38 @@ Mybatis有三种基本的Executor执行器,`SimpleExecutor`、`ReuseExecutor` 1. 通过注解绑定,在接口的方法上面加上 @Select@Update等注解里面包含Sql语句来绑定(SQL语句比较简单的时候,推荐注解绑定) 2. 通过xml里面写SQL来绑定, 指定xml映射文件里面的namespace必须为接口的全路径名(SQL语句比较复杂的时候,推荐xml绑定) +## Mybatis 是如何进行分页的? + +Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,先把数据都查出来,然后再做分页。 + +可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。 + +## 分页插件的基本原理是什么? + +分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql(SQL 拼接 limit),根据 dialect 方言,添加对应的物理分页语句和物理分页参数,用到了技术 JDK 动态代理,用到了责任链设计模式。 + ## 简述Mybatis的插件运行原理 Mybatis仅可以编写针对 `ParameterHandler`、`ResultSetHandler`、`StatementHandler`、`Executor`这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是`InvocationHandler`的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。 编写插件:实现Mybatis的Interceptor接口并复写`intercept()`方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。 +## .如何编写一个插件? + +编写插件:实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后再给插件编写注解,指定要拦截哪一个接口的哪些方法即可,最后在配置文件中配置你编写的插件。 + +## .Mybatis 是否支持延迟加载? + +Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载`lazyLoadingEnabled=true|false`。 + +## 延迟加载的基本原理是什么? + +延迟加载的基本原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法。 + +比如调用`a.getB().getName()`,拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用`a.setB(b)`,于是 a 的对象 b 属性就有值了,接着完成`a.getB().getName()`方法的调用。 + +当然了,不光是 Mybatis,几乎所有的包括 Hibernate,支持延迟加载的原理都是一样的。 + ## #{}和${}的区别是什么? #{ } 被解析成预编译语句,预编译之后可以直接执行,不需要重新编译sql。 @@ -115,3 +151,7 @@ mybatis底层使用`PreparedStatement`,默认情况下,将对所有的 sql 二级缓存要求返回的POJO必须是可序列化的,即要求实现Serializable接口。 当开启二级缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index e9ddb23..6eba065 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -294,3 +294,7 @@ hello.msg=大彬 ## @Value原理 @Value的解析就是在bean初始化阶段。BeanPostProcessor定义了bean初始化前后用户可以对bean进行操作的接口方法,它的一个重要实现类`AutowiredAnnotationBeanPostProcessor`为bean中的@Autowired和@Value注解的注入功能提供支持。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" index 82ac987..82aca97 100644 --- "a/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" @@ -86,3 +86,4 @@ Spring MVC的工作原理如下: +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index 641525e..f0f66c0 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -614,3 +614,7 @@ Spring的Bean默认都是单例的,某些情况下,单例是并发不安全 **4、分布式或微服务的并发安全** 如果还要进一步考虑到微服务或分布式服务的影响,方式3便不合适了。这种情况下可以借助于可以共享某些信息的分布式缓存中间件,如Redis等。这样即可保证同一种服务的不同服务实例都拥有同一份共享信息了。 + + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" index c068c14..5438b9a 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" @@ -19,6 +19,25 @@ 异步:系统进程用一种走走停停的方式执行,(并不是一下子走完),进程什么时候以怎样的速度向前推进是不可预知的 +## 进程线程 + +进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间。 + +线程是比进程更小的执行单位,它是在一个进程中独立的控制流,一个进程可以启动多个线程,每条线程并行执行不同的任务。 + +**进程和线程的区别如下**: + +- 调度:进程是资源管理的基本单位,线程是程序执行的基本单位。 +- 切换:线程上下文切换比进程上下文切换要快得多。 +- 拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源。 +- 系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,I/O设备等,OS所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销。 + +## 并发和并行 + +并发就是在一段时间内,多个任务都会被处理;但在某一时刻,只有一个任务在执行。单核处理器可以做到并发。比如有两个进程`A`和`B`,`A`运行一个时间片之后,切换到`B`,`B`运行一个时间片之后又切换到`A`。因为切换速度足够快,所以宏观上表现为在一段时间内能同时运行多个程序。 + +并行就是在同一时刻,有多个任务在执行。这个需要多核处理器才能完成,在微观上就能同时执行多条指令,不同的程序被放到不同的处理器上运行,这个是物理上的多个进程同时进行。 + ## 多线程相较单线程的好处 1、并发提升程序执行效率 @@ -53,4 +72,215 @@ 3、**共享内存**。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 -4、**信号量**。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 \ No newline at end of file +4、**信号量**。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 + +## 死锁 + +死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。 + +如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 + +![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) + +下面通过例子说明线程死锁,代码来自并发编程之美。 + +```java +public class DeadLockDemo { + private static Object resource1 = new Object();//资源 1 + private static Object resource2 = new Object();//资源 2 + + public static void main(String[] args) { + new Thread(() -> { + synchronized (resource1) { + System.out.println(Thread.currentThread() + "get resource1"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread() + "waiting get resource2"); + synchronized (resource2) { + System.out.println(Thread.currentThread() + "get resource2"); + } + } + }, "线程 1").start(); + + new Thread(() -> { + synchronized (resource2) { + System.out.println(Thread.currentThread() + "get resource2"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread() + "waiting get resource1"); + synchronized (resource1) { + System.out.println(Thread.currentThread() + "get resource1"); + } + } + }, "线程 2").start(); + } +} +``` + +代码输出如下: + +```java +Thread[线程 1,5,main]get resource1 +Thread[线程 2,5,main]get resource2 +Thread[线程 1,5,main]waiting get resource2 +Thread[线程 2,5,main]waiting get resource1 +``` + +线程 A 通过 `synchronized` (resource1) 获得 resource1 的监视器锁,然后通过 `Thread.sleep(1000)`。让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。 + +## 进程调度策略有哪几种? + +- **先来先服务**:非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。另外,对`I/O`密集型进程也不利,因为这种进程每次进行`I/O`操作之后又得重新排队。 + +- **短作业优先**:非抢占式的调度算法,按估计运行时间最短的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。 + +- **最短剩余时间优先**:最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。 + +- **时间片轮转**:将所有就绪进程按 `FCFS` 的原则排成一个队列,每次调度时,把 `CPU` 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 `CPU` 时间分配给队首的进程。 + + 时间片轮转算法的效率和时间片的大小有很大关系:因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。 而如果时间片过长,那么实时性就不能得到保证。 + +- **优先级调度**:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。 + +## 进程有哪些状态? + +进程一共有`5`种状态,分别是创建、就绪、运行(执行)、终止、阻塞。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220613090034.png) + +- 运行状态就是进程正在`CPU`上运行。在单处理机环境下,每一时刻最多只有一个进程处于运行状态。 +- 就绪状态就是说进程已处于准备运行的状态,即进程获得了除`CPU`之外的一切所需资源,一旦得到`CPU`即可运行。 +- 阻塞状态就是进程正在等待某一事件而暂停运行,比如等待某资源为可用或等待`I/O`完成。即使`CPU`空闲,该进程也不能运行。 + +**运行态→阻塞态**:往往是由于等待外设,等待主存等资源分配或等待人工干预而引起的。 +**阻塞态→就绪态**:则是等待的条件已满足,只需分配到处理器后就能运行。 +**运行态→就绪态**:不是由于自身原因,而是由外界原因使运行状态的进程让出处理器,这时候就变成就绪态。例如时间片用完,或有更高优先级的进程来抢占处理器等。 +**就绪态→运行态**:系统按某种策略选中就绪队列中的一个进程占用处理器,此时就变成了运行态。 + +## 死锁怎么产生?怎么避免? + +**死锁产生的四个必要条件**: + +- 互斥:一个资源每次只能被一个进程使用 + +- 请求与保持:一个进程因请求资源而阻塞时,不释放获得的资源 + +- 不剥夺:进程已获得的资源,在未使用之前,不能强行剥夺 + +- 循环等待:进程之间循环等待着资源 + +**避免死锁的方法**: + +- 互斥条件不能破坏,因为加锁就是为了保证互斥 +- 一次性申请所有的资源,避免线程占有资源而且在等待其他资源 +- 占有部分资源的线程进一步申请其他资源时,如果申请不到,主动释放它占有的资源 +- 按序申请资源 + +## 虚拟内存 + +虚拟存储器就是具有请求调入功能,能从逻辑上对内存容量加以扩充的一种存储器系统,虚拟内存有多次性,对换性和虚拟性三个特征,它可以将程序分多次调入内存,使得在较小的用户空间可以执行较大的用户程序,所以同时容纳更多的进程并发执行,从而提高系统的吞吐量。发生缺页时可以调入一个段也可以调入一个页,取决于内存的存储管理方式。虚拟性表示虚拟内存和物理内存的映射。 + +Linux下,进程不能直接读写内存物理地址,只能访问【虚拟内存地址】。操作系统会把虚拟内存地址-->物理地址。 + +虚拟内存解决有限的内存空间加载较大应用程序的问题,根据需要在内存和磁盘之间来回传送数据。 + +通过段页表的形式,虚拟内存中取一段连续的内存空间映射到主内存中,主内存空间的程序段可以不连续 。 + +## 什么是分页? + +把内存空间划分为**大小相等且固定的块**,作为主存的基本单位。因为程序数据存储在不同的页面中,而页面又离散的分布在内存中,**因此需要一个页表来记录映射关系,以实现从页号到物理块号的映射。** + +访问分页系统中内存数据需要**两次的内存访问** (一次是从内存中访问页表,从中找到指定的物理块号,加上页内偏移得到实际物理地址;第二次就是根据第一次得到的物理地址访问内存取出数据)。 + +## 什么是分段? + +**分页是为了提高内存利用率,而分段是为了满足程序员在编写代码的时候的一些逻辑需求(比如数据共享,数据保护,动态链接等)。** + +分段内存管理当中,**地址是二维的,一维是段号,二维是段内地址;其中每个段的长度是不一样的,而且每个段内部都是从0开始编址的**。由于分段管理中,每个段内部是连续内存分配,但是段和段之间是离散分配的,因此也存在一个逻辑地址到物理地址的映射关系,相应的就是段表机制。 + +## 分页和分段有什区别? + +- 分页对程序员是透明的,但是分段需要程序员显式划分每个段。 +- 分页的地址空间是一维地址空间,分段是二维的。 +- 页的大小不可变,段的大小可以动态改变。 +- 分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。 + +## 页面置换算法 + +**为什么要页面置换:** + +因为应用程序是分多次装入内存的,所以运行到一定的时间,一定会发生缺页。地址映射的过程中,如果页面中发现要访问的页面不在内存中,会产生缺页中断。此时操作系统必须在内存里选择一个页面把他移出内存,为即将调入的页面让出空间。选择淘汰哪一页的规则就是页面置换算法 + +**几种页面置换算法:** + +**最佳置换算法(理想)**:将当前页面中在未来最长时间内不会被访问的页置换出去 + +**先进先出**:淘汰最早调入的页面 + +**最近最久未使用 LRU**:每个页面有一个t来记录上次页面被访问直到现在,每次置换时置换t值最大的页面(用寄存器或栈实现) + +**时钟算法clock**(也被称为最近未使用算法NRU):页面设置访问为,将页面链接为一个环形列表,每个页有一个访问位0/1, 1表示又一次获救的机会,下次循环指针指向它时可以免除此次置换,但是会把访问位置为0, 代表他下次如果碰到循环指针就该被置换了。页面被访问的时候访问位设为1。页面置换的时候,如果当前指针的访问位为0,置换,否则将这个值置为0,循环直到遇到访问位为0的页面。 + +**改进型Clock算法**:在clock算法的基础上添加一个修改位,优先替换访问位和修改位都是0的页面,其次替换访问位为0修改位为1的页面。 + +**最少使用算法LFU**:设置寄存器记录页面被访问次数,每次置换当前访问次数最少的。 + +## 用户态和内核态 + +内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序。 + +用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取。 + +最大的区别就是权限不同,在运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。 + +### 为什么要有这两种状态? + +内核速度快但是资源有限,能控制的进程数不多,所以需要速度慢一些的用户态协助,但是为了避免用户态被恶意利用,所以限制了用户态程序的权限。 + +需要限制不同的程序之间的访问能力,防止他们获取别的程序的内存数据,或者获取外围设备的数据,并发送到网络,CPU划分出**两个权限等级** -- 用户态和内核态。 + +### 什么时候转换 + +**1、系统调用**: + +用户进程主动发起的。用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如fork()就是执行一个创建新进程的系统调用 + +用户程序使用系统调用,系统调用会转换为内核态并调用操作系统 + +**2、发生异常**: + +会从当前运行进程切换到处理次此异常的内核相关程序中 + +**3、外围设备的中断:** + +所有程序都运行在用户态,但在从硬盘读取数据、或从键盘输入时,这些事情只有操作系统能做,程序需要向操作系统请求以程序的名义来执行这些操作。这个时候用户态程序切换到内核态。 + +## 什么是缓冲区溢出?有什么危害? + +缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。 + +危害有以下两点: + +- 程序崩溃,导致拒绝额服务 +- 跳转并且执行一段恶意代码 + +造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。 + +## IO多路复用 + +**IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合**: + +- 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。 +- 当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。 +- 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。 +- 如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。 +- 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。 +- 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) \ No newline at end of file diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" index 6f5ed74..92991c4 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" @@ -20,6 +20,37 @@ - 哈希表:提高查找性能 - 红黑树:大致平衡的二叉查找树,相对AVL树,插入删除结点较快,查找性能没有提升 +## 数组 + +数组的优点: + +- 存取速度快 + +数组的缺点: + +- 事先必须知道数组的长度 +- 插入删除元素很慢 +- 空间通常是有限制的 +- 需要大块连续的内存块 +- 插入删除元素的效率很低 + +## 链表 + +### 优缺点 + +优点: + +- 空间没有限制 +- 插入删除元素很快 + +缺点:存取速度很慢 + +### 分类 + +- 单向链表 一个节点指向下一个节点。 +- 双向链表 一个节点有两个指针域。 +- 循环链表 能通过任何一个节点找到其他所有的节点,将两种(双向/单向)链表的最后一个结点指向第一个结点从而实现循环 + ## AVL树 diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 48969f2..c91b807 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -344,3 +344,6 @@ ARP解决了同一个局域网上的主机和路由器IP和MAC地址的解析。 - 源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。 - 如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。 + + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) From 4dc2e1c43caabd59ef24f6df046ddc5840275ae1 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 19 Jun 2022 17:15:50 +0800 Subject: [PATCH 08/84] update --- ...21\351\235\242\350\257\225\351\242\230.md" | 47 --- ...00\351\235\242\350\257\225\351\242\230.md" | 55 --- ...21\351\235\242\350\257\225\351\242\230.md" | 54 --- ...10\351\235\242\350\257\225\351\242\230.md" | 50 --- ...07\345\215\227\346\200\273\347\273\223.md" | 75 ---- ...is\351\235\242\350\257\225\351\242\230.md" | 39 +- ...PC\347\232\204\345\216\237\347\220\206.md" | 3 +- ...03\345\274\217\344\272\213\345\212\241.md" | 2 +- ...03\345\274\217\347\274\223\345\255\230.md" | 6 +- ...06\345\270\203\345\274\217\351\224\201.md" | 2 + .../\345\276\256\346\234\215\345\212\241.md" | 7 +- .../MySQL\345\237\272\347\241\200.md" | 96 ----- ...21\351\235\242\350\257\225\351\242\230.md" | 49 --- ...is\351\235\242\350\257\225\351\242\230.md" | 2 - ...15\345\212\241\345\256\236\346\210\230.md" | 58 --- .../Spring\345\256\236\346\210\230.md" | 65 ---- ...ng\351\235\242\350\257\225\351\242\230.md" | 32 -- ...06\344\270\216\345\256\236\346\210\230.md" | 62 --- ...72\351\253\230\351\242\221\350\257\215.md" | 65 ---- ...1\253\230\351\242\221\350\257\215 - wx.md" | 66 ---- ...72\351\253\230\351\242\221\350\257\215.md" | 84 +++++ ...65\350\257\235\345\217\267\347\240\201.md" | 82 ---- ...01\347\232\204\344\270\252\346\225\260.md" | 55 +++ ...73\345\275\225\345\216\237\347\220\206.md" | 4 +- ...37\351\235\242\350\257\225\351\242\230.md" | 56 +-- ...43\347\240\201\345\256\236\347\216\260.md" | 148 -------- ...43\347\240\201\345\256\236\347\216\260.md" | 214 ----------- ...60\346\215\256\347\273\223\346\236\204.md" | 183 +++++---- .../\347\256\227\346\263\225.md" | 353 ++++++++++++++---- .../session\345\222\214cookie.md" | 10 - .../\345\233\276\350\247\243HTTP.md" | 47 --- ...21\351\235\242\350\257\225\351\242\230.md" | 38 +- 32 files changed, 565 insertions(+), 1544 deletions(-) delete mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" delete mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" create mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" delete mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" create mode 100644 "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 49892fd..d93bc43 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -1,50 +1,3 @@ - - - - -- [讲一下JVM内存结构?](#%E8%AE%B2%E4%B8%80%E4%B8%8Bjvm%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84) - - [程序计数器](#%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8) - - [虚拟机栈](#%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88) - - [本地方法栈](#%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88) - - [堆](#%E5%A0%86) - - [方法区](#%E6%96%B9%E6%B3%95%E5%8C%BA) - - [运行时常量池](#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0) - - [直接内存](#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98) -- [Java对象的定位方式](#java%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AE%9A%E4%BD%8D%E6%96%B9%E5%BC%8F) -- [说一下堆栈的区别?](#%E8%AF%B4%E4%B8%80%E4%B8%8B%E5%A0%86%E6%A0%88%E7%9A%84%E5%8C%BA%E5%88%AB) -- [什么情况下会发生栈溢出?](#%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E4%BC%9A%E5%8F%91%E7%94%9F%E6%A0%88%E6%BA%A2%E5%87%BA) -- [类文件结构](#%E7%B1%BB%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84) -- [什么是类加载?类加载的过程?](#%E4%BB%80%E4%B9%88%E6%98%AF%E7%B1%BB%E5%8A%A0%E8%BD%BD%E7%B1%BB%E5%8A%A0%E8%BD%BD%E7%9A%84%E8%BF%87%E7%A8%8B) -- [什么是双亲委派模型?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%A8%A1%E5%9E%8B) -- [为什么需要双亲委派模型?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%A8%A1%E5%9E%8B) -- [什么是类加载器,类加载器有哪些?](#%E4%BB%80%E4%B9%88%E6%98%AF%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%9C%89%E5%93%AA%E4%BA%9B) -- [类的实例化顺序?](#%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%8C%96%E9%A1%BA%E5%BA%8F) -- [如何判断一个对象是否存活?](#%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%90%A6%E5%AD%98%E6%B4%BB) -- [可作为GC Roots的对象有哪些?](#%E5%8F%AF%E4%BD%9C%E4%B8%BAgc-roots%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%9C%89%E5%93%AA%E4%BA%9B) -- [什么情况下类会被卸载?](#%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E7%B1%BB%E4%BC%9A%E8%A2%AB%E5%8D%B8%E8%BD%BD) -- [强引用、软引用、弱引用、虚引用是什么,有什么区别?](#%E5%BC%BA%E5%BC%95%E7%94%A8%E8%BD%AF%E5%BC%95%E7%94%A8%E5%BC%B1%E5%BC%95%E7%94%A8%E8%99%9A%E5%BC%95%E7%94%A8%E6%98%AF%E4%BB%80%E4%B9%88%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [GC是什么?为什么要GC?](#gc%E6%98%AF%E4%BB%80%E4%B9%88%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81gc) -- [Minor GC 和 Full GC的区别?](#minor-gc-%E5%92%8C-full-gc%E7%9A%84%E5%8C%BA%E5%88%AB) -- [内存的分配策略?](#%E5%86%85%E5%AD%98%E7%9A%84%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5) -- [Full GC 的触发条件?](#full-gc-%E7%9A%84%E8%A7%A6%E5%8F%91%E6%9D%A1%E4%BB%B6) -- [垃圾回收算法有哪些?](#%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B) -- [有哪些垃圾回收器?](#%E6%9C%89%E5%93%AA%E4%BA%9B%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8) -- [常用的 JVM 调优的命令都有哪些?](#%E5%B8%B8%E7%94%A8%E7%9A%84-jvm-%E8%B0%83%E4%BC%98%E7%9A%84%E5%91%BD%E4%BB%A4%E9%83%BD%E6%9C%89%E5%93%AA%E4%BA%9B) -- [对象头了解吗?](#%E5%AF%B9%E8%B1%A1%E5%A4%B4%E4%BA%86%E8%A7%A3%E5%90%97) -- [main方法执行过程](#main%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B) -- [对象创建过程](#%E5%AF%B9%E8%B1%A1%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B) -- [如何排查 OOM 的问题?](#%E5%A6%82%E4%BD%95%E6%8E%92%E6%9F%A5-oom-%E7%9A%84%E9%97%AE%E9%A2%98) - - - -> 首先给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - ## 讲一下JVM内存结构? JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index f477f15..e4e9624 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -1,58 +1,3 @@ - - - -- [Java的特点](#java%E7%9A%84%E7%89%B9%E7%82%B9) -- [Java 与 C++ 的区别](#java-%E4%B8%8E-c-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [面向对象和面向过程的区别?](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%92%8C%E9%9D%A2%E5%90%91%E8%BF%87%E7%A8%8B%E7%9A%84%E5%8C%BA%E5%88%AB) -- [JKD和JRE的区别?](#jkd%E5%92%8Cjre%E7%9A%84%E5%8C%BA%E5%88%AB) -- [面向对象有哪些特性?](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E6%9C%89%E5%93%AA%E4%BA%9B%E7%89%B9%E6%80%A7) -- [Java的基本数据类型有哪些?](#java%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%9C%89%E5%93%AA%E4%BA%9B) -- [什么是值传递和引用传递?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%80%BC%E4%BC%A0%E9%80%92%E5%92%8C%E5%BC%95%E7%94%A8%E4%BC%A0%E9%80%92) -- [自动装箱和拆箱](#%E8%87%AA%E5%8A%A8%E8%A3%85%E7%AE%B1%E5%92%8C%E6%8B%86%E7%AE%B1) -- [String 为什么不可变?](#string-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E5%8F%AF%E5%8F%98) -- [String, StringBuffer 和 StringBuilder区别](#string-stringbuffer-%E5%92%8C-stringbuilder%E5%8C%BA%E5%88%AB) -- [String 类的常用方法有哪些?](#string-%E7%B1%BB%E7%9A%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B) -- [new String("dabin")会创建几个对象?](#new-stringdabin%E4%BC%9A%E5%88%9B%E5%BB%BA%E5%87%A0%E4%B8%AA%E5%AF%B9%E8%B1%A1) -- [什么是字符串常量池?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E6%B1%A0) -- [object常用方法有哪些?](#object%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B) -- [讲讲深拷贝和浅拷贝?](#%E8%AE%B2%E8%AE%B2%E6%B7%B1%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%B5%85%E6%8B%B7%E8%B4%9D) -- [两个对象的hashCode()相同,则 equals()是否也一定为 true?](#%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84hashcode%E7%9B%B8%E5%90%8C%E5%88%99-equals%E6%98%AF%E5%90%A6%E4%B9%9F%E4%B8%80%E5%AE%9A%E4%B8%BA-true) -- [Java创建对象有几种方式?](#java%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E6%9C%89%E5%87%A0%E7%A7%8D%E6%96%B9%E5%BC%8F) -- [说说类实例化的顺序](#%E8%AF%B4%E8%AF%B4%E7%B1%BB%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%9A%84%E9%A1%BA%E5%BA%8F) -- [equals和==有什么区别?](#equals%E5%92%8C%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [常见的关键字有哪些?](#%E5%B8%B8%E8%A7%81%E7%9A%84%E5%85%B3%E9%94%AE%E5%AD%97%E6%9C%89%E5%93%AA%E4%BA%9B) - - [static](#static) - - [final](#final) - - [this](#this) - - [super](#super) -- [final, finally, finalize 的区别](#final-finally-finalize-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [final关键字的作用?](#final%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E4%BD%9C%E7%94%A8) -- [方法重载和重写的区别?](#%E6%96%B9%E6%B3%95%E9%87%8D%E8%BD%BD%E5%92%8C%E9%87%8D%E5%86%99%E7%9A%84%E5%8C%BA%E5%88%AB) -- [接口与抽象类区别?](#%E6%8E%A5%E5%8F%A3%E4%B8%8E%E6%8A%BD%E8%B1%A1%E7%B1%BB%E5%8C%BA%E5%88%AB) -- [常见的Exception有哪些?](#%E5%B8%B8%E8%A7%81%E7%9A%84exception%E6%9C%89%E5%93%AA%E4%BA%9B) -- [Error和Exception的区别?](#error%E5%92%8Cexception%E7%9A%84%E5%8C%BA%E5%88%AB) -- [运行时异常和非运行时异常(checked)的区别?](#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%BC%82%E5%B8%B8%E5%92%8C%E9%9D%9E%E8%BF%90%E8%A1%8C%E6%97%B6%E5%BC%82%E5%B8%B8checked%E7%9A%84%E5%8C%BA%E5%88%AB) -- [throw和throws的区别?](#throw%E5%92%8Cthrows%E7%9A%84%E5%8C%BA%E5%88%AB) -- [BIO/NIO/AIO区别的区别?](#bionioaio%E5%8C%BA%E5%88%AB%E7%9A%84%E5%8C%BA%E5%88%AB) -- [守护线程是什么?](#%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E6%98%AF%E4%BB%80%E4%B9%88) -- [Java支持多继承吗?](#java%E6%94%AF%E6%8C%81%E5%A4%9A%E7%BB%A7%E6%89%BF%E5%90%97) -- [如何实现对象克隆?](#%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%AF%B9%E8%B1%A1%E5%85%8B%E9%9A%86) -- [同步和异步的区别?](#%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5%E7%9A%84%E5%8C%BA%E5%88%AB) -- [阻塞和非阻塞的区别?](#%E9%98%BB%E5%A1%9E%E5%92%8C%E9%9D%9E%E9%98%BB%E5%A1%9E%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Java8的新特性有哪些?](#java8%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7%E6%9C%89%E5%93%AA%E4%BA%9B) -- [什么是序列化和反序列化?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96) -- [如何实现序列化](#%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%BA%8F%E5%88%97%E5%8C%96) - - - -> 首先给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - ## Java的特点 **Java是一门面向对象的编程语言。**面向对象和面向过程的区别参考下一个问题。 diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index cf0911c..e71a0dd 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -1,57 +1,3 @@ - - - - -- [线程池](#%E7%BA%BF%E7%A8%8B%E6%B1%A0) - - [为什么使用线程池?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E7%BA%BF%E7%A8%8B%E6%B1%A0) - - [线程池执行原理?](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%89%A7%E8%A1%8C%E5%8E%9F%E7%90%86) - - [线程池参数有哪些?](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8F%82%E6%95%B0%E6%9C%89%E5%93%AA%E4%BA%9B) - - [线程池大小怎么设置?](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E5%B0%8F%E6%80%8E%E4%B9%88%E8%AE%BE%E7%BD%AE) - - [线程池的类型有哪些?适用场景?](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E7%B1%BB%E5%9E%8B%E6%9C%89%E5%93%AA%E4%BA%9B%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF) -- [进程线程](#%E8%BF%9B%E7%A8%8B%E7%BA%BF%E7%A8%8B) - - [线程的生命周期](#%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) - - [讲讲线程中断?](#%E8%AE%B2%E8%AE%B2%E7%BA%BF%E7%A8%8B%E4%B8%AD%E6%96%AD) - - [创建线程有哪几种方式?](#%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B%E6%9C%89%E5%93%AA%E5%87%A0%E7%A7%8D%E6%96%B9%E5%BC%8F) - - [什么是线程死锁?](#%E4%BB%80%E4%B9%88%E6%98%AF%E7%BA%BF%E7%A8%8B%E6%AD%BB%E9%94%81) - - [线程死锁怎么产生?怎么避免?](#%E7%BA%BF%E7%A8%8B%E6%AD%BB%E9%94%81%E6%80%8E%E4%B9%88%E4%BA%A7%E7%94%9F%E6%80%8E%E4%B9%88%E9%81%BF%E5%85%8D) - - [线程run和start的区别?](#%E7%BA%BF%E7%A8%8Brun%E5%92%8Cstart%E7%9A%84%E5%8C%BA%E5%88%AB) - - [线程都有哪些方法?](#%E7%BA%BF%E7%A8%8B%E9%83%BD%E6%9C%89%E5%93%AA%E4%BA%9B%E6%96%B9%E6%B3%95) -- [volatile底层原理](#volatile%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86) -- [synchronized的用法有哪些?](#synchronized%E7%9A%84%E7%94%A8%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B) -- [synchronized的作用有哪些?](#synchronized%E7%9A%84%E4%BD%9C%E7%94%A8%E6%9C%89%E5%93%AA%E4%BA%9B) -- [synchronized 底层实现原理?](#synchronized-%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86) -- [volatile和synchronized的区别是什么?](#volatile%E5%92%8Csynchronized%E7%9A%84%E5%8C%BA%E5%88%AB%E6%98%AF%E4%BB%80%E4%B9%88) -- [ReentrantLock和synchronized区别](#reentrantlock%E5%92%8Csynchronized%E5%8C%BA%E5%88%AB) -- [wait()和sleep()的异同点?](#wait%E5%92%8Csleep%E7%9A%84%E5%BC%82%E5%90%8C%E7%82%B9) -- [Runnable和Callable有什么区别?](#runnable%E5%92%8Ccallable%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [线程执行顺序怎么控制?](#%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E6%80%8E%E4%B9%88%E6%8E%A7%E5%88%B6) -- [守护线程是什么?](#%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E6%98%AF%E4%BB%80%E4%B9%88) -- [线程间通信方式](#%E7%BA%BF%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F) -- [ThreadLocal](#threadlocal) - - [ThreadLocal原理](#threadlocal%E5%8E%9F%E7%90%86) - - [ThreadLocal内存泄漏的原因?](#threadlocal%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E7%9A%84%E5%8E%9F%E5%9B%A0) - - [ThreadLocal使用场景有哪些?](#threadlocal%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E6%9C%89%E5%93%AA%E4%BA%9B) -- [AQS原理](#aqs%E5%8E%9F%E7%90%86) -- [ReentrantLock 是如何实现可重入性的?](#reentrantlock-%E6%98%AF%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%8F%AF%E9%87%8D%E5%85%A5%E6%80%A7%E7%9A%84) -- [锁的分类](#%E9%94%81%E7%9A%84%E5%88%86%E7%B1%BB) - - [公平锁与非公平锁](#%E5%85%AC%E5%B9%B3%E9%94%81%E4%B8%8E%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81) - - [共享式与独占式锁](#%E5%85%B1%E4%BA%AB%E5%BC%8F%E4%B8%8E%E7%8B%AC%E5%8D%A0%E5%BC%8F%E9%94%81) - - [悲观锁与乐观锁](#%E6%82%B2%E8%A7%82%E9%94%81%E4%B8%8E%E4%B9%90%E8%A7%82%E9%94%81) -- [乐观锁有什么问题?](#%E4%B9%90%E8%A7%82%E9%94%81%E6%9C%89%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98) -- [什么是CAS?](#%E4%BB%80%E4%B9%88%E6%98%AFcas) -- [CAS存在的问题?](#cas%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98) -- [并发工具](#%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7) - - [CountDownLatch](#countdownlatch) - - [CyclicBarrier](#cyclicbarrier) - - [CyclicBarrier和CountDownLatch区别](#cyclicbarrier%E5%92%8Ccountdownlatch%E5%8C%BA%E5%88%AB) - - [Semaphore](#semaphore) -- [原子类](#%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [基本类型原子类](#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [数组类型原子类](#%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [引用类型原子类](#%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) - - - ## 线程池 线程池:一个管理线程的池子。 diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index f5b3209..ba6af67 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -1,53 +1,3 @@ - - - - -- [常见的集合有哪些?](#%E5%B8%B8%E8%A7%81%E7%9A%84%E9%9B%86%E5%90%88%E6%9C%89%E5%93%AA%E4%BA%9B) -- [List 、Set和Map 的区别](#list-set%E5%92%8Cmap-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [ArrayList 了解吗?](#arraylist-%E4%BA%86%E8%A7%A3%E5%90%97) -- [ArrayList 的扩容机制?](#arraylist-%E7%9A%84%E6%89%A9%E5%AE%B9%E6%9C%BA%E5%88%B6) -- [怎么在遍历 ArrayList 时移除一个元素?](#%E6%80%8E%E4%B9%88%E5%9C%A8%E9%81%8D%E5%8E%86-arraylist-%E6%97%B6%E7%A7%BB%E9%99%A4%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0) -- [Arraylist 和 Vector 的区别](#arraylist-%E5%92%8C-vector-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Arraylist 与 LinkedList 区别](#arraylist-%E4%B8%8E-linkedlist-%E5%8C%BA%E5%88%AB) -- [HashMap](#hashmap) - - [解决hash冲突的办法有哪些?HashMap用的哪种?](#%E8%A7%A3%E5%86%B3hash%E5%86%B2%E7%AA%81%E7%9A%84%E5%8A%9E%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9Bhashmap%E7%94%A8%E7%9A%84%E5%93%AA%E7%A7%8D) - - [使用的hash算法?](#%E4%BD%BF%E7%94%A8%E7%9A%84hash%E7%AE%97%E6%B3%95) - - [扩容过程?](#%E6%89%A9%E5%AE%B9%E8%BF%87%E7%A8%8B) - - [put方法流程?](#put%E6%96%B9%E6%B3%95%E6%B5%81%E7%A8%8B) - - [红黑树的特点?](#%E7%BA%A2%E9%BB%91%E6%A0%91%E7%9A%84%E7%89%B9%E7%82%B9) - - [为什么使用红黑树而不使用AVL树?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E7%BA%A2%E9%BB%91%E6%A0%91%E8%80%8C%E4%B8%8D%E4%BD%BF%E7%94%A8avl%E6%A0%91) - - [在解决 hash 冲突的时候,为什么选择先用链表,再转红黑树?](#%E5%9C%A8%E8%A7%A3%E5%86%B3-hash-%E5%86%B2%E7%AA%81%E7%9A%84%E6%97%B6%E5%80%99%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9%E5%85%88%E7%94%A8%E9%93%BE%E8%A1%A8%E5%86%8D%E8%BD%AC%E7%BA%A2%E9%BB%91%E6%A0%91) - - [HashMap 的长度为什么是 2 的幂次方?](#hashmap-%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF-2-%E7%9A%84%E5%B9%82%E6%AC%A1%E6%96%B9) - - [HashMap默认加载因子是多少?为什么是 0.75?](#hashmap%E9%BB%98%E8%AE%A4%E5%8A%A0%E8%BD%BD%E5%9B%A0%E5%AD%90%E6%98%AF%E5%A4%9A%E5%B0%91%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF-075) - - [一般用什么作为HashMap的key?](#%E4%B8%80%E8%88%AC%E7%94%A8%E4%BB%80%E4%B9%88%E4%BD%9C%E4%B8%BAhashmap%E7%9A%84key) - - [HashMap为什么线程不安全?](#hashmap%E4%B8%BA%E4%BB%80%E4%B9%88%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8) - - [HashMap和HashTable的区别?](#hashmap%E5%92%8Chashtable%E7%9A%84%E5%8C%BA%E5%88%AB) -- [LinkedHashMap底层原理?](#linkedhashmap%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86) -- [讲一下TreeMap?](#%E8%AE%B2%E4%B8%80%E4%B8%8Btreemap) -- [HashSet底层原理?](#hashset%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86) -- [HashSet、LinkedHashSet 和 TreeSet 的区别?](#hashsetlinkedhashset-%E5%92%8C-treeset-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [什么是fail fast?](#%E4%BB%80%E4%B9%88%E6%98%AFfail-fast) -- [什么是fail safe?](#%E4%BB%80%E4%B9%88%E6%98%AFfail-safe) -- [讲一下ArrayDeque?](#%E8%AE%B2%E4%B8%80%E4%B8%8Barraydeque) -- [哪些集合类是线程安全的?哪些不安全?](#%E5%93%AA%E4%BA%9B%E9%9B%86%E5%90%88%E7%B1%BB%E6%98%AF%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%93%AA%E4%BA%9B%E4%B8%8D%E5%AE%89%E5%85%A8) -- [迭代器 Iterator 是什么?](#%E8%BF%AD%E4%BB%A3%E5%99%A8-iterator-%E6%98%AF%E4%BB%80%E4%B9%88) -- [Iterator 和 ListIterator 有什么区别?](#iterator-%E5%92%8C-listiterator-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [并发容器](#%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8) - - [ConcurrentHashMap](#concurrenthashmap) - - [put执行流程?](#put%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B) - - [怎么扩容?](#%E6%80%8E%E4%B9%88%E6%89%A9%E5%AE%B9) - - [ConcurrentHashMap 和 Hashtable 的区别?](#concurrenthashmap-%E5%92%8C-hashtable-%E7%9A%84%E5%8C%BA%E5%88%AB) - - [CopyOnWrite](#copyonwrite) - - [ConcurrentLinkedQueue](#concurrentlinkedqueue) - - [阻塞队列](#%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97) - - [JDK提供的阻塞队列](#jdk%E6%8F%90%E4%BE%9B%E7%9A%84%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97) - - [原理](#%E5%8E%9F%E7%90%86) -- [参考链接](#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5) - - - - - ## 常见的集合有哪些? Java集合类主要由两个接口**Collection**和**Map**派生出来的,Collection有三个子接口:List、Set、Queue。 diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index 8d4e0d7..128b9a4 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -1,78 +1,3 @@ - - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [优缺点](#%E4%BC%98%E7%BC%BA%E7%82%B9) - - [io多路复用](#io%E5%A4%9A%E8%B7%AF%E5%A4%8D%E7%94%A8) - - [应用场景](#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF) - - [Memcached和Redis的区别](#memcached%E5%92%8Credis%E7%9A%84%E5%8C%BA%E5%88%AB) -- [数据类型](#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B) - - [字符串类型](#%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B) - - [SETNX和SETEX](#setnx%E5%92%8Csetex) - - [keys和scan](#keys%E5%92%8Cscan) - - [expire](#expire) - - [type](#type) - - [散列类型](#%E6%95%A3%E5%88%97%E7%B1%BB%E5%9E%8B) - - [列表类型](#%E5%88%97%E8%A1%A8%E7%B1%BB%E5%9E%8B) - - [集合类型](#%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B) - - [有序集合类型](#%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B) - - [Bitmaps](#bitmaps) - - [HyperLogLog](#hyperloglog) - - [数据结构](#%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) - - [动态字符串](#%E5%8A%A8%E6%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2) - - [字典](#%E5%AD%97%E5%85%B8) - - [整数集合](#%E6%95%B4%E6%95%B0%E9%9B%86%E5%90%88) - - [压缩列表](#%E5%8E%8B%E7%BC%A9%E5%88%97%E8%A1%A8) - - [跳表](#%E8%B7%B3%E8%A1%A8) - - [对象](#%E5%AF%B9%E8%B1%A1) - - [底层实现](#%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0) - - [string](#string) - - [hash](#hash) - - [list](#list) - - [set](#set) - - [zset](#zset) - - [使用场景](#%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF) - - [数据库管理](#%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86) -- [排序](#%E6%8E%92%E5%BA%8F) -- [事务](#%E4%BA%8B%E5%8A%A1) - - [WATCH命令](#watch%E5%91%BD%E4%BB%A4) -- [消息队列](#%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97) - - [优先级队列](#%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97) - - [发布/订阅模式](#%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85%E6%A8%A1%E5%BC%8F) - - [延时队列](#%E5%BB%B6%E6%97%B6%E9%98%9F%E5%88%97) -- [持久化](#%E6%8C%81%E4%B9%85%E5%8C%96) - - [RDB方式](#rdb%E6%96%B9%E5%BC%8F) - - [AOF方式](#aof%E6%96%B9%E5%BC%8F) -- [集群](#%E9%9B%86%E7%BE%A4) - - [主从复制](#%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6) - - [同步机制](#%E5%90%8C%E6%AD%A5%E6%9C%BA%E5%88%B6) - - [读写分离](#%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB) - - [从数据库持久化](#%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8C%81%E4%B9%85%E5%8C%96) - - [哨兵Sentinel](#%E5%93%A8%E5%85%B5sentinel) - - [作用](#%E4%BD%9C%E7%94%A8) - - [定时任务](#%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1) - - [工作原理](#%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86) - - [cluster](#cluster) - - [哈希分区算法](#%E5%93%88%E5%B8%8C%E5%88%86%E5%8C%BA%E7%AE%97%E6%B3%95) - - [故障转移](#%E6%95%85%E9%9A%9C%E8%BD%AC%E7%A7%BB) -- [LUA脚本](#lua%E8%84%9A%E6%9C%AC) - - [evalsha](#evalsha) - - [lua脚本作用](#lua%E8%84%9A%E6%9C%AC%E4%BD%9C%E7%94%A8) - - [应用场景](#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF-1) -- [删除策略](#%E5%88%A0%E9%99%A4%E7%AD%96%E7%95%A5) -- [其他](#%E5%85%B6%E4%BB%96) - - [客户端](#%E5%AE%A2%E6%88%B7%E7%AB%AF) - - [慢查询](#%E6%85%A2%E6%9F%A5%E8%AF%A2) - - [pipeline](#pipeline) - - [数据一致性](#%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7) - - - -目录结构如下: - -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210914000822843.png) - ## 简介 Redis是一个高性能的key-value数据库。Redis对数据的操作都是原子性的。 diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" index 03a9618..4db94a9 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" @@ -1,40 +1,3 @@ - - - - -- [Redis是什么?](#redis%E6%98%AF%E4%BB%80%E4%B9%88) -- [Redis优缺点?](#redis%E4%BC%98%E7%BC%BA%E7%82%B9) -- [Redis为什么这么快?](#redis%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%B9%88%E5%BF%AB) -- [Redis为何选择单线程](#redis%E4%B8%BA%E4%BD%95%E9%80%89%E6%8B%A9%E5%8D%95%E7%BA%BF%E7%A8%8B) -- [Redis6.0为何引入多线程?](#redis60%E4%B8%BA%E4%BD%95%E5%BC%95%E5%85%A5%E5%A4%9A%E7%BA%BF%E7%A8%8B) -- [Redis应用场景有哪些?](#redis%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E6%9C%89%E5%93%AA%E4%BA%9B) -- [Memcached和Redis的区别?](#memcached%E5%92%8Credis%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Redis 数据类型有哪些?](#redis-%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%9C%89%E5%93%AA%E4%BA%9B) -- [keys命令存在的问题?](#keys%E5%91%BD%E4%BB%A4%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98) -- [SortedSet和List异同点?](#sortedset%E5%92%8Clist%E5%BC%82%E5%90%8C%E7%82%B9) -- [Redis事务](#redis%E4%BA%8B%E5%8A%A1) -- [持久化机制](#%E6%8C%81%E4%B9%85%E5%8C%96%E6%9C%BA%E5%88%B6) - - [RDB方式](#rdb%E6%96%B9%E5%BC%8F) - - [AOF方式](#aof%E6%96%B9%E5%BC%8F) -- [RDB和AOF如何选择?](#rdb%E5%92%8Caof%E5%A6%82%E4%BD%95%E9%80%89%E6%8B%A9) -- [Redis常见的部署方式有哪些?](#redis%E5%B8%B8%E8%A7%81%E7%9A%84%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F%E6%9C%89%E5%93%AA%E4%BA%9B) -- [主从复制](#%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6) -- [哨兵Sentinel](#%E5%93%A8%E5%85%B5sentinel) -- [Redis cluster](#redis-cluster) - - [哈希分区算法有哪些?](#%E5%93%88%E5%B8%8C%E5%88%86%E5%8C%BA%E7%AE%97%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B) -- [过期键的删除策略?](#%E8%BF%87%E6%9C%9F%E9%94%AE%E7%9A%84%E5%88%A0%E9%99%A4%E7%AD%96%E7%95%A5) -- [内存淘汰策略有哪些?](#%E5%86%85%E5%AD%98%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5%E6%9C%89%E5%93%AA%E4%BA%9B) -- [如何保证缓存与数据库双写时的数据一致性?](#%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E7%BC%93%E5%AD%98%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8F%8C%E5%86%99%E6%97%B6%E7%9A%84%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7) -- [缓存穿透](#%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F) -- [缓存雪崩](#%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9) -- [缓存击穿](#%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF) -- [Redis 怎么实现消息队列?](#redis-%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97) -- [pipeline的作用?](#pipeline%E7%9A%84%E4%BD%9C%E7%94%A8) -- [LUA脚本](#lua%E8%84%9A%E6%9C%AC) -- [什么是RedLock?](#%E4%BB%80%E4%B9%88%E6%98%AFredlock) - - - ## Redis是什么? Redis(`Remote Dictionary Server`)是一个使用 C 语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis 的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。 @@ -438,6 +401,8 @@ Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到 数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由Redis自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。 +以上几个方案都不完美,需要根据业务需求,评估哪种方案影响较小,然后选择相应的方案。 + ## 缓存常见问题 ### 缓存穿透 diff --git "a/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" "b/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" index 383686b..5ecd5d1 100644 --- "a/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" +++ "b/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" @@ -44,6 +44,7 @@ ClientRemotingProcessor#processReplyMessage中主要做的从消息中获取消 六、总结 所以整体上看来,RocketMQ的Request/Reply模式,其实是利用客户端线程阻塞来换取请求异步变同步以及RocketMQ的回调机制从而间接的实现了RPC效果,但是相比直接RPC调用,数据的链路更长,性能肯定是会有损耗,但是请求会持久化,所以给了重复下发提供了可能。 -———————————————— + + 版权声明:本文为CSDN博主「林风自在」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lveex/article/details/122514893 \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" index 2f9cfa0..05ce1f0 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" @@ -54,7 +54,7 @@ TCC 的全称是:`Try`、`Confirm`、`Cancel`。 这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个 **事务回滚实际上是严重依赖于你自己写代码来回滚和补偿** 了,会造成补偿代码巨大,非常之恶心。 -![img](https://hadyang.com/interview/docs/architecture/distributed/transaction/images/distributed-transaction-TCC.png) + ## 可靠消息最终一致性方案 diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" index bd1f578..d19654d 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" @@ -2,8 +2,6 @@ 并且由于最早的单台机器的内存资源以及承载能力有限,如果大量使用本地缓存,也会使相同的数据被不同的节点存储多份,对内存资源造成较大的浪费,因此,才催生出了分布式缓存。 -![](https://hadyang.com/interview/docs/architecture/distributed/cache/images/36bb3e9d1be0ea97b3e836dc467a9c87.png) - ## 应用场景 1. **页面缓存**:用来缓存Web 页面的内容片段,包括HTML、CSS 和图片等; @@ -95,4 +93,6 @@ public String get(String key) { **3、异步更新缓存** -数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由Redis自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。 \ No newline at end of file +数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由Redis自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。 + +以上几个方案都不完美,需要根据业务需求,评估哪种方案影响较小,然后选择相应的方案。 \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" index 5645b0b..8a65dd1 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" @@ -248,6 +248,8 @@ ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它 - 从实现的复杂性角度(从低到高)Zookeeper > Redis > 数据库; - 从可靠性角度(从高到低)Zookeeper > Redis > 数据库。 + + ## 参考链接 https://mp.weixin.qq.com/s/xQknd6xsVDPBr4TbETTk2A \ No newline at end of file diff --git "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" index 99ffb31..7f52c58 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" @@ -1,4 +1,4 @@ -## 简介 +## 什么是微服务? 微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务和服务之间采用轻量级的通信机制进行协作。每个服务可以被独立的部署到生产环境。 @@ -38,7 +38,7 @@ -## 服务划分 +## 服务怎么划分? 横向拆分:按照不同的业务域进行拆分,例如订单、营销、风控、积分资源等。形成独立的业务领域微服务集群。 @@ -145,7 +145,7 @@ **服务网关基本功能**: -![服务网关](https://raw.githubusercontent.com/Tyson0314/img/master/20220508120340.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508120340.png) - 智能路由:接收**外部**一切请求,并转发到后端的对外服务。注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。 - 权限校验:网关可以做一些用户身份认证,权限认证,防止非法请求操作API 接口,对内部服务起到保护作用 @@ -191,4 +191,3 @@ Service Mesh 是微服务时代的 TCP/IP 协议。 参考:https://zhuanlan.zhihu.com/p/61901608 - diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" index 111ea22..13d9ab1 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" @@ -1,99 +1,3 @@ - - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [数据类型](#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B) - - [整型](#%E6%95%B4%E5%9E%8B) - - [浮点型](#%E6%B5%AE%E7%82%B9%E5%9E%8B) - - [定点数](#%E5%AE%9A%E7%82%B9%E6%95%B0) - - [字符串](#%E5%AD%97%E7%AC%A6%E4%B8%B2) - - [二进制数据(BLOB)](#%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0%E6%8D%AEblob) - - [日期时间类型](#%E6%97%A5%E6%9C%9F%E6%97%B6%E9%97%B4%E7%B1%BB%E5%9E%8B) -- [基本命令](#%E5%9F%BA%E6%9C%AC%E5%91%BD%E4%BB%A4) - - [启动](#%E5%90%AF%E5%8A%A8) - - [数据库操作](#%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C) - - [表](#%E8%A1%A8) - - [检索](#%E6%A3%80%E7%B4%A2) - - [排序](#%E6%8E%92%E5%BA%8F) - - [过滤](#%E8%BF%87%E6%BB%A4) - - [不匹配检查:](#%E4%B8%8D%E5%8C%B9%E9%85%8D%E6%A3%80%E6%9F%A5) - - [范围查询:](#%E8%8C%83%E5%9B%B4%E6%9F%A5%E8%AF%A2) - - [空值检查](#%E7%A9%BA%E5%80%BC%E6%A3%80%E6%9F%A5) - - [计算次序](#%E8%AE%A1%E7%AE%97%E6%AC%A1%E5%BA%8F) - - [IN 操作符](#in-%E6%93%8D%E4%BD%9C%E7%AC%A6) - - [NOT操作符](#not%E6%93%8D%E4%BD%9C%E7%AC%A6) - - [LIKE操作符](#like%E6%93%8D%E4%BD%9C%E7%AC%A6) - - [LIMIT](#limit) - - [正则表达式](#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F) -- [计算字段](#%E8%AE%A1%E7%AE%97%E5%AD%97%E6%AE%B5) - - [拼接字段](#%E6%8B%BC%E6%8E%A5%E5%AD%97%E6%AE%B5) - - [计算字段](#%E8%AE%A1%E7%AE%97%E5%AD%97%E6%AE%B5-1) -- [函数](#%E5%87%BD%E6%95%B0) - - [文本处理](#%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86) - - [日期处理函数](#%E6%97%A5%E6%9C%9F%E5%A4%84%E7%90%86%E5%87%BD%E6%95%B0) - - [数值处理函数](#%E6%95%B0%E5%80%BC%E5%A4%84%E7%90%86%E5%87%BD%E6%95%B0) -- [汇总数据](#%E6%B1%87%E6%80%BB%E6%95%B0%E6%8D%AE) - - [聚集函数](#%E8%81%9A%E9%9B%86%E5%87%BD%E6%95%B0) -- [分组](#%E5%88%86%E7%BB%84) - - [过滤分组](#%E8%BF%87%E6%BB%A4%E5%88%86%E7%BB%84) - - [having和where区别](#having%E5%92%8Cwhere%E5%8C%BA%E5%88%AB) - - [SELECT 子句顺序](#select-%E5%AD%90%E5%8F%A5%E9%A1%BA%E5%BA%8F) -- [子查询](#%E5%AD%90%E6%9F%A5%E8%AF%A2) -- [连接](#%E8%BF%9E%E6%8E%A5) - - [内连接](#%E5%86%85%E8%BF%9E%E6%8E%A5) - - [自连接](#%E8%87%AA%E8%BF%9E%E6%8E%A5) - - [自然连接](#%E8%87%AA%E7%84%B6%E8%BF%9E%E6%8E%A5) - - [内连接](#%E5%86%85%E8%BF%9E%E6%8E%A5-1) - - [外连接](#%E5%A4%96%E8%BF%9E%E6%8E%A5) - - [多表连接](#%E5%A4%9A%E8%A1%A8%E8%BF%9E%E6%8E%A5) -- [组合查询](#%E7%BB%84%E5%90%88%E6%9F%A5%E8%AF%A2) - - [UNION](#union) -- [全文搜索](#%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2) -- [表操作](#%E8%A1%A8%E6%93%8D%E4%BD%9C) - - [创建表](#%E5%88%9B%E5%BB%BA%E8%A1%A8) - - [更新表](#%E6%9B%B4%E6%96%B0%E8%A1%A8) - - [约束](#%E7%BA%A6%E6%9D%9F) - - [删除表](#%E5%88%A0%E9%99%A4%E8%A1%A8) - - [重命名表](#%E9%87%8D%E5%91%BD%E5%90%8D%E8%A1%A8) -- [列操作](#%E5%88%97%E6%93%8D%E4%BD%9C) - - [插入数据](#%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE) - - [更新数据](#%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE) - - [删除数据](#%E5%88%A0%E9%99%A4%E6%95%B0%E6%8D%AE) - - [truncate、delete与drop区别](#truncatedelete%E4%B8%8Edrop%E5%8C%BA%E5%88%AB) -- [引擎](#%E5%BC%95%E6%93%8E) -- [视图](#%E8%A7%86%E5%9B%BE) - - [应用](#%E5%BA%94%E7%94%A8) - - [限制](#%E9%99%90%E5%88%B6) - - [语法](#%E8%AF%AD%E6%B3%95) - - [简化复杂连接](#%E7%AE%80%E5%8C%96%E5%A4%8D%E6%9D%82%E8%BF%9E%E6%8E%A5) - - [更新视图](#%E6%9B%B4%E6%96%B0%E8%A7%86%E5%9B%BE) -- [存储过程](#%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B) - - [创建](#%E5%88%9B%E5%BB%BA) - - [调用](#%E8%B0%83%E7%94%A8) - - [删除](#%E5%88%A0%E9%99%A4) - - [参数](#%E5%8F%82%E6%95%B0) - - [实例](#%E5%AE%9E%E4%BE%8B) - - [检查](#%E6%A3%80%E6%9F%A5) -- [游标](#%E6%B8%B8%E6%A0%87) - - [创建游标](#%E5%88%9B%E5%BB%BA%E6%B8%B8%E6%A0%87) - - [使用游标](#%E4%BD%BF%E7%94%A8%E6%B8%B8%E6%A0%87) -- [触发器](#%E8%A7%A6%E5%8F%91%E5%99%A8) - - [创建](#%E5%88%9B%E5%BB%BA-1) - - [删除](#%E5%88%A0%E9%99%A4-1) - - [使用触发器](#%E4%BD%BF%E7%94%A8%E8%A7%A6%E5%8F%91%E5%99%A8) -- [事务处理](#%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86) - - [保留点](#%E4%BF%9D%E7%95%99%E7%82%B9) -- [权限](#%E6%9D%83%E9%99%90) - - [管理用户](#%E7%AE%A1%E7%90%86%E7%94%A8%E6%88%B7) -- [优化性能](#%E4%BC%98%E5%8C%96%E6%80%A7%E8%83%BD) -- [索引](#%E7%B4%A2%E5%BC%95) - - [创建索引](#%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95) - - [删除索引](#%E5%88%A0%E9%99%A4%E7%B4%A2%E5%BC%95) - - [查看索引](#%E6%9F%A5%E7%9C%8B%E7%B4%A2%E5%BC%95) - - - ## 简介 SQL 结构化查询语言。 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index e7bfe2d..6f12608 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -1,52 +1,3 @@ - - - - -- [事务的四大特性?](#%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%9B%9B%E5%A4%A7%E7%89%B9%E6%80%A7) -- [数据库的三大范式](#%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E4%B8%89%E5%A4%A7%E8%8C%83%E5%BC%8F) -- [事务隔离级别有哪些?](#%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E6%9C%89%E5%93%AA%E4%BA%9B) -- [索引](#%E7%B4%A2%E5%BC%95) - - [什么是索引?](#%E4%BB%80%E4%B9%88%E6%98%AF%E7%B4%A2%E5%BC%95) - - [索引的优缺点?](#%E7%B4%A2%E5%BC%95%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9) - - [索引的作用?](#%E7%B4%A2%E5%BC%95%E7%9A%84%E4%BD%9C%E7%94%A8) - - [什么情况下需要建索引?](#%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E9%9C%80%E8%A6%81%E5%BB%BA%E7%B4%A2%E5%BC%95) - - [什么情况下不建索引?](#%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8D%E5%BB%BA%E7%B4%A2%E5%BC%95) - - [索引的数据结构](#%E7%B4%A2%E5%BC%95%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) - - [Hash索引和B+树索引的区别?](#hash%E7%B4%A2%E5%BC%95%E5%92%8Cb%E6%A0%91%E7%B4%A2%E5%BC%95%E7%9A%84%E5%8C%BA%E5%88%AB) - - [为什么B+树比B树更适合实现数据库索引?](#%E4%B8%BA%E4%BB%80%E4%B9%88b%E6%A0%91%E6%AF%94b%E6%A0%91%E6%9B%B4%E9%80%82%E5%90%88%E5%AE%9E%E7%8E%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95) - - [索引有什么分类?](#%E7%B4%A2%E5%BC%95%E6%9C%89%E4%BB%80%E4%B9%88%E5%88%86%E7%B1%BB) - - [什么是最左匹配原则?](#%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%80%E5%B7%A6%E5%8C%B9%E9%85%8D%E5%8E%9F%E5%88%99) - - [什么是聚集索引?](#%E4%BB%80%E4%B9%88%E6%98%AF%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95) - - [什么是覆盖索引?](#%E4%BB%80%E4%B9%88%E6%98%AF%E8%A6%86%E7%9B%96%E7%B4%A2%E5%BC%95) - - [索引的设计原则?](#%E7%B4%A2%E5%BC%95%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99) - - [索引什么时候会失效?](#%E7%B4%A2%E5%BC%95%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E4%BC%9A%E5%A4%B1%E6%95%88) - - [什么是前缀索引?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%89%8D%E7%BC%80%E7%B4%A2%E5%BC%95) -- [常见的存储引擎有哪些?](#%E5%B8%B8%E8%A7%81%E7%9A%84%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E6%9C%89%E5%93%AA%E4%BA%9B) -- [MyISAM和InnoDB的区别?](#myisam%E5%92%8Cinnodb%E7%9A%84%E5%8C%BA%E5%88%AB) -- [MVCC 实现原理?](#mvcc-%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86) -- [快照读和当前读](#%E5%BF%AB%E7%85%A7%E8%AF%BB%E5%92%8C%E5%BD%93%E5%89%8D%E8%AF%BB) -- [共享锁和排他锁](#%E5%85%B1%E4%BA%AB%E9%94%81%E5%92%8C%E6%8E%92%E4%BB%96%E9%94%81) -- [大表怎么优化?](#%E5%A4%A7%E8%A1%A8%E6%80%8E%E4%B9%88%E4%BC%98%E5%8C%96) -- [bin log/redo log/undo log](#bin-logredo-logundo-log) -- [bin log和redo log有什么区别?](#bin-log%E5%92%8Credo-log%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [讲一下MySQL架构?](#%E8%AE%B2%E4%B8%80%E4%B8%8Bmysql%E6%9E%B6%E6%9E%84) -- [分库分表](#%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8) -- [什么是分区表?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%88%86%E5%8C%BA%E8%A1%A8) -- [分区表类型](#%E5%88%86%E5%8C%BA%E8%A1%A8%E7%B1%BB%E5%9E%8B) -- [分区的问题?](#%E5%88%86%E5%8C%BA%E7%9A%84%E9%97%AE%E9%A2%98) -- [查询语句执行流程?](#%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B) -- [更新语句执行过程?](#%E6%9B%B4%E6%96%B0%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B) -- [exist和in的区别?](#exist%E5%92%8Cin%E7%9A%84%E5%8C%BA%E5%88%AB) -- [MySQL中int(10)和char(10)的区别? ](#mysql%E4%B8%ADint10%E5%92%8Cchar10%E7%9A%84%E5%8C%BA%E5%88%AB) -- [truncate、delete与drop区别?](#truncatedelete%E4%B8%8Edrop%E5%8C%BA%E5%88%AB) -- [having和where区别?](#having%E5%92%8Cwhere%E5%8C%BA%E5%88%AB) -- [什么是MySQL主从同步?](#%E4%BB%80%E4%B9%88%E6%98%AFmysql%E4%B8%BB%E4%BB%8E%E5%90%8C%E6%AD%A5) -- [为什么要做主从同步?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%81%9A%E4%B8%BB%E4%BB%8E%E5%90%8C%E6%AD%A5) -- [乐观锁和悲观锁是什么?](#%E4%B9%90%E8%A7%82%E9%94%81%E5%92%8C%E6%82%B2%E8%A7%82%E9%94%81%E6%98%AF%E4%BB%80%E4%B9%88) -- [用过processlist吗?](#%E7%94%A8%E8%BF%87processlist%E5%90%97) - - - ## 事务的四大特性? **事务特性ACID**:**原子性**(`Atomicity`)、**一致性**(`Consistency`)、**隔离性**(`Isolation`)、**持久性**(`Durability`)。 diff --git "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" index 174db08..49f4bc0 100644 --- "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" @@ -76,8 +76,6 @@ Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集 Mybatis仅可以编写针对 `ParameterHandler`、`ResultSetHandler`、`StatementHandler`、`Executor`这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是`InvocationHandler`的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。 -编写插件:实现Mybatis的Interceptor接口并复写`intercept()`方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。 - ## .如何编写一个插件? 编写插件:实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后再给插件编写注解,指定要拦截哪一个接口的哪些方法即可,最后在配置文件中配置你编写的插件。 diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" index f1f910b..7a75bb4 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" @@ -1,61 +1,3 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [基础知识](#%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86) -- [Spring Cloud Eureka](#spring-cloud-eureka) - - [服务注册与发现](#%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0) - - [代码实例](#%E4%BB%A3%E7%A0%81%E5%AE%9E%E4%BE%8B) - - [高可用注册中心](#%E9%AB%98%E5%8F%AF%E7%94%A8%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83) -- [Spring Cloud Ribbon](#spring-cloud-ribbon) - - [RestTemplate](#resttemplate) - - [代码实例](#%E4%BB%A3%E7%A0%81%E5%AE%9E%E4%BE%8B-1) -- [Spring Cloud Hystrix](#spring-cloud-hystrix) - - [代码实例](#%E4%BB%A3%E7%A0%81%E5%AE%9E%E4%BE%8B-2) -- [Spring Cloud Feign](#spring-cloud-feign) - - [负载均衡功能](#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8A%9F%E8%83%BD) - - [服务降级功能](#%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E5%8A%9F%E8%83%BD) -- [Spring Cloud Zuul](#spring-cloud-zuul) - - [路由规则](#%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99) - - [访问前缀](#%E8%AE%BF%E9%97%AE%E5%89%8D%E7%BC%80) - - [header过滤](#header%E8%BF%87%E6%BB%A4) - - [重定向](#%E9%87%8D%E5%AE%9A%E5%90%91) - - [查看路由信息](#%E6%9F%A5%E7%9C%8B%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF) - - [过滤器](#%E8%BF%87%E6%BB%A4%E5%99%A8) - - [过滤器类型](#%E8%BF%87%E6%BB%A4%E5%99%A8%E7%B1%BB%E5%9E%8B) - - [自定义过滤器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%BF%87%E6%BB%A4%E5%99%A8) - - [禁用过滤器](#%E7%A6%81%E7%94%A8%E8%BF%87%E6%BB%A4%E5%99%A8) - - [Ribbon和Hystrix的支持](#ribbon%E5%92%8Chystrix%E7%9A%84%E6%94%AF%E6%8C%81) - - [常用配置](#%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE) -- [Spring Cloud Gateway](#spring-cloud-gateway) - - [配置路由](#%E9%85%8D%E7%BD%AE%E8%B7%AF%E7%94%B1) - - [Route Predicate](#route-predicate) - - [After Route Predicate](#after-route-predicate) - - [Cookie Route Predicate](#cookie-route-predicate) - - [Header Route Predicate](#header-route-predicate) - - [Host Route Predicate](#host-route-predicate) - - [Route Filter](#route-filter) - - [AddRequestParameter GatewayFilter](#addrequestparameter-gatewayfilter) - - [StripPrefix GatewayFilter](#stripprefix-gatewayfilter) - - [PrefixPate GatewayFilter](#prefixpate-gatewayfilter) - - [Hystrix GatewayFilter](#hystrix-gatewayfilter) - - [RequestRateLimiter GatewayFilter](#requestratelimiter-gatewayfilter) - - [Retry GatewayFilter](#retry-gatewayfilter) - - [结合注册中心使用](#%E7%BB%93%E5%90%88%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BD%BF%E7%94%A8) - - [使用动态路由](#%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1) - - [使用过滤器](#%E4%BD%BF%E7%94%A8%E8%BF%87%E6%BB%A4%E5%99%A8) -- [Spring Cloud Config](#spring-cloud-config) - - [准备配置信息](#%E5%87%86%E5%A4%87%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF) - - [配置中心](#%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83) - - [获取配置信息](#%E8%8E%B7%E5%8F%96%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF) - - [刷新配置](#%E5%88%B7%E6%96%B0%E9%85%8D%E7%BD%AE) - - [安全认证](#%E5%AE%89%E5%85%A8%E8%AE%A4%E8%AF%81) - - [配置中心集群](#%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E9%9B%86%E7%BE%A4) -- [Spring Cloud Bus](#spring-cloud-bus) -- [Spring Cloud Security](#spring-cloud-security) - - - ## 基础知识 微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行。 diff --git "a/\346\241\206\346\236\266/Spring\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/Spring\345\256\236\346\210\230.md" index b7eb212..f56fe59 100644 --- "a/\346\241\206\346\236\266/Spring\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/Spring\345\256\236\346\210\230.md" @@ -1,68 +1,3 @@ - - - - -- [Spring的核心](#spring%E7%9A%84%E6%A0%B8%E5%BF%83) -- [装配bean](#%E8%A3%85%E9%85%8Dbean) - - [自动装配bean](#%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8Dbean) - - [验证自动装配](#%E9%AA%8C%E8%AF%81%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D) - - [通过Java代码装配bean](#%E9%80%9A%E8%BF%87java%E4%BB%A3%E7%A0%81%E8%A3%85%E9%85%8Dbean) - - [通过xml装配bean](#%E9%80%9A%E8%BF%87xml%E8%A3%85%E9%85%8Dbean) - - [构造器注入](#%E6%9E%84%E9%80%A0%E5%99%A8%E6%B3%A8%E5%85%A5) - - [属性注入](#%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5) - - [混合配置](#%E6%B7%B7%E5%90%88%E9%85%8D%E7%BD%AE) - - [在JavaConfig中引用xml配置](#%E5%9C%A8javaconfig%E4%B8%AD%E5%BC%95%E7%94%A8xml%E9%85%8D%E7%BD%AE) - - [在xml配置中引用JavaConfig](#%E5%9C%A8xml%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BC%95%E7%94%A8javaconfig) -- [高级装配](#%E9%AB%98%E7%BA%A7%E8%A3%85%E9%85%8D) - - [自动装配的歧义性](#%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E7%9A%84%E6%AD%A7%E4%B9%89%E6%80%A7) - - [标识首选的bean](#%E6%A0%87%E8%AF%86%E9%A6%96%E9%80%89%E7%9A%84bean) - - [限定自动装配的bean](#%E9%99%90%E5%AE%9A%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E7%9A%84bean) - - [创建自定义的限定符](#%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E9%99%90%E5%AE%9A%E7%AC%A6) - - [bean的作用域](#bean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F) - - [运行时值注入](#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%80%BC%E6%B3%A8%E5%85%A5) - - [注入外部的值](#%E6%B3%A8%E5%85%A5%E5%A4%96%E9%83%A8%E7%9A%84%E5%80%BC) - - [使用Spring表达式语言进行装配](#%E4%BD%BF%E7%94%A8spring%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E8%A8%80%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D) -- [面向切面](#%E9%9D%A2%E5%90%91%E5%88%87%E9%9D%A2) - - [AOP术语](#aop%E6%9C%AF%E8%AF%AD) - - [Spring对aop的支持](#spring%E5%AF%B9aop%E7%9A%84%E6%94%AF%E6%8C%81) - - [通过切面选择连接点](#%E9%80%9A%E8%BF%87%E5%88%87%E9%9D%A2%E9%80%89%E6%8B%A9%E8%BF%9E%E6%8E%A5%E7%82%B9) - - [使用注解创建切面](#%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%E5%88%9B%E5%BB%BA%E5%88%87%E9%9D%A2) - - [定义切面](#%E5%AE%9A%E4%B9%89%E5%88%87%E9%9D%A2) - - [创建环绕通知](#%E5%88%9B%E5%BB%BA%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5) - - [处理通知中的参数](#%E5%A4%84%E7%90%86%E9%80%9A%E7%9F%A5%E4%B8%AD%E7%9A%84%E5%8F%82%E6%95%B0) - - [通过注解引入新功能](#%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3%E5%BC%95%E5%85%A5%E6%96%B0%E5%8A%9F%E8%83%BD) - - [在xml中声明切面](#%E5%9C%A8xml%E4%B8%AD%E5%A3%B0%E6%98%8E%E5%88%87%E9%9D%A2) - - [声明通知](#%E5%A3%B0%E6%98%8E%E9%80%9A%E7%9F%A5) - - [创建环绕通知](#%E5%88%9B%E5%BB%BA%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5-1) - - [为通知传递参数](#%E4%B8%BA%E9%80%9A%E7%9F%A5%E4%BC%A0%E9%80%92%E5%8F%82%E6%95%B0) - - [通过切面引入新的功能](#%E9%80%9A%E8%BF%87%E5%88%87%E9%9D%A2%E5%BC%95%E5%85%A5%E6%96%B0%E7%9A%84%E5%8A%9F%E8%83%BD) - - [注入AspectJ切面](#%E6%B3%A8%E5%85%A5aspectj%E5%88%87%E9%9D%A2) -- [后端中的 Spring](#%E5%90%8E%E7%AB%AF%E4%B8%AD%E7%9A%84-spring) - - [数据访问模板化](#%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E6%A8%A1%E6%9D%BF%E5%8C%96) - - [配置数据源](#%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E6%BA%90) - - [在 Spring 中集成 Hibernate](#%E5%9C%A8-spring-%E4%B8%AD%E9%9B%86%E6%88%90-hibernate) - - [Spring 与 Java 持久化 API](#spring-%E4%B8%8E-java-%E6%8C%81%E4%B9%85%E5%8C%96--api) - - [配置实体管理器工厂](#%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BD%93%E7%AE%A1%E7%90%86%E5%99%A8%E5%B7%A5%E5%8E%82) - - [编写 JPA Repository](#%E7%BC%96%E5%86%99-jpa-repository) - - [借助 Spring Data 实现自动化的 JPA Repository](#%E5%80%9F%E5%8A%A9-spring-data-%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E5%8C%96%E7%9A%84-jpa-repository) - - [Spring Data JPA 的核心接口](#spring-data-jpa-%E7%9A%84%E6%A0%B8%E5%BF%83%E6%8E%A5%E5%8F%A3) - - [定义数据访问层](#%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E5%B1%82) - - [定义查询方法](#%E5%AE%9A%E4%B9%89%E6%9F%A5%E8%AF%A2%E6%96%B9%E6%B3%95) - - [混合自定义的功能](#%E6%B7%B7%E5%90%88%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E5%8A%9F%E8%83%BD) -- [Spring Security](#spring-security) - - [基于内存的用户存储](#%E5%9F%BA%E4%BA%8E%E5%86%85%E5%AD%98%E7%9A%84%E7%94%A8%E6%88%B7%E5%AD%98%E5%82%A8) - - [基于数据库表进行认证](#%E5%9F%BA%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A1%A8%E8%BF%9B%E8%A1%8C%E8%AE%A4%E8%AF%81) - - [拦截请求](#%E6%8B%A6%E6%88%AA%E8%AF%B7%E6%B1%82) - - [使用Spring表达式进行安全保护](#%E4%BD%BF%E7%94%A8spring%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%BF%9B%E8%A1%8C%E5%AE%89%E5%85%A8%E4%BF%9D%E6%8A%A4) - - [安全通道](#%E5%AE%89%E5%85%A8%E9%80%9A%E9%81%93) - - [认证用户](#%E8%AE%A4%E8%AF%81%E7%94%A8%E6%88%B7) - - [方法级别安全](#%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%E5%AE%89%E5%85%A8) - - [@Secured](#secured) - - [@RolesAllowed](#rolesallowed) - - [使用表达式实现方法级别的安全性](#%E4%BD%BF%E7%94%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7) - - - ## Spring的核心 相对于EJB(Enterprise JaveBean),Spring提供了更加轻量级和简单的编程模型。 diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index f0f66c0..697a649 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -1,35 +1,3 @@ - - - - -- [Spring的优点](#spring%E7%9A%84%E4%BC%98%E7%82%B9) -- [Spring 用到了哪些设计模式?](#spring-%E7%94%A8%E5%88%B0%E4%BA%86%E5%93%AA%E4%BA%9B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F) -- [什么是AOP?](#%E4%BB%80%E4%B9%88%E6%98%AFaop) -- [AOP有哪些实现方式?](#aop%E6%9C%89%E5%93%AA%E4%BA%9B%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F) -- [JDK动态代理和CGLIB动态代理的区别?](#jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%92%8Ccglib%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Spring AOP相关术语](#spring-aop%E7%9B%B8%E5%85%B3%E6%9C%AF%E8%AF%AD) -- [Spring通知有哪些类型?](#spring%E9%80%9A%E7%9F%A5%E6%9C%89%E5%93%AA%E4%BA%9B%E7%B1%BB%E5%9E%8B) -- [什么是IOC?](#%E4%BB%80%E4%B9%88%E6%98%AFioc) -- [IOC的优点是什么?](#ioc%E7%9A%84%E4%BC%98%E7%82%B9%E6%98%AF%E4%BB%80%E4%B9%88) -- [什么是依赖注入?](#%E4%BB%80%E4%B9%88%E6%98%AF%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5) -- [IOC容器初始化过程?](#ioc%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B) -- [Bean的生命周期](#bean%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) -- [BeanFactory和FactoryBean的区别?](#beanfactory%E5%92%8Cfactorybean%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Bean注入容器有哪些方式?](#bean%E6%B3%A8%E5%85%A5%E5%AE%B9%E5%99%A8%E6%9C%89%E5%93%AA%E4%BA%9B%E6%96%B9%E5%BC%8F) -- [Bean的作用域](#bean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F) -- [Spring自动装配的方式有哪些?](#spring%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E7%9A%84%E6%96%B9%E5%BC%8F%E6%9C%89%E5%93%AA%E4%BA%9B) -- [@Autowired和@Resource的区别?](#autowired%E5%92%8Cresource%E7%9A%84%E5%8C%BA%E5%88%AB) -- [@Qualifier 注解有什么作用](#qualifier-%E6%B3%A8%E8%A7%A3%E6%9C%89%E4%BB%80%E4%B9%88%E4%BD%9C%E7%94%A8) -- [@Bean和@Component有什么区别?](#bean%E5%92%8Ccomponent%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB) -- [@Component、@Controller、@Repositor和@Service 的区别?](#componentcontrollerrepositor%E5%92%8Cservice-%E7%9A%84%E5%8C%BA%E5%88%AB) -- [Spring 事务实现方式有哪些?](#spring-%E4%BA%8B%E5%8A%A1%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E6%9C%89%E5%93%AA%E4%BA%9B) -- [有哪些事务传播行为?](#%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BA%8B%E5%8A%A1%E4%BC%A0%E6%92%AD%E8%A1%8C%E4%B8%BA) -- [Spring怎么解决循环依赖的问题?](#spring%E6%80%8E%E4%B9%88%E8%A7%A3%E5%86%B3%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96%E7%9A%84%E9%97%AE%E9%A2%98) -- [Spring启动过程](#spring%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B) -- [Spring 的单例 Bean 是否有线程安全问题?](#spring-%E7%9A%84%E5%8D%95%E4%BE%8B-bean-%E6%98%AF%E5%90%A6%E6%9C%89%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98) - - - ## Spring的优点 - 通过控制反转和依赖注入实现**松耦合**。 diff --git "a/\346\241\206\346\236\266/\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\346\212\200\346\234\257\345\216\237\347\220\206\344\270\216\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\346\212\200\346\234\257\345\216\237\347\220\206\344\270\216\345\256\236\346\210\230.md" index 1c51b46..bc1d6ca 100644 --- "a/\346\241\206\346\236\266/\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\346\212\200\346\234\257\345\216\237\347\220\206\344\270\216\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\346\212\200\346\234\257\345\216\237\347\220\206\344\270\216\345\256\236\346\210\230.md" @@ -1,65 +1,3 @@ - - - - -- [Mybatis简介](#mybatis%E7%AE%80%E4%BB%8B) - - [传统的JDBC编程](#%E4%BC%A0%E7%BB%9F%E7%9A%84jdbc%E7%BC%96%E7%A8%8B) - - [Hibernate与Mybatis](#hibernate%E4%B8%8Emybatis) -- [Mybatis入门](#mybatis%E5%85%A5%E9%97%A8) - - [SqlSessionFactory](#sqlsessionfactory) - - [SqlSession](#sqlsession) - - [映射器Mapper](#%E6%98%A0%E5%B0%84%E5%99%A8mapper) - - [Mybatis组件的生命周期](#mybatis%E7%BB%84%E4%BB%B6%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) -- [配置](#%E9%85%8D%E7%BD%AE) - - [properties](#properties) - - [typeAliases](#typealiases) - - [typeHandler](#typehandler) - - [自定义typeHandler](#%E8%87%AA%E5%AE%9A%E4%B9%89typehandler) - - [枚举类型typeHandler](#%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8Btypehandler) - - [自定义枚举类typeHandler](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9E%9A%E4%B8%BE%E7%B1%BBtypehandler) - - [objectFactory](#objectfactory) - - [environments](#environments) - - [数据库事务](#%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BA%8B%E5%8A%A1) -- [映射器](#%E6%98%A0%E5%B0%84%E5%99%A8) - - [select元素](#select%E5%85%83%E7%B4%A0) - - [自动映射](#%E8%87%AA%E5%8A%A8%E6%98%A0%E5%B0%84) - - [传递多个参数](#%E4%BC%A0%E9%80%92%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0) - - [使用resultMap映射结果集](#%E4%BD%BF%E7%94%A8resultmap%E6%98%A0%E5%B0%84%E7%BB%93%E6%9E%9C%E9%9B%86) - - [insert元素](#insert%E5%85%83%E7%B4%A0) - - [主键回填](#%E4%B8%BB%E9%94%AE%E5%9B%9E%E5%A1%AB) - - [自增主键](#%E8%87%AA%E5%A2%9E%E4%B8%BB%E9%94%AE) - - [非自增主键](#%E9%9D%9E%E8%87%AA%E5%A2%9E%E4%B8%BB%E9%94%AE) - - [update和delete元素](#update%E5%92%8Cdelete%E5%85%83%E7%B4%A0) - - [sql元素](#sql%E5%85%83%E7%B4%A0) - - [resultMap元素](#resultmap%E5%85%83%E7%B4%A0) - - [级联](#%E7%BA%A7%E8%81%94) - - [association一对一级联](#association%E4%B8%80%E5%AF%B9%E4%B8%80%E7%BA%A7%E8%81%94) - - [collection一对多级联](#collection%E4%B8%80%E5%AF%B9%E5%A4%9A%E7%BA%A7%E8%81%94) - - [discriminator鉴别器级联](#discriminator%E9%89%B4%E5%88%AB%E5%99%A8%E7%BA%A7%E8%81%94) - - [延迟加载](#%E5%BB%B6%E8%BF%9F%E5%8A%A0%E8%BD%BD) -- [动态SQL](#%E5%8A%A8%E6%80%81sql) - - [if元素](#if%E5%85%83%E7%B4%A0) - - [choose元素](#choose%E5%85%83%E7%B4%A0) - - [where元素](#where%E5%85%83%E7%B4%A0) - - [set元素](#set%E5%85%83%E7%B4%A0) - - [foreach元素](#foreach%E5%85%83%E7%B4%A0) - - [bind元素](#bind%E5%85%83%E7%B4%A0) -- [Mybatis-Spring应用](#mybatis-spring%E5%BA%94%E7%94%A8) -- [实用场景](#%E5%AE%9E%E7%94%A8%E5%9C%BA%E6%99%AF) - - [批量更新](#%E6%89%B9%E9%87%8F%E6%9B%B4%E6%96%B0) - - [存储过程](#%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B) - - [in和out参数](#in%E5%92%8Cout%E5%8F%82%E6%95%B0) - - [游标](#%E6%B8%B8%E6%A0%87) - - [分页](#%E5%88%86%E9%A1%B5) - - [RowBounds分页](#rowbounds%E5%88%86%E9%A1%B5) -- [预编译](#%E9%A2%84%E7%BC%96%E8%AF%91) -- [缓存](#%E7%BC%93%E5%AD%98) - - [一级缓存和二级缓存](#%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E5%92%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98) -- [原理](#%E5%8E%9F%E7%90%86) -- [优缺点](#%E4%BC%98%E7%BC%BA%E7%82%B9) - - - ## Mybatis简介 JDBC定义了连接数据库的接口规范,每个数据库厂商都会提供具体的实现,JDBC是一种典型的桥接模式。 diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" deleted file mode 100644 index c6ec6e8..0000000 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\343\200\220\344\274\230\345\214\226\347\211\210\343\200\221\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" +++ /dev/null @@ -1,65 +0,0 @@ -本期是【**大厂面试**】系列文章的第**34**期 - -回复【**手册**】获取大彬精心整理的**大厂面试手册**。 - -## 面试开始 - -旁白:通过微信聊天方式模拟现场面试,题目出自腾讯PCG一面 - -**面试官**:**上回考了你一道场景题,还记得不?** - -**面试官**:**题目是这样的,一个1G大小的文件,文件里每一行是一个词,每个词的大小不超过16byte,要求返回出现频率最高的100个词** - -**面试官**:**内存大小限制是10M** - -**面试官**:**当时你给的解法有问题啊,还好我回去查了下,不然就给蒙混过关了。。** - -**面试官**:**你用的是分治的思想,进行哈希取余,放进小文件。** - -**面试官**:**但是在极端情况,比如都是同一个词或者某一个词超过10m,小文件会超过10m内存限制啊** - -大彬:是的哦,上次的解法不严谨,今天给你介绍另一种解法: - -**第一步**,对大文件的单词进行排序,排序之后,相同的单词会紧挨着 - -排序的步骤如下: - -1.1 将文件按照顺序切分成大小不超过2m的小文件,总共500个小文件 - -1.2 使用10m内存**分别**对500个小文件中的单词进行**排序** - -1.3 使用一个大小为500大小的堆,对500个小文件进行**多路排序**,结果写到一个大文件中 - -其中1.3步骤中,对500个小文件进行多路排序的思路如下: - -- 初始化一个最小堆,大小就是小文件的个数500。堆中的每个节点存放每个有序小文件对应的输入流。 -- 按照每个有序文件中的下一行数据对所有文件输入流进行排序,单词小的输入文件流放在堆顶。 -- 拿出堆顶的输入流,并其下一行数据写入到最终排序的文件中,如果拿出来的输入流中还有数据的话,那么将这个输入流再一次添加到堆中。否则说明该文件输入流中没有数据了,那么可以关闭这个流。 -- 循环这个过程,直到所有文件输入流都没有数据为止。 - -**第二步**: - -2.1 初始化一个100个节点的**小顶堆**,用于保存100个出现频率最多的单词 - -2.2 遍历整个文件,一个单词一个单词的从文件中取出来,并计数 - -2.3 等到遍历的单词和上一个单词不同的话,那么上一个单词及其频率如果大于堆顶的词的频率,那么放在堆中,否则不放 - -最终,小顶堆中就是出现频率前100的单词了。 - -可以看出,这种解法相对之前的解法,更为严谨,就算整个文件都是同一个词,此解法同样有效。 - -**面试官**:行吧,今天面试就到这里吧 - - - -## 点关注,不迷路 - -大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 - -希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ - -后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 - -![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) - diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" deleted file mode 100644 index 02d5b41..0000000 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215 - wx.md" +++ /dev/null @@ -1,66 +0,0 @@ -本期是【**大厂面试**】系列文章的第**26**期 - -回复【**手册**】获取大彬精心整理的**大厂面试手册**。 - -## 面试开始 - -旁白:通过微信聊天方式模拟现场面试,题目出自腾讯PCG一面 - -**面试官**:**今天来道场景题** - -**面试官**:假如有一个1G大小的文件,文件里每一行是一个词,每个词的大小不超过16byte,要求返回出现频率最高的100个词 - -**面试官**:内存大小限制是10M - -旁白:由于内存限制,我们无法直接将大文件的所有词一次性读到内存中 - -旁白:可以采用**分治策略**,把一个大文件分解成多个小文件,保证每个文件的大小小于10M,进而直接将单个小文件读取到内存中进行处理 - -**大彬**:第一步,首先遍历大文件,对遍历到的每个词x,执行 `hash(x) % 500`,将结果为i的词存放到文件f(i)中 - -**大彬**:遍历结束后,可以得到500个小文件 - -**大彬**:之所以使用500个小文件,是因为原文件大小为1G,1G/500=2M,每个小文件的大小为2M左右,基本不会超过内存大小10M的限制 - -**大彬**:第二步,接着统计每个小文件中出现频数最高的100个词 - -**大彬**:可以使用HashMap来实现,其中key为词,value为该词出现的频率 - -**大彬**:对于遍历到的词x,如果在map中不存在,则执行 `map.put(x, 1)` - -**大彬**:若存在,则执行 `map.put(x, map.get(x)+1)`,将该词出现的次数加1 - -**大彬**:第三步,在第二步中找出了每个文件出现频率最高的100个词之后,通过维护一个小顶堆来找出所有小文件中出现频率最高的100个词 - -**大彬**:具体方法是,遍历第一个文件,把第一个文件中出现频率最高的100个词构建成一个小顶堆 - -**大彬**:如果第一个文件中词的个数小于100,可以继续遍历第二个文件,直到构建好有100个结点的小顶堆为止 - -**大彬**:继续遍历其他小文件,如果遍历到的词的出现次数大于堆顶上词的出现次数,可以用新遍历到的词替换堆顶的词,然后重新调整这个堆为小顶堆 - -**大彬**:当遍历完所有小文件后,这个小顶堆中的词就是出现频率最高的100个词 - -**大彬**:最后总结一下 - -1. 采用**分治**的思想,进行哈希取余 -2. 使用**HashMap**统计每个小文件单词出现的次数 -3. 使用**小顶堆**,遍历步骤2中的小文件,找出出现频率Top100的单词 - -面试官:在第二步中,将1G的文件分解到500个小文件,小文件的大小可能超过10M吧?怎么处理? - -大彬:如果某个小文件的大小超过10MB了,可以采用相同的方法对这个文件继续分解成g(1)...g(x),直到文件的大小小于10MB为止 - -**面试官**:good!今天面试就到这吧 - - - -## 点关注,不迷路 - -大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 - -希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ - -后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 - -![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) - diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" new file mode 100644 index 0000000..885806d --- /dev/null +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" @@ -0,0 +1,84 @@ +大家好,我是大彬~ + +今天分享一道面试常考的海量数据场景题。 + +## 题目描述 + +假如有一个**1G**大小的文件,文件里每一行是一个词,每个词的大小不超过**16byte**,要求返回出现频率最高的100个词。内存大小限制是**10M** + +## 解法1 + +由于内存限制,我们无法直接将大文件的所有词一次性读到内存中。 + +可以采用**分治策略**,把一个大文件分解成多个小文件,保证每个文件的大小小于10M,进而直接将单个小文件读取到内存中进行处理。 + +**第一步**,首先遍历大文件,对遍历到的每个词x,执行 `hash(x) % 500`,将结果为i的词存放到文件f(i)中,遍历结束后,可以得到500个小文件,每个小文件的大小为2M左右; + +**第二步**,接着统计每个小文件中出现频数最高的100个词。可以使用HashMap来实现,其中key为词,value为该词出现的频率。 + +对于遍历到的词x,如果在map中不存在,则执行 `map.put(x, 1)。` + +若存在,则执行 `map.put(x, map.get(x)+1)`,将该词出现的次数加1。 + +**第三步**,在第二步中找出了每个文件出现频率最高的100个词之后,通过维护一个**小顶堆**来找出所有小文件中出现频率最高的100个词。 + +具体方法是,遍历第一个文件,把第一个文件中出现频率最高的100个词构建成一个小顶堆。 + +如果第一个文件中词的个数小于100,可以继续遍历第二个文件,直到构建好有100个结点的小顶堆为止。 + +继续遍历其他小文件,如果遍历到的词的出现次数大于堆顶上词的出现次数,可以用新遍历到的词替换堆顶的词,然后重新调整这个堆为小顶堆。 + +当遍历完所有小文件后,这个小顶堆中的词就是出现频率最高的100个词。 + +总结一下,这种解法的主要思路如下: + +1. 采用**分治**的思想,进行哈希取余 +2. 使用**HashMap**统计每个小文件单词出现的次数 +3. 使用**小顶堆**,遍历步骤2中的小文件,找出词频top100的单词 + +但是很容易可以发现问题,在第二步中,如果这个1G的大文件中有某个词词频过高,可能导致小文件大小超过10m。这种情况下该怎么处理呢? + +接下来看另外一种解法。 + +## 解法2 + +**第一步**:使用多路归并排序对大文件进行排序,这样相同的单词肯定是紧挨着的 + +多路归并排序对大文件进行排序的步骤如下: + +① 将文件按照顺序切分成大小不超过2m的小文件,总共500个小文件 + +② 使用10MB内存**分别**对 500 个小文件中的单词进行**排序** + +③ 使用一个大小为500大小的堆,对500个小文件进行**多路排序**,结果写到一个大文件中 + +其中第三步,对500个小文件进行多路排序的思路如下: + +- 初始化一个最小堆,大小就是有序小文件的个数500。堆中的每个节点存放每个有序小文件对应的输入流。 +- 按照每个有序文件中的下一行数据对所有文件输入流进行排序,单词小的输入文件流放在堆顶。 +- 拿出堆顶的输入流,并其下一行数据写入到最终排序的文件中,如果拿出来的输入流中还有数据的话,那么将这个输入流再一次添加到栈中。否则说明该文件输入流中没有数据了,那么可以关闭这个流。 +- 循环这个过程,直到所有文件输入流都没有数据为止。 + +**第二步**: + +① 初始化一个100个节点的**小顶堆**,用于保存100个出现频率最多的单词 + +② 遍历整个文件,一个单词一个单词的从文件中取出来,并计数 + +③ 等到遍历的单词和上一个单词不同的话,那么上一个单词及其频率如果大于堆顶的词的频率,那么放在堆中,否则不放 + +最终,小顶堆中就是出现频率前100的单词了。 + +解法2相对解法1,更加严谨,如果某个词词频过高或者整个文件都是同一个词的话,解法1不适用。 + + +## 点关注,不迷路 + +大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 + +希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ + +后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) + diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" deleted file mode 100644 index 7a452aa..0000000 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\224\265\350\257\235\345\217\267\347\240\201.md" +++ /dev/null @@ -1,82 +0,0 @@ -本期是【**大厂面试**】系列文章的第**35**期 - -回复【**手册**】获取大彬精心整理的**大厂面试手册**。 - -## 面试开始 - -旁白:通过微信聊天方式模拟现场面试,题目出自百度一面 - -**面试官**:**已知某个文件内包含大量电话号码,每个号码为8位数字,如何统计不同号码的个数?** - -旁白:这类题目其实是求解数据重复的问题 - -大彬:对于这类问题,可以使用**位图法**处理 - -大彬:8位电话号码可以表示的范围为00000000~99999999。 - -大彬:如果用 bit表示一个号码,那么总共需要1亿个bit,总共需要大约100MB的内存。 - -大彬:申请一个位图并初始化为0,然后遍历所有电话号码,把遍历到的电话号码对应的位图中的bit设置为1。 - -大彬:当遍历完成后,如果bit值为1,则表示这个电话号码在文件中存在,否则这个bit对应的电话号码在文件中不存在。 - -大彬:所以这个位图中bit值为1的数量就是不同电话号码的个数了。 - -面试官:那么如何确定电话号码对应的是位图中的哪一位呢? - -大彬:嗯,可以使用下面的方法来做电话号码和位图的映射。 - -```java -00000000 对应位图最后一位:0×0000…000001。 -00000001 对应位图倒数第二位:0×0000…0000010(1 向左移 1 位)。 -00000002 对应位图倒数第三位:0×0000…0000100(1 向左移 2 位)。 -…… -00000012 对应位图的倒数第十三位:0×0000…0001 0000 0000 0000(1 向左移 12 位)。 -``` - -大彬:也就是说,电话号码就是1这个数字左移的次数。 - -**面试官:那用代码怎么实现呢?** - -大彬:首先位图可以使用一个int数组来实现。 - -旁白:在Java中int占用**4byte** - -大彬:假设电话号码为 P,而通过电话号码获取位图中对应位置的方法为: - -大彬:第一步,因为int整数占用4*8=32bit,通过 **P/32** 就可以计算出该电话号码在 bitmap 数组中的下标,从而可以确定它对应的 bit 在数组中的位置。 - -大彬:第二步,通过 P%32 就可以计算出这个电话号码在这个int数字中具体的bit的位置。 - -大彬:只要把1向左移 **P%32** 位,然后把得到的值与这个数组中的值做或运算,就可以把这个电话号码在位图中对应的位设置为1。 - -大彬:以00000100号码为例 - -大彬:首先计算数组下标,100 / 32 = 3,得到数组下标位3 - -大彬:然后计算电话号码在这个int数字中具体的bit的位置,100 % 32 = 4 - -大彬:取余为0左移1位,故取余为4左移5位,得到000...000100000 - -大彬:将位图中对应的位设置为 1,即arr[2] = arr[2] **|** 000..00100000 - -大彬:这就将电话号码映射到了位图的某一位了。 - -![原理1-1](https://gitee.com/tysondai/img/raw/master/20220423094735.png) - -**面试官**:点赞 - -**面试官**:今天面试就到这里吧 - - - -## 点关注,不迷路 - -大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 - -希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ - -后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 - -![](https://gitee.com/tysondai/img/raw/master/公众号.jpg) - diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" new file mode 100644 index 0000000..5b480ae --- /dev/null +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" @@ -0,0 +1,55 @@ +大家好,我是大彬~ + +海量数据题目是面试经常会考的题型,今天给大家分享一道百度二面的题目。 + +## 题目描述 + +**已知某个文件内包含大量电话号码,每个号码为8位数字,如何统计不同号码的个数?** + +## 思路分析 + +这类题目其实是求解数据重复的问题。对于这类问题,可以使用**位图法**处理 + +8位电话号码可以表示的范围为00000000~99999999。如果用 bit表示一个号码,那么总共需要1亿个bit,总共需要大约**10MB**的内存。 + +申请一个位图并初始化为0,然后遍历所有电话号码,**把遍历到的电话号码对应的位图中的bit设置为1**。当遍历完成后,如果bit值为1,则表示这个电话号码在文件中存在,否则这个bit对应的电话号码在文件中不存在。 + +最后这个**位图中bit值为1的数量**就是不同电话号码的个数了。 + +那么如何确定电话号码对应的是位图中的哪一位呢? + +可以使用下面的方法来做**电话号码和位图的映射**。 + +```java +00000000 对应位图最后一位:0×0000…000001。 +00000001 对应位图倒数第二位:0×0000…0000010(1 向左移 1 位)。 +00000002 对应位图倒数第三位:0×0000…0000100(1 向左移 2 位)。 +…… +00000012 对应位图的倒数第十三位:0×0000…0001 0000 0000 0000(1 向左移 12 位)。 +``` + +也就是说,电话号码就是1这个数字左移的次数。 + +## 具体实现 + +首先位图可以使用一个**int数组**来实现(在Java中int占用**4byte**)。 + +假设电话号码为 P,而通过电话号码获取位图中对应位置的方法为: + +**第一步**,因为int整数占用4*8=32bit,通过 **P/32** 就可以计算出该电话号码在 bitmap 数组中的下标,从而可以确定它对应的 bit 在数组中的位置。 + +**第二步**,通过 **P%32** 就可以计算出这个电话号码在这个int数字中具体的bit的位置。只要把1向左移 **P%32** 位,然后把得到的值与这个数组中的值做或运算,就可以把这个电话号码在位图中对应的位设置为1。 + +以00000100号码为例。 + +1. 首先计算数组下标,100 / 32 = 3,得到数组下标位3。 +2. 然后计算电话号码在这个int数字中具体的bit的位置,100 % 32 = 4。取余为0左移1位,故取余为4左移5位,得到000...000010000 +3. 将位图中对应的位设置为 1,即arr[2] = arr[2] **|** 000..00010000。 +4. 这就将电话号码映射到了位图的某一位了。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423094735.png) + +最后,统计位图中bit值为1的数量,便能得到不同电话号码的个数了。 + + + diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" index 01224d9..93f6591 100644 --- "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" @@ -54,7 +54,7 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P 大彬:这个阶段是交互过程如下图所示。 -![](https://gitee.com/tysondai/img/raw/master/20220411002823.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220411002823.png) **3、已确认** @@ -66,7 +66,7 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P 这个阶段是交互过程如下图所示。 -![](https://gitee.com/tysondai/img/raw/master/20220411002832.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220411002832.png) 大彬:以上就是整个扫码登录功能的详细设计! diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" index 5438b9a..c8e073c 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" @@ -1,14 +1,3 @@ -## 操作系统里的内存碎片怎么理解? - -内存碎片通常分为内部碎片和外部碎片: - -1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就会产生内部碎片。通常内部碎片难以完全避免 -2. 外部碎片是由于某些未分配的连续内存区域太小,以至于不能满足任意进程的内存分配请求,从而不能被进程利用的内存区域。 - -## 有什么解决办法? - -现在普遍采取的内存分配方式是段页式内存分配。将内存分为不同的段,再将每一段分成固定大小的页。通过页表机制,使段内的页可以不必连续处于同一内存区域。 - ## 操作系统的四个特性? 并发:同一段时间内多个程序执行(与并行区分,并行指的是同一时刻有多个事件,多处理器系统可以使程序并行执行) @@ -74,13 +63,13 @@ 4、**信号量**。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 -## 死锁 +## 什么是死锁? 死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) +![](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -134,6 +123,25 @@ Thread[线程 2,5,main]waiting get resource1 线程 A 通过 `synchronized` (resource1) 获得 resource1 的监视器锁,然后通过 `Thread.sleep(1000)`。让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。 +## 死锁怎么产生?怎么避免? + +**死锁产生的四个必要条件**: + +- 互斥:一个资源每次只能被一个进程使用 + +- 请求与保持:一个进程因请求资源而阻塞时,不释放获得的资源 + +- 不剥夺:进程已获得的资源,在未使用之前,不能强行剥夺 + +- 循环等待:进程之间循环等待着资源 + +**避免死锁的方法**: + +- 互斥条件不能破坏,因为加锁就是为了保证互斥 +- 一次性申请所有的资源,避免线程占有资源而且在等待其他资源 +- 占有部分资源的线程进一步申请其他资源时,如果申请不到,主动释放它占有的资源 +- 按序申请资源 + ## 进程调度策略有哪几种? - **先来先服务**:非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。另外,对`I/O`密集型进程也不利,因为这种进程每次进行`I/O`操作之后又得重新排队。 @@ -163,24 +171,16 @@ Thread[线程 2,5,main]waiting get resource1 **运行态→就绪态**:不是由于自身原因,而是由外界原因使运行状态的进程让出处理器,这时候就变成就绪态。例如时间片用完,或有更高优先级的进程来抢占处理器等。 **就绪态→运行态**:系统按某种策略选中就绪队列中的一个进程占用处理器,此时就变成了运行态。 -## 死锁怎么产生?怎么避免? - -**死锁产生的四个必要条件**: - -- 互斥:一个资源每次只能被一个进程使用 - -- 请求与保持:一个进程因请求资源而阻塞时,不释放获得的资源 +## 操作系统里的内存碎片怎么理解? -- 不剥夺:进程已获得的资源,在未使用之前,不能强行剥夺 +内存碎片通常分为内部碎片和外部碎片: -- 循环等待:进程之间循环等待着资源 +1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就会产生内部碎片。通常内部碎片难以完全避免 +2. 外部碎片是由于某些未分配的连续内存区域太小,以至于不能满足任意进程的内存分配请求,从而不能被进程利用的内存区域。 -**避免死锁的方法**: +**有什么解决办法**? -- 互斥条件不能破坏,因为加锁就是为了保证互斥 -- 一次性申请所有的资源,避免线程占有资源而且在等待其他资源 -- 占有部分资源的线程进一步申请其他资源时,如果申请不到,主动释放它占有的资源 -- 按序申请资源 +现在普遍采取的内存分配方式是段页式内存分配。将内存分为不同的段,再将每一段分成固定大小的页。通过页表机制,使段内的页可以不必连续处于同一内存区域。 ## 虚拟内存 @@ -283,4 +283,6 @@ Linux下,进程不能直接读写内存物理地址,只能访问【虚拟内 - 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。 - 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。 + + ![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) \ No newline at end of file diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" deleted file mode 100644 index c0ff353..0000000 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\345\211\215\345\272\217\343\200\201\344\270\255\345\272\217\343\200\201\345\220\216\345\272\217\343\200\201\345\261\202\345\272\217\351\201\215\345\216\206\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ /dev/null @@ -1,148 +0,0 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [前序遍历](#%E5%89%8D%E5%BA%8F%E9%81%8D%E5%8E%86) -- [中序遍历](#%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86) -- [后序遍历](#%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86) -- [层序遍历](#%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86) - - - -二叉树的先序、中序和后序属于深度优先遍历DFS,层次遍历属于广度优先遍历BFS。 - -![image-20200704000607410](E:\project\java\learn\Java-learning\img\tree-visit.png) - -# 前序遍历 - -```java -class Solution { - //方法1 - public List preorderTraversal1(TreeNode root) { - List result = new ArrayList<>(); - LinkedList ll = new LinkedList<>(); //类型声明List改为LinkedList,List没有addFirst()/removeFirst()方法 - - while (root != null || !ll.isEmpty()) { - while (root != null) { - result.add(root.val); - ll.addFirst(root); - root = root.left; - } - root = ll.removeFirst(); - root = root.right; - } - - return result; - } - //方法2 - public List preorderTraversal2(TreeNode root) { - List result = new ArrayList<>(); - if(root == null) { - return result; - } - - Stack s = new Stack<>(); - s.push(root); - while(!s.isEmpty()) { - TreeNode node = s.pop(); - result.add(node.val); - if(node.right != null) { - s.push(node.right);//先压右,再压左 - } - if(node.left != null) { - s.push(node.left); - } - } - - return result; - } -} -``` - -# 中序遍历 - -```java - public List inorderTraversal(TreeNode root) { - List res = new ArrayList<>(); - Deque deque = new ArrayDeque<>(); - - while (!deque.isEmpty() || root != null) { - while (root != null) { - deque.push(root); - root = root.left; - } - root = deque.pop(); - res.add(root.val); - root = root.right; - } - - return res; - } -``` - -# 后序遍历 - -使用 null 作为标志位,访问到 null 说明此次递归调用结束。 - -```java -class Solution { - public List postorderTraversal(TreeNode root) { - List res = new LinkedList<>(); - if (root == null) { - return res; - } - - Stack stack = new Stack<>(); - stack.push(root); - while (!stack.isEmpty()) { - root = stack.pop(); - if (root != null) { - stack.push(root);//最后访问 - stack.push(null); - if (root.right != null) { - stack.push(root.right); - } - if (root.left != null) { - stack.push(root.left); - } - } else { //值为null说明此次递归调用结束,将节点值存进结果 - res.add(stack.pop().val); - } - } - - return res; - } -} -``` - -# 层序遍历 - -``` -class Solution { - public List> levelOrder(TreeNode root) { - List> res = new ArrayList<>(); - LinkedList queue = new LinkedList<>(); - if (root == null) { - return res; - } - queue.addLast(root); - while (!queue.isEmpty()) { - List levelList = new LinkedList<>(); - int size = queue.size(); - while (size-- > 0) { - root = queue.removeFirst(); - levelList.add(root.val); - if (root.left != null) { - queue.addLast(root.left); - } - if (root.right != null) { - queue.addLast(root.right); - } - } - res.add(levelList); - } - return res; - } -} -``` - diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" deleted file mode 100644 index 9ad4fb0..0000000 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\345\270\270\350\247\201\347\232\204\346\216\222\345\272\217\347\256\227\346\263\225Java\344\273\243\347\240\201\345\256\236\347\216\260.md" +++ /dev/null @@ -1,214 +0,0 @@ - - - -- [冒泡排序](#%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F) -- [插入排序](#%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F) -- [选择排序](#%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F) -- [基数排序](#%E5%9F%BA%E6%95%B0%E6%8E%92%E5%BA%8F) -- [快速排序](#%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F) -- [归并排序](#%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F) -- [堆排序](#%E5%A0%86%E6%8E%92%E5%BA%8F) - - - -常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 - -![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) - -## 冒泡排序 - -```java - public void bubbleSort(int[] arr) { - if (arr == null) { - return; - } - boolean flag; - for (int i = arr.length - 1; i > 0; i--) { - flag = false; - for (int j = 0; j < i; j++) { - if (arr[j] > arr[j + 1]) { - int tmp = arr[j]; - arr[j] = arr[j + 1]; - arr[j + 1] = tmp; - flag = true; - } - } - if (!flag) { - return; - } - } - } -``` - -## 插入排序 - -```java - public void insertSort(int[] arr) { - if (arr == null) { - return; - } - for (int i = 1; i < arr.length; i++) { - int tmp = arr[i]; - int j = i; - for (; j > 0 && tmp < arr[j - 1]; j--) { - arr[j] = arr[j - 1]; - } - arr[j] = tmp; - } - } -``` - -## 选择排序 - -```java - public void selectionSort(int[] arr) { - if (arr == null) { - return; - } - for (int i = 0; i < arr.length - 1; i++) { - for (int j = i + 1; j < arr.length; j++) { - if (arr[i] > arr[j]) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - } - } - } -``` - -## 基数排序 - -在基数排序中,因为没有比较操作,所以在时间复杂上,最好的情况与最坏的情况在时间上是一致的,均为 O(d * (n + r))。d 为位数,r 为基数,n 为原数组个数。 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMzExMDYyOTY4Ni00MDU0Mjk5NjkucG5n?x-oss-process=image/format,png) - -## 快速排序 - -```java - public void quickSort(int[] arr) { - if (arr == null) { - return; - } - quickSortHelper(arr, 0, arr.length - 1); - } - private void quickSortHelper(int[] arr, int left, int right) { - if (left > right) { - return; - } - int tmp = arr[left]; - int i = left; - int j = right; - while (i < j) { - //j先走,最终循环终止时,j停留的位置就是arr[left]的正确位置 - //改为i<=j,则会进入死循环,[1,5,5,5,5]->[1] 5 [5,5,5]->[5,5,5],会死循环 - while (i < j && arr[j] >= tmp) { - j--; - } - while (i < j && arr[i] <= tmp) { - i++; - } - if (i < j) { - int tmp1 = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp1; - } else { - break; - } - } - - //当循环终止的时候,i=j,因为是j先走的,j所在位置的值小于arr[left],交换arr[j]和arr[left] - arr[left] = arr[j]; - arr[j] = tmp; - - quickSortHelper(arr, left, j - 1); - quickSortHelper(arr, j + 1, right); - } -``` - -## 归并排序 - -![归并排序图](https://images2015.cnblogs.com/blog/1024555/201612/1024555-20161218163120151-452283750.png) - -```java -public class MergeSort { - public void mergeSort(int[] arr) { - if (arr == null || arr.length == 0) { - return; - } - //辅助数组 - int[] tmpArr = new int[arr.length]; - mergeSort(arr, tmpArr, 0, arr.length - 1); - } - - private void mergeSort(int[] arr, int[] tmpArr, int left, int right) { - if (left < right) { - int mid = (left + right) >> 1; - mergeSort(arr, tmpArr, left, mid); - mergeSort(arr, tmpArr, mid + 1, right); - merge(arr, tmpArr, left, mid, right); - } - } - - private void merge(int[] arr, int[] tmpArr, int left, int mid, int right) { - int i = left; - int j = mid + 1; - int tmpIndex = left; - while (i <= mid && j <= right) { - if (arr[i] < arr[j]) { - tmpArr[tmpIndex++] = arr[i]; - i++; - } else { - tmpArr[tmpIndex++] = arr[j]; - j++; - } - } - - while (i <= mid) { - tmpArr[tmpIndex++] = arr[i++]; - } - - while (j <= right) { - tmpArr[tmpIndex++] = arr[j++]; - } - - for (int m = left; m <= right; m++) { - arr[m] = tmpArr[m]; - } - } -} -``` - -## 堆排序 - -堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 - -![](https://img-blog.csdn.net/20150312212515074) - -**Top大问题**解决思路:使用一个固定大小的**最小堆**,当堆满后,每次添加数据的时候与堆顶元素比较,若小于堆顶元素,则舍弃,若大于堆顶元素,则删除堆顶元素,添加新增元素,对堆进行重新排序。 - -对于n个数,取Top m个数,时间复杂度为O(nlogm),这样在n较大情况下,是优于nlogn(其他排序算法)的时间复杂度的。 - -PriorityQueue 是一种基于优先级堆的优先级队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头。优先级队列用数组实现,但是数组大小可以动态增加,容量无限。 - -```java -//找出前k个最大数,采用小顶堆实现 -public static int[] findKMax(int[] nums, int k) { - PriorityQueue pq = new PriorityQueue<>(k);//队列默认自然顺序排列,小顶堆,不必重写compare - - for (int num : nums) { - if (pq.size() < k) { - pq.offer(num); - } else if (pq.peek() < num) {//如果堆顶元素 < 新数,则删除堆顶,加入新数入堆 - pq.poll(); - pq.offer(num); - } - } - - int[] result = new int[k]; - for (int i = 0; i < k&&!pq.isEmpty(); i++) { - result[i] = pq.poll(); - } - return result; -} -``` - diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" index 92991c4..9bb6945 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" @@ -1,16 +1,3 @@ - - - - -- [各种数据结构应用场景](#%E5%90%84%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF) -- [AVL树](#avl%E6%A0%91) -- [B树](#b%E6%A0%91) -- [红黑树](#%E7%BA%A2%E9%BB%91%E6%A0%91) -- [图](#%E5%9B%BE) -- [二分查找](#%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE) - - - ## 各种数据结构应用场景 - 栈:逆序输出;语法检查,符号成对判断;方法调用 @@ -36,8 +23,6 @@ ## 链表 -### 优缺点 - 优点: - 空间没有限制 @@ -45,15 +30,52 @@ 缺点:存取速度很慢 -### 分类 +**分类** - 单向链表 一个节点指向下一个节点。 - 双向链表 一个节点有两个指针域。 - 循环链表 能通过任何一个节点找到其他所有的节点,将两种(双向/单向)链表的最后一个结点指向第一个结点从而实现循环 +## 哈希表 + +散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 + +## 栈 + +我们把类似于弹夹那种先进后出的数据结构称为栈,栈是限定**仅在表尾进行插入和删除操作**的线性表,我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈,栈又称后进后出的线性表,简称LIFO结构。 + +栈的特殊之处在于限制了这个线性表的**插入和删除位置,它始终只在栈顶进行**。这也就使得:栈底是固定的,最先进栈的只能在栈底。 + +栈的插入操作,叫做进栈;栈的删除操作叫做出栈。 + +## 队列 + +队列是只允许**在一端进行插入操作,而在另一端进行删除操作**的线性表,队列是一种先进先出的线性表,简称FIFO,允许插入的一端称为队尾(Rear),允许删除的一端称为队头(Front)。向队中插入元素称为进队,新元素进队后成为新的队尾元素;向队中删除元素称为出队,元素出队后,其后继元素就成为新的队头元素。 +## 树 - ## AVL树 +树是一种数据结构,它看上去像一棵 "圣诞树",它的根在上,叶朝下。 + +**树有多个节点(node),用以储存元素。某些节点之间存在一定的关系,用连线表示,连线称为边(edge)。边的上端节点称为父节点,下端称为子节点。树像是一个不断分叉的树根。** + +### 二叉树 + +最多有两棵子树的树被称为二叉树 + +满二叉树: 二叉树中所有非叶子结点的度都是2,且叶子结点都在同一层次上 + +完全二叉树: 如果一个二叉树与满二叉树前m个节点的结构相同,这样的二叉树被称为完全二叉树 + +### 二叉查找树 + +指一棵空树或者具有下列性质的二叉树。 + +- 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值; +- 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值; +- 任意节点的左、右子树也分别为二叉查找树; +- 没有键值相等的节点。 + +### AVL树 平衡二叉搜索树,它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1。 @@ -67,21 +89,14 @@ ![在这里插入图片描述](https://img-blog.csdnimg.cn/20181206115511699.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==,size_16,color_FFFFFF,t_70) +### B树 - -## B树 - -也称B-树,属于多叉树又名平衡多路查找树。 - -规则: +也称B-树,属于多叉树又名平衡多路查找树。规则: - 1<子节点数<=m,m代表一个树节点最多有多少个查找路径 - 每个节点最多有m-1个关键字,非根节点至少有m/2个关键字,根节点最少可以只有1个关键字 - 每个节点都有指针指向子节点,指针个数=关键字个数+1,叶子节点指针指向null -三叉树: -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMDE1MjkwNjM1MS04MDUwOTY4NTMucG5n?x-oss-process=image/format,png) - B-树的特性: 1. 关键字集合分布在整颗树中; @@ -95,54 +110,58 @@ B-和B+树的区别 - B+树的非叶子结点不包含data,叶子结点使用链表连接,便于区间查找和遍历。B-树需要遍历整棵树,范围查询性能没有B+树好。 - B-树的非树节点存放数据和索引,搜索可能在非叶子结点结束,访问更快。 - - -## 红黑树 +### 红黑树 红黑树是对AVL树的优化,只要求部分平衡,用非严格的平衡来换取增删节点时候旋转次数的降低,提高了插入和删除的性能。查找性能并没有提高,查找的时间复杂度是O(logn)。红黑树通过左旋、右旋和变色维持平衡。 对于插入节点,AVL和红黑树都是最多两次旋转来实现平衡。对于删除节点,avl需要维护从被删除节点到根节点root这条路径上所有节点的平衡,旋转的量级为O(logN),而红黑树最多只需旋转3次。 -- 特性: - (1) 每个节点或者是黑色,或者是红色。 - (2) 根节点和叶子节点是黑色,叶子节点为空。 - (4)红色节点的子节点必须是黑色的。 - (5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点,保证没有一条路径会比其他路径长一倍。 +特性: +(1) 每个节点或者是黑色,或者是红色。 +(2) 根节点和叶子节点是黑色,叶子节点为空。 +(4)红色节点的子节点必须是黑色的。 +(5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点,保证没有一条路径会比其他路径长一倍。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165116.png) -- 优点:相比avl树,红黑树插入删除的效率更高。红黑树维持红黑性质所做的红黑变换和旋转的开销,相较于avl树维持平衡的开销要小得多。 +优点:相比avl树,红黑树插入删除的效率更高。红黑树维持红黑性质所做的红黑变换和旋转的开销,相较于avl树维持平衡的开销要小得多。 -- 应用:主要用来存储有序的数据,Java中的TreeSet和TreeMap都是通过红黑树实现的。 - ![在这里插入图片描述](https://img-blog.csdn.net/20181007120411579?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) +应用:主要用来存储有序的数据,Java中的TreeSet和TreeMap都是通过红黑树实现的。 ## 图 图由顶点集(vertex set)和边集(edge set)所组成。 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMDE4NDk0NjAyOC0xNTY4NzUzODc1LnBuZw?x-oss-process=image/format,png) + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165442.png) 图的存储结构有邻接矩阵、邻接表和边集数组三种。 -邻接矩阵 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMDE4NTExNjYxOC0xODU0OTkxNjEwLnBuZw?x-oss-process=image/format,png) -邻接表 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMDE4NTMxNTU1MC0xOTQ3MTIzMDAucG5n?x-oss-process=image/format,png) + +1、邻接矩阵 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165526.png) + +2、邻接表 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165617.png) 下面给出建立图的邻接表中所使用的边结点类的定义 ```java - public class EdgeNode { //定义邻接表中的边结点类型 - int adjvex; //邻接点域 - int weight; //边的权值域,假定为整型,对于无权图,边的权值为1 - EdgeNode next; //指向下一个边结点的链接域 - public EdgeNode(int adj, EdgeNode nt) - { //对无权图中的边结点进行初始化 - adjvex=adj; next=nt; weight=1; - } - public EdgeNode(int adj, int wgt, EdgeNode nt) - { //对有权图中的边结点进行初始化 - adjvex=adj; next=nt; weight=wgt; - } - } +public class EdgeNode { //定义邻接表中的边结点类型 + int adjvex; //邻接点域 + int weight; //边的权值域,假定为整型,对于无权图,边的权值为1 + EdgeNode next; //指向下一个边结点的链接域 + public EdgeNode(int adj, EdgeNode nt) + { //对无权图中的边结点进行初始化 + adjvex=adj; next=nt; weight=1; + } + public EdgeNode(int adj, int wgt, EdgeNode nt) + { //对有权图中的边结点进行初始化 + adjvex=adj; next=nt; weight=wgt; + } +} ``` 图的接口类定义如下: @@ -170,43 +189,43 @@ public interface Graph 深度优先遍历 ```java - private void dfs(int i, boolean[] visited) { - System.out.printl(i + " "); - visited[i] = true; - EdgeNode p = a[i]; - while(p != null) { - int j = p.adjvex; - if(!visited[j]) { - dfs(j, visited); - } - p = p.next; +private void dfs(int i, boolean[] visited) { + System.out.printl(i + " "); + visited[i] = true; + EdgeNode p = a[i]; + while(p != null) { + int j = p.adjvex; + if(!visited[j]) { + dfs(j, visited); } + p = p.next; } +} ``` 广度优先搜索 ```java - private void bfs(int i, boolean[] visited) { - LinkedList queue = new LinkedList<>(); - System.out.print(i + " "); - visited[i] = true; - queue.offer(i); - while(!queue.isEmpty()) { - int k = queue.poll(); - EdgeNode p = a[k]; - - while(p != null) { - int j = p.adjvex; - if(!visited[j]) { - System.out.print(j + " "); - visited[j] = true; - queue.offer(j); - } - p = p.next; +private void bfs(int i, boolean[] visited) { + LinkedList queue = new LinkedList<>(); + System.out.print(i + " "); + visited[i] = true; + queue.offer(i); + while(!queue.isEmpty()) { + int k = queue.poll(); + EdgeNode p = a[k]; + + while(p != null) { + int j = p.adjvex; + if(!visited[j]) { + System.out.print(j + " "); + visited[j] = true; + queue.offer(j); } + p = p.next; } } +} ``` diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" index 7325e6a..7100651 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" @@ -1,113 +1,220 @@ -# 二分查找 +## 二叉树的遍历 + +二叉树的先序、中序和后序属于深度优先遍历DFS,层次遍历属于广度优先遍历BFS。 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165820.png) + +### 前序遍历 ```java - public int binarySearch(int[] arr, int target) { - if (arr == null || arr.length <= 1) { - return -1; +class Solution { + //方法1 + public List preorderTraversal1(TreeNode root) { + List result = new ArrayList<>(); + LinkedList ll = new LinkedList<>(); //类型声明List改为LinkedList,List没有addFirst()/removeFirst()方法 + + while (root != null || !ll.isEmpty()) { + while (root != null) { + result.add(root.val); + ll.addFirst(root); + root = root.left; + } + root = ll.removeFirst(); + root = root.right; } - int left = 0; - int right = arr.length - 1; + return result; + } + //方法2 + public List preorderTraversal2(TreeNode root) { + List result = new ArrayList<>(); + if(root == null) { + return result; + } + + Stack s = new Stack<>(); + s.push(root); + while(!s.isEmpty()) { + TreeNode node = s.pop(); + result.add(node.val); + if(node.right != null) { + s.push(node.right);//先压右,再压左 + } + if(node.left != null) { + s.push(node.left); + } + } + + return result; + } +} +``` - while (left <= right) { - int mid = (left + right) >>> 1; - if (arr[mid] > target) { - right = mid - 1; - } else if (arr[mid] < target) { - left = mid + 1; - } else { - return mid; +### 中序遍历 + +```java + public List inorderTraversal(TreeNode root) { + List res = new ArrayList<>(); + Deque deque = new ArrayDeque<>(); + + while (!deque.isEmpty() || root != null) { + while (root != null) { + deque.push(root); + root = root.left; } + root = deque.pop(); + res.add(root.val); + root = root.right; } - return -1; + return res; } ``` -# 归并排序 +### 后序遍历 +使用 null 作为标志位,访问到 null 说明此次递归调用结束。 +```java +class Solution { + public List postorderTraversal(TreeNode root) { + List res = new LinkedList<>(); + if (root == null) { + return res; + } -## 简单讲下归并排序? + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + root = stack.pop(); + if (root != null) { + stack.push(root);//最后访问 + stack.push(null); + if (root.right != null) { + stack.push(root.right); + } + if (root.left != null) { + stack.push(root.left); + } + } else { //值为null说明此次递归调用结束,将节点值存进结果 + res.add(stack.pop().val); + } + } -归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。 + return res; + } +} +``` -## 说说归并排序怎么实现的? +### 层序遍历 -两路归并排序算法思路是递归处理。每个递归过程涉及三个步骤 +``` +class Solution { + public List> levelOrder(TreeNode root) { + List> res = new ArrayList<>(); + LinkedList queue = new LinkedList<>(); + if (root == null) { + return res; + } + queue.addLast(root); + while (!queue.isEmpty()) { + List levelList = new LinkedList<>(); + int size = queue.size(); + while (size-- > 0) { + root = queue.removeFirst(); + levelList.add(root.val); + if (root.left != null) { + queue.addLast(root.left); + } + if (root.right != null) { + queue.addLast(root.right); + } + } + res.add(levelList); + } + return res; + } +} +``` -- 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素 -- 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作 -- 合并: 合并两个排好序的子序列,生成排序结果 +## 排序算法 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220327151830.png) +常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 -代码实现: +![](https://raw.githubusercontent.com/Tyson0314/img/master/排序算法.png) + +### 冒泡排序 ```java -public class MergeSort { - public void mergeSort(int[] arr) { - if (arr == null || arr.length == 0) { + public void bubbleSort(int[] arr) { + if (arr == null) { return; } - //辅助数组 - int[] tmpArr = new int[arr.length]; - mergeSort(arr, tmpArr, 0, arr.length - 1); - } - - private void mergeSort(int[] arr, int[] tmpArr, int left, int right) { - if (left < right) { - int mid = (left + right) >> 1; - mergeSort(arr, tmpArr, left, mid); - mergeSort(arr, tmpArr, mid + 1, right); - merge(arr, tmpArr, left, mid, right); + boolean flag; + for (int i = arr.length - 1; i > 0; i--) { + flag = false; + for (int j = 0; j < i; j++) { + if (arr[j] > arr[j + 1]) { + int tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + flag = true; + } + } + if (!flag) { + return; + } } } +``` - private void merge(int[] arr, int[] tmpArr, int left, int mid, int right) { - int i = left; - int j = mid + 1; - int tmpIndex = left; - while (i <= mid && j <= right) { - if (arr[i] < arr[j]) { - tmpArr[tmpIndex++] = arr[i]; - i++; - } else { - tmpArr[tmpIndex++] = arr[j]; - j++; +### 插入排序 + +```java + public void insertSort(int[] arr) { + if (arr == null) { + return; + } + for (int i = 1; i < arr.length; i++) { + int tmp = arr[i]; + int j = i; + for (; j > 0 && tmp < arr[j - 1]; j--) { + arr[j] = arr[j - 1]; } + arr[j] = tmp; } + } +``` - while (i <= mid) { - tmpArr[tmpIndex++] = arr[i++]; - } +### 选择排序 - while (j <= right) { - tmpArr[tmpIndex++] = arr[j++]; +```java + public void selectionSort(int[] arr) { + if (arr == null) { + return; } - - for (int m = left; m <= right; m++) { - arr[m] = tmpArr[m]; + for (int i = 0; i < arr.length - 1; i++) { + for (int j = i + 1; j < arr.length; j++) { + if (arr[i] > arr[j]) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + } } } -} ``` -## 时间复杂度是多少? - -对长度为n的序列,需进行logn次二路归并,每次归并的时间为O(n),故时间复杂度是O(nlgn)。 - -## 空间复杂度是多少? +### 基数排序 -归并排序需要辅助空间来暂存两个有序子序列归并的结果,故其辅助空间复杂度为O(n) +在基数排序中,因为没有比较操作,所以在时间复杂上,最好的情况与最坏的情况在时间上是一致的,均为 O(d * (n + r))。d 为位数,r 为基数,n 为原数组个数。 +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTI1MjkxMC8yMDE4MDkvMTI1MjkxMC0yMDE4MDkxMzExMDYyOTY4Ni00MDU0Mjk5NjkucG5n?x-oss-process=image/format,png) -# 快速排序 - -## 了解快速排序吗? +### 快速排序 快速排序是由**冒泡排序**改进而得到的,是一种排序执行效率很高的排序算法,它利用**分治法**来对待排序序列进行分治排序,它的思想主要是通过一趟排序将待排记录分隔成独立的两部分,其中的一部分比关键字小,后面一部分比关键字大,然后再对这前后的两部分分别采用这种方式进行排序,通过递归的运算最终达到整个序列有序。 -## 快速排序的过程? +快速排序的过程如下: 1. 在待排序的N个记录中任取一个元素(通常取第一个记录)作为基准,称为基准记录; 2. 定义两个索引 left 和 right 分别表示首索引和尾索引,key 表示基准值; @@ -117,7 +224,11 @@ public class MergeSort { 6. 再进行下一趟排序时,待排序列被分成两个区:[0,left-1]和[righ+1,end] 7. 对每一个分区重复以上步骤,直到所有分区中的记录都有序,排序完成 -代码实现: +快排为什么比冒泡效率高? + +快速排序之所以比较快,是因为相比冒泡排序,每次的交换都是跳跃式的,每次设置一个基准值,将小于基准值的都交换到左边,大于基准值的都交换到右边,这样不会像冒泡一样每次都只交换相邻的两个数,因此比较和交换的此数都变少了,速度自然更高。 + +快速排序的平均时间复杂度是O(nlgn),最坏时间复杂度是O(n^2)。 ```java public void quickSort(int[] arr) { @@ -160,10 +271,104 @@ public class MergeSort { } ``` -## 快排为什么比冒泡效率高? +### 归并排序 + +归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。 + +两路归并排序算法思路是递归处理。每个递归过程涉及三个步骤 + +- 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素 +- 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作 +- 合并: 合并两个排好序的子序列,生成排序结果 + +![](https://raw.githubusercontent.com/Tyson0314/img/master/20220327151830.png) + +时间复杂度:对长度为n的序列,需进行logn次二路归并,每次归并的时间为O(n),故时间复杂度是O(nlgn)。 + +空间复杂度:归并排序需要辅助空间来暂存两个有序子序列归并的结果,故其辅助空间复杂度为O(n) + +```java +public class MergeSort { + public void mergeSort(int[] arr) { + if (arr == null || arr.length == 0) { + return; + } + //辅助数组 + int[] tmpArr = new int[arr.length]; + mergeSort(arr, tmpArr, 0, arr.length - 1); + } + + private void mergeSort(int[] arr, int[] tmpArr, int left, int right) { + if (left < right) { + int mid = (left + right) >> 1; + mergeSort(arr, tmpArr, left, mid); + mergeSort(arr, tmpArr, mid + 1, right); + merge(arr, tmpArr, left, mid, right); + } + } + + private void merge(int[] arr, int[] tmpArr, int left, int mid, int right) { + int i = left; + int j = mid + 1; + int tmpIndex = left; + while (i <= mid && j <= right) { + if (arr[i] < arr[j]) { + tmpArr[tmpIndex++] = arr[i]; + i++; + } else { + tmpArr[tmpIndex++] = arr[j]; + j++; + } + } + + while (i <= mid) { + tmpArr[tmpIndex++] = arr[i++]; + } + + while (j <= right) { + tmpArr[tmpIndex++] = arr[j++]; + } + + for (int m = left; m <= right; m++) { + arr[m] = tmpArr[m]; + } + } +} +``` + +### 堆排序 + +堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 + +![](https://img-blog.csdn.net/20150312212515074) + +**Top大问题**解决思路:使用一个固定大小的**最小堆**,当堆满后,每次添加数据的时候与堆顶元素比较,若小于堆顶元素,则舍弃,若大于堆顶元素,则删除堆顶元素,添加新增元素,对堆进行重新排序。 + +对于n个数,取Top m个数,时间复杂度为O(nlogm),这样在n较大情况下,是优于nlogn(其他排序算法)的时间复杂度的。 + +PriorityQueue 是一种基于优先级堆的优先级队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头。优先级队列用数组实现,但是数组大小可以动态增加,容量无限。 + +```java +//找出前k个最大数,采用小顶堆实现 +public static int[] findKMax(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>(k);//队列默认自然顺序排列,小顶堆,不必重写compare + + for (int num : nums) { + if (pq.size() < k) { + pq.offer(num); + } else if (pq.peek() < num) {//如果堆顶元素 < 新数,则删除堆顶,加入新数入堆 + pq.poll(); + pq.offer(num); + } + } + + int[] result = new int[k]; + for (int i = 0; i < k&&!pq.isEmpty(); i++) { + result[i] = pq.poll(); + } + return result; +} +``` -快速排序之所以比较快,是因为相比冒泡排序,每次的交换都是跳跃式的,每次设置一个基准值,将小于基准值的都交换到左边,大于基准值的都交换到右边,这样不会像冒泡一样每次都只交换相邻的两个数,因此比较和交换的此数都变少了,速度自然更高。 -## 快排的时间复杂度是多少? -快速排序的平均时间复杂度是O(nlgn),最坏时间复杂度是O(n^2)。 \ No newline at end of file diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" index da09566..6cc4584 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" @@ -1,13 +1,3 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [cookie](#cookie) -- [session](#session) -- [区别](#%E5%8C%BA%E5%88%AB) - - - 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 ## cookie diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" index 642e7c3..abf68ff 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" @@ -1,50 +1,3 @@ - - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [URI和URL](#uri%E5%92%8Curl) - - [URI 格式](#uri-%E6%A0%BC%E5%BC%8F) -- [简单的HTTP协议](#%E7%AE%80%E5%8D%95%E7%9A%84http%E5%8D%8F%E8%AE%AE) - - [请求](#%E8%AF%B7%E6%B1%82) - - [响应](#%E5%93%8D%E5%BA%94) - - [首部](#%E9%A6%96%E9%83%A8) - - [通用首部字段](#%E9%80%9A%E7%94%A8%E9%A6%96%E9%83%A8%E5%AD%97%E6%AE%B5) - - [请求首部字段](#%E8%AF%B7%E6%B1%82%E9%A6%96%E9%83%A8%E5%AD%97%E6%AE%B5) - - [响应首部字段](#%E5%93%8D%E5%BA%94%E9%A6%96%E9%83%A8%E5%AD%97%E6%AE%B5) - - [实体首部字段](#%E5%AE%9E%E4%BD%93%E9%A6%96%E9%83%A8%E5%AD%97%E6%AE%B5) - - [Cookie相关的首部](#cookie%E7%9B%B8%E5%85%B3%E7%9A%84%E9%A6%96%E9%83%A8) - - [请求URI定位资源](#%E8%AF%B7%E6%B1%82uri%E5%AE%9A%E4%BD%8D%E8%B5%84%E6%BA%90) - - [HTTP方法](#http%E6%96%B9%E6%B3%95) - - [持久连接](#%E6%8C%81%E4%B9%85%E8%BF%9E%E6%8E%A5) - - [Cookie](#cookie) - - [编码提升传输速率](#%E7%BC%96%E7%A0%81%E6%8F%90%E5%8D%87%E4%BC%A0%E8%BE%93%E9%80%9F%E7%8E%87) - - [multipart 多部分对象集合](#multipart-%E5%A4%9A%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E9%9B%86%E5%90%88) - - [范围请求](#%E8%8C%83%E5%9B%B4%E8%AF%B7%E6%B1%82) - - [内容协商返回最合适的内容](#%E5%86%85%E5%AE%B9%E5%8D%8F%E5%95%86%E8%BF%94%E5%9B%9E%E6%9C%80%E5%90%88%E9%80%82%E7%9A%84%E5%86%85%E5%AE%B9) -- [状态码](#%E7%8A%B6%E6%80%81%E7%A0%81) - - [2xx 成功](#2xx-%E6%88%90%E5%8A%9F) - - [3xx 重定向](#3xx-%E9%87%8D%E5%AE%9A%E5%90%91) - - [4xx 客户端错误](#4xx-%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%94%99%E8%AF%AF) - - [5xx 服务器错误](#5xx-%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%94%99%E8%AF%AF) -- [Web 服务器](#web-%E6%9C%8D%E5%8A%A1%E5%99%A8) - - [代理](#%E4%BB%A3%E7%90%86) - - [网关](#%E7%BD%91%E5%85%B3) - - [隧道](#%E9%9A%A7%E9%81%93) -- [HTTPS](#https) - - [公开密钥加密](#%E5%85%AC%E5%BC%80%E5%AF%86%E9%92%A5%E5%8A%A0%E5%AF%86) -- [认证机制](#%E8%AE%A4%E8%AF%81%E6%9C%BA%E5%88%B6) - - [BASIC 认证](#basic-%E8%AE%A4%E8%AF%81) - - [DIGEST 认证](#digest-%E8%AE%A4%E8%AF%81) - - [SSL 客户端认证](#ssl-%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%A4%E8%AF%81) - - [基于表单认证](#%E5%9F%BA%E4%BA%8E%E8%A1%A8%E5%8D%95%E8%AE%A4%E8%AF%81) -- [基于 HTTP 的功能追加协议](#%E5%9F%BA%E4%BA%8E-http-%E7%9A%84%E5%8A%9F%E8%83%BD%E8%BF%BD%E5%8A%A0%E5%8D%8F%E8%AE%AE) - - [WebSocket](#websocket) - - [Web 服务器管理文件的 WebDAV](#web-%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AE%A1%E7%90%86%E6%96%87%E4%BB%B6%E7%9A%84-webdav) -- [Web 的攻击技术](#web-%E7%9A%84%E6%94%BB%E5%87%BB%E6%8A%80%E6%9C%AF) - - - ## 简介 访问baidu.com的过程: diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index c91b807..3d82083 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -1,39 +1,3 @@ - - - - -- [网络分层结构](#%E7%BD%91%E7%BB%9C%E5%88%86%E5%B1%82%E7%BB%93%E6%9E%84) -- [三次握手](#%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B) -- [两次握手可以吗?](#%E4%B8%A4%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%8F%AF%E4%BB%A5%E5%90%97) -- [四次挥手](#%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B) -- [第四次挥手为什么要等待2MSL?](#%E7%AC%AC%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%AD%89%E5%BE%852msl) -- [为什么是四次挥手?](#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B) -- [TCP有哪些特点?](#tcp%E6%9C%89%E5%93%AA%E4%BA%9B%E7%89%B9%E7%82%B9) -- [TCP和UDP的区别?](#tcp%E5%92%8Cudp%E7%9A%84%E5%8C%BA%E5%88%AB) -- [HTTP协议的特点?](#http%E5%8D%8F%E8%AE%AE%E7%9A%84%E7%89%B9%E7%82%B9) -- [HTTP报文格式](#http%E6%8A%A5%E6%96%87%E6%A0%BC%E5%BC%8F) -- [HTTP状态码有哪些?](#http%E7%8A%B6%E6%80%81%E7%A0%81%E6%9C%89%E5%93%AA%E4%BA%9B) -- [POST和GET的区别?](#post%E5%92%8Cget%E7%9A%84%E5%8C%BA%E5%88%AB) -- [HTTP长连接和短连接?](#http%E9%95%BF%E8%BF%9E%E6%8E%A5%E5%92%8C%E7%9F%AD%E8%BF%9E%E6%8E%A5) -- [HTTP1.1和 HTTP2.0的区别?](#http11%E5%92%8C-http20%E7%9A%84%E5%8C%BA%E5%88%AB) -- [HTTPS与HTTP的区别?](#https%E4%B8%8Ehttp%E7%9A%84%E5%8C%BA%E5%88%AB) -- [什么是数字证书?](#%E4%BB%80%E4%B9%88%E6%98%AF%E6%95%B0%E5%AD%97%E8%AF%81%E4%B9%A6) -- [HTTPS原理](#https%E5%8E%9F%E7%90%86) -- [DNS 的解析过程?](#dns-%E7%9A%84%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B) -- [浏览器中输入URL返回页面过程?](#%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E8%BE%93%E5%85%A5url%E8%BF%94%E5%9B%9E%E9%A1%B5%E9%9D%A2%E8%BF%87%E7%A8%8B) -- [什么是cookie和session?](#%E4%BB%80%E4%B9%88%E6%98%AFcookie%E5%92%8Csession) -- [Cookie和Session的区别?](#cookie%E5%92%8Csession%E7%9A%84%E5%8C%BA%E5%88%AB) -- [什么是对称加密和非对称加密?](#%E4%BB%80%E4%B9%88%E6%98%AF%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E5%92%8C%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86) -- [滑动窗口机制](#%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E6%9C%BA%E5%88%B6) -- [详细讲一下拥塞控制?](#%E8%AF%A6%E7%BB%86%E8%AE%B2%E4%B8%80%E4%B8%8B%E6%8B%A5%E5%A1%9E%E6%8E%A7%E5%88%B6) - - [慢开始](#%E6%85%A2%E5%BC%80%E5%A7%8B) - - [拥塞避免](#%E6%8B%A5%E5%A1%9E%E9%81%BF%E5%85%8D) - - [快重传](#%E5%BF%AB%E9%87%8D%E4%BC%A0) - - [快恢复](#%E5%BF%AB%E6%81%A2%E5%A4%8D) -- [ARP协议](#arp%E5%8D%8F%E8%AE%AE) - - - ## 网络分层结构 计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 @@ -265,6 +229,7 @@ HTTP2.0相比HTTP1.1支持的特性: 由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 **cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 + ![](https://raw.githubusercontent.com/Tyson0314/img/master/cookie.png) **cookie工作流程**: @@ -274,6 +239,7 @@ HTTP2.0相比HTTP1.1支持的特性: 3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 **session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 + ![](https://raw.githubusercontent.com/Tyson0314/img/master/session.png) ## Cookie和Session的区别? From 8f8e07cd359bc88430495d0aeed3d3a417aa7107 Mon Sep 17 00:00:00 2001 From: tyson Date: Tue, 5 Jul 2022 08:28:01 +0800 Subject: [PATCH 09/84] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Java/JVM.md | 32 +- ...21\351\235\242\350\257\225\351\242\230.md" | 16 +- ...a8\346\226\260\347\211\271\346\200\247.md" | 0 "Java/Java\345\237\272\347\241\200.md" | 10 +- ...00\351\235\242\350\257\225\351\242\230.md" | 33 +- ...21\351\235\242\350\257\225\351\242\230.md" | 14 +- ...10\351\235\242\350\257\225\351\242\230.md" | 10 +- "Java/\345\271\266\345\217\221.md" | 22 +- "Java/\351\233\206\345\220\210.md" | 8 +- README.md | 30 +- ...07\345\215\227\346\200\273\347\273\223.md" | 14 +- ...is\351\235\242\350\257\225\351\242\230.md" | 12 +- ...23\345\255\230\345\207\273\347\251\277.md" | 0 ...\345\261\200\345\224\257\344\270\200ID.md" | 16 +- .../\345\276\256\346\234\215\345\212\241.md" | 4 +- ...34\347\250\213\350\260\203\347\224\250.md" | 2 +- .../GitHub\346\214\207\345\215\227.md" | 18 +- "\345\267\245\345\205\267/progit2.md" | 10 +- .../MySQL\345\237\272\347\241\200.md" | 12 +- ...47\350\241\214\350\256\241\345\210\222.md" | 44 +-- .../MySQL\350\277\233\351\230\266.md" | 24 +- ...21\351\235\242\350\257\225\351\242\230.md" | 28 +- ...is\351\235\242\350\257\225\351\242\230.md" | 2 +- ...25\351\242\230\346\200\273\347\273\223.md" | 4 +- ...15\345\212\241\345\256\236\346\210\230.md" | 2 +- ...VC\351\235\242\350\257\225\351\242\230.md" | 2 +- ...ng\351\235\242\350\257\225\351\242\230.md" | 356 +++++++++++++++++- ...72\351\253\230\351\242\221\350\257\215.md" | 2 +- ...01\347\232\204\344\270\252\346\225\260.md" | 2 +- .../RabbitMQ.md" | 10 +- ...73\344\277\241\351\230\237\345\210\227.md" | 0 ...27\351\235\242\350\257\225\351\242\230.md" | 2 +- ...73\345\275\225\345\216\237\347\220\206.md" | 6 +- ...73\347\273\237\350\256\276\350\256\241.md" | 4 +- ...347\273\237\350\256\276\350\256\241old.md" | 2 +- 35 files changed, 550 insertions(+), 203 deletions(-) rename Java/Java8.md => "Java/Java8\346\226\260\347\211\271\346\200\247.md" (100%) rename "\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" => "Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" (98%) rename "\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" => "Redis/Redis\351\235\242\350\257\225\351\242\230.md" (98%) rename "\344\270\255\351\227\264\344\273\266/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" => "Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" (100%) rename "\344\270\255\351\227\264\344\273\266/RabbitMQ.md" => "\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" (98%) rename "\344\270\255\351\227\264\344\273\266/\346\255\273\344\277\241\351\230\237\345\210\227.md" => "\346\266\210\346\201\257\351\230\237\345\210\227/\346\255\273\344\277\241\351\230\237\345\210\227.md" (100%) rename "\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" => "\346\266\210\346\201\257\351\230\237\345\210\227/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" (99%) diff --git a/Java/JVM.md b/Java/JVM.md index 05f5634..b19e730 100644 --- a/Java/JVM.md +++ b/Java/JVM.md @@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。 JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 -![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png) +![image-20210905150636105](http://img.dabin-coder.cn/image/image-20210905150636105.png) > 图片来源:深入理解Java虚拟机-周志明 @@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png) +![](http://img.dabin-coder.cn/image/string-new.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png) +![](http://img.dabin-coder.cn/image/string-intern.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png) +![](http://img.dabin-coder.cn/image/string-equal.png) > 图片来源:https://blog.csdn.net/soonfly @@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对 - 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png) +![](http://img.dabin-coder.cn/image/object-handle.png) - 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png) +![](http://img.dabin-coder.cn/image/direct-pointer.png) @@ -245,7 +245,7 @@ ClassFile { 加载、验证、准备、解析、初始化、使用和卸载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png) +![](http://img.dabin-coder.cn/image/image-20210905002423703.png) ## 类加载的过程 @@ -281,7 +281,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png) +![](http://img.dabin-coder.cn/image/image-20210905002827546.png) 双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 @@ -339,7 +339,7 @@ public abstract class ClassLoader { 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png) +![](http://img.dabin-coder.cn/image/object-dead.png) ### 引用计数法 @@ -365,7 +365,7 @@ public class ReferenceCountingGc { 通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png) +![](http://img.dabin-coder.cn/image/gc-root-refer.png) #### 可作为GC Roots的对象 @@ -469,13 +469,13 @@ public class ReferenceCountingGc { 标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png) +![](http://img.dabin-coder.cn/image/image-20210905003458130.png) ### 复制清除算法 半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png) +![](http://img.dabin-coder.cn/image/image-20210905003714551.png) 特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 @@ -534,7 +534,7 @@ java -XX:+PrintCommandLineFlags -version 单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png) +![](http://img.dabin-coder.cn/image/serial-collector.png) 特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 @@ -542,7 +542,7 @@ java -XX:+PrintCommandLineFlags -version Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png) +![](http://img.dabin-coder.cn/image/parnew-collector.png) 除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 @@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时 - 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 - 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png) +![](http://img.dabin-coder.cn/image/cms-collector.png) 由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 @@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应 G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg) +![](http://img.dabin-coder.cn/image/g1-region.jpg) G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index d93bc43..3f2af40 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -2,7 +2,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png) +![](http://img.dabin-coder.cn/image/jvm内存结构0.png) ### 程序计数器 @@ -138,7 +138,7 @@ ClassFile { 类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png) +![](http://img.dabin-coder.cn/image/类加载.png) **加载** @@ -166,7 +166,7 @@ ClassFile { 一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png) +![](http://img.dabin-coder.cn/image/双亲委派.png) 双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下: @@ -265,7 +265,7 @@ public class ReferenceCount { 通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png) +![](http://img.dabin-coder.cn/image/可达性分析0.png) ## 可作为GC Roots的对象有哪些? @@ -366,7 +366,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png) +![](http://img.dabin-coder.cn/image/标记清除.png) **复制清除算法** @@ -378,7 +378,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一 根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png) +![](http://img.dabin-coder.cn/image/标记整理.png) **分类收集算法** @@ -461,7 +461,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低 G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png) +![](http://img.dabin-coder.cn/image/g1分区.png) G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。 @@ -703,4 +703,4 @@ class Person { -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git a/Java/Java8.md "b/Java/Java8\346\226\260\347\211\271\346\200\247.md" similarity index 100% rename from Java/Java8.md rename to "Java/Java8\346\226\260\347\211\271\346\200\247.md" diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" index 72cff97..3a08dc1 100644 --- "a/Java/Java\345\237\272\347\241\200.md" +++ "b/Java/Java\345\237\272\347\241\200.md" @@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接 Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 -![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png) +![field-method](http://img.dabin-coder.cn/image/field-method.png) ## Method类 @@ -1101,7 +1101,7 @@ public class GenericMethod { Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: -![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png) +![exception](http://img.dabin-coder.cn/image/exception.png) - Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 @@ -1198,7 +1198,7 @@ public class ExceptionTest { Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 -![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg) +![io](http://img.dabin-coder.cn/image/io.jpg) > 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) @@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 -![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png) +![bio](http://img.dabin-coder.cn/image/bio.png) ## NIO NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 -![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png) +![nio](http://img.dabin-coder.cn/image/nio.png) NIO与IO区别: diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index e4e9624..04f0e86 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -46,7 +46,7 @@ **JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png) +![](http://img.dabin-coder.cn/image/20220402230447.png) 所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。 @@ -56,7 +56,7 @@ 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png) +![](http://img.dabin-coder.cn/image/20220401234008.png) JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。 @@ -86,7 +86,7 @@ JRE = JVM + Java 核心类库 JDK = JRE + Java工具 + 编译器 + 调试器 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png) +![](http://img.dabin-coder.cn/image/20220402230613.png) ## 面向对象有哪些特性? @@ -232,7 +232,11 @@ private static class IntegerCache { ## String 为什么不可变? -先看下Java8 String类的源码: +先看看什么是不可变的对象。 + +如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。 + +接着来看Java8 String类的源码: ```java public final class String @@ -245,12 +249,27 @@ public final class String } ``` -String类是final的,它的所有成员变量也都是final的。为什么是final的? +从源码可以看出,String对象其实在内部就是一个个字符,存储在这个value数组里面的。 + +value数组用final修饰,final 修饰的变量,值不能被修改。因此value不可以指向其他对象。 + +String类内部所有的字段都是私有的,也就是被private修饰。而且String没有对外提供修改内部状态的方法,因此value数组不能改变。 + +所以,String是不可变的。 + +那为什么String要设计成不可变的? + +主要有以下几点原因: 1. **线程安全**。同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。 2. **支持hash映射和缓存。**因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性使得 hash 值也不会变,不需要重新计算。 +3. **出于安全考虑**。网络地址URL、文件路径path、密码通常情况下都是以String类型保存,假若String不是固定不变的,将会引起各种安全隐患。比如将密码用String的类型保存,那么它将一直留在内存中,直到垃圾收集器把它清除。假如String类不是固定不变的,那么这个密码可能会被改变,导致出现安全隐患。 3. **字符串常量池优化**。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。 +既然我们的String是不可变的,它内部还有很多substring, replace, replaceAll这些操作的方法。这些方法好像会改变String对象?怎么解释呢? + +其实不是的,我们每次调用replace等方法,其实会在堆内存中创建了一个新的对象。然后其value数组引用指向不同的对象。 + ## String, StringBuffer 和 StringBuilder区别 **1. 可变性** @@ -975,7 +994,7 @@ unchecked Exception: 不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423154450.png) +![](http://img.dabin-coder.cn/image/20220423154450.png) @@ -1113,4 +1132,4 @@ Java泛型是JDK 5中引⼊的⼀个新特性, 允许在定义类和接口的 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" index e71a0dd..022a2fc 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" @@ -10,7 +10,7 @@ ### 线程池执行原理? -![线程池执行流程](https://raw.githubusercontent.com/Tyson0314/img/master/线程池执行流程.png) +![线程池执行流程](http://img.dabin-coder.cn/image/线程池执行流程.png) 1. 当线程池里存活的线程数小于核心线程数`corePoolSize`时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数`corePoolSize`时,线程池里面的线程会一直存活着,就算空闲时间超过了`keepAliveTime`,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。 2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。 @@ -145,7 +145,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](http://img.dabin-coder.cn/image/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -171,7 +171,7 @@ public static ExecutorService newCachedThreadPool() { **终止(TERMINATED)**:表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](http://img.dabin-coder.cn/image/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -347,7 +347,7 @@ class RunnableDemo implements Runnable { 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。 -![死锁](https://raw.githubusercontent.com/Tyson0314/img/master/死锁.png) +![死锁](http://img.dabin-coder.cn/image/死锁.png) 下面通过例子说明线程死锁,代码来自并发编程之美。 @@ -632,7 +632,7 @@ class SeasonThreadTask implements Runnable{ 每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/threadlocal.png) +![](http://img.dabin-coder.cn/image/threadlocal.png) 调用`threadLocal.set()`-->调用`getMap(Thread)`-->返回当前线程的`ThreadLocalMap`-->`map.set(this, value)`,this是`threadLocal`本身。源码如下: @@ -729,7 +729,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节点中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/aqs.png) +![](http://img.dabin-coder.cn/image/aqs.png) ## ReentrantLock 是如何实现可重入性的? @@ -1095,4 +1095,4 @@ JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" index ba6af67..5af404d 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" @@ -4,9 +4,9 @@ Java集合类主要由两个接口**Collection**和**Map**派生出来的,Coll Java集合框架图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/collections2.png) +![](http://img.dabin-coder.cn/image/collections2.png) -![](https://raw.githubusercontent.com/Tyson0314/img/master/map.png) +![](http://img.dabin-coder.cn/image/map.png) List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合。Map代表的是存储key-value对的集合,可根据元素的key来访问value。 @@ -147,7 +147,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![图片来源网络](http://img.dabin-coder.cn/image/hashmap-put.png) ### 红黑树的特点? @@ -221,7 +221,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](http://img.dabin-coder.cn/image/image-20210905215046510.png) **TreeMap的特点:** @@ -548,4 +548,4 @@ https://coolshell.cn/articles/9606.htm(HashMap 死循环) -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" index 1f35396..65ea9c9 100644 --- "a/Java/\345\271\266\345\217\221.md" +++ "b/Java/\345\271\266\345\217\221.md" @@ -87,7 +87,7 @@ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveT 创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/thread-pool.png) +![](http://img.dabin-coder.cn/image/thread-pool.png) ThreadPoolExecutor 的通用构造函数: @@ -326,7 +326,7 @@ public static ExecutorService newCachedThreadPool() { 3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; 4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/scheduled-task.jpg) +![](http://img.dabin-coder.cn/image/scheduled-task.jpg) 适用场景:周期性执行任务的场景,需要限制线程数量的场景。 @@ -340,7 +340,7 @@ FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VAL CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/executors-ali.png) +![](http://img.dabin-coder.cn/image/executors-ali.png) 正确示例(阿里巴巴编码规范): @@ -369,7 +369,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909233258929.png) +![](http://img.dabin-coder.cn/image/image-20210909233258929.png) 本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 @@ -392,7 +392,7 @@ Java内存模型:线程之间的共享变量存储在主内存里,每个线 终止(TERMINATED):表示该线程已经执行完毕。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210909235618175.png) +![](http://img.dabin-coder.cn/image/image-20210909235618175.png) > 图片来源:Java并发编程的艺术 @@ -680,7 +680,7 @@ public class SynchronizedDemo { Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-block.png) +![](http://img.dabin-coder.cn/image/synchronized-block.png) **方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 @@ -692,7 +692,7 @@ public class SynchronizedMethod { } ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/synchronized-method.png) +![](http://img.dabin-coder.cn/image/synchronized-method.png) #### 锁的状态 @@ -1077,7 +1077,7 @@ private volatile int state;//共享变量,使用volatile修饰保证线程可 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210910000456607.png) +![](http://img.dabin-coder.cn/image/image-20210910000456607.png) @@ -1112,19 +1112,19 @@ public void conditionSignal() throws InterruptedException { 每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-await.png) +![](http://img.dabin-coder.cn/image/condition-await.png) > 图片来源:Java并发编程的艺术 在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-wait-queue.png) +![](http://img.dabin-coder.cn/image/condition-wait-queue.png) > 图片来源:Java并发编程的艺术 线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/condition-signal.png) +![](http://img.dabin-coder.cn/image/condition-signal.png) > 图片来源:Java并发编程的艺术 diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" index 83fecae..d626f12 100644 --- "a/Java/\351\233\206\345\220\210.md" +++ "b/Java/\351\233\206\345\220\210.md" @@ -51,7 +51,7 @@ 以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/Java-Collections.jpeg) +![](http://img.dabin-coder.cn/image/Java-Collections.jpeg) ### HashMap @@ -88,7 +88,7 @@ put方法流程: 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![](https://raw.githubusercontent.com/Tyson0314/img/master/hashmap-put.png) +![](http://img.dabin-coder.cn/image/hashmap-put.png) > 参考链接: > @@ -121,7 +121,7 @@ HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初 LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 -![linkedhashmap](https://raw.githubusercontent.com/Tyson0314/img/master/linkedhashmap.png) +![linkedhashmap](http://img.dabin-coder.cn/image/linkedhashmap.png) ### TreeMap @@ -136,7 +136,7 @@ public class TreeMap TreeMap 的继承结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905215046510.png) +![](http://img.dabin-coder.cn/image/image-20210905215046510.png) **TreeMap的特点:** diff --git a/README.md b/README.md index eed60e3..21e4c06 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,17 @@ 如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的**公众号『 程序员大彬 』**,后台回复『 PDF 』可以**下载最新版本的大厂高频面试题目PDF版本**。 -
+

个人公众号


- 微信交流群 -公众号 - 知乎 - 牛客网 - 掘金 - 免费PDF + 微信交流群 +公众号 + 知乎 + 牛客网 + 掘金 + 免费PDF

@@ -90,9 +90,9 @@ ## Redis -1. [【大厂面试】——Redis30问](中间件/Redis面试题.md)(牛客高赞,推荐 :+1:) -2. [Redis分布式锁(推荐 :+1:)](中间件/Redis分布式锁.md) -4. [缓存穿透、缓存雪崩、缓存击穿](中间件/缓存穿透、缓存雪崩、缓存击穿.md) +1. [【大厂面试】——Redis30问](Redis/Redis面试题.md)(牛客高赞,推荐 :+1:) +2. [Redis分布式锁(推荐 :+1:)](Redis/Redis分布式锁.md) +4. [缓存穿透、缓存雪崩、缓存击穿](Redis/缓存穿透、缓存雪崩、缓存击穿.md) # 框架 @@ -131,9 +131,9 @@ ## RabbitMQ -1. [消息队列面试题](中间件/消息队列面试题.md) -1. [RabbitMQ核心知识总结](中间件/RabbitMQ.md) (推荐 :+1:) -2. [死信队列](中间件/死信队列.md) +1. [消息队列面试题](消息队列/消息队列面试题.md) +1. [RabbitMQ核心知识总结](消息队列/RabbitMQ.md) (推荐 :+1:) +2. [死信队列](消息队列/死信队列.md) # 计算机网络 @@ -180,7 +180,7 @@ 如果想进**技术、面试交流群**,可以扫描下方二维码加我微信,**备注加群**,我拉你进群,群里有BAT大佬,互相学习~ -
+

@@ -191,7 +191,7 @@ | 微信 | 支付宝 | | ----------------------------------------------------------- | ------------------------------------------------------------ | -| ![](https://raw.githubusercontent.com/Tyson0314/img/master/微信收款.png) | ![](https://raw.githubusercontent.com/Tyson0314/img/master/支付宝赞赏码.png) | +| ![](http://img.dabin-coder.cn/image/微信收款.png) | ![](http://img.dabin-coder.cn/image/支付宝赞赏码.png) | 每笔赞赏我会在下面记录下来,感谢你们,我会更加努力,砥砺前行~ diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" "b/Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" similarity index 98% rename from "\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" rename to "Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" index 128b9a4..a3b0f32 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" +++ "b/Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" @@ -428,7 +428,7 @@ ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的 - 最底层的链表包含所有的元素 - 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-skiplist.png) +![](http://img.dabin-coder.cn/image/redis-skiplist.png) #### 对象 @@ -470,7 +470,7 @@ hash类型内部编码有两种: Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/list-api.png) +![](http://img.dabin-coder.cn/image/list-api.png) 使用场景: @@ -555,7 +555,7 @@ GET #返回文章ID。 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](http://img.dabin-coder.cn/image/redis-multi.jpg) DISCARD:放弃事务,即该事务内的所有命令都将取消 @@ -578,7 +578,7 @@ QUEUED 事务里的命令执行时会读取最新的值: -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-transaction.png) +![](http://img.dabin-coder.cn/image/redis-transaction.png) ### WATCH命令 @@ -725,7 +725,7 @@ SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-replication.png) +![](http://img.dabin-coder.cn/image/redis-replication.png) Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 @@ -857,7 +857,7 @@ redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 使用evalsha执行Lua脚本过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/evalsha.png) +![](http://img.dabin-coder.cn/image/evalsha.png) ### lua脚本作用 @@ -1000,7 +1000,7 @@ public void write(String key,Object data){ 解决方法: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210913235221410.png) +![](http://img.dabin-coder.cn/image/image-20210913235221410.png) > 图片来源:https://tech.it168.com diff --git "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" "b/Redis/Redis\351\235\242\350\257\225\351\242\230.md" similarity index 98% rename from "\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" rename to "Redis/Redis\351\235\242\350\257\225\351\242\230.md" index 4db94a9..b9a05f4 100644 --- "a/\344\270\255\351\227\264\344\273\266/Redis\351\235\242\350\257\225\351\242\230.md" +++ "b/Redis/Redis\351\235\242\350\257\225\351\242\230.md" @@ -120,7 +120,7 @@ scan的缺点:在scan的过程中如果有键的变化(增加、删除、修 3. EXEC命令进行提交事务 -![](https://raw.githubusercontent.com/Tyson0314/img/master/redis-multi.jpg) +![](http://img.dabin-coder.cn/image/redis-multi.jpg) 一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: @@ -191,7 +191,7 @@ Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF` `bgsave`是主流的触发 RDB 持久化的方式,执行过程如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/rdb持久化过程.png) +![](http://img.dabin-coder.cn/image/rdb持久化过程.png) - 执行`BGSAVE`命令 - Redis 父进程判断当前**是否存在正在执行的子进程**,如果存在,`BGSAVE`命令直接返回。 @@ -236,7 +236,7 @@ appendfsync no //由操作系统决定何时进行同步操作 接下来看一下 AOF 持久化执行流程: -![](https://raw.githubusercontent.com/Tyson0314/img/master/aof工作流程0.png) +![](http://img.dabin-coder.cn/image/aof工作流程0.png) 1. 所有的写入命令会追加到 AOP 缓冲区中。 2. AOF 缓冲区根据对应的策略向硬盘同步。 @@ -296,7 +296,7 @@ Redis的复制功能是支持多个数据库之间的数据同步。主数据库 客户端连接Redis的时候,先连接哨兵,哨兵会告诉客户端Redis主节点的地址,然后客户端连接上Redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/sentinel.png) +![](http://img.dabin-coder.cn/image/sentinel.png) **工作原理** @@ -315,7 +315,7 @@ Redis cluster集群节点最小配置6个节点以上(3主3从),其中主 Redis cluster采用**虚拟槽分区**,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cluster_slots.png) +![](http://img.dabin-coder.cn/image/cluster_slots.png) **工作原理:** @@ -607,4 +607,4 @@ Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\344\270\255\351\227\264\344\273\266/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" "b/Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" similarity index 100% rename from "\344\270\255\351\227\264\344\273\266/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" rename to "Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" diff --git "a/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" "b/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" index 59b6f58..0871efa 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" @@ -1,6 +1,6 @@ 传统的单体架构的时候,我们基本是单库然后业务单表的结构。每个业务表的ID一般我们都是从1增,通过`AUTO_INCREMENT=1`设置自增起始值,但是在分布式服务架构模式下分库分表的设计,使得多个库或多个表存储相同的业务数据。这种情况根据数据库的自增ID就会产生相同ID的情况,不能保证主键的唯一性。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508235751.png) +![](http://img.dabin-coder.cn/image/20220508235751.png) 如上图,如果第一个订单存储在 DB1 上则订单 ID 为1,当一个新订单又入库了存储在 DB2 上订单 ID 也为1。我们系统的架构虽然是分布式的,但是在用户层应是无感知的,重复的订单主键显而易见是不被允许的。那么针对分布式系统如何做到主键唯一性呢? @@ -65,7 +65,7 @@ public static void main(String[] args) { 假设有三台机器,则DB1中order表的起始ID值为1,DB2中order表的起始值为2,DB3中order表的起始值为3,它们自增的步长都为3,则它们的ID生成范围如下图所示: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000004.png) +![](http://img.dabin-coder.cn/image/20220509000004.png) 通过这种方式明显的优势就是依赖于数据库自身不需要其他资源,并且ID号单调自增,可以实现一些对ID有特殊要求的业务。 @@ -94,7 +94,7 @@ Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划 这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508235958.png) +![](http://img.dabin-coder.cn/image/20220508235958.png) Snowflake 的[Twitter官方原版](https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala)是用Scala写的,对Scala语言有研究的同学可以去阅读下,以下是 Java 版本的写法。 @@ -303,7 +303,7 @@ UidGenerator 依然是以划分命名空间的方式将 64-bit位分割成多个 - 中间的 workId (数据中心+工作机器,可以其他组成方式)则由 22-bit位组成,可表示 2^22 = 4194304个工作ID。 - 最后由13-bit位构成自增序列,可表示2^13 = 8192个数。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000004.png) +![](http://img.dabin-coder.cn/image/20220509000004.png) 其中 workId (机器 id),最多可支持约420w次机器启动。内置实现为在启动时由数据库分配(表名为 WORKER_NODE),默认分配策略为用后即弃,后续可提供复用策略。 @@ -427,7 +427,7 @@ CREATE TABLE `leaf_alloc` ( 原来获取ID每次都需要写数据库,现在只需要把step设置得足够大,比如1000。那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。读写数据库的频率从1减小到了1/step,大致架构如下图所示: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000142.png) +![](http://img.dabin-coder.cn/image/20220509000142.png) 同时Leaf-segment 为了解决 TP999(满足千分之九百九十九的网络请求所需要的最低耗时)数据波动大,当号段使用完之后还是会hang在更新数据库的I/O上,TP999 数据会出现偶尔的尖刺的问题,提供了双buffer优化。 @@ -435,7 +435,7 @@ CREATE TABLE `leaf_alloc` ( 为了DB取号段的过程能够做到无阻塞,不需要在DB取号段的时候阻塞请求线程,即当号段消费到某个点时就异步的把下一个号段加载到内存中,而不需要等到号段用尽的时候才去更新号段。这样做就可以很大程度上的降低系统的 TP999 指标。详细实现如下图所示: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000258.png) +![](http://img.dabin-coder.cn/image/20220509000258.png) 采用双buffer的方式,Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复。 @@ -454,13 +454,13 @@ Leaf-snowflake是按照下面几个步骤启动的: - 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。 - 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000333.png) +![](http://img.dabin-coder.cn/image/20220509000333.png) 为了减少对 Zookeeper的依赖性,会在本机文件系统上缓存一个workerID文件。当ZooKeeper出现问题,恰好机器出现问题需要重启时,能保证服务能够正常启动。 上文阐述过在类 snowflake算法上都存在时钟回拨的问题,Leaf-snowflake在解决时钟回拨的问题上是通过校验自身系统时间与 `leaf_forever/${self}`节点记录时间做比较然后启动报警的措施。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220509000708.png) +![](http://img.dabin-coder.cn/image/20220509000708.png) 美团官方建议是由于强依赖时钟,对时间的要求比较敏感,在机器工作时NTP同步也会造成秒级别的回退,建议可以直接关闭NTP同步。要么在时钟回拨的时候直接不提供服务直接返回ERROR_CODE,等时钟追上即可。或者做一层重试,然后上报报警系统,更或者是发现有时钟回拨之后自动摘除本身节点并报警。 diff --git "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" index 7f52c58..c48afc0 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" +++ "b/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" @@ -137,7 +137,7 @@ 更好的方式是采用API网关(也叫做服务网关),实现一个API网关**接管所有的入口流量**,类似Nginx的作用,将所有用户的请求转发给后端的服务器,但网关做的不仅仅只是简单的转发,也会针对流量做一些扩展,比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等,这样将通用的逻辑抽出来,由网关统一去做,业务方也能够更专注于业务逻辑,提升迭代的效率。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508185101.jpg) +![](http://img.dabin-coder.cn/image/20220508185101.jpg) 通过引入API网关,客户端只需要与API网关交互,而不用与各个业务方的接口分别通讯,但多引入一个组件就多引入了一个潜在的故障点,因此要实现一个高性能、稳定的网关,也会涉及到很多点。 @@ -145,7 +145,7 @@ **服务网关基本功能**: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508120340.png) +![](http://img.dabin-coder.cn/image/20220508120340.png) - 智能路由:接收**外部**一切请求,并转发到后端的对外服务。注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。 - 权限校验:网关可以做一些用户身份认证,权限认证,防止非法请求操作API 接口,对内部服务起到保护作用 diff --git "a/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" "b/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" index 4f38569..beade88 100644 --- "a/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" +++ "b/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" @@ -22,7 +22,7 @@ RPC是一个完整的远程调用方案,它通常包括通信协议和序列 > stub说的都是“一小块代码”,通常是有个caller要调用callee的时候,中间需要一些特殊处理的逻辑,就会用这种“小块代码”去做。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220508160414.png) +![](http://img.dabin-coder.cn/image/20220508160414.png) 1. 服务消费端(client)以本地调用的方式调用远程服务; 2. 客户端 Stub(client stub) 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(序列化):`RpcRequest`; diff --git "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" index a125d4b..d78291f 100644 --- "a/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" +++ "b/\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" @@ -22,15 +22,15 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 创建一个新的仓库,用来存放项目。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822154700616.png) + ![](http://img.dabin-coder.cn/image/image-20210822154700616.png) - 或者你在GitHub上看到别人有一个超级无敌有趣的项目,可以直接fork过来,可以理解成复制过来,变成你自己的。之后你想怎么改就怎么改! - ![image-20210822155107839](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155107839.png) + ![image-20210822155107839](http://img.dabin-coder.cn/image/image-20210822155107839.png) - 然后你可以通过Git命令行`git clone xxx`把项目clone到本地,在本地进行创作。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822155359118.png) + ![](http://img.dabin-coder.cn/image/image-20210822155359118.png) - 最后,在本地创作完成,可以使用`git commit -m xxx`提交到本地库,然后使用`git push`把修改推送到GitHub仓库。之后就可以在GitHub上面看到你修改的内容啦~ @@ -42,23 +42,23 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 评价GitHub项目的两个重要的参数:star和fork。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161003170.png) +![](http://img.dabin-coder.cn/image/image-20210822161003170.png) 比较优秀和热门的项目,star数目和fork数目都会比较多。我们可以根据这两个参数筛选出比较好的项目。使用`关键字 stars:>=xxx forks:>=xxx` 可以筛选出star和fork数目大于xxx的相关项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161122586.png) +![](http://img.dabin-coder.cn/image/image-20210822161122586.png) - 使用 `awesome 关键字`,可以筛选出比较高质量的学习、书籍、工具类或者插件类的集合。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822161608599.png) +![](http://img.dabin-coder.cn/image/image-20210822161608599.png) - 在特定位置搜索关键词。有些关键词出现在项目的不同位置,比如项目名称、项目描述和README等。使用`关键词 in name/description/Readme`,可以搜索到相关的内容。比如使用`spring in name`,可以搜索到在项目名中包含spring的项目。 -![image-20210822162144086](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822162144086.png) +![image-20210822162144086](http://img.dabin-coder.cn/image/image-20210822162144086.png) - 指定条件搜索关键词。如`tool language:java`搜索到的是包含关键字tool的Java项目,`tool followers:>1000`可以搜索到包含关键字tool,且follower数量大于1000的项目。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822163111390.png) +![](http://img.dabin-coder.cn/image/image-20210822163111390.png) @@ -72,7 +72,7 @@ Git又是什么呢?简单的说,**Git 是一个管理你的代码历史记 - 文档神器。可以为自己的项目建立wiki,可以用markdown语法写wiki; -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210822172419760.png) +![](http://img.dabin-coder.cn/image/image-20210822172419760.png) - 使用GitHub pages建立个人静态网站,搞一个有自己域名的独立博客,想想都觉得开心。使用GitHub pages的好处是搭建简单而且免费,支持静态脚本,并且可以绑定自己的域名。具体可以参考:[GitHub Pages 建立个人网站详细教程 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/58229299) diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/progit2.md" index 68b8c2b..a79a027 100644 --- "a/\345\267\245\345\205\267/progit2.md" +++ "b/\345\267\245\345\205\267/progit2.md" @@ -85,7 +85,7 @@ Git工作流程如下: Git 的工作流程图如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-work-flow.png) +![](http://img.dabin-coder.cn/image/git-work-flow.png) > 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 @@ -103,11 +103,11 @@ Git 的三种状态:已修改(modified)、已暂存(staged)和已提 基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/git工作流程.png) +![](http://img.dabin-coder.cn/image/git工作流程.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` -![](https://raw.githubusercontent.com/Tyson0314/img/master/git-status.png) +![](http://img.dabin-coder.cn/image/git-status.png) ## 配置 @@ -156,7 +156,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](https://raw.githubusercontent.com/Tyson0314/img/master/git生命周期.png) +![git生命周期](http://img.dabin-coder.cn/image/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -262,7 +262,7 @@ git commit -m "add readme.md" 单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210830225020753.png) +![](http://img.dabin-coder.cn/image/image-20210830225020753.png) 此时应该这么操作: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" index 13d9ab1..8c66844 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" @@ -361,7 +361,7 @@ WHERE Soundex(cust_contact) = Soundex('Y Lie'); ### 日期处理函数 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235607.png) +![](http://img.dabin-coder.cn/image/20220530235607.png) 查找2005年9月的所有订单: ```mysql @@ -380,7 +380,7 @@ WHERE Year(order_date) = 2005 AND Month(order_date) = 9; ### 数值处理函数 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233617.png) +![](http://img.dabin-coder.cn/image/20220530233617.png) ## 汇总数据 @@ -415,7 +415,7 @@ SELECT * FROM orders GROUP BY cust_id; ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233523.png) +![](http://img.dabin-coder.cn/image/20220530233523.png) 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。 @@ -534,7 +534,7 @@ SELECT * FROM role NATURAL JOIN user_role; 返回结果: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235619.png) +![](http://img.dabin-coder.cn/image/20220530235619.png) ### 内连接 @@ -546,7 +546,7 @@ SELECT * FROM role INNNER JOIN user_role 返回结果: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235640.png) +![](http://img.dabin-coder.cn/image/20220530235640.png) join…using(column)按指定的属性做等值连接。 join…on tableA.column1 = tableB.column2 指定条件。 @@ -557,7 +557,7 @@ SELECT * FROM role INNER JOIN user_role ON role.role_id = user_role.role_id 返回结果: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530235654.png) +![](http://img.dabin-coder.cn/image/20220530235654.png) ### 外连接 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" index e9f255a..eaffa77 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" @@ -91,7 +91,7 @@ where blog_id = ( 三个表依次嵌套,发现最里层的子查询 `id`最大,最先执行。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-id.png) +![](http://img.dabin-coder.cn/image/explain-id.png) ## select_type @@ -107,13 +107,13 @@ where blog_id = ( 查询的表名,并不一定是真实存在的表,有别名显示别名,也可能为临时表。当from子句中有子查询时,table列是 ``的格式,表示当前查询依赖 id为N的查询,会先执行 id为N的查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804083523885.png) +![](http://img.dabin-coder.cn/image/image-20210804083523885.png) ## partitions 查询时匹配到的分区信息,对于非分区表值为`NULL`,当查询的是分区表时,`partitions`显示分区表命中的分区情况。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802022931773.png) +![](http://img.dabin-coder.cn/image/image-20210802022931773.png) ## type @@ -123,25 +123,25 @@ where blog_id = ( 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快。比如,Mysql系统表proxies_priv在Mysql服务启动时候已经加载在内存中,对这个表进行查询不需要进行磁盘 IO。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801233419732.png) +![](http://img.dabin-coder.cn/image/image-20210801233419732.png) ### const 单表操作的时候,查询使用了主键或者唯一索引。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-const.png) +![](http://img.dabin-coder.cn/image/explain-const.png) ### eq_ref **多表关联**查询的时候,主键和唯一索引作为关联条件。如下图的sql,对于user表(外循环)的每一行,user_role表(内循环)只有一行满足join条件,只要查找到这行记录,就会跳出内循环,继续外循环的下一轮查询。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801232638027.png) +![](http://img.dabin-coder.cn/image/image-20210801232638027.png) ### ref 查找条件列使用了索引而且不为主键和唯一索引。虽然使用了索引,但该索引列的值并不唯一,这样即使使用索引查找到了第一条数据,仍然不能停止,要在目标值附近进行小范围扫描。但它的好处是不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内做扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-ref.png) +![](http://img.dabin-coder.cn/image/explain-ref.png) ### ref_or_null @@ -151,13 +151,13 @@ where blog_id = ( 使用了索引合并优化方法,查询使用了两个以上的索引。新建comment表,id为主键,value_id为非唯一索引,执行`explain select content from comment where value_id = 1181000 and id > 1000;`,执行结果显示查询同时使用了id和value_id索引,type列的值为index_merge。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802001215614.png) +![](http://img.dabin-coder.cn/image/image-20210802001215614.png) ### range 有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。像between、and、'>'、'<'、in和or都是范围索引扫描。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-range.png) +![](http://img.dabin-coder.cn/image/explain-range.png) ### index @@ -165,17 +165,17 @@ index包括select索引列,order by主键两种情况。 1. order by主键。这种情况会按照索引顺序全表扫描数据,拿到的数据是按照主键排好序的,不需要额外进行排序。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225045980.png) + ![](http://img.dabin-coder.cn/image/image-20210801225045980.png) 2. select索引列。type为index,而且extra字段为using index,也称这种情况为索引覆盖。所需要取的数据都在索引列,无需回表查询。 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210801225942948.png) + ![](http://img.dabin-coder.cn/image/image-20210801225942948.png) ### all 全表扫描,查询没有用到索引,性能最差。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/explain-all.png) +![](http://img.dabin-coder.cn/image/explain-all.png) ## possible_keys @@ -249,13 +249,13 @@ CREATE TABLE `t_orderdetail` ( 查询的列未被索引覆盖,where筛选条件非索引的前导列。对存储引擎返回的结果进行过滤(Post-filter,后过滤),一般发生在MySQL服务器,而不是存储引擎层。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232729417.png) +![](http://img.dabin-coder.cn/image/image-20210802232729417.png) ### using index 查询的列被索引覆盖,并且where筛选条件符合最左前缀原则,通过**索引查找**就能直接找到符合条件的数据,不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802232357282.png) +![](http://img.dabin-coder.cn/image/image-20210802232357282.png) ### Using where&Using index @@ -265,17 +265,17 @@ CREATE TABLE `t_orderdetail` ( - where筛选条件不符合最左前缀原则 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233120283.png) + ![](http://img.dabin-coder.cn/image/image-20210802233120283.png) - where筛选条件是索引列前导列的一个范围 - ![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802233455880.png) + ![](http://img.dabin-coder.cn/image/image-20210802233455880.png) ### null 查询的列未被索引覆盖,并且where筛选条件是索引的前导列,也就是用到了索引,但是部分字段未被索引覆盖,必须回表查询这些字段,Extra中为NULL。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210802234122321.png) +![](http://img.dabin-coder.cn/image/image-20210802234122321.png) ### using index condition @@ -283,11 +283,11 @@ CREATE TABLE `t_orderdetail` ( 不使用ICP的情况(`set optimizer_switch='index_condition_pushdown=off'`),如下图,在步骤4中,没有使用where条件过滤索引: -![](https://raw.githubusercontent.com/Tyson0314/img/master/no-icp.png) +![](http://img.dabin-coder.cn/image/no-icp.png) 使用ICP的情况(`set optimizer_switch='index_condition_pushdown=on'`): -![](https://raw.githubusercontent.com/Tyson0314/img/master/icp.png) +![](http://img.dabin-coder.cn/image/icp.png) 下面的例子使用了ICP: @@ -296,11 +296,11 @@ explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G; ``` -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084617433.png) +![](http://img.dabin-coder.cn/image/image-20210803084617433.png) 关掉ICP之后(`set optimizer_switch='index_condition_pushdown=off'`),可以看到extra列为using where,不会使用索引下推。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210803084815503.png) +![](http://img.dabin-coder.cn/image/image-20210803084815503.png) ### using temporary @@ -314,7 +314,7 @@ from t_order where user_id > 1 and user_id < 5\G; - select 查询字段不全是索引字段 - select 查询字段都是索引字段,但是 order by 字段和索引字段的顺序不一致 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210804084029239.png) +![](http://img.dabin-coder.cn/image/image-20210804084029239.png) ### using join buffer diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" index 7caa4e5..d66e18c 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" @@ -138,7 +138,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821165019147.png) +![](http://img.dabin-coder.cn/image/image-20210821165019147.png) 进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的数据项。 @@ -170,15 +170,15 @@ Index_comment: 如下图,col1 是主键,col2和col3是普通字段。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234137916.png) +![](http://img.dabin-coder.cn/image/image-20200520234137916.png) 下图是主键索引对应的 B+树结构,每个节点对应磁盘的一页。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234200868.png) +![](http://img.dabin-coder.cn/image/image-20200520234200868.png) 对col3 建立一个单列索引,对应的B+树结构: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20200520234231001.png) +![](http://img.dabin-coder.cn/image/image-20200520234231001.png) ### 索引分类 1. 主键索引:名为primary的唯一非空索引,不允许有空值。 @@ -208,7 +208,7 @@ Index_comment: 对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会对b进行比较排序)。直接执行`b = 2`这种查询条件没有办法利用索引。 -![最左匹配](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210821103313578.png) +![最左匹配](http://img.dabin-coder.cn/image/image-20210821103313578.png) 从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行`a = 1 and b = 2`是a,b字段能用到索引的。而你执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。 @@ -218,7 +218,7 @@ InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的 聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-clustered-index.png) +![](http://img.dabin-coder.cn/image/mysql-clustered-index.png) 对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。 @@ -244,7 +244,7 @@ explain select user_id from user_like where blog_id = 1; Extra中为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](http://img.dabin-coder.cn/image/cover-index.png) ### 索引失效 @@ -322,7 +322,7 @@ MEMORY引擎默认使用哈希索引,将键的哈希值和指向数据行的 myisam引擎主键索引和其他索引区别不大,叶子节点都包含索引值和行指针。 innodb引擎二级索引叶子存储的是索引值和主键值(不是行指针),这样可以减少行移动和数据页分裂时二级索引的维护工作。 - ![myisam-innodb-index](https://raw.githubusercontent.com/Tyson0314/img/master/myisam-innodb-index.png) + ![myisam-innodb-index](http://img.dabin-coder.cn/image/myisam-innodb-index.png) @@ -351,7 +351,7 @@ mvcc实现依赖于版本链,版本链是通过表的三个隐藏字段实现 3. 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链; 4. 记录redo log; -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc-impl.png) +![](http://img.dabin-coder.cn/image/mvcc-impl.png) ### read view @@ -388,14 +388,14 @@ repeatable read:在一个事务范围内,第一次select时更新这个read_ 事务a和事务b同时开启事务,事务a插入数据然后提交,事务b执行全表的update,然后执行查询,查到了事务A中添加的数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](http://img.dabin-coder.cn/image/幻读1.png) MySQL如何实现避免幻读: - 在快照读情况下,MySQL通过mvcc来避免幻读。 - 在当前读情况下,MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/current-read.png) +![](http://img.dabin-coder.cn/image/current-read.png) next-key包括两部分:行锁和间隙锁。行锁是加在索引上的锁,间隙锁是加在索引之间的。 @@ -531,7 +531,7 @@ MySQL主要分为 Server 层和存储引擎层: - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 - **存储引擎**: 主要负责数据的存储和读取。server 层通过api与存储引擎进行通信。 -![MySQL-archpng](https://raw.githubusercontent.com/Tyson0314/img/master/mysql-archpng.png) +![MySQL-archpng](http://img.dabin-coder.cn/image/mysql-archpng.png) ### Server 层基本组件 diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" index 6f12608..123d7cc 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" @@ -132,7 +132,7 @@ utf8 就像是阉割版的utf8mb4,只支持部分字符。比如`emoji`表情 通过`SHOW COLLATION WHERE Charset = 'utf8mb4';`可以查看到`utf8mb4`下支持什么比较规则。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220527084528.png) +![](http://img.dabin-coder.cn/image/20220527084528.png) 如果`collation = utf8mb4_general_ci`,是指使用utf8mb4字符集的前提下,**挨个字符进行比较**(`general`),并且不区分大小写(`_ci,case insensitice`)。 @@ -201,7 +201,7 @@ B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B 在 B+ 树中,节点中的 `key` 从左到右递增排列,如果某个指针的左右相邻 `key` 分别是 keyi 和 keyi+1,则该指针指向节点的所有 `key` 大于等于 keyi 且小于等于 keyi+1。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/B+树索引0.png) +![](http://img.dabin-coder.cn/image/B+树索引0.png) 进行查找操作时,首先在根节点进行二分查找,找到`key`所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出`key`所对应的数据项。 @@ -273,7 +273,7 @@ ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...); 如下图,对(a, b) 建立索引,a 在索引树中是全局有序的,而 b 是全局无序,局部有序(当a相等时,会根据b进行排序)。直接执行`b = 2`这种查询条件无法使用索引。 -![最左前缀](https://raw.githubusercontent.com/Tyson0314/img/master/最左前缀.png) +![最左前缀](http://img.dabin-coder.cn/image/最左前缀.png) 当a的值确定的时候,b是有序的。例如`a = 1`时,b值为1,2是有序的状态。当`a = 2`时候,b的值为1,4也是有序状态。 当执行`a = 1 and b = 2`时a和b字段能用到索引。而执行`a > 1 and b = 2`时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段无法使用索引。 @@ -307,7 +307,7 @@ explain select user_id from user_like where blog_id = 1; `explain`结果的`Extra`列为`Using where; Using index`, 查询的列被索引覆盖,where筛选条件不符合最左前缀原则,无法通过索引查找找到符合条件的数据,但可以通过**索引扫描**找到符合条件的数据,也不需要回表查询数据。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/cover-index.png) +![](http://img.dabin-coder.cn/image/cover-index.png) ### 索引的设计原则? @@ -417,7 +417,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 每条表记录大概是这样的: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc9.png) +![](http://img.dabin-coder.cn/image/mvcc9.png) 使用事务更新行记录的时候,就会生成版本链,执行过程如下: @@ -429,15 +429,15 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、初始数据如下,其中`DB_ROW_ID`和`DB_ROLL_PTR`为空。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc2.png) +![](http://img.dabin-coder.cn/image/mvcc2.png) 2、事务A对该行数据做了修改,将`age`修改为12,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc7.png) +![](http://img.dabin-coder.cn/image/mvcc7.png) 3、之后事务B也对该行记录做了修改,将`age`修改为8,效果如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/mvcc11.png) +![](http://img.dabin-coder.cn/image/mvcc11.png) 4、此时undo log有两行记录,并且通过回滚指针连在一起。 @@ -457,7 +457,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 **前提**:`DATA_TRX_ID` 表示每个数据行的最新的事务ID;`up_limit_id`表示当前快照中的最先开始的事务;`low_limit_id`表示当前快照中的最慢开始的事务,即最后一个事务。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/read_view10.png) +![](http://img.dabin-coder.cn/image/read_view10.png) - 如果`DATA_TRX_ID` < `up_limit_id`:说明在创建`read view`时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。 - 如果`DATA_TRX_ID` >= `low_limit_id`:说明当前版本的记录的事务是在创建`read view`之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。 @@ -482,7 +482,7 @@ MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实 1、首先,user表只有两条记录,具体如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210922232259664.png) +![](http://img.dabin-coder.cn/image/image-20210922232259664.png) 2、事务a和事务b同时开启事务`start transaction`; @@ -500,7 +500,7 @@ update user set user_name = 'a'; 5、事务b然后执行查询,查到了事务a中插入的数据。(下图左边是事务b,右边是事务a。事务开始之前只有两条记录,事务a插入一条数据之后,事务b查询出来是三条数据) -![](https://raw.githubusercontent.com/Tyson0314/img/master/幻读1.png) +![](http://img.dabin-coder.cn/image/幻读1.png) 以上就是当前读出现的幻读现象。 @@ -579,7 +579,7 @@ MySQL主要分为 Server 层和存储引擎层: 垂直划分数据库是根据业务进行划分,例如购物场景,可以将库中涉及商品、订单、用户的表分别划分出成一个库,通过降低单库的大小来提高性能。同样的,分表的情况就是将一个大表根据业务功能拆分成一个个子表,例如商品基本信息和商品描述,商品基本信息一般会展示在商品列表,商品描述在商品详情页,可以将商品基本信息和商品描述拆分成两张表。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/垂直划分.png) +![](http://img.dabin-coder.cn/image/垂直划分.png) **优点**:行记录变小,数据页可以存放更多记录,在查询时减少I/O次数。 @@ -593,7 +593,7 @@ MySQL主要分为 Server 层和存储引擎层: 水平划分是根据一定规则,例如时间或id序列值等进行数据的拆分。比如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,从而提升性能。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/水平划分.png) +![](http://img.dabin-coder.cn/image/水平划分.png) **优点**:单库(表)的数据量得以减少,提高性能;切分出的表结构相同,程序改动较少。 @@ -925,4 +925,4 @@ B+树中**非叶子节点存的是key + 指针**;**叶子节点存的是数据 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" index 49f4bc0..5dddfd8 100644 --- "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" @@ -152,4 +152,4 @@ mybatis底层使用`PreparedStatement`,默认情况下,将对所有的 sql -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index 6eba065..7e70a4c 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -28,7 +28,7 @@ SpringBoot实现自动配置原理图解: > 公众号【程序员大彬】,回复【自动配置】下载高清图片 -![](https://raw.githubusercontent.com/Tyson0314/img/master/SpringBoot的自动配置原理.jpg) +![](http://img.dabin-coder.cn/image/SpringBoot的自动配置原理.jpg) 在 application.properties 中设置属性 debug=true,可以在控制台查看已启用和未启用的自动配置。 @@ -297,4 +297,4 @@ hello.msg=大彬 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" index 7a75bb4..aedbd7f 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ "b/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" @@ -1485,7 +1485,7 @@ OAuth在"客户端"(云冲印)与"服务提供商"(谷歌)之间,设 "客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220530233149.png) +![](http://img.dabin-coder.cn/image/20220530233149.png) (A)用户打开客户端以后,客户端要求用户给予授权。 diff --git "a/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" index 82aca97..0892077 100644 --- "a/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" @@ -86,4 +86,4 @@ Spring MVC的工作原理如下: -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" index 697a649..82c11b5 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" @@ -184,7 +184,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](https://raw.githubusercontent.com/Tyson0314/img/master/bean生命周期.png) +![](http://img.dabin-coder.cn/image/bean生命周期.png) 1.调用bean的构造方法创建Bean @@ -272,29 +272,124 @@ Spring 将会在应用启动时创建 `SqlSessionFactory`,并使用 `sqlSessio ## Bean注入容器有哪些方式? -将普通类交给Spring容器管理,通常有以下方法: +1、@Configuration + @Bean -1、使用`@Configuration`与`@Bean`注解 +@Configuration用来声明一个配置类,然后使用 @Bean 注解,用于声明一个bean,将其加入到Spring容器中。 -2、使用`@Controller`、`@Service`、`@Repository`、`@Component` 注解标注该类,然后启用`@ComponentScan`自动扫描 +```java +@Configuration +public class MyConfiguration { + @Bean + public Person person() { + Person person = new Person(); + person.setName("大彬"); + return person; + } +} +``` + +2、通过包扫描特定注解的方式 + +@ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有特定注解的bean,然后加至容器中。 + +特定注解包括@Controller、@Service、@Repository、@Component + +```java +@Component +public class Person { + //... +} + +@ComponentScan(basePackages = "com.dabin.test.*") +public class Demo1 { + public static void main(String[] args) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class); + Person bean = applicationContext.getBean(Person.class); + System.out.println(bean); + } +} +``` + +3、@Import注解导入 -3、使用`@Import` 方法。使用@Import注解把bean导入到当前容器中,代码如下: +@Import注解平时开发用的不多,但是也是非常重要的,在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。 ```java -//@SpringBootApplication @ComponentScan /*把用到的资源导入到当前容器中*/ -@Import({Dog.class, Cat.class}) +@Import({Person.class}) public class App { public static void main(String[] args) throws Exception { ConfigurableApplicationContext context = SpringApplication.run(App.class, args); - System.out.println(context.getBean(Dog.class)); - System.out.println(context.getBean(Cat.class)); + System.out.println(context.getBean(Person.class)); context.close(); } } ``` +4、实现BeanDefinitionRegistryPostProcessor进行后置处理。 + +在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。 + +在下面的代码中,我们手动向beanDefinitionRegistry中注册了person的BeanDefinition。最终成功将person加入到applicationContext中。 + +```java +public class Demo1 { + public static void main(String[] args) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor(); + applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor); + applicationContext.refresh(); + Person bean = applicationContext.getBean(Person.class); + System.out.println(bean); + } +} + +class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition(); + registry.registerBeanDefinition("person", beanDefinition); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + } +} +``` + +5、使用FactoryBean接口 + +如下图代码,使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,这里没有向容器中直接注入 Person,而是注入 PersonFactoryBean,然后从容器中拿Person这个类型的bean。 + +```java +@Configuration +public class Demo1 { + @Bean + public PersonFactoryBean personFactoryBean() { + return new PersonFactoryBean(); + } + + public static void main(String[] args) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class); + Person bean = applicationContext.getBean(Person.class); + System.out.println(bean); + } +} + +class PersonFactoryBean implements FactoryBean { + @Override + public Person getObject() throws Exception { + return new Person(); + } + + @Override + public Class getObjectType() { + return Person.class; + } +} +``` + ## Bean的作用域 @@ -347,7 +442,7 @@ Spring的自动装配有三种模式:**byType**(根据类型),**byName**(根 ## @Autowired和@Resource的区别? -默认情况下@Autowired是按类型匹配的(byType)。如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。@Autowired 可以传递一个`required=false`的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。 +Autowire是spring的注解。默认情况下@Autowired是按类型匹配的(byType)。如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。@Autowired 可以传递一个`required=false`的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。 ```java public class UserServiceImpl implements UserService { @@ -358,7 +453,7 @@ public class UserServiceImpl implements UserService { } ``` -@Resource,默认按 byName模式自动注入。@Resource有两个中重要的属性:name和type。Spring容器对于@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。 +Resource是j2ee的注解,默认按 byName模式自动注入。@Resource有两个中重要的属性:name和type。name属性指定bean的名字,type属性则指定bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性,则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。 ```java @Resource(name="userDao") @@ -371,9 +466,11 @@ public void setUserDao(UserDao userDao) { } ``` -上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式。@Value接收一个String的值,该值指定了将要被注入到内置的java类型属性值,Spring 容器会做好类型转换。一般情况下@Value会与properties文件结合使用。 +上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式。 + +@Value和@Autowired、@Resource类似,也是用来对属性进行注入的,只不过@Value是用来从Properties文件中来获取值的,并且@Value可以解析SpEL(Spring表达式)。 -jdbc.properties文件如下: +比如,jdbc.properties文件如下: ```properties jdbc.driver=com.mysql.jdbc.Driver @@ -478,7 +575,97 @@ public class WebSocketConfig { 使用`PROPAGATION_NESTED`时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。 +## Spring事务在什么情况下会失效? + +**1.访问权限问题** + +java的访问权限主要有四种:private、default、protected、public,它们的权限从左到右,依次变大。 + +如果事务方法的访问权限不是定义成public,这样会导致事务失效,因为spring要求被代理方法必须是`public`的。 +翻开源码,可以看到,在`AbstractFallbackTransactionAttributeSource`类的`computeTransactionAttribute`方法中有个判断,如果目标方法不是public,则返回null,即不支持事务。 + +```java +protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) { + // Don't allow no-public methods as required. + if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { + return null; + } + ... +} +``` + +**2. 方法用final修饰** + +如果事务方法用final修饰,将会导致事务失效。因为spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。 + +但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。 + +> 同理,如果某个方法是static的,同样无法通过动态代理,变成事务方法。 + +**3.对象没有被spring管理** + +使用spring事务的前提是:对象要被spring管理,需要创建bean实例。如果类没有加@Controller、@Service、@Component、@Repository等注解,即该类没有交给spring去管理,那么它的方法也不会生成事务。 + +**4.表不支持事务** + +如果MySQL使用的存储引擎是myisam,这样的话是不支持事务的。因为myisam存储引擎不支持事务。 + +**5.方法内部调用** + +如下代码所示,update方法上面没有加 `@Transactional` 注解,调用有 `@Transactional` 注解的 updateOrder 方法,updateOrder 方法上的事务会失效。 + +因为发生了自身调用,调用该类自己的方法,而没有经过 Spring 的代理类,只有在外部调用事务才会生效。 + +```java +@Service +public class OrderServiceImpl implements OrderService { + + public void update(Order order) { + this.updateOrder(order); + } + + @Transactional + public void updateOrder(Order order) { + // update order + } +} +``` + +解决方法: + +1、再声明一个service,将内部调用改为外部调用 + +2、使用编程式事务 + +3、使用AopContext.currentProxy()获取代理对象 + +```java +@Servcie +public class OrderServiceImpl implements OrderService { + + public void update(Order order) { + ((OrderService)AopContext.currentProxy()).updateOrder(order); + } + + @Transactional + public void updateOrder(Order order) { + // update order + } + } +``` + +**6.未开启事务** + +如果是spring项目,则需要在配置文件中手动配置事务相关参数。如果忘了配置,事务肯定是不会生效的。 + +如果是springboot项目,那么不需要手动配置。因为springboot已经在`DataSourceTransactionManagerAutoConfiguration`类中帮我们开启了事务。 + +**7.吞了异常** + +有时候事务不会回滚,有可能是在代码中手动catch了异常。因为开发者自己捕获了异常,又没有手动抛出,把异常吞掉了,这种情况下spring事务不会回滚。 + +如果想要spring事务能够正常回滚,必须抛出它能够处理的异常。如果没有抛异常,则spring认为程序是正常的。 ## Spring怎么解决循环依赖的问题? @@ -583,6 +770,147 @@ Spring的Bean默认都是单例的,某些情况下,单例是并发不安全 如果还要进一步考虑到微服务或分布式服务的影响,方式3便不合适了。这种情况下可以借助于可以共享某些信息的分布式缓存中间件,如Redis等。这样即可保证同一种服务的不同服务实例都拥有同一份共享信息了。 +## @Async注解的原理 + +当我们调用第三方接口或者方法的时候,我们不需要等待方法返回才去执行其它逻辑,这时如果响应时间过长,就会极大的影响程序的执行效率。所以这时就需要使用异步方法来并行执行我们的逻辑。在springboot中可以使用@Async注解实现异步操作。 + +使用@Async注解实现异步操作的步骤: + +1.首先在启动类上添加 @EnableAsync 注解。 + +```java +@Configuration +@EnableAsync +public class App { + public static void main(String[] args) { + ApplicationContext ctx = new + AnnotationConfigApplicationContext(App.class); + MyAsync service = ctx.getBean(MyAsync.class); + System.out.println(service.getClass()); + service.async1(); + System.out.println("main thread finish..."); + } +} +``` + +2.在对应的方法上添加@Async注解。 + +```java +@Component +public class MyAsync { + @Async + public void asyncTest() { + try { + TimeUnit.SECONDS.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("asyncTest..."); + } +} +``` + +运行代码,控制台输出: + +```java +main thread finish... +asyncTest... +``` + +证明asyncTest方法异步执行了。 + +原理: + +我们在主启动类上贴了一个@EnableAsync注解,才能使用@Async生效。@EnableAsync的作用是通过@import导入了AsyncConfigurationSelector。在AsyncConfigurationSelector的selectImports方法将ProxyAsyncConfiguration定义为Bean注入容器。在ProxyAsyncConfiguration中通过@Bean的方式注入AsyncAnnotationBeanPostProcessor类。 + +![](http://img.dabin-coder.cn/image/20220628224208.png) + +代码如下: + +```java +@Import(AsyncConfigurationSelector.class) +public @interface EnableAsync { +} + +public class AsyncConfigurationSelector extends AdviceModeImportSelector { + public String[] selectImports(AdviceMode adviceMode) { + switch (adviceMode) { + case PROXY: + return new String[] { ProxyAsyncConfiguration.class.getName() }; + //... + } + } +} + +public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration { + @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME) + public AsyncAnnotationBeanPostProcessor asyncAdvisor() { + //创建postProcessor + AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor(); + //... + } +} +``` + +AsyncAnnotationBeanPostProcessor往往期创建了一个增强器AsyncAnnotationAdvisor。在AsyncAnnotationAdvisor的buildAdvice方法中,创建了AnnotationAsyncExecutionInterceptor。 + +```java +public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor { + @Override + public void setBeanFactory(BeanFactory beanFactory) { + super.setBeanFactory(beanFactory); + //创建一个增强器 + AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler); + //... + advisor.setBeanFactory(beanFactory); + this.advisor = advisor; + } +} + + +public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { + public AsyncAnnotationAdvisor( + @Nullable Supplier executor, @Nullable Supplier exceptionHandler) { + //增强方法 + this.advice = buildAdvice(executor, exceptionHandler); + this.pointcut = buildPointcut(asyncAnnotationTypes); + } + + // 委托给AnnotationAsyncExecutionInterceptor拦截器 + protected Advice buildAdvice( + @Nullable Supplier executor, @Nullable Supplier exceptionHandler) { + //拦截器 + AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null); + interceptor.configure(executor, exceptionHandler); + return interceptor; + } +} +``` + +AnnotationAsyncExecutionInterceptor继承自AsyncExecutionInterceptor,间接实现了MethodInterceptor。该拦截器的实现的invoke方法把原来方法的调用提交到新的线程池执行,从而实现了方法的异步。 + +```java +public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered { + public Object invoke(final MethodInvocation invocation) throws Throwable { + //... + //构建放到AsyncTaskExecutor执行Callable Task + Callable task = () -> { + //... + }; + //提交到新的线程池执行 + return doSubmit(task, executor, invocation.getMethod().getReturnType()); + } +} +``` + +由上面分析可以看到,@Async注解其实是通过代理的方式来实现异步调用的。 + +那使用@Async有什么要注意的呢? + +1.使用@Aysnc的时候最好配置一个线程池Executor以让线程复用节省资源,或者为SimpleAsyncTaskExecutor设置基于线程池实现的ThreadFactory,在否则会默认使用SimpleAsyncTaskExecutor,该executor会在每次调用时新建一个线程。 + +2.调用本类的异步方法是不会起作用的。这种方式绕过了代理而直接调用了方法,@Async注解会失效。 + -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" index 885806d..70a08a9 100644 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" @@ -80,5 +80,5 @@ 后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) +![](http://img.dabin-coder.cn/image/公众号.jpg) diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" index 5b480ae..c2ac733 100644 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" +++ "b/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" @@ -47,7 +47,7 @@ 3. 将位图中对应的位设置为 1,即arr[2] = arr[2] **|** 000..00010000。 4. 这就将电话号码映射到了位图的某一位了。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423094735.png) +![](http://img.dabin-coder.cn/image/20220423094735.png) 最后,统计位图中bit值为1的数量,便能得到不同电话号码的个数了。 diff --git "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" "b/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" similarity index 98% rename from "\344\270\255\351\227\264\344\273\266/RabbitMQ.md" rename to "\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" index 4c51d3e..c89865f 100644 --- "a/\344\270\255\351\227\264\344\273\266/RabbitMQ.md" +++ "b/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" @@ -33,7 +33,7 @@ RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq.png) +![](http://img.dabin-coder.cn/image/rabbitmq.png) ## 基本概念 @@ -82,19 +82,19 @@ Exchange规则。 direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-direct.png) +![](http://img.dabin-coder.cn/image/rabbitmq-direct.png) ## fanout 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-fanout.png) +![](http://img.dabin-coder.cn/image/rabbitmq-fanout.png) ## topic topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/rabbitmq-topic.png) +![](http://img.dabin-coder.cn/image/rabbitmq-topic.png) ## headers @@ -420,4 +420,4 @@ msg.getMessageProperties().setExpiration("3000"); -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\344\270\255\351\227\264\344\273\266/\346\255\273\344\277\241\351\230\237\345\210\227.md" "b/\346\266\210\346\201\257\351\230\237\345\210\227/\346\255\273\344\277\241\351\230\237\345\210\227.md" similarity index 100% rename from "\344\270\255\351\227\264\344\273\266/\346\255\273\344\277\241\351\230\237\345\210\227.md" rename to "\346\266\210\346\201\257\351\230\237\345\210\227/\346\255\273\344\277\241\351\230\237\345\210\227.md" diff --git "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" "b/\346\266\210\346\201\257\351\230\237\345\210\227/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" similarity index 99% rename from "\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" rename to "\346\266\210\346\201\257\351\230\237\345\210\227/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" index bfbacf6..90a7b0b 100644 --- "a/\344\270\255\351\227\264\344\273\266/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" +++ "b/\346\266\210\346\201\257\351\230\237\345\210\227/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" @@ -69,4 +69,4 @@ -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png) \ No newline at end of file +![](http://img.dabin-coder.cn/image/20220612101342.png) \ No newline at end of file diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" index 93f6591..9b2fa63 100644 --- "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" @@ -54,7 +54,7 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P 大彬:这个阶段是交互过程如下图所示。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220411002823.png) +![](http://img.dabin-coder.cn/image/20220411002823.png) **3、已确认** @@ -66,7 +66,7 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P 这个阶段是交互过程如下图所示。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220411002832.png) +![](http://img.dabin-coder.cn/image/20220411002832.png) 大彬:以上就是整个扫码登录功能的详细设计! @@ -82,4 +82,4 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P 后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/公众号.jpg) +![](http://img.dabin-coder.cn/image/公众号.jpg) diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" index 036738f..7b0003c 100644 --- "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" +++ "b/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" @@ -98,7 +98,7 @@ The document has moved Date: Sun, 30 Oct 2022 17:28:42 +0800 Subject: [PATCH 10/84] update1030 --- README.md | 154 ++-- ...76\350\256\241\346\250\241\345\274\217.md" | 714 ++++++++++++++---- .../docker-overview.md" | 0 .../git-overview.md" | 0 "\345\267\245\345\205\267/linux-overview.md" | 647 ++++++++++++++++ .../maven-overview.md" | 0 .../RabbitMQ.md" | 103 +-- .../kafka.md" | 168 +++++ 8 files changed, 1505 insertions(+), 281 deletions(-) rename "\345\267\245\345\205\267/docker.md" => "\345\267\245\345\205\267/docker-overview.md" (100%) rename "\345\267\245\345\205\267/progit2.md" => "\345\267\245\345\205\267/git-overview.md" (100%) create mode 100644 "\345\267\245\345\205\267/linux-overview.md" rename "\345\267\245\345\205\267/Maven\345\256\236\346\210\230.md" => "\345\267\245\345\205\267/maven-overview.md" (100%) create mode 100644 "\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" diff --git a/README.md b/README.md index 21e4c06..3ea05f6 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,14 @@ [点击此处](https://zhuanlan.zhihu.com/p/395162772) 查看我的**自学路线**。 +# 面试网站 + +大彬自己搭建了一个**小破站**,将**本仓库所有的面试题**都整理到小破站了,欢迎大家访问~ + +网站地址:https://topjavaer.cn + +![](http://img.dabin-coder.cn/image/image-20221030165150524.png) + # 仓库简介 **本仓库用于分享互联网大厂高频面试题、Java核心知识总结,包括Java基础、并发、MySQL、Springboot、MyBatis、Redis、RabbitMQ等等,面试必备!** @@ -30,6 +38,7 @@

+ # 简历很重要 [简历投递之后总是石沉大海?](https://zhuanlan.zhihu.com/p/406982597) @@ -42,25 +51,6 @@ - [Java优质项目推荐](https://www.zhihu.com/question/325011850/answer/2257046656) - [优质视频教程推荐](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247487149&idx=1&sn=aa883c9f020945d3f210550bd688c7d0&chksm=ce98f3ebf9ef7afdae0b37c4d0751806b0fbbf08df783fba536e5ec20ec6a6e1512198dc6206&token=104697471&lang=zh_CN#rd)(推荐 :+1:) -# 大厂面试系列 - -1. [字节跳动一面面经](https://mp.weixin.qq.com/s/RH-SunzjqUTTx8HWaCmCcw) -2. [别再问我Java List八股文了!](https://mp.weixin.qq.com/s/doyy_GYGWoH_YHgyMijStA) -3. [腾讯面试,你真的懂HTTP吗?](https://mp.weixin.qq.com/s/kC7XRBfO7Z5hZcX6Dz2viw) -4. [美团二面面经,最后竟然有惊喜?](https://mp.weixin.qq.com/s/3HvOtTU29HGALqmeeOZNWw) -5. [Java多线程,被面试官难倒了!](https://mp.weixin.qq.com/s/tv8pOLaS6hpwgbKOB9w0Zw) -6. [京东二面,Redis为什么这么快?](https://mp.weixin.qq.com/s/S3vN5T9HpziRd2s5ysLaSg) -7. [MySQL索引,给我整不会了!](https://mp.weixin.qq.com/s/Q5CrDlNInpnckJaBQSrA7w) -8. [别再问我Java虚拟机八股文了!](https://mp.weixin.qq.com/s/npo5-VqQt5sqZiSwPv6LVw) -9. [计算机网络,问傻了!](https://mp.weixin.qq.com/s/WXcMLa_tdxpRLhO4U8LHIQ) -10. [Spring这几道题你会吗?](https://mp.weixin.qq.com/s/DtgYRFfOQxQdtQosCU-6aw) -10. [面向对象编程?](https://mp.weixin.qq.com/s/M8jDnLat61YAbM1-jIhJIA) -10. [Java内功深厚?](https://mp.weixin.qq.com/s/v_kWSHX9GMS_aoqfwUMKsg) -10. [面试初级Java开发,面试官问我MySQL架构?](https://mp.weixin.qq.com/s/JvDZCk4IecmaEYfFsRhpjQ) -10. [手写红黑树?](https://mp.weixin.qq.com/s/yznh_IfMg4hWqU62U-t9GQ) -10. [面完阿里,直接入职!](https://mp.weixin.qq.com/s/49QJ1FzaGTe-_54PT8_8jA) -10. [华为面经](https://mp.weixin.qq.com/s/KmjwoG7pNvAHiX1UNnef6g) - # Java ## 基础 @@ -86,20 +76,23 @@ 1. [【大厂面试】—— MySQL高频面试题50道](数据库/MySQL高频面试题.md)(**知乎1k+收藏,推荐** :+1:) 2. [图解索引下推](https://mp.weixin.qq.com/s/W1XQYmihtSdbLWQKeNwZvQ)(推荐 :+1:) -3. [MySQL执行计划](数据库/MySQL执行计划.md)(推荐 :+1:) +3. [MySQL执行计划详解](数据库/MySQL执行计划.md)(推荐 :+1:) ## Redis 1. [【大厂面试】——Redis30问](Redis/Redis面试题.md)(牛客高赞,推荐 :+1:) -2. [Redis分布式锁(推荐 :+1:)](Redis/Redis分布式锁.md) -4. [缓存穿透、缓存雪崩、缓存击穿](Redis/缓存穿透、缓存雪崩、缓存击穿.md) +2. [缓存穿透、缓存雪崩、缓存击穿](Redis/缓存穿透、缓存雪崩、缓存击穿.md) + +## ElasticSearch + +1. [ElasticSearch高频面试题](https://mp.weixin.qq.com/s/Ffb8NDgavf9QAWYBm0qAVg) # 框架 ## Spring 1. [Spring高频面试题30道](框架/Spring面试题.md)(推荐 :+1:) -3. [Spring用到哪些设计模式?](框架/Spring用到哪些设计模式.md) +2. [Spring用到哪些设计模式?](框架/Spring用到哪些设计模式.md) ## Spring Boot @@ -121,60 +114,116 @@ ## SpringCloud +[[SpringCloud面试题](https://topjavaer.cn/framework/springcloud-interview.html)(推荐 :+1:) + [SpringCloud总结](框架/SpringCloud微服务实战.md) ## Netty [Netty实战笔记](框架/netty实战.md) +# 分布式 + +## 微服务 + +[微服务面试题](https://topjavaer.cn/distributed/micro-service.html) + +## RPC + +[RPC面试题](https://topjavaer.cn/distributed/rpc.html) + +## 全局唯一ID + +[全局唯一ID](https://topjavaer.cn/distributed/global-unique-id.html) + +## 分布式事务 + +[分布式事务总结](https://topjavaer.cn/distributed/distributed-transaction.html) + +## 分布式架构 + +[分布式架构演进](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247490543&idx=1&sn=ee34bee96511d5e548381e0576f8b484&chksm=ce98e6a9f9ef6fbf7db9c2b6d2fed26853a3bc13a50c3228ab57bea55afe0772008cdb1f957b&token=1594696656&lang=zh_CN#rd) + +# 高并发 + +## 限流 + +[限流算法总结](https://topjavaer.cn/advance/concurrent/1-current-limiting.html) + +## 负载均衡 + +[负载均衡](https://topjavaer.cn/advance/concurrent/2-load-balance.html) + # 消息队列 ## RabbitMQ 1. [消息队列面试题](消息队列/消息队列面试题.md) -1. [RabbitMQ核心知识总结](消息队列/RabbitMQ.md) (推荐 :+1:) -2. [死信队列](消息队列/死信队列.md) +2. [RabbitMQ面试题总结](消息队列/rabbitmq.md) (推荐 :+1:) +3. [Kafka面试题总结](消息队列/kafka.md) (推荐 :+1:) +4. [死信队列](消息队列/死信队列.md) # 计算机网络 [【大厂面试】—— 计算机网络常见面试题总结](计算机基础/网络/计算机网络高频面试题.md) (**知乎1k+收藏!推荐 :+1:**) -[session和cookie详解](计算机基础/网络/session和cookie.md) - # 数据结构与算法 [如何高效的刷LeetCode?](https://www.zhihu.com/question/280279208/answer/2377906738) -[7种常见的排序算法Java代码实现](计算机基础/数据结构与算法/常见的排序算法Java代码实现.md) +[120道Leetcode题解(高频)](https://topjavaer.cn/leetcode/hot120/) -[二叉树前序、中序、后序、层序遍历代码实现](计算机基础/数据结构与算法/二叉树前序、中序、后序、层序遍历代码实现.md) - -[常见数据结构总结](计算机基础/数据结构与算法/数据结构.md) +[常见数据结构总结](https://topjavaer.cn/computer-basic/data-structure.html) # 设计模式 [字节跳动大佬总结的设计模式PDF](https://t.1yb.co/y96J) -[设计模式总结](其他/设计模式.md) +[设计模式总结](https://topjavaer.cn/advance/design-pattern/) + +# 海量数据场景题 + +1. [统计不同电话号码的个数](https://topjavaer.cn/system-design/1-scan-code-login.html) +2. [出现频率最高的100个词](https://topjavaer.cn/mass-data/2-find-hign-frequency-word.html) +3. [查找两个大文件共同的URL](https://topjavaer.cn/mass-data/3-find-same-url.html) +4. [如何在100亿的数据中找到中位数](https://topjavaer.cn/mass-data/4-find-mid-num.html) +5. [找出最热门的查询串](https://topjavaer.cn/mass-data/5-find-hot-string.html) +6. [如何找出排名前500的数字](https://topjavaer.cn/mass-data/6-top-500-num.html) # 工具 -[Git 超详细总结!](工具/progit2.md)(推荐 :+1:) +[Git 超详细总结!](工具/git-overview.md)(推荐 :+1:) -# 其他精选文章 +[Linux 常用命令总结!](工具/linux-overview.md) -1. [记一次OOM问题排查](https://mp.weixin.qq.com/s/40C1OdtfGJSrecBoL9Mjbg) -2. [推荐一款画图神器](https://mp.weixin.qq.com/s/vDtWku41rpeux8ZhZyA81w) -3. [有哪些值得推荐的Java书籍?](https://mp.weixin.qq.com/s/MUB07APbyDH2-iftGDdGlA) -4. [这款MarkDown神器,要收费啦!](https://mp.weixin.qq.com/s/aCEi-4vb3kNPF0-E4rB5Kg) -5. [在B站学Java](https://mp.weixin.qq.com/s/_xfT2Tr6rT8qSAFrtRQ3wQ) -6. [你见过这样使用Github的吗?](https://mp.weixin.qq.com/s/U_AItugf8KaUPyIun_xagg) +[Docker 基础总结!](工具/docker-overview.md) +[Maven 基础总结!](tools/maven-overview.md) +# 大厂面试系列 -**本仓库持续更新中,欢迎star和pr~** +1. [字节跳动一面面经](https://mp.weixin.qq.com/s/RH-SunzjqUTTx8HWaCmCcw) +2. [别再问我Java List八股文了!](https://mp.weixin.qq.com/s/doyy_GYGWoH_YHgyMijStA) +3. [腾讯面试,你真的懂HTTP吗?](https://mp.weixin.qq.com/s/kC7XRBfO7Z5hZcX6Dz2viw) +4. [美团二面面经,最后竟然有惊喜?](https://mp.weixin.qq.com/s/3HvOtTU29HGALqmeeOZNWw) +5. [Java多线程,被面试官难倒了!](https://mp.weixin.qq.com/s/tv8pOLaS6hpwgbKOB9w0Zw) +6. [京东二面,Redis为什么这么快?](https://mp.weixin.qq.com/s/S3vN5T9HpziRd2s5ysLaSg) +7. [MySQL索引,给我整不会了!](https://mp.weixin.qq.com/s/Q5CrDlNInpnckJaBQSrA7w) +8. [别再问我Java虚拟机八股文了!](https://mp.weixin.qq.com/s/npo5-VqQt5sqZiSwPv6LVw) +9. [计算机网络,问傻了!](https://mp.weixin.qq.com/s/WXcMLa_tdxpRLhO4U8LHIQ) +10. [Spring这几道题你会吗?](https://mp.weixin.qq.com/s/DtgYRFfOQxQdtQosCU-6aw) +11. [面向对象编程?](https://mp.weixin.qq.com/s/M8jDnLat61YAbM1-jIhJIA) +12. [Java内功深厚?](https://mp.weixin.qq.com/s/v_kWSHX9GMS_aoqfwUMKsg) +13. [面试初级Java开发,面试官问我MySQL架构?](https://mp.weixin.qq.com/s/JvDZCk4IecmaEYfFsRhpjQ) +14. [手写红黑树?](https://mp.weixin.qq.com/s/yznh_IfMg4hWqU62U-t9GQ) +15. [面完阿里,直接入职!](https://mp.weixin.qq.com/s/49QJ1FzaGTe-_54PT8_8jA) +16. [华为面经](https://mp.weixin.qq.com/s/KmjwoG7pNvAHiX1UNnef6g) + +# 其他优质文章 +[优质文章汇总,持续更新中~](https://topjavaer.cn/advance/excellent-article/) +![](http://img.dabin-coder.cn/image/image-20221030172546796.png) # 交流 @@ -185,24 +234,27 @@ + # 赞赏 如果觉得**本仓库**对您有帮助的话,可以请大彬**喝一杯咖啡**(小伙伴们赞赏的时候可以备注下哦~) -| 微信 | 支付宝 | -| ----------------------------------------------------------- | ------------------------------------------------------------ | +| 微信 | 支付宝 | +| ------------------------------------------------- | ----------------------------------------------------- | | ![](http://img.dabin-coder.cn/image/微信收款.png) | ![](http://img.dabin-coder.cn/image/支付宝赞赏码.png) | 每笔赞赏我会在下面记录下来,感谢你们,我会更加努力,砥砺前行~ -| 日期 | 来源 | **用户** | **金额** | 备注 | -| ---------- | ------------ | -------- | -------- | ------ | -| 2021.11.19 | 微信收款码 | *张 | 6.66元 | 支持! | -| 2021.11.25 | 支付宝收款码 | *海 | 1元 | | -| 2021.12.10 | 微信收款码 | 浩*y | 10元 | | -| 2021.12.15 | 微信收款码 | biubiu* | 6.66元 | 好 | -| 2022.02.17 | 微信收款码 | *齐 | 8元 | | -| 2022.05.03 | 微信收款码 | *哈 | 2元 | | +| 日期 | 来源 | **用户** | **金额** | 备注 | +| ---------- | ------------ | -------- | -------- | ------------------------ | +| 2021.11.19 | 微信收款码 | *张 | 6.66元 | 支持! | +| 2021.11.25 | 支付宝收款码 | *海 | 1元 | | +| 2021.12.10 | 微信收款码 | 浩*y | 10元 | | +| 2021.12.15 | 微信收款码 | biubiu* | 6.66元 | 好 | +| 2022.02.17 | 微信收款码 | *齐 | 8元 | | +| 2022.05.03 | 微信收款码 | *哈 | 2元 | | +| 2022.06.12 | 微信收款码 | *可 | 8.8元 | | +| 2022.10.19 | 微信收款码 | *斌 | 10元 | 支持一下,希望能持续更新 | diff --git "a/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" index 3808e3a..ebbd8e1 100644 --- "a/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1,27 +1,3 @@ - - - - -- [单例模式](#%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F) - - [饿汉模式](#%E9%A5%BF%E6%B1%89%E6%A8%A1%E5%BC%8F) - - [双重检查锁定](#%E5%8F%8C%E9%87%8D%E6%A3%80%E6%9F%A5%E9%94%81%E5%AE%9A) - - [静态内部类](#%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB) -- [装饰模式](#%E8%A3%85%E9%A5%B0%E6%A8%A1%E5%BC%8F) -- [适配器模式](#%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F) -- [观察者模式](#%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F) -- [代理模式](#%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F) - - [静态代理](#%E9%9D%99%E6%80%81%E4%BB%A3%E7%90%86) - - [动态代理](#%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86) - - [JDK动态代理](#jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86) -- [工厂模式](#%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F) - - [简单工厂模式](#%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F) - - [工厂方法模式](#%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F) - - [抽象工厂模式](#%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F) -- [模板模式](#%E6%A8%A1%E6%9D%BF%E6%A8%A1%E5%BC%8F) -- [建造者模式](#%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F) - - - ## 设计模式的六大原则 - 开闭原则:对扩展开放,对修改关闭,多使用抽象类和接口。 @@ -37,6 +13,10 @@ ### 饿汉模式 +JVM在类的初始化阶段,会执行类的静态方法。在执行类的初始化期间,JVM会去获取Class对象的锁。这个锁可以同步多个线程对同一个类的初始化。 + +饿汉模式只在类加载的时候创建一次实例,没有多线程同步的问题。单例没有用到也会被创建,而且在类加载之后就被创建,内存就被浪费了。 + ``` public class Singleton { private static Singleton instance = new Singleton(); @@ -46,12 +26,10 @@ public class Singleton { } } ``` -JVM在类的初始化阶段,会执行类的静态方法。在执行类的初始化期间,JVM会去获取Class对象的锁。这个锁可以同步多个线程对同一个类的初始化。 - -饿汉模式只在类加载的时候创建一次实例,没有多线程同步的问题。单例没有用到也会被创建,而且在类加载之后就被创建,内存就被浪费了。 - ### 双重检查锁定 +双重校验锁先判断 instance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。 + instance使用static修饰的原因:getInstance为静态方法,因为静态方法的内部不能直接使用非静态变量,只有静态成员才能在没有创建对象时进行初始化,所以返回的这个实例必须是静态的。 ``` @@ -104,6 +82,12 @@ instance = memory;   // 3:设置instance指向刚分配的内存地址 ### 静态内部类 +它与饿汉模式一样,也是利用了类初始化机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。 + +![](http://img.dabin-coder.cn/image/singleton-class-init.png) + +基于类初始化的方案的实现代码更简洁。 + ``` public class Instance { private static class InstanceHolder { @@ -115,62 +99,564 @@ public class Instance { } } ``` -它与饿汉模式一样,也是利用了类初始化机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。 +但基于volatile的双重检查锁定的方案有一个额外的优势:除了可以对静态字段实现延迟初始化外,还可以对实例字段实现延迟初始化。字段延迟初始化降低了初始化类或创建实例的开销,但增加了访问被延迟初始化的字段的开销。在大多数时候,正常的初始化要优于延迟初始化。 + +## 工厂模式 + +工厂模式是用来封装对象的创建。 + +### 简单工厂模式 + +把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化,这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。 + +```java + public class ShapeFactory { + public static final String TAG = "ShapeFactory"; + public static Shape getShape(String type) { + Shape shape = null; + if (type.equalsIgnoreCase("circle")) { + shape = new CircleShape(); + } else if (type.equalsIgnoreCase("rect")) { + shape = new RectShape(); + } else if (type.equalsIgnoreCase("triangle")) { + shape = new TriangleShape(); + } + return shape; + } + } +``` + +优点:只需要一个工厂创建对象,代码量少。 + +缺点:系统扩展困难,新增产品需要修改工厂逻辑,当产品较多时,会造成工厂逻辑过于复杂,不利于系统扩展和维护。 + +### 工厂方法模式 + +针对不同的对象提供不同的工厂。每个对象都有一个与之对应的工厂。 + +```java +public interface Reader { + void read(); +} + +public class JpgReader implements Reader { + @Override + public void read() { + System.out.print("read jpg"); + } +} + +public class PngReader implements Reader { + @Override + public void read() { + System.out.print("read png"); + } +} + +public interface ReaderFactory { + Reader getReader(); +} + +public class JpgReaderFactory implements ReaderFactory { + @Override + public Reader getReader() { + return new JpgReader(); + } +} + +public class PngReaderFactory implements ReaderFactory { + @Override + public Reader getReader() { + return new PngReader(); + } +} +``` + +客户端通过子类来指定创建对应的对象。 + +```java +ReaderFactory factory=new JpgReaderFactory(); +Reader reader=factory.getReader(); +reader.read(); +``` + +优点:增加新的产品类时无须修改现有系统,只需增加新产品和对应的工厂类即可。 + +### 抽象工厂模式 + +抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 + +多了一层抽象,减少了工厂的数量(HpMouseFactory和HpKeyboFactory合并为HpFactory)。 + +![](http://img.dabin-coder.cn/image/抽象工厂.png) + + + +## 模板模式 + +模板模式:一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 这种类型的设计模式属于行为型模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 + +**模板模式**主要由抽象模板(Abstract Template)角色和具体模板(Concrete Template)角色组成。 + +- 抽象模板(Abstract Template): 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。 +- 具体模板(Concrete Template): 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。 + +示例图如下: + +![](http://img.dabin-coder.cn/image/模板方法.jpg) + +以游戏为例。创建一个抽象类,它的模板方法被设置为 final,这样它就不会被重写。 + +```java +public abstract class Game { + abstract void initialize(); + abstract void startPlay(); + abstract void endPlay(); + + //模板 + public final void play(){ + //初始化游戏 + initialize(); + + //开始游戏 + startPlay(); + + //结束游戏 + endPlay(); + } +} +``` + +Football类: + +```java +public class Football extends Game { + + @Override + void endPlay() { + System.out.println("Football Game Finished!"); + } + + @Override + void initialize() { + System.out.println("Football Game Initialized! Start playing."); + } + + @Override + void startPlay() { + System.out.println("Football Game Started. Enjoy the game!"); + } +} +``` + +使用Game的模板方法 play() 来演示游戏的定义方式。 + +```java +public class TemplatePatternDemo { + public static void main(String[] args) { + + Game game = new Cricket(); + game.play(); + System.out.println(); + game = new Football(); + game.play(); + } +} +``` + +**模板模式优点** : + +1. 封装不变部分,扩展可变部分。 +2. 提取公共代码,便于维护。 +3. 行为由父类控制,子类实现。 + +**模板模式缺点**: + +- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。 + +## 策略模式 + +策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。 + +其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。 + +**策略模式**主要由这三个角色组成,环境角色(Context)、抽象策略角色(Strategy)和具体策略角色(ConcreteStrategy)。 + +- 环境角色(Context):持有一个策略类的引用,提供给客户端使用。 +- 抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 +- 具体策略角色(ConcreteStrategy):包装了相关的算法或行为。 + +示例图如下: + +![](http://img.dabin-coder.cn/image/策略模式.png) + +以计算器为例,如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。 + +但是在这些方法中,我们发现其基本方法是固定的,这时我们就可以通过策略模式来进行开发,可以有效避免通过if/else来进行判断,即使后续增加其他的计算规则也可灵活进行调整。 + +首先定义一个抽象策略角色,并拥有一个计算的方法。 + +```java +interface CalculateStrategy { + int doOperation(int num1, int num2); +} +``` + +然后再定义加减乘除这些具体策略角色并实现方法。代码如下: + +```java +class OperationAdd implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 + num2; + } +} + +class OperationSub implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 - num2; + } +} + +class OperationMul implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 * num2; + } +} + +class OperationDiv implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 / num2; + } +} +``` + +最后在定义一个环境角色,提供一个计算的接口供客户端使用。代码如下: + +```java +class CalculatorContext { + private CalculateStrategy strategy; + + public CalculatorContext(CalculateStrategy strategy) { + this.strategy = strategy; + } + + public int executeStrategy(int num1, int num2) { + return strategy.doOperation(num1, num2); + } +} +``` + +测试代码如下: + +```java +public static void main(String[] args) { + int a=4,b=2; + CalculatorContext context = new CalculatorContext(new OperationAdd()); + System.out.println("a + b = "+context.executeStrategy(a, b)); + + CalculatorContext context2 = new CalculatorContext(new OperationSub()); + System.out.println("a - b = "+context2.executeStrategy(a, b)); + + CalculatorContext context3 = new CalculatorContext(new OperationMul()); + System.out.println("a * b = "+context3.executeStrategy(a, b)); + + CalculatorContext context4 = new CalculatorContext(new OperationDiv()); + System.out.println("a / b = "+context4.executeStrategy(a, b)); +} +``` + +**策略模式优点:** + +- 扩展性好,可以在不修改对象结构的情况下,为新的算法进行添加新的类进行实现; +- 灵活性好,可以对算法进行自由切换; + +**策略模式缺点:** + +- 使用策略类变多,会增加系统的复杂度。; +- 客户端必须知道所有的策略类才能进行调用; + +**使用场景:** + +- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为; + 一个系统需要动态地在几种算法中选择一种; +- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现; + +## 责任链模式 + +为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。 + +在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。 + +**责任链模式是一种对象行为型模式,其主要优点如下。** + +1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。 +2. 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。 +3. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。 +4. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。 +5. 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。 + +代码实现如下: + +请假条类 + +```java +public class LeaveRequest { + //姓名 + private String name; + // 请假天数 + private int num; + // 请假内容 + private String content; + + public LeaveRequest(String name, int num, String content) { + this.name = name; + this.num = num; + this.content = content; + } + + public String getName() { + return name; + } + + public int getNum() { + return num; + } + + public String getContent() { + return content; + } + +} +``` + +处理类 + +```java +public abstract class Handler { + protected final static int NUM_ONE = 1; + protected final static int NUM_THREE = 3; + protected final static int NUM_SEVEN = 7; + + //该领导处理的请假天数区间 + private int numStart; + private int numEnd; + + + //领导上还有领导 + private Handler nextHandler; + + //设置请假天数范围 + public Handler(int numStart) { + this.numStart = numStart; + } + + //设置请假天数范围 + public Handler(int numStart, int numEnd) { + this.numStart = numStart; + this.numEnd = numEnd; + } + + //设置上级领导 + public void setNextHandler(Handler nextHandler) { + this.nextHandler = nextHandler; + } + + //提交请假条 + public final void submit(LeaveRequest leaveRequest) { + if (this.numStart == 0) { + return; + } + //请假天数达到领导处理要求 + if (leaveRequest.getNum() >= this.numStart) { + this.handleLeave(leaveRequest); + + //如果还有上级 并且请假天数超过当前领导的处理范围 + if (this.nextHandler != null && leaveRequest.getNum() > numEnd) { + //继续提交 + this.nextHandler.submit(leaveRequest); + } else { + System.out.println("流程结束!!!"); + } + } + } + + //各级领导处理请假条方法 + protected abstract void handleLeave(LeaveRequest leave); + +} +``` + +小组长类 + +```java +public class GroupLeader extends Handler { + //1-3天的假 + public GroupLeader() { + super(Handler.NUM_ONE, Handler.NUM_THREE); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("小组长审批通过:同意!"); + } +} +``` + +部门经理类 + +```java +public class Manager extends Handler { + //3-7天的假 + public Manager() { + super(Handler.NUM_THREE, Handler.NUM_SEVEN); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("部门经理审批通过:同意!"); + } +} +``` + +总经理类 + +```java +public class GeneralManager extends Handler{ + //7天以上的假 + public GeneralManager() { + super(Handler.NUM_THREE, Handler.NUM_SEVEN); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("总经理审批通过:同意!"); + } +} +``` + +测试类 + +```java +public class Client { + public static void main(String[] args) { + //请假条 + LeaveRequest leave = new LeaveRequest("小庄", 3, "出去旅游"); + + //各位领导 + Manager manager = new Manager(); + GroupLeader groupLeader = new GroupLeader(); + GeneralManager generalManager = new GeneralManager(); + + /* + * 小组长上司是经理 经理上司是总经理 + */ + groupLeader.setNextHandler(manager); + manager.setNextHandler(generalManager); + + //提交 + groupLeader.submit(leave); + + } +} +``` + +应用场景: + +1. 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。 +2. 可动态指定一组对象处理请求,或添加新的处理者。 +3. 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。 + +[参考链接](https://segmentfault.com/a/1190000040450513) + +## 迭代器模式 + +提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示。 + +把在元素之间游走的责任交给迭代器,而不是聚合对象。 -![image-20200630092741672](../img/singleton-class-init.png) +**应用实例:**JAVA 中的 iterator。 -基于类初始化的方案的实现代码更简洁。但基于volatile的双重检查锁定的方案有一个额外的优势:除了可以对静态字段实现延迟初始化外,还可以对实例字段实现延迟初始化。字段延迟初始化降低了初始化类或创建实例的开销,但增加了访问被延迟初始化的字段的开销。在大多数时候,正常的初始化要优于延迟初始化。 +**优点:** 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。 -[参考:单例模式](https://blog.csdn.net/goodlixueyong/article/details/51935526) +**缺点:**由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。 + +**使用场景:** 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。 + +**迭代器模式在JDK中的应用** + +ArrayList的遍历: + +```java +Iterator iter = null; + +System.out.println("ArrayList:"); +iter = arrayList.iterator(); +while (iter.hasNext()) { + System.out.print(iter.next() + "\t"); +} +``` ## 装饰模式 + +装饰者模式(decorator pattern):动态地将责任附加到对象上, 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案。 + 装饰模式以对客户端透明的方式拓展对象的功能,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。 +比如设置FileInputStream,先用BufferedInputStream装饰它,再用自己写的LowerCaseInputStream过滤器去装饰它。 + ``` InputStream in = new LowerCaseInputStream( new BufferedInputStream( new FileInputStream("test.txt"))); ``` -设置FileInputStream,先用BufferedInputStream装饰它,再用自己写的LowerCaseInputStream过滤器去装饰它。 - 在装饰模式中的角色有: -抽象组件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。 -具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类。 -装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。 -具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。 -![在这里插入图片描述](https://img-blog.csdn.net/20180925095631732?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) + +- 抽象组件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。 +- 具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类。 +- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。 +- 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。 ## 适配器模式 -将现成的对象通过适配变成我们需要的接口。 +适配器模式将现成的对象通过适配变成我们需要的接口。 适配器让原本接口不兼容的类可以合作。 + 适配器模式有类的适配器模式和对象的适配器模式两种不同的形式。 对象适配器模式通过组合对象进行适配。 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxOC8xMC8xOS8xNjY4YWM5YTA2NzUzMjQ0?x-oss-process=image/format,png) +![](http://img.dabin-coder.cn/image/适配器对象适配,png) 类适配器通过继承来完成适配。 -![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAxOC8xMC8xOS8xNjY4YWM5YTA2NTEyYjBj?x-oss-process=image/format,png) +![](http://img.dabin-coder.cn/image/适配器-类继承,png) -适配器模式的优点 +适配器模式的**优点**: 1. 更好的复用性。系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。 2. 更好的扩展性。在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。 ## 观察者模式 + +定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。 + +主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。 + 多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。其作用是让主题对象和观察者松耦合。 观察者模式所涉及的角色有: -抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。 -具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。 -抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。 -具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。 -Observer接口 Observable类 -被观察者类都是java.util.Observable类的子类。 -![在这里插入图片描述](https://img-blog.csdn.net/20180925095713437?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) -[观察者模式](https://www.cnblogs.com/luohanguo/p/7825656.html) + +- 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。 +- 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。 +- 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。 +- 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。 @@ -188,7 +674,7 @@ Observer接口 Observable类 动态代理:代理类在程序运行时创建,在内存中临时生成一个代理对象,在运行期间对业务方法进行增强。 -#### JDK动态代理 +**JDK动态代理** JDK实现代理只需要使用newProxyInstance方法: @@ -196,9 +682,13 @@ JDK实现代理只需要使用newProxyInstance方法: static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h ) ``` -ClassLoader loader:指定当前目标对象使用的类加载器 -Class[] interfaces:目标对象实现的接口的类型 -InvocationHandler h:当代理对象调用目标对象的方法时,会触发事件处理器的invoke方法() +三个入参: + +- ClassLoader loader:指定当前目标对象使用的类加载器 +- Class[] interfaces:目标对象实现的接口的类型 +- InvocationHandler:当代理对象调用目标对象的方法时,会触发事件处理器的invoke方法() + +示例代码: ``` public class DynamicProxyDemo { @@ -247,119 +737,11 @@ class MyInvacationHandler implements InvocationHandler { } ``` +## 建造者模式 +建造者模式:封装一个对象的构造过程,并允许按步骤构造。 -## 工厂模式 -工厂模式是用来封装对象的创建。 - -### 简单工厂模式 - -只有一个工厂类。适用于需要创建的对象较少的场景。 - -```java - public class ShapeFactory { - public static final String TAG = "ShapeFactory"; - public static Shape getShape(String type) { - Shape shape = null; - if (type.equalsIgnoreCase("circle")) { - shape = new CircleShape(); - } else if (type.equalsIgnoreCase("rect")) { - shape = new RectShape(); - } else if (type.equalsIgnoreCase("triangle")) { - shape = new TriangleShape(); - } - return shape; - } - } -``` - -优点:只需要一个工厂创建对象,代码量少。 - -缺点:系统扩展困难,新增产品需要修改工厂逻辑,当产品较多时,会造成工厂逻辑过于复杂,不利于系统扩展和维护。 - -### 工厂方法模式 - -针对不同的对象提供不同的工厂。每个对象都有一个与之对应的工厂。 - -```java -public interface Reader { - void read(); -} - -public class JpgReader implements Reader { - @Override - public void read() { - System.out.print("read jpg"); - } -} - -public class PngReader implements Reader { - @Override - public void read() { - System.out.print("read png"); - } -} - -public interface ReaderFactory { - Reader getReader(); -} - -public class JpgReaderFactory implements ReaderFactory { - @Override - public Reader getReader() { - return new JpgReader(); - } -} - -public class PngReaderFactory implements ReaderFactory { - @Override - public Reader getReader() { - return new PngReader(); - } -} -``` - -客户端通过子类来指定创建对应的对象。 - -```java -ReaderFactory factory=new JpgReaderFactory(); -Reader reader=factory.getReader(); -reader.read(); -``` - -优点:增加新的产品类时无须修改现有系统,只需增加新产品和对应的工厂类即可。 - -### 抽象工厂模式 - -多了一层抽象,减少了工厂的数量(HpMouseFactory和HpKeyboFactory合并为HpFactory)。 -![在这里插入图片描述](https://img-blog.csdn.net/2018092509574846?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) - - - -## 模板模式 - -在抽象类中定义一个操作中算法的骨架,子类按照需要重写方法实现。 - -```java -public abstract class DodishTemplate { - //模板 - protected void dodish(){ - this.preparation(); - this.doing(); - this.carriedDishes(); - } - - public abstract void preparation(); - - public abstract void doing(); - - public abstract void carriedDishes (); -} -``` - - - -## 建造者模式 +有两种形式:传统建造者模式和传统建造者模式变种。 传统建造者模式: diff --git "a/\345\267\245\345\205\267/docker.md" "b/\345\267\245\345\205\267/docker-overview.md" similarity index 100% rename from "\345\267\245\345\205\267/docker.md" rename to "\345\267\245\345\205\267/docker-overview.md" diff --git "a/\345\267\245\345\205\267/progit2.md" "b/\345\267\245\345\205\267/git-overview.md" similarity index 100% rename from "\345\267\245\345\205\267/progit2.md" rename to "\345\267\245\345\205\267/git-overview.md" diff --git "a/\345\267\245\345\205\267/linux-overview.md" "b/\345\267\245\345\205\267/linux-overview.md" new file mode 100644 index 0000000..f3cd728 --- /dev/null +++ "b/\345\267\245\345\205\267/linux-overview.md" @@ -0,0 +1,647 @@ +# 基本操作 + +## Linux关机,重启 + +``` +#关机 +shutdown -h now + +#重启 +shutdown -r now +``` + +## 查看系统,CPU信息 + +``` +#查看系统内核信息 +uname -a + +#查看系统内核版本 +cat /proc/version + +#查看当前用户环境变量 +env + +cat /proc/cpuinfo + +#查看有几个逻辑cpu, 包括cpu型号 +cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c + +#查看有几颗cpu,每颗分别是几核 +cat /proc/cpuinfo | grep physical | uniq -c + +#查看当前CPU运行在32bit还是64bit模式下, 如果是运行在32bit下也不代表CPU不支持64bit +getconf LONG_BIT + +#结果大于0, 说明支持64bit计算. lm指long mode, 支持lm则是64bit +cat /proc/cpuinfo | grep flags | grep ' lm ' | wc -l +``` + +## 建立软连接 + +``` +ln -s /usr/local/jdk1.8/ jdk +``` + +## rpm相关 + +``` +#查看是否通过rpm安装了该软件 +rpm -qa | grep 软件名 +``` + +## sshkey + +``` +#创建sshkey +ssh-keygen -t rsa -C your_email@example.com + +#id_rsa.pub 的内容拷贝到要控制的服务器的 home/username/.ssh/authorized_keys 中,如果没有则新建(.ssh权限为700, authorized_keys权限为600) +``` + +## 命令重命名 + +``` +#在各个用户的.bash_profile中添加重命名配置 +alias ll='ls -alF' +``` + +## 同步服务器时间 + +``` +sudo ntpdate -u ntp.api.bz +``` + +## 后台运行命令 + +``` +#后台运行,并且有nohup.out输出 +nohup xxx & + +#后台运行, 不输出任何日志 +nohup xxx > /dev/null & + +#后台运行, 并将错误信息做标准输出到日志中 +nohup xxx >out.log 2>&1 & +``` + +## 强制活动用户退出 + +``` +#命令来完成强制活动用户退出.其中TTY表示终端名称 +pkill -kill -t [TTY] +``` + +## 查看命令路径 + +``` +which <命令> +``` + +## 查看进程所有打开最大fd数 + +``` +ulimit -n +``` + +## 配置dns + +``` +vim /etc/resolv.conf +``` + +## nslookup,查看域名路由表 + +``` +nslookup google.com +``` + +## last, 最近登录信息列表 + +``` +#最近登录的5个账号 +last -n 5 +``` + +## 设置固定ip + +``` +ifconfig em1 192.168.5.177 netmask 255.255.255.0 +``` + +## 查看进程内加载的环境变量 + +``` +#也可以去 cd /proc 目录下, 查看进程内存中加载的东西 +ps eww -p XXXXX(进程号) +``` + +## 查看进程树找到服务器进程 + +``` +ps auwxf +``` + +## 查看进程启动路径 + +``` +cd /proc/xxx(进程号) +ls -all +#cwd对应的是启动路径 +``` + +## 添加用户, 配置sudo权限 + +``` +#新增用户 +useradd 用户名 +passwd 用户名 + +#增加sudo权限 +vim /etc/sudoers +#修改文件里面的 +#root ALL=(ALL) ALL +#用户名 ALL=(ALL) ALL +``` + +## 强制关闭进程名包含xxx的所有进程 + +``` +ps aux|grep xxx | grep -v grep | awk '{print $2}' | xargs kill -9 +``` + +# 磁盘,文件,目录相关操作 + +## vim操作 + +``` +#normal模式下 g表示全局, x表示查找的内容, y表示替换后的内容 +:%s/x/y/g + +#normal模式下 +0 #光标移到行首(数字0) +$ #光标移至行尾 +shift + g #跳到文件最后 +gg #跳到文件头 + +#显示行号 +:set nu + +#去除行号 +:set nonu + +#检索 +/xxx(检索内容) #从头检索, 按n查找下一个 +?xxx(检索内容) #从尾部检索 +``` + +## 打开只读文件,修改后需要保存时(不用切换用户即可保存的方式) + +``` +#在normal模式下 +:w !sudo tee % +``` + +## 查看磁盘, 文件目录基本信息 + +``` +#查看磁盘挂载情况 +mount + +#查看磁盘分区信息 +df + +#查看目录及子目录大小 +du -H -h + +#查看当前目录下各个文件, 文件夹占了多少空间, 不会递归 +du -sh * +``` + +## wc命令 + +``` +#查看文件里有多少行 +wc -l filename + +#看文件里有多少个word +wc -w filename + +#文件里最长的那一行是多少个字 +wc -L filename + +#统计字节数 +wc -c +``` + +## 常用压缩, 解压缩命令 + +### 压缩命令 + +``` +tar czvf xxx.tar 压缩目录 + +zip -r xxx.zip 压缩目录 +``` + +### 解压缩命令 + +``` +tar zxvf xxx.tar + +#解压到指定文件夹 +tar zxvf xxx.tar -C /xxx/yyy/ + +unzip xxx.zip +``` + +## 变更文件所属用户, 用户组 + +``` +chown eagleye.eagleye xxx.log +``` + +## cp, scp, mkdir + +``` +#复制 +cp xxx.log + +#复制并强制覆盖同名文件 +cp -f xxx.log + +#复制文件夹 +cp -r xxx(源文件夹) yyy(目标文件夹) + +#远程复制 +scp -P ssh端口 username@10.10.10.101:/home/username/xxx /home/xxx + +#级联创建目录 +mkdir -p /xxx/yyy/zzz + +#批量创建文件夹, 会在test,main下都创建java, resources文件夹 +mkdir -p src/{test,main}/{java,resources} +``` + +## 比较两个文件 + +``` +diff -u 1.txt 2.txt +``` + +## 日志输出的字节数,可以用作性能测试 + +``` +#如果做性能测试, 可以每执行一次, 往日志里面输出 “.” , 这样日志中的字节数就是实际的性能测试运行的次数, 还可以看见实时速率. +tail -f xxx.log | pv -bt +``` + +## 查看, 去除特殊字符 + +``` +#查看特殊字符 +cat -v xxx.sh + +#去除特殊字符 +sed -i 's/^M//g’ env.sh 去除文件的特殊字符, 比如^M: 需要这样输入: ctrl+v+enter +``` + +## 处理因系统原因引起的文件中特殊字符的问题 + +``` +#可以转换为该系统下的文件格式 +cat file.sh > file.sh_bak + +#先将file.sh中文件内容复制下来然后运行, 然后粘贴内容, 最后ctrl + d 保存退出 +cat > file1.sh + +#在vim中通过如下设置文件编码和文件格式 +:set fileencodings=utf-8 ,然后 w (存盘)一下即可转化为 utf8 格式, +:set fileformat=unix + +#在mac下使用dos2unix进行文件格式化 +find . -name "*.sh" | xargs dos2unix +``` + +## tee, 重定向的同时输出到屏幕 + +``` +awk ‘{print $0}’ xxx.log | tee test.log +``` + +# 检索相关 + +## grep + +``` +#反向匹配, 查找不包含xxx的内容 +grep -v xxx + +#排除所有空行 +grep -v '^/pre> + +#返回结果 2,则说明第二行是空行 +grep -n “^$” 111.txt + +#查询以abc开头的行 +grep -n “^abc” 111.txt + +#同时列出该词语出现在文章的第几行 +grep 'xxx' -n xxx.log + +#计算一下该字串出现的次数 +grep 'xxx' -c xxx.log + +#比对的时候,不计较大小写的不同 +grep 'xxx' -i xxx.log +``` + +## awk + +``` +#以':' 为分隔符,如果第五域有user则输出该行 +awk -F ':' '{if ($5 ~ /user/) print $0}' /etc/passwd + +#统计单个文件中某个字符(串)(中文无效)出现的次数 +awk -v RS='character' 'END {print --NR}' xxx.txt +``` + +## find检索命令 + +``` +#在目录下找后缀是.mysql的文件 +find /home/eagleye -name '*.mysql' -print + +#会从 /usr 目录开始往下找,找最近3天之内存取过的文件。 +find /usr -atime 3 –print + +#会从 /usr 目录开始往下找,找最近5天之内修改过的文件。 +find /usr -ctime 5 –print + +#会从 /doc 目录开始往下找,找jacky 的、文件名开头是 j的文件。 +find /doc -user jacky -name 'j*' –print + +#会从 /doc 目录开始往下找,找寻文件名是 ja 开头或者 ma开头的文件。 +find /doc \( -name 'ja*' -o- -name 'ma*' \) –print + +#会从 /doc 目录开始往下找,找到凡是文件名结尾为 bak的文件,把它删除掉。-exec 选项是执行的意思,rm 是删除命令,{ } 表示文件名,“\;”是规定的命令结尾。 +find /doc -name '*bak' -exec rm {} \; +``` + +# 网络相关 + +## 查看什么进程使用了该端口 + +``` +lsof -i:port +``` + +## 获取本机ip地址 + +``` +/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:" +``` + +## iptables + +``` +#查看iptables状态 +service iptables status + +#要封停一个ip +iptables -I INPUT -s ***.***.***.*** -j DROP + +#要解封一个IP,使用下面这条命令: +iptables -D INPUT -s ***.***.***.*** -j DROP + +备注: 参数-I是表示Insert(添加),-D表示Delete(删除)。后面跟的是规则,INPUT表示入站,***.***.***.***表示要封停的IP,DROP表示放弃连接。 + +#开启9090端口的访问 +/sbin/iptables -I INPUT -p tcp --dport 9090 -j ACCEPT + +#防火墙开启、关闭、重启 +/etc/init.d/iptables status +/etc/init.d/iptables start +/etc/init.d/iptables stop +/etc/init.d/iptables restart +``` + +## nc命令, tcp调试利器 + +``` +#给某一个endpoint发送TCP请求,就将data的内容发送到对端 +nc 192.168.0.11 8000 < data.txt + +#nc可以当做服务器,监听某个端口号,把某一次请求的内容存储到received_data里 +nc -l 8000 > received_data + +#上边只监听一次,如果多次可以加上-k参数 +nc -lk 8000 +``` + +## tcpdump + +``` +#dump出本机12301端口的tcp包 +tcpdump -i em1 tcp port 12301 -s 1500 -w abc.pcap +``` + +## 跟踪网络路由路径 + +``` +#traceroute默认使用udp方式, 如果是-I则改成icmp方式 +traceroute -I www.163.com + +#从ttl第3跳跟踪 +traceroute -M 3 www.163.com + +#加上端口跟踪 +traceroute -p 8080 192.168.10.11 +``` + +## ss + +``` +#显示本地打开的所有端口 +ss -l + +#显示每个进程具体打开的socket +ss -pl + +#显示所有tcp socket +ss -t -a + +#显示所有的UDP Socekt +ss -u -a + +#显示所有已建立的SMTP连接 +ss -o state established '( dport = :smtp or sport = :smtp )' + +#显示所有已建立的HTTP连接 +ss -o state established '( dport = :http or sport = :http )' + +找出所有连接X服务器的进程 +ss -x src /tmp/.X11-unix/* + +列出当前socket统计信息 +ss -s + +解释:netstat是遍历/proc下面每个PID目录,ss直接读/proc/net下面的统计信息。所以ss执行的时候消耗资源以及消耗的时间都比netstat少很多 +``` + +## netstat + +``` +#输出每个ip的连接数,以及总的各个状态的连接数 +netstat -n | awk '/^tcp/ {n=split($(NF-1),array,":");if(n<=2)++S[array[(1)]];else++S[array[(4)]];++s[$NF];++N} END {for(a in S){printf("%-20s %s\n", a, S[a]);++I}printf("%-20s %s\n","TOTAL_IP",I);for(a in s) printf("%-20s %s\n",a, s[a]);printf("%-20s %s\n","TOTAL_LINK",N);}' + +#统计所有连接状态, +#CLOSED:无连接是活动的或正在进行 +#LISTEN:服务器在等待进入呼叫 +#SYN_RECV:一个连接请求已经到达,等待确认 +#SYN_SENT:应用已经开始,打开一个连接 +#ESTABLISHED:正常数据传输状态 +#FIN_WAIT1:应用说它已经完成 +#FIN_WAIT2:另一边已同意释放 +#ITMED_WAIT:等待所有分组死掉 +#CLOSING:两边同时尝试关闭 +#TIME_WAIT:主动关闭连接一端还没有等到另一端反馈期间的状态 +#LAST_ACK:等待所有分组死掉 +netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}' + +#查找较多time_wait连接 +netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20 +``` + +# 监控linux性能命令 + +## top + +``` +按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序, 然后回车。而大写的 R 键可以将当前的排序倒转 +``` + +| 列名 | 含义 | +| :------ | :----------------------------------------------------------- | +| PID | 进程id | +| PPID | 父进程id | +| RUSER | Real user name | +| UID | 进程所有者的用户id | +| USER | 进程所有者的用户名 | +| GROUP | 进程所有者的组名 | +| TTY | 启动进程的终端名。不是从终端启动的进程则显示为 ? | +| PR | 优先级 | +| NI | nice值。负值表示高优先级,正值表示低优先级 | +| P | 最后使用的CPU,仅在多CPU环境下有意义 | +| %CPU | 上次更新到现在的CPU时间占用百分比 | +| TIME | 进程使用的CPU时间总计,单位秒 | +| TIME+ | 进程使用的CPU时间总计,单位1/100秒 | +| %MEM | 进程使用的物理内存百分比 | +| VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES | +| SWAP | 进程使用的虚拟内存中,被换出的大小,单位kb。 | +| RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA | +| CODE | 可执行代码占用的物理内存大小,单位kb | +| DATA | 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb | +| SHR | 共享内存大小,单位kb | +| nFLT | 页面错误次数 | +| nDRT | 最后一次写入到现在,被修改过的页面数。 | +| S | 进程状态。D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程 | +| COMMAND | 命令名/命令行 | +| WCHAN | 若该进程在睡眠,则显示睡眠中的系统函数名 | +| Flags | 任务标志,参考 sched.h | + +## dmesg,查看系统日志 + +``` +dmesg +``` + +## iostat,磁盘IO情况监控 + +``` +iostat -xz 1 + +#r/s, w/s, rkB/s, wkB/s:分别表示每秒读写次数和每秒读写数据量(千字节)。读写量过大,可能会引起性能问题。 +#await:IO操作的平均等待时间,单位是毫秒。这是应用程序在和磁盘交互时,需要消耗的时间,包括IO等待和实际操作的耗时。如果这个数值过大,可能是硬件设备遇到了瓶颈或者出现故障。 +#avgqu-sz:向设备发出的请求平均数量。如果这个数值大于1,可能是硬件设备已经饱和(部分前端硬件设备支持并行写入)。 +#%util:设备利用率。这个数值表示设备的繁忙程度,经验值是如果超过60,可能会影响IO性能(可以参照IO操作平均等待时间)。如果到达100%,说明硬件设备已经饱和。 +#如果显示的是逻辑设备的数据,那么设备利用率不代表后端实际的硬件设备已经饱和。值得注意的是,即使IO性能不理想,也不一定意味这应用程序性能会不好,可以利用诸如预读取、写缓存等策略提升应用性能。 +``` + +## free,内存使用情况 + +``` +free -m + +eg: + + total used free shared buffers cached +Mem: 1002 769 232 0 62 421 +-/+ buffers/cache: 286 715 +Swap: 1153 0 1153 + +第一部分Mem行: +total 内存总数: 1002M +used 已经使用的内存数: 769M +free 空闲的内存数: 232M +shared 当前已经废弃不用,总是0 +buffers Buffer 缓存内存数: 62M +cached Page 缓存内存数:421M + +关系:total(1002M) = used(769M) + free(232M) + +第二部分(-/+ buffers/cache): +(-buffers/cache) used内存数:286M (指的第一部分Mem行中的used – buffers – cached) +(+buffers/cache) free内存数: 715M (指的第一部分Mem行中的free + buffers + cached) + +可见-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数. + +第三部分是指交换分区 +``` + +## sar,查看网络吞吐状态 + +``` +#sar命令在这里可以查看网络设备的吞吐率。在排查性能问题时,可以通过网络设备的吞吐量,判断网络设备是否已经饱和 +sar -n DEV 1 + +# +#sar命令在这里用于查看TCP连接状态,其中包括: +#active/s:每秒本地发起的TCP连接数,既通过connect调用创建的TCP连接; +#passive/s:每秒远程发起的TCP连接数,即通过accept调用创建的TCP连接; +#retrans/s:每秒TCP重传数量; +#TCP连接数可以用来判断性能问题是否由于建立了过多的连接,进一步可以判断是主动发起的连接,还是被动接受的连接。TCP重传可能是因为网络环境恶劣,或者服务器压力过大导致丢包 +sar -n TCP,ETCP 1 +``` + +## vmstat, 给定时间监控CPU使用率, 内存使用, 虚拟内存交互, IO读写 + +``` +#2表示每2秒采集一次状态信息, 1表示只采集一次(忽略既是一直采集) +vmstat 2 1 + +eg: +r b swpd free buff cache si so bi bo in cs us sy id wa +1 0 0 3499840 315836 3819660 0 0 0 1 2 0 0 0 100 0 +0 0 0 3499584 315836 3819660 0 0 0 0 88 158 0 0 100 0 +0 0 0 3499708 315836 3819660 0 0 0 2 86 162 0 0 100 0 +0 0 0 3499708 315836 3819660 0 0 0 10 81 151 0 0 100 0 +1 0 0 3499732 315836 3819660 0 0 0 2 83 154 0 0 100 0 +``` + +- r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。 +- b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。 +- swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。 +- free 空闲的物理内存的大小,我的机器内存总共8G,剩余3415M。 +- buff Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M +- cache cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。) +- si 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。 +- so 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。 +- bi 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒 +- bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。 +- in 每秒CPU的中断次数,包括时间中断 +- cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。 +- us 用户CPU时间,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。 +- sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。 +- id 空闲 CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。 +- wt 等待IO CPU时间。 \ No newline at end of file diff --git "a/\345\267\245\345\205\267/Maven\345\256\236\346\210\230.md" "b/\345\267\245\345\205\267/maven-overview.md" similarity index 100% rename from "\345\267\245\345\205\267/Maven\345\256\236\346\210\230.md" rename to "\345\267\245\345\205\267/maven-overview.md" diff --git "a/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" "b/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" index c89865f..6fcc798 100644 --- "a/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" +++ "b/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" @@ -1,41 +1,14 @@ - - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [基本概念](#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5) - - [什么时候使用MQ](#%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E4%BD%BF%E7%94%A8mq) - - [优缺点](#%E4%BC%98%E7%BC%BA%E7%82%B9) -- [Exchange 类型](#exchange-%E7%B1%BB%E5%9E%8B) - - [direct](#direct) - - [fanout](#fanout) - - [topic](#topic) - - [headers](#headers) -- [消息丢失](#%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1) - - [生产者确认机制](#%E7%94%9F%E4%BA%A7%E8%80%85%E7%A1%AE%E8%AE%A4%E6%9C%BA%E5%88%B6) - - [路由不可达消息](#%E8%B7%AF%E7%94%B1%E4%B8%8D%E5%8F%AF%E8%BE%BE%E6%B6%88%E6%81%AF) - - [Return消息机制](#return%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6) - - [备份交换机](#%E5%A4%87%E4%BB%BD%E4%BA%A4%E6%8D%A2%E6%9C%BA) - - [消费者手动消息确认](#%E6%B6%88%E8%B4%B9%E8%80%85%E6%89%8B%E5%8A%A8%E6%B6%88%E6%81%AF%E7%A1%AE%E8%AE%A4) - - [持久化](#%E6%8C%81%E4%B9%85%E5%8C%96) - - [镜像队列](#%E9%95%9C%E5%83%8F%E9%98%9F%E5%88%97) -- [重复消费](#%E9%87%8D%E5%A4%8D%E6%B6%88%E8%B4%B9) -- [消费端限流](#%E6%B6%88%E8%B4%B9%E7%AB%AF%E9%99%90%E6%B5%81) -- [死信队列](#%E6%AD%BB%E4%BF%A1%E9%98%9F%E5%88%97) -- [其他](#%E5%85%B6%E4%BB%96) - - [pull模式](#pull%E6%A8%A1%E5%BC%8F) - - [消息过期时间](#%E6%B6%88%E6%81%AF%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4) -- [参考链接](#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5) - - - -# 简介 +--- +sidebar: heading +--- + +## 什么是RabbitMQ? RabbitMQ是一个由erlang开发的消息队列。消息队列用于应用间的异步协作。 ![](http://img.dabin-coder.cn/image/rabbitmq.png) -## 基本概念 +## RabbitMQ的组件 Message:由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key、priority、delivery-mode(是否持久性存储)等。 @@ -57,15 +30,23 @@ Broker:消息队列服务器实体。 以常见的订单系统为例,用户点击下单按钮之后的业务逻辑可能包括:扣减库存、生成相应单据、发短信通知。这种场景下就可以用 MQ 。将短信通知放到 MQ 异步执行,在下单的主流程(比如扣减库存、生成相应单据)完成之后发送一条消息到 MQ, 让主流程快速完结,而由另外的线程消费MQ的消息。 -## 优缺点 +## RabbitMQ的优缺点 缺点:使用erlang实现,不利于二次开发和维护;性能较kafka差,持久化消息和ACK确认的情况下生产和消费消息单机吞吐量大约在1-2万左右,kafka单机吞吐量在十万级别。 优点:有管理界面,方便使用;可靠性高;功能丰富,支持消息持久化、消息确认机制、多种消息分发机制。 +## RabbitMQ 有哪些重要的角色? + +RabbitMQ 中重要的角色有:生产者、消费者和代理。 + +1. 生产者:消息的创建者,负责创建和推送数据到消息服务器; +2. 消费者:消息的接收方,用于处理数据和确认消息; -# Exchange 类型 +3. 代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。 + +## Exchange 类型 Exchange分发消息时根据类型的不同分发策略不同,目前共四种类型:direct、fanout、topic、headers 。headers 模式根据消息的headers进行路由,此外 headers 交换器和 direct 交换器完全一致,但性能差很多。 @@ -78,35 +59,35 @@ Exchange规则。 | topic | 模糊匹配 | | headers | Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的header属性进行匹配。 | -## direct +**direct** direct交换机会将消息路由到binding key 和 routing key完全匹配的队列中。它是完全匹配、单播的模式。 ![](http://img.dabin-coder.cn/image/rabbitmq-direct.png) -## fanout +**fanout** 所有发到 fanout 类型交换机的消息都会路由到所有与该交换机绑定的队列上去。fanout 类型转发消息是最快的。 ![](http://img.dabin-coder.cn/image/rabbitmq-fanout.png) -## topic +**topic** -topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词。 +topic交换机使用routing key和binding key进行模糊匹配,匹配成功则将消息发送到相应的队列。routing key和binding key都是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“##”,用于做模糊匹配,其中“\*”用于匹配一个单词,“##”用于匹配多个单词。 ![](http://img.dabin-coder.cn/image/rabbitmq-topic.png) -## headers +**headers** headers交换机是根据发送的消息内容中的headers属性进行路由的。在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。 -# 消息丢失 +## 消息丢失 消息丢失场景:生产者生产消息到RabbitMQ Server消息丢失、RabbitMQ Server存储的消息丢失和RabbitMQ Server到消费者消息丢失。 消息丢失从三个方面来解决:生产者确认机制、消费者手动确认消息和持久化。 -## 生产者确认机制 +### 生产者确认机制 生产者发送消息到队列,无法确保发送的消息成功的到达server。 @@ -120,7 +101,7 @@ headers交换机是根据发送的消息内容中的headers属性进行路由的 ```yaml spring: rabbitmq: - #开启 confirm 确认机制 + ##开启 confirm 确认机制 publisher-confirms: true ``` @@ -139,20 +120,20 @@ final RabbitTemplate.ConfirmCallback confirmCallback = (CorrelationData correlat rabbitTemplate.setConfirmCallback(confirmCallback); ``` -## 路由不可达消息 +### 路由不可达消息 生产者确认机制只确保消息正确到达交换机,对于从交换机路由到Queue失败的消息,会被丢弃掉,导致消息丢失。 对于不可路由的消息,有两种处理方式:Return消息机制和备份交换机。 -### Return消息机制 +**Return消息机制** Return消息机制提供了回调函数 ReturnCallback,当消息从交换机路由到Queue失败才会回调这个方法。需要将`mandatory` 设置为 `true` ,才能监听到路由不可达的消息。 ```yaml spring: rabbitmq: - #触发ReturnCallback必须设置mandatory=true, 否则Exchange没有找到Queue就会丢弃掉消息, 而不会触发ReturnCallback + ##触发ReturnCallback必须设置mandatory=true, 否则Exchange没有找到Queue就会丢弃掉消息, 而不会触发ReturnCallback template.mandatory: true ``` @@ -167,11 +148,11 @@ rabbitTemplate.setReturnCallback(returnCallback); 当消息从交换机路由到Queue失败时,会返回 `return exchange: , routingKey: MAIL, replyCode: 312, replyText: NO_ROUTE`。 -### 备份交换机 +**备份交换机** 备份交换机alternate-exchange 是一个普通的exchange,当你发送消息到对应的exchange时,没有匹配到queue,就会自动转移到备份交换机对应的queue,这样消息就不会丢失。 -## 消费者手动消息确认 +### 消费者手动消息确认 有可能消费者收到消息还没来得及处理MQ服务就宕机了,导致消息丢失。因为消息者默认采用自动ack,一旦消费者收到消息后会通知MQ Server这条消息已经处理好了,MQ 就会移除这条消息。 @@ -180,7 +161,7 @@ rabbitTemplate.setReturnCallback(returnCallback); 消费者设置手动ack: ```java -#设置消费端手动 ack +##设置消费端手动 ack spring.rabbitmq.listener.simple.acknowledge-mode=manual ``` @@ -204,7 +185,7 @@ spring.rabbitmq.listener.simple.acknowledge-mode=manual 当消息消费失败时,消费端给broker回复nack,如果consumer设置了requeue为false,则nack后broker会删除消息或者进入死信队列,否则消息会重新入队。 -## 持久化 +### 持久化 如果RabbitMQ服务异常导致重启,将会导致消息丢失。RabbitMQ提供了持久化的机制,将内存中的消息持久化到硬盘上,即使重启RabbitMQ,消息也不会丢失。 @@ -216,15 +197,13 @@ spring.rabbitmq.listener.simple.acknowledge-mode=manual 当发布一条消息到交换机上时,Rabbit会先把消息写入持久化日志,然后才向生产者发送响应。一旦从队列中消费了一条消息的话并且做了确认,RabbitMQ会在持久化日志中移除这条消息。在消费消息前,如果RabbitMQ重启的话,服务器会自动重建交换机和队列,加载持久化日志中的消息到相应的队列或者交换机上,保证消息不会丢失。 -## 镜像队列 +### 镜像队列 当MQ发生故障时,会导致服务不可用。引入RabbitMQ的镜像队列机制,将queue镜像到集群中其他的节点之上。如果集群中的一个节点失效了,能自动地切换到镜像中的另一个节点以保证服务的可用性。 通常每一个镜像队列都包含一个master和多个slave,分别对应于不同的节点。发送到镜像队列的所有消息总是被直接发送到master和所有的slave之上。除了publish外所有动作都只会向master发送,然后由master将命令执行的结果广播给slave,从镜像队列中的消费操作实际上是在master上执行的。 - - -# 重复消费 +## 消息重复消费怎么处理? 消息重复的原因有两个:1.生产时消息重复,2.消费时消息重复。 @@ -238,9 +217,7 @@ spring.rabbitmq.listener.simple.acknowledge-mode=manual 2. 如果不存在,则正常消费,消费完毕后写入redis/db 3. 如果存在,则证明消息被消费过,直接丢弃 - - -# 消费端限流 +## 消费端怎么进行限流? 当 RabbitMQ 服务器积压大量消息时,队列里的消息会大量涌入消费端,可能导致消费端服务器奔溃。这种情况下需要对消费端限流。 @@ -249,7 +226,7 @@ Spring RabbitMQ 提供参数 prefetch 可以设置单个请求处理的消息个 开启消费端限流: ```properties -#在单个请求中处理的消息个数,unack的最大数量 +##在单个请求中处理的消息个数,unack的最大数量 spring.rabbitmq.listener.simple.prefetch=2 ``` @@ -261,7 +238,7 @@ spring.rabbitmq.listener.simple.prefetch=2 void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException; ``` -# 死信队列 +## 什么是死信队列? 消费失败的消息存放的队列。 @@ -383,9 +360,7 @@ public class DeadListener { 当普通队列中有死信时,RabbitMQ 就会自动的将这个消息重新发布到设置的死信交换机去,然后被路由到死信队列。可以监听死信队列中的消息做相应的处理。 -# 其他 - -## pull模式 +## 说说pull模式 pull模式主要是通过channel.basicGet方法来获取消息,示例代码如下: @@ -395,7 +370,7 @@ System.out.println(new String(response.getBody())); channel.basicAck(response.getEnvelope().getDeliveryTag(),false); ``` -## 消息过期时间 +## 怎么设置消息的过期时间? 在生产端发送消息的时候可以给消息设置过期时间,单位为毫秒(ms) @@ -406,7 +381,7 @@ msg.getMessageProperties().setExpiration("3000"); 也可以在创建队列的时候指定队列的ttl,从消息入队列开始计算,超过该时间的消息将会被移除。 -# 参考链接 +## 参考链接 [RabbitMQ基础](https://www.jianshu.com/p/79ca08116d57) diff --git "a/\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" "b/\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" new file mode 100644 index 0000000..5dd9255 --- /dev/null +++ "b/\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" @@ -0,0 +1,168 @@ +--- +sidebar: heading +--- + + + +## Kafka 都有哪些特点? + +- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。 +- 可扩展性:kafka集群支持热扩展 +- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失 +- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败) +- 高并发:支持数千个客户端同时读写 + +## 请简述下你在哪些场景下会选择 Kafka? + +- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。 +- 消息系统:解耦和生产者和消费者、缓存消息等。 +- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。 +- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。 +- 流式处理:比如spark streaming和 Flink + +## Kafka 的设计架构你知道吗? + + +Kafka 架构分为以下几个部分: + +- Producer :消息生产者,就是向 kafka broker 发消息的客户端。 +- Consumer :消息消费者,向 kafka broker 取消息的客户端。 +- Topic :可以理解为一个队列,一个 Topic 又分为一个或多个分区, +- Consumer Group:这是 kafka 用来实现一个 topic 消息的广播(发给所有的 consumer)和单播(发给任意一个 consumer)的手段。一个 topic 可以有多个 Consumer Group。 +- Broker :一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker 可以容纳多个 topic。 +- Partition:为了实现扩展性,一个非常大的 topic 可以分布到多个 broker上,每个 partition 是一个有序的队列。partition 中的每条消息都会被分配一个有序的id(offset)。将消息发给 consumer,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。 +- Offset:kafka 的存储文件都是按照 offset.kafka 来命名,用 offset 做名字的好处是方便查找。例如你想找位于 2049 的位置,只要找到 2048.kafka 的文件即可。当然 the first offset 就是 00000000000.kafka。 + +## Kafka 分区的目的? + +分区对于 Kafka 集群的好处是:实现负载均衡。分区对于消费者来说,可以提高并发度,提高效率。 + +## 你知道 Kafka 是如何做到消息的有序性? + +kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。 + +## Kafka Producer 的执行过程? + +1,Producer生产消息 --> 2,从Zookeeper找到Partition的Leader --> 3,推送消息 --> 4,通过ISR列表通知给Follower --> 5, Follower从Leader拉取消息,并发送ack --> 6,Leader收到所有副本的ack,更新Offset,并向Producer发送ack,表示消息写入成功。 + +## 讲一下你使用 Kafka Consumer 消费消息时的[线程模型](https://link.segmentfault.com/?enc=sniyt20KkIXAqIjQ4fraxQ%3D%3D.cmMRO%2FsnA0vXdDv1sttq1%2BSlDgGBRoAPWJw1zI%2Fslu10a6nBqqaCr9uYIZXuLMdYNK9%2B%2B17KBqxtMLvdyqlxYQ%3D%3D),为何如此设计? + +Thread-Per-Consumer Model,这种多线程模型是利用Kafka的topic分多个partition的机制来实现并行:每个线程都有自己的consumer实例,负责消费若干个partition。各个线程之间是完全独立的,不涉及任何线程同步和通信,所以实现起来非常简单。 + +## 请谈一谈 Kafka 数据一致性原理 + +一致性就是说不论是老的 Leader 还是新选举的 Leader,Consumer 都能读到一样的数据。 + +假设分区的副本为3,其中副本0是 Leader,副本1和副本2是 follower,并且在 ISR 列表里面。虽然副本0已经写入了 Message4,但是 Consumer 只能读取到 Message2。因为所有的 ISR 都同步了 Message2,只有 High Water Mark 以上的消息才支持 Consumer 读取,而 High Water Mark 取决于 ISR 列表里面偏移量最小的分区,对应于上图的副本2,这个很类似于木桶原理。 + +这样做的原因是还没有被足够多副本复制的消息被认为是“不安全”的,如果 Leader 发生崩溃,另一个副本成为新 Leader,那么这些消息很可能丢失了。如果我们允许消费者读取这些消息,可能就会破坏一致性。试想,一个消费者从当前 Leader(副本0) 读取并处理了 Message4,这个时候 Leader 挂掉了,选举了副本1为新的 Leader,这时候另一个消费者再去从新的 Leader 读取消息,发现这个消息其实并不存在,这就导致了数据不一致性问题。 + +当然,引入了 High Water Mark 机制,会导致 Broker 间的消息复制因为某些原因变慢,那么消息到达消费者的时间也会随之变长(因为我们会先等待消息复制完毕)。延迟时间可以通过参数 replica.lag.time.max.ms 参数配置,它指定了副本在复制消息时可被允许的最大延迟时间。 + +## ISR、OSR、AR 是什么? + +ISR:In-Sync Replicas 副本同步队列 + +OSR:Out-of-Sync Replicas + +AR:Assigned Replicas 所有副本 + +ISR是由leader维护,follower从leader同步数据有一些延迟(具体可以参见 图文了解 Kafka 的副本复制机制),超过相应的阈值会把 follower 剔除出 ISR, 存入OSR(Out-of-Sync Replicas )列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。 + +## LEO、HW、LSO、LW等分别代表什么 + +LEO:是 LogEndOffset 的简称,代表当前日志文件中下一条 + +HW:水位或水印(watermark)一词,也可称为高水位(high watermark),通常被用在流式处理领域(比如Apache Flink、Apache Spark等),以表征元素或事件在基于时间层面上的进度。在Kafka中,水位的概念反而与时间无关,而是与位置信息相关。严格来说,它表示的就是位置信息,即位移(offset)。取 partition 对应的 ISR中 最小的 LEO 作为 HW,consumer 最多只能消费到 HW 所在的位置上一条信息。 + +LSO:是 LastStableOffset 的简称,对未完成的事务而言,LSO 的值等于事务中第一条消息的位置(firstUnstableOffset),对已完成的事务而言,它的值同 HW 相同 + +LW:Low Watermark 低水位, 代表 AR 集合中最小的 logStartOffset 值。 + +## 数据传输的事务有几种? + +数据传输的事务定义通常有以下三种级别: + +(1)最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输 +(2)最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输. +(3)精确的一次(Exactly once): 不会漏传输也不会重复传输,每个消息都传输被 + +## Kafka 消费者是否可以消费指定分区消息? + +Kafa consumer消费消息时,向broker发出fetch请求去消费特定分区的消息,consumer指定消息在日志中的偏移量(offset),就可以消费从这个位置开始的消息,customer拥有了offset的控制权,可以向后回滚去重新消费之前的消息,这是很有意义的。 + +## Kafka消息是采用Pull模式,还是Push模式? + +Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers将消息推送到consumer,也就是pull还push。在这方面,Kafka遵循了一种大部分消息系统共同的传统的设计:producer将消息推送到broker,consumer从broker拉取消息。 + +一些消息系统比如Scribe和Apache Flume采用了push模式,将消息推送到下游的consumer。这样做有好处也有坏处:由broker决定消息推送的速率,对于不同消费速率的consumer就不太好处理了。消息系统都致力于让consumer以最大的速率最快速的消费消息,但不幸的是,push模式下,当broker推送的速率远大于consumer消费的速率时,consumer恐怕就要崩溃了。最终Kafka还是选取了传统的pull模式。 + +Pull模式的另外一个好处是consumer可以自主决定是否批量的从broker拉取数据。Push模式必须在不知道下游consumer消费能力和消费策略的情况下决定是立即推送每条消息还是缓存之后批量推送。如果为了避免consumer崩溃而采用较低的推送速率,将可能导致一次只推送较少的消息而造成浪费。Pull模式下,consumer就可以根据自己的消费能力去决定这些策略。 + +Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到新消息到t达。为了避免这点,Kafka有个参数可以让consumer阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发 + +## Kafka 高效文件存储设计特点 + +Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。 + +通过索引信息可以快速定位message和确定response的最大大小。 + +通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。 + +通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小 + +## Kafka创建Topic时如何将分区放置到不同的Broker中 + +副本因子不能大于 Broker 的个数; + +第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的; + +其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推; + +剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的 + +## 谈一谈 Kafka 的再均衡 + +在Kafka中,当有新消费者加入或者订阅的topic数发生变化时,会触发Rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消费者)机制,Rebalance顾名思义就是重新均衡消费者消费。Rebalance的过程如下: + +第一步:所有成员都向coordinator发送请求,请求入组。一旦所有成员都发送了请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader。 + +第二步:leader开始分配消费方案,指明具体哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案发给coordinator。coordinator接收到分配方案之后会把方案发给各个consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。 + +所以对于Rebalance来说,Coordinator起着至关重要的作用 + +## Kafka 是如何实现高吞吐率的? + +Kafka是分布式消息系统,需要处理海量的消息,Kafka的设计是把所有的消息都写入速度低容量大的硬盘,以此来换取更强的存储能力,但实际上,使用硬盘并没有带来过多的性能损失。kafka主要使用了以下几个方式实现了超高的吞吐率: + +- 顺序读写; +- 零拷贝 +- 文件分段 +- 批量发送 +- 数据压缩。 + +## Kafka 缺点? + +- 由于是批量发送,数据并非真正的实时; +- 对于mqtt协议不支持; +- 不支持物联网传感数据直接接入; +- 仅支持统一分区内消息有序,无法实现全局消息有序; +- 监控不完善,需要安装插件; +- 依赖zookeeper进行元数据管理; + + +## Kafka 新旧消费者的区别 + +旧的 Kafka 消费者 API 主要包括:SimpleConsumer(简单消费者) 和 ZookeeperConsumerConnectir(高级消费者)。SimpleConsumer 名字看起来是简单消费者,但是其实用起来很不简单,可以使用它从特定的分区和偏移量开始读取消息。高级消费者和现在新的消费者有点像,有消费者群组,有分区再均衡,不过它使用 ZK 来管理消费者群组,并不具备偏移量和再均衡的可操控性。 + +现在的消费者同时支持以上两种行为,所以为啥还用旧消费者 API 呢? + +## Kafka 分区数可以增加或减少吗?为什么? + +我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数。 + +Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。 + + + +> 参考:https://blog.51cto.com/u_15127589/2679155 \ No newline at end of file From 93cc798a596168b82c9297d0e1ed24afcc36c272 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 30 Oct 2022 17:32:31 +0800 Subject: [PATCH 11/84] modify url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ea05f6..9fc5372 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ # 海量数据场景题 -1. [统计不同电话号码的个数](https://topjavaer.cn/system-design/1-scan-code-login.html) +1. [统计不同电话号码的个数](https://topjavaer.cn/mass-data/1-count-phone-num.html) 2. [出现频率最高的100个词](https://topjavaer.cn/mass-data/2-find-hign-frequency-word.html) 3. [查找两个大文件共同的URL](https://topjavaer.cn/mass-data/3-find-same-url.html) 4. [如何在100亿的数据中找到中位数](https://topjavaer.cn/mass-data/4-find-mid-num.html) From 9afe51d51d4648b9e70b520e6f243c8683967b66 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 6 Nov 2022 15:24:32 +0800 Subject: [PATCH 12/84] interview --- README.md | 44 ++--- interview/1-byte-and-dance.md | 316 ++++++++++++++++++++++++++++++++++ interview/10-netease.md | 115 +++++++++++++ interview/2-tencent.md | 66 +++++++ interview/3-baidu.md | 107 ++++++++++++ interview/4-ali.md | 79 +++++++++ interview/5-kuaishou.md | 79 +++++++++ interview/6-meituan.md | 74 ++++++++ interview/7-shopee.md | 73 ++++++++ interview/8-jingdong.md | 58 +++++++ interview/9-huawei.md | 56 ++++++ interview/README.md | 13 ++ 12 files changed, 1055 insertions(+), 25 deletions(-) create mode 100644 interview/1-byte-and-dance.md create mode 100644 interview/10-netease.md create mode 100644 interview/2-tencent.md create mode 100644 interview/3-baidu.md create mode 100644 interview/4-ali.md create mode 100644 interview/5-kuaishou.md create mode 100644 interview/6-meituan.md create mode 100644 interview/7-shopee.md create mode 100644 interview/8-jingdong.md create mode 100644 interview/9-huawei.md create mode 100644 interview/README.md diff --git a/README.md b/README.md index 9fc5372..88004f5 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,25 @@ 5. [找出最热门的查询串](https://topjavaer.cn/mass-data/5-find-hot-string.html) 6. [如何找出排名前500的数字](https://topjavaer.cn/mass-data/6-top-500-num.html) +# 大厂面经汇总 + +- [字节跳动](./interview/1-byte-and-dance.md) +- [腾讯](./interview/2-tencent.md) +- [百度](./interview/3-baidu.md) +- [阿里](./interview/4-ali.md) +- [快手](./interview/5-kuaishou.md) +- [美团](./interview/6-meituan.md) +- [shopee](./interview/7-shopee.md) +- [京东](./interview/8-jingdong.md) +- [华为](./interview/9-huawei.md) +- [网易](./interview/10-netease.md) + +# 其他优质文章 + +[优质文章汇总,持续更新中~](https://topjavaer.cn/advance/excellent-article/) + +![](http://img.dabin-coder.cn/image/image-20221030172546796.png) + # 工具 [Git 超详细总结!](工具/git-overview.md)(推荐 :+1:) @@ -200,31 +219,6 @@ [Maven 基础总结!](tools/maven-overview.md) -# 大厂面试系列 - -1. [字节跳动一面面经](https://mp.weixin.qq.com/s/RH-SunzjqUTTx8HWaCmCcw) -2. [别再问我Java List八股文了!](https://mp.weixin.qq.com/s/doyy_GYGWoH_YHgyMijStA) -3. [腾讯面试,你真的懂HTTP吗?](https://mp.weixin.qq.com/s/kC7XRBfO7Z5hZcX6Dz2viw) -4. [美团二面面经,最后竟然有惊喜?](https://mp.weixin.qq.com/s/3HvOtTU29HGALqmeeOZNWw) -5. [Java多线程,被面试官难倒了!](https://mp.weixin.qq.com/s/tv8pOLaS6hpwgbKOB9w0Zw) -6. [京东二面,Redis为什么这么快?](https://mp.weixin.qq.com/s/S3vN5T9HpziRd2s5ysLaSg) -7. [MySQL索引,给我整不会了!](https://mp.weixin.qq.com/s/Q5CrDlNInpnckJaBQSrA7w) -8. [别再问我Java虚拟机八股文了!](https://mp.weixin.qq.com/s/npo5-VqQt5sqZiSwPv6LVw) -9. [计算机网络,问傻了!](https://mp.weixin.qq.com/s/WXcMLa_tdxpRLhO4U8LHIQ) -10. [Spring这几道题你会吗?](https://mp.weixin.qq.com/s/DtgYRFfOQxQdtQosCU-6aw) -11. [面向对象编程?](https://mp.weixin.qq.com/s/M8jDnLat61YAbM1-jIhJIA) -12. [Java内功深厚?](https://mp.weixin.qq.com/s/v_kWSHX9GMS_aoqfwUMKsg) -13. [面试初级Java开发,面试官问我MySQL架构?](https://mp.weixin.qq.com/s/JvDZCk4IecmaEYfFsRhpjQ) -14. [手写红黑树?](https://mp.weixin.qq.com/s/yznh_IfMg4hWqU62U-t9GQ) -15. [面完阿里,直接入职!](https://mp.weixin.qq.com/s/49QJ1FzaGTe-_54PT8_8jA) -16. [华为面经](https://mp.weixin.qq.com/s/KmjwoG7pNvAHiX1UNnef6g) - -# 其他优质文章 - -[优质文章汇总,持续更新中~](https://topjavaer.cn/advance/excellent-article/) - -![](http://img.dabin-coder.cn/image/image-20221030172546796.png) - # 交流 如果想进**技术、面试交流群**,可以扫描下方二维码加我微信,**备注加群**,我拉你进群,群里有BAT大佬,互相学习~ diff --git a/interview/1-byte-and-dance.md b/interview/1-byte-and-dance.md new file mode 100644 index 0000000..185ae8f --- /dev/null +++ b/interview/1-byte-and-dance.md @@ -0,0 +1,316 @@ +# 字节跳动 + +## 面经1 + +一面: + + 1.IM系统用户登录怎么实现的? + + 2.登录状态是怎么保存的?session是怎么获取的?sessionid是怎么识别的?整个流程是什么样的?有没有考虑分布式session? + + 3.Redis的数据类型 + + 4.Redis数据类型的底层数据结构 + + 5.三次握手、四次挥手 + + 6.Redis持久化机制 + + 7.MySQL的InnoDB索引数据结构 + + 8.哪些SQL的关键字会让索引失效 + + 9.队列、栈、数组、链表 + + 10.算法题:leetcode 92题 + + 二面: + +1.讲讲爬虫的构成 + +2.爬虫抓到的数据不清洗吗?不去重吗? + +3.对爬虫有什么更多的了解吗? + +4.Linux进程间通信机制 + +5.进程和线程的区别 + +6.线程私有的数据有哪些?(不是Java线程) + +7.讲一下堆排序,每次调整的时间复杂度?堆排序是稳定的吗?(一开始说错了,应该是不稳定的,后面面试官问稳定的定义是什么) + +8.哈希表的原理,怎么减小哈希表的冲突,怎么保证哈希表的并行读写 + +9.Kafka用过吗?说说Kafka的原理?怎么保证Kafka的高可用?Kafka怎么保证消息有序? + +10.项目里的set实现点赞,zset实现关注,为什么? + +11.zset底层实现?说一下跳表?节点的高度是多少?怎么决定节点的高度? + +12.https了解吗? + +13.中间人攻击知道吗?怎么做https的抓包?https怎么篡改? + +14.虚拟地址到物理地址的映射过程 + +15.算法题:给一个数组,建一颗最小高度的二叉树(递归和非递归) + + 三面: + +1.介绍一下做过的项目,哪些挑战性比较大,比较有难度的 + +2.IM项目怎么用Netty的,为什么要用Netty,长连接交互是怎样的 + +3.消息怎么存储,怎么发送,怎么知道消息已读和未读的 + +4.读了5条消息、又来5条消息,你是怎么去更新的,你的消息是幂等的吗? + +5.项目里怎么用ES的,ES怎么支持搜索的 + +6.技术论坛网站的评论是怎么存储的 + +7.查询评论是在DB里扫表查询吗?怎么展示所有的评论?性能如何?想要查询更快可以做哪些优化? + +8.结合缓存和DB的时候会出现哪些问题?要怎么解决? + +9.快排了解吗?介绍一下快排?时间复杂度是多少?为什么会退化成O(n^2)?单链表可以做快排吗?快排最核心的逻辑是什么?写一下单链表快排 + +## 面经2 + +一年经验,Java开发 + +1. 自我介绍; +2. 项目介绍;(延申较浅) +3. 手撕算法:NC95 最长连续子序列 +4. 手撕算法:NC91 最长递增子序列 +5. 线程和进程的区别?怎么创建线程?有哪些状态?有什么区别? +6. Java1.8了解哪些新特性?重点讲讲HashMap和CurrentHashMap。 +7. OSI七层协议和TCP/IP五层协议有什么区别?TCP/UDP在哪一层?对TCP了解多少? +8. 你还有什么要问的吗? + +总结:开幕雷击,字节对算法还是挺看重的。 + +## 面经3 + +字节电商后端 + +- 进程和线程区别 +- 为什么进程切换开销比线程切换开销大? +- 你知道逻辑地址和物理地址么? +- sql题(表T (id,name,salary,city)用SQL实现找到同时符合城市平均工资大于5000,单人工资大于10000的人的名字) +- wifi属于OSI哪一层 +- 三次握手四次挥手相关(细节,以及为什么三次,为什么四次) +- hashmap的底层原理 +- 红黑树和二叉搜索树,二叉树之间的区别 +- 为什么hashmap不直接用红黑树 + + 算法题 + +1. 求从一个树的左边的叶子节点到一个树右边的叶子节点的最短路径) + +2. 最长回文子串 +3. 给定一个数N,求(1-n)所有的可能子序列)比如给个1 返回1 给个2 返回1,2,1 2 + +## 面经4 + +1. 自我介绍 +2. 项目 +3. volatile原理和作用 +4. 什么是指令重排序,举个例子 +5. AQS原理 +6. JVM内存模型 +7. 类加载过程 +8. 双亲委派机制 +9. 介绍代理模式 +10. redis数据结构 +11. HTTP状态码,header +12. MVCC原理 +13. 算法: + + - 买股票无限次 + - 买股票只买一次 + - 买股票有手续费 + - 买股票最多买两次 + +## 面经5 + +1. 自我介绍 +2. 业务部分: + + - 2.1 堆和栈的区别 + - 2.2 调用一个函数在堆中的过程 + - 2.3 密码学 中间人攻击、RSA、DSA密码的差别、加密过程,私钥加密公钥加密,数字签名的过程(跟本人网络空间安全背景有关) + - 2.4 彩虹表、 kerberos、ECC(椭圆曲线加密) + +3. 算法题: + + 4. 一个无序数组,求其topK + + 5. 时段统计。动态规划。 + +## 面经6 + +1. 自我介绍 +2. 实习介绍:你在腾讯干了啥 +3. 实习项目介绍:这个项目(深挖) +4. 项目为啥立项,你做了什么模块 +5. 你的日志模块是怎么设计的,怎么开发的 +6. 你的token怎么做的,怎么保证唯一 +7. 你开发的业务模块举个例子(给他举了),你是怎么设计数据表的,具体用了哪些中间件 +8. mysql中inoodb的索引有哪些种类 +9. B+树索引具体是怎么实现的 +10. B树与B+树的区别 +11. 为什么B+树的中间节点不储存数据? +12. 给一个索引,在有的查询过程中他没有走索引查询,说说你能想到的原因 +13. 红黑树了解过么? +14. 用过redis么?(妈耶能别聊数据库了么) +15. 你提到了kafka是吧,来聊一哈 +16. 聊一下你对git的理解 +17. git rebase与git merge的区别 +18. 聊一下你对工作流的理解 + +手撕算法: + +给四个整数,判断是否只通过四则运算加()优先级能否运算出24 + +## 面经7 + +一面: + +1. 自我介绍 +2. JAVA SDK起到的作用 +3. 项目 +4. 数据流(项目) +5. 排序(介绍下你知道的排序和复杂度) +6. Arrays.sort底层的排序算法(有三种策略) +7. 堆排序基本思路 +8. linux,操作系统的开机流程(这题我不会。) +9. 进程和线程的区别 +10. 进程切换会发生什么 +11. 进程调度算法有哪些 +12. TCP、udp区别 +13. java锁,关键字区别 +14. 公平锁、非公平锁解释一下 + +二面: + +1. 算法题:由前序遍历中序遍历重建子树; +2. 为什么静态类中不能使用非静态类(从类加载过程回答); +3. java类加载过程; + 3.1. 加载阶段中,为什么要有自定义的类加载器; + 3.2. 双亲委派原则的机制; +4. HashMap数据结构; + 4.1. 为什么小于6是链表,大于8变成红黑树; + 4.2. HashMap扩容机制; + 4.3. HashMap是否线程安全,例子; + 4.4. ConcurrentHashMap和HashTable的区别; + 4.5. ConcurrentHashMap如何保证高效,为什么是线程安全,为什么比HashTable优秀,分段锁机制; + 4.6. CAS能保证线程安全吗(我回答能,面试官说不能。。估计想考ABA问题),volatile关键字能保证线程安全吗; +5. 随机数求根,比如根号二的值。(二分查询) +6. 有n个筐,筐固定,每个筐内有不同数目的苹果,移动苹果,使每个筐苹果平均(移动的代价:1~2算1步,1~3算2步)使步数最小; + +三面: + +1. 自我介绍 +2. 解决什么问题,做了些什么?(项目) +3. 多个接口,有失败怎么办(项目) +4. redis分布式锁怎么实现 +5. 时间过期怎么办 +6. ArrayList怎么扩容,时间复杂度O(n)?插尾部O(1),平均是多少,答案O(2)需要考虑扩容,小伙伴们可以自己推一下。 +7. HashMap底层原理 +8. mysql索引什么原理、B+树 +9. mysql和redis区别(讲一下各自优缺点) +10. 为什么不用redis存数据? +11. 算法:LRU缓存(),先讲一下再写 + +## 面经8 + +抖音电商 + +1. 自我介绍 +2. 讲一下HashMap的put方法 +3. 讲一下HashMap的扩容过程 +4. 讲一下你自定义协议怎么解决粘包问题的? +5. 算法题:LeetCode 二叉树根节点到子节点的路径和 +6. mysql的索引结构 +7. 为什么用B+树呢? +8. having的作用 +9. 聚簇索引、非聚簇索引 +10. 聚簇索引比非聚簇索引的优点 +11. mysql的四个隔离级别,应用场景 +12. 如何在可重复读隔离级别解决幻读问题 +13. dubbo的负载均衡策略 +14. java的动态代理 +15. Spring哪里用到了动态代理? +16. CGlib动态代理说一下 +17. MQ如何保证消息不会丢失 + +## 面经9 + +一面 + +- 怎么理解微服务 +- 微服务的缺点 +- 微服务之间怎么做负载均衡 +- Oauth2基本流程、原理 +- 登录模块是怎么做的 +- cookie和session的区别 +- 购物车为什么用Redis存,是永久存储吗 +- 为什么购物车多读多写 +- Redis怎样清除过期key,有哪些策略 +- lru是怎样的过程 +- Redis字典底层怎么实现的 +- hashtable是怎样实现的 +- ziplist怎样实现的 +- 普通的哈希表怎样实现的 +- 哈希表怎么扩容 +- 使用MQ的好处 +- MQ解耦和微服务解耦的区别 +- 算法:最长回文子串 +- https建立连接的过程(SSL/TLS协商的过程) +- 对称加密和非对称加密的优缺点 +- 为什么要区分内核态和用户态 +- 什么时候从用户态切换到内核态 +- 你编程的情况下,系统调用什么时候会发生 + 反问:业务,开发语言,表现,对应届生的要求(重点是基础和算法) + 面试体验不错,但是项目挖的有点深 + +2面 + +- 手写单例模式 +- volatile什么作用 +- 多线程的几种实现方式 +- 四种方式的区别 +- 锁用过哪些 +- 排它锁什么意思 +- 自旋锁什么意思 +- CAS相关 +- MySQL可以不指定主键建表吗,背后的逻辑是什么 +- 聚簇索引和其他索引有什么区别 +- 建唯一索引,插入数据时是怎么处理的 +- 重复插入会报错,是怎么处理的 +- 不同事物隔离级别的实现 +- 以前没有实习过吗 +- lc40 组合总和II + 反问:部门怎样培养新人,刚进来做什么(学基础,语言和中间件,做demo),大概多久做需求(1周到1个月不等,看学习情况),框架和中间件以开源的为主还是以自研的为主(自研的) + +3面 + +- 有在实习吗 +- 面试通过后可以实习吗 +- 做项目的过程中遇到过什么问题 +- 内存泄露具体发生在哪 +- 什么情况下会出现多线程访问 +- 缓存穿透,怎么解决 (好像一紧张说成缓存击穿了,面试复盘的时候才发现。。。) +- 缓存雪崩,怎么解决 +- 缓存与数据库数据一致性 +- 超卖问题怎么解决的 +- 集群环境下,Redis内存里的数据怎么保证一致 +- 算法:给定一个字符数组,和一个字符串,在字符串里找到任意一个完全由字符数组组成的子串,字符顺序无所谓(滑动窗口) + + + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/10-netease.md b/interview/10-netease.md new file mode 100644 index 0000000..7267aca --- /dev/null +++ b/interview/10-netease.md @@ -0,0 +1,115 @@ +# 网易面经 + +## 面经1 + +- 自我介绍 +- 如何创建一个Java对象 +- 在哪检查类的合法性 +- 如果这个类不存在,会怎么样 +- 类的加载机制 +- Thread的几种状态,调用什么方法切换的 +- 对象锁,2种暂停 +- Wait()和sleep()的区别 +- 用的线程池叫什么,有什么特性 +- 对springboot的理解 +- springMVC的filter和xx的区别 +- ArrayList和LinkedList的区别 + + + +## 面经2 + +- 怼项目 +- A、B、C并发执行完,D、E、F并发执行实现方式 +- 线程池 +- CountDownLatch、LinkedHashMap、AQS实现原理 +- 部分J.U.C包底层实现 +- Sychronized和Lock区别 +- Condition用法 +- 用sychronized实现Condition功能 +- Condition和sychronized实现Condition两种方式有什么区别 +- JVM分区 +- 垃圾回收 +- 类加载机制 +- 双亲委派机制 +- Redis基本数据类型 +- Redis集群方式 +- Redis哨兵 +- Redis备份 +- Redis持久化方式及区别、优缺点、实现方式 +- Redis集群作用 +- MySQL索引方式 +- MySQL组合索引 +- MySQL实现组合索引方式 +- MySQL集群方式 +- MySQL日志文件 +- MySQL集群实现原理 +- MySQL事物隔离级别,作用 +- Spring IOC +- 怎么解决循环引用 +- 聚簇索引和非聚簇索引 +- 怎么自定义String类型 + +## 面经3 + +- 自我介绍。 +- 你在xxx实习前后端都写?说说vue,angular,react的区别。 +- 如果给你个新项目,你用哪个框架,为什么。 +- 听说你用过缓存?用了什么缓存?几级缓存?怎么用的? +- 缓存怎么保证和内存的数据一致性? +- 如果让你自己设计一个缓存系统,你怎么设计? +- 你了解哪些 hash 方法?一致性 hash 是干嘛的? +- 对分布式有多少了解? +- 为什么用 springboot,好在哪? +- 给你一个sql语句,怎么判断有没有命中索引? +- 如果让你现在设计xx项目,你会怎么做? +- 你觉得java程序员写代码的时候应该关注哪些地方? +- 在xxx实习中项目的难点? +- pb和 json 你会怎么使用? + +## 面经4 + +- 说一个源码改进业务的例子。 +- websocket心跳如何实现? +- zk/db/redis锁怎么选型。 +- 8台物理机能撑住百万的长连接,一台能撑住13w???数据感觉有问题,至少有20台吧(lf+hl) +- 多租户隔离,为什么不用两个进程? +- 需要下沉容器层,有插件层消除重复。 +- 表现为同一个应用,然后只注册到注册中心一次。两个应用可以使用相同端口号。 +- 另外进程就更重了,要消耗更多的资源,而且不好管控。 +- 流程编排分支条件如何实现? +- 业务身份,这个有问题,如果大量增加分支,会拷贝多份,会有很多重复的规则文件,但是只有一两个组件不一样。 +- 目前做法时在组件中可能有业务条件判断。后续会使用表达式语言增加分支条件支持,业务身份只支持大粒度的区分。 +- 流程编排如何避免大量调用下游服务,是否做了隔离? +- 感觉调用下游要做熔断,例如hystrix。但是这个有点重了。sdk要做薄。 +- 客服IM也区分在线消息和离线消息,都会存起来,如果掉线了,下次登录成功了主动拉取就行。 + + +## 面经5 + +- 介绍一下JVM内存模型。 +- MySQL索引优化原则 +- BufferPool原理聊聊。 +- 解释一下什么是负载均衡,Dubbo的负载均衡说一下? +- 当MySQL单表记录数过大时,数据库如何优化? +- 一个4库的怎么拆分成8库的在表数量不变的情况下? +- 举举例子业务中DDD的设计。 +- 函数式编程的本质是什么,为什么需要了解过吗? +- 知道流的原理吗 Foreach函数碰到报错后面的执行吗?为什么? +- kafka消息怎么保证不丢失的? +- 为什么跳槽? +- 对不是互联网电商方向,其他方向感兴趣吗? +- 今后有什么职场规划或者学习计划。 +- 你认为你的个人性格是怎样的呢。 + + +## 面经6 + +- 自我介绍 +- 项目介绍 +- 浏览器输入 youdao.com 发生了什么有多详细说多详细。一直问到数据链路层 mac地址 +- TCP 有哪些状态 +- 归并排序 思想 及复杂度 +- Mysql MVCC +- 算法题。剑指Offer26,树的子结构 +- 反问 \ No newline at end of file diff --git a/interview/2-tencent.md b/interview/2-tencent.md new file mode 100644 index 0000000..c37e35f --- /dev/null +++ b/interview/2-tencent.md @@ -0,0 +1,66 @@ +# 腾讯 + +## 一面 +1. mysql索引结构? +2. redis持久化策略? +3. zookeeper节点类型说一下; +4. zookeeper选举机制? +5. zookeeper主节点故障,如何重新选举? +6. syn机制? +7. 线程池的核心参数; +8. threadlocal的实现,原理,业务用来做什么? +9. spring DI的原理; +10. 四次挥手; +11. gc root选择; +12. 标记清除算法的过程,标记清楚算法如何给对象分配内存空间? +13. cms算法的缺点; +## 二面 +1. CorruntHashmap理解 +2. ThreadLocal原理 +3. hashmap; +4. Java数据类型,同步机制; +5. 讲讲贪心算法; +6. 如果线上用户出现502错误你怎么排查? +7. 并发量很大,服务器宕机。你会怎么做? +## 三面 +1. syn和lock的区别,哪个更好?怎么选择? +2. hashmap源码,为什么8个节点变成红黑树又为什么到了6个节点才恢复为链表? +3. 缓存穿透,怎么解决? +4. 负载均衡算法,实现; +5. 轮询和随机的缺点; +6. 分布式服务治理; +7. dns迭代和递归的区别; +8. 算法题:最长回文串 +9. 为什么连接的时候是三次握手,关闭的时候却是四次握手? +## 四面 +1. 自我介绍 就背景进行一些提问 +2. 简单说说计算机网络 +3. 简单描述一下从浏览器输入一个地址到服务端整个交互过程 +4. 说说数据结构 +5. 操作系统用过吗 +6. 用过 linux 的哪些命令 +7. 查看一个进程监听了哪些端口 +8. 详细介绍项目(简历上的域名访问不了) +9. 讲解之前工作经历中做的东西 + 10.做一道算法题(判断二叉树是否对称) +10. java 如何从源代码转换成机器码执行的 +11. java 的击穿 +12. 网络的七层结构 +13. tcp\udp 详解 区别 +14. https 协议的交互过程 +15. linux 基础命令 +16. linux 开机过程 +17. 了解现在市面上主流的 cpu 架构 +18. fpga 概念了解吗 +19. 市面上的图数据库 +20. rdf 讲解 +21. 图数据库底层存储 +22. b 树,b+树的概念和区别 +23. 红黑树平衡二叉树优缺点和应用场景 +24. 有没有了解 docker 等云技术 + + + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/3-baidu.md b/interview/3-baidu.md new file mode 100644 index 0000000..18caa36 --- /dev/null +++ b/interview/3-baidu.md @@ -0,0 +1,107 @@ +# 百度 + +## 面经1 + +shiro的组件 +分布式一致性算法 +zookeeper那些能参与投票,leader能投票吗? +netty零拷贝实现 +volatile,如何感知到变量变化的 +redis高可用 +http如何跨域? +tcp如何长链接。 +http如何操作浏览器缓存。 +用过消息队列吗? +怎么自己扩展validator(参数校验) +jwt组成 header payload 签名加密算法那些。 +rsa如何运用到jwt中 +synchronized和volatile的区别 +什么是上下文切换,URL解析过程 +http有那些方法,get那些 +进程和线程的区别。 +和别人协作出现冲突怎么办 +如何学一个新语言 +怎么自学的 + +## 面经2 + +说说IO多路复用 +你刚刚说的多路复用针对的是各个请求(比如set,get),那返回值Redis是怎么处理的(愣住) +MySQL B+树一般几层,怎么算的 +数据库隔离级别 +脏读、不可重复读、幻读(结合具体场景来讲) +MySQL隔离级别分别怎么实现的 +MVCC +redo log、undo log +刷脏页的流程 +算法题:平方根 + +## 面经3 + +自我介绍 +项目是自己练手的项目吗,怎么找的 +项目是从0开始搭建的,还是有用开源的脚手架 +秒杀大概用到哪些东西,怎么实现的 +MQ幂等性和消息积压问题 +缓存与数据库数据一致性 +唯一ID +Java里怎么保证多个线程的互斥性 +一个线程有哪些状态 +AQS怎么理解的 +Spring IOC容器创建Bean的流程 +创建的Bean是单例还是多例的 +SpringCloud config是怎么在Bean创建后更新Bean的值的 +SpringBoot自动配置原理 +SpringMVC执行流程 +使用Spring和直接使用Java语言面向对象开发,有哪些好处 +怎么理解面向对象 +了解哪些设计模式 +策略模式描述一下 +JVM由哪些模块组成 +框架里打破双亲委派机制的SPI大概怎么实现的 +那说说双亲委派 +垃圾回收主要回收哪些区域 +怎么识别哪些是垃圾 +哪些是根节点 +什么时候会出现Full GC +不同垃圾收集器的区别 +TCP为什么要握三次手,为什么要挥四次手,大概什么流程 +实现环形队列(数组,增加和删除功能) +反转链表(迭代) + +## 面经4 +专业是偏向硬件吗 +对百度了解多少 +有什么兴趣爱好 +经常打球吗 +喜欢听什么音乐 +经常听音乐吗,什么时候开始喜欢听音乐的 +你说两个具体的歌名我听听 +平时是怎样的一个人,有什么特点 +有做过什么有成就感的事吗 +后面选择百度的概率有多少 +想过自己5年后、10年后是怎样的吗 + +## 面经5 + +1.面试官介绍自己,然后自我介绍 +2.java中的线程池有哪些?为什么使用线程池?你在哪里使用过或是见过? +3.Mysql底层是怎么实现的?从内存布局,磁盘布局说起? +4.Mysql有哪些索引?B树和B+树的区别,分别解决了什么问题? +5.try catch finally机制讲解一下? +6.为什么要使用SpringBoot做开发?与传统的开发有什么不一样的? +7.什么是微服务?微服务是如何实现服务的注册与发现的? +8.java中的集合分类有哪些?知道Queue吗?她下面有哪些实现类?重点说说HashMap? +9.在集合中哪些集合类是线程安全的? +10.什么是数字签名,作用是什么?使用的是什么算法? +11.常见的网络攻击有哪些? +12.在表单提交的时候,容易发起什么样的攻击? +13.在进行服务调用的时候如何进行身份验证,如何防止网络攻击? +14.你见过哪些安全框架?具体怎么使用的?(shiro) +15.两道算法题:1)普通的二分查找,问了其中的一些细节,二分查找存在的问题? 2)判断S1中是不是有S2的排列,找到返回true,否则返回false +16.Cookie和session 的使用场景,他们之间的关系? +17.String,StringBuilder,StringBuffer的区别,String的两种初始化的区别? + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/4-ali.md b/interview/4-ali.md new file mode 100644 index 0000000..2c99b2e --- /dev/null +++ b/interview/4-ali.md @@ -0,0 +1,79 @@ +# 阿里 + +## 面经1 + +1. 简单介绍项目 +2. 知道哪些数据结构以及他们的特点 +3. 链表增删快,那如何提高其查询效率,有没有什么想法? +4. B+树了解吗?B+树如何范围查询?B+树退化的极端情况是什么? +5. 跳表了解吗? +6. 大顶堆、小顶堆了解吗? +7. 实现长地址请求到服务端,然后服务端重定向短地址给客户端,如何实现长短地址的互相映射? +8. 那我现在有10份数据,有1000个线程来争抢,你要怎么处理? +9. 分布式是什么?为什么要分布式?分布式又会有哪些问题?分布式系统是如何实现事物的? +10. Redis集群了解吗?如何处理宕机的情况?Redis的同步策略? +11. LRU算法了解吗?你会如何实现它?这个算法可以应用在哪些场景下? +12. TCP为什么是三次握手?两次行不行?多次行不行? +13. TCP的安全性是如何实现的?两台服务器之间可以同时建立多条TCP链接吗?怎么实现的? +14. 客服端输入一个网址后,是如何拿到客服想要的数据的,是怎样在网络中传输的? +15. cookie和session +16. java有哪些锁?共享锁是什么?CAS?乐观锁和悲观锁?synchronied的底层原理?锁升级?死锁怎么形成的?如何破解死锁? + +## 面经2 + + +1. Java容器:List,Set,Map +2. Map的遍历方式 +3. HashMap扩容为什么是扩为两倍? +4. Java线程同步机制(信号量,闭锁,栅栏) +5. 对volatile的理解:常用于状态标记 +6. 八种基本数据类型的大小以及他们的封装类(顺带了解自动拆箱与装箱) +7. 线程阻塞几种情况?如何自己实现阻塞队列? +8. Java垃圾回收。可达性分析->引用级别->二次标记(finalize方法)->垃圾收集 算法(4个)->回收策略(3个)->垃圾收集器(GMS、G1)。 +9. java内存模型 +10. TCP/IP的理解 +11. 进程和线程的区别 +12. http状态码含义 +13. ThreadLocal(线程本地变量),如何实现一个本地缓存 +14. JVM内存区哪里会出现溢出? +15. 双亲委派模型的理解,怎样将两个全路径相同的类加载到内存中? +16. CMS收集器和G1收集器 +17. TCP流量控制和拥塞控制 +18. 服务器处理一个http请求的过程 +19. 例举几个Mysql优化手段 +20. 数据库死锁定义,怎样避免死锁 +21. spring的aop是什么?如何实现的 +22. 面向对象的设计原则 +23. 策略模式的实现 +24. 操作系统的内存管理的页面淘汰 算法 ,介绍下LRU(最近最少使用算法 ) +25. B+树的特点与优势 + +## 面经3 + +- 自我介绍,说简历里没有的东西 +- 说几个你最近在看的技术(MySQL,多线程) +- 口述了一个统计数据的场景题 +- 如果这个统计数据场景不用MySQL,而是用Java来实现,怎么做 +- 如果数据量过大,内存放不下呢 +- 用面向对象的思想解决上面提出的问题,创建出父类,子类,方法,说一下思路 +- 下一个场景,口述了一个登录场景,同学用线程池做登录校验,会有什么问题 +- 如何解决这些问题 +- 你给出的方案弊端在哪里,还有哪些方案 + +## 面经4 + + + +- 谈谈类加载机制。 +- hashmap和concurenthashmap +- 16g机器,让你分配jvm内存怎么分配。 +- 机器慢了怎么排查。 +- 谈谈consul和zookeeper,还有服务发现机制。 +- 详细说明raft协议。 +- 谈谈consul和zookeeper区别。 +- 服务注册的时候发现没有注册成功会是什么原因。 +- 讲讲你认为的rpc和service mesh之间的关系。 + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/5-kuaishou.md b/interview/5-kuaishou.md new file mode 100644 index 0000000..a06a8c2 --- /dev/null +++ b/interview/5-kuaishou.md @@ -0,0 +1,79 @@ +# 快手 + +## 一面 + +1. 简单介绍项目 +2. 知道哪些数据结构以及他们的特点 +3. 链表增删快,那如何提高其查询效率,有没有什么想法? +4. B+树了解吗?B+树如何范围查询?B+树退化的极端情况是什么? +5. 跳表了解吗? +6. 大顶堆、小顶堆了解吗? +7. 实现长地址请求到服务端,然后服务端重定向短地址给客户端,如何实现长短地址的互相映射? +8. 那我现在有10份数据,有1000个线程来争抢,你要怎么处理? +9. 分布式是什么?为什么要分布式?分布式又会有哪些问题?分布式系统是如何实现事物的? +10. Redis集群了解吗?如何处理宕机的情况?Redis的同步策略? +11. LRU算法了解吗?你会如何实现它?这个算法可以应用在哪些场景下? +12. TCP为什么是三次握手?两次行不行?多次行不行? +13. TCP的安全性是如何实现的?两台服务器之间可以同时建立多条TCP链接吗?怎么实现的? +14. 客服端输入一个网址后,是如何拿到客服想要的数据的,是怎样在网络中传输的? +15. cookie和session +16. java有哪些锁?共享锁是什么?CAS?乐观锁和悲观锁?synchronied的底层原理?锁升级?死锁怎么形成的?如何破解死锁? + +## 二面 + + +1. Java容器:List,Set,Map +2. Map的遍历方式 +3. HashMap扩容为什么是扩为两倍? +4. Java线程同步机制(信号量,闭锁,栅栏) +5. 对volatile的理解:常用于状态标记 +6. 八种基本数据类型的大小以及他们的封装类(顺带了解自动拆箱与装箱) +7. 线程阻塞几种情况?如何自己实现阻塞队列? +8. Java垃圾回收。可达性分析->引用级别->二次标记(finalize方法)->垃圾收集 算法(4个)->回收策略(3个)->垃圾收集器(GMS、G1)。 +9. java内存模型 +10. TCP/IP的理解 +11. 进程和线程的区别 +12. http状态码含义 +13. ThreadLocal(线程本地变量),如何实现一个本地缓存 +14. JVM内存区哪里会出现溢出? +15. 双亲委派模型的理解,怎样将两个全路径相同的类加载到内存中? +16. CMS收集器和G1收集器 +17. TCP流量控制和拥塞控制 +18. 服务器处理一个http请求的过程 +19. 例举几个Mysql优化手段 +20. 数据库死锁定义,怎样避免死锁 +21. spring的aop是什么?如何实现的 +22. 面向对象的设计原则 +23. 策略模式的实现 +24. 操作系统的内存管理的页面淘汰 算法 ,介绍下LRU(最近最少使用算法 ) +25. B+树的特点与优势 + +## 三面 + +- 自我介绍,说简历里没有的东西 +- 说几个你最近在看的技术(MySQL,多线程) +- 口述了一个统计数据的场景题 +- 如果这个统计数据场景不用MySQL,而是用Java来实现,怎么做 +- 如果数据量过大,内存放不下呢 +- 用面向对象的思想解决上面提出的问题,创建出父类,子类,方法,说一下思路 +- 下一个场景,口述了一个登录场景,同学用线程池做登录校验,会有什么问题 +- 如何解决这些问题 +- 你给出的方案弊端在哪里,还有哪些方案 + +## 四面 + +- 谈谈类加载机制。 +- hashmap和concurenthashmap +- 16g机器,让你分配jvm内存怎么分配。 +- 机器慢了怎么排查。 +- 谈谈consul和zookeeper,还有服务发现机制。 +- 详细说明raft协议。 +- 谈谈consul和zookeeper区别。 +- 服务注册的时候发现没有注册成功会是什么原因。 +- 讲讲你认为的rpc和service mesh之间的关系。 + + + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/6-meituan.md b/interview/6-meituan.md new file mode 100644 index 0000000..5b183c0 --- /dev/null +++ b/interview/6-meituan.md @@ -0,0 +1,74 @@ +# 美团 + +## 一面 + +- 消息队列如何保证可靠性 +- 消息队列如何保证消息幂等性 +- 消息队列的优缺点 +- 为什么用b+树 +- 聚集索引和主键区别,其他引擎怎么做的 +- 平时数据库编码 +- explain参数 +- http报文参数有哪些吗? +- 做题,链表奇偶有序输出 + +## 二面 + +- 自我介绍 +- 有哪些排序算法? +- 介绍下快排/堆排/归并排序。 +- 数据库中的索引应该如何设计? +- 有哪些索引失效的情况? +- 你们用到的HTTP接口用到了什么提交方式? +- GET/POST的区别? +- 除了GET/POST还有哪些? +- 面向对象的基本原则?再详细说下依赖倒转。 +- 介绍下策略模式和观察者模式? +- 如何保证用户请求的等幂性?等幂性指的是用户可能连点提交三次支付请求,返回同样的结果(支付成功),但实际后台只执行一次,保持一致性。 +- 介绍下TCP四次挥手? +- 第四次挥手后客户端是立刻就关闭了吗?是什么状态? +- 两个大文件,分别每行都存一个url,查找两个文件中重复的url。 +- 一个大文件中,每一行有一个整数,怎么找第100大的数? +- 一个大文件中,每一行有一个整数,怎么找中位数? +- redis的基本数据结构? +- zset是怎么实现的?有哪些命令? +- 算法题 力扣221. 最大正方形 + +## 三面 + +- 项目相关(模块划分,项目需求,技术方案,数据库设计,表的结构及关系,担任角色) +- http协议的关键字段,比如request和response头部信息有哪些关键字段,有什么含义 +- http状态码:100,200,502,504 +- http和https的区别,https是为了解决什么问题 +- 三次握手、四次挥手(详细过程+状态变化) +- 出现大量的close_wait可能是什么原因,解决方案,通过什么工具看出来网络有问题等等 +- Java中常见的集合有哪些,List、Set、Map初始容量加载因子了解吗 +- Java中线程通信的方式有哪些,大概的原理 +- MySQL如果遇到性能不好的问题,比如说慢查询,怎么做 +- 数据库优化方案(索引 | 分库分表) +- 有哪些索引,数据结构,建立索引的原则 +- 分库分表的原则,说说场景(水平 | 垂直、热数据 | 冷数据 blabla) +- 算法题:两数之和 + +## 四面 + +- 自我介绍、项目介绍,问了数据量 +- 了解微服务吗?(有没有自己在做项目时进行调研,了解企业目前常用的工具、方法) +- 了解springcloud吗? +- 一台机器无法满足运载需求,怎么办呢?答:多搞几台机器,问:多台机器如何协同工作? +- 解释一下mapreduce +- 如果有一个很大的文件,TB级别,文件里是乱序的数字,如何排序?mapreduce如何实现? +- 排序过程中的归并排序,请描述一下其过程?时间复杂度 +- 进程、线程区别,问使用Java时,里面多线程的概念和os里的线程进程的区别是什么?真正使用时,Java里的线程和进程是如何调度? +- 多线程的同步互斥的方法?答了信号量,问具体怎么实现,答pv操作,给了具体的场景,问变量如何初始化(等同于口述代码) +- 有哪些索引?(mysql为例) +- b树、b+树是什么样的树结构,查询复杂度?是平衡二叉树吗? +- 使用过redis吗?具体做什么? +- 手撕代码:LRU算法;正反序层序遍历二叉树 + + + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) + diff --git a/interview/7-shopee.md b/interview/7-shopee.md new file mode 100644 index 0000000..f548f56 --- /dev/null +++ b/interview/7-shopee.md @@ -0,0 +1,73 @@ +# shopee + +## 面经1 + +消息队列如何保证可靠性 +消息队列如何保证消息幂等性 +消息队列的优缺点 +为什么用b+树 +聚集索引和主键区别,其他引擎怎么做的 +平时数据库编码 +explain参数 +http报文参数有哪些吗? +做题,链表奇偶有序输出 + +## 面经2 + +1. 自我介绍 +2. 有哪些排序算法? +3. 介绍下快排/堆排/归并排序。 +4. 数据库中的索引应该如何设计? +5. 有哪些索引失效的情况? +6. 你们用到的HTTP接口用到了什么提交方式? +7. GET/POST的区别? +8. 除了GET/POST还有哪些? +9. 面向对象的基本原则?再详细说下依赖倒转。 +10. 介绍下策略模式和观察者模式? +11. 如何保证用户请求的等幂性?等幂性指的是用户可能连点提交三次支付请求,返回同样的结果(支付成功),但实际后台只执行一次,保持一致性。 +12. 介绍下TCP四次挥手? +13. 第四次挥手后客户端是立刻就关闭了吗?是什么状态? +14. 两个大文件,分别每行都存一个url,查找两个文件中重复的url。 +15. 一个大文件中,每一行有一个整数,怎么找第100大的数? +16. 一个大文件中,每一行有一个整数,怎么找中位数? +17. redis的基本数据结构? +18. zset是怎么实现的?有哪些命令? +19. 算法题 力扣221. 最大正方形 + +## 面经3 + +自我介绍、项目介绍,问了数据量 + +了解微服务吗?(有没有自己在做项目时进行调研,了解企业目前常用的工具、方法) + +了解springcloud吗? + +一台机器无法满足运载需求,怎么办呢?答:多搞几台机器,问:多台机器如何协同工作? + +开始瞎答:mapreduce + +解释一下mapreduce + +如果有一个很大的文件,TB级别,文件里是乱序的数字,如何排序?mapreduce如何实现? + +排序过程中的归并排序,请描述一下其过程?时间复杂度 + +进程、线程区别,问使用Java时,里面多线程的概念和os里的线程进程的区别是什么?真正使用时,Java里的线程和进程是如何调度? + +多线程的同步互斥的方法?答了信号量,问具体怎么实现,答pv操作,给了具体的场景,问变量如何初始化(等同于口述代码) + +有哪些索引?(mysql为例) + +b树、b+树是什么样的树结构,查询复杂度?是平衡二叉树吗? + +使用过redis吗?具体做什么? + +手撕代码:LRU算法;正反序层序遍历二叉树 + + + + + +**最后给大家分享一份精心整理的大厂高频面试题PDF,需要的小伙伴可以自行下载:** + +[大厂面试手册](http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd) \ No newline at end of file diff --git a/interview/8-jingdong.md b/interview/8-jingdong.md new file mode 100644 index 0000000..aa06fb9 --- /dev/null +++ b/interview/8-jingdong.md @@ -0,0 +1,58 @@ +# 京东 + +## 一面 + +- kafka在应用场景以及 项目 里的实现 +- bitmap底层 +- object里有哪些方法 +- hashmap相关 +- sychronized和reentrantlock相关问题以及锁升级 +- cas和volatile +- 线程几种状态以及转化 +- jvm内存模型 +- mybatis相关问题 +- Redis数据结构,问了下跳表的底层 +- RDB和AOF +- MySQL索引有哪些 +- b+树底层实现 +- 最左前缀原理 + +## 二面 + +- 线程的状态 +- cms +- 增量更新法 +- GcRoots是哪些 +- java基础 +- mysql索引 +- 项目具体实现 + +## 三面 + +- 索引 +- 谈谈多线程 +- jvm如何调优 +- mq在项目中的用法 +- 遇到的多线程问题,如何解决 +- 最长无重复字串 +- 找到A^2+B^2 = C + +## 四面 + +- 数据库乐观锁、悲观锁 +- 为啥用Redis +- sql语句执行顺序 +- SpringMVC优点,原理 +- aop优点,原理 +- ioc优点,原理 +- 面向对象概念 +- 封装 +- 项目中封装如何体现 +- 高内聚,低耦合啥意思,如何去设计 +- 设计一个电梯场景,实现面向对象,高内聚,低耦合的情况 +- 统计学校内共享单车数量,你有啥想法(开放题) + +**最后分享一个BAT大佬总结的高频面试题PDF,需要的小伙伴可以自行下载(复制链接到浏览器打开):** + +链接:https://pan.baidu.com/s/16GnVoALA1r6BhumuUrXIRg +提取码:6666 diff --git a/interview/9-huawei.md b/interview/9-huawei.md new file mode 100644 index 0000000..ffb1c83 --- /dev/null +++ b/interview/9-huawei.md @@ -0,0 +1,56 @@ +# 华为 + +最近越来越多公司校招进入面试流程了,为了帮助大家更好的应对面试,大彬整理了往年华为校招面试的题目,供大家参考~ + +## 面经1 + +### 技术一面 + +1. 自我介绍 +2. 说下项目中的难点 +3. volatile和synchronized的区别, 问的比较细 +4. 大顶堆小顶堆怎么删除根节点 +5. CSRF攻击是什么,怎么预防 +6. 线程通信方式。 +7. Volitate关键字。 +8. Java 高效拷贝数组。 +9. 算法题 跳跃游戏 leetcode 55。 + + +### 技术二面 +1. 上来就手撕代码 ,奇偶链表,leetcode原题,先说思路,然后打开ide共享屏幕撕代码 +2. 手写单例模式,并说为什么这样写,会不会有什么问题,涉及到volatile原理 +3. mysql常用的数据类型 +4. Java集合框架的主类是什么,HashSet有没有继承Collection软件工程学过哪些课程 +5. 软件工程学过哪些课程 +6. 进程和线程的区别 +7. 知道哪些排序算法,快排的时间复杂度是多少,是稳定的排序算法吗 +8. 编程题/算法 +题目大概:请输出两个字符串a和b相减的结果(a>b,a和b的字符串长度介于1~50之间)。 +例:输入a:“99999”,b=“99998” +输出:“1” + + +## 面经2 +### 华为一面 +1. 项目、论文。 +2. String能否被继承。 +3. Java内存泄露和排查。 +4. Hash方式和Hash冲突解决。 +5. 静态代理和动态代理。 +6. spring boot常用的注解有哪些 +7. spring boot的配置文件 +8. redis集群的几种方式详细说一下 +9. redis缓存雪崩,缓存击穿,缓存穿透是什么,怎么解决 +10. mysql索引相关,为什么用B+树 +11. 手撕代码,链表求和,leetcode原题:https://leetcode-cn.com/problems/sum-lists-lcci/ + +### 华为二面 +- 是否用过Java、Python做系统的项目 +- 平时熟练使用哪种语言 +- HashMap、HashSet、HashTable、StringBuffer、StringBuilder哪些是线程安全,哪些是线程不安全 +- HashSet数据结构,跟HashMap有什么区别 +- char和varchar的区别 +- mysql建索引的原则,索引是不是越多越好,为什么 +- spring boot用到了哪些设计模式,从源码层面说说你熟悉的以及实现 +- jvm调优你用什么工具,具体怎么做的,怎么调优 diff --git a/interview/README.md b/interview/README.md new file mode 100644 index 0000000..4ebcf45 --- /dev/null +++ b/interview/README.md @@ -0,0 +1,13 @@ + +## 大厂面经汇总 + +- [字节跳动](./1-byte-and-dance.md) +- [腾讯](./2-tencent.md) +- [百度](./3-baidu.md) +- [阿里](./4-ali.md) +- [快手](./5-kuaishou.md) +- [美团](./6-meituan.md) +- [shopee](./7-shopee.md) +- [京东](./8-jingdong.md) +- [华为](./9-huawei.md) +- [网易](./10-netease.md) From f6221f6632d461880411d1996780f5a4511cb15a Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 6 Nov 2022 15:33:16 +0800 Subject: [PATCH 13/84] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B8=B8=E8=A7=81?= =?UTF-8?q?=E7=9A=84Exception=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 04f0e86..0992793 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -921,7 +921,7 @@ class BMWCar extends Car implements Alarm { 5. `NumberFormatException` //数字格式化异常 6. `ArithmeticException` //数学运算异常 -unchecked Exception: +checked Exception: 1. `NoSuchFieldException` //反射异常,没有对应的字段 2. `ClassNotFoundException` //类没有找到异常 From 24a1369a74ca68d2d8049afcaf1258452b3dc793 Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 6 Nov 2022 15:36:46 +0800 Subject: [PATCH 14/84] =?UTF-8?q?Java=E5=9F=BA=E7=A1=80=E9=9D=A2=E8=AF=95?= =?UTF-8?q?=E9=A2=98=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...00\351\235\242\350\257\225\351\242\230.md" | 414 +++++++++++++++--- 1 file changed, 361 insertions(+), 53 deletions(-) diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index 0992793..a3a25bb 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -1,12 +1,19 @@ +--- +sidebar: heading + +--- + +![](http://img.dabin-coder.cn/image/Java基础.jpg) + ## Java的特点 -**Java是一门面向对象的编程语言。**面向对象和面向过程的区别参考下一个问题。 +**Java是一门面向对象的编程语言**。面向对象和面向过程的区别参考下一个问题。 -**Java具有平台独立性和移植性。** +**Java具有平台独立性和移植性**。 - Java有一句口号:`Write once, run anywhere`,一次编写、到处运行。这也是Java的魅力所在。而实现这种特性的正是Java虚拟机JVM。已编译的Java程序可以在任何带有JVM的平台上运行。你可以在windows平台编写代码,然后拿到linux上运行。只要你在编写完代码后,将代码编译成.class文件,再把class文件打成Java包,这个jar包就可以在不同的平台上运行了。 -**Java具有稳健性。** +**Java具有稳健性**。 - Java是一个强类型语言,它允许扩展编译时检查潜在类型不匹配问题的功能。Java要求显式的方法声明,它不支持C风格的隐式声明。这些严格的要求保证编译程序能捕捉调用错误,这就导致更可靠的程序。 - 异常处理是Java中使得程序更稳健的另一个特征。异常是某种类似于错误的异常条件出现的信号。使用`try/catch/finally`语句,程序员可以找到出错的处理代码,这就简化了出错处理和恢复的任务。 @@ -19,32 +26,11 @@ - Java 支持自动垃圾回收,而 C++ 需要手动回收。 - Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。 -## 面向对象和面向过程的区别? +## JDK/JRE/JVM三者的关系 -面向对象和面向过程是一种软件开发思想。 - -- 面向过程就是分析出解决问题所需要的步骤,然后用函数按这些步骤实现,使用的时候依次调用就可以了。 +**JVM** -- 面向对象是把构成问题事务分解成各个对象,分别设计这些对象,然后将他们组装成有完整功能的系统。面向过程只用函数实现,面向对象是用类实现各个功能模块。 - -以五子棋为例,面向过程的设计思路就是首先分析问题的步骤: - -1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。 -把上面每个步骤用分别的函数来实现,问题就解决了。 - -而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为: - -1. 黑白双方 -2. 棋盘系统,负责绘制画面 -3. 规则系统,负责判定诸如犯规、输赢等。 - -黑白双方负责接受用户的输入,并告知棋盘系统棋子布局发生变化,棋盘系统接收到了棋子的变化的信息就负责在屏幕上面显示出这种变化,同时利用规则系统来对棋局进行判定。 - -## JKD/JRE/JVM三者的关系 - -### JVM - -**JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 +英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。 ![](http://img.dabin-coder.cn/image/20220402230447.png) @@ -52,7 +38,7 @@ 针对不同的系统有不同的 jvm 实现,有 Linux 版本的 jvm 实现,也有Windows 版本的 jvm 实现,但是同一段代码在编译后的字节码是一样的。这就是Java能够跨平台,实现一次编写,多处运行的原因所在。 -### JRE +**JRE** 英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。 @@ -62,31 +48,81 @@ JRE是Java的运行环境,并不是一个开发环境,所以没有包含任 如果你只是想运行Java程序,而不是开发Java程序的话,那么你只需要安装JRE即可。 -### JDK +**JDK** 英文名称(Java Development Kit),就是 Java 开发工具包 学过Java的同学,都应该安装过JDK。当我们安装完JDK之后,目录结构是这样的 -![](https://cdn.jsdelivr.net/gh/Tyson0314/img/20220404120509.png) +![](http://img.dabin-coder.cn/image/20220404120509.png) 可以看到,JDK目录下有个JRE,也就是JDK中已经集成了 JRE,不用单独安装JRE。 另外,JDK中还有一些好用的工具,如jinfo,jps,jstack等。 -![](https://cdn.jsdelivr.net/gh/Tyson0314/img/20220404120507.png) +![](http://img.dabin-coder.cn/image/20220404120507.png) +最后,总结一下JDK/JRE/JVM,他们三者的关系 +**JRE = JVM + Java 核心类库** -### 总结 +**JDK = JRE + Java工具 + 编译器 + 调试器** -最后,总结一下JDK/JRE/JVM,他们三者的关系 +![](http://img.dabin-coder.cn/image/20220402230613.png) -JRE = JVM + Java 核心类库 +## Java程序是编译执行还是解释执行? -JDK = JRE + Java工具 + 编译器 + 调试器 +先看看什么是编译型语言和解释型语言。 -![](http://img.dabin-coder.cn/image/20220402230613.png) +**编译型语言** + +在程序运行之前,通过编译器将源程序编译成机器码可运行的二进制,以后执行这个程序时,就不用再进行编译了。 + +优点:编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高,可以脱离语言环境独立运行。 + +缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。 + +**总结**:执行速度快、效率高;依靠编译器、跨平台性差些。 + +**代表语言**:C、C++、Pascal、Object-C以及Swift。 + +**解释型语言** + +定义:解释型语言的源代码不是直接翻译成机器码,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。在运行的时候才将源程序翻译成机器码,翻译一句,然后执行一句,直至结束。 + +优点: + +1. 有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(如虚拟机)。 +2. 灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护。 + +缺点:每次运行的时候都要解释一遍,性能上不如编译型语言。 + +总结:解释型语言执行速度慢、效率低;依靠解释器、跨平台性好。 + +代表语言:JavaScript、Python、Erlang、PHP、Perl、Ruby。 + +对于Java这种语言,它的**源代码**会先通过javac编译成**字节码**,再通过jvm将字节码转换成**机器码**执行,即解释运行 和编译运行配合使用,所以可以称为混合型或者半编译型。 + +## 面向对象和面向过程的区别? + +面向对象和面向过程是一种软件开发思想。 + +- 面向过程就是分析出解决问题所需要的步骤,然后用函数按这些步骤实现,使用的时候依次调用就可以了。 + +- 面向对象是把构成问题事务分解成各个对象,分别设计这些对象,然后将他们组装成有完整功能的系统。面向过程只用函数实现,面向对象是用类实现各个功能模块。 + +以五子棋为例,面向过程的设计思路就是首先分析问题的步骤: + +1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。 +把上面每个步骤用分别的函数来实现,问题就解决了。 + +而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为: + +1. 黑白双方 +2. 棋盘系统,负责绘制画面 +3. 规则系统,负责判定诸如犯规、输赢等。 + +黑白双方负责接受用户的输入,并告知棋盘系统棋子布局发生变化,棋盘系统接收到了棋子的变化的信息就负责在屏幕上面显示出这种变化,同时利用规则系统来对棋局进行判定。 ## 面向对象有哪些特性? @@ -103,6 +139,27 @@ JDK = JRE + Java工具 + 编译器 + 调试器 4、抽象。把客观事物用代码抽象出来。 +## 数组到底是不是对象? + +先说说对象的概念。对象是根据某个类创建出来的一个实例,表示某类事物中一个具体的个体。 + +对象具有各种属性,并且具有一些特定的行为。站在计算机的角度,对象就是内存中的一个内存块,在这个内存块封装了一些数据,也就是类中定义的各个属性。 + +所以,对象是用来封装数据的。 + +java中的数组具有java中其他对象的一些基本特点。比如封装了一些数据,可以访问属性,也可以调用方法。 + +因此,可以说,数组是对象。 + +也可以通过代码验证数组是对象的事实。比如以下的代码,输出结果为java.lang.Object。 + +```java +Class clz = int[].class; +System.out.println(clz.getSuperclass().getName()); +``` + +由此,可以看出,数组类的父类就是Object类,那么可以推断出数组就是对象。 + ## Java的基本数据类型有哪些? - byte,8bit @@ -119,6 +176,8 @@ JDK = JRE + Java工具 + 编译器 + 调试器 | 二进制位数 | 1 | 8 | 16 | 16 | 32 | 64 | 32 | 64 | | 包装类 | Boolean | Byte | Character | Short | Integer | Long | Float | Double | +在Java规范中,没有明确指出boolean的大小。在《Java虚拟机规范》给出了单个boolean占4个字节,和boolean数组1个字节的定义,具体 **还要看虚拟机实现是否按照规范来**,因此boolean占用1个字节或者4个字节都是有可能的。 + ## 为什么不能用浮点型表示金额? 由于计算机中保存的小数其实是十进制的小数的近似值,并不是准确值,所以,千万不要在代码中使用浮点数来表示金额等重要的指标。 @@ -127,8 +186,10 @@ JDK = JRE + Java工具 + 编译器 + 调试器 ## 什么是值传递和引用传递? -- 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。 -- 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。所以对引用对象进行操作会同时改变原对象。 +- 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。 +- 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本,并不是原对象本身,两者指向同一片内存空间。所以对引用对象进行操作会同时改变原对象。 + +**java中不存在引用传递,只有值传递**。即不存在变量a指向变量b,变量b指向对象的这种情况。 ## 了解Java的包装类型吗?为什么需要包装类? @@ -228,7 +289,7 @@ private static class IntegerCache { } ``` -这是IntegerCache静态代码块中的一段,默认Integer cache 的下限是-128,上限默认127。当赋值100给Integer时,刚好在这个范围内,所以从cache中取对应的Integer并返回,所以a和b返回的是同一个对象,所以==比较是相等的,当赋值200给Integer时,不在cache 的范围内,所以会new Integer并返回,当然==比较的结果是不相等的。 +这是IntegerCache静态代码块中的一段,默认Integer cache 的下限是-128,上限默认127。当赋值100给Integer时,刚好在这个范围内,所以从cache中取对应的Integer并返回,所以a和b返回的是同一个对象,所以`==`比较是相等的,当赋值200给Integer时,不在cache 的范围内,所以会new Integer并返回,当然`==`比较的结果是不相等的。 ## String 为什么不可变? @@ -262,14 +323,26 @@ String类内部所有的字段都是私有的,也就是被private修饰。而 主要有以下几点原因: 1. **线程安全**。同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。 -2. **支持hash映射和缓存。**因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性使得 hash 值也不会变,不需要重新计算。 +2. **支持hash映射和缓存**。因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性使得 hash 值也不会变,不需要重新计算。 3. **出于安全考虑**。网络地址URL、文件路径path、密码通常情况下都是以String类型保存,假若String不是固定不变的,将会引起各种安全隐患。比如将密码用String的类型保存,那么它将一直留在内存中,直到垃圾收集器把它清除。假如String类不是固定不变的,那么这个密码可能会被改变,导致出现安全隐患。 -3. **字符串常量池优化**。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。 +4. **字符串常量池优化**。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。 既然我们的String是不可变的,它内部还有很多substring, replace, replaceAll这些操作的方法。这些方法好像会改变String对象?怎么解释呢? 其实不是的,我们每次调用replace等方法,其实会在堆内存中创建了一个新的对象。然后其value数组引用指向不同的对象。 +## 为何JDK9要将String的底层实现由char[]改成byte[]? + +主要是为了**节约String占用的内存**。 + +在大部分Java程序的堆内存中,String占用的空间最大,并且绝大多数String只有Latin-1字符,这些Latin-1字符只需要1个字节就够了。 + +而在JDK9之前,JVM因为String使用char数组存储,每个char占2个字节,所以即使字符串只需要1字节,它也要按照2字节进行分配,浪费了一半的内存空间。 + +到了JDK9之后,对于每个字符串,会先判断它是不是只有Latin-1字符,如果是,就按照1字节的规格进行分配内存,如果不是,就按照2字节的规格进行分配,这样便提高了内存使用率,同时GC次数也会减少,提升效率。 + +不过Latin-1编码集支持的字符有限,比如不支持中文字符,因此对于中文字符串,用的是UTF16编码(两个字节),所以用byte[]和char[]实现没什么区别。 + ## String, StringBuffer 和 StringBuilder区别 **1. 可变性** @@ -283,6 +356,62 @@ String类内部所有的字段都是私有的,也就是被private修饰。而 - StringBuilder 不是线程安全的 - StringBuffer 是线程安全的,内部使用 synchronized 进行同步 +## 什么是StringJoiner? + +StringJoiner是 Java 8 新增的一个 API,它基于 StringBuilder 实现,用于实现对字符串之间通过分隔符拼接的场景。 + +StringJoiner 有两个构造方法,第一个构造要求依次传入分隔符、前缀和后缀。第二个构造则只要求传入分隔符即可(前缀和后缀默认为空字符串)。 + +```java +StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) +StringJoiner(CharSequence delimiter) +``` + +有些字符串拼接场景,使用 StringBuffer 或 StringBuilder 则显得比较繁琐。 + +比如下面的例子: + +```java +List values = Arrays.asList(1, 3, 5); +StringBuilder sb = new StringBuilder("("); + +for (int i = 0; i < values.size(); i++) { + sb.append(values.get(i)); + if (i != values.size() -1) { + sb.append(","); + } +} + +sb.append(")"); +``` + +而通过StringJoiner来实现拼接List的各个元素,代码看起来更加简洁。 + +```java +List values = Arrays.asList(1, 3, 5); +StringJoiner sj = new StringJoiner(",", "(", ")"); + +for (Integer value : values) { + sj.add(value.toString()); +} +``` + +另外,像平时经常使用的Collectors.joining(","),底层就是通过StringJoiner实现的。 + +源码如下: + +```java +public static Collector joining( + CharSequence delimiter,CharSequence prefix,CharSequence suffix) { + return new CollectorImpl<>( + () -> new StringJoiner(delimiter, prefix, suffix), + StringJoiner::add, StringJoiner::merge, + StringJoiner::toString, CH_NOID); +} +``` + + + ## String 类的常用方法有哪些? - indexOf():返回指定字符的索引。 @@ -308,6 +437,49 @@ String类内部所有的字段都是私有的,也就是被private修饰。而 字符串常量池(String Pool)保存着所有字符串字面量,这些字面量在编译时期就确定。字符串常量池位于堆内存中,专门用来存储字符串常量。在创建字符串时,JVM首先会检查字符串常量池,如果该字符串已经存在池中,则返回其引用,如果不存在,则创建此字符串并放入池中,并返回其引用。 +## String最大长度是多少? + +String类提供了一个length方法,返回值为int类型,而int的取值上限为2^31 -1。 + +所以理论上String的最大长度为2^31 -1。 + +**达到这个长度的话需要多大的内存吗**? + +String内部是使用一个char数组来维护字符序列的,一个char占用两个字节。如果说String最大长度是2^31 -1的话,那么最大的字符串占用内存空间约等于4GB。 + +也就是说,我们需要有大于4GB的JVM运行内存才行。 + +**那String一般都存储在JVM的哪块区域呢**? + +字符串在JVM中的存储分两种情况,一种是String对象,存储在JVM的堆栈中。一种是字符串常量,存储在常量池里面。 + +**什么情况下字符串会存储在常量池呢**? + +当通过字面量进行字符串声明时,比如String s = "程序新大彬";,这个字符串在编译之后会以常量的形式进入到常量池。 + +**那常量池中的字符串最大长度是2^31-1吗**? + +不是的,常量池对String的长度是有另外限制的。。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表示。 + +```java +CONSTANT_Utf8_info { + u1 tag; + u2 length; + u1 bytes[length]; +} +``` + +length在这里就是代表字符串的长度,length的类型是u2,u2是无符号的16位整数,也就是说最大长度可以做到2^16-1 即 65535。 + +不过javac编译器做了限制,需要length < 65535。所以字符串常量在常量池中的最大长度是65535 - 1 = 65534。 + +最后总结一下: + +String在不同的状态下,具有不同的长度限制。 + +- 字符串常量长度不能超过65534 +- 堆内字符串的长度不超过2^31-1 + ## Object常用方法有哪些? Java面试经常会出现的一道题目,Object的常用方法。下面给大家整理一下。 @@ -844,7 +1016,7 @@ public class B extends A { ## 方法重载和重写的区别? -**同个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载。**参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。 +**同个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载**。参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。 重载是面向对象的一个基本特性。 @@ -862,7 +1034,7 @@ public class OverrideTest { } ``` -**方法的重写描述的是父类和子类之间的。当父类的功能无法满足子类的需求,可以在子类对方法进行重写。**方法重写时, 方法名与形参列表必须一致。 +**方法的重写描述的是父类和子类之间的。当父类的功能无法满足子类的需求,可以在子类对方法进行重写**。方法重写时, 方法名与形参列表必须一致。 如下代码,Person为父类,Student为子类,在Student中重写了dailyTask方法。 @@ -888,9 +1060,9 @@ public class Student extends Person { 1、**语法层面**上的区别 -- 抽象类可以有方法实现,而接口的方法中只能是抽象方法(Java 8 开始接口方法可以有默认实现); +- 抽象类可以有方法实现,而接口的方法中只能是抽象方法(Java 8 之后接口方法可以有默认实现); - 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型; -- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法; +- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法(Java 8之后接口可以有静态方法); - 一个类只能继承一个抽象类,而一个类却可以实现多个接口。 2、**设计层面**上的区别 @@ -1071,17 +1243,60 @@ Java不支持多继承的原因: - Optional 类 :Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。 - Date Time API :加强对日期与时间的处理。 -> [Java8 新特性总结]([Java-learning/Java8.md at master · Tyson0314/Java-learning (github.com)](https://github.com/Tyson0314/Java-learning/blob/master/Java/Java8.md)) +> [Java8 新特性总结](https://github.com/Tyson0314/Java-learning/blob/master/Java/Java8新特性.md) + +## 序列化和反序列化 + +- 序列化:把对象转换为字节序列的过程称为对象的序列化. +- 反序列化:把字节序列恢复为对象的过程称为对象的反序列化. + +## 什么时候需要用到序列化和反序列化呢? + +当我们只在本地 JVM 里运行下 Java 实例,这个时候是不需要什么序列化和反序列化的,但当我们需要将内存中的对象持久化到磁盘,数据库中时,当我们需要与浏览器进行交互时,当我们需要实现 RPC 时,这个时候就需要序列化和反序列化了. + +前两个需要用到序列化和反序列化的场景,是不是让我们有一个很大的疑问? 我们在与浏览器交互时,还有将内存中的对象持久化到数据库中时,好像都没有去进行序列化和反序列化,因为我们都没有实现 Serializable 接口,但一直正常运行. + +下面先给出结论: + +**只要我们对内存中的对象进行持久化或网络传输,这个时候都需要序列化和反序列化.** + +理由: + +服务器与浏览器交互时真的没有用到 Serializable 接口吗? JSON 格式实际上就是将一个对象转化为字符串,所以服务器与浏览器交互时的数据格式其实是字符串,我们来看来 String 类型的源码: + +``` +public final class String + implements java.io.Serializable,Comparable,CharSequence { + /\*\* The value is used for character storage. \*/ + private final char value\[\]; + + /\*\* Cache the hash code for the string \*/ + private int hash; // Default to 0 + + /\*\* use serialVersionUID from JDK 1.0.2 for interoperability \*/ + private static final long serialVersionUID = -6849794470754667710L; + + ...... +} +``` + +String 类型实现了 Serializable 接口,并显示指定 serialVersionUID 的值. -## 什么是序列化和反序列化? +然后我们再来看对象持久化到数据库中时的情况,Mybatis 数据库映射文件里的 insert 代码: + +``` + + INSERT INTO t\_user(name,age) VALUES (#{name},#{age}) + +``` -序列化:把内存中的对象转换为字节序列的过程。 +实际上我们并不是将整个对象持久化到数据库中,而是将对象中的属性持久化到数据库中,而这些属性(如Date/String)都实现了 Serializable 接口。 -反序列化:把字节序列恢复为Java对象的过程。 +## 实现序列化和反序列化为什么要实现 Serializable 接口? -## 如何实现序列化 +在 Java 中实现了 Serializable 接口后, JVM 在类加载的时候就会发现我们实现了这个接口,然后在初始化实例对象的时候就会在底层帮我们实现序列化和反序列化。 -实现`Serializable`接口即可。序列化的时候(如`objectOutputStream.writeObject(user)`),会判断user是否实现了`Serializable`,如果对象没有实现`Serializable`接口,在序列化的时候会抛出`NotSerializableException`异常。源码如下: +如果被写对象类型不是String、数组、Enum,并且没有实现Serializable接口,那么在进行序列化的时候,将抛出NotSerializableException。源码如下: ```java // remaining cases @@ -1103,6 +1318,20 @@ if (obj instanceof String) { } ``` +## 实现 Serializable 接口之后,为什么还要显示指定 serialVersionUID 的值? + +如果不显示指定 serialVersionUID,JVM 在序列化时会根据属性自动生成一个 serialVersionUID,然后与属性一起序列化,再进行持久化或网络传输. 在反序列化时,JVM 会再根据属性自动生成一个新版 serialVersionUID,然后将这个新版 serialVersionUID 与序列化时生成的旧版 serialVersionUID 进行比较,如果相同则反序列化成功,否则报错. + +如果显示指定了 serialVersionUID,JVM 在序列化和反序列化时仍然都会生成一个 serialVersionUID,但值为我们显示指定的值,这样在反序列化时新旧版本的 serialVersionUID 就一致了. + +如果我们的类写完后不再修改,那么不指定serialVersionUID,不会有问题,但这在实际开发中是不可能的,我们的类会不断迭代,一旦类被修改了,那旧对象反序列化就会报错。 所以在实际开发中,我们都会显示指定一个 serialVersionUID。 + +## static 属性为什么不会被序列化? + +因为序列化是针对对象而言的,而 static 属性优先于对象存在,随着类的加载而加载,所以不会被序列化. + +看到这个结论,是不是有人会问,serialVersionUID 也被 static 修饰,为什么 serialVersionUID 会被序列化? 其实 serialVersionUID 属性并没有被序列化,JVM 在序列化对象时会自动生成一个 serialVersionUID,然后将我们显示指定的 serialVersionUID 属性值赋给自动生成的 serialVersionUID. + ## transient关键字的作用? Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。 @@ -1128,8 +1357,87 @@ Java泛型是JDK 5中引⼊的⼀个新特性, 允许在定义类和接口的 泛型最⼤的好处是可以提⾼代码的复⽤性。以List接口为例,我们可以将String、 Integer等类型放⼊List中, 如不⽤泛型, 存放String类型要写⼀个List接口, 存放Integer要写另外⼀个List接口, 泛型可以很好的解决这个问题。 -## String为什么不可变? +## 如何停止一个正在运行的线程? + +有几种方式。 + +1、**使用线程的stop方法**。 + +使用stop()方法可以强制终止线程。不过stop是一个被废弃掉的方法,不推荐使用。 + +使用Stop方法,会一直向上传播ThreadDeath异常,从而使得目标线程解锁所有锁住的监视器,即释放掉所有的对象锁。使得之前被锁住的对象得不到同步的处理,因此可能会造成数据不一致的问题。 + +2、**使用interrupt方法中断线程**,该方法只是告诉线程要终止,但最终何时终止取决于计算机。调用interrupt方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。 + +接着调用 Thread.currentThread().isInterrupted()方法,可以用来判断当前线程是否被终止,通过这个判断我们可以做一些业务逻辑处理,通常如果isInterrupted返回true的话,会抛一个中断异常,然后通过try-catch捕获。 + +3、**设置标志位** + +设置标志位,当标识位为某个值时,使线程正常退出。设置标志位是用到了共享变量的方式,为了保证共享变量在内存中的可见性,可以使用volatile修饰它,这样的话,变量取值始终会从主存中获取最新值。 + +但是这种volatile标记共享变量的方式,在线程发生阻塞时是无法完成响应的。比如调用Thread.sleep() 方法之后,线程处于不可运行状态,即便是主线程修改了共享变量的值,该线程此时根本无法检查循环标志,所以也就无法实现线程中断。 + +因此,interrupt() 加上手动抛异常的方式是目前中断一个正在运行的线程**最为正确**的方式了。 + +## 什么是跨域? + +简单来讲,跨域是指从一个域名的网页去请求另一个域名的资源。由于有**同源策略**的关系,一般是不允许这么直接访问的。但是,很多场景经常会有跨域访问的需求,比如,在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域问题。 + +**那什么是同源策略呢**? + +所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。 + +同源策略限制以下几种行为: + +```mipsasm +1. Cookie、LocalStorage 和 IndexDB 无法读取 +2. DOM 和 Js对象无法获得 +3. AJAX 请求不能发送 +``` + +**为什么要有同源策略**? + +举个例子,假如你刚刚在网银输入账号密码,查看了自己的余额,然后再去访问其他带颜色的网站,这个网站可以访问刚刚的网银站点,并且获取账号密码,那后果可想而知。因此,从安全的角度来讲,同源策略是有利于保护网站信息的。 + +## 跨域问题怎么解决呢? + +嗯,有以下几种方法: + +**CORS**,跨域资源共享 + +CORS(Cross-origin resource sharing),跨域资源共享。CORS 其实是浏览器制定的一个规范,浏览器会自动进行 CORS 通信,它的实现主要在服务端,通过一些 HTTP Header 来限制可以访问的域,例如页面 A 需要访问 B 服务器上的数据,如果 B 服务器 上声明了允许 A 的域名访问,那么从 A 到 B 的跨域请求就可以完成。 + +**@CrossOrigin注解** + +如果项目使用的是Springboot,可以在Controller类上添加一个 @CrossOrigin(origins ="*") 注解就可以实现对当前controller 的跨域访问了,当然这个标签也可以加到方法上,或者直接加到入口类上对所有接口进行跨域处理。注意SpringMVC的版本要在4.2或以上版本才支持@CrossOrigin。 + +**nginx反向代理接口跨域** + +nginx反向代理跨域原理如下: 首先同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。 + +nginx反向代理接口跨域实现思路如下:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。 + +```js +// proxy服务器 +server { + listen 81; + server_name www.domain1.com; + location / { + proxy_pass http://www.domain2.com:8080; #反向代理 + proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 + index index.html index.htm; + + add_header Access-Control-Allow-Origin http://www.domain1.com; + } +} +``` + +这样我们的前端代理只要访问 http:www.domain1.com:81/*就可以了。 + +**通过jsonp跨域** + +通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,这是浏览器允许的操作,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。 -![](http://img.dabin-coder.cn/image/20220612101342.png) +![](http://img.dabin-coder.cn/image/20220612101342.png) \ No newline at end of file From f3e1054917b4db4d607f8a32afb45931733b47bf Mon Sep 17 00:00:00 2001 From: tyson Date: Sun, 6 Nov 2022 16:04:52 +0800 Subject: [PATCH 15/84] update --- ...7\272\347\241\200\351\235\242\350\257\225\351\242\230.md" | 5 ----- 1 file changed, 5 deletions(-) diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" index a3a25bb..bd5b11e 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ "b/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" @@ -1,8 +1,3 @@ ---- -sidebar: heading - ---- - ![](http://img.dabin-coder.cn/image/Java基础.jpg) ## Java的特点 From 72f3eb86e253ca44a5a1a13b360f66c3500eab66 Mon Sep 17 00:00:00 2001 From: tyson Date: Fri, 23 Dec 2022 09:22:56 +0800 Subject: [PATCH 16/84] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 23 +- CNAME | 1 + Java/JVM.md | 831 --- Java/Java web.md | 83 - ...26\347\250\213\346\200\235\346\203\263.md" | 3916 ----------- ...va\345\205\263\351\224\256\345\255\227.md" | 205 - "Java/Java\345\237\272\347\241\200.md" | 1582 ----- ...66\345\217\221\347\274\226\347\250\213.md" | 392 -- ...70\347\224\250\346\226\271\346\263\225.md" | 241 - "Java/\345\271\266\345\217\221.md" | 1166 ---- "Java/\351\233\206\345\220\210.md" | 479 -- README.md | 141 +- ...23\345\255\230\345\207\273\347\251\277.md" | 60 - docs/.vuepress/config.ts | 86 + docs/.vuepress/enhanceApp.js | 13 + docs/.vuepress/navbar.ts | 276 + docs/.vuepress/sidebar.ts | 176 + docs/.vuepress/styles/index.scss | 0 docs/.vuepress/styles/palette.scss | 0 docs/.vuepress/theme.ts | 166 + .../vuepress-sidebar-auto.js | 92 + docs/README.md | 82 + docs/about/contact.md | 27 + docs/about/introduce.md | 66 + docs/advance/concurrent/1-current-limiting.md | 139 + docs/advance/concurrent/2-load-balance.md | 164 + docs/advance/concurrent/README.md | 4 + .../advance/design-pattern-all.md | 0 docs/advance/design-pattern/1-principle.md | 9 + docs/advance/design-pattern/10-observer.md | 17 + docs/advance/design-pattern/11-proxy.md | 77 + docs/advance/design-pattern/12-builder.md | 79 + docs/advance/design-pattern/2-singleton.md | 94 + docs/advance/design-pattern/3-factory.md | 91 + docs/advance/design-pattern/4-template.md | 82 + docs/advance/design-pattern/5-strategy.md | 111 + docs/advance/design-pattern/6-chain.md | 190 + docs/advance/design-pattern/7-iterator.md | 30 + docs/advance/design-pattern/8-decorator.md | 20 + docs/advance/design-pattern/9-adapter.md | 18 + docs/advance/design-pattern/README.md | 25 + .../advance/distributed/1-global-unique-id.md | 30 +- .../advance/distributed/2-distributed-lock.md | 4 +- .../advance/distributed/3-rpc.md | 4 +- docs/advance/distributed/4-micro-service.md | 183 + docs/advance/distributed/5-distibuted-arch.md | 3 + .../distributed/6-distributed-transaction.md | 197 + docs/advance/distributed/README.md | 8 + .../excellent-article/1-redis-stock-minus.md | 317 + .../excellent-article/10-file-upload.md | 341 + .../11-8-architect-pattern.md | 3 + .../12-mysql-table-max-rows.md | 212 + .../excellent-article/13-order-by-work.md | 263 + .../excellent-article/14-architect-forward.md | 49 + .../excellent-article/15-http-vs-rpc.md | 265 + .../excellent-article/16-what-is-jwt.md | 167 + .../excellent-article/2-spring-transaction.md | 111 + .../3-springboot-auto-assembly.md | 544 ++ .../4-remove-duplicate-code.md | 595 ++ .../excellent-article/5-jvm-optimize.md | 94 + .../excellent-article/6-spring-three-cache.md | 119 + .../excellent-article/7-sql-optimize.md | 421 ++ .../8-interface-idempotent.md | 88 + .../excellent-article/9-jvm-optimize-param.md | 242 + docs/advance/excellent-article/README.md | 19 + .../system-design/1-scan-code-login.md | 43 +- .../2-order-timeout-auto-cancel.md | 616 ++ docs/advance/system-design/3-file-send.md | 17 + .../advance/system-design/3-short-url.md | 60 +- docs/advance/system-design/4-oversold.md | 30 + docs/advance/system-design/5-second-kill.md | 45 + .../6-wechat-redpacket-design.md | 134 + docs/advance/system-design/7-file-send.md | 17 + docs/advance/system-design/8-sso-design.md | 113 + docs/advance/system-design/README.md | 11 + ...3\346\215\267\346\226\271\345\274\217.lnk" | Bin 0 -> 705 bytes docs/campus-recruit/README.md | 3 + docs/campus-recruit/career-plan.md | 37 + .../interview}/1-byte-and-dance.md | 0 .../campus-recruit/interview}/10-netease.md | 0 .../campus-recruit/interview}/2-tencent.md | 2 +- .../campus-recruit/interview}/3-baidu.md | 0 .../campus-recruit/interview}/4-ali.md | 0 .../campus-recruit/interview}/5-kuaishou.md | 0 .../campus-recruit/interview}/6-meituan.md | 0 .../campus-recruit/interview}/7-shopee.md | 0 .../campus-recruit/interview}/8-jingdong.md | 0 .../campus-recruit/interview}/9-huawei.md | 0 .../campus-recruit/interview}/README.md | 0 docs/campus-recruit/layoffs-solution.md | 24 + .../campus-recruit/program-language/README.md | 5 + .../program-language/java-or-c++.md | 34 + .../program-language/java-or-golang.md | 73 + docs/campus-recruit/project-experience.md | 124 + docs/campus-recruit/resume.md | 136 + docs/campus-recruit/share/1-23-backend.md | 108 + docs/campus-recruit/share/2-no-offer.md | 56 + docs/campus-recruit/share/README.md | 5 + docs/computer-basic/algorithm.md | 1440 ++++ .../computer-basic/data-structure.md | 128 +- docs/computer-basic/network.md | 601 ++ .../computer-basic/operate-system.md | 10 +- .../\345\233\276\350\247\243HTTP.md" | 6 +- docs/database/es/1-es-architect.md | 53 + .../database/mysql-basic-all.md | 224 +- docs/database/mysql-basic/1-data-type.md | 82 + docs/database/mysql-basic/10-view.md | 50 + docs/database/mysql-basic/11-procedure.md | 101 + docs/database/mysql-basic/12-cursor.md | 58 + docs/database/mysql-basic/13-trigger.md | 51 + docs/database/mysql-basic/14-transaction.md | 32 + docs/database/mysql-basic/15-permission.md | 35 + .../mysql-basic/16-performace-optimization.md | 18 + docs/database/mysql-basic/17-index.md | 36 + docs/database/mysql-basic/2-basic-command.md | 230 + docs/database/mysql-basic/3-function.md | 42 + docs/database/mysql-basic/4-sum.md | 22 + docs/database/mysql-basic/5-group.md | 56 + docs/database/mysql-basic/6-join.md | 92 + .../database/mysql-basic/7-full-text-query.md | 39 + docs/database/mysql-basic/8-table-operate.md | 105 + docs/database/mysql-basic/9-column-operate.md | 48 + docs/database/mysql-basic/README.md | 31 + .../database/mysql-execution-plan.md | 38 +- .../database/mysql.md | 221 +- docs/distributed/1-global-unique-id.md | 489 ++ docs/distributed/2-distributed-lock.md | 259 + docs/distributed/2.1-rpc.md | 123 + .../distributed/3-micro-service.md | 6 +- docs/distributed/4-distibuted-arch.md | 3 + docs/distributed/5-distributed-transaction.md | 199 + ...PC\347\232\204\345\216\237\347\220\206.md" | 0 ...15\347\275\256\344\270\255\345\277\203.md" | 0 .../framework/mybatis.md | 15 +- .../framework/netty-overview.md | 245 +- docs/framework/netty/1-overview.md | 16 + docs/framework/netty/10-encoder-decoder.md | 146 + .../netty/11-preset-channel-handler.md | 409 ++ docs/framework/netty/2-make-your-app.md | 186 + docs/framework/netty/3-component.md | 70 + docs/framework/netty/4-transport.md | 66 + docs/framework/netty/6-channel-handler.md | 88 + docs/framework/netty/7-channel-pipeline.md | 79 + .../netty/8-eventloop-thread-model.md | 46 + docs/framework/netty/9-guide.md | 57 + docs/framework/netty/README.md | 24 + .../framework/spring.md | 64 +- .../framework/springboot.md | 65 +- docs/framework/springcloud-interview.md | 249 + .../framework/springcloud-overview.md | 110 +- docs/framework/springcloud/1-basic.md | 48 + docs/framework/springcloud/10-bus.md | 6 + docs/framework/springcloud/11-security.md | 28 + .../2-springboot-springcloud-diff.md | 9 + docs/framework/springcloud/3-eureka.md | 117 + docs/framework/springcloud/4-ribbon.md | 132 + docs/framework/springcloud/5-hystrix.md | 82 + docs/framework/springcloud/6-feign.md | 120 + docs/framework/springcloud/7-zuul.md | 278 + docs/framework/springcloud/8-gateway.md | 407 ++ docs/framework/springcloud/9-config.md | 274 + docs/framework/springcloud/README.md | 22 + docs/framework/springmvc.md | 188 + .../concurrent/1-forbid-default-executor.md | 43 + docs/interview/java/1-create-object.md | 9 + docs/interview/java/2-3rd-interface.md | 13 + docs/interview/java/3-design-interface.md | 11 + docs/interview/java/4-interface-slow.md | 19 + .../java/5-comparable-vs-comparator.md | 14 + docs/interview/java/README.md | 7 + .../interview/javaweb/1-interceptor-filter.md | 27 + docs/interview/mq/1-why-to-use-mq.md | 32 + .../network/1-input-url-return-page.md | 25 + docs/interview/network/2-http-status-code.md | 86 + .../java/java-basic.md | 74 + .../java/java-collection.md | 48 +- .../java/java-concurrent.md | 148 +- .../java/java8-all.md | 83 +- docs/java/java8/1-functional-program.md | 16 + docs/java/java8/2-lambda.md | 26 + docs/java/java8/3-functional-interface.md | 25 + .../java8/4-inner-functional-interface.md | 149 + docs/java/java8/5-stream.md | 272 + docs/java/java8/6-parallel-stream.md | 31 + docs/java/java8/7-map.md | 118 + docs/java/java8/README.md | 11 + .../java/jvm.md | 80 +- docs/learn/ghelper.md | 63 + docs/learn/leetcode.md | 25 + docs/learn/manual.md | 22 + docs/learning-resources/chang-gou-mall.md | 15 + docs/learning-resources/cs-learn-guide.md | 273 + docs/learning-resources/java-learn-guide.md | 810 +++ docs/learning-resources/leetcode-note.md | 26 + docs/learning-resources/mysql-top.md | 213 + docs/learning-resources/mysql45-section.md | 19 + docs/learning-resources/sgg-java-learn.md | 33 + docs/learning-resources/shang-chou.md | 13 + docs/learning-resources/springboot-guide.md | 21 + docs/leetcode/README.md | 40 + docs/leetcode/hot120/1-two-sum.md | 49 + ...inary-tree-zigzag-level-order-traversal.md | 69 + .../104-maximum-depth-of-binary-tree.md | 52 + .../hot120/11-container-with-most-water.md | 52 + .../hot120/1143-longest-common-subquence.md | 102 + docs/leetcode/hot120/120-triangle.md | 47 + .../121-best-time-to-buy-and-sell-stock.md | 41 + .../122-best-time-to-buy-and-sell-stock-ii.md | 43 + .../128-longest-consecutive-sequence.md | 54 + .../leetcode/hot120/131-palindrome-partion.md | 69 + docs/leetcode/hot120/133-clone-graph.md | 89 + docs/leetcode/hot120/134-gas-station.md | 50 + docs/leetcode/hot120/141-linked-list-cycle.md | 96 + docs/leetcode/hot120/148-sort-list.md | 112 + docs/leetcode/hot120/15-3sum.md | 62 + .../hot120/152-maximum-product-subarray.md | 45 + .../160-intersection-of-two-linked-lists.md | 39 + docs/leetcode/hot120/169-majority-element.md | 47 + docs/leetcode/hot120/18-4sum .md | 76 + .../19-remove-nth-node-from-end-of-list.md | 55 + .../hot120/199-binary-tree-right-side-view.md | 51 + docs/leetcode/hot120/20-valid-parentheses.md | 56 + docs/leetcode/hot120/200-number-of-islands.md | 65 + .../hot120/206-reverse-linked-list.md | 44 + .../hot120/21-merge-two-sorted-lists.md | 41 + .../215-kth-largest-element-in-an-array.md | 94 + .../hot120/22-generate-parentheses.md | 105 + .../hot120/234-palindrome-linked-list.md | 56 + ...lowest-common-ancestor-of-a-binary-tree.md | 41 + .../leetcode/hot120/24-swap-nodes-in-pairs.md | 42 + .../26-remove-duplicates-from-sorted-array.md | 56 + docs/leetcode/hot120/27-remove-element.md | 44 + docs/leetcode/hot120/28-mirror-binary-tree.md | 44 + .../leetcode/hot120/29-divide-two-integers.md | 65 + ...-substring-without-repeating-characters.md | 59 + docs/leetcode/hot120/31-next-permutation.md | 53 + ...ast-position-of-element-in-sorted-array.md | 56 + docs/leetcode/hot120/36-valid-sudoku.md | 75 + docs/leetcode/hot120/40-combination-sum-ii.md | 68 + docs/leetcode/hot120/415-add-strings.md | 48 + docs/leetcode/hot120/43-multiply-strings.md | 53 + docs/leetcode/hot120/46-permutations.md | 49 + docs/leetcode/hot120/47-permutations-ii.md | 63 + docs/leetcode/hot120/48-rotate-image.md | 49 + docs/leetcode/hot120/49-group-anagrams.md | 44 + .../hot120/5-longest-palindromic-substring.md | 68 + docs/leetcode/hot120/50-powx-n.md | 41 + docs/leetcode/hot120/53-maximum-subarray.md | 37 + docs/leetcode/hot120/54-spiral-matrix.md | 71 + .../hot120/543-diameter-of-binary-tree.md | 47 + docs/leetcode/hot120/55-jump-game.md | 47 + docs/leetcode/hot120/56-merge-intervals.md | 43 + docs/leetcode/hot120/59-spiral-matrix-ii.md | 60 + docs/leetcode/hot120/62-unique-paths.md | 120 + docs/leetcode/hot120/7-reverse-integer.md | 58 + docs/leetcode/hot120/71-simplify-path.md | 73 + docs/leetcode/hot120/73-set-matrix-zeroes.md | 76 + docs/leetcode/hot120/74-search-a-2d-matrix.md | 54 + docs/leetcode/hot120/75-sort-colors.md | 51 + docs/leetcode/hot120/77-combinations.md | 67 + .../83-remove-duplicates-from-sorted-list.md | 39 + docs/leetcode/hot120/9-palindrome-number.md | 51 + .../hot120/92-reverse-linked-list-ii.md | 41 + ...958-check-completeness-of-a-binary-tree.md | 57 + .../hot120/98-validate-binary-search-tree.md | 56 + docs/leetcode/hot120/README.md | 41 + .../mass-data/1-count-phone-num.md | 8 +- .../mass-data/2-find-hign-frequency-word.md | 17 +- docs/mass-data/3-find-same-url.md | 30 + docs/mass-data/4-find-mid-num.md | 36 + docs/mass-data/5-find-hot-string.md | 54 + docs/mass-data/6-top-500-num.md | 116 + docs/mass-data/7-query-frequency-sort.md | 33 + docs/mass-data/8-topk-template.md | 166 + docs/mass-data/README.md | 12 + .../kafka.md" => docs/message-queue/kafka.md | 0 docs/message-queue/mq.md | 181 + .../message-queue/rabbitmq.md | 0 docs/other/leave-a-message.md | 4 + docs/other/site-diary.md | 109 + .../service-performance-optimization.md | 25 + .../redis/redis-basic-all.md | 0 docs/redis/redis-basic/1-introduce.md | 36 + docs/redis/redis-basic/10-lua.md | 70 + docs/redis/redis-basic/11-deletion-policy.md | 26 + docs/redis/redis-basic/12-others.md | 81 + docs/redis/redis-basic/2-data-type.md | 318 + docs/redis/redis-basic/3-data-structure.md | 100 + docs/redis/redis-basic/4-implement.md | 68 + docs/redis/redis-basic/5-sort.md | 36 + docs/redis/redis-basic/6-transaction.md | 61 + docs/redis/redis-basic/7-message-queue.md | 31 + docs/redis/redis-basic/8-persistence.md | 67 + docs/redis/redis-basic/9-cluster.md | 121 + docs/redis/redis-basic/README.md | 26 + .../redis/redis.md | 78 +- docs/resource/1-cs-books.md | 329 + .../tools/docker-overview.md | 152 +- docs/tools/docker/1-introduce.md | 27 + docs/tools/docker/2-image-command.md | 209 + docs/tools/docker/3-container-command.md | 242 + docs/tools/docker/4-docker-compose.md | 102 + docs/tools/docker/5-maven-build.md | 136 + docs/tools/docker/6-other.md | 53 + docs/tools/docker/README.md | 17 + .../tools/git-overview.md | 143 +- docs/tools/git/1-introduce.md | 71 + docs/tools/git/2-basic.md | 280 + docs/tools/git/3-remote-repo.md | 110 + docs/tools/git/4-label.md | 101 + docs/tools/git/5-branch.md | 305 + docs/tools/git/README.md | 17 + .../tools/linux-overview.md | 0 docs/tools/linux/1-basic.md | 172 + docs/tools/linux/2-disk-file.md | 159 + docs/tools/linux/3-search.md | 59 + docs/tools/linux/4-net.md | 125 + docs/tools/linux/5-monitor.md | 131 + docs/tools/linux/README.md | 12 + .../tools/maven-overview.md | 127 +- docs/tools/maven/1-introduce.md | 12 + docs/tools/maven/2-basic.md | 104 + docs/tools/maven/3-dependency.md | 53 + docs/tools/maven/4-repo.md | 88 + docs/tools/maven/5-lifecycle.md | 24 + docs/tools/maven/6-plugin.md | 63 + docs/tools/maven/7-aggregator.md | 17 + docs/tools/maven/8-inherit.md | 169 + docs/tools/maven/README.md | 20 + docs/tools/typora-overview.md | 184 + img/1588431199776.png | Bin 63521 -> 0 bytes img/ConcurrentHashMap-segment.jpg | Bin 230179 -> 0 bytes img/JDK1.8-ConcurrentHashMap-Structure.jpg | Bin 12869 -> 0 bytes img/Java-Collections.jpeg | Bin 167969 -> 0 bytes img/all-table-search.jpg | Bin 14178 -> 0 bytes img/aqs.png | Bin 21797 -> 0 bytes img/bean-life-cycle.jpg | Bin 29410 -> 0 bytes img/bloom-filter.jpg | Bin 23578 -> 0 bytes img/cms-collector.png | Bin 86817 -> 0 bytes img/concurrent/executors-ali.png | Bin 114331 -> 0 bytes img/concurrent/synchronized-block.png | Bin 188866 -> 0 bytes img/concurrent/synchronized-method.png | Bin 127575 -> 0 bytes img/condition-await.png | Bin 49132 -> 0 bytes img/condition-signal.png | Bin 48475 -> 0 bytes img/condition-wait-queue.png | Bin 46923 -> 0 bytes img/cover-index.png | Bin 25311 -> 0 bytes img/direct-pointer.png | Bin 94396 -> 0 bytes img/docker/docker.jpg | Bin 88608 -> 0 bytes img/explain-all.png | Bin 8446 -> 0 bytes img/explain-const.png | Bin 4419 -> 0 bytes img/explain-id.png | Bin 5014 -> 0 bytes img/explain-range.png | Bin 4762 -> 0 bytes img/explain-ref.png | Bin 10220 -> 0 bytes img/g1-region.jpg | Bin 19644 -> 0 bytes img/gc-root-refer.png | Bin 14443 -> 0 bytes img/git-status.png | Bin 109277 -> 0 bytes img/heap-structure.png | Bin 56484 -> 0 bytes img/image-20200520234137916.png | Bin 13219 -> 0 bytes img/image-20200520234200868.png | Bin 26483 -> 0 bytes img/image-20200520234231001.png | Bin 25332 -> 0 bytes img/image-20200608232749393.png | Bin 4492 -> 0 bytes img/image-20200608232951873.png | Bin 2591 -> 0 bytes img/image-20200608233400458.png | Bin 2946 -> 0 bytes img/image-20200614165333479.png | Bin 208621 -> 0 bytes img/image-20200614165432775.png | Bin 195674 -> 0 bytes img/index-search-range.jpg | Bin 14490 -> 0 bytes img/index-search.jpg | Bin 12920 -> 0 bytes img/java-basic/exception.png | Bin 37810 -> 0 bytes img/java-basic/field-method.png | Bin 118178 -> 0 bytes img/java-basic/io.jpg | Bin 50725 -> 0 bytes img/java-ram-region.png | Bin 110051 -> 0 bytes img/jmeter/http-request-param.png | Bin 30984 -> 0 bytes img/jmeter/jmeter-aggregate-report.png | Bin 49256 -> 0 bytes img/jmeter/jmeter-default-request.png | Bin 79751 -> 0 bytes img/jmeter/jmeter-request-header.png | Bin 75457 -> 0 bytes img/jmeter/jmeter-thread-group.png | Bin 34358 -> 0 bytes img/jvm/string-equal.png | Bin 33445 -> 0 bytes img/jvm/string-intern.png | Bin 36462 -> 0 bytes img/jvm/string-new.png | Bin 28718 -> 0 bytes img/left-match.jpg | Bin 31737 -> 0 bytes img/middleware/redis-transaction.png | Bin 7291 -> 0 bytes img/middleware/redis-usage.png | Bin 31580 -> 0 bytes img/mysql-architecture.png | Bin 1229182 -> 0 bytes img/mysql-clustered-index.png | Bin 35301 -> 0 bytes img/mysql/arch.png | Bin 69339 -> 0 bytes img/mysql/current-read.png | Bin 10277 -> 0 bytes img/mysql/mvcc-impl.png | Bin 38026 -> 0 bytes img/mysql/myisam-innodb-index.png | Bin 82352 -> 0 bytes img/mysql/mysql-archpng.png | Bin 223491 -> 0 bytes img/mysql/nested-loop.png | Bin 129701 -> 0 bytes img/mysql/orderby.png | Bin 6252 -> 0 bytes img/net/bio.png | Bin 6774 -> 0 bytes img/net/cdn.png | Bin 942422 -> 0 bytes img/net/https-certificate-chain.jpg | Bin 33273 -> 0 bytes img/net/https-certificate.png | Bin 34566 -> 0 bytes img/net/https-client-hello.jpg | Bin 86157 -> 0 bytes img/net/https-server-hello.jpg | Bin 37249 -> 0 bytes img/net/nio.png | Bin 7276 -> 0 bytes img/oauth2.png | Bin 10836 -> 0 bytes img/object-dead.png | Bin 49726 -> 0 bytes img/object-handle.png | Bin 110349 -> 0 bytes img/optimistic-lock.jpg | Bin 39394 -> 0 bytes img/others/json-web-token.png | Bin 61702 -> 0 bytes img/others/seckill.jpg | Bin 32958 -> 0 bytes img/parnew-collector.png | Bin 42532 -> 0 bytes img/rabbitmq-direct.png | Bin 8762 -> 0 bytes img/rabbitmq-fanout.png | Bin 9472 -> 0 bytes img/rabbitmq-return-listener.png | Bin 48332 -> 0 bytes img/rabbitmq-topic.png | Bin 12484 -> 0 bytes img/rabbitmq.png | Bin 6474 -> 0 bytes img/redis/cache-consist.png | Bin 23667 -> 0 bytes img/redis/evalsha.png | Bin 184215 -> 0 bytes img/redis/list-api.png | Bin 178712 -> 0 bytes img/redis/redis-replication.png | Bin 178354 -> 0 bytes img/redis/redis-skiplist.png | Bin 11736 -> 0 bytes img/redis/time-complexity.png | Bin 421110 -> 0 bytes ...0\344\272\222\346\226\245\351\224\201.png" | Bin 232236 -> 0 bytes img/scheduled-task.jpg | Bin 85304 -> 0 bytes img/serial-collector.png | Bin 34121 -> 0 bytes img/singleton-class-init.png | Bin 49462 -> 0 bytes ...7\345\210\253\346\263\250\350\247\243.png" | Bin 57651 -> 0 bytes ...5\347\275\256\345\216\237\347\220\206.jpg" | Bin 851247 -> 0 bytes img/thread-pool.png | Bin 17381 -> 0 bytes img/thread-status.jpeg | Bin 88664 -> 0 bytes img/threadlocal-oom.png | Bin 23902 -> 0 bytes img/threadlocal.png | Bin 17096 -> 0 bytes img/tree-visit.png | Bin 25772 -> 0 bytes img/two-index.jpg | Bin 15986 -> 0 bytes img/web/servlet-container.jpg | Bin 22543 -> 0 bytes "img/\345\271\273\350\257\2731.png" | Bin 22122 -> 0 bytes ...5\345\241\236\346\216\247\345\210\266.jpg" | Bin 48625 -> 0 bytes ...5\347\275\256\346\226\271\346\263\225.png" | Bin 49050 -> 0 bytes package-lock.json | 6195 +++++++++++++++++ package.json | 26 + .../Elasticsearch\345\205\245\351\227\250.md" | 2438 ------- "\345\205\266\344\273\226/code.md" | 77 - "\345\205\266\344\273\226/linux.md" | 417 -- "\345\205\266\344\273\226/note.md" | 286 - .../\345\256\236\346\210\230\347\257\207.md" | 93 - ...03\345\274\217\344\272\213\345\212\241.md" | 77 - ...03\345\274\217\347\274\223\345\255\230.md" | 98 - "\345\211\215\347\253\257/vue.md" | 401 -- .../GitHub\346\214\207\345\215\227.md" | 91 - "\345\267\245\345\205\267/NPM.md" | 48 - "\345\267\245\345\205\267/jenkins.md" | 120 - "\345\267\245\345\205\267/jmeter.md" | 39 - ...50\347\275\262\351\241\271\347\233\256.md" | 325 - .../MySQL\350\277\233\351\230\266.md" | 811 --- .../SpringBoot\345\256\236\346\210\230.md" | 1028 --- "\346\241\206\346\236\266/SpringMVC.md" | 1602 ----- ...VC\351\235\242\350\257\225\351\242\230.md" | 89 - .../Spring\345\256\236\346\210\230.md" | 3228 --------- .../Spring\346\200\273\347\273\223.md" | 471 -- ...76\350\256\241\346\250\241\345\274\217.md" | 67 - ...52\345\212\250\350\243\205\351\205\215.md" | 187 - ...06\344\270\216\345\256\236\346\210\230.md" | 2435 ------- ...73\344\277\241\351\230\237\345\210\227.md" | 117 - ...27\351\235\242\350\257\225\351\242\230.md" | 72 - ...347\273\237\350\256\276\350\256\241old.md" | 24 - .../\347\256\227\346\263\225.md" | 374 - .../TCP IP\345\215\217\350\256\256.md" | 349 - .../session\345\222\214cookie.md" | 23 - .../\347\275\221\347\273\234.md" | 362 - ...21\351\235\242\350\257\225\351\242\230.md" | 315 - 464 files changed, 34561 insertions(+), 26055 deletions(-) create mode 100644 CNAME delete mode 100644 Java/JVM.md delete mode 100644 Java/Java web.md delete mode 100644 "Java/Java \347\274\226\347\250\213\346\200\235\346\203\263.md" delete mode 100644 "Java/Java\345\205\263\351\224\256\345\255\227.md" delete mode 100644 "Java/Java\345\237\272\347\241\200.md" delete mode 100644 "Java/Java\345\271\266\345\217\221\347\274\226\347\250\213.md" delete mode 100644 "Java/Object\347\261\273\345\270\270\347\224\250\346\226\271\346\263\225.md" delete mode 100644 "Java/\345\271\266\345\217\221.md" delete mode 100644 "Java/\351\233\206\345\220\210.md" delete mode 100644 "Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" create mode 100644 docs/.vuepress/config.ts create mode 100644 docs/.vuepress/enhanceApp.js create mode 100644 docs/.vuepress/navbar.ts create mode 100644 docs/.vuepress/sidebar.ts create mode 100644 docs/.vuepress/styles/index.scss create mode 100644 docs/.vuepress/styles/palette.scss create mode 100644 docs/.vuepress/theme.ts create mode 100644 docs/.vuepress/vuepress-sidebar-auto/vuepress-sidebar-auto.js create mode 100644 docs/README.md create mode 100644 docs/about/contact.md create mode 100644 docs/about/introduce.md create mode 100644 docs/advance/concurrent/1-current-limiting.md create mode 100644 docs/advance/concurrent/2-load-balance.md create mode 100644 docs/advance/concurrent/README.md rename "\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" => docs/advance/design-pattern-all.md (100%) create mode 100644 docs/advance/design-pattern/1-principle.md create mode 100644 docs/advance/design-pattern/10-observer.md create mode 100644 docs/advance/design-pattern/11-proxy.md create mode 100644 docs/advance/design-pattern/12-builder.md create mode 100644 docs/advance/design-pattern/2-singleton.md create mode 100644 docs/advance/design-pattern/3-factory.md create mode 100644 docs/advance/design-pattern/4-template.md create mode 100644 docs/advance/design-pattern/5-strategy.md create mode 100644 docs/advance/design-pattern/6-chain.md create mode 100644 docs/advance/design-pattern/7-iterator.md create mode 100644 docs/advance/design-pattern/8-decorator.md create mode 100644 docs/advance/design-pattern/9-adapter.md create mode 100644 docs/advance/design-pattern/README.md rename "\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" => docs/advance/distributed/1-global-unique-id.md (97%) rename "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" => docs/advance/distributed/2-distributed-lock.md (99%) rename "\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" => docs/advance/distributed/3-rpc.md (99%) create mode 100644 docs/advance/distributed/4-micro-service.md create mode 100644 docs/advance/distributed/5-distibuted-arch.md create mode 100644 docs/advance/distributed/6-distributed-transaction.md create mode 100644 docs/advance/distributed/README.md create mode 100644 docs/advance/excellent-article/1-redis-stock-minus.md create mode 100644 docs/advance/excellent-article/10-file-upload.md create mode 100644 docs/advance/excellent-article/11-8-architect-pattern.md create mode 100644 docs/advance/excellent-article/12-mysql-table-max-rows.md create mode 100644 docs/advance/excellent-article/13-order-by-work.md create mode 100644 docs/advance/excellent-article/14-architect-forward.md create mode 100644 docs/advance/excellent-article/15-http-vs-rpc.md create mode 100644 docs/advance/excellent-article/16-what-is-jwt.md create mode 100644 docs/advance/excellent-article/2-spring-transaction.md create mode 100644 docs/advance/excellent-article/3-springboot-auto-assembly.md create mode 100644 docs/advance/excellent-article/4-remove-duplicate-code.md create mode 100644 docs/advance/excellent-article/5-jvm-optimize.md create mode 100644 docs/advance/excellent-article/6-spring-three-cache.md create mode 100644 docs/advance/excellent-article/7-sql-optimize.md create mode 100644 docs/advance/excellent-article/8-interface-idempotent.md create mode 100644 docs/advance/excellent-article/9-jvm-optimize-param.md create mode 100644 docs/advance/excellent-article/README.md rename "\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" => docs/advance/system-design/1-scan-code-login.md (51%) create mode 100644 docs/advance/system-design/2-order-timeout-auto-cancel.md create mode 100644 docs/advance/system-design/3-file-send.md rename "\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" => docs/advance/system-design/3-short-url.md (61%) create mode 100644 docs/advance/system-design/4-oversold.md create mode 100644 docs/advance/system-design/5-second-kill.md create mode 100644 docs/advance/system-design/6-wechat-redpacket-design.md create mode 100644 docs/advance/system-design/7-file-send.md create mode 100644 docs/advance/system-design/8-sso-design.md create mode 100644 docs/advance/system-design/README.md create mode 100644 "docs/advance/system-design/\345\233\276\347\211\207 - \345\277\253\346\215\267\346\226\271\345\274\217.lnk" create mode 100644 docs/campus-recruit/README.md create mode 100644 docs/campus-recruit/career-plan.md rename {interview => docs/campus-recruit/interview}/1-byte-and-dance.md (100%) rename {interview => docs/campus-recruit/interview}/10-netease.md (100%) rename {interview => docs/campus-recruit/interview}/2-tencent.md (98%) rename {interview => docs/campus-recruit/interview}/3-baidu.md (100%) rename {interview => docs/campus-recruit/interview}/4-ali.md (100%) rename {interview => docs/campus-recruit/interview}/5-kuaishou.md (100%) rename {interview => docs/campus-recruit/interview}/6-meituan.md (100%) rename {interview => docs/campus-recruit/interview}/7-shopee.md (100%) rename {interview => docs/campus-recruit/interview}/8-jingdong.md (100%) rename {interview => docs/campus-recruit/interview}/9-huawei.md (100%) rename {interview => docs/campus-recruit/interview}/README.md (100%) create mode 100644 docs/campus-recruit/layoffs-solution.md create mode 100644 docs/campus-recruit/program-language/README.md create mode 100644 docs/campus-recruit/program-language/java-or-c++.md create mode 100644 docs/campus-recruit/program-language/java-or-golang.md create mode 100644 docs/campus-recruit/project-experience.md create mode 100644 docs/campus-recruit/resume.md create mode 100644 docs/campus-recruit/share/1-23-backend.md create mode 100644 docs/campus-recruit/share/2-no-offer.md create mode 100644 docs/campus-recruit/share/README.md create mode 100644 docs/computer-basic/algorithm.md rename "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" => docs/computer-basic/data-structure.md (62%) create mode 100644 docs/computer-basic/network.md rename "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\223\215\344\275\234\347\263\273\347\273\237/\346\223\215\344\275\234\347\263\273\347\273\237\351\235\242\350\257\225\351\242\230.md" => docs/computer-basic/operate-system.md (98%) rename "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\345\233\276\350\247\243HTTP.md" => "docs/computer-basic/\345\233\276\350\247\243HTTP.md" (99%) create mode 100644 docs/database/es/1-es-architect.md rename "\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" => docs/database/mysql-basic-all.md (94%) create mode 100644 docs/database/mysql-basic/1-data-type.md create mode 100644 docs/database/mysql-basic/10-view.md create mode 100644 docs/database/mysql-basic/11-procedure.md create mode 100644 docs/database/mysql-basic/12-cursor.md create mode 100644 docs/database/mysql-basic/13-trigger.md create mode 100644 docs/database/mysql-basic/14-transaction.md create mode 100644 docs/database/mysql-basic/15-permission.md create mode 100644 docs/database/mysql-basic/16-performace-optimization.md create mode 100644 docs/database/mysql-basic/17-index.md create mode 100644 docs/database/mysql-basic/2-basic-command.md create mode 100644 docs/database/mysql-basic/3-function.md create mode 100644 docs/database/mysql-basic/4-sum.md create mode 100644 docs/database/mysql-basic/5-group.md create mode 100644 docs/database/mysql-basic/6-join.md create mode 100644 docs/database/mysql-basic/7-full-text-query.md create mode 100644 docs/database/mysql-basic/8-table-operate.md create mode 100644 docs/database/mysql-basic/9-column-operate.md create mode 100644 docs/database/mysql-basic/README.md rename "\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" => docs/database/mysql-execution-plan.md (92%) rename "\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" => docs/database/mysql.md (77%) create mode 100644 docs/distributed/1-global-unique-id.md create mode 100644 docs/distributed/2-distributed-lock.md create mode 100644 docs/distributed/2.1-rpc.md rename "\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" => docs/distributed/3-micro-service.md (99%) create mode 100644 docs/distributed/4-distibuted-arch.md create mode 100644 docs/distributed/5-distributed-transaction.md rename "\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" => "docs/distributed/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" (100%) rename "\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" => "docs/framework/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" (100%) rename "\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" => docs/framework/mybatis.md (86%) rename "\346\241\206\346\236\266/netty\345\256\236\346\210\230.md" => docs/framework/netty-overview.md (84%) create mode 100644 docs/framework/netty/1-overview.md create mode 100644 docs/framework/netty/10-encoder-decoder.md create mode 100644 docs/framework/netty/11-preset-channel-handler.md create mode 100644 docs/framework/netty/2-make-your-app.md create mode 100644 docs/framework/netty/3-component.md create mode 100644 docs/framework/netty/4-transport.md create mode 100644 docs/framework/netty/6-channel-handler.md create mode 100644 docs/framework/netty/7-channel-pipeline.md create mode 100644 docs/framework/netty/8-eventloop-thread-model.md create mode 100644 docs/framework/netty/9-guide.md create mode 100644 docs/framework/netty/README.md rename "\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" => docs/framework/spring.md (92%) rename "\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" => docs/framework/springboot.md (74%) create mode 100644 docs/framework/springcloud-interview.md rename "\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" => docs/framework/springcloud-overview.md (96%) create mode 100644 docs/framework/springcloud/1-basic.md create mode 100644 docs/framework/springcloud/10-bus.md create mode 100644 docs/framework/springcloud/11-security.md create mode 100644 docs/framework/springcloud/2-springboot-springcloud-diff.md create mode 100644 docs/framework/springcloud/3-eureka.md create mode 100644 docs/framework/springcloud/4-ribbon.md create mode 100644 docs/framework/springcloud/5-hystrix.md create mode 100644 docs/framework/springcloud/6-feign.md create mode 100644 docs/framework/springcloud/7-zuul.md create mode 100644 docs/framework/springcloud/8-gateway.md create mode 100644 docs/framework/springcloud/9-config.md create mode 100644 docs/framework/springcloud/README.md create mode 100644 docs/framework/springmvc.md create mode 100644 docs/interview/concurrent/1-forbid-default-executor.md create mode 100644 docs/interview/java/1-create-object.md create mode 100644 docs/interview/java/2-3rd-interface.md create mode 100644 docs/interview/java/3-design-interface.md create mode 100644 docs/interview/java/4-interface-slow.md create mode 100644 docs/interview/java/5-comparable-vs-comparator.md create mode 100644 docs/interview/java/README.md create mode 100644 docs/interview/javaweb/1-interceptor-filter.md create mode 100644 docs/interview/mq/1-why-to-use-mq.md create mode 100644 docs/interview/network/1-input-url-return-page.md create mode 100644 docs/interview/network/2-http-status-code.md rename "Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" => docs/java/java-basic.md (91%) rename "Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" => docs/java/java-collection.md (91%) rename "Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" => docs/java/java-concurrent.md (84%) rename "Java/Java8\346\226\260\347\211\271\346\200\247.md" => docs/java/java8-all.md (87%) create mode 100644 docs/java/java8/1-functional-program.md create mode 100644 docs/java/java8/2-lambda.md create mode 100644 docs/java/java8/3-functional-interface.md create mode 100644 docs/java/java8/4-inner-functional-interface.md create mode 100644 docs/java/java8/5-stream.md create mode 100644 docs/java/java8/6-parallel-stream.md create mode 100644 docs/java/java8/7-map.md create mode 100644 docs/java/java8/README.md rename "Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" => docs/java/jvm.md (87%) create mode 100644 docs/learn/ghelper.md create mode 100644 docs/learn/leetcode.md create mode 100644 docs/learn/manual.md create mode 100644 docs/learning-resources/chang-gou-mall.md create mode 100644 docs/learning-resources/cs-learn-guide.md create mode 100644 docs/learning-resources/java-learn-guide.md create mode 100644 docs/learning-resources/leetcode-note.md create mode 100644 docs/learning-resources/mysql-top.md create mode 100644 docs/learning-resources/mysql45-section.md create mode 100644 docs/learning-resources/sgg-java-learn.md create mode 100644 docs/learning-resources/shang-chou.md create mode 100644 docs/learning-resources/springboot-guide.md create mode 100644 docs/leetcode/README.md create mode 100644 docs/leetcode/hot120/1-two-sum.md create mode 100644 docs/leetcode/hot120/103-binary-tree-zigzag-level-order-traversal.md create mode 100644 docs/leetcode/hot120/104-maximum-depth-of-binary-tree.md create mode 100644 docs/leetcode/hot120/11-container-with-most-water.md create mode 100644 docs/leetcode/hot120/1143-longest-common-subquence.md create mode 100644 docs/leetcode/hot120/120-triangle.md create mode 100644 docs/leetcode/hot120/121-best-time-to-buy-and-sell-stock.md create mode 100644 docs/leetcode/hot120/122-best-time-to-buy-and-sell-stock-ii.md create mode 100644 docs/leetcode/hot120/128-longest-consecutive-sequence.md create mode 100644 docs/leetcode/hot120/131-palindrome-partion.md create mode 100644 docs/leetcode/hot120/133-clone-graph.md create mode 100644 docs/leetcode/hot120/134-gas-station.md create mode 100644 docs/leetcode/hot120/141-linked-list-cycle.md create mode 100644 docs/leetcode/hot120/148-sort-list.md create mode 100644 docs/leetcode/hot120/15-3sum.md create mode 100644 docs/leetcode/hot120/152-maximum-product-subarray.md create mode 100644 docs/leetcode/hot120/160-intersection-of-two-linked-lists.md create mode 100644 docs/leetcode/hot120/169-majority-element.md create mode 100644 docs/leetcode/hot120/18-4sum .md create mode 100644 docs/leetcode/hot120/19-remove-nth-node-from-end-of-list.md create mode 100644 docs/leetcode/hot120/199-binary-tree-right-side-view.md create mode 100644 docs/leetcode/hot120/20-valid-parentheses.md create mode 100644 docs/leetcode/hot120/200-number-of-islands.md create mode 100644 docs/leetcode/hot120/206-reverse-linked-list.md create mode 100644 docs/leetcode/hot120/21-merge-two-sorted-lists.md create mode 100644 docs/leetcode/hot120/215-kth-largest-element-in-an-array.md create mode 100644 docs/leetcode/hot120/22-generate-parentheses.md create mode 100644 docs/leetcode/hot120/234-palindrome-linked-list.md create mode 100644 docs/leetcode/hot120/236-lowest-common-ancestor-of-a-binary-tree.md create mode 100644 docs/leetcode/hot120/24-swap-nodes-in-pairs.md create mode 100644 docs/leetcode/hot120/26-remove-duplicates-from-sorted-array.md create mode 100644 docs/leetcode/hot120/27-remove-element.md create mode 100644 docs/leetcode/hot120/28-mirror-binary-tree.md create mode 100644 docs/leetcode/hot120/29-divide-two-integers.md create mode 100644 docs/leetcode/hot120/3-longest-substring-without-repeating-characters.md create mode 100644 docs/leetcode/hot120/31-next-permutation.md create mode 100644 docs/leetcode/hot120/34-find-first-and-last-position-of-element-in-sorted-array.md create mode 100644 docs/leetcode/hot120/36-valid-sudoku.md create mode 100644 docs/leetcode/hot120/40-combination-sum-ii.md create mode 100644 docs/leetcode/hot120/415-add-strings.md create mode 100644 docs/leetcode/hot120/43-multiply-strings.md create mode 100644 docs/leetcode/hot120/46-permutations.md create mode 100644 docs/leetcode/hot120/47-permutations-ii.md create mode 100644 docs/leetcode/hot120/48-rotate-image.md create mode 100644 docs/leetcode/hot120/49-group-anagrams.md create mode 100644 docs/leetcode/hot120/5-longest-palindromic-substring.md create mode 100644 docs/leetcode/hot120/50-powx-n.md create mode 100644 docs/leetcode/hot120/53-maximum-subarray.md create mode 100644 docs/leetcode/hot120/54-spiral-matrix.md create mode 100644 docs/leetcode/hot120/543-diameter-of-binary-tree.md create mode 100644 docs/leetcode/hot120/55-jump-game.md create mode 100644 docs/leetcode/hot120/56-merge-intervals.md create mode 100644 docs/leetcode/hot120/59-spiral-matrix-ii.md create mode 100644 docs/leetcode/hot120/62-unique-paths.md create mode 100644 docs/leetcode/hot120/7-reverse-integer.md create mode 100644 docs/leetcode/hot120/71-simplify-path.md create mode 100644 docs/leetcode/hot120/73-set-matrix-zeroes.md create mode 100644 docs/leetcode/hot120/74-search-a-2d-matrix.md create mode 100644 docs/leetcode/hot120/75-sort-colors.md create mode 100644 docs/leetcode/hot120/77-combinations.md create mode 100644 docs/leetcode/hot120/83-remove-duplicates-from-sorted-list.md create mode 100644 docs/leetcode/hot120/9-palindrome-number.md create mode 100644 docs/leetcode/hot120/92-reverse-linked-list-ii.md create mode 100644 docs/leetcode/hot120/958-check-completeness-of-a-binary-tree.md create mode 100644 docs/leetcode/hot120/98-validate-binary-search-tree.md create mode 100644 docs/leetcode/hot120/README.md rename "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" => docs/mass-data/1-count-phone-num.md (95%) rename "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" => docs/mass-data/2-find-hign-frequency-word.md (87%) create mode 100644 docs/mass-data/3-find-same-url.md create mode 100644 docs/mass-data/4-find-mid-num.md create mode 100644 docs/mass-data/5-find-hot-string.md create mode 100644 docs/mass-data/6-top-500-num.md create mode 100644 docs/mass-data/7-query-frequency-sort.md create mode 100644 docs/mass-data/8-topk-template.md create mode 100644 docs/mass-data/README.md rename "\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" => docs/message-queue/kafka.md (100%) create mode 100644 docs/message-queue/mq.md rename "\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" => docs/message-queue/rabbitmq.md (100%) create mode 100644 docs/other/leave-a-message.md create mode 100644 docs/other/site-diary.md create mode 100644 docs/practice/service-performance-optimization.md rename "Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" => docs/redis/redis-basic-all.md (100%) create mode 100644 docs/redis/redis-basic/1-introduce.md create mode 100644 docs/redis/redis-basic/10-lua.md create mode 100644 docs/redis/redis-basic/11-deletion-policy.md create mode 100644 docs/redis/redis-basic/12-others.md create mode 100644 docs/redis/redis-basic/2-data-type.md create mode 100644 docs/redis/redis-basic/3-data-structure.md create mode 100644 docs/redis/redis-basic/4-implement.md create mode 100644 docs/redis/redis-basic/5-sort.md create mode 100644 docs/redis/redis-basic/6-transaction.md create mode 100644 docs/redis/redis-basic/7-message-queue.md create mode 100644 docs/redis/redis-basic/8-persistence.md create mode 100644 docs/redis/redis-basic/9-cluster.md create mode 100644 docs/redis/redis-basic/README.md rename "Redis/Redis\351\235\242\350\257\225\351\242\230.md" => docs/redis/redis.md (85%) create mode 100644 docs/resource/1-cs-books.md rename "\345\267\245\345\205\267/docker-overview.md" => docs/tools/docker-overview.md (76%) create mode 100644 docs/tools/docker/1-introduce.md create mode 100644 docs/tools/docker/2-image-command.md create mode 100644 docs/tools/docker/3-container-command.md create mode 100644 docs/tools/docker/4-docker-compose.md create mode 100644 docs/tools/docker/5-maven-build.md create mode 100644 docs/tools/docker/6-other.md create mode 100644 docs/tools/docker/README.md rename "\345\267\245\345\205\267/git-overview.md" => docs/tools/git-overview.md (81%) create mode 100644 docs/tools/git/1-introduce.md create mode 100644 docs/tools/git/2-basic.md create mode 100644 docs/tools/git/3-remote-repo.md create mode 100644 docs/tools/git/4-label.md create mode 100644 docs/tools/git/5-branch.md create mode 100644 docs/tools/git/README.md rename "\345\267\245\345\205\267/linux-overview.md" => docs/tools/linux-overview.md (100%) create mode 100644 docs/tools/linux/1-basic.md create mode 100644 docs/tools/linux/2-disk-file.md create mode 100644 docs/tools/linux/3-search.md create mode 100644 docs/tools/linux/4-net.md create mode 100644 docs/tools/linux/5-monitor.md create mode 100644 docs/tools/linux/README.md rename "\345\267\245\345\205\267/maven-overview.md" => docs/tools/maven-overview.md (83%) create mode 100644 docs/tools/maven/1-introduce.md create mode 100644 docs/tools/maven/2-basic.md create mode 100644 docs/tools/maven/3-dependency.md create mode 100644 docs/tools/maven/4-repo.md create mode 100644 docs/tools/maven/5-lifecycle.md create mode 100644 docs/tools/maven/6-plugin.md create mode 100644 docs/tools/maven/7-aggregator.md create mode 100644 docs/tools/maven/8-inherit.md create mode 100644 docs/tools/maven/README.md create mode 100644 docs/tools/typora-overview.md delete mode 100644 img/1588431199776.png delete mode 100644 img/ConcurrentHashMap-segment.jpg delete mode 100644 img/JDK1.8-ConcurrentHashMap-Structure.jpg delete mode 100644 img/Java-Collections.jpeg delete mode 100644 img/all-table-search.jpg delete mode 100644 img/aqs.png delete mode 100644 img/bean-life-cycle.jpg delete mode 100644 img/bloom-filter.jpg delete mode 100644 img/cms-collector.png delete mode 100644 img/concurrent/executors-ali.png delete mode 100644 img/concurrent/synchronized-block.png delete mode 100644 img/concurrent/synchronized-method.png delete mode 100644 img/condition-await.png delete mode 100644 img/condition-signal.png delete mode 100644 img/condition-wait-queue.png delete mode 100644 img/cover-index.png delete mode 100644 img/direct-pointer.png delete mode 100644 img/docker/docker.jpg delete mode 100644 img/explain-all.png delete mode 100644 img/explain-const.png delete mode 100644 img/explain-id.png delete mode 100644 img/explain-range.png delete mode 100644 img/explain-ref.png delete mode 100644 img/g1-region.jpg delete mode 100644 img/gc-root-refer.png delete mode 100644 img/git-status.png delete mode 100644 img/heap-structure.png delete mode 100644 img/image-20200520234137916.png delete mode 100644 img/image-20200520234200868.png delete mode 100644 img/image-20200520234231001.png delete mode 100644 img/image-20200608232749393.png delete mode 100644 img/image-20200608232951873.png delete mode 100644 img/image-20200608233400458.png delete mode 100644 img/image-20200614165333479.png delete mode 100644 img/image-20200614165432775.png delete mode 100644 img/index-search-range.jpg delete mode 100644 img/index-search.jpg delete mode 100644 img/java-basic/exception.png delete mode 100644 img/java-basic/field-method.png delete mode 100644 img/java-basic/io.jpg delete mode 100644 img/java-ram-region.png delete mode 100644 img/jmeter/http-request-param.png delete mode 100644 img/jmeter/jmeter-aggregate-report.png delete mode 100644 img/jmeter/jmeter-default-request.png delete mode 100644 img/jmeter/jmeter-request-header.png delete mode 100644 img/jmeter/jmeter-thread-group.png delete mode 100644 img/jvm/string-equal.png delete mode 100644 img/jvm/string-intern.png delete mode 100644 img/jvm/string-new.png delete mode 100644 img/left-match.jpg delete mode 100644 img/middleware/redis-transaction.png delete mode 100644 img/middleware/redis-usage.png delete mode 100644 img/mysql-architecture.png delete mode 100644 img/mysql-clustered-index.png delete mode 100644 img/mysql/arch.png delete mode 100644 img/mysql/current-read.png delete mode 100644 img/mysql/mvcc-impl.png delete mode 100644 img/mysql/myisam-innodb-index.png delete mode 100644 img/mysql/mysql-archpng.png delete mode 100644 img/mysql/nested-loop.png delete mode 100644 img/mysql/orderby.png delete mode 100644 img/net/bio.png delete mode 100644 img/net/cdn.png delete mode 100644 img/net/https-certificate-chain.jpg delete mode 100644 img/net/https-certificate.png delete mode 100644 img/net/https-client-hello.jpg delete mode 100644 img/net/https-server-hello.jpg delete mode 100644 img/net/nio.png delete mode 100644 img/oauth2.png delete mode 100644 img/object-dead.png delete mode 100644 img/object-handle.png delete mode 100644 img/optimistic-lock.jpg delete mode 100644 img/others/json-web-token.png delete mode 100644 img/others/seckill.jpg delete mode 100644 img/parnew-collector.png delete mode 100644 img/rabbitmq-direct.png delete mode 100644 img/rabbitmq-fanout.png delete mode 100644 img/rabbitmq-return-listener.png delete mode 100644 img/rabbitmq-topic.png delete mode 100644 img/rabbitmq.png delete mode 100644 img/redis/cache-consist.png delete mode 100644 img/redis/evalsha.png delete mode 100644 img/redis/list-api.png delete mode 100644 img/redis/redis-replication.png delete mode 100644 img/redis/redis-skiplist.png delete mode 100644 img/redis/time-complexity.png delete mode 100644 "img/redis/\347\274\223\345\255\230\345\207\273\347\251\277\345\212\240\344\272\222\346\226\245\351\224\201.png" delete mode 100644 img/scheduled-task.jpg delete mode 100644 img/serial-collector.png delete mode 100644 img/singleton-class-init.png delete mode 100644 "img/spring/\346\226\271\346\263\225\347\272\247\345\210\253\346\263\250\350\247\243.png" delete mode 100644 "img/springboot/SpringBoot\347\232\204\350\207\252\345\212\250\351\205\215\347\275\256\345\216\237\347\220\206.jpg" delete mode 100644 img/thread-pool.png delete mode 100644 img/thread-status.jpeg delete mode 100644 img/threadlocal-oom.png delete mode 100644 img/threadlocal.png delete mode 100644 img/tree-visit.png delete mode 100644 img/two-index.jpg delete mode 100644 img/web/servlet-container.jpg delete mode 100644 "img/\345\271\273\350\257\2731.png" delete mode 100644 "img/\346\213\245\345\241\236\346\216\247\345\210\266.jpg" delete mode 100644 "img/\350\257\267\346\261\202\344\277\235\346\212\244\351\205\215\347\275\256\346\226\271\346\263\225.png" create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 "\344\270\255\351\227\264\344\273\266/Elasticsearch\345\205\245\351\227\250.md" delete mode 100644 "\345\205\266\344\273\226/code.md" delete mode 100644 "\345\205\266\344\273\226/linux.md" delete mode 100644 "\345\205\266\344\273\226/note.md" delete mode 100644 "\345\205\266\344\273\226/\345\256\236\346\210\230\347\257\207.md" delete mode 100644 "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" delete mode 100644 "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230.md" delete mode 100644 "\345\211\215\347\253\257/vue.md" delete mode 100644 "\345\267\245\345\205\267/GitHub\346\214\207\345\215\227.md" delete mode 100644 "\345\267\245\345\205\267/NPM.md" delete mode 100644 "\345\267\245\345\205\267/jenkins.md" delete mode 100644 "\345\267\245\345\205\267/jmeter.md" delete mode 100644 "\345\267\245\345\205\267/nginx\351\203\250\347\275\262\351\241\271\347\233\256.md" delete mode 100644 "\346\225\260\346\215\256\345\272\223/MySQL\350\277\233\351\230\266.md" delete mode 100644 "\346\241\206\346\236\266/SpringBoot\345\256\236\346\210\230.md" delete mode 100644 "\346\241\206\346\236\266/SpringMVC.md" delete mode 100644 "\346\241\206\346\236\266/SpringMVC\351\235\242\350\257\225\351\242\230.md" delete mode 100644 "\346\241\206\346\236\266/Spring\345\256\236\346\210\230.md" delete mode 100644 "\346\241\206\346\236\266/Spring\346\200\273\347\273\223.md" delete mode 100644 "\346\241\206\346\236\266/Spring\347\224\250\345\210\260\345\223\252\344\272\233\350\256\276\350\256\241\346\250\241\345\274\217.md" delete mode 100644 "\346\241\206\346\236\266/Spring\350\207\252\345\212\250\350\243\205\351\205\215.md" delete mode 100644 "\346\241\206\346\236\266/\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\346\212\200\346\234\257\345\216\237\347\220\206\344\270\216\345\256\236\346\210\230.md" delete mode 100644 "\346\266\210\346\201\257\351\230\237\345\210\227/\346\255\273\344\277\241\351\230\237\345\210\227.md" delete mode 100644 "\346\266\210\346\201\257\351\230\237\345\210\227/\346\266\210\346\201\257\351\230\237\345\210\227\351\235\242\350\257\225\351\242\230.md" delete mode 100644 "\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241old.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\347\256\227\346\263\225.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/TCP IP\345\215\217\350\256\256.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/session\345\222\214cookie.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\347\275\221\347\273\234.md" delete mode 100644 "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\275\221\347\273\234/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" diff --git a/.gitignore b/.gitignore index af0556b..0182294 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,14 @@ .DS_Store +*.log node_modules/ -/dist/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Editor directories and files -.idea -.vscode -*.suo -*.ntvs* -*.njsproj -*.sln +*.bat +*.sh +web/ +.idea/ *.py +public/ +docs/.vuepress/.temp/ +docs/.vuepress/.cache/ +ByteDanceVerify.html +google053c90e5a7354c40.html +sogousiteverification.txt \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..59cab98 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +topjavaer.cn diff --git a/Java/JVM.md b/Java/JVM.md deleted file mode 100644 index b19e730..0000000 --- a/Java/JVM.md +++ /dev/null @@ -1,831 +0,0 @@ - - -> 本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础、MySQL、Springboot、mybatis、Redis、rabbitMQ等等,欢迎大家提pr和star! -> -> github地址:https://github.com/Tyson0314/Java-learning -> -> gitee地址:https://gitee.com/tysondai/Java-learning - - - - - -- [内存结构](#%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84) - - [程序计数器](#%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8) - - [虚拟机栈](#%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88) - - [本地方法栈](#%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88) - - [堆](#%E5%A0%86) - - [方法区](#%E6%96%B9%E6%B3%95%E5%8C%BA) - - [永久代](#%E6%B0%B8%E4%B9%85%E4%BB%A3) - - [元空间](#%E5%85%83%E7%A9%BA%E9%97%B4) - - [运行时常量池](#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0) - - [直接内存](#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98) - - [对象的访问定位](#%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%BF%E9%97%AE%E5%AE%9A%E4%BD%8D) -- [类文件结构](#%E7%B1%BB%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84) -- [类的生命周期](#%E7%B1%BB%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) -- [类加载的过程](#%E7%B1%BB%E5%8A%A0%E8%BD%BD%E7%9A%84%E8%BF%87%E7%A8%8B) - - [加载](#%E5%8A%A0%E8%BD%BD) - - [验证](#%E9%AA%8C%E8%AF%81) - - [准备](#%E5%87%86%E5%A4%87) - - [解析](#%E8%A7%A3%E6%9E%90) - - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96) -- [双亲委派模型](#%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%A8%A1%E5%9E%8B) - - [实现](#%E5%AE%9E%E7%8E%B0) -- [对象死亡](#%E5%AF%B9%E8%B1%A1%E6%AD%BB%E4%BA%A1) - - [引用计数法](#%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E6%B3%95) - - [可达性分析](#%E5%8F%AF%E8%BE%BE%E6%80%A7%E5%88%86%E6%9E%90) - - [可作为GC Roots的对象](#%E5%8F%AF%E4%BD%9C%E4%B8%BAgc-roots%E7%9A%84%E5%AF%B9%E8%B1%A1) - - [引用](#%E5%BC%95%E7%94%A8) - - [强引用](#%E5%BC%BA%E5%BC%95%E7%94%A8) - - [软引用](#%E8%BD%AF%E5%BC%95%E7%94%A8) - - [弱引用](#%E5%BC%B1%E5%BC%95%E7%94%A8) - - [虚引用](#%E8%99%9A%E5%BC%95%E7%94%A8) - - [常量回收](#%E5%B8%B8%E9%87%8F%E5%9B%9E%E6%94%B6) - - [类的卸载](#%E7%B1%BB%E7%9A%84%E5%8D%B8%E8%BD%BD) -- [内存分配与回收策略](#%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E4%B8%8E%E5%9B%9E%E6%94%B6%E7%AD%96%E7%95%A5) - - [Minor GC 和 Full GC](#minor-gc-%E5%92%8C-full-gc) - - [内存分配策略](#%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5) - - [对象优先在 Eden 分配](#%E5%AF%B9%E8%B1%A1%E4%BC%98%E5%85%88%E5%9C%A8-eden-%E5%88%86%E9%85%8D) - - [大对象直接进入老年代](#%E5%A4%A7%E5%AF%B9%E8%B1%A1%E7%9B%B4%E6%8E%A5%E8%BF%9B%E5%85%A5%E8%80%81%E5%B9%B4%E4%BB%A3) - - [长期存活的对象进入老年代](#%E9%95%BF%E6%9C%9F%E5%AD%98%E6%B4%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%BF%9B%E5%85%A5%E8%80%81%E5%B9%B4%E4%BB%A3) - - [动态对象年龄判定](#%E5%8A%A8%E6%80%81%E5%AF%B9%E8%B1%A1%E5%B9%B4%E9%BE%84%E5%88%A4%E5%AE%9A) - - [空间分配担保](#%E7%A9%BA%E9%97%B4%E5%88%86%E9%85%8D%E6%8B%85%E4%BF%9D) - - [Full GC 的触发条件](#full-gc-%E7%9A%84%E8%A7%A6%E5%8F%91%E6%9D%A1%E4%BB%B6) - - [调用 System.gc()](#%E8%B0%83%E7%94%A8-systemgc) - - [老年代空间不足](#%E8%80%81%E5%B9%B4%E4%BB%A3%E7%A9%BA%E9%97%B4%E4%B8%8D%E8%B6%B3) - - [空间分配担保失败](#%E7%A9%BA%E9%97%B4%E5%88%86%E9%85%8D%E6%8B%85%E4%BF%9D%E5%A4%B1%E8%B4%A5) -- [垃圾回收算法](#%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95) - - [标记清除算法](#%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4%E7%AE%97%E6%B3%95) - - [复制清除算法](#%E5%A4%8D%E5%88%B6%E6%B8%85%E9%99%A4%E7%AE%97%E6%B3%95) - - [标记整理算法](#%E6%A0%87%E8%AE%B0%E6%95%B4%E7%90%86%E7%AE%97%E6%B3%95) - - [分类收集算法](#%E5%88%86%E7%B1%BB%E6%94%B6%E9%9B%86%E7%AE%97%E6%B3%95) - - [记忆集](#%E8%AE%B0%E5%BF%86%E9%9B%86) -- [垃圾收集器](#%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8) - - [Serial 收集器](#serial-%E6%94%B6%E9%9B%86%E5%99%A8) - - [ParNew 收集器](#parnew-%E6%94%B6%E9%9B%86%E5%99%A8) - - [Parallel Scavenge 收集器](#parallel-scavenge-%E6%94%B6%E9%9B%86%E5%99%A8) - - [Serial Old 收集器](#serial-old-%E6%94%B6%E9%9B%86%E5%99%A8) - - [Parallel Old 收集器](#parallel-old-%E6%94%B6%E9%9B%86%E5%99%A8) - - [CMS 收集器](#cms-%E6%94%B6%E9%9B%86%E5%99%A8) - - [回收过程](#%E5%9B%9E%E6%94%B6%E8%BF%87%E7%A8%8B) - - [CMS垃圾回收特点](#cms%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%89%B9%E7%82%B9) - - [G1收集器](#g1%E6%94%B6%E9%9B%86%E5%99%A8) - - [回收过程](#%E5%9B%9E%E6%94%B6%E8%BF%87%E7%A8%8B-1) -- [JVM调优工具](#jvm%E8%B0%83%E4%BC%98%E5%B7%A5%E5%85%B7) - - [jps](#jps) - - [jstack](#jstack) - - [jstat](#jstat) - - [jmap](#jmap) -- [补充](#%E8%A1%A5%E5%85%85) - - [对象头](#%E5%AF%B9%E8%B1%A1%E5%A4%B4) - - [main方法执行过程](#main%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B) - - [对象创建过程](#%E5%AF%B9%E8%B1%A1%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B) -- [参考资料](#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99) - - - -## 内存结构 - -Java 内存模型(JMM)是基于共享内存的多线程通信机制。 - -JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。 - -![image-20210905150636105](http://img.dabin-coder.cn/image/image-20210905150636105.png) - -> 图片来源:深入理解Java虚拟机-周志明 - -### 程序计数器 - -程序计数器主要有两个作用: - -1. 当前线程所执行的字节码的行号指示器,通过改变它实现代码的流程控制,如:顺序执行、选择、循环、异常处理。 -2. 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。 - -程序计数器是唯一一个不会出现 `OutOfMemoryError` 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。 - -### 虚拟机栈 - -Java 虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。每一次函数调用都会有一个对应的栈帧被压入虚拟机栈,每一个函数调用结束后,都会有一个栈帧被弹出。 - -局部变量表是用于存放方法参数和方法内的局部变量。 - -每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,在方法调用过程中,会进行动态链接,将这个符号引用转化为直接引用。 - -- 部分符号引用在类加载阶段的时候就转化为直接引用,这种转化就是静态链接 -- 部分符号引用在运行期间转化为直接引用,这种转化就是动态链接 - -Java 虚拟机栈也是线程私有的,每个线程都有各自的 Java 虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡。Java 虚拟机栈会出现两种错误:`StackOverFlowError` 和 `OutOfMemoryError`。 - -可以通过 -Xss 参数来指定每个线程的 Java 虚拟机栈内存大小,在 JDK 1.4 中默认为 256K,而在 JDK 1.5+ 默认为 1M: - -```java -java -Xss2M -``` - -### 本地方法栈 - -虚拟机栈为虚拟机执行 Java 方法服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。Native 方法一般是用其它语言(C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。 - -本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。 - -### 堆 - -此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。Java 堆是垃圾收集器管理的主要区域,因此也被称作GC堆。 - -Java 堆可以细分为:新生代(Eden 空间、From Survivor、To Survivor 空间)和老年代。进一步划分的目的是更好地回收内存,或者更快地分配内存。 - -通过 -Xms设定程序启动时占用内存大小,通过 -Xmx 设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。 - -```java -java -Xms1M -Xmx2M -``` - -通过 -Xss 设定每个线程的堆栈大小。设置这个参数,需要评估一个线程大约需要占用多少内存,可能会有多少线程同时运行等。 - -> 在这里也给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - -### 方法区 - -方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区逻辑上属于堆的一部分。 - -对方法区进行垃圾回收的主要目标是对常量池的回收和对类的卸载。 - -#### 永久代 - -方法区是 JVM 的规范,而永久代(PermGen)是方法区的一种实现方式,并且只有 HotSpot 有永久代。而对于其他类型的虚拟机,如 JRockit(Oracle)、J9(IBM) 并没有永久代。由于方法区主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。最典型的场景就是,在 jsp 页面比较多的情况,容易出现永久代内存溢出。 - -#### 元空间 - -JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。两者最大的区别在于:元空间并不在虚拟机中,而是使用直接内存。 - -为什么要将永久代替换为元空间呢? - -永久代内存受限于 JVM 可用内存,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是相比永久代内存溢出的概率更小。 - -### 运行时常量池 - -运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 - -![](http://img.dabin-coder.cn/image/string-new.png) - -![](http://img.dabin-coder.cn/image/string-intern.png) - -![](http://img.dabin-coder.cn/image/string-equal.png) - -> 图片来源:https://blog.csdn.net/soonfly - -### 直接内存 - -直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 错误出现。 - -NIO的Buffer提供了DirectBuffer,可以直接访问系统物理内存,避免堆内内存到堆外内存的数据拷贝操作,提高效率。DirectBuffer直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制,不受最大堆内存的限制。 - -直接内存的读写操作比堆内存快,可以提升程序I/O操作的性能。通常在I/O通信过程中,会存在堆内内存到堆外内存的数据拷贝操作,对于需要频繁进行内存间数据拷贝且生命周期较短的暂存数据,都建议存储到直接内存。 - -### 对象的访问定位 - -Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有使用句柄和直接指针两种: - -- 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。 - -![](http://img.dabin-coder.cn/image/object-handle.png) - -- 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。 - -![](http://img.dabin-coder.cn/image/direct-pointer.png) - - - -## 类文件结构 - -Class 文件结构: - -```java -ClassFile { - u4 magic; //Class 文件的标志 - u2 minor_version;//Class 的小版本号 - u2 major_version;//Class 的大版本号 - u2 constant_pool_count;//常量池的数量 - cp_info constant_pool[constant_pool_count-1];//常量池 - u2 access_flags;//Class 的访问标记 - u2 this_class;//当前类 - u2 super_class;//父类 - u2 interfaces_count;//接口 - u2 interfaces[interfaces_count];//一个类可以实现多个接口 - u2 fields_count;//Class 文件的字段属性 - field_info fields[fields_count];//一个类会可以有个字段 - u2 methods_count;//Class 文件的方法数量 - method_info methods[methods_count];//一个类可以有个多个方法 - u2 attributes_count;//此类的属性表中的属性数 - attribute_info attributes[attributes_count];//属性表集合 -} -``` - -魔数:class 文件标志。 - -文件版本:高版本的 Java 虚拟机可以执行低版本编译器生成的 Class 文件,但是低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。 - -常量池:存放字面量和符号引用。字面量类似于Java的常量,如字符串,声明为final的常量值等。符号引用包含三类:类和接口的全限定名,方法的名称和描述符,字段的名称和描述符。 - -访问标志:识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。 - -当前类索引this_class:类索引用于确定这个类的全限定名。 - -属性表集合:在 Class 文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。与 Class 文件中其它的数据项目要求的顺序、长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写 入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。 - - - -## 类的生命周期 - -加载、验证、准备、解析、初始化、使用和卸载。 - -![](http://img.dabin-coder.cn/image/image-20210905002423703.png) - -## 类加载的过程 - -类的加载指的是将类的class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个对象,这个对象封装了类在方法区内的数据结构,并且提供了访问方法区内的类信息的接口。 - -### 加载 - -类加载过程的一个阶段:通过一个类的完全限定查找此类字节码文件,并利用字节码文件创建一个Class对象。 - -1. 通过全类名获取定义此类的二进制字节流 -2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构 -3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 - -### 验证 - -确保Class文件的字节流中包含的信息符合虚拟机规范,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。主要包括四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。 - -### 准备 - -为类变量分配内存并设置类变量初始值的阶段。此阶段进行内存分配的仅包括类变量,不包括实例变量和final修饰的static变量(因为final在编译的时候就会分配了),实例变量会在对象实例化时随着对象一块分配在 Java 堆中。 - -### 解析 - -虚拟机将常量池内的符号引用替换为直接引用的过程。符号引用用于描述目标,直接引用直接指向目标的地址。 - -### 初始化 - -初始化阶段就是执行类构造器\()方法的过程。\()并不是程序员在Java代码中直接编写的方法,它是Javac编译器的自动生成的,由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。 - - - -## 双亲委派模型 - -一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。 - -![](http://img.dabin-coder.cn/image/image-20210905002827546.png) - -双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。 - -### 实现 - -双亲委派模型的具体实现代码在抽象类 java.lang.ClassLoader 中,此类的 loadClass() 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 ClassNotFoundException,此时尝试自己去加载。 - -```java -public abstract class ClassLoader { - // The parent class loader for delegation - private final ClassLoader parent; - - public Class loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - synchronized (getClassLoadingLock(name)) { - // First, check if the class has already been loaded - Class c = findLoadedClass(name); - if (c == null) { - try { - if (parent != null) { - c = parent.loadClass(name, false); - } else { - c = findBootstrapClassOrNull(name); - } - } catch (ClassNotFoundException e) { - // ClassNotFoundException thrown if class not found - // from the non-null parent class loader - } - - if (c == null) { - // If still not found, then invoke findClass in order - // to find the class. - c = findClass(name); - } - } - if (resolve) { - resolveClass(c); - } - return c; - } - } - - protected Class findClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException(name); - } -} -``` - - - -## 对象死亡 - -堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。 - -![](http://img.dabin-coder.cn/image/object-dead.png) - -### 引用计数法 - -给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。 - -这种方法很难解决对象之间相互循环引用的问题。 - -```java -public class ReferenceCountingGc { - Object instance = null; - public static void main(String[] args) { - ReferenceCountingGc objA = new ReferenceCountingGc(); - ReferenceCountingGc objB = new ReferenceCountingGc(); - objA.instance = objB; - objB.instance = objA; - objA = null; - objB = null; - } -} -``` - -### 可达性分析 - -通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。 - -![](http://img.dabin-coder.cn/image/gc-root-refer.png) - -#### 可作为GC Roots的对象 - -1. 虚拟机栈(栈帧中的本地变量表)中引用的对象 -2. 本地方法栈中JNI(Native方法)引用的对象 -3. 方法区中类静态属性引用的对象 -4. 方法区中常量引用的对象 -5. 所有被同步锁(synchronized关键字)持有的对象。 - -### 引用 - -引用分为强引用、软引用、弱引用、虚引用四种。 - -在程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速 JVM 对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。 - -#### 强引用 - -垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。 - -#### 软引用 - -如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 - -#### 弱引用 - -在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。 - -#### 虚引用 - -虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。**虚引用主要用来跟踪对象被垃圾回收的活动**。 - -### 常量回收 - -运行时常量池主要回收的是废弃的常量。假如在常量池中存在字符串 "abc",如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 "abc" 就是废弃常量,如果这时发生内存回收的话而且有必要的话,"abc" 就会被系统清理出常量池。 - -### 类的卸载 - -需要同时满足下面 3 个条件才能算是 “无用的类” : - -- 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。 -- 加载该类的 ClassLoader 已经被回收。 -- 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。 - -虚拟机可以对满足上述 3 个条件的无用类进行回收,但不一定被回收。 - - - -## 内存分配与回收策略 - -### Minor GC 和 Full GC - -- Minor GC:回收新生代,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。 - -- Full GC:回收老年代和新生代,老年代对象其存活时间长,因此 Full GC 很少执行,执行速度会比 Minor GC 慢很多。 - -### 内存分配策略 - -#### 对象优先在 Eden 分配 - -大多数情况下,对象在新生代 Eden 上分配,当 Eden 空间不够时,发起 Minor GC。 - -#### 大对象直接进入老年代 - -大对象是指需要连续内存空间的对象,最典型的大对象是那种很长的字符串以及数组。经常出现大对象会提前触发垃圾收集以获取足够的连续空间分配给大对象。 - -可以设置JVM参数 -XX:PretenureSizeThreshold,大于此值的对象直接在老年代分配,避免在 Eden 和 Survivor 之间的大量内存复制。 - -#### 长期存活的对象进入老年代 - -通过参数 `-XX:MaxTenuringThreshold` 可以设置对象进入老年代的年龄阈值。对象在 Survivor 中每经过一次 MinorGC,年龄就增加 1 岁,当它的年龄增加到一定程度,就会被晋升到老年代中。 - -#### 动态对象年龄判定 - -虚拟机并不是永远要求对象的年龄必须达到 MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象可以直接进入老年代,无需等到 MaxTenuringThreshold 中要求的年龄。 - -#### 空间分配担保 - -在发生 Minor GC 之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立的话,那么 Minor GC 可以确认是安全的。如果不成立的话虚拟机会查看 HandlePromotionFailure 的值是否允许担保失败。如果允许,那么就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次 Minor GC;如果小于,或者 HandlePromotionFailure 的值不允许冒险,那么就要进行一次 Full GC。 - -### Full GC 的触发条件 - -对于 Minor GC,其触发条件比较简单,当 Eden 空间满时,就将触发一次 Minor GC。而 Full GC 触发条件相对复杂,有以下条件: - -#### 调用 System.gc() - -只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。 - -#### 老年代空间不足 - -老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。除此之外,可以通过 -Xmn 参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。 - -#### 空间分配担保失败 - -使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果担保失败会执行一次 Full GC。 - - - -## 垃圾回收算法 - -### 标记清除算法 - -标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。 - -![](http://img.dabin-coder.cn/image/image-20210905003458130.png) - -### 复制清除算法 - -半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 - -![](http://img.dabin-coder.cn/image/image-20210905003714551.png) - -特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。 - -### 标记整理算法 - -根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。 - -### 分类收集算法 - -根据各个年代的特点采用最适当的收集算法。 - -一般将堆分为新生代和老年代。 - -- 新生代使用:复制算法 -- 老年代使用:标记清除算法或者标记整理算法 - -在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。 - -由于对象之间会存在跨代引用,如果要进行一次新生代垃圾收集,除了需要遍历新生代对象,还要额外遍历整个老年代的所有对象,这会给内存回收带来很大的性能负担。 - -跨代引用相对于同代引用来说仅占极少数。存在互相引用关系的两个对象,是应该倾向于同时生存或者同时消亡的。举个例子,如果某个新生代对象存在跨代引用,由于老年代对象难以消亡,该引用会使得新生代对象在收集时同样得以存活,进而在年龄增长之后晋升到老年代中,这时跨代引用也随即被消除了。 - -所以没必要为了少量的跨代引用去扫描整个老年代,只需在新生代建立一个全局的数据结构 Remembered Set,这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会存在跨代引用。此后当发生Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。 - -#### 记忆集 - -记忆集是一种用于记录从非收集区域指向收集区域的指针集合的抽象数据结构。Card Table 是最常用的一种记忆集实现形式。字节数组CARD_TABLE的每一个元素都对应着其标识的内存区域中一块特定大小的内存块,这个内存块被称作“卡页”(Card Page)。 - -一个卡页的内存中通常包含不止一个对象,只要卡页内有一个(或更多)对象的字段存在着跨代指针,那就将对应卡表的数组元素的值标识为1,称为这个元素变脏(Dirty),没有则标识为0。在垃圾收集发生时,只要筛选出卡表中变脏的元素,就能轻易得出哪些卡页内存块中包含跨代指针,把它们加入GC Roots中一并扫描。 - - - -## 垃圾收集器 - -经典的垃圾收集器主要有三种类型:串行收集器、并行收集器和并发标记清除收集器CMS,这三种收集器分别可以是满足Java应用三种不同的需求:内存占用及并发开销最小化、应用吞吐量最大化和应用GC暂停时间最小化。 - -JDK1.7和1.8中默认使用的是Parallel Scavenge和Parallel Old收集器组合。jdk1.9 默认垃圾收集器是G1。 - -```java -java -XX:+PrintCommandLineFlags -version -``` - -7个垃圾收集器的特点: - -| 收集器 | 串行、并行or并发 | 新生代/老年代 | 算法 | 目标 | 适用场景 | -| :-------------------: | :--------------: | :-----------: | :----------------: | :----------: | :---------------------------------------: | -| **Serial** | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单CPU环境下的Client模式 | -| **ParNew** | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在Server模式下与CMS配合 | -| **Parallel Scavenge** | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 | -| **Serial Old** | 串行 | 老年代 | 标记-整理 | 响应速度优先 | 单CPU环境下的Client模式、CMS的后备预案 | -| **Parallel Old** | 并行 | 老年代 | 标记-整理 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 | -| **CMS** | 并发 | 老年代 | 标记-清除 | 响应速度优先 | 集中在互联网站或B/S系统服务端上的Java应用 | -| **G1** | 并发 | both | 标记-整理+复制算法 | 响应速度优先 | 面向服务端应用,将来替换CMS | - -### Serial 收集器 - -单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 - -![](http://img.dabin-coder.cn/image/serial-collector.png) - -特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。 - -### ParNew 收集器 - -Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。 - -![](http://img.dabin-coder.cn/image/parnew-collector.png) - -除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。 - -### Parallel Scavenge 收集器 - -新生代收集器,基于复制清除算法实现的收集器。吞吐量优先收集器,也是能够并行收集的多线程收集器,允许多个垃圾回收线程同时运行,降低垃圾收集时间,提高吞吐量。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值(吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间))。Parallel Scavenge 收集器关注点是吞吐量,高效率的利用 CPU 资源。CMS 垃圾收集器关注点更多的是用户线程的停顿时间。 - -Parallel Scavenge收集器提供了两个参数用于**精确控制吞吐量**,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。 - --XX:MaxGCPauseMillis参数允许的值是一个大于0的毫秒数,收集器将尽力保证内存回收花费的时间不超过用户设定值。 - --XX:GCTimeRatio参数的值则应当是一个大于0小于100的整数,也就是垃圾收集时间占总时间的比率,相当于吞吐量的倒数。 - -相比ParNew收集器的优点: - -1. 精确控制吞吐量; -2. 垃圾收集的自适应的调节策略。通过参数-XX:+UseAdaptiveSizePolicy 打开自适应调节策略,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整参数以提供最合适的停顿时间或者最大的吞吐量。调整的参数包括新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等。 - -### Serial Old 收集器 - -Serial 收集器的老年代版本,它同样是一个单线程收集器,使用标记整理算法。它主要有两大用途:一种用途是在 JDK1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用,另一种用途是作为 CMS 收集器的后备方案。 - -### Parallel Old 收集器 - -Parallel Scavenge 收集器的老年代版本。多线程垃圾收集,使用标记-整理算法。在注重吞吐量以及 CPU 资源的场合,都可以优先考虑 Parallel Scavenge 收集器和 Parallel Old 收集器。 - -### CMS 收集器 - -Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时间。第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程基本上同时工作。在并发标记和并发清除阶段,虽然用户线程没有被暂停,但是由于垃圾收集器线程占用了一部分系统资源,应用程序的吞吐量会降低。 - -#### 回收过程 - -基于标记清除算法实现,垃圾收集整个过程分为四个步骤: - -- 初始标记: stw暂停所有的其他线程,记录直接与 gc root 直接相连的对象,速度很快 。 -- 并发标记:从GC Roots开始对堆中对象进行可达性分析,找出存活对象,耗时较长,但是不需要停顿用户线程。 -- 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 -- 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。 - -![](http://img.dabin-coder.cn/image/cms-collector.png) - -由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 - -优点:并发收集,低停顿。 - -缺点: - -- 标记清除算法导致收集结束有大量空间碎片,往往出现老年代空间剩余,但无法找到足够大连续空间来分配当前对象,不得不提前触发一次 Full GC。 -- 会产生浮动垃圾,由于CMS并发清理阶段用户线程还在运行着,会不断有新的垃圾产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好等到下一次GC去处理; -- 对处理器资源非常敏感。在并发阶段,收集器占用了一部分线程资源,导致应用程序变慢,降低总吞吐量。 - -#### CMS垃圾回收特点 - -1. cms只会回收老年代和永久代(1.8开始为元数据区,需要设置CMSClassUnloadingEnabled),不会收集年轻代; -2. cms垃圾回收器开始执行回收操作,有一个触发阈值,默认是老年代或永久带达到92%,不能等到old内存用尽时回收,否则会导致并发回收失败。因为需要预留空间给用户线程运行。 - -### G1收集器 - -G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应用场景中追求高吞吐量和低停顿之间的最佳平衡。 - -在G1收集器出现之前的所有其他收集器,包括CMS在内,垃圾收集的目标范围要么是整个新生代(Minor GC),要么就是整个老年代(Major GC),再要么就是整个Java堆(Full GC)。而G1可以面向堆内存任何部分来组成回收集(Collection Set,一般简称CSet)进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。 - -G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。 - -![](http://img.dabin-coder.cn/image/g1-region.jpg) - -G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。 - -Java堆分成多个独立Region,Region里面会存在跨Region引用对象,在垃圾回收寻找GC Roots需要扫描整个堆。G1采用了Rset(Remembered Set)来避免扫描整个堆。每个Region会有一个RSet,记录了哪些Region引用本Region中对象,即谁引用了我的对象,这样的话,在做可达性分析的时候就可以避免全堆扫描。 - -特点:可以由用户指定期望的垃圾收集停顿时间。 - -#### 回收过程 - -G1 收集器的运作大致分为以下几个步骤: - -- 初始标记:。stw暂停所有的其他线程,记录直接与 gc root 直接相连的对象,速度很快 。 -- 并发标记。从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。 -- 最终标记。对用户线程做另一个短暂的暂停,用于处理并发阶段对象引用出现变动的区域。 -- 筛选回收。对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧的Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。 - - - -## JVM调优工具 - -### jps - -列出本机所有java进程的pid。 - -选项 - -- -q 仅输出VM标识符,不包括class name,jar name,arguments in main method -- -m 输出main method的参数 -- -l 输出完全的包名,应用主类名,jar的完全路径名 -- -v 输出jvm参数 -- -V 输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件 -- -Joption 传递参数到vm,例如:-J-Xms48m - -```bash -jps -lvm -//output -//4124 com.zzx.Application -javaagent:E:\IDEA2019\lib\idea_rt.jar=10291:E:\IDEA2019\bin -Dfile.encoding=UTF-8 -``` - -### jstack - -查看某个Java进程内的线程堆栈信息。-l,long listings,打印额外的锁信息,发生死锁时可以使用`jstack -l pid`观察锁持有情况。 - -```java -jstack -l 4124 | more -``` - -output: - -```java -"http-nio-8001-exec-10" #40 daemon prio=5 os_prio=0 tid=0x000000002542f000 nid=0x4028 waiting on condition [0x000000002cc9e000] - java.lang.Thread.State: WAITING (parking) - at sun.misc.Unsafe.park(Native Method) - - parking to wait for <0x000000077420d7e8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) - at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) - at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) - at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) - at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103) - at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31) - at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) - at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) - at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) - at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) - at java.lang.Thread.run(Thread.java:748) - - Locked ownable synchronizers: - - None -``` - -### jstat - -虚拟机各种运行状态信息(类装载、内存、垃圾收集、jit编译等运行数据)。gcuitl 查看新生代、老年代及持久代GC的情况。 - -```java -jstat -gcutil 4124 - S0 S1 E O M CCS YGC YGCT FGC FGCT GCT - 0.00 0.00 67.21 19.20 96.36 94.96 10 0.084 3 0.191 0.275 -``` - -### jmap - -查看堆内存快照。查看进程中新生代、老年代、永久代的使用情况。 - -查询进程4124的堆内存快照: - -```java ->jmap -heap 4124 -Attaching to process ID 4124, please wait... -Debugger attached successfully. -Server compiler detected. -JVM version is 25.221-b11 - -using thread-local object allocation. -Parallel GC with 6 thread(s) - -Heap Configuration: - MinHeapFreeRatio = 0 - MaxHeapFreeRatio = 100 - MaxHeapSize = 4238344192 (4042.0MB) - NewSize = 88604672 (84.5MB) - MaxNewSize = 1412431872 (1347.0MB) - OldSize = 177733632 (169.5MB) - NewRatio = 2 - SurvivorRatio = 8 - MetaspaceSize = 21807104 (20.796875MB) - CompressedClassSpaceSize = 1073741824 (1024.0MB) - MaxMetaspaceSize = 17592186044415 MB - G1HeapRegionSize = 0 (0.0MB) - -Heap Usage: -PS Young Generation -Eden Space: - capacity = 327155712 (312.0MB) - used = 223702392 (213.33922576904297MB) - free = 103453320 (98.66077423095703MB) - 68.37795697725736% used -From Space: - capacity = 21495808 (20.5MB) - used = 0 (0.0MB) - free = 21495808 (20.5MB) - 0.0% used -To Space: - capacity = 23068672 (22.0MB) - used = 0 (0.0MB) - free = 23068672 (22.0MB) - 0.0% used -PS Old Generation - capacity = 217579520 (207.5MB) - used = 41781472 (39.845916748046875MB) - free = 175798048 (167.65408325195312MB) - 19.20285144484187% used - -27776 interned Strings occupying 3262336 bytes. -``` - -查询进程pid = 41843 存活的对象占用内存前100排序: `jmap -histo:live 41843 | head -n 100` - - - -## 补充 - -### 对象头 - -Java对象保存在内存中时,由以下三部分组成:对象头、实例数据和对齐填充字节。 - -java的对象头由以下三部分组成:mark word、指向类信息的指针和数组长度(数组对象才有)。 - -mark word包含:对象的hashcode、分代年龄和锁标志位。 - -对象的实例数据就是在java代码中对象的属性和值。 - -对齐填充字节:因为JVM要求java的对象占的内存大小应该是8bit的倍数,所以后面有几个字节用于把对象的大小补齐至8bit的倍数。 - -**内存对齐的主要作用是:** - -1. 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 -2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。 - -### main方法执行过程 - -以下是示例代码: - -```java -public class App { - public static void main(String[] args) { - Student s = new Student("dabin"); - s.getName(); - } -} - -class Student { - public String name; - - public Student(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } -} -``` - -执行main方法的步骤如下: - -1. 编译好 App.java 后得到 App.class 后,执行 App.class,系统会启动一个 JVM 进程,从 classpath 路径中找到一个名为 App.class 的二进制文件,将 App 的类信息加载到运行时数据区的方法区内,这个过程叫做 App 类的加载 -2. JVM 找到 App 的主程序入口,执行main方法 -3. 这个main中的第一条语句为 `Student student = new Student("dabin") `,就是让 JVM 创建一个Student对象,但是这个时候方法区中是没有 Student 类的信息的,所以 JVM 马上加载 Student 类,把 Student 类的信息放到方法区中 -4. 加载完 Student 类后,JVM 在堆中为一个新的 Student 实例分配内存,然后调用构造函数初始化 Student 实例,这个 Student 实例持有 **指向方法区中的 Student 类的类型信息** 的引用 -5. 执行student.getName()时,JVM 根据 student 的引用找到 student 对象,然后根据 student 对象持有的引用定位到方法区中 student 类的类型信息的方法表,获得 getName() 的字节码地址。 -6. 执行getName() - - - -### 对象创建过程 - -1. 类加载检查 - - 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。 - -2. 分配内存 - - 在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。 - -3. 初始化零值 - - 分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。 - -4. 设置对象头 - - Hotspot 虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据(哈希码、GC 分代年龄、锁状态标志等等),另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。 - -5. 执行init方法 - - 按照Java代码进行初始化。 - - - -## 参考资料 - -- 周志明. 深入理解 Java 虚拟机 [M]. 机械工业出版社 diff --git a/Java/Java web.md b/Java/Java web.md deleted file mode 100644 index b92935b..0000000 --- a/Java/Java web.md +++ /dev/null @@ -1,83 +0,0 @@ - - - - -- [servlet](#servlet) -- [jsp](#jsp) -- [Tomcat](#tomcat) - - [tomcat和netty区别](#tomcat%E5%92%8Cnetty%E5%8C%BA%E5%88%AB) -- [跨域](#%E8%B7%A8%E5%9F%9F) - - [同源策略](#%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5) - - [CSRF攻击](#csrf%E6%94%BB%E5%87%BB) -- [statement和prepareStatement](#statement%E5%92%8Cpreparestatement) - - - -## servlet - -servlet接口定义的是一套处理网络请求的规范。servlet运行在服务端,由servlet容器管理,用于生成动态的内容(早期的web技术主要用来浏览静态页面)。 - -Servlet是什么? - -- 运行在Servlet容器(如Tomcat)中的Java类 -- 没有main方法,不能独立运行,必须被部署到Servlet容器中,由容器来实例化和调用Servlet的方法 - -servlet生命周期指它从被web服务器加载到它被销毁的整个过程,分三个阶段: -1. 初始化阶段,调用init()方法 -2. 响应客户请求阶段,调用service()方法 -3. 终止阶段,调用destroy()方法 - -servlet容器:负责接收请求,生成servlet实例用于处理请求(调用service方法),然后将servlet生成的响应数据返回给客户端。 - -![](../img/web/servlet-container.jpg) - - - -## jsp - -Java server pages。当有人请求JSP时,服务器会自动帮我们把JSP中的HTML片段和java代码拼接成静态资源响应给浏览器。也就是说JSP运行在服务器端,但最终发给客户端的都已经是转换好的HTML静态页面(在响应体里)。 - -即:**JSP = HTML + Java片段**(各种标签本质上还是Java片段) - - - -## Tomcat - -Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持。 - -### tomcat和netty区别 - -Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。 - - - -## 跨域 - -当发送请求时,如果浏览器发现是跨源AJAX请求,就自动在头信息之中,添加一个Origin字段。 - -`Origin: http://api.bob.com` - -对于服务端,如果请求头Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP响应。浏览器收到响应后,发现响应头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。 - -如果请求头Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。 - -```java -Access-Control-Allow-Origin: http://api.bob.com -Access-Control-Allow-Credentials: true -Access-Control-Expose-Headers: FooBar -``` - -### 同源策略 - -同domain(或ip),同端口,同协议视为同一个域,一个域内的脚本仅仅具有本域内的权限,也就是本域脚本只能读写本域内的资源,而无法访问其它域的资源。这种安全限制称为同源策略。 - -### CSRF攻击 - -跨域请求有可能被黑客利用来发动 CSRF攻击。CSRF攻击(Cross-site request forgery),跨站请求伪造。攻击者盗用了你的身份,以你的名义发送请求,比如发送邮件,发消息,盗取你的账号,甚至购买商品。 - - - -## statement和prepareStatement -Statement对象每次执行sql,相关数据库都会执行sql语句的编译,prepareStatement是预编译的,支持批处理。 -PreparedStatement是预编译的,对于批量处理可以大大提高效率,也叫JDBC存储过程。 -prepareStatement对象的开销比statement对象开销大,对于一次性操作使用statement更佳。 \ No newline at end of file diff --git "a/Java/Java \347\274\226\347\250\213\346\200\235\346\203\263.md" "b/Java/Java \347\274\226\347\250\213\346\200\235\346\203\263.md" deleted file mode 100644 index 960b2ac..0000000 --- "a/Java/Java \347\274\226\347\250\213\346\200\235\346\203\263.md" +++ /dev/null @@ -1,3916 +0,0 @@ - - - -- [基础知识](#%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86) - - [数据类型](#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B) - - [整型](#%E6%95%B4%E5%9E%8B) - - [浮点类型](#%E6%B5%AE%E7%82%B9%E7%B1%BB%E5%9E%8B) - - [char 类型](#char-%E7%B1%BB%E5%9E%8B) - - [boolean 类型](#boolean-%E7%B1%BB%E5%9E%8B) - - [大数值](#%E5%A4%A7%E6%95%B0%E5%80%BC) - - [操作符](#%E6%93%8D%E4%BD%9C%E7%AC%A6) - - [注释文档](#%E6%B3%A8%E9%87%8A%E6%96%87%E6%A1%A3) - - [代码规范](#%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83) -- [控制执行流程](#%E6%8E%A7%E5%88%B6%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B) - - [switch](#switch) - - [break 和 continue 实现 goto](#break-%E5%92%8C-continue-%E5%AE%9E%E7%8E%B0-goto) -- [初始化和清理](#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E6%B8%85%E7%90%86) - - [成员初始化](#%E6%88%90%E5%91%98%E5%88%9D%E5%A7%8B%E5%8C%96) - - [可变参数列表](#%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8) -- [访问权限控制](#%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6) - - [访问权限修饰词](#%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90%E4%BF%AE%E9%A5%B0%E8%AF%8D) -- [复用类](#%E5%A4%8D%E7%94%A8%E7%B1%BB) - - [继承语法](#%E7%BB%A7%E6%89%BF%E8%AF%AD%E6%B3%95) - - [final 关键字](#final-%E5%85%B3%E9%94%AE%E5%AD%97) - - [初始化及类的加载](#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8A%E7%B1%BB%E7%9A%84%E5%8A%A0%E8%BD%BD) - - [继承与初始化](#%E7%BB%A7%E6%89%BF%E4%B8%8E%E5%88%9D%E5%A7%8B%E5%8C%96) -- [多态](#%E5%A4%9A%E6%80%81) - - [缺陷:“覆盖”私有方法](#%E7%BC%BA%E9%99%B7%E8%A6%86%E7%9B%96%E7%A7%81%E6%9C%89%E6%96%B9%E6%B3%95) - - [域和静态方法](#%E5%9F%9F%E5%92%8C%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95) - - [构造器和多态](#%E6%9E%84%E9%80%A0%E5%99%A8%E5%92%8C%E5%A4%9A%E6%80%81) - - [构造器的调用顺序](#%E6%9E%84%E9%80%A0%E5%99%A8%E7%9A%84%E8%B0%83%E7%94%A8%E9%A1%BA%E5%BA%8F) -- [接口](#%E6%8E%A5%E5%8F%A3) - - [抽象类](#%E6%8A%BD%E8%B1%A1%E7%B1%BB) - - [接口的域](#%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%9F%9F) -- [内部类](#%E5%86%85%E9%83%A8%E7%B1%BB) - - [.this 和 .new](#this-%E5%92%8C-new) - - [匿名内部类](#%E5%8C%BF%E5%90%8D%E5%86%85%E9%83%A8%E7%B1%BB) - - [工厂方法](#%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95) - - [嵌套类](#%E5%B5%8C%E5%A5%97%E7%B1%BB) - - [为什么需要内部类](#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E5%86%85%E9%83%A8%E7%B1%BB) - - [局部内部类](#%E5%B1%80%E9%83%A8%E5%86%85%E9%83%A8%E7%B1%BB) - - [内部类标识符](#%E5%86%85%E9%83%A8%E7%B1%BB%E6%A0%87%E8%AF%86%E7%AC%A6) -- [容器](#%E5%AE%B9%E5%99%A8) - - [添加一组元素](#%E6%B7%BB%E5%8A%A0%E4%B8%80%E7%BB%84%E5%85%83%E7%B4%A0) - - [迭代器](#%E8%BF%AD%E4%BB%A3%E5%99%A8) - - [LinkedList](#linkedlist) - - [Set](#set) - - [Map](#map) - - [Queue](#queue) - - [PriorityQueue](#priorityqueue) - - [foreach 和 迭代器](#foreach-%E5%92%8C-%E8%BF%AD%E4%BB%A3%E5%99%A8) - - [适配器方法](#%E9%80%82%E9%85%8D%E5%99%A8%E6%96%B9%E6%B3%95) -- [异常、断言和日志](#%E5%BC%82%E5%B8%B8%E6%96%AD%E8%A8%80%E5%92%8C%E6%97%A5%E5%BF%97) - - [异常分类](#%E5%BC%82%E5%B8%B8%E5%88%86%E7%B1%BB) - - [声明异常](#%E5%A3%B0%E6%98%8E%E5%BC%82%E5%B8%B8) - - [捕获异常](#%E6%8D%95%E8%8E%B7%E5%BC%82%E5%B8%B8) - - [带资源的 try 语句](#%E5%B8%A6%E8%B5%84%E6%BA%90%E7%9A%84-try-%E8%AF%AD%E5%8F%A5) - - [断言](#%E6%96%AD%E8%A8%80) - - [启用和禁用断言](#%E5%90%AF%E7%94%A8%E5%92%8C%E7%A6%81%E7%94%A8%E6%96%AD%E8%A8%80) - - [日志](#%E6%97%A5%E5%BF%97) - - [logback](#logback) -- [字符串](#%E5%AD%97%E7%AC%A6%E4%B8%B2) - - [格式化输出](#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%BE%93%E5%87%BA) - - [printf() 和 format()](#printf-%E5%92%8C-format) - - [Formatter](#formatter) - - [正则表达式](#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F) - - [基础](#%E5%9F%BA%E7%A1%80) - - [创建正则表达式](#%E5%88%9B%E5%BB%BA%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F) - - [Pattern 和 Matcher](#pattern-%E5%92%8C-matcher) - - [扫描输入](#%E6%89%AB%E6%8F%8F%E8%BE%93%E5%85%A5) - - [Scanner 定界符](#scanner-%E5%AE%9A%E7%95%8C%E7%AC%A6) - - [用正则表达式扫描](#%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%89%AB%E6%8F%8F) -- [类型信息](#%E7%B1%BB%E5%9E%8B%E4%BF%A1%E6%81%AF) - - [反射](#%E5%8F%8D%E5%B0%84) -- [泛型](#%E6%B3%9B%E5%9E%8B) - - [类型参数的好处](#%E7%B1%BB%E5%9E%8B%E5%8F%82%E6%95%B0%E7%9A%84%E5%A5%BD%E5%A4%84) - - [泛型类](#%E6%B3%9B%E5%9E%8B%E7%B1%BB) - - [泛型接口](#%E6%B3%9B%E5%9E%8B%E6%8E%A5%E5%8F%A3) - - [泛型方法](#%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95) - - [可变参数和泛型方法](#%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E5%92%8C%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95) - - [匿名内部类](#%E5%8C%BF%E5%90%8D%E5%86%85%E9%83%A8%E7%B1%BB-1) - - [泛型擦除](#%E6%B3%9B%E5%9E%8B%E6%93%A6%E9%99%A4) - - [类型变量的限定](#%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E9%99%90%E5%AE%9A) - - [擦除的问题](#%E6%93%A6%E9%99%A4%E7%9A%84%E9%97%AE%E9%A2%98) - - [边界](#%E8%BE%B9%E7%95%8C) - - [通配符](#%E9%80%9A%E9%85%8D%E7%AC%A6) - - [上界通配符](#%E4%B8%8A%E7%95%8C%E9%80%9A%E9%85%8D%E7%AC%A6) - - [下界通配符](#%E4%B8%8B%E7%95%8C%E9%80%9A%E9%85%8D%E7%AC%A6) -- [数组](#%E6%95%B0%E7%BB%84) - - [复制数组](#%E5%A4%8D%E5%88%B6%E6%95%B0%E7%BB%84) - - [Arrays 工具](#arrays-%E5%B7%A5%E5%85%B7) - - [数组拷贝](#%E6%95%B0%E7%BB%84%E6%8B%B7%E8%B4%9D) - - [数组的比较](#%E6%95%B0%E7%BB%84%E7%9A%84%E6%AF%94%E8%BE%83) - - [数组元素的比较](#%E6%95%B0%E7%BB%84%E5%85%83%E7%B4%A0%E7%9A%84%E6%AF%94%E8%BE%83) - - [数组排序](#%E6%95%B0%E7%BB%84%E6%8E%92%E5%BA%8F) - - [排序数组查找](#%E6%8E%92%E5%BA%8F%E6%95%B0%E7%BB%84%E6%9F%A5%E6%89%BE) -- [容器深入研究](#%E5%AE%B9%E5%99%A8%E6%B7%B1%E5%85%A5%E7%A0%94%E7%A9%B6) - - [填充容器](#%E5%A1%AB%E5%85%85%E5%AE%B9%E5%99%A8) - - [SortedSet](#sortedset) - - [队列](#%E9%98%9F%E5%88%97) - - [优先级队列](#%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97) - - [双向队列](#%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97) - - [LinkedHashMap](#linkedhashmap) - - [Colletions 工具类](#colletions-%E5%B7%A5%E5%85%B7%E7%B1%BB) - - [排序和查询](#%E6%8E%92%E5%BA%8F%E5%92%8C%E6%9F%A5%E8%AF%A2) - - [只读容器](#%E5%8F%AA%E8%AF%BB%E5%AE%B9%E5%99%A8) - - [Collection 和 Map 的同步控制](#collection-%E5%92%8C-map-%E7%9A%84%E5%90%8C%E6%AD%A5%E6%8E%A7%E5%88%B6) - - [快速报错机制](#%E5%BF%AB%E9%80%9F%E6%8A%A5%E9%94%99%E6%9C%BA%E5%88%B6) - - [Java 1.0/1.1 的容器](#java-1011-%E7%9A%84%E5%AE%B9%E5%99%A8) - - [BitSet](#bitset) -- [Java I/O 系统](#java-io-%E7%B3%BB%E7%BB%9F) - - [输入和输出](#%E8%BE%93%E5%85%A5%E5%92%8C%E8%BE%93%E5%87%BA) - - [InputStream 和 OutputStream](#inputstream-%E5%92%8C-outputstream) - - [Reader 和 Writer](#reader-%E5%92%8C-writer) - - [组合输入输出流过滤器](#%E7%BB%84%E5%90%88%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E6%B5%81%E8%BF%87%E6%BB%A4%E5%99%A8) - - [文本输入和输出](#%E6%96%87%E6%9C%AC%E8%BE%93%E5%85%A5%E5%92%8C%E8%BE%93%E5%87%BA) - - [以文本格式存储对象](#%E4%BB%A5%E6%96%87%E6%9C%AC%E6%A0%BC%E5%BC%8F%E5%AD%98%E5%82%A8%E5%AF%B9%E8%B1%A1) - - [字符编码方式](#%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%E6%96%B9%E5%BC%8F) - - [读写二进制数据](#%E8%AF%BB%E5%86%99%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0%E6%8D%AE) - - [DataInput 和 DataOutput](#datainput-%E5%92%8C-dataoutput) - - [随机访问文件](#%E9%9A%8F%E6%9C%BA%E8%AE%BF%E9%97%AE%E6%96%87%E4%BB%B6) - - [序列化](#%E5%BA%8F%E5%88%97%E5%8C%96) - - [操作文件](#%E6%93%8D%E4%BD%9C%E6%96%87%E4%BB%B6) - - [目录列表器](#%E7%9B%AE%E5%BD%95%E5%88%97%E8%A1%A8%E5%99%A8) - - [](#) -- [枚举类型](#%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B) - - [基本 enum 特性](#%E5%9F%BA%E6%9C%AC-enum-%E7%89%B9%E6%80%A7) - - [向 enum 添加新方法](#%E5%90%91-enum-%E6%B7%BB%E5%8A%A0%E6%96%B0%E6%96%B9%E6%B3%95) - - [覆盖 enum 的方法](#%E8%A6%86%E7%9B%96-enum-%E7%9A%84%E6%96%B9%E6%B3%95) - - [Switch 语句中的 enum](#switch-%E8%AF%AD%E5%8F%A5%E4%B8%AD%E7%9A%84-enum) - - [EnumSet](#enumset) - - [源码解析](#%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90) - - [EnumMap](#enummap) -- [注解](#%E6%B3%A8%E8%A7%A3) - - [基本语法](#%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95) - - [自定义注解](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3) - - [元注解](#%E5%85%83%E6%B3%A8%E8%A7%A3) - - [编写注解处理器](#%E7%BC%96%E5%86%99%E6%B3%A8%E8%A7%A3%E5%A4%84%E7%90%86%E5%99%A8) - - [注解综合](#%E6%B3%A8%E8%A7%A3%E7%BB%BC%E5%90%88) - - - -## 基础知识 - -### 数据类型 - -#### 整型 - -| 类型 | 存储空间 | -| ----- | -------- | -| int | 4字节 | -| short | 2字节 | -| long | 8字节 | -| byte | 1字节 | - -byte 的取值范围是-128~127。整型的取值范围和运行 Java 代码的机器无关。Java 没有无符号的整型。 - -**数据类型表示:** - -长整型:400L - -十六进制:0xCA - -八进制:020(有前缀0) - -二进制:0b1001(Java 7及以上版本) - -从 Java 7开始,可以为数据字面量添加下划线,如1_000_000,方便易读。Java 编译器会去除这些下划线。 - -#### 浮点类型 - -| 类型 | 存储空间 | -| ------ | -------- | -| float | 4字节 | -| double | 8字节 | - -float 类型的数值会有后缀 F 或者 f (2.01F),没有后缀 F 的浮点数默认为 double 类型(也可以加后缀 D)。浮点数采用二进制系统表示,有些数值会有精度损失,如`System.out.println(2.0 - 1.1)`会输出0.8999999999999999。如果数值计算不允许有任何精度误差,应该使用 BigDecimal。 - -**特殊值** - -正无穷大:Double.POSITIVE_INFINITY - -负无穷大:Double.NEGATIVE_INFINITY - -NaN(不是一个数字):Double.NaN - -#### char 类型 - -Unicode 字符用一个或者两个 char 值描述。Unicode 字符可以表示为十六进制,其范围从/u0000到/uffff。 - -#### boolean 类型 - -布尔类型有两个值:true 和 false。布尔型和整型不能相互转化。Java 语言表达式所操作的 boolean 值,在编译之后都使用Java虚拟机中的int数据类型来代替,而 boolean 数组将会被编码成 Java 虚拟机的 byte 数组,每个元素 boolean 元素占8位”。这样我们可以得出 boolean 类型占了单独使用是4个字节,在数组中又是1个字节。 - -#### 大数值 - -BigInteger 实现了任意精度的整数运算,BigDecimal 实现了任意精度的浮点数运算。 - -```java -BigInteger a = BigInteger.valueOf(100); -BigInteger b = BigInteger.valueOf(100); -BigInteger c = a.add(b); -BigInteger d = c.multiply(b.add(BigInteger.valueOf(2))); -``` - -### 操作符 - -**截尾和舍入** - -```java -float num = 0.7f; -//类型转化对数字进行截尾 -System.out.println((int)num); //0 -//四舍五入操作 -System.out.println(Math.round(num)); //1 -``` - -### 注释文档 - -javadoc 用来提取注释的工具。javadoc 只能为 public 和 protected 成员进行文档注释。 - -### 代码规范 - -可以采用将 public 成员放在开头,后面跟着 protect、包访问权限和 private 成员的创建类的形式,方便类的使用者阅读最为重要的部分(public成员)。 - -```java -public class OrganizedByAccess { - public void method1() {} - public void method2() {} - protected void method3() {} - void method4() {} - private method5() {} - private int i; - //... -} -``` - - - -## 控制执行流程 - -### switch - -break 会跳出 switch 语句,没有 break 语句则会一直往下执行。 - -```java -int i = 1; -switch (i) { - case 0: - System.out.println("i = 0"); - break; - case 1: - System.out.println("i = 1"); - break; - case 2: - System.out.println("i = 2"); - break; - default: - System.out.println("i >= 3"); -} -//输出i = 1 - -switch (i) { - case 0: - System.out.println("i = 0"); - //break; - case 1: - System.out.println("i = 1"); - //break; - case 2: - System.out.println("i = 2"); - //break; - default: - System.out.println("i >= 3"); -} -//输出 -//i = 1 -//i = 2 -//i >= 3 -``` - -### break 和 continue 实现 goto - -```java -public class LabeledFor { - public static void main(String[] args) { - int i = 0; - outer: // Can't have statements here - for(; true ;) { // infinite loop - inner: // Can't have statements here - for(; i < 10; i++) { - print("i = " + i); - if(i == 2) { - print("continue"); - continue; - } - if(i == 3) { - print("break"); - i++; - break;//break跳出循环,不会执行递增操作 - } - if(i == 7) { - print("continue outer"); - i++; - continue outer;//continue跳到循环顶部,不会执行递增操作 - } - if(i == 8) { - print("break outer"); - break outer; - } - for(int k = 0; k < 5; k++) { - if(k == 3) { - print("continue inner"); - continue inner; - } - } - } - } - // Can't break or continue to labels here - } -} -``` - - - -## 初始化和清理 - -### 成员初始化 - -局部变量未初始化就使用,会产生编译时错误。类的数据成员是基本类型,它们会有初值(如 int 类型的数据成员初值为0)。 - -### 可变参数列表 - -Java SE5 开始支持可变参数列表。当指定参数时,编译器会将元素列表转换为数组。 - -```java -public class VarArgs { - public static void printArray(Object... args) { - for(Object obj : args) { - System.out.print(obj + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - printArray(new Integer(1), new Integer(3)); - printArray("tyson", "sophia", "tom"); - printArray(new Integer[]{2, 4, 6}); - printArray();//空列表 - } -} -``` - -## 访问权限控制 - -package 语句必须是文件中第一行非注释代码。 - -### 访问权限修饰词 - -1. 包访问权限 - - 默认的访问权限没有任何关键字,通常是指包访问权限,即当前包的所有其他类对当前成员具有访问权限。 - -2. protected - - 继承访问权限,派生类可以访问基类的 protected 元素。同时,protected 也提供包访问权限,即相同包内的其他类也可以访问 protected 元素。 - -3. private - - 通过 private 隐藏了代码细节,类库设计者可以更改类内部工作方式,而不会影响客户端。 - -4. public - - - -示例代码: - -```java -package com.tyson.chapter6_access; -//Cookie.java -public class Cookie { - public Cookie() { - System.out.println("Cookie constructor"); - } - protected void bite() { - System.out.println("bite"); - } -} - -//ChocolateChip.java -public class ChocolateChip extends Cookie { - //私有构造器 - private ChocolateChip() { - System.out.println("chocolate chip constructor"); - } - //通过静态方法创建类 - public static ChocolateChip createChocolateChip() { - return new ChocolateChip(); - } - - public void chomp() { - //访问父类的protected成员 - bite(); - } -} - -class Application { - public static void main(String[] args) { - ChocolateChip chocolateChip = ChocolateChip.createChocolateChip(); - chocolateChip.chomp(); - } -} -``` - - - -## 复用类 - -### 继承语法 - -派生类如果没有指定某个基类的构造器,则会调用基类的默认构造器,若没有默认的构造器(不带参数的构造器),编译器会报错。 - -### final 关键字 - -1. final 数据 - - 基本类型变量用 final 修饰,则该变量是常量,数值不能改变;对象引用用 final 修饰,则一旦该引用被初始化指向一个对象,就不能再把它改为指向另一个对象,不过对象自身可以修改,只是引用不能修改。 - -2. final 参数 - - 将参数指明为 final,则无法在方法中更改参数。 - -```java -public class FinalArguments { - void add(final Num num) { - //num = new Num(1); //不能更改final参数 - num.i++; - } - void add(final int i) { - //i++; //不能更改final参数的值 - } -} - -class Num { - int i; - public Num(int i) { - this.i = i; - } -} -``` - -3. final 方法 - - final 方法不能被重写,使用 final 方法主要是为了防止继承类修改它的含义。过去使用 final 方法效率会高点,现在的 JVM 相比之前有了很大的优化,没必要通过设置 final 来提高效率。 - -4. final 类 - - final 类不能被继承。final 类的所有方法都被隐式指定为 final。JDK 的 String 类就是 final 类。 - -### 初始化及类的加载 - -#### 继承与初始化 - -```java -class Insect { - private int i = printInit("Insect.i initialized"); - protected int j; - Insect() { - System.out.println("i = " + i + ", j = " + j); - j = 39; - } - private static int x1 = - printInit("static Insect.x1 initialized"); - static int printInit(String s) { - System.out.println(s); - return 47; - } -} - -public class Beetle extends Insect { - private int k = printInit("Beetle.k initialized"); - public Beetle() { - System.out.println("k = " + k + ", j = " + j); - } - private static int x2 = - printInit("static Beetle.x2 initialized"); - public static void main(String[] args) { - System.out.println("Beetle constructor"); - Beetle b = new Beetle(); - } -} -/*output -static Insect.x1 initialized -static Beetle.x2 initialized -Beetle constructor -Insect.i initialized -i = 47, j = 0 -Beetle.k initialized -k = 47, j = 39 - */ -``` - - - -## 多态 - -封装把接口和实现分离开来,多态消除类型之间的耦合关系。 - -向上转型:将子类看作是它的基类的过程。子类转型为基类就是在继承图上向上移动。 - -![向上转型](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190402204948375-70203256.png) - -### 缺陷:“覆盖”私有方法 - -```java -public class PrivateOverride { - private void f() { - System.out.println("private f()"); - } - - public static void main(String[] args) { - PrivateOverride po = new Derived(); - po.f(); - } -} - -class Derived extends PrivateOverride { - public void f() { - System.out.println("public f()"); - } -} -/* -private f() - */ -``` - -Derived 类的 f() 实际上是一个全新的方法。基类的 f() 方法在子类 Derived 中不可见,因此不能被重载。 - -### 域和静态方法 - -只有普通的方法调用具备多态性,域和静态方法没有多态性。 - -### 构造器和多态 - -构造器实际上是 static 方法,只不过 static 声明是隐式的,不具备多态性。 - -#### 构造器的调用顺序 - -```java -class Meal { - private int weight = get(); - Meal() { - print("Meal()"); - } - public int get() { - System.out.println("Meal.get()"); - return 1; - } -} - -class Bread { - Bread() { - print("Bread()"); - } -} - -class Cheese { - Cheese() { - print("Cheese()"); - } -} - -class Lettuce { - Lettuce() { - print("Lettuce()"); - } -} - -class Lunch extends Meal { - private int price = food(); - Lunch() { - print("Lunch()"); - } - public int food() { - System.out.println("Lunch.food()"); - return 1; - } -} - -class PortableLunch extends Lunch { - PortableLunch() { - print("PortableLunch()"); - } -} - -public class Sandwich extends PortableLunch { - private Bread b = new Bread(); - private Cheese c = new Cheese(); - private Lettuce l = new Lettuce(); - - public Sandwich() { - print("Sandwich()"); - } - - public static void main(String[] args) { - new Sandwich(); - } -} /* Output: -Meal.get() -Meal() -Lunch.food() -Lunch() -PortableLunch() -Bread() -Cheese() -Lettuce() -Sandwich() -*/ - -``` - -调用顺序: - -1. 按照声明顺序调用基类成员的初始化方法 -2. 基类构造器。从最顶层的基类到最底层的派生类 -3. 按照声明顺序调用成员的初始化方法 -4. 派生类构造器 - - - -## 接口 - -接口和内部类为我们提供了一种将接口与实现分离的方法。 - -### 抽象类 - -从一个抽象类继承,需要为基类中的所有方法提供方法定义。如果没有提供,则派生类也是抽象类。 - -如果有一个类,让其包含任何 abstract 方法都没有实际意义,而我们又想阻止产生这个类的任何对象,这时候可以把它设置成一个没有任何抽象方法的抽象类。 - -### 接口的域 - -接口中的域都自动声明为`public static final`,故接口可以用来创建常量组。Java SE5之前没有提供 enum 实现,可以通过接口实现 enum 的功能。 - -## 内部类 - -内部类允许把一些逻辑相关的类组织在一起,并控制内部类的可视性。内部类可以访问外围类,有些通过编写内部类可以让代码结构更清晰。 - -### .this 和 .new - -使用外部类的名字后面紧跟 .this,可以生成对外部类对象的引用。 - -```java -public class DotThis { - void f() { - System.out.println("DotThis.f()"); - } - public class Inner { - public DotThis outer() { - return DotThis.this; - } - } - public Inner inner() { - return new Inner(); - } - - public static void main(String[] args) { - DotThis dt = new DotThis(); - DotThis.Inner dti = dt.inner(); - dti.outer().f(); - } -} -//output DotThis.f() -``` - -使用 .new 创建内部类的对象。 - -```java -public class DotNew { - public class Inner {} - - public static void main(String[] args) { - DotNew dn = new DotNew(); - DotNew.Inner dni = dn.new Inner(); - } -} -``` - -创建内部类的对象,必须通过外部类的对象来创建,在拥有外部类对象之前是不可能创建内部类对象的。这是因为内部类对象会隐式连接到创建它的外部类对象上。但是如果创建的是嵌套类(静态内部类),则不需要创建外部类对象。 - -### 匿名内部类 - -```java -//Wrapping.java -public class Wrapping { - private int i; - - public Wrapping(int x) { - i = x; - } - public int value() { - return i; - } -} - -//Parcel.java -public class Parcel { - public Wrapping wrapping(int x) { - return new Wrapping(x) {//传递构造器参数 - @Override - public int value() { - return super.value() * 47; - } - }; - } - - public static void main(String[] args) { - Parcel p = new Parcel(); - Wrapping w = p.wrapping(8); - System.out.println(w.value()); - } -} -//output 376 -``` - -在匿名类定义字段时,还能够对其执行初始化操作。 - -```java -//Destination.java -public interface Destination { - String readLabel(); -} - -//Parcel1.java -public class Parcel1 { - public Destination destination(final String dest) { - return new Destination() { - private String label = dest; - @Override - public String readLabel() { - return label; - } - }; - } - - public static void main(String[] args) { - Parcel1 p1 = new Parcel1(); - Destination d = p1.destination("Puning"); - System.out.println(d.readLabel()); - } -} -``` - -匿名内部类没有命名构造器,通过实例初始化给匿名内部类创建构造器的效果。 - -```java -abstract class Base { - public Base(int i) { - System.out.println("Base constructor, i = " + i); - } - - public abstract void f(); -} - -public class AnonymousConstructor { - public static Base getBase(int i) { - return new Base(i) { - //构造器的效果 - { - System.out.println("Inside instance initializer"); - } - @Override - public void f() { - System.out.println("In anonymous f()"); - } - }; - } - - public static void main(String[] args) { - Base base = getBase(47); - base.f(); - } -} /* Output: -Base constructor, i = 47 -Inside instance initializer -In anonymous f() -*/ -``` - -#### 工厂方法 - -使用匿名内部类改进工厂方法。 - -```java -interface Game { boolean move();} -interface GameFactory { Game getGame();} - -public class Games { - public static void playGame(GameFactory gameFactory) { - Game game = gameFactory.getGame(); - while(game.move()) { - ; - } - } - - public static void main(String[] args) { - playGame(Checkers.factory); - playGame(Chess.factory); - } -} - -class Chess implements Game { - - private Chess() {} - private int moves = 0; - private static final int MOVES = 4; - - @Override - public boolean move() { - System.out.println("chess move " + moves); - return ++moves != MOVES; - } - - public static GameFactory factory = new GameFactory() { - @Override - public Game getGame() { - return new Chess(); - } - }; -} - -class Checkers implements Game { - private Checkers() {} - private int moves = 0; - private static final int MOVES = 3; - @Override - public boolean move() { - System.out.println("checkers move" + moves); - return ++moves != MOVES; - } - - public static GameFactory factory = new GameFactory() { - @Override - public Game getGame() { - return new Checkers(); - } - }; -} -/* -checkers move0 -checkers move1 -checkers move2 -chess move 0 -chess move 1 -chess move 2 -chess move 3 - */ -``` - -### 嵌套类 - -将内部类声明为 static,即为嵌套类。普通的内部类隐式保存了一个指向外围类对象的引用,而嵌套类没有。所以创建嵌套类的对象,不需要先创建外围类对象。并且嵌套类不能访问非静态的外围类的成员。 - -普通的内部类不能包含 static 字段和 static 方法,也不能包含嵌套类,但嵌套类可以包含这些。 - -```java -public class NestingClass { - public static class StaticInner { - public void dynamicFuc() { - System.out.println("StaticInner动态方法"); - } - public static void staticFuc() { - System.out.println("StaticInner静态方法"); - } - } - - public static void main(String[] args) { - StaticInner si = new StaticInner(); - si.dynamicFuc(); - StaticInner.staticFuc();//直接通过类名调用静态方法 - } -} -/* -StaticInner动态方法 -StaticInner静态方法 - */ -``` - -嵌套类没有.this引用。 - -### 为什么需要内部类 - -使用内部类可以实现多重继承。 - -```java -interface Selector { - boolean end(); - Object current(); - void next(); -} - -public class Sequence { - private Object[] items; - private int next = 0; - - public Sequence(int size) { - items = new Object[size]; - } - - public void add(Object x) { - if (next < items.length) - items[next++] = x; - } - - private class SequenceSelector implements Selector { - private int i = 0; - - public boolean end() { - return i == items.length; - } - public Object current() { - return items[i]; - } - public void next() { - if (i < items.length) i++; - } - } - - public Selector selector() { - return new SequenceSelector(); - } - - public static void main(String[] args) { - Sequence sequence = new Sequence(10); - for (int i = 0; i < 10; i++) - sequence.add(Integer.toString(i)); - Selector selector = sequence.selector(); - while (!selector.end()) { - System.out.print(selector.current() + " "); - selector.next(); - } - } -} /* Output: -0 1 2 3 4 5 6 7 8 9 -*/ -``` - -如果 Sequence.java 不使用内部类,就必须声明 Sequence 是一个 Selector,对于某个特定的 Sequence 只能有一个 Selector。使用内部类的话很容易就可以拥有另一个方法 reverseSelector(),用来生成一个反向遍历序列的 Selector。 - -### 局部内部类 - -```java -interface Counter {int next();} - -public class LocalInnerClass { - private int count = 0; - - Counter getCounter(final String name) { - // A local inner class: - class LocalCounter implements Counter { - public LocalCounter() { - // Local inner class can have a constructor - print("LocalCounter()"); - } - - public int next() { - printnb(name); // Access local final - return count++; - } - } - return new LocalCounter(); - } - - // The same thing with an anonymous inner class: - Counter getCounter2(final String name) { - return new Counter() { - // Anonymous inner class cannot have a named - // constructor, only an instance initializer: - { - print("Counter()"); - } - - public int next() { - printnb(name); // Access local final - return count++; - } - }; - } - - public static void main(String[] args) { - LocalInnerClass lic = new LocalInnerClass(); - Counter c1 = lic.getCounter("Local inner "), - c2 = lic.getCounter2("Anonymous inner "); - print(c1.next()); - print(c2.next()); - } -} /* Output: -LocalCounter() -Counter() -Local inner 0 -Anonymous inner 1 -*/ -``` - -局部内部类可以拥有命名的构造器或者重载构造器,而匿名内部类只能使用实例初始化。如果需要不止一个该内部类对象,那么只能使用局部内部类。 - -### 内部类标识符 - -内部类文件的命名格式:外围类名字加上"$",再加上内部类的名字(如果是匿名类,则是一个数字)。 - -`LocalInnerClass$1LocalCounter.class` - -`LocalInnerClass$1.class` - - - -## 容器 - -![容器分类](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190407155626374-53010434.png) - -### 添加一组元素 - -```java -public class AddingGroups { - public static void main(String[] args) { - Collection nums = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); - Integer[] ints = {5, 6, 7}; - nums.addAll(Arrays.asList(ints)); - Collections.addAll(nums, 8, 9); - Collections.addAll(nums, ints); - - List list = Arrays.asList(1, 2, 3); - list.set(1, 90); - System.out.println(list.getClass()); - //底层是数组java.util.Arrays$ArrayList,不能修改结构,java.lang.UnsupportedOperationException - //list.add(7); - } -} -``` - -`Arrays.asList()`返回类型是`java.util.Arrays$ArrayList`,底层是数组,试图删除或增加元素会抛异常 UnsupportedOperationException。 - -### 迭代器 - -```java -import typeinfo.pets.Pet; -import typeinfo.pets.Pets; -import java.util.Iterator; -import java.util.List; - -public class SimpleIteration { - public static void main(String[] args) { - List pets = Pets.arrayList(8); - Iterator it = pets.iterator(); - while(it.hasNext()) { - Pet p = it.next(); - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - for(Pet p : pets) { - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - it = pets.iterator(); - for(int i = 0; i < 4; i++) { - it.next(); - it.remove();//删除最近遍历的元素 - } - System.out.println(pets); - } -} -/*output -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx -[Pug, Cymric, Pug, Manx] - */ -``` - -ListIterator 是一个更为强大的 Iterator 子类型,它只能用于各种 List 类的遍历。ListIterator 可以双向移动。它还可以产生迭代器当前位置前一个和后一个元素的索引,并且可以使用 set() 方法修改最近遍历的元素。通过 listIterator(index) 可以创建指向索引为index的元素的ListIterator。 - -```java -public class ListIteration { - public static void main(String[] args) { - List pets = Pets.arrayList(8); - ListIterator it = pets.listIterator(); - while(it.hasNext()) { - System.out.print(it.next() + ", " + it.nextIndex() + - ", " + it.previousIndex() + "; "); - } - System.out.println(); - while(it.hasPrevious()) { - System.out.print(it.previous().id() + " "); - } - System.out.println(); - System.out.println(pets); - //创建指向索引为index元素处的ListIterator - it = pets.listIterator(3); - while(it.hasNext()) { - it.next(); - it.set(Pets.randomPet()); - } - System.out.println(pets); - } -}/*output -Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, 5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7; -7 6 5 4 3 2 1 0 -[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx] -[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, EgyptianMau] - */ -``` - -### LinkedList - -```java -public class LinkedListFeatures { - public static void main(String[] args) { - LinkedList pets = - new LinkedList(Pets.arrayList(5)); - print(pets); - // Identical: - print("pets.getFirst(): " + pets.getFirst()); - print("pets.element(): " + pets.element()); - // Only differs in empty-list behavior: - print("pets.peek(): " + pets.peek()); - // Identical; remove and return the first element: - print("pets.remove(): " + pets.remove()); - print("pets.removeFirst(): " + pets.removeFirst()); - // Only differs in empty-list behavior: - print("pets.poll(): " + pets.poll()); - print(pets); - pets.addFirst(new Rat()); - print("After addFirst(): " + pets); - pets.offer(Pets.randomPet()); - print("After offer(): " + pets); - pets.add(Pets.randomPet()); - print("After add(): " + pets); - pets.addLast(new Hamster()); - print("After addLast(): " + pets); - print("pets.removeLast(): " + pets.removeLast()); - } -} /* Output: -[Rat, Manx, Cymric, Mutt, Pug] -pets.getFirst(): Rat -pets.element(): Rat -pets.peek(): Rat -pets.remove(): Rat -pets.removeFirst(): Manx -pets.poll(): Cymric -[Mutt, Pug] -After addFirst(): [Rat, Mutt, Pug] -After offer(): [Rat, Mutt, Pug, Cymric] -After add(): [Rat, Mutt, Pug, Cymric, Pug] -After addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster] -pets.removeLast(): Hamster -*/ -``` - -LinkedList 具有实现栈所有功能的所有方法,可以将 LinkedList 作为栈使用: - -```java -public class MyStack { - private LinkedList storage = new LinkedList<>(); - public void push(T t) { - storage.addFirst(t); - } - public T pop() { - return storage.removeFirst(); - } - public T peek() { - return storage.getFirst(); - } - public boolean isEmpty() { - return storage.isEmpty(); - } - @Override - public String toString() { - return storage.toString(); - } -} -``` - -### Set - -Set 不保存重复的元素,插入相同的元素会被忽略。HashSet 存储元素没有顺序;TreeSet 按照升序的方式存储元素;LinkedHashList 使用链表维护元素的插入顺序,并通过散列提供了快速访问能力。 - -```java -public class SortedSetOfInteger { - public static void main(String[] args) { - Random rand = new Random(47); - SortedSet set = new TreeSet<>(); - for (int i = 0; i < 1000; i++) { - set.add(rand.nextInt(30)); - } - System.out.println(set); - } -} -/*output -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] - */ -``` - -TreeSet 对字母排序是按照字典序,大小写字母会被分到不同的组,如果想按照字母序排序,可以向 TreeSet 构造器传入 String.CASE_INSENTIVE_ORDER 比较器。 - -```java -public class SortedWords { - public static void main(String[] args) { - //往构造器传入String.CASE_INSENTIVE_ORDER 比较器 - Set words = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - String[] strs = {"hello", "world", "tyson", "a"}; - words.addAll(Arrays.asList(strs)); - System.out.println(words); - } -} -/* -[a, hello, tyson, world] - */ -``` - -### Map - -HashMap 设计用来快速访问;TreeMap保持键始终处于升序状态;LinkedHashMap 使用链表维护元素的插入顺序,并通过散列提供了快速访问能力。 - -```java -public class PetMap { - public static void main(String[] args) { - Map petMap = new HashMap<>(); - petMap.put("Tyson", new Cat("cat")); - petMap.put("Sophia", new Dog("dog")); - petMap.put("Tom", new Hamster("hamster")); - - System.out.println(petMap.keySet()); - System.out.println(petMap.values()); - for(String person : petMap.keySet()) { - System.out.println(person + " : " + petMap.get(person)); - } - - Set> entries = petMap.entrySet(); - for(Map.Entry entry : entries) { - System.out.println(entry.getKey() + ": " + entry.getValue()); - entry.setValue(new Cat("cat")); - System.out.println(entry.getKey() + ": " + entry.getValue()); - } - - } -} -/*output -[Tom, Tyson, Sophia] -[Hamster hamster, Cat cat, Dog dog] -Tom : Hamster hamster -Tyson : Cat cat -Sophia : Dog dog -Tom: Hamster hamster -Tom: Cat cat -Tyson: Cat cat -Tyson: Cat cat -Sophia: Dog dog -Sophia: Cat cat - */ -``` - -### Queue - -LinkedList 实现了 Queue 接口,可以作为队列使用。 - -```java -public class QueueDemo { - public static void printQ(Queue queue) { - while(queue.peek() != null) { - System.out.print(queue.remove() + " "); - } - System.out.println(); - } - public static void main(String[] args) { - Queue queue = new LinkedList<>(); - Random rand = new Random(47); - for(int i = 0; i < 10; i++) { - queue.offer(rand.nextInt(i + 10)); - } - printQ(queue); - Queue qc = new LinkedList<>(); - for(char c : "tyson".toCharArray()) { - qc.offer(c); - } - printQ(qc); - } -} -``` - -peek()和 element()都将在不移除的情况下返回对头,peek()方法在队列为空时返回 null,而element()会跑 NoSuchElementExeception 异常。 - -poll()和remove()方法将移除并返回对头,poll()在队列为空时返回 null,而remove()会跑 NoSuchElementExeception 异常。 - -#### PriorityQueue - -Integer、String 和 Character 内建了自然排序,可以与 PriorityQueue 一起工作。要想在 PriorityQueue 中使用自己的类,就必须提供自己的 Comparator。 - -```java -public class PriorityQueueDemo { - public static void main(String[] args) { - PriorityQueue priorityQueue = - new PriorityQueue(); - Random rand = new Random(47); - for(int i = 0; i < 10; i++) - priorityQueue.offer(rand.nextInt(i + 10)); - QueueDemo.printQ(priorityQueue); - - List ints = Arrays.asList(25, 22, 20, - 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25); - priorityQueue = new PriorityQueue(ints); - QueueDemo.printQ(priorityQueue); - priorityQueue = new PriorityQueue( - ints.size(), Collections.reverseOrder()); - priorityQueue.addAll(ints); - QueueDemo.printQ(priorityQueue); - - String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION"; - List strings = Arrays.asList(fact.split("")); - PriorityQueue stringPQ = - new PriorityQueue(strings); - QueueDemo.printQ(stringPQ); - stringPQ = new PriorityQueue( - strings.size(), Collections.reverseOrder()); - stringPQ.addAll(strings); - QueueDemo.printQ(stringPQ); - - Set charSet = new HashSet(); - for(char c : fact.toCharArray()) - charSet.add(c); // Autoboxing - PriorityQueue characterPQ = - new PriorityQueue(charSet); - QueueDemo.printQ(characterPQ); - } -} /* Output: -0 1 1 1 1 1 3 5 8 14 -1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25 -25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1 - A A B C C C D D E E E F H H I I L N N O O O O S S S T T U U U W -W U U U T T S S S O O O O N N L I I H H F E E E D D C C C B A A - A B C D E F H I L N O S T U W -*///:~ -``` - -### foreach 和 迭代器 - -Java SE5引入了 Iterable 接口,该接口包含了一个能够产生 Iterator 的 iterator()方法。任何实现了 Iterable 的类(如Collection)都可以应用于 foreach 语句中。 - -```java -public class IterableClass implements Iterable { - protected String[] words = {"hello", "world", "program"}; - @Override - public Iterator iterator() { - return new Iterator() { - private int index = 0; - @Override - public boolean hasNext() { - return index < words.length; - } - @Override - public String next() { - return words[index++]; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - public static void main(String[] args) { - for(String s : new IterableClass()) { - System.out.print(s + " "); - } - } -} -``` - -### 适配器方法 - -添加反向迭代器功能。 - -```java -public class ReversibleArrayList extends ArrayList { - public ReversibleArrayList(Collection c) { super(c); } - public Iterable reversed() { - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - int current = size() - 1; - @Override - public boolean hasNext() { return current > -1; } - @Override - public T next() { return get(current--); } - }; - } - }; - } - public static void main(String[] args) { - ReversibleArrayList ral = - new ReversibleArrayList<>(Arrays.asList(new String[]{"hello", "world", "yes"})); - for(String s : ral.reversed()) { - System.out.print(s + " "); - } - } -} -``` - - - -## 异常、断言和日志 - -Java 语言给出了三种处理系统错误的机制:抛出异常、日志和使用断言。 - -### 异常分类 - -所有异常都有 Throwable 继承而来。 - -![异常层次结构](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190420203248534-1858171357.png) - - - -Error 类描述 Java 运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这种类型的对象。Error是程序无法处理的错误。 - -RuntimeException由程序错误导致,如果发生了 Runtime Exception,那一定是你的问题,应该修正程序避免这类异常发生。常见的运行时异常有: - -```java -ClassCastException -IndexOutOfBoundsException -NullPointerException -ArrayStoreException -NumberFormatException -ArithmeticException -``` - -其他 Exception 由具体的环境,如读取的文件不存在、文件为空、sql异常、寻找不存在的 Class 对象等导致的异常。 - -Java 语言规范将派生于 Error 类或 Runtime Exception 类的异常称为非检查(unchecked)异常;其他所有异常称为检查(checked)异常,编译器将会核查是否为所有的检查异常提供异常处理器。 - -### 声明异常 - -一个方法必须声明所有可能抛出的检查异常。任何抛出异常的方法都可能是一个死亡陷阱,如果没有异常处理器捕获这个异常,当前线程就会结束。非检查异常要么不可控,要么应当避免发生。 - -如果在子类覆盖了父类的方法,在子类方法中可以抛出更特定的异常,或者不抛异常。如果父类方法没有抛出异常,则子类只能在方法内捕获所有检查异常,不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围。 - -### 捕获异常 - -捕获多个异常可以合并 catch 子句(异常类型不存在子类关系)。 - -```java -try { - // -} catch (FileNotFindException | UnknowHostException e) { - e.printStackTrace(); -} -``` - -解耦合 try/catch 和 try/finally 语句块,这种设计方式不仅代码清晰,而且还会报告 finally 子句出现的错误。 - -```java -InputStream in = ...; -try { - try { - // - } finally { - in.close(); - } -} catch (IOException ex) { - ex.printStackTrace(); -} -``` - -### 带资源的 try 语句 - -```java -try (Scanner in = new Scanner(new FileInputStream("e:\data"), "UTF-8"); - PrintWriter out = new PrinterWriter("out.txt")) { - while (in.hasNext()) { - System.out.println(in.next().toUpperCase()); - } -} -``` - -Java SE7 引入了带资源的 try 语句,当语句正常退出或者有异常,都会调用`in.close()`方法。如果`in.close()`方法也抛出异常,则原来的异常会重新抛出,而close方法抛出的异常会被抑制,通过调用 getSuppressed 方法可以得到从close 方法抛出并被抑制的异常列表。 - -### 断言 - -```java -int x = -1; -if(x < 0) { - throw new IllegalArgumentException("x < 0"); -} -double y = Math.sqrt(x); -``` - -这段检查代码会一直保留在程序,如果程序中含有大量这样的检查,程序运行起来将会很慢。 - -断言允许在测试期间向代码插入一些检查语句。当代码发布时,这些检查语句将会被自动的移走。 - -Java 语言引入了关键字 assert,assert 有两种形式: - -```java -assert condition; -assert condition: expression;//expression用于产生消息字符串 -``` - -这两种形式都会对条件进行检测,如果结果是 false,则会抛出 AssertError 异常。第二种形式中,表达式将会被传入 AssertError 的构造器,并转化成一个消息字符串。 - -断言 x 是一个非负数值: - -```java -assert x >= 0; -assert x >= 0 : x;//将x的值传递给AssertError异常 -``` - -断言只应该用在测试阶段确定程序内部的错误位置。 - -#### 启用和禁用断言 - -默认情况下,断言被禁用,可以在运行程序时用`-eableassertions`或`-ea`选项启用。idea --> run configuration --> vm options 添加 `-ea` 开启断言。 - -`java -enableassertions MyApp` - -启用和禁用断言是类加载器的功能,在启用和禁用断言时不必重新编译程序。当断言被禁用时,类加载器将跳过断言代码,因此不会降低程序的运行速度。 - -在某个类和包使用断言:`java -ea:MyClass -ea:com.tyson.chapter12 MyApp` MyClass 类和 com.tyson.chapter12 包以及子包的所有类都会启用断言。 - -使用选项`-dableassertions`或`-da`禁用某个类和包的断言。 - -### 日志 - -#### logback - -``的三个属性 - -- scan:默认值为true,配置文件发生更改时会重新加载。 -- scanPeriod:设置监控配置文件的时间间隔,默认单位是毫秒。 -- debug:默认值是false,打印logback内部日志信息,实时查看logback运行状态。 - -``的子标签 -root是根``,只有level属性,默认为DEBUG。 -logger关联包或者具体的类到appender,可以定义日志类型、级别。 -Appender主要用于指定日志输出的目的地,如控制台、文件、数据库。 - -``` - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - -``` -日志级别:ERROR>WARN>INFO>DEBUG>TRACE - -Layout用于自定义日志输出格式。 -``` - - - -``` - - - -## 字符串 - -String 对象是不可变的。String 类中会修改 String 的方法都会创建一个全新的 String 对象。 - -### 格式化输出 - -#### printf() 和 format() - -```java -public class SimpleFormat { - public static void main(String[] args) { - int x = 5; - double y = 5.26; - System.out.format("Row 1: [%d %f]\n", x, y); - System.out.printf("Row 1: [%d %f]\n", x, y); - } -} -/*output -Row 1: [5 5.260000] -Row 1: [5 5.260000] - */ -``` - -#### Formatter - -```java -public class FormatterDemo { - public static void main(String[] args) { - Formatter f = new Formatter(System.out); - String item = "peas"; - int quatity = 3; - float price = 5.2f; - //-表示右对齐 - f.format("%-10s %5s %10s\n", "item", "quatity", "price"); - //-表示右对齐,%10.10s指宽度为10,最大输出字符为10 - f.format("%-10.10s %5d %10.2f\n", item, quatity, price); - //String.format() - System.out.println("------string.format()------"); - System.out.println(String.format("%-10.10s %5d %10.2f", item, quatity, price)); - } -} -/* -item quatity price -peas 3 5.20 -------string.format()------ -peas 3 5.20 - */ -``` - -String.format()接受与Formatter.format()一样的参数,它是通过创建一个 Formatter 对象实现的。 - -### 正则表达式 - -#### 基础 - -可能有一个负号在最前面:`-?` - -`\\`在 Java 表示插入一个正则表达式的反斜线 - -表示一个数字:`\\d` - -插入普通的反斜线:`\\\\` - -`+`表示一个或多个之前的表达式 - -可能有一个负号,后面跟着一个或多个数字:`-?\\d+` - -```java -public class IntegerMatch { - public static void main(String[] args) { - System.out.println("-89".matches("-?\\d+")); - System.out.println("+98".matches("-?\\d+")); - //竖直线|代表或操作;+是特殊符号,需转义;括号可以将表达式分组 - System.out.println("+789".matches("(-|\\+)?\\d+")); - } -} -/*output -true -false -true - */ -``` - -String 自带一个正则表达式工具 split()方法,它可以将字符串从正则表达式匹配的地方切开。特殊字符如`.`和`|`需要用反斜杠转义,即`\\.`和`\\|`。 - -```java -public class Splitting { - public static String motto = "All in all, we all have a dream."; - public static void split(String regex) { - System.out.println(Arrays.toString(motto.split(regex))); - } - public static void main(String[] args) { - //.需要转义 - split("\\."); - split(" "); - //\\w+表示一个或多个非单词字符 - split("\\W+"); - //表示字母n后面跟着一个或多个非单词字符 - split("n\\W+"); - } -} -/*output -[All in all, we all have a dream, Thanks] -[All, in, all,, we, all, have, a, dream., Thanks.] -[All, in, all, we, all, have, a, dream, Thanks] -[All i, all, we all have a dream. Thanks.] - */ -``` - -替换功能。 - -```java -public class Replacing { - public static void main(String[] args) { - //小写的w表示字母 - System.out.println(Splitting.motto.replaceFirst("w\\w+", "they")); - System.out.println(Splitting.motto.replaceAll("all|dream", "apple")); - } -} -/*output -All in all, they all have a dream. -All in apple, we apple have a apple. - */ -``` - -#### 创建正则表达式 - -字符类表达式,JDK 文档中 java.util.regex.Pattern 页面有完整的表达式。 - -[jdk8文档](https://docs.oracle.com/javase/8/docs/api/index.html) - -[菜鸟教程正则表达式语法](http://www.runoob.com/java/java-regular-expressions.html) - -**常用的字符类表达式** - -| 字符 | 描述 | -| -------- | ------------------------------------------------------------ | -| . | 匹配除"\r\n"之外的任何单个字符 | -| + | 表示一个或多个之前的表达式,如\\\d+表示一个或多个数字 | -| * | 零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,} | -| ? | 零次或一次匹配前面的字符或子表达式。如"do(es)?"匹配"do"或"does"中的"do"。? 等效于 {0,1} | -| [abc] | 包含a/b/c的任何字符(和a\|b\|c作用相同) | -| [^abc] | 除了a/b/c外的任何字符 | -| [a-zA-z] | a-z/A-Z的任何字符 | -| \s | 空白符(空格、tab、换行、换页和回车) | -| \S | 非空白符(\[^\s]) | -| \d | 数字0-9 | -| \D | 非数字(\[^0-9]) | -| \w | 字符[a-zA-Z0-9] | -| \W | 非字符 | - -**边界匹配符** - -| 符号 | 描述 | -| ---- | ---------- | -| ^ | 一行的起始 | -| $ | 一行的结束 | -| \b | 词的边界 | -| \B | 非词的边界 | - -**量词** - -![正则表达式量词](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190409100645126-737003966.png) - -Rudolph.java - -```java -public class Rudolph { - public static void main(String[] args) { - for(String pattern : new String[]{ "Rudolph", - "[rR]udolph", "[rR][aeiou][a-z]ol.*", "R.*" }) - System.out.println("Rudolph".matches(pattern)); - } -} /* Output: -true -true -true -true -*///:~ -``` - -#### Pattern 和 Matcher - -Pattern 和 Matcher 功能较 String 更为强大。Pattern.compile(String regex) 用来编译正则表达式,生成一个。 - -**find()** - -`Matcher.find()`可用来在 CharSequence 中查找多个匹配。find()可以像迭代器一样前向遍历输入的字符串。重载的 find(int index)能够接收一个整数参数,作为搜索起点。 - -```java -public class Finding { - //划分为单词 - public static Pattern WORD_PATTERN = Pattern.compile("\\w+"); - public static void main(String[] args) { - Matcher m = WORD_PATTERN.matcher("Everyone is born equally"); - //find()可用来查找多个匹配 - while(m.find()) { - System.out.print(m.group() + " "); - } - System.out.println(); - int i = 0; - //指定搜索起点 - while(m.find(i++)) { - System.out.print(m.group() + " "); - } - } -} -/*output -Everyone is born equally -Everyone veryone eryone ryone yone one ne e is is s born born orn rn n equally equally qually ually ally lly ly y - */ -``` - -**组** - -组使用括号划分的正则表达式,如`A(B(C))D`,组0是ABCD,组1是BC,组2是C。Matcher 对象提供了一系列方法,用以获取与组相关的信息: - -`public int groupCount()`返回该匹配器的分组数目(**不包含第0组**),如上面例子分组数目为2组(不包含第0组); - -`public String group()`返回前一次匹配操作(如find())的第0组(整个匹配); - -`public String group(int i)`返回前一次匹配操作指定的组号,如果没有匹配到输入字符串的任何部分,将会返回null。 - -```java -public class Groups { - public static final String POEM = - "Twas brillig, and the slithy toves\n" + - "Did gyre and gimble in the wabe.\n" + - "All mimsy were the borogoves,\n" + - "And the mome raths outgrabe.\n\n" + - "Beware the Jabberwock, my son,\n" + - "The jaws that bite, the claws that catch.\n" + - "Beware the Jubjub bird, and shun\n" + - "The frumious Bandersnatch.\n" + - "end\n"; //匹配失败 - //捕获每行最后的三个词 - public static Pattern LAST_THREE_WORD_PATTERN = Pattern.compile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$"); - - public static void main(String[] args) { - Matcher m = LAST_THREE_WORD_PATTERN.matcher(POEM); - while(m.find()) { - //有4个分组,不包括分组0,分组0是整个匹配 - for(int i = 0; i <= m.groupCount(); i++) { - System.out.print("[" + m.group(i) + "]"); - } - System.out.println(); - } - } -} -/* Output: -[the slithy toves][the][slithy toves][slithy][toves] -[in the wabe.][in][the wabe.][the][wabe.] -[were the borogoves,][were][the borogoves,][the][borogoves,] -[mome raths outgrabe.][mome][raths outgrabe.][raths][outgrabe.] -[Jabberwock, my son,][Jabberwock,][my son,][my][son,] -[claws that catch.][claws][that catch.][that][catch.] -[bird, and shun][bird,][and shun][and][shun] -[The frumious Bandersnatch.][The][frumious Bandersnatch.][frumious][Bandersnatch.] -*/ -``` - -默认情况下,^和$仅匹配输入的完整字符串的开始和结束。?m表示多行模式下,^和$分别匹配一行的开始和结束。 - -**start() 与 end()** - -在匹配操作成功之后,start()返回匹配的起始位置的索引,end()返回所匹配字符的最后字符的索引加一的值。 - -**Pattern 标记** - -Pattern 类的 compile()方法还有一个版本,可以接收一个标记参数,以调整匹配的行为: - -`Pattern Pattern.compile(String regex, int flag)` - -flag 来自以下 Pattern 类中的常量: - -![Pattern 标记参数](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190409103507798-1192565494.png) - -可以通过'|'(或)操作符组合多个标记的功能: - -```java -public class ReFlags { - public static Pattern WORD_PATTERN = Pattern.compile("^java", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public static void main(String[] args) { - Matcher m = WORD_PATTERN.matcher("java has regex\nJava has regex\n" + - "JAVA has pretty good regular expressions\n" + - "Regular expressions are in Java"); - while(m.find()) { - System.out.println(m.group()); - } - } -} -/* Output: -java -Java -JAVA -*/ -``` - -**split()** - -```java -public class SplitDemo { - public static void main(String[] args) { - String input = "This!!unusual use!!of exclamation!!points"; - print(Arrays.toString(Pattern.compile("!!").split(input))); - // 限制分割字符串的数量 - print(Arrays.toString(Pattern.compile("!!").split(input, 3))); - } -} /* Output: -[This, unusual use, of exclamation, points] -[This, unusual use, of exclamation!!points] -*/ -``` - -**替换操作** - -```java -public class TheReplacements { - public static void main(String[] args) throws Exception { - String s = TextFile.read("src/com/tyson/chapter13/string/regex/TheReplacements.java"); - // 匹配上面的注释 - Matcher mInput = Pattern.compile("/\\*!(.*)!\\*/", Pattern.DOTALL).matcher(s); - if (mInput.find()) { - s = mInput.group(1); // 捕捉正则表达式括号,组是括号划分的正则表达式 - } - - // Replace two or more spaces with a single space: - s = s.replaceAll(" {2,}", " "); - // Replace one or more spaces at the beginning of each - // line with no spaces. Must enable MULTILINE mode: - s = s.replaceAll("(?m)^ +", ""); - print(s); - s = s.replaceFirst("[aeiou]", "(VOWEL1)"); - StringBuffer sbuf = new StringBuffer(); - Pattern p = Pattern.compile("[aeiou]"); - Matcher m = p.matcher(s); - // Process the find information as you - // perform the replacements: - while (m.find()) - //将找到的元音字母转化为大写字母 - m.appendReplacement(sbuf, m.group().toUpperCase()); - // Put in the remainder of the text: - m.appendTail(sbuf); - print(sbuf); - } -} /* Output: -Here's a block of text to use as input to -the regular expression matcher. Note that we'll -first extract the block of text by looking for -the special delimiters, then process the -extracted block. -H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO -thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll -fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr -thE spEcIAl dElImItErs, thEn prOcEss thE -ExtrActEd blOck. -*/ -``` - -**reset()** - -通过 reset() 方法,可以将 Matcher 对象应用于一个新的字符序列。 - -```java -public class Resetting { - public static void main(String[] args) throws Exception { - Matcher m = Pattern.compile("[frb][aiu][gx]").matcher("fix the rug with bags"); - while (m.find()) - System.out.print(m.group() + " "); - System.out.println(); - m.reset("fix the rig with rags"); - while (m.find()) - System.out.print(m.group() + " "); - } -} /* Output: -fix rug bag -fix rig rag -*/ -``` - -### 扫描输入 - -Java SE5新增了 Scanner 类,Scanner 的构造器可以接受任何类型的输入对象,包括 File 对象、InputStream、String 或者 Readable 对象。Scanner 所有的输入、分词以及翻译都隐藏在不用类型的 next 方法中。普通的 next()方法返回下一个 String 。 - -#### Scanner 定界符 - -默认情况下,Scanner 根据空白字符对输入进行分词,我们可以用正则表达式指定自己所需的定界符。 - -```java -public class ScannerDelimiter { - public static void main(String[] args) { - Scanner sc = new Scanner("12, 42, 85, 23"); - //使用逗号包括逗号前后的空白字符作为定界符 - sc.useDelimiter("\\s*,\\s*"); - while(sc.hasNextInt()) { - System.out.println(sc.nextInt()); - } - } -} -``` - -#### 用正则表达式扫描 - -```java -public class ThreatAnalyzer { - static String threatData = - "58.27.82.161@02/10/2005\n" + - "204.45.234.40@02/11/2005\n" + - "58.27.82.161@02/11/2005\n" + - "58.27.82.161@02/12/2005\n" + - "58.27.82.161@02/12/2005\n" + - "[Next log section with different data format]"; - - public static void main(String[] args) { - Scanner sc = new Scanner(threatData); - String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@(\\d{2}/\\d{2}/\\d{4})"; - while(sc.hasNext(pattern)) { - sc.next(pattern); - MatchResult match = sc.match(); - String ip = match.group(1); - String date = match.group(2); - System.out.format("Thread on %s from %s\n", ip, date); - } - } -} -/*output -Thread on 58.27.82.161 from 02/10/2005 -Thread on 204.45.234.40 from 02/11/2005 -Thread on 58.27.82.161 from 02/11/2005 -Thread on 58.27.82.161 from 02/12/2005 -Thread on 58.27.82.161 from 02/12/2005 - */ -``` - -注意:配合正则表达式进行扫描时,正则表达式不要含有定界符(Scanner 默认定界符是空白符,根据空白符对输入进行分词)。 - - - -## 类型信息 - -通过运行时类型信息可以在程序运行时发现和使用类型信息。 - -`Class.forName("Gum")`类 Gum 没有被加载就加载它。 - -### 反射 - -类方法提取: - -```java -public class typeinfo { - //匹配类似包名的字符串 com.tyson.chapter - public static Pattern p = Pattern.compile("\\w+\\."); - public static void main(String[] args) { - try { - Class c = Class.forName("com.tyson.chapter10.innerclass.LocalInnerClass"); - Method[] methods = c.getMethods(); - for(Method m : methods) { - //去掉包名 - System.out.println(p.matcher(m.toString()).replaceAll("")); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } -} -/*output -public static void main(String[]) -public final void wait() throws InterruptedException -public final void wait(long,int) throws InterruptedException -public final native void wait(long) throws InterruptedException -public boolean equals(Object) -public String toString() -public native int hashCode() -public final native Class getClass() -public final native void notify() -public final native void notifyAll() - */ -``` - - - -## 泛型 - -泛型实现了参数化类型的概念,使代码可以应用于多种类型。使用泛型编写的程序比使用 Object 变量再进行强制类型转化的程序具有更好的安全性和可读性。 - -### 类型参数的好处 - -Java SE5泛型出现之前,ArrayList 是通过维护一个 Object 数组实现的。 - -```java -public class MyArrayList { - private Object[] elementData; - private int index = 0; - public MyArrayList() { elementData = new Object[8]; } - public Object get(int i) { return elementData[i]; } - public void add(Object o) { elementData[index++] = o; } - - public static void main(String[] args) { - MyArrayList list = new MyArrayList(); - list.add("tyson"); - System.out.println((String)list.get(0)); - list.add(new Cat()); - System.out.println((String)list.get(1)); - } -} -/*output -tyson -Exception in thread "main" java.lang.ClassCastException: typeinfo.pets.Cat cannot be cast to java.lang.String - at com.tyson.chapter15.generics.MyArrayList.main(MyArrayList.java:29) - */ -``` - -当获取值的时候需要进行强制类型转化,并且 add 操作可以放进任何类型的对象,编译和运行都不报错,当获取值进行强制类型转换时,可能会抛异常。 - -### 泛型类 - -```java -public class Holder { - private T a; - public Holder(T a) { this.a = a; } - public void set(T a) { this.a = a; } - public T get() { return a; } - - public static void main(String[] args) { - Holder h = new Holder<>("Tyson"); - System.out.println(h.get()); - } -} -//output Tyson -``` - -### 泛型接口 - -泛型也可以用于接口。 - -```java -//public interface Generator { T next(); } - -public class Fibonacci implements Generator { - private int count = 0; - @Override - public Integer next() { - return fib(count++); - } - public int fib(int n) { - if(n < 2) { return 1; } - return fib(n - 2) + fib(n - 1); - } - - public static void main(String[] args) { - Fibonacci fib = new Fibonacci(); - for(int i = 0; i < 10; i++) { - System.out.print(fib.next() + " "); - } - } -} -//output:1 1 2 3 5 8 13 21 34 55 -``` - -### 泛型方法 - -如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法。对于一个 static 方法而言,无法访问泛型类的类型参数,所以如果 static 方法需要使用泛化能力,就必须使其成为泛型方法。 - -定义泛型方法,只需将泛型参数列表放在返回值之前。 - -```java -public class GenericMethod { - public void f(T t) { System.out.println(t.getClass().getName()); } - - public static void main(String[] args) { - GenericMethod gm = new GenericMethod(); - //可省略,编译器自己可推断出 - gm.f(""); - gm.f(1); - gm.f(1.0); - gm.f(1.0f); - gm.f(gm); - } -} -/*output -java.lang.String -java.lang.Integer -java.lang.Double -java.lang.Float -com.tyson.chapter15.generics.GenericMethod - */ -``` - -GenericMethod 并不是参数化的,只有 f() 拥有参数类型。 - -#### 可变参数和泛型方法 - -向参数个数可变的方法传递一个泛型类型的实例。 - -```java -public class GenericVarArgs { - public static List makeList(T... args) { - List result = new ArrayList<>(); - for(T item : args) { - result.add(item); - } - return result; - } - - public static void main(String[] args) { - List l = makeList("a", "b"); - System.out.println(l); - } -} -//output:[a, b] -``` - -### 匿名内部类 - -```java -public class Customer { - public Customer() {} - public static Generator generator() { - return new Generator() { - @Override - public Customer next() { - return new Customer(); - } - }; - } - - public static void main(String[] args) { - System.out.println(Customer.generator().next()); - } -} -``` - -### 泛型擦除 - -```java -public class ErasedTypeEquvalence { - public static void main(String[] args) { - Class c1 = new ArrayList().getClass(); - Class c2 = new ArrayList().getClass(); - System.out.println(c1 == c2); - } -} -//output:true -``` - -`List`的类型变量没有显式的限定,擦除类型后变成原始的 List,故`List`和`List`是相同的类型。 - -```java -class Manipulator { - private T obj; - public Manipulator(T t) { obj = t; } - public void manipulate() { obj.f(); } -} -``` - -Manipulator 类有显式限定 HasF,故擦除类型后变成: - -```java -class Manipulato { - private HasF obj; - public Manipulator(HasF t) { obj = HasF; } - public void manipulate() { obj.f(); } -} -``` - -### 类型变量的限定 - -给定泛型类的边界,以此告知编译器只能接受遵循这个边界的类型。 - -```java -//HasF.java -public class HasF { - public void f() { - System.out.println("Has.f()"); - } -} - -//Manipulation.java -class Manipulator { - private T obj; - public Manipulator(T t) { obj = t; } - public void manipulate() { obj.f(); } -} - -public class Manipulation { - public static void main(String[] args) { - HasF hf = new HasF(); - Manipulator manipulator = new Manipulator<>(hf); - manipulator.manipulate(); - } -} -//output: Has.f() -``` - -### 擦除的问题 - -```java -class GenericBase { - private T element; - public void set(T arg) { element = arg; } - public T get() { return element; } - - public static void main(String[] args) { - - } -} - -class Derived extends GenericBase {} - -public class ErasureAndInheritance { - public static void main(String[] args) { - Derived d = new Derived(); - d.set(new Object()); - System.out.println(d.get()); - } -} -//output: java.lang.Object@6d6f6e28 -``` - -Derived 继承自 GenericBase,但是没有任何泛型参数,而编译器不会发出任何警告。 - -### 边界 - -在泛型的参数类型上设置限制条件,可以强制规定泛型可以应用的类型,从而可以按照自己的边界类型去调用方法。如果将泛型参数限制为某个类型子集,那么就可以用这些类型子集来调用方法。 - -```java -interface HasColor { Color getColor(); } - -class Colored { - T item; - Colored(T item) { this.item = item; } - T getItem() { return item; } - Color color() { return item.getColor(); } -} - -class Dimension { public int x; } - -//编译错误,应该类在前,接口在后 -//class ColoredDimension {} - -class ColoredDimension { - T item; - ColoredDimension(T item) { this.item = item; } - T getItem() { return item; } - Color color() { return item.getColor(); } - int getX() { return item.x; } -} - -interface Weight { int weight(); } - -//边界继承只能有一个类,可以有多个接口 -class Solid { - T item; - Solid(T item) { this.item = item; } - T getItem() { return item; } - Color color() { return item.getColor(); } - int getX() { return item.x; } - int weight() { return item.weight(); } -} - -class Bounded extends Dimension implements HasColor, Weight { - - @Override - public Color getColor() { return null; } - - @Override - public int weight() { return 0; } -} - -public class BasicBounds { - public static void main(String[] args) { - Solid solid = new Solid<>(new Bounded()); - solid.color(); - solid.getX(); - solid.weight(); - } -} -``` - -通过在继承的每个层次上添加边界限制,消除 BasicBounds.java 代码冗余。 - -```java -class HoldItem { - T item; - HoldItem(T item) { this.item = item; } - T getItem() { return item; } -} - -class Colored2 extends HoldItem { - Colored2(T item) { super(item); } - Color color() { return item.getColor(); } -} - -class ColorDimension2 extends Colored2 { - ColorDimension2(T item) { super(item); } - int getX() { return item.x; } -} - -class Solid2 extends ColorDimension2 { - Solid2(T item) { super(item); } - int weight() { return item.weight(); } -} - -public class InheritBounds { - public static void main(String[] args) { - Solid2 solid2 = new Solid2<>(new Bounded()); - solid2.color(); - solid2.getX(); - solid2.weight(); - } -} -``` - -### 通配符 - -参考自:[泛型超详细解读](https://blog.csdn.net/jeffleo/article/details/52250948) | [通配符的上界通配符和下界通配符](https://blog.csdn.net/hello_worldee/article/details/77934244) - -#### 上界通配符 - -上界< ? extends Class> - -```java -class Fruit { } -class Apple extends Fruit { } -class Orange extends Fruit { } - -public class UpperBound { - public static void main(String[] args) { - List list = new ArrayList<>(); - //编译错误 - //list.add(new Apple()); - //list.add(new Orange()); - //list.add(new Fruit()); - list.add(null); - - list.contains(new Apple()); - list.indexOf(new Apple()); - - System.out.println(list.get(0)); - } -} -``` - -可见,指定了下边界,却不能add任何类型,甚至Object都不行,除了null,因为null代表任何类型。List< ? extends Fruit>可以解读为,“具有任何从Fruit继承的类型”,但实际上,它意味着,它没有指定具体类型。对于编译器来说,当你指定了一个List< ? extends Fruit>,add的参数也变成了“? extends Fruit”。因此编译器并不能了解这里到底需要哪种Fruit的子类型,因此他不会接受任何类型的Fruit。 - -然而,contain和indexof却能执行,这是因为,这两个方法的参数是Object,不涉及任何的通配符,所以编译器允许它调用。 - -list.get(0)能够执行是因为,当item在此list存在时,编译器能够确定他是Apple的子类,所以能够安全获得。 - -#### 下界通配符 - -< ? super Class>表示,指定类的基类。 - -```java -class Apple1 extends Apple {} - -public class LowerBound{ - - public static void main(String[] args) { - List list = new ArrayList<>(); - list.add(new Apple()); - list.add(new Apple1()); - //编译错误 - //list.add(new Fruit()); - - Object apple = list.get(0); - System.out.println(apple); - } -} -//output: com.tyson.chapter15.generics.Apple@6d6f6e28 -``` - -对于super,get返回的是Object,因为编译器不能确定列表中的是Apple的哪个子类,所以只能返回Object。 - -List < ? super Apple>, 代表容器内存放的是Apple的所有父类,所以有多态和上转型,这个容器时可以接受所有Apple父类的子类的(多态的定义:父类可以接受子类型对象)。Apple和Apple1都直接或间接继承了Fruit,所以Apple和Apple1是能够加入List < ? super Apple>这个容器的。 - -list.add(new Fruit())不能添加,是因为容器内存放的是Apple的**所有**父类,正是因为能存放所有,Apple的父类可能有Fruit1, Fruit2, Fruit3 , 所以编译器根本不能识别你要存放哪个Apple的父类,所以不能添加Fruit,因为这不能保证类型安全的原则。这从最后的Object apple = list.get(0)可以看出。 - - - -## 数组 - -数组的 length 是数组的大小,不是实际保存的元素个数。 - -如果不显式初始化,基本类型数组会被自动初始化成初值,对象数组则会被初始化成 null。 - -### 复制数组 - -Java 标准类库提供有 static 方法 System.arraycopy(),用来复制数组比用 for 循环复制要快的多。System.arraycopy() 针对所有类型做了重载。 - -```java -public class CopyArrays { - public static void main(String[] args) { - int[] src = new int[7]; - int[] dest = new int[10]; - Arrays.fill(src, 47); - Arrays.fill(dest, 99); - System.out.println("src = " + Arrays.toString(src)); - System.out.println("dest = " + Arrays.toString(dest)); - System.arraycopy(src, 0, dest, 0, src.length); - System.out.println("dest = " + Arrays.toString(dest)); - } -} -/*output -src = [47, 47, 47, 47, 47, 47, 47] -dest = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99] -dest = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99] - */ -``` - -基本类型数组和对象数组都可以复制。复制对象只是复制对象引用,即浅复制。System.arraycopy() 不会执行自动包装和自动拆包,两个数组需要具有相同的数据类型。 - -### Arrays 工具 - -#### 数组拷贝 - -```java -public class ArrayCopy { - //Arrays 类方法的使用 - public static void main(String[] args) { - int[] arr = {12, 45, 2, 56, 20}; - int[] arrCopy = Arrays.copyOf(arr, arr.length); - System.out.println("arr: " + Arrays.toString(arr)); - System.out.println("arrCopy: " + Arrays.toString(arrCopy)); - //增加数组大小 - arrCopy = Arrays.copyOf(arr, 2 * arr.length); - System.out.println("arr: " + Arrays.toString(arr)); - System.out.println("arrCopy: " + Arrays.toString(arrCopy)); - } -} -/*output -arr: [12, 45, 2, 56, 20] -arrCopy: [12, 45, 2, 56, 20] -arr: [12, 45, 2, 56, 20] -arrCopy: [12, 45, 2, 56, 20, 0, 0, 0, 0, 0] - */ -``` - -`Array.copyOf()`底层是通过`System.arraycopy()`使用的。 - -```java -public static T[] copyOf(U[] original, int newLength, Class newType) { - @SuppressWarnings("unchecked") - T[] copy = ((Object)newType == (Object)Object[].class) - ? (T[]) new Object[newLength] - : (T[]) Array.newInstance(newType.getComponentType(), newLength); - System.arraycopy(original, 0, copy, 0, - Math.min(original.length, newLength)); - return copy; -} -``` - -#### 数组的比较 - -Arrays 类提供了重载后的 equals() 方法,用来比较整个数组。 - -```java -public class ComparingArrays { - public static void main(String[] args) { - int[] a1 = new int[10]; - int[] a2 = new int[10]; - Arrays.fill(a1, 47); - Arrays.fill(a2, 47); - System.out.println(Arrays.equals(a1, a2)); - a2[1] = 0; - System.out.println(Arrays.equals(a1, a2)); - String[] s1 = new String[2]; - Arrays.fill(s1, "hello"); - String[] s2 = { new String("hello"), new String("hello")}; - System.out.println(Arrays.equals(s1, s2)); - } -} -/*output -true -false -true - */ -``` - -#### 数组元素的比较 - -1. 实现`java.lang.Comparable`接口,使得类本身具有比较比较能力。 - - ```java - public class CompType implements Comparable { - int i; - int j; - public CompType(int i, int j) { - this.i = i; - this.j = j; - } - - @Override - public String toString() { - return "CompType{" + - "i=" + i + - ", j=" + j + - '}'; - } - - @Override - public int compareTo(CompType ct) { - return i < ct.i ? -1 : (i == ct.i ? 0 : 1); - } - - private static Random r = new Random(47); - public static Generator generator() { - return new Generator() { - @Override - public CompType next() { - return new CompType(r.nextInt(100), r.nextInt(100)); - } - }; - } - - public static void main(String[] args) { - CompType[] arr = Generated.array(new CompType[4], generator()); - System.out.println("before sorting: " + Arrays.toString(arr)); - Arrays.sort(arr); - System.out.println("after sorting: " + Arrays.toString(arr)); - //反转自然排列顺序 - Arrays.sort(arr, Collections.reverseOrder()); - System.out.println("reverse order: " + Arrays.toString(arr)); - } - } - /*output - before sorting: [CompType{i=58, j=55}, CompType{i=93, j=61}, CompType{i=61, j=29}, CompType{i=68, j=0}] - after sorting: [CompType{i=58, j=55}, CompType{i=61, j=29}, CompType{i=68, j=0}, CompType{i=93, j=61}] - reverse order: [CompType{i=93, j=61}, CompType{i=68, j=0}, CompType{i=61, j=29}, CompType{i=58, j=55}] - */ - ``` - -2. 编写自己的比较器Comparator。 - - ```java - class CompTypeComparator implements Comparator { - - @Override - public int compare(CompType o1, CompType o2) { - return o1.j > o2.j ? 1 : (o1.j == o2.j ? 0 : -1); - } - } - - public class ComparatorTest { - public static void main(String[] args) { - CompType[] arr = Generated.array(new CompType[4], CompType.generator()); - System.out.println("before sorting: " + Arrays.toString(arr)); - Arrays.sort(arr, new CompTypeComparator()); - System.out.println("after sorting: " + Arrays.toString(arr)); - } - } - /*output - before sorting: [CompType{i=58, j=55}, CompType{i=93, j=61}, CompType{i=61, j=29}, CompType{i=68, j=0}] - after sorting: [CompType{i=68, j=0}, CompType{i=61, j=29}, CompType{i=58, j=55}, CompType{i=93, j=61}] - */ - ``` - -#### 数组排序 - -使用内置的排序方法,就可以对基本类型数组进行排序。也可以对对象数组进行排序,只要该对象实现了 Comparable 接口或者具有相关联的 Comparator。 - -```java -public class StringSorting { - public static void main(String[] args) { - String[] strs = Generated.array(new String[5], new RandomGenerator.String(5)); - System.out.println("before sorting: " + Arrays.toString(strs)); - Arrays.sort(strs); - System.out.println("after sorting: " + Arrays.toString(strs)); - Arrays.sort(strs, Collections.reverseOrder()); - System.out.println("reverse order: " + Arrays.toString(strs)); - Arrays.sort(strs, String.CASE_INSENSITIVE_ORDER); - System.out.println("case insensive: " + Arrays.toString(strs)); - } -} -/*output -before sorting: [YNzbr, nyGcF, OWZnT, cQrGs, eGZMm] -after sorting: [OWZnT, YNzbr, cQrGs, eGZMm, nyGcF] -reverse order: [nyGcF, eGZMm, cQrGs, YNzbr, OWZnT] -case insensive: [cQrGs, eGZMm, nyGcF, OWZnT, YNzbr] - */ -``` - -String 排序算法依据词典编排顺序排序。大写字母在前,小写字母在后。Java 标准类库中的排序算法针对正排序做了优化。针对基础类型设计了快速排序,针对对象设计了稳定归并排序。 - -#### 排序数组查找 - -若数组已经排序,既可以使用`Arrays.binarySearch()`执行快速查找。 - -```java -public class ArraySearching { - public static void main(String[] args) { - Generator gen = new RandomGenerator.Integer(1000); - int[] arr = ConvertTo.primitive(Generated.array(new Integer[5], gen)); - Arrays.sort(arr); - System.out.println("after sorting: " + Arrays.toString(arr)); - while(true) { - int r = gen.next(); - int location = Arrays.binarySearch(arr, r); - if(location >= 0) { - System.out.println("location: " + location + "-->" + arr[location]); - break; - } - } - } -} -/*output -after sorting: [258, 555, 693, 861, 961] -location: 3-->861 - */ -``` - -找到目标,`Arrays.binarySearch()`返回值大于或等于0。否则返回负值:`-(插入点)- 1`; - -对象数组使用`Arrays.binarySearch()`需要提供Comparator。 - -```java -public class StringSearch { - public static void main(String[] args) { - String[] strs = Generated.array(new String[6], new RandomGenerator.String(5)); - Arrays.sort(strs, String.CASE_INSENSITIVE_ORDER); - System.out.println(Arrays.toString(strs)); - int index = Arrays.binarySearch(strs, strs[3], String.CASE_INSENSITIVE_ORDER); - System.out.println("index: " + index + "-->" + strs[index]); - } -} -/*output -[cQrGs, eGZMm, JMRoE, nyGcF, OWZnT, YNzbr] -index: 3-->nyGcF - */ -``` - - - -## 容器深入研究 - -### 填充容器 - -```java -public class FillingList { - public static void main(String[] args) { - List list = new ArrayList<>(Collections.nCopies(3, "Tyson")); - System.out.println(list); - Collections.fill(list, "Sophia"); - System.out.println(list); - } -} -/*output -[Tyson, Tyson, Tyson] -[Sophia, Sophia, Sophia] - */ -``` - -### SortedSet - -按对象的比较函数对元素进行排序。用 TreeSet 迭代通常比用 HashSet 要快。 - -```java -public class SortedSetDemo { - public static void main(String[] args) { - SortedSet sortedSet = new TreeSet<>(); - Collections.addAll(sortedSet, "one two three four".split(" ")); - System.out.println(sortedSet); - System.out.println("first: " + sortedSet.first()); - System.out.println("last: " + sortedSet.last()); - Iterator itr = sortedSet.iterator(); - while (itr.hasNext()) { - System.out.print(itr.next() + " "); - } - System.out.println(); - //from包含-to不包含 - System.out.println("subSet: " + sortedSet.subSet("one", "three")); - //小于three的元素 - System.out.println(sortedSet.headSet("three")); - //大于等于one的元素 - System.out.println(sortedSet.tailSet("one")); - } -} -/*output -[four, one, three, two] -first: four -last: two -four one three two -subSet: [one] -[four, one] -[one, three, two] - */ -``` - -### 队列 - -除了并发应用,Queue Java SE5中仅有两个实现 LinkedList 和 PriorityQueue,它们的差异在于排序行为不在性能。 - -#### 优先级队列 - -```java -public class ToDoList extends PriorityQueue { - static class ToDoItem implements Comparable { - private char primary; - private int secondary; - private String item; - - public ToDoItem(String item, char pri, int sec) { - this.item = item; - primary = pri; - secondary = sec; - } - @Override - public int compareTo(ToDoItem o) { - if(primary > o.primary) { - return 1; - } - if(primary == o.primary) { - if(secondary > o.secondary) { - return 1; - } else if (secondary == o.secondary) { - return 0; - } else { - return -1; - } - } - return -1; - } - @Override - public String toString() { - return "ToDoItem{" + - "primary=" + primary + - ", secondary=" + secondary + - ", item='" + item + '\'' + - '}'; - } - } - public void add(String item, char pri, int sec) { - super.add(new ToDoItem(item, pri, sec)); - } - - public static void main(String[] args) { - ToDoList toDoList = new ToDoList(); - toDoList.add("homework", 'b', 3); - toDoList.add("feed dog", 'a', 4); - toDoList.add("lunch", 'a', 1); - while (!toDoList.isEmpty()) { - System.out.println(toDoList.remove()); - } - } -} -/*output -ToDoItem{primary=a, secondary=1, item='lunch'} -ToDoItem{primary=a, secondary=4, item='feed dog'} -ToDoItem{primary=b, secondary=3, item='homework'} - */ -``` - -#### 双向队列 - -可以在队列任何一端添加或移除元素。Java 标准库中没有任何显式的用于双向队列的接口。 - -```java -public class Deque { - private LinkedList deque = new LinkedList<>(); - public void addFirst(T t) { deque.add(t); } - public void addLast(T t) { deque.add(t); } - public T getFirst() { return deque.getFirst(); } - public T getLast() { return deque.getLast(); } - public T removeFirst() { return deque.removeFirst(); } - public T removeLast() { return deque.removeLast(); } - public int size() { return deque.size(); } - @Override - public String toString() { return deque.toString(); } - - public static void main(String[] args) { - Deque deque = new Deque<>(); - for(int i = 20; i < 27; i++) { - deque.addFirst(i); - } - for(int j = 50; j < 55; j++) { - deque.addLast(j); - } - System.out.println(deque); - while(deque.size() != 0) { - System.out.print(deque.removeFirst() + " "); - } - } -} -/*output -[20, 21, 22, 23, 24, 25, 26, 50, 51, 52, 53, 54] -20 21 22 23 24 25 26 50 51 52 53 54 - */ -``` - -### LinkedHashMap - -可以在构造器中设定 LinkedHashMap,使之采用基于访问的最近最少使用(LRU)算法,没有访问过的元素会出现在队列的前面。可用于定期清理元素以节省空间。 - -```java -public class LinkedHashMapDemo { - public static void main(String[] args) { - LinkedHashMap linkedHashMap = new LinkedHashMap<>(new CountingMapData(5)); - System.out.println(linkedHashMap); - linkedHashMap = new LinkedHashMap<>(16, 0.75f, true); - linkedHashMap.putAll(new CountingMapData(5)); - for(int i = 0; i < 3; i++) { - linkedHashMap.get(i); - } - System.out.println(linkedHashMap); - linkedHashMap.get(3); - System.out.println(linkedHashMap); - } -} -/*output -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0} -{3=D0, 4=E0, 0=A0, 1=B0, 2=C0} -{4=E0, 0=A0, 1=B0, 2=C0, 3=D0} - */ -``` - -### Colletions 工具类 - -```java -public class Utilities { - static List list = Arrays.asList("one two three four".split(" ")); - - public static void main(String[] args) { - System.out.println(list); - System.out.println("list disjoint(four)?" + - Collections.disjoint(list, Collections.singletonList("four"))); //不相交 - System.out.println("max: " + Collections.max(list)); - System.out.println("min: " + Collections.min(list)); - System.out.println("max with comparator: " + Collections.max(list, String.CASE_INSENSITIVE_ORDER)); - List subList = Arrays.asList("one two".split(" ")); - System.out.println("indexOfSubList: " + Collections.indexOfSubList(list, subList)); - System.out.println("lastIndexOfSubList: " + Collections.lastIndexOfSubList(list, subList)); - Collections.replaceAll(list, "one", "emm"); - System.out.println("replace all: " + list); - Collections.reverse(list); - System.out.println("reverse: " + list); - Collections.rotate(list, 1); - System.out.println("rotate: " + list); - List source = Arrays.asList("int the matrix".split(" ")); - Collections.copy(list, source); - System.out.println("copy: " + list); - Collections.swap(list, 0, list.size() - 1); - System.out.println("swap: " + list); - Collections.shuffle(list, new Random((47))); - System.out.println("shuffle: " + list); //打乱 - Collections.fill(list, "frequency"); - System.out.println("fill: " + list); - System.out.println("frequency of 'frequency': " + Collections.frequency(list, "frequency")); - List nCopies = Collections.nCopies(3, "nCopies;"); - System.out.println("nCopies: " + nCopies); - System.out.println("list disjoint nCopies? " + Collections.disjoint(list, nCopies)); - Enumeration e = Collections.enumeration(nCopies); - Vector v = new Vector<>(); - while(e.hasMoreElements()) { - v.add(e.nextElement()); - } - ArrayList arrayList = Collections.list(v.elements()); - System.out.println("arrayList: " + arrayList); - } -} -/*output -[one, two, three, four] -list disjoint(four)?false -max: two -min: four -max with comparator: two -indexOfSubList: 0 -lastIndexOfSubList: 0 -replace all: [emm, two, three, four] -reverse: [four, three, two, emm] -rotate: [emm, four, three, two] -copy: [int, the, matrix, two] -swap: [two, the, matrix, int] -shuffle: [two, the, int, matrix] -fill: [frequency, frequency, frequency, frequency] -frequency of 'frequency': 4 -nCopies: [nCopies;, nCopies;, nCopies;] -list disjoint nCopies? true -arrayList: [nCopies;, nCopies;, nCopies;] - */ -``` - -#### 排序和查询 - -```java -public class ListSortSearch { - public static void main(String[] args) { - List list = - new ArrayList(Utilities.list); - list.addAll(Utilities.list); - print(list); - Collections.shuffle(list, new Random(47)); - print("Shuffled: " + list); - // Use a ListIterator to trim off the last elements: - ListIterator it = list.listIterator(4); - while (it.hasNext()) { - it.next(); - it.remove(); - } - print("Trimmed: " + list); - Collections.sort(list); - print("Sorted: " + list); - String key = list.get(3); - int index = Collections.binarySearch(list, key); - print("Location of " + key + " is " + index + - ", list.get(" + index + ") = " + list.get(index)); - Collections.sort(list, String.CASE_INSENSITIVE_ORDER); - print("Case-insensitive sorted: " + list); - key = list.get(3); - index = Collections.binarySearch(list, key, - String.CASE_INSENSITIVE_ORDER); - print("Location of " + key + " is " + index + - ", list.get(" + index + ") = " + list.get(index)); - } -} /* Output: -[one, Two, three, Four, five, six, one, one, Two, three, Four, five, six, one] -Shuffled: [Four, five, one, one, Two, six, six, three, three, five, Four, Two, one, one] -Trimmed: [Four, five, one, one, Two, six, six, three, three, five] -Sorted: [Four, Two, five, five, one, one, six, six, three, three] -Location of six is 7, list.get(7) = six -Case-insensitive sorted: [five, five, Four, one, one, six, six, three, three, Two] -Location of three is 7, list.get(7) = three -*/ -``` - -#### 只读容器 - -```java -public class ReadOnly { - static Collection data = - new ArrayList<>(Countries.names(6)); - - public static void main(String[] args) { - Collection c = Collections.unmodifiableCollection( - new ArrayList<>(data)); - print(c); // Reading is OK - //! c.add("one"); // Can't change it - - List a = Collections.unmodifiableList(new ArrayList<>(data)); - ListIterator lit = a.listIterator(); - print(lit.next()); // Reading is OK - //! lit.add("one"); // Can't change it - - Set s = Collections.unmodifiableSet(new HashSet<>(data)); - print(s); // Reading is OK - //! s.add("one"); // Can't change it - - // For a SortedSet: - Set ss = Collections.unmodifiableSortedSet(new TreeSet<>(data)); - - Map m = Collections.unmodifiableMap( - new HashMap<>(Countries.capitals(6))); - print(m); // Reading is OK - //! m.put("Ralph", "Howdy!"); - - // For a SortedMap: - Map sm = Collections.unmodifiableSortedMap( - new TreeMap<>(Countries.capitals(6))); - } -} -``` - -#### Collection 和 Map 的同步控制 - -```java -public class Synchronization { - public static void main(String[] args) { - Collection c = Collections.synchronizedCollection(new ArrayList<>()); - List list = Collections.synchronizedList(new ArrayList<>()); - Set set = Collections.synchronizedSet(new HashSet<>()); - Set ss = Collections.synchronizedSortedSet(new TreeSet<>()); - Map map = Collections.synchronizedMap(new HashMap<>()); - Map sm = Collections.synchronizedSortedMap(new TreeMap<>()); - } -} -``` - -#### 快速报错机制 - - fast-fail 是 Java 容器的一种保护机制。当多个线程对同一个集合进行操作时,就有可能会产生 fast-fail 事件。例如:当线程a正通过 iterator 遍历集合时,另一个线程b修改了集合的内容(modCount 不等于expectedModCount),那么线程a在遍历的时候会抛出 ConcurrentModificationException,产生 fast-fail 事件。 - -```java -public class FastFail { - public static void main(String[] args) { - Collection c = new ArrayList<>(); - Iterator itr = c.iterator(); - c.add("haha"); - try { - String s = itr.next(); - } catch (ConcurrentModificationException ex) { - ex.printStackTrace(); - } - } -} -``` - -在此例中,应该添加完所有元素后,再获取迭代器。 - -**多线程并发修改容器的方法:** - -- 使用`Colletions.synchronizedList()`方法或在修改集合内容的地方加上 synchronized。这样的话,增删集合内容的同步锁会阻塞遍历操作,影响性能。 -- 使用 CopyOnWriteArrayList 来替换 ArrayList。在对 CopyOnWriteArrayList 进行修改操作的时候,会拷贝一个新的集合,对新的集合进行操作,操作完成后再把引用指向新的集合。 - -### Java 1.0/1.1 的容器 - -#### BitSet - -参考自:[JAVA中BitSet使用](https://blog.csdn.net/xv1356027897/article/details/79518647) - -位图,数据的存在性可以使用bit位上的1或0来表示,一个long型数字占用64位空间,那么一个long型数字就可以保存64个数字的“存在性”状态(true or false)。BitSet内部是一个long[]数组,数组的大小由 BitSet 接收的最大数字决定,这个数组将数字分段表示[0,63],[64,127],[128,191]...。即long[0]用来存储[0,63]这个范围的数字的“存在性”,long[1]用来存储[64,127],依次递推。 - -```java -public class BitSetDemo { - public static void printBitSet(BitSet b) { - System.out.println("BitSet: " + b); - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < b.size(); i++) { - sb.append(b.get(i) ? "1" : "0"); - } - System.out.println("bitset pattern: " + sb); - } - public static void main(String[] args) { - Random rand = new Random(47); - int num = rand.nextInt(20); - BitSet bs = new BitSet(); - bs.set(num); - System.out.println(bs); - System.out.println("num exist? " + bs.get(num)); - System.out.println("size of bitset: " + bs.size()); - System.out.println("the number of bits set: " + bs.cardinality()); - bs.set(num);//重复设置 - System.out.println("set again! num exist? " + bs.get(num)); - bs.clear(num);//清除 - System.out.println("after clearing bit: " + bs); - - bs.set(num + 100);//自动扩充容量 - System.out.println("num+100 exist? " + bs.get(num + 100)); - System.out.println("num-1 exist? " + bs.get(num - 1)); - System.out.println("size of bitset: " + bs.size()); - } -} -/*output -{18} -num exist? true -size of bitset: 64 -the number of bits set: 1 -set again! num exist? true -after clearing bit: {} -num+100 exist? true -num-1 exist? false -size of bitset: 128 - */ -``` - - - -## Java I/O 系统 - -### 输入和输出 - -继承自 InputStream 或 Reader 的类都具有 read() 方法,用于读取单个字节或者字节数组;继承自 OutputStream 或 Writer 的类都含有 write() 方法,用于写单个字节或字节数组。 - -#### InputStream 和 OutputStream - -InputStream 用来表示那些从不同数据源产生输入的类。这些数据源包括:1.字节数组;2.String 对象;3.文件;4.管道;5.一个由其他种类的流组成的序列。 - -InputStream 类有一个抽象方法:`abstract int read()`,这个方法将读入并返回一个字节,或者在遇到输入源结尾时返回-1。 - -OutputStream 决定了输出所要去的目标:字节数组、文件或管道。OutputStream 的 `abstract void write(int b)` 可以向某个输出位置写出一个字节。 - -read() 和 write() 方法在执行时都将阻塞,等待数据被读入或者写出。 - -#### Reader 和 Writer - -字符流是由通过字节流转换得到的,转化过程耗时,而且容易出现乱码问题。I/O 流提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。 - -```java -abstract int read(); -abstract void write(char c); -``` - -### 组合输入输出流过滤器 - -FileInputStream 和 FileOutputStream 可以提供附在磁盘文件上的输入流和输出流。 - -`FileInputStream fin = new FileInputStream("E:/data.txt") //E:\\data.txt` - -通过 java.io.File.separator 可以获得与平台相关的 文件分隔符。 - -FileInputStream 只支持在文件的读写字节,而DataInputStream 只支持数值的读写。 - -实现从文件读取数字,需要将 FileInputStream 和 DataInputStream 组合。 - -```java -FileInputStream fin = new FileInputStream("e:/data.txt"); -DataInputStream din = new DataInputStream(fin); -double x = din.readDouble(); -``` - -使用缓冲机制: - -```java -DataInputStream din = new DataInputStream( - new BufferedInputStream( - new FileInputStream("E:/data.txt") - ) -); -``` - -可回推的输入流: - -```java -PushbackInputStream pin = new PushbackInputStream( - new BufferedInputStream( - new FileInputStream("E:/data.txt") - ) -); - -int b = pin.read(); -if(b != '<') { - pin.unread(b); -} -``` - -从 zip 文件读入数字: - -```java -DataInputStream din = new DataInputStream( - new ZipInputStream( - new FileInputStream("E:/data.zip") - ) -); -``` - -### 文本输入和输出 - -将字节流转化为 Unicode 字符的读入器: - -```java -//Reader in = new InputStreamReader(System.in); -Reader in = new InputStreamReader(new FileInputStream("E:/data.txt"), StandardCharsets.UTF_8); -``` - -将 Unicode 字符转化为字节流的写出器: - -```java -PrintWriter out = new PrintWriter("H:/data.txt", "UTF-8"); -out.print("haha"); -out.flush(); -``` - -默认情况下,自动冲刷机制是禁用的,可以使用`PrintWriter(Writer out, Boolean autoFlush)`启用或禁用自动冲刷机制: - -```java -PrintWriter out = new PrintWriter( - new OutputStreamWriter( - new FileOutputStream("H:/data.txt"), "UTF-8"), - true); -out.print("tyson"); -out.flush(); -``` - -### 以文本格式存储对象 - -```java -public class TextFile { - public static void main(String[] args) throws IOException { - Employee[] staff = new Employee[2]; - DateTimeFormatter ymd = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - //字符串转换成LocalDate类型 - LocalDate ld = LocalDate.parse("2015-11-23", ymd); - staff[0] = new Employee("tyson", 1200.00, ld); - staff[1] = new Employee("tom", 1200.00, ld); - - try (PrintWriter out = new PrintWriter("H:/data.txt", "UTF-8")) { - writeData(staff, out); - } - try (Scanner in = new Scanner( - new FileInputStream("H:/data.txt"), "UTF-8")) { - Employee[] newStaff = readData(in); - - for(Employee e : newStaff) { - System.out.println(e); - } - } - } - - private static void writeData(Employee[] employees, PrintWriter out) throws IOException { - out.println(employees.length); - for(Employee e : employees) { - writeEmployee(out, e); - } - } - - private static Employee[] readData(Scanner in) { - int n = in.nextInt(); - in.nextLine(); - - Employee[] employees = new Employee[n]; - for(int i = 0; i < n ; i++) { - employees[i] = readEmployee(in); - } - - return employees; - } - - public static void writeEmployee(PrintWriter out, Employee e) throws IOException { - out.println(e.getName() + "|" + e.getSalary() + "|" + e.getHireDate()); - } - - public static Employee readEmployee(Scanner in) { - String line = in.nextLine(); - String[] tokens = line.split("\\|"); - String name = tokens[0]; - double salary = Double.parseDouble(tokens[1]); - LocalDate hireDate = LocalDate.parse(tokens[2]); - return new Employee(name, salary, hireDate); - } -} -/*output -Employee{name='tyson', salary=1200.0, hireDate=2015-11-23} -Employee{name='tom', salary=1200.0, hireDate=2015-11-23} - */ -``` - -### 字符编码方式 - -输入和输出流都是用于字节序列,很多情况下,我们希望操作的是字符序列。 - -平台使用的编码方法可以由静态方法`Charset.defaultCharset`返回。 - -将字节数组转化成字符串: - -```java -String str = new String(bytes, StandardCharsets.UTF_8); -``` - -### 读写二进制数据 - -#### DataInput 和 DataOutput - -DataOutput 接口定义了以二进制格式写数组、字符、字符串等的方法,如 writeChars、writeByte、writeInt 和 writeDouble。 - -writeInt 总是将一个整数写出为4字节的二进制数量值,writeDouble 总将一个 double 值写出为8字节的二进制数量值。Java 会将所有的值都按照高位在前的模式写出,这使得 Java 数据文件可以独立于平台。 - -DataInput 接口用于二进制格式读数据,接口定义了如下方法:readInt、readShort、readChar等。 - -DataInputStream 实现了 DataInput 接口,DataOutputStream 实现了 DataOutput 接口: - -```java -DataInputStream in = new DataInputStream(new FileInputStream("e:/data.txt")); -DataOutputStream out = new DataOutputStream(new FileOutputStream("e:/data.txt")); -``` - -#### 随机访问文件 - -RandomAccessFile 类可以在文件中的任何位置查找或写入。RandomAccessFile 类同时实现了 DataInput 和 DataOutput 接口。 - -#### 序列化 - -**保存和加载序列化对象** - -保存对象: - -```java -ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("e:/data.txt")); -Employee tyson = new Employee(); -out.writeObject(tyson); -``` - -读回对象: - -```java -ObjectInputStream in = new ObjectInputStream(new FileInputStream("e:/data.txt")); -Employee e = (Employee)in.readObject(); -``` - -其中,Employee 需要实现 Serializable 接口,接口没有任何方法: - -```java -Employee implements Serializable {...} -``` - -ObjectStreamTest.java - -```java -/** - * Copyright (C), 2018-2019 - * FileName: ObjectStream - * Author: Tyson - * Date: 2019/4/25/0025 14:58 - * Description: 对象序列化 - */ -package com.tyson.chapter18.io; - -import java.io.*; - -/** - * @author Tyson - * @ClassName: ObjectStream - * @create 2019/4/25/0025 14:58 - */ -public class ObjectStream { - public static void main(String[] args) throws IOException, ClassNotFoundException { - Employee tyson = new Employee("tyson", 8888.0, "2015-02-15"); - Manager sophia = new Manager("sophia", 6666.0, "2012-03-15"); - sophia.setSecretary(tyson); - Manager tom = new Manager("tom", 5555.0, "2014-03-16"); - tom.setSecretary(tyson); - Employee[] staff = new Employee[3]; - staff[0] = tyson; - staff[1] = sophia; - staff[2] = tom; - - try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("e:/data.txt"))) { - out.writeObject(staff); - out.flush(); - } - - try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("e:/data.txt"))) { - Employee[] newStaff = (Employee[]) in.readObject(); - newStaff[1].setSalary(23333.0); - for(Employee e : newStaff) { - System.out.println(e); - } - //原对象sophia不变 - System.out.println(staff[1]); - } - } -} - -class Manager extends Employee { - private Employee secretary; - - public Manager(String name, Double salary, String hireDate) { - super(name, salary, hireDate); - } - - @Override - public String toString() { - return "Manager{" + - "name=" +super.getName() + - ", salary=" +super.getSalary() + - ", hireday=" +super.getHireDate() + - ", secretary=" + secretary + - '}'; - } - - public Employee getSecretary() { - return secretary; - } - - public void setSecretary(Employee secretary) { - this.secretary = secretary; - } -} -``` - -通过关键字 transient 可以将某些不可序列化的域设置成瞬时的域,这些域在对象被序列化时总是被跳过。 - -**使用序列化实现克隆** - -将对象序列化到输出流中,然后将其读回,产生的新对象是原对象的深拷贝。 - -### 操作文件 - -File 类既能代表特定文件的名称,又能代表一个目录下的一组文件的名称。 - -#### 目录列表器 - -获取某个目录下以".java"文件后缀结尾的文件名。 - -```java -class DirFilter implements FilenameFilter { - private Pattern pattern; - public DirFilter(String regex) { - pattern = Pattern.compile(regex); - } - @Override - public boolean accept(File dir, String name) { - return pattern.matcher(name).matches(); - } -} - -public class DirList { - public static void main(String[] args) { - File path = new File("H:" + File.separator + - "java-data" + File.separator + "TIJ4-code" + File.separator + "containers"); - //Java文件后缀".+\\.java$" - String[] list = path.list(new DirFilter("A.+\\.java$")); - Arrays.sort(list); - System.out.println(Arrays.toString(list)); - } -} -/*output -[AssociativeArray.java] - */ -``` - -用匿名内部类实现。 - -```java -public class DirList { - public static void main(String[] args) { - File f = new File("H:" + File.separator + - "java-data" + File.separator + "TIJ4-code" + File.separator + "containers"); - String[] fileNames = f.list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".java"); - } - }); - System.out.println(Arrays.toString(fileNames)); - } -} -``` - -### - -## 枚举类型 - -### 基本 enum 特性 - -除了不能继承自一个 enum 之外,我们基本上可以将 enum 看做一个常规的类。所有的 enum 都继承自 java.lang.Enum 类,所以 enum 不能再继承其他类。在创建一个新的 enum 时,可以同时实现一个或多个接口。 - -```java -enum Color { RED, GREEN, BLUE } - -public class EnumClass { - public static void main(String[] args) { - for(Color c : Color.values()) { - System.out.println(c + " ordinal: " + c.ordinal()); - System.out.print(c.compareTo(Color.RED) + " "); - System.out.print(c.equals(Color.RED) + " "); - System.out.println(c == Color.RED); - System.out.println(c.getDeclaringClass()); - System.out.println(c.name()); - System.out.println("-------------------------"); - } - for(String s : "RED GREEN BLUE".split(" ")) { - Color c = Enum.valueOf(Color.class, s); - System.out.println(c); - } - } -} -/*output -RED ordinal: 0 -0 true true -class com.tyson.chapter19.enumerated.Color -RED -------------------------- -GREEN ordinal: 1 -1 false false -class com.tyson.chapter19.enumerated.Color -GREEN -------------------------- -BLUE ordinal: 2 -2 false false -class com.tyson.chapter19.enumerated.Color -BLUE -------------------------- -RED -GREEN -BLUE - */ -``` - -values() 是编译器添加的 static 方法,Enum 类中没有 values() 方法。ordinal() 方法返回一个 int 值,这是每个 enum 实例声明时的次序,从0开始。valueOf() 根据给定的名字返回相应的 enum实例,如果不存在给定名字的实例,将会抛出异常。 - -### 向 enum 添加新方法 - -```java -public enum Direction { - WEST("Xizang"), - NORTH("Beijing"), - EAST("Shanghai"), - SOUTH("Hainan");//定义自己的方法,enum实例序列的最后需添加分号 - //属性和方法需要在enum实例之后定义 - private String discription; - private Direction(String discription) { - this.discription = discription; - } - public String getDiscription() { - return discription; - } - - public static void main(String[] args) { - for(Direction dir : Direction.values()) { - System.out.println(dir + ": " + dir.getDiscription()); - } - } -} -/*output -WEST: Xizang -NORTH: Beijing -EAST: Shanghai -SOUTH: Hainan - */ -``` - -### 覆盖 enum 的方法 - -```java -public enum Animal { - CAT, DOG, BIRD, PIG; - @Override - public String toString() { - String id = name(); - String lower = id.substring(1).toLowerCase(); - return id.charAt(0) + lower; - } - - public static void main(String[] args) { - for(Animal a : values()) { - System.out.print(a + " "); - } - } -} -//output: Cat Dog Bird Pig -``` - -### Switch 语句中的 enum - -```java -enum Signal { - GREEN, YELLOW, RED, -} - -public class TrafficLight { - Signal color = Signal.RED; - - public void change() { - switch (color) { - case RED: - color = Signal.GREEN; - break; - case GREEN: - color = Signal.YELLOW; - break; - case YELLOW: - color = Signal.RED; - break; - } - } - @Override - public String toString() { - return "the traffic light is: " + color; - } - - public static void main(String[] args) { - TrafficLight tl = new TrafficLight(); - for (int i = 0; i < 4; i++) { - System.out.println(tl); - tl.change(); - } - } -} -/*output -the traffic light is: RED -the traffic light is: GREEN -the traffic light is: YELLOW -the traffic light is: RED - */ -``` - -### EnumSet - - 如果你想用一个数表示多种状态,那么位运算是一种很好的选择。EnumSet 是通过位运算实现的。它是一个与枚举类型一起使用的专用 Set 实现。枚举set中所有元素都必须来自单个枚举类型(即必须是同类型,且该类型是 Enum 的子类)。 - -```java -public enum Season { - SPRING, SUMMER, AUTUMN, WINTER; - - public static void main(String[] args) { - Set emptyEnumSet = EnumSet.noneOf(Season.class); - System.out.println("EnumSet.noneOf(): " + emptyEnumSet); - emptyEnumSet.add(SPRING); - System.out.println("emptyEnumSet.add(SPRING): " + emptyEnumSet); - Set enumSet = EnumSet.allOf(Season.class); - System.out.println("EnumSet.allOf(): " + enumSet); - emptyEnumSet.addAll(enumSet); - System.out.println("emptyEnumSet.addAll(): " + emptyEnumSet); - Season[] seasons = new Season[emptyEnumSet.size()]; - enumSet.toArray(seasons); - System.out.println("seasons: " + Arrays.toString(seasons)); - } -} -/*output -EnumSet.noneOf(): [] -emptyEnumSet.add(SPRING): [SPRING] -EnumSet.allOf(): [SPRING, SUMMER, AUTUMN, WINTER] -emptyEnumSet.addAll(): [SPRING, SUMMER, AUTUMN, WINTER] -seasons: [SPRING, SUMMER, AUTUMN, WINTER] - */ -``` - -#### 源码解析 - -参考自:[EnumSet源码解析](https://www.jianshu.com/p/f7035c5816b1) - -```java -//EnumSet的容量小于64,创建的是RegularEnumSet,大于64,创建的是JumboEnumSet -public boolean add(E e) { - // 校验枚举类型 - typeCheck(e); - - long oldElements = elements; - elements |= (1L << ((Enum)e).ordinal()); - return elements != oldElements; -} - -/** - * 用于校验枚举类型,位于EnumSet中 - */ -final void typeCheck(E e) { - Class eClass = e.getClass(); - if (eClass != elementType && eClass.getSuperclass() != elementType) - throw new ClassCastException(eClass + " != " + elementType); -} -``` - -每一个枚举元素都有一个属性ordinal,用来表示该元素在枚举类型中的次序或者说下标。 - -![EnumSet add方法](https://img2018.cnblogs.com/blog/1252910/201904/1252910-20190415211843720-460902205.png) - -addAll 方法就是将 elements 上,从低位到枚举长度上的下标值置为1。比如某一个枚举类型共5个元素,而addAll 就是将 elements 的二进制的低5位置为1。 - -```java -void addAll() { - if (universe.length != 0) - elements = -1L >>> -universe.length; -} -``` - -### EnumMap - -EnumMap 是一种特殊的 Map,它要求其中的键必须来自一个 enum。由于 enum 本身的限制,所以 EnumMap 在内部可由数组实现。因此 EnumMap 的速度很快。 - -```java -interface Command { void action(); } -public class EnumMaps { - public static void main(String[] args) { - EnumMap em = new EnumMap<>(AlarmPoints.class); - em.put(KITCHEN, new Command() { - @Override - public void action() { - System.out.println("Kitchen fire!"); - } - }); - em.put(BATHROOM, new Command() { - @Override - public void action() { - System.out.println("Bathroom alert"); - } - }); - for(Map.Entry e : em.entrySet()) { - System.out.print(e.getKey() + ": "); - e.getValue().action(); - } - //获取不存在的值 - try { - em.get(UTILITY).action(); - } catch (Exception ex) { - System.out.println(ex); - } - } -} -/*output -BATHROOM: Bathroom alert -KITCHEN: Kitchen fire! -java.lang.NullPointerException - */ -``` - -与 EnumSet 一样,enum 实例定义时的次序决定了其在 EnumMap 中的顺序。每个 enum 实例都会作为键存放到 EnumMap 中,如果没有为这个键调用 put() 方法来存入相应的值的话,其对应的值为 null。 - - - -## 注解 - -Java SE5内置了三种定义在 java.lang 中的注解:@Override,@Deprecated 和 @SuppressWarnings(关闭不当的编译器警告信息)。 - -### 基本语法 - -```java -@Target(ElementType.METHOD)//应用于什么地方,方法、域等 -@Retention(RetentionPolicy.SOURCE)//注解在哪一个级别可用,SOURCE/CLASS/RUNTIME -public @interface Override { -} -``` - -#### 自定义注解 - -```java -//UserCase.java -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface UserCase { - public int id(); - public String description() default "no description"; -} - -//PasswordUtils.java -public class PasswordUtils { - @UserCase(id = 47, description = "Passwords must contain at least one numeric") - public boolean validatePassword(String password) { - return password.matches("\\w*\\d\\w*"); - } -} -``` - -注解元素(本例的是 id和description)只能是基本类型、String、Class、enum、Annotation 和这些类型的数组。 - -@Retention注解三种取值:**RetentionPolicy.SOURCE**、**RetentionPolicy.CLASS**、**RetentionPolicy.RUNTIME**分别对应:Java源文件(.java文件)---->.class文件---->内存中的字节码。 - -@Target元注解决定了一个注解可以标识到哪些成分上,如标识在在类身上,或者属性身上,或者方法身上等成分,@Target默认值为任何元素(成分)。 - -**Retention注解说明** - -参考自:[注解](https://www.cnblogs.com/xdp-gacl/p/3622275.html) - -当在Java源程序上加了一个注解,这个Java源程序要由javac去编译,javac把java源文件编译成.class文件,在编译成class时可能会把Java源程序上的一些注解给去掉,java编译器在处理java源程序时,可能会认为这个注解没有用了,于是就把这个注解去掉了,那么此时在编译好的class中就找不到注解了, 这是编译器编译java源程序时对注解进行处理的第一种可能情况,假设java编译器在把java源程序编译成class时,没有把java源程序中的注解去掉,那么此时在编译好的class中就可以找到注解,当程序使用编译好的class文件时,需要用类加载器把class文件加载到内存中,class文件中的东西不是字节码,class文件里面的东西由类加载器加载到内存中去,类加载器在加载class文件时,会对class文件里面的东西进行处理,如安全检查,处理完以后得到的最终在内存中的二进制的东西才是字节码,类加载器在把class文件加载到内存中时也有转换,转换时是否把class文件中的注解保留下来,这也有说法,所以说**一个注解的生命周期有三个阶段:java源文件是一个阶段,class文件是一个阶段,内存中的字节码是一个阶段**,javac把java源文件编译成.class文件时,有可能去掉里面的注解,类加载器把.class文件加载到内存时也有可能去掉里面的注解,因此**在自定义注解时就可以使用Retention注解指明自定义注解的生命周期,自定义注解的生命周期是在RetentionPolicy.SOURCE阶段(java源文件阶段),还是在RetentionPolicy.CLASS阶段(class文件阶段),或者是在RetentionPolicy.RUNTIME阶段(内存中的字节码运行时阶段)**,根据**JDK提供的API可以知道默认是在RetentionPolicy.CLASS阶段 (JDK的API写到:the retention policy defaults to RetentionPolicy.CLASS)。** - -### 元注解 - -元、注解负责注解其他的注解。 - -| 注解 | 作用 | -| ----------- | -------------------------------- | -| @Target | 表示该注解可以用于什么地方 | -| @Retention | 表示需要在什么级别保存该注解信息 | -| @Documented | 将此注解包含在 Javadoc 中 | -| @Inherited | 允许子类继承父类的注解 | - -### 编写注解处理器 - -使用注解时,很重要的一部分就是创建和使用注解处理器。 - -```java -public class UseCaseTracker { - public static void trackUseCases(List useCases, Class c) { - for(Method m : c.getDeclaredMethods()) { - UseCase uc = m.getAnnotation(UseCase.class); - if(uc != null) { - System.out.println("found use case: " + uc.id() + " " + uc.description()); - useCases.remove(new Integer(uc.id())); - } - } - for(int i : useCases) { - System.out.println("warning: missing use case-" + i); - } - } - - public static void main(String[] args) { - List useCases = new ArrayList<>(); - Collections.addAll(useCases, 47, 48); - trackUseCases(useCases, PasswordUtils.class); - } -} -/*output -found use case: 47 Passwords must contain at least one numeric -warning: missing use case-48 - */ -``` - -### 注解综合 - -```java -//TrafficLight.java -public enum TrafficLight { - RED, GREEN, YELLOW; -} - -//MetaAnnotation.java -public @interface MetaAnnotation { - String value(); -} - -//MyAnnotation.java -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface MyAnnotation { - String color() default "blue"; - //当只有value属性要设置时,可以省略"value=" - String value(); - int[] arrayAttr() default {1, 2, 3}; - TrafficLight lamp() default TrafficLight.GREEN; - MetaAnnotation annotationAttr() default @MetaAnnotation("tyson"); -} - -//MyAnnotationTracker.java -@MyAnnotation( - color = "red", - value = "MyAnnotation注解用于MyAnnotationTracker类", - arrayAttr = {6, 6, 6}, - lamp = TrafficLight.GREEN, - annotationAttr = @MetaAnnotation("sophia") -) -public class MyAnnotationTracker { - @MyAnnotation("MyAnnotation注解用于main方法") - public static void main(String[] args) { - //如果指定类型的注解存在于此元素上则返回true - if(MyAnnotationTracker.class.isAnnotationPresent(MyAnnotation.class)) { - //获取类的注解 - MyAnnotation myAnnotation = (MyAnnotation)MyAnnotationTracker.class.getAnnotation(MyAnnotation.class); - System.out.println(myAnnotation.color()); - System.out.println(myAnnotation.value()); - System.out.println(Arrays.toString(myAnnotation.arrayAttr())); - System.out.println(myAnnotation.lamp()); - MetaAnnotation ma = myAnnotation.annotationAttr(); - System.out.println(ma.value()); - } - //获取方法的注解 - for(Method m : MyAnnotationTracker.class.getDeclaredMethods()) { - MyAnnotation myAnnotation1 = m.getAnnotation(MyAnnotation.class); - if(myAnnotation1 != null) { - System.out.println(myAnnotation1.value()); - } - } - } -} -/*output -red -MyAnnotation注解用于MyAnnotationTracker类 -[6, 6, 6] -GREEN -sophia -MyAnnotation注解用于main方法 - */ -``` - - - - - - - diff --git "a/Java/Java\345\205\263\351\224\256\345\255\227.md" "b/Java/Java\345\205\263\351\224\256\345\255\227.md" deleted file mode 100644 index 3dc54e5..0000000 --- "a/Java/Java\345\205\263\351\224\256\345\255\227.md" +++ /dev/null @@ -1,205 +0,0 @@ - - - - -- [static](#static) - - [静态变量](#%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F) - - [静态方法](#%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95) - - [静态代码块](#%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97) - - [静态内部类](#%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB) -- [final](#final) -- [this](#this) -- [super](#super) - - - -## static - -static可以用来修饰类的成员方法、类的成员变量。 - -### 静态变量 - -static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。 - -以下例子,age为非静态变量,则p1打印结果是:`Name:zhangsan, Age:10`;若age使用static修饰,则p1打印结果是:`Name:zhangsan, Age:12`,因为static变量在内存只有一个副本。 - -```java -public class Person { - String name; - int age; - - public String toString() { - return "Name:" + name + ", Age:" + age; - } - - public static void main(String[] args) { - Person p1 = new Person(); - p1.name = "zhangsan"; - p1.age = 10; - Person p2 = new Person(); - p2.name = "lisi"; - p2.age = 12; - System.out.println(p1); - System.out.println(p2); - } - /**Output - * Name:zhangsan, Age:10 - * Name:lisi, Age:12 - *///~ -} -``` - -### 静态方法 - -static方法一般称作静态方法。静态方法不依赖于任何对象就可以进行访问,通过类名即可调用静态方法。 - -```java -public class Utils { - public static void print(String s) { - System.out.println("hello world: " + s); - } - - public static void main(String[] args) { - Utils.print("程序员大彬"); - } -} -``` - -### 静态代码块 - -静态代码块只会在类加载的时候执行一次。以下例子,startDate和endDate在类加载的时候进行赋值。 - -```java -class Person { - private Date birthDate; - private static Date startDate, endDate; - static{ - startDate = Date.valueOf("2008"); - endDate = Date.valueOf("2021"); - } - - public Person(Date birthDate) { - this.birthDate = birthDate; - } -} -``` - -### 静态内部类 - -**在静态方法里**,使用⾮静态内部类依赖于外部类的实例,也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。⽽静态内部类不需要。 - -```java -public class OuterClass { - class InnerClass { - } - static class StaticInnerClass { - } - public static void main(String[] args) { - // 在静态方法里,不能直接使用OuterClass.this去创建InnerClass的实例 - // 需要先创建OuterClass的实例o,然后通过o创建InnerClass的实例 - // InnerClass innerClass = new InnerClass(); - OuterClass outerClass = new OuterClass(); - InnerClass innerClass = outerClass.new InnerClass(); - StaticInnerClass staticInnerClass = new StaticInnerClass(); - - outerClass.test(); - } - - public void nonStaticMethod() { - InnerClass innerClass = new InnerClass(); - System.out.println("nonStaticMethod..."); - } -} -``` - - - -## final - -1. **基本数据**类型用final修饰,则不能修改,是常量;**对象引用**用final修饰,则引用只能指向该对象,不能指向别的对象,但是对象本身可以修改。 - -2. final修饰的方法不能被子类重写 - -3. final修饰的类不能被继承。 - - - -## this - - `this.属性名称`指访问类中的成员变量,可以用来区分成员变量和局部变量。如下代码所示,`this.name`访问类Person当前实例的变量。 - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-17 00:29 - */ -public class Person { - String name; - int age; - - public Person(String name, int age) { - this.name = name; - this.age = age; - } -} -``` - -`this.方法名称`用来访问本类的方法。以下代码中,`this.born()`调用类 Person 的当前实例的方法。 - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-17 00:29 - */ -public class Person { - String name; - int age; - - public Person(String name, int age) { - this.born(); - this.name = name; - this.age = age; - } - - void born() { - } -} -``` - - - -## super - -super 关键字用于在子类中访问父类的变量和方法。 - -```java -class A { - protected String name = "大彬"; - - public void getName() { - System.out.println("父类:" + name); - } -} - -public class B extends A { - @Override - public void getName() { - System.out.println(super.name); - super.getName(); - } - - public static void main(String[] args) { - B b = new B(); - b.getName(); - } - /** - * 大彬 - * 父类:大彬 - */ -} -``` - -在子类B中,我们重写了父类的getName()方法,如果在重写的getName()方法中我们要调用父类的相同方法,必须要通过super关键字显式指出。 - diff --git "a/Java/Java\345\237\272\347\241\200.md" "b/Java/Java\345\237\272\347\241\200.md" deleted file mode 100644 index 3a08dc1..0000000 --- "a/Java/Java\345\237\272\347\241\200.md" +++ /dev/null @@ -1,1582 +0,0 @@ - - - - -- [Java概述](#java%E6%A6%82%E8%BF%B0) - - [Java的特点](#java%E7%9A%84%E7%89%B9%E7%82%B9) - - [JKD和JRE](#jkd%E5%92%8Cjre) - - [JDK](#jdk) - - [JRE](#jre) -- [Java基础语法](#java%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95) - - [基本数据类型](#%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B) - - [包装类型](#%E5%8C%85%E8%A3%85%E7%B1%BB%E5%9E%8B) - - [包装类缓存](#%E5%8C%85%E8%A3%85%E7%B1%BB%E7%BC%93%E5%AD%98) - - [String](#string) - - [String拼接](#string%E6%8B%BC%E6%8E%A5) - - [关键字](#%E5%85%B3%E9%94%AE%E5%AD%97) - - [static](#static) - - [静态变量](#%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F) - - [静态方法](#%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95) - - [静态代码块](#%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97) - - [静态内部类](#%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB) - - [final](#final) - - [this](#this) - - [super](#super) - - [object常用方法](#object%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95) - - [toString](#tostring) - - [equals](#equals) - - [hashCode](#hashcode) - - [clone](#clone) - - [浅拷贝](#%E6%B5%85%E6%8B%B7%E8%B4%9D) - - [深拷贝](#%E6%B7%B1%E6%8B%B7%E8%B4%9D) - - [getClass](#getclass) - - [wait](#wait) - - [notity](#notity) - - [equals()和hashcode()的关系](#equals%E5%92%8Chashcode%E7%9A%84%E5%85%B3%E7%B3%BB) - - [==和equals区别](#%E5%92%8Cequals%E5%8C%BA%E5%88%AB) -- [面向对象](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1) - - [面向对象特性](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%89%B9%E6%80%A7) - - [多态怎么实现](#%E5%A4%9A%E6%80%81%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0) - - [类与对象](#%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1) - - [属性](#%E5%B1%9E%E6%80%A7) - - [方法](#%E6%96%B9%E6%B3%95) - - [普通方法](#%E6%99%AE%E9%80%9A%E6%96%B9%E6%B3%95) - - [构造方法](#%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95) - - [方法重载](#%E6%96%B9%E6%B3%95%E9%87%8D%E8%BD%BD) - - [方法重写](#%E6%96%B9%E6%B3%95%E9%87%8D%E5%86%99) - - [初始化顺序](#%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F) -- [接口和抽象类](#%E6%8E%A5%E5%8F%A3%E5%92%8C%E6%8A%BD%E8%B1%A1%E7%B1%BB) - - [抽象类](#%E6%8A%BD%E8%B1%A1%E7%B1%BB) - - [接口](#%E6%8E%A5%E5%8F%A3) - - [接口与抽象类区别](#%E6%8E%A5%E5%8F%A3%E4%B8%8E%E6%8A%BD%E8%B1%A1%E7%B1%BB%E5%8C%BA%E5%88%AB) -- [反射](#%E5%8F%8D%E5%B0%84) - - [Class类](#class%E7%B1%BB) - - [Field类](#field%E7%B1%BB) - - [Method类](#method%E7%B1%BB) -- [泛型](#%E6%B3%9B%E5%9E%8B) - - [泛型类](#%E6%B3%9B%E5%9E%8B%E7%B1%BB) - - [泛型接口](#%E6%B3%9B%E5%9E%8B%E6%8E%A5%E5%8F%A3) - - [泛型方法](#%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95) -- [Exception](#exception) - - [Throwable](#throwable) - - [常见的Exception](#%E5%B8%B8%E8%A7%81%E7%9A%84exception) - - [关键字](#%E5%85%B3%E9%94%AE%E5%AD%97-1) -- [IO流](#io%E6%B5%81) - - [InputStream 和 OutputStream](#inputstream-%E5%92%8C-outputstream) - - [Reader 和 Writer](#reader-%E5%92%8C-writer) - - [字符流和字节流的转换](#%E5%AD%97%E7%AC%A6%E6%B5%81%E5%92%8C%E5%AD%97%E8%8A%82%E6%B5%81%E7%9A%84%E8%BD%AC%E6%8D%A2) - - [同步异步](#%E5%90%8C%E6%AD%A5%E5%BC%82%E6%AD%A5) - - [阻塞非阻塞](#%E9%98%BB%E5%A1%9E%E9%9D%9E%E9%98%BB%E5%A1%9E) - - [BIO](#bio) - - [NIO](#nio) - - [AIO](#aio) - - [BIO/NIO/AIO区别](#bionioaio%E5%8C%BA%E5%88%AB) -- [ThreadLocal](#threadlocal) - - [原理](#%E5%8E%9F%E7%90%86) - - [内存泄漏](#%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F) - - [使用场景](#%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF) -- [线程安全类](#%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%B1%BB) -- [常见操作](#%E5%B8%B8%E8%A7%81%E6%93%8D%E4%BD%9C) - - [排序](#%E6%8E%92%E5%BA%8F) - - [数组操作](#%E6%95%B0%E7%BB%84%E6%93%8D%E4%BD%9C) - - [拷贝](#%E6%8B%B7%E8%B4%9D) - - [数组拷贝](#%E6%95%B0%E7%BB%84%E6%8B%B7%E8%B4%9D) - - [对象拷贝](#%E5%AF%B9%E8%B1%A1%E6%8B%B7%E8%B4%9D) - - [序列化](#%E5%BA%8F%E5%88%97%E5%8C%96) - - [什么情况下需要序列化?](#%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E9%9C%80%E8%A6%81%E5%BA%8F%E5%88%97%E5%8C%96) - - [如何实现序列化](#%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%BA%8F%E5%88%97%E5%8C%96) - - [serialVersionUID](#serialversionuid) - - [遍历](#%E9%81%8D%E5%8E%86) - - [fast-fail](#fast-fail) - - [fail-safe](#fail-safe) - - [移除集合元素](#%E7%A7%BB%E9%99%A4%E9%9B%86%E5%90%88%E5%85%83%E7%B4%A0) - - - -# Java概述 - -## Java的特点 - -**Java是一门面向对象的编程语言。**面向对象和面向过程是一种软件开发思想。 - -- 面向过程就是分析出解决问题所需要的步骤,然后用函数按这些步骤实现,使用的时候依次调用就可以了。面向对象是把构成问题事务分解成各个对象,分别设计这些对象,然后将他们组装成有完整功能的系统。面向过程只用函数实现,面向对象是用类实现各个功能模块。 - - 例如五子棋,面向过程的设计思路就是首先分析问题的步骤: - 1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。 - 把上面每个步骤用分别的函数来实现,问题就解决了。 - -- 而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为: - 1、黑白双方 - 2、棋盘系统,负责绘制画面 - 3、规则系统,负责判定诸如犯规、输赢等。 - 黑白双方负责接受用户的输入,并告知棋盘系统棋子布局发生变化,棋盘系统接收到了棋子的变化的信息就负责在屏幕上面显示出这种变化,同时利用规则系统来对棋局进行判定。 - -**Java具有平台独立性和移植性。** - -- Java有一句口号:Write once, run anywhere,一次编写、到处运行。这也是Java的魅力所在。而实现这种特性的正是Java虚拟机JVM。已编译的Java程序可以在任何带有JVM的平台上运行。你可以在windows平台编写代码,然后拿到linux上运行。只要你在编写完代码后,将代码编译成.class文件,再把class文件打成Java包,这个jar包就可以在不同的平台上运行了。 - -**Java具有稳健性。** - -- Java是一个强类型语言,它允许扩展编译时检查潜在类型不匹配问题的功能。Java要求显式的方法声明,它不支持C风格的隐式声明。这些严格的要求保证编译程序能捕捉调用错误,这就导致更可靠的程序。 -- 异常处理是Java中使得程序更稳健的另一个特征。异常是某种类似于错误的异常条件出现的信号。使用try/catch/finally语句,程序员可以找到出错的处理代码,这就简化了出错处理和恢复的任务。 - -## JKD和JRE - -JDK和JRE是Java开发和运行工具,其中JDK包含了JRE,而JRE是可以独立安装的。 - -### JDK - -Java Development Kit,JAVA语言的软件工具开发包,是整个JAVA开发的核心,它包含了JAVA的运行(JVM+JAVA类库)环境和JAVA工具。 - -### JRE - -JRE(Java Runtime Environment,Java运行环境):包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)。 - -JRE是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。 - -# Java基础语法 - -## 基本数据类型 - -- byte,8bit -- char,16bit -- short,16bit -- int,32bit -- float,32bit -- long,64bit -- double,64bit -- boolean,只有两个值:true、false,可以使⽤用 1 bit 来存储,但是具体⼤小没有明确规定。 - -## 包装类型 - -基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值通过自动装箱与拆箱完成。 - -```java -Integer x = 1; // 装箱 调⽤ Integer.valueOf(1) -int y = x; // 拆箱 调⽤了 X.intValue() -``` - -### 包装类缓存 - -使用Integer.valueOf(i)生成Integer,如果 -128 <= i <= 127,则直接从cache取对象返回,不会创建新的对象,避免频繁创建包装类对象。 - -```java - public static Integer valueOf(int i) { - if (i >= IntegerCache.low && i <= IntegerCache.high) - return IntegerCache.cache[i + (-IntegerCache.low)]; - return new Integer(i); - } -``` - -## String - -String是final类,不可被继承。 - -### String拼接 - -字符串拼接可以使用String用+做拼接,也可以使用StringBuilder和StringBuffer实现,三种方式对比: - -- 底层都是char数组实现的 - -- 字符串拼接性能:StringBuilder > StringBuffer > String -- String 是字符串常量,一旦创建之后该对象是不可更改的,用+对String做拼接操作,实际上是先通过建立StringBuilder,然后调用append()做拼接操作,所以在大量字符串拼接的时候,会频繁创建StringBuilder,性能较差。 -- StringBuilder和StringBuffer的对象是字符串变量,对变量进行操作就是直接对该对象进行修改(修改char[]数组),所以速度要比String快很多。 -- 在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的,StringBuffer中很多方法带有synchronized关键字,可以保证线程安全。 - -## 关键字 - -### static - -static可以用来修饰类的成员方法、类的成员变量。 - -#### 静态变量 - -static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。 - -以下例子,age为非静态变量,则p1打印结果是:`Name:zhangsan, Age:10`;若age使用static修饰,则p1打印结果是:`Name:zhangsan, Age:12`,因为static变量在内存只有一个副本。 - -```java -public class Person { - String name; - int age; - - public String toString() { - return "Name:" + name + ", Age:" + age; - } - - public static void main(String[] args) { - Person p1 = new Person(); - p1.name = "zhangsan"; - p1.age = 10; - Person p2 = new Person(); - p2.name = "lisi"; - p2.age = 12; - System.out.println(p1); - System.out.println(p2); - } - /**Output - * Name:zhangsan, Age:10 - * Name:lisi, Age:12 - *///~ -} -``` - -#### 静态方法 - -static方法一般称作静态方法。静态方法不依赖于任何对象就可以进行访问,通过类名即可调用静态方法。 - -```java -public class Utils { - public static void print(String s) { - System.out.println("hello world: " + s); - } - - public static void main(String[] args) { - Utils.print("程序员大彬"); - } -} -``` - -#### 静态代码块 - -静态代码块只会在类加载的时候执行一次。以下例子,startDate和endDate在类加载的时候进行赋值。 - -```java -class Person { - private Date birthDate; - private static Date startDate, endDate; - static{ - startDate = Date.valueOf("2008"); - endDate = Date.valueOf("2021"); - } - - public Person(Date birthDate) { - this.birthDate = birthDate; - } -} -``` - -#### 静态内部类 - -**在静态方法里**,使用⾮静态内部类依赖于外部类的实例,也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。⽽静态内部类不需要。 - -```java -public class OuterClass { - class InnerClass { - } - static class StaticInnerClass { - } - public static void main(String[] args) { - // 在静态方法里,不能直接使用OuterClass.this去创建InnerClass的实例 - // 需要先创建OuterClass的实例o,然后通过o创建InnerClass的实例 - // InnerClass innerClass = new InnerClass(); - OuterClass outerClass = new OuterClass(); - InnerClass innerClass = outerClass.new InnerClass(); - StaticInnerClass staticInnerClass = new StaticInnerClass(); - - outerClass.test(); - } - - public void nonStaticMethod() { - InnerClass innerClass = new InnerClass(); - System.out.println("nonStaticMethod..."); - } -} -``` - - - -### final - -1. **基本数据**类型用final修饰,则不能修改,是常量;**对象引用**用final修饰,则引用只能指向该对象,不能指向别的对象,但是对象本身可以修改。 - -2. final修饰的方法不能被子类重写 - -3. final修饰的类不能被继承。 - - - -### this - - `this.属性名称`指访问类中的成员变量,可以用来区分成员变量和局部变量。如下代码所示,`this.name`访问类Person当前实例的变量。 - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-17 00:29 - */ -public class Person { - String name; - int age; - - public Person(String name, int age) { - this.name = name; - this.age = age; - } -} -``` - -`this.方法名称`用来访问本类的方法。以下代码中,`this.born()`调用类 Person 的当前实例的方法。 - -```java -/** - * @description: - * @author: 程序员大彬 - * @time: 2021-08-17 00:29 - */ -public class Person { - String name; - int age; - - public Person(String name, int age) { - this.born(); - this.name = name; - this.age = age; - } - - void born() { - } -} -``` - - - -### super - -super 关键字用于在子类中访问父类的变量和方法。 - -```java -class A { - protected String name = "大彬"; - - public void getName() { - System.out.println("父类:" + name); - } -} - -public class B extends A { - @Override - public void getName() { - System.out.println(super.name); - super.getName(); - } - - public static void main(String[] args) { - B b = new B(); - b.getName(); - } - /** - * 大彬 - * 父类:大彬 - */ -} -``` - -在子类B中,我们重写了父类的getName()方法,如果在重写的getName()方法中我们要调用父类的相同方法,必须要通过super关键字显式指出。 - -## object常用方法 - -Java面试经常会出现的一道题目,Object的常用方法。下面给大家整理一下。 - -object常用方法有:toString()、equals()、hashCode()、clone()等。 - -### toString - -默认输出对象地址。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - public static void main(String[] args) { - System.out.println(new Person(18, "程序员大彬").toString()); - } - //output - //me.tyson.java.core.Person@4554617c -} -``` - -可以重写toString方法,按照重写逻辑输出对象值。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - @Override - public String toString() { - return name + ":" + age; - } - - public static void main(String[] args) { - System.out.println(new Person(18, "程序员大彬").toString()); - } - //output - //程序员大彬:18 -} -``` - -### equals - -默认比较两个引用变量是否指向同一个对象(内存地址)。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - public static void main(String[] args) { - String name = "程序员大彬"; - Person p1 = new Person(18, name); - Person p2 = new Person(18, name); - - System.out.println(p1.equals(p2)); - } - //output - //false -} -``` - -可以重写equals方法,按照age和name是否相等来判断: - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (o instanceof Person) { - Person p = (Person) o; - return age == p.age && name.equals(p.name); - } - return false; - } - - public static void main(String[] args) { - String name = "程序员大彬"; - Person p1 = new Person(18, name); - Person p2 = new Person(18, name); - - System.out.println(p1.equals(p2)); - } - //output - //true -} -``` - -### hashCode - -将与对象相关的信息映射成一个哈希值,默认的实现hashCode值是根据内存地址换算出来。 - -```java -public class Cat { - public static void main(String[] args) { - System.out.println(new Cat().hashCode()); - } - //out - //1349277854 -} -``` - -### clone - -java赋值是复制对象引用,如果我们想要得到一个对象的副本,使用赋值操作是无法达到目的的。Object对象有个clone()方法,实现了对 - -象中各个属性的复制,但它的可见范围是protected的。 - -```java -protected native Object clone() throws CloneNotSupportedException; -``` - -所以实体类使用克隆的前提是: - -- 实现Cloneable接口,这是一个标记接口,自身没有方法,这应该是一种约定。调用clone方法时,会判断有没有实现Cloneable接口,没有实现Cloneable的话会抛异常CloneNotSupportedException。 -- 覆盖clone()方法,可见性提升为public。 - -```java -public class Cat implements Cloneable { - private String name; - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - c.name = "程序员大彬"; - Cat cloneCat = (Cat) c.clone(); - c.name = "大彬"; - System.out.println(cloneCat.name); - } - //output - //程序员大彬 -} -``` - -#### 浅拷贝 - -拷⻉对象和原始对象的引⽤类型引用同⼀个对象。 - -以下例子,Cat对象里面有个Person对象,调用clone之后,克隆对象和原对象的Person引用的是同一个对象,这就是浅拷贝。 - -```java -public class Cat implements Cloneable { - private String name; - private Person owner; - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - Person p = new Person(18, "程序员大彬"); - c.owner = p; - - Cat cloneCat = (Cat) c.clone(); - p.setName("大彬"); - System.out.println(cloneCat.owner.getName()); - } - //output - //大彬 -} -``` - -#### 深拷贝 - -拷贝对象和原始对象的引用类型引用不同的对象。 - -以下例子,在clone函数中不仅调用了super.clone,而且调用Person对象的clone方法(Person也要实现Cloneable接口并重写clone方法),从而实现了深拷贝。可以看到,拷贝对象的值不会受到原对象的影响。 - -```java -public class Cat implements Cloneable { - private String name; - private Person owner; - - @Override - protected Object clone() throws CloneNotSupportedException { - Cat c = null; - c = (Cat) super.clone(); - c.owner = (Person) owner.clone();//拷贝Person对象 - return c; - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - Person p = new Person(18, "程序员大彬"); - c.owner = p; - - Cat cloneCat = (Cat) c.clone(); - p.setName("大彬"); - System.out.println(cloneCat.owner.getName()); - } - //output - //程序员大彬 -} -``` - -### getClass - -返回此 Object 的运行时类,常用于java反射机制。 - -```java -public class Person { - private String name; - - public Person(String name) { - this.name = name; - } - - public static void main(String[] args) { - Person p = new Person("程序员大彬"); - Class clz = p.getClass(); - System.out.println(clz); - //获取类名 - System.out.println(clz.getName()); - } - /** - * class com.tyson.basic.Person - * com.tyson.basic.Person - */ -} -``` - -### wait - -当前线程调用对象的wait()方法之后,当前线程会释放对象锁,进入等待状态。等待其他线程调用此对象的notify()/notifyAll()唤醒或者等待超时时间wait(long timeout)自动唤醒。线程需要获取obj对象锁之后才能调用 obj.wait()。 - -### notity - -obj.notify()唤醒在此对象上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象上等待的所有线程。 - -> LockSupport.park()/LockSupport.parkNanos(long nanos)/LockSupport.parkUntil(long deadlines),用于阻塞当前线程。对比obj.wait()方法,不需要获得锁就可以让线程进入等待状态,需要通过LockSupport.unpark(Thread thread)唤醒。 - -### equals()和hashcode()的关系 - -equals与hashcode的关系: -1、如果两个对象调用equals比较返回true,那么它们的hashCode值一定要相同; -2、如果两个对象的hashCode相同,它们并不一定相同。 - -hashcode方法主要是用来提升对象比较的效率,先进行hashcode()的比较,如果不相同,那就不必在进行equals的比较,这样就大大减少了equals比较的次数,当比较对象的数量很大的时候能提升效率。 - -之所以重写equals()要重写hashcode(),是为了保证equals()方法返回true的情况下hashcode值也要一致,如果重写了equals()没有重写hashcode(),就会出现两个对象相等但hashcode()不相等的情况。这样,当用其中的一个对象作为键保存到hashMap、hashTable或hashSet中,再以另一个对象作为键值去查找他们的时候,则会查找不到。 - -### ==和equals区别 - -- 对于基本数据类型,==比较的是他们的值。基本数据类型没有equal方法; - -- 对于复合数据类型,==比较的是它们的存放地址(是否是同一个对象)。equals()默认比较地址值,重写的话按照重写逻辑去比较。 - -# 面向对象 - -## 面向对象特性 - -面向对象四大特性:封装,继承,多态,抽象 - -- 封装就是将类的信息隐藏在类内部,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。 良好的封装能够减少耦合。 -- 继承是从已有的类中派生出新的类,新的类继承父类的属性和行为,并能扩展新的能力,大大增加程序的重用性和易维护性。在Java中是单继承的,也就是说一个子类只有一个父类。 -- 多态是同一个行为具有多个不同表现形式的能力。在不修改程序代码的情况下改变程序运行时绑定的代码。 - 实现多态的三要素:继承、重写、父类引用指向子类对象。 - 静态多态性:通过重载实现,相同的方法有不同的參数列表,可以根据参数的不同,做出不同的处理。 - 动态多态性:在子类中重写父类的方法。运行期间判断所引用对象的实际类型,根据其实际类型调用相应的方法。 -- 抽象。把客观事物用代码抽象出来。 - -### 多态怎么实现 - -Java提供了编译时多态和运行时多态两种多态机制。编译时多态通过重载实现,根据传入参数不同调用不同的方法。运行时多态通过重写来实现,在子类中重写父类的方法,运行期间判断所引用对象的实际类型,根据其实际类型调用相应的方法。 - -## 类与对象 - -**类class**对一类事物的描述,是抽象的、概念上的定义。类的结构包括属性和方法。 - -```java -public class Person { - //属性 - private int age; - private String name; - - //构造方法 - public Person(int age, String name) { - this.age = age; - this.name = name; - } -} -``` - -对象是实际存在的该类事物的个体,也称为实例。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - public static void main(String[] args) { - //p为对象 - Person p = new Person(18, "程序员大彬"); - } -} -``` - -在Java中,万物皆对象,一切事物都可以看做对象。上述代码通过new关键字,创建了Person对象,p为对象的引用,p指向所创建的Person对象的内存地址。 - -## 属性 - -属性用来描述对象的状态信息,通常以变量的形式进行定义。变量分为成员变量和局部变量。 - -在类中,方法体之外定义的变量称为成员变量: - -- 成员变量定义在类中,在整个类中都可以被访问 -- 成员变量分为类变量和实例变量,实例变量存在于每个对象所在的堆内存中。实例变量要创建对象后才能访问。 -- 成员变量有默认初始化值 -- 成员变量的权限修饰符可以指定 - -定义在方法内,代码块内的变量称为局部变量: - -- 局部变量存在于栈内存中 -- 局部变量作用范围结束,变量的内存空间回自动释放 -- 局部变量没有默认值,每次必须显示初始化 -- 局部变量声明时不指定权限修饰符 - -## 方法 - -描述的是对象的动作信息,方法也称为函数。 - -### 普通方法 - -普通通方法的语法结构: - -```java -[修饰符列表] 返回值类型 方法名(形参列表){ - //方法体 -} -``` - -定义方法可以将功能代码进行封装。便于该功能进行复用。方法只有被调用才会被执行。 - -### 构造方法 - -构造方法是一种比较特殊的方法,通过构造方法可以创建对象以及初始化实例变量。实例变量没有手动赋值的时候,系统会赋默认值。 - -```java -public class Person { - //属性 - private int age; - private String name; - - //构造方法 - public Person(int age, String name) { - this.age = age; - this.name = name; - } -} -``` - -## 方法重载 - -同个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载。参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。 - -重载是面向对象的一个基本特性。 - -```java -public class OverrideTest { - void setPerson() { } - - void setPerson(String name) { - //set name - } - - void setPerson(String name, int age) { - //set name and age - } -} -``` - -## 方法重写 - -方法的重写描述的是父类和子类之间的。当父类的功能无法满足子类的需求,可以在子类对方法进行重写。 - -方法重写时, 方法名与形参列表必须一致。 - -如下代码,Person为父类,Student为子类,在Student中重写了dailyTask方法。 - -```java -public class Person { - private String name; - - public void dailyTask() { - System.out.println("work eat sleep"); - } -} - - -public class Student extends Person { - @Override - public void dailyTask() { - System.out.println("study eat sleep"); - } -} -``` - -## 初始化顺序 - -Java中类初始化顺序: - -1. 静态属性,静态代码块。 -2. 普通属性,普通代码块。 -3. 构造方法。 - -```java -public class LifeCycle { - // 静态属性 - private static String staticField = getStaticField(); - - // 静态代码块 - static { - System.out.println(staticField); - System.out.println("静态代码块初始化"); - } - - // 普通属性 - private String field = getField(); - - // 普通代码块 - { - System.out.println(field); - System.out.println("普通代码块初始化"); - } - - // 构造方法 - public LifeCycle() { - System.out.println("构造方法初始化"); - } - - // 静态方法 - public static String getStaticField() { - String statiFiled = "静态属性初始化"; - return statiFiled; - } - - // 普通方法 - public String getField() { - String filed = "普通属性初始化"; - return filed; - } - - public static void main(String[] argc) { - new LifeCycle(); - } - - /** - * 静态属性初始化 - * 静态代码块初始化 - * 普通属性初始化 - * 普通代码块初始化 - * 构造方法初始化 - */ -} -``` - -# 接口和抽象类 - -Java中接口和抽象类的定义语法分别为interface与abstract关键字。 - -## 抽象类 - -首先了解一下抽象方法。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的格式为: - -```java -abstract void method(); -``` - -抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有未实现的方法,所以不能用抽象类创建对象。 - -抽象类的特点: - -- 抽象类不能被实例化只能被继承; -- 包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法; -- 抽象类中的抽象方法的修饰符只能为public或者protected,默认为public。 - -## 接口 - -接口对行为的抽象。在Java中,定一个接口的形式如下: - -```java -public interface InterfaceName { -} -``` - -接口中可以含有变量和方法。 - -**接口的特点:** - -- 接口中的变量会被隐式指定为public static final类型,而方法会被隐式地指定为public abstract类型; -- 接口中的方法必须是抽象方法,所有的方法不能有具体的实现; -- 一个类可以实现多个接口。 - -**接口的用处** - -接口是对行为的抽象,通过接口可以实现不相关类的相同行为。通过接口可以知道一个类具有哪些行为特性。 - -## 接口与抽象类区别 - -- 语法层面上 - 1)抽象类可以有方法实现,而接口的方法中只能是抽象方法; - 2)抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型; - 3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法; - 4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。 - -- 设计层面上的区别 - 1)抽象层次不同。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口只是对类行为进行抽象。继承抽象类是一种"是不是"的关系,而接口实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是具备不具备的关系,比如鸟是否能飞。 - 2) 继承抽象类的是具有相似特点的类,而实现接口的却可以不同的类。 - - 门和警报的例子: - - ```java - class AlarmDoor extends Door implements Alarm { - //code - } - - class BMWCar extends Car implements Alarm { - //code - } - ``` - -# 反射 - -Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,并且能改变它的属性。 - -作用:可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等。需要注意的是反射使用不当会造成很高的资源消耗! - -## Class类 - -在Java中,每定义一个Java class实体都会产生一个Class对象。这个Class对象用于表示这个类的类型信息。 - -获取Class对象的三种方式: - -```java -//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object -// 类型的对象,而我不知道你具体是什么类,用这种方法 -  Person p1 = new Person(); -  Class c1 = p1.getClass(); - -//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高 -// 这说明任何一个类都有一个隐含的静态成员变量 class -  Class c2 = Person.class; - -//3、通过 Class 对象的 forName() 静态方法来获取,用的最多, -// 但可能抛出 ClassNotFoundException 异常 -  Class c3 = Class.forName("com.ys.reflex.Person"); -``` - -Class 类提供了一些方法,可以获取成员变量、成员方法、接口、超类、构造方法: - -```java -  getName():获得类的完整名字。 -  getFields():获得类的public类型的属性。 -  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类 -  getMethods():获得类的public类型的方法。 -  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类 -  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。 -  getConstructors():获得类的public类型的构造方法。 -  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。 -  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。 -``` - -## Field类 - -Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。 - -![field-method](http://img.dabin-coder.cn/image/field-method.png) - -## Method类 - -Method类位于 java.lang.reflect 包中,主要用于在程序运行状态中,动态地获取方法信息。 - -Method类常用的方法: - -1. getAnnotation(Class annotationClass):如果该方法对象存在指定类型的注解,则返回该注解,否则返回null。 -2. getName():返回方法对象名称。 -3. isAnnotationPresent(Class annotationClass):如果该方法对象上有指定类型的注解,则返回true,否则为false。 -4. getDeclaringClass ():返回该方法对象表示的方法所在类的Class对象。 -5. getParameters():返回一个参数对象数组,该数组表示该方法对象的所有参数。 -6. getReturnType():返回一个Class对象,该Class对象表示该方法对象的返回对象,会擦除泛型。 - -# 泛型 - -泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。编译时会进行类型擦除。在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。 - -## 泛型类 - -泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。 - -泛型类示例: - -```java -//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 -//在实例化泛型类时,必须指定T的具体类型 -public class Generic{ - //key这个成员变量的类型为T,T的类型由外部指定 - private T key; - - public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定 - this.key = key; - } - - public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 - return key; - } -} -``` - -泛型类的使用: - -```java -@Slf4j -public class GenericTest { - public static void main(String[] args) { - //泛型的类型参数只能是类类型(包括自定义类),不能是简单类型 - //传入的实参类型需与泛型的类型参数类型相同,即为Integer. - Generic genericInteger = new Generic(666); - - //传入的实参类型需与泛型的类型参数类型相同,即为String. - Generic genericString = new Generic("程序员大彬"); - log.info("泛型测试: key is {}", genericInteger.getKey()); - log.info("泛型测试: key is {}", genericString.getKey()); - } - - /** - * output - * 23:51:55.519 [main] INFO com.tyson.generic.GenericTest - 泛型测试: key is 666 - * 23:51:55.526 [main] INFO com.tyson.generic.GenericTest - 泛型测试: key is 程序员大彬 - */ -} -``` - -## 泛型接口 - -泛型接口与泛型类的定义及使用基本相同。 - -```java -//定义一个泛型接口 -public interface Generator { - public T next(); -} -``` - -## 泛型方法 - -泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。 - -```java -@Slf4j -public class GenericMethod { - - /** - * 泛型方法的基本介绍 - * @param t 传入的泛型实参 - * @return T 返回值为T类型 - * 说明: - * 1)public 与 返回值中间非常重要,可以理解为声明此方法为泛型方法。 - * 2)只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。 - * 3)表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。 - * 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。 - */ - public void genericMethod(T t) { - log.info(t.toString()); - } - - public static void main(String[] args) { - GenericMethod genericMethod = new GenericMethod(); - genericMethod.genericMethod("程序员大彬"); - genericMethod.genericMethod(666); - } - - /** - * output - * 23:59:11.906 [main] INFO com.tyson.generic.GenericMethod - 程序员大彬 - * 23:59:11.912 [main] INFO com.tyson.generic.GenericMethod - 666 - */ -} -``` - - - -# Exception - -在 JAVA 语言中,将程序执行中发生的不正常情况称为异常。异常是程序经常会出现的情况,发现错误的最佳时机是在编译阶段,也就是运行程序之前。 - -所有异常都继承了 Throwable。 - -## Throwable - -Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类: - -![exception](http://img.dabin-coder.cn/image/exception.png) - -- Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。 - - 栈溢出:如下代码递归调用main,最终会抛出StackOverflowError。 - - ```java - public class Test { - public static void main(String[] args) { - main(args); - } - /** - * Exception in thread "main" java.lang.StackOverflowError - */ - } - ``` - - 内存溢出OOM:下面的代码中,新建了一个数组,数组长度是 1G,又因为是 Integer 包装类型,一个元素占 4 个字节,所以,这个数组占用内存 4GB。最后,堆内存空间不足,抛出了 OOM。 - - ```java - public class Test { - public static void main(String[] args) { - Integer[] arr = new Integer[1024 * 1024 * 1024]; - } - /** - * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space - */ - } - ``` - -- Exception:其它因编程错误或偶然的外在因素导致的一般性问题。可以在代码中进行处理。如:空指针异常、数组下标越界等。 - -unchecked exception包括RuntimeException和Error类,其他所有异常称为检查(checked)异常。 - -运行时异常和非运行时异常(checked)的区别: - -1. RuntimeException由程序错误导致,应该修正程序避免这类异常发生。 -2. checked Exception由具体的环境(读取的文件不存在或文件为空或sql异常)导致的异常。必须进行处理,不然编译不通过,可以catch或者throws。 - -## 常见的Exception - -常见的RuntimeException: - -```java -ClassCastException //类型转换异常 -IndexOutOfBoundsException //数组越界异常 -NullPointerException //空指针 -ArrayStoreException //数组存储异常 -NumberFormatException //数字格式化异常 -ArithmeticException //数学运算异常 -``` - -unchecked Exception: - -``` -NoSuchFieldException //反射异常,没有对应的字段 -ClassNotFoundException //类没有找到异常 -IllegalAccessException //安全权限异常,可能是反射时调用了private方法 -``` - -## 关键字 - -- **throw**:用于抛出一个具体的异常对象。 - -- **throws**:用在方法签名中,用于声明该方法可能抛出的异常。子类方法抛出的异常范围更加小,或者根本不抛异常。 - -- **try**:用于监听。将可能抛出异常的代码放在try语句块之中,当try语句块内发生异常时,异常就被抛出。 -- **catch**:用于捕获异常。 -- **finally**:finally语句块总是会被执行。它主要用于回收在try块里打开的资源(如数据库连接、网络连接和磁盘文件)。 - -如下代码示例,除以0抛出异常,发生异常之后的代码不会执行,直接跳到catch语句块执行,最后执行finally语句块。 - -```java -public class ExceptionTest { - public static void main(String[] args) { - try { - int i = 1 / 0; - System.out.println(i + 1); - } catch (Exception e) { - System.out.println(e.getMessage()); - } finally { - System.out.println("run finally..."); - } - } - /** - * / by zero - * run finally... - */ -} -``` - - - -# IO流 - -Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 - -![io](http://img.dabin-coder.cn/image/io.jpg) - -> 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336) - -## InputStream 和 OutputStream - -InputStream 用来表示那些从不同数据源产生输入的类。这些数据源包括:1.字节数组;2.String 对象;3.文件;4.管道;5.一个由其他种类的流组成的序列。 - -InputStream 类有一个抽象方法:`abstract int read()`,这个方法将读入并返回一个字节,或者在遇到输入源结尾时返回-1。 - -OutputStream 决定了输出所要去的目标:字节数组、文件或管道。OutputStream 的 `abstract void write(int b)` 可以向某个输出位置写出一个字节。 - -read() 和 write() 方法在执行时都将阻塞,等待数据被读入或者写出。 - -常用的字节流有FileInputStream、FileOutputStream、ObjectInputStream、ObjectOutputStream。 - -## Reader 和 Writer - -字符流是由通过字节流转换得到的,转化过程耗时,而且容易出现乱码问题。I/O 流提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。 - -```java -abstract int read(); -abstract void write(char c); -``` - -## 字符流和字节流的转换 - -InputStreamReader:字节到字符的转换,可对读取到的字节数据经过指定编码转换成字符。 - -OutputStreamWriter:字符到字节的转换,可对读取到的字符数据经过指定编码转换成字节。 - -## 同步异步 - -同步:发出一个调用时,在没有得到结果之前,该调用就不返回。 - -异步:在调用发出后,被调用者返回结果之后会通知调用者,或通过回调函数处理这个调用。 - -## 阻塞非阻塞 - -阻塞和非阻塞关注的是线程的状态。 - -阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会恢复运行。 - -非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 - -> 举个例子,理解下同步、阻塞、异步、非阻塞的区别: -> -> 同步就是烧开水,要自己来看开没开;异步就是水开了,然后水壶响了通知你水开了(回调通知)。阻塞是烧开水的过程中,你不能干其他事情,必须在旁边等着;非阻塞是烧开水的过程里可以干其他事情。 - -## BIO - -同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。 - -![bio](http://img.dabin-coder.cn/image/bio.png) - -## NIO - -NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 - -![nio](http://img.dabin-coder.cn/image/nio.png) - -NIO与IO区别: - -- IO是面向流的,NIO是面向缓冲区的; -- IO流是阻塞的,NIO流是不阻塞的; -- NIO有选择器,而IO没有。 - -Buffer:Buffer用于和Channel交互。从Channel中读取数据到Buffer里,从Buffer把数据写入到Channel。 - -Channel:NIO 通过Channel(通道) 进行读写。通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。 - -Selector:使用更少的线程来就可以来处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销。 - -## AIO - -异步非阻塞 IO。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。 - -## BIO/NIO/AIO区别 - -同步阻塞IO : 用户进程发起一个IO操作以后,必须等待IO操作的真正完成后,才能继续运行。 - -同步非阻塞IO: 客户端与服务器通过Channel连接,采用多路复用器轮询注册的Channel。提高吞吐量和可靠性。用户进程发起一个IO操作以后,可做其它事情,但用户进程需要轮询IO操作是否完成,这样造成不必要的CPU资源浪费。 - -异步非阻塞IO: 非阻塞异步通信模式,NIO的升级版,采用异步通道实现异步通信,其read和write方法均是异步方法。用户进程发起一个IO操作,然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知。类比Future模式。 - - - -# ThreadLocal -线程本地变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程。 - -## 原理 - -每个线程都有一个ThreadLocalMap(ThreadLocal内部类),Map中元素的键为ThreadLocal,而值对应线程的变量副本。 - -![image-20200715234257808](../img/threadlocal.png) - -调用threadLocal.set()-->调用getMap(Thread)-->返回当前线程的ThreadLocalMap-->map.set(this, value),this是ThreadLocal - -```java -public void set(T value) { - Thread t = Thread.currentThread(); - ThreadLocalMap map = getMap(t); - if (map != null) - map.set(this, value); - else - createMap(t, value); -} - -ThreadLocalMap getMap(Thread t) { - return t.threadLocals; -} - -void createMap(Thread t, T firstValue) { - t.threadLocals = new ThreadLocalMap(this, firstValue); -} -``` -调用get()-->调用getMap(Thread)-->返回当前线程的ThreadLocalMap-->map.getEntry(this),返回value - -```java - public T get() { - Thread t = Thread.currentThread(); - ThreadLocalMap map = getMap(t); - if (map != null) { - ThreadLocalMap.Entry e = map.getEntry(this); - if (e != null) { - @SuppressWarnings("unchecked") - T result = (T)e.value; - return result; - } - } - return setInitialValue(); - } -``` - -threadLocals的类型ThreadLocalMap的键为ThreadLocal对象,因为每个线程中可有多个threadLocal变量,如longLocal和stringLocal。 - -``` -public class ThreadLocalDemo { - ThreadLocal longLocal = new ThreadLocal<>(); - - public void set() { - longLocal.set(Thread.currentThread().getId()); - } - public Long get() { - return longLocal.get(); - } - - public static void main(String[] args) throws InterruptedException { - ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo(); - threadLocalDemo.set(); - System.out.println(threadLocalDemo.get()); - - Thread thread = new Thread(() -> { - threadLocalDemo.set(); - System.out.println(threadLocalDemo.get()); - } - ); - - thread.start(); - thread.join(); - - System.out.println(threadLocalDemo.get()); - } -} -``` -ThreadLocal 并不是用来解决共享资源的多线程访问的问题,因为每个线程中的资源只是副本,并不共享。因此ThreadLocal适合作为线程上下文变量,简化线程内传参。 - -## 内存泄漏 - -每个Thread都有⼀个ThreadLocalMap的内部属性,map的key是ThreaLocal,定义为弱引用,value是强引用类型。GC的时候会⾃动回收key,而value的回收取决于Thread对象的生命周期。一般会通过线程池的方式复用Thread对象节省资源,这也就导致了Thread对象的生命周期比较长,这样便一直存在一条强引用链的关系:Thread --> ThreadLocalMap-->Entry-->Value,随着任务的执行,value就有可能越来越多且无法释放,最终导致内存泄漏。 - -![image-20200715235804982](../img/threadlocal-oom.png) - -解决⽅法:每次使⽤完ThreadLocal就调⽤它的remove()⽅法,手动将对应的键值对删除,从⽽避免内存泄漏。 - -```java -currentTime.set(System.currentTimeMillis()); -result = joinPoint.proceed(); -Log log = new Log("INFO",System.currentTimeMillis() - currentTime.get()); -currentTime.remove(); -``` - -## 使用场景 - -ThreadLocal 适用场景:每个线程需要有自己单独的实例,且需要在多个方法中共享实例,即同时满足实例在线程间的隔离与方法间的共享。比如Java web应用中,每个线程有自己单独的 Session 实例,就可以使用ThreadLocal来实现。 - - - -# 线程安全类 - -线程安全:代码段在多线程下执行和在单线程下执行能获得一样的结果。 -线程安全类:线程安全的类其方法是同步的,每次只能有一个线程访问,效率较低。 -- vector:比arraylist多了个同步化机制,效率较低 -- stack:堆栈类,继承自vector -- hashtable:hashtable不允许插入空值,hashmap允许 -- enumeration:枚举,相当于迭代器 -- StringBuffer - -Iterator和Enumeration的重要区别: -- Enumeration为vector/hashtable等类提供遍历接口,Iterator为ArrayList/HashMap提供遍历接口。 -- Enumeration只能读集合中的数据,不能删除。 -- Enumeration是先进后出,而Iterator是先进先出。 -- Enumeration不支持fast-fail机制,不会抛ConcurrentModificationException。 - - - -# 常见操作 - -## 排序 - -数组 - -```java -Arrays.sort(jdArray, (int[] jd1, int[] jd2) -> {return jd1[0] - jd2[0];}); -``` - - - -## 数组操作 - -数组遍历 - -```java -Arrays.asList(array).stream().forEach(System.out::println); -``` - -数组排序 - -```java -Arrays.sort(players,(String s1,String s2)->(s1.compareTo(s2))); -``` - -集合转数组: - -```java -//List --> Array -List list = new ArrayList<>(); -list.add(1); -Integer[] arr = list.toArray(new Integer[list.size()]); -``` - -数组转集合: - -```java -//Array --> List -String[] array = {"java", "c"}; -List list = Arrays.asList(array); -``` - -该方法存在一定的弊端,返回的list是Arrays里面的一个静态内部类(数组的视图),对list的操作会反映在原数组上,而且list是定长的,不支持add、remove操作。 - -该ArrayList并非java.util.ArrayList,而是 java.util.Arrays.ArrayList.ArrayList(T[]),该类并未实现add、remove方法,因此在使用时存在局限性。 - -代替方案: - -```java -List list = new ArrayList(Arrays.asList(array)); -``` - - - -## 拷贝 - -### 数组拷贝 - -```java -System.arraycopy(Object src, int srcPos, Object dest, int desPos, int length) -Arrays.copyOf(originalArr, length) //length为拷贝的长度 -Arrays.copyOfRange(originalArr, from, to); //from包含,to不包含 -``` - -二维数组拷贝: - -```java -int[][] arr = {{1, 2},{3, 4}}; -int[][] newArr = new int[2][2]; -for(int i = 0; i < arr.length; i++) { - newArr[i] = arr[i].clone(); -} -``` - -### 对象拷贝 - -实现对象克隆有两种方式: - -1. 实现Cloneable接口并重写Object类中的clone()方法; - -2. 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。 - -实现cloneable接口,重写clone方法。 - -```java -public class Dog implements Cloneable { - private String id; - private String name; - - public Dog(String id, String name) { - this.id = id; - this.name = name; - } - - // 省略 getter 、 setter 以及 toString 方法 - - @Override - public Dog clone() throws CloneNotSupportedException { - Dog dog = (Dog) super.clone(); - - return dog; - } -} -``` - -使用: - -```java -Dog dog1 = new Dog("1", "Dog1"); -Dog dog2 = dog1.clone(); - -dog2.setName("Dog1 changed"); - -System.out.println(dog1); // Dog{id='1', name='Dog1'} -System.out.println(dog2); // Dog{id='1', name='Dog1 changed'} -``` - -如果一个类引用了其他类,引用的类也需要实现cloneable接口,比较麻烦。可以将所有的类都实现Serializable接口,通过序列化反序列化实现对象的深度拷贝。 - -## 序列化 - -序列化:把内存中的对象转换为字节序列的过程称为对象的序列化。 - -### 什么情况下需要序列化? - -当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; -当你想在网络上传送对象的时候; - -### 如何实现序列化 - -实现Serializable接口即可。序列化的时候(如objectOutputStream.writeObject(user)),会判断user是否实现了Serializable(obj instanceof Serializable),如果对象没有实现Serializable接口,在序列化的时候会抛出NotSerializableException异常。 - -### serialVersionUID - -serialVersionUID 是 Java 为每个序列化类产生的版本标识,可用来保证在反序列时,发送方发送的和接受方接收的是可兼容的对象。类的serialVersionUID的默认值完全依赖于Java编译器的实现。当完成序列化之后,此时对对象进行修改,由编译器生成的serialVersionUID会改变,这样反序列化的时候会报错。可以在序列化对象中添加 serialVersionUID,固定版本号,这样即便序列化对象做了修改,版本都是一致的,就能进行反序列化了。 - -## 遍历 - -### fast-fail - -fast-fail是Java集合的一种错误机制。当多个线程对同一个集合进行操作时,就有可能会产生fast-fail事件。 -例如:当线程a正通过iterator遍历集合时,另一个线程b修改了集合的内容,此时modCount(记录集合操作过程的修改次数)会加1,不等于expectedModCount,那么线程a访问集合的时候,就会抛出ConcurrentModificationException,产生fast-fail事件。边遍历边修改集合也会产生fast-fail事件。 - -解决方法: - -- 使用Colletions.synchronizedList方法或在修改集合内容的地方加上synchronized。这样的话,增删集合内容的同步锁会阻塞遍历操作,影响性能。 -- 使用CopyOnWriteArrayList来替换ArrayList。在对CopyOnWriteArrayList进行修改操作的时候,会拷贝一个新的数组,对新的数组进行操作,操作完成后再把引用移到新的数组。 - -### fail-safe - -fail-safe允许在遍历的过程中对容器中的数据进行修改。因为采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先copy原有集合内容,在拷贝的集合上进行遍历。 - -由于迭代时是对原集合的拷贝的值进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发`ConcurrentModificationException`。 - -java.util.concurrent包下的容器都是安全失败的,可以在多线程下并发使用。常见的的使用fail-safe方式遍历的容器有`ConcerrentHashMap`和`CopyOnWriteArrayList`等。 - -fail-safe机制有两个问题:(1)需要复制集合,产生大量的无效对象,内存开销大;(2)不能访问到修改后的内容 。 - -### 移除集合元素 - -遍历时安全的移除集合中的元素,要使用遍历器Iterator和iterator.remove()方法。next()必须在remove()之前调用。 - -``` -ArrayList list = new ArrayList(Arrays.asList("a","b","c","d")); -Iterator iter = list.iterator(); -while(iter.hasNext()){ - String s = iter.next(); - if(s.equals("a")){ - iter.remove(); - } -} -``` - - - diff --git "a/Java/Java\345\271\266\345\217\221\347\274\226\347\250\213.md" "b/Java/Java\345\271\266\345\217\221\347\274\226\347\250\213.md" deleted file mode 100644 index 5381c9e..0000000 --- "a/Java/Java\345\271\266\345\217\221\347\274\226\347\250\213.md" +++ /dev/null @@ -1,392 +0,0 @@ - - - - -- [共享对象](#%E5%85%B1%E4%BA%AB%E5%AF%B9%E8%B1%A1) - - [非原子的64位操作](#%E9%9D%9E%E5%8E%9F%E5%AD%90%E7%9A%8464%E4%BD%8D%E6%93%8D%E4%BD%9C) - - [this 引用逸出](#this-%E5%BC%95%E7%94%A8%E9%80%B8%E5%87%BA) - - [安全的对象构造过程](#%E5%AE%89%E5%85%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%9E%84%E9%80%A0%E8%BF%87%E7%A8%8B) - - [ThreadLocal](#threadlocal) -- [容器](#%E5%AE%B9%E5%99%A8) - - [间接的迭代操作](#%E9%97%B4%E6%8E%A5%E7%9A%84%E8%BF%AD%E4%BB%A3%E6%93%8D%E4%BD%9C) - - [ConcurrentHashMap](#concurrenthashmap) - - [同步工具类](#%E5%90%8C%E6%AD%A5%E5%B7%A5%E5%85%B7%E7%B1%BB) - - [信号量](#%E4%BF%A1%E5%8F%B7%E9%87%8F) - - [缓存系统](#%E7%BC%93%E5%AD%98%E7%B3%BB%E7%BB%9F) -- [任务执行](#%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C) - - [Executor 框架](#executor-%E6%A1%86%E6%9E%B6) - - [延迟任务](#%E5%BB%B6%E8%BF%9F%E4%BB%BB%E5%8A%A1) - - [携带结果的 Callable 和 Future](#%E6%90%BA%E5%B8%A6%E7%BB%93%E6%9E%9C%E7%9A%84-callable-%E5%92%8C-future) - - [为任务设置时限](#%E4%B8%BA%E4%BB%BB%E5%8A%A1%E8%AE%BE%E7%BD%AE%E6%97%B6%E9%99%90) - - [取消与关闭](#%E5%8F%96%E6%B6%88%E4%B8%8E%E5%85%B3%E9%97%AD) - - [任务取消](#%E4%BB%BB%E5%8A%A1%E5%8F%96%E6%B6%88) - - [阻塞和中断](#%E9%98%BB%E5%A1%9E%E5%92%8C%E4%B8%AD%E6%96%AD) - - - -## 共享对象 - -### 非原子的64位操作 - -在多线程程序使用共享且可变的64位数据类型的变量是不安全的。 - - - -### this 引用逸出 - -参考自:[this 引用逸出](https://www.cnblogs.com/whatisjava/archive/2013/05/29/3106336.html) - -实例化 ThisEscape 对象时,会调用 source 的 registerListener 方法,这时便启动了一个线程,而且这个线程持有了 ThisEscape 对象(调用了对象的 doSomething 方法),但此时 ThisEscape 对象却没有实例化完成(还没有返回一个引用),所以我们说,此时造成了一个 this 引用逸出,即还没有完成的实例化 ThisEscape 对象的动作,却已经暴露了对象的引用。其他线程访问还没有构造好的对象,可能会造成意料不到的问题。 - -```java -public class ThisEscape { -  public ThisEscape(EventSource source) { -    source.registerListener(new EventListener() { -      public void onEvent(Event e) { -        doSomething(e); -      } -    }); -  } - -  void doSomething(Event e) { -  } - -  interface EventSource { -    void registerListener(EventListener e); -  } - -  interface EventListener { -    void onEvent(Event e); -  } - -  interface Event { -  } -} -``` - -### 安全的对象构造过程 - -使用工厂方法来防止 this 引用在构造过程中逸出。 - -```java -public class SafeListener { -  private final EventListener listener; - -  private SafeListener() { -    listener = new EventListener() { -      public void onEvent(Event e) { -        doSomething(e); -      } -    }; -  } - -  public static SafeListener newInstance(EventSource source) { -    SafeListener safe = new SafeListener(); -    source.registerListener(safe.listener); -    return safe; -  } - -  void doSomething(Event e) { -  } - -  interface EventSource { -    void registerListener(EventListener e); -  } - -  interface EventListener { -    void onEvent(Event e); -  } - -  interface Event { -  } - } -``` - -构造好了 SafeListener 对象(通过构造器构造)之后,才启动了监听线程,也就确保了构造完成之后再使用SafeListener对象。 - -### ThreadLocal - -当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 -每个线程都有一个ThreadLocalMap(ThreadLocal内部类),Map中元素的键为ThreadLocal,而值对应线程的变量副本。 -调用set()-->调用getMap(Thread)-->返回当前线程的ThreadLocalMap-->map.set(this, value),this是ThreadLocal。 -调用get()-->调用getMap(Thread)-->返回当前线程的ThreadLocalMap-->map.getEntry(this),返回value。 - -```java -public class ThreadLocalDemo { - ThreadLocal longLocal = new ThreadLocal<>(); - - public void set() { - longLocal.set(Thread.currentThread().getId()); - } - - public String get() { - return Thread.currentThread().getName() + ": " + longLocal.get(); - } - - public static void main(String[] args) throws InterruptedException { - ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo(); - threadLocalDemo.set(); - System.out.println(threadLocalDemo.get()); - - Thread thread = new Thread(() -> { - threadLocalDemo.set(); - System.out.println(threadLocalDemo.get()); - } - ); - - thread.start(); - thread.join(); - - System.out.println(threadLocalDemo.get()); - } -} -/*output -main: 1 -Thread-0: 11 -main: 1 - */ -``` - -## 容器 - -### 间接的迭代操作 - -调用容器的 toString 方法会迭代容器。容器的 hashcode 和 equals 方法也会间接的进行迭代操作。 - -```java -public class HiddenIterator { - private final Set set = new HashSet<>(); - //... - public void print() { - System.out.println("set: " + set); - } -} -``` - -### ConcurrentHashMap -多线程环境下,使用Hashmap进行put操作会引起死循环。 -CocurrentHashMap利用锁分段技术增加了锁的数目,从而使争夺同一把锁的线程的数目得到控制。 -锁分段技术就是将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 -ConcurrentHashMap调用get的时候不加锁,原因是node数组成员val和指针next是用volatile修饰的,更改后的值会立刻刷新到主存中,保证了可见性,node数组table也用volatile修饰,保证在运行过程对其他线程具有可见性。 - -JDK1.7中的ConcurrentHashmap主要使用Segment来实现减小锁粒度,把HashMap分割成若干个Segment,在put的时候需要锁住Segment,get时候不加锁,使用volatile来保证可见性,当要统计size时,比较统计前后modCount是否发生变化。如果没有变化,则直接返回size。否则,需要依次锁住所有的Segment来计算。jdk1.7中ConcurrentHashmap中,当长度过长碰撞会很频繁,链表的增改删查操作都会消耗很长的时间,影响性能。 - -jdk1.8不采用segment而采用Node,锁住Node来实现减小锁粒度。当链表长度过长时,Node会转换成TreeNode。 - -put 操作会对当前的table进行无条件自循环直到put成功,可以分成以下流程来概述: -1)如果没有初始化就先调用 initTable 方法来进行初始化过程 -2)如果没有hash冲突就直接CAS插入 -3)如果还在进行扩容操作就先进行扩容 -4)如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入 - -5)如果该链表的数量大于阈值8,就要先转换成黑红树的结构 -6)如果添加成功就调用 addCount 方法统计size,并且检查是否需要扩容 - -### 同步工具类 - -#### 信号量 - -信号量 Semaphore 用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。 - -通过信号量实现有界的HashSet: - -```java -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Semaphore; - -public class BoundedHashSet { - private final Set set; - private final Semaphore sem; - - public BoundedHashSet(int bound) { - set = Collections.synchronizedSet(new HashSet<>()); - sem = new Semaphore(bound); - } - - public boolean add(T t) throws InterruptedException { - sem.acquire(); - boolean wasAdded = false; - try { - wasAdded = set.add(t); - return wasAdded; - } finally { - if (!wasAdded) { - sem.release(); - } - } - } - - public boolean remove(Object o) { - boolean wasRemoved = set.remove(o); - if (wasRemoved) { - sem.release(); - } - return wasRemoved; - } -} -``` - -### 缓存系统 - -假设有一个高计算开销的 compute 函数,我们可以将计算结果保存在 Map 中,调用 compute 时先检查 Map 是否存在需要的结果。使用 ConturrentHashMap 可以提高系统的并发能力。假如两个线程同时调用 compute ,则相同的数据会被计算多次,使用 FutureTask 可以避免这个问题。 - -```java -interface Computable { - V compute(A arg) throws InterruptedException; -} - -public class Memorizer implements Computable { - private final ConcurrentMap> cache = new ConcurrentHashMap<>(); - private final Computable c; - public Memorizer(Computable c) { - this.c = c; - } - @Override - public V compute(A arg) throws InterruptedException { - while (true) { - Future f = cache.get(arg); - if (f == null) { - Callable eval = new Callable() { - @Override - public V call() throws InterruptedException { - return c.compute(arg); - } - }; - FutureTask ft = new FutureTask<>(eval); - //先放进缓存,再进行计算;若线程x正在计算某个值,而线程y刚好正在查找这个值,则线程y会等待x的计算结果 - f = cache.putIfAbsent(arg, ft); - //避免两个线程同一时间调用compute计算相同的值 - if (f == null) { - f = ft; - ft.run(); - } - } - try { - return f.get(); - } catch (CancellationException ex) { - cache.remove(arg, f); - } catch (ExecutionException ex) { - ex.printStackTrace(); - } - } - } -} -``` - -## 任务执行 - -### Executor 框架 - -1.5后引入的 Executor 框架的最大优点是把任务的提交和执行解耦。Executor 是任务执行的抽象,,使用 Runnable 或 Callable 来表示任务。 - -```java -public class TaskExecutionWebServer { - private static final int NTHREADS = 100; - private static final Executor exec = Executors.newFixedThreadPool(NTHREADS); - - public static void main(String[] args) throws IOException { - ServerSocket socket = new ServerSocket(80); - while (true) { - final Socket connection = socket.accept(); - Runnable task = new Runnable() { - @Override - public void run() { - //handleRequest(connection); - } - }; - //将任务提交到工作队列 - exec.execute(task); - } - } -} -``` - - - -#### 延迟任务 - -Timer 类负责延迟任务和周期任务,然后 Timer 存在一些缺陷。现在一般使用 ScheduledThreadPoolExecutor 来代替它,通过 ScheduledThreadPoolExecutor 的构造函数或者 Executors.newScheduledThreadPool 工厂方法来创建该类的对象(不推荐,见阿里编码规范)。 - -#### 携带结果的 Callable 和 Future - -当提交一个Callable对象给ExecutorService,将得到一个Future对象,调用Future对象的get方法等待执行结果就好了。而 get 方法的行为取决于任务的状态(尚未开始、正在运行、已完成)。任务已完成,那么 get 会立即返回或者抛出异常;任务没有完成,get 将一直阻塞直到任务完成;任务抛出异常,那么 get 会将异常封装成 ExecutionException 重新抛出;任务被取消,那么 get 将抛出 CancellationExeception,此时通过 getCause 可以获取被封装的初始异常。 - - -#### 为任务设置时限 - -Future.get() 支持时间限制,当结果可用时,它将直接返回,如果在指定时间内没有计算出结果,那么将抛出 TimeoutException。 - -```java -Page renderPageWithAd() throws InterruptedException { - long endNanos = System.nanoTime() + TIME_BUDGET; - Future f = exec.submit(new FetchAdTask()); - //等待广告同时显示页面 - Page page = renderPageBody(); - Ad ad; - try { - //只等待指定的时间 - long timeLeft = endNanos - System.nanoTime(); - ad = f.get(timeLeft, NANOSECONDES); - } catch (ExecutionException e) { - ad = DEFAULT_AD; - } catch (TimeoutException e) { - ad = DEFAULT_AD; - //超时则取消任务 - f.cancel(true); - } - page.setAd(ad); - return page; -} -``` - -### 取消与关闭 - -Java 没有提供任何机制来安全的终止线程,但它提供了中断机制,这是一种协作机制,能够使一个线程终止另一个线程的当前工作。 - - -#### 任务取消 - -给任务设置某个“请求取消”的标志,而任务将定期查看该标志,如果设置了该标志,那么任务将提前结束。 - -#### 阻塞和中断 - -如果任务中调用了一个阻塞方法,那么任务有可能永远不会检查取消标志,因此永远不会结束。通过中断机制可以避免这个问题。一些特殊的阻塞库的方法支持中断。 - -线程可能受到阻塞的原因:等待 IO 操作,等待获得锁,等待从 Thread.sleep 方法醒来,或是等待另一个线程的计算结果。阻塞方法可能会抛出 InterruptedException。当在代码中调用了一个会抛出 InterruptedException 的方法时,这个方法也就变成了阻塞方法,需要处理中断异常。阻塞方法必须等待某个不受它控制的事件发生后才能继续执行。 - -每个线程都有一个 boolean 类型的中断状态,当中断线程时,这个线程的中断状态会被设置为 true。在 Thread 中包含了中断线程以及查询线程中断状态的方法。 - -```java -public class Thread { - public void interrupt() {} //中断目标线程 - public boolean isInterrupted() {} //返回目标线程的中断状态 - public static boolean interrupted() {}//清除当前线程中断状态的唯一方法,并返回它之前的值 -} -``` - -阻塞方法如 Thread.sleep 和 Object.wait 等,都会检查线程何时中断,并且在发生中断时提前返回。它们在响应中断时执行的操作包含:清除中断状态,抛出 InterruptedException,表示阻塞操作由于中断而提前结束。**调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息**。对中断操作的正确理解是:它并不会真正的中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻自己中断。 - -阻塞方法必须处理对中断的响应,有两种处理方法: - -1. 传递 InterruptedException 给方法的调用者。 -2. 恢复中断。有时不能抛出 InterruptedException,如代码是 Runnable 一部分时,必须捕获 InterruptedException,并通过调用当前线程上的 interrupt 方法恢复中断状态,这样在高层代码就看到引发了一个中断。 - -```java -public class TaskRunnable implements Runnable { - BlockingQueue queue; - ... - public void run() { - try { - processTask(queue.take()); - } catch (InterruptedException e) { - //恢复被中断的状态,不然会丢失线程被中断的证据 - Thread.currentThread().interrupt(); - } - } -} -``` - - - diff --git "a/Java/Object\347\261\273\345\270\270\347\224\250\346\226\271\346\263\225.md" "b/Java/Object\347\261\273\345\270\270\347\224\250\346\226\271\346\263\225.md" deleted file mode 100644 index e78bb55..0000000 --- "a/Java/Object\347\261\273\345\270\270\347\224\250\346\226\271\346\263\225.md" +++ /dev/null @@ -1,241 +0,0 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [Object常用方法](#object%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95) - - [toString](#tostring) - - [equals](#equals) - - [hashCode](#hashcode) - - [clone](#clone) - - [浅拷贝](#%E6%B5%85%E6%8B%B7%E8%B4%9D) - - [深拷贝](#%E6%B7%B1%E6%8B%B7%E8%B4%9D) - - - -## Object常用方法 - -Java面试经常会出现的一道题目,Object的常用方法。下面给大家整理一下。 - -object常用方法有:toString()、equals()、hashCode()、clone()等。 - -### toString - -默认输出对象地址。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - public static void main(String[] args) { - System.out.println(new Person(18, "程序员大彬").toString()); - } - //output - //me.tyson.java.core.Person@4554617c -} -``` - -可以重写toString方法,按照重写逻辑输出对象值。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - @Override - public String toString() { - return name + ":" + age; - } - - public static void main(String[] args) { - System.out.println(new Person(18, "程序员大彬").toString()); - } - //output - //程序员大彬:18 -} -``` - -### equals - -默认比较两个引用变量是否指向同一个对象(内存地址)。 - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - public static void main(String[] args) { - String name = "程序员大彬"; - Person p1 = new Person(18, name); - Person p2 = new Person(18, name); - - System.out.println(p1.equals(p2)); - } - //output - //false -} -``` - -可以重写equals方法,按照age和name是否相等来判断: - -```java -public class Person { - private int age; - private String name; - - public Person(int age, String name) { - this.age = age; - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (o instanceof Person) { - Person p = (Person) o; - return age == p.age && name.equals(p.name); - } - return false; - } - - public static void main(String[] args) { - String name = "程序员大彬"; - Person p1 = new Person(18, name); - Person p2 = new Person(18, name); - - System.out.println(p1.equals(p2)); - } - //output - //true -} -``` - -### hashCode - -将与对象相关的信息映射成一个哈希值,默认的实现hashCode值是根据内存地址换算出来。 - -```java -public class Cat { - public static void main(String[] args) { - System.out.println(new Cat().hashCode()); - } - //out - //1349277854 -} -``` - -### clone - -java赋值是复制对象引用,如果我们想要得到一个对象的副本,使用赋值操作是无法达到目的的。Object对象有个clone()方法,实现了对 - -象中各个属性的复制,但它的可见范围是protected的。 - -```java -protected native Object clone() throws CloneNotSupportedException; -``` - -所以实体类使用克隆的前提是: - -- 实现Cloneable接口,这是一个标记接口,自身没有方法,这应该是一种约定。调用clone方法时,会判断有没有实现Cloneable接口,没有实现Cloneable的话会抛异常CloneNotSupportedException。 -- 覆盖clone()方法,可见性提升为public。 - -```java -public class Cat implements Cloneable { - private String name; - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - c.name = "程序员大彬"; - Cat cloneCat = (Cat) c.clone(); - c.name = "大彬"; - System.out.println(cloneCat.name); - } - //output - //程序员大彬 -} -``` - -下面介绍下浅拷贝和深拷贝。 - -#### 浅拷贝 - -拷⻉对象和原始对象的引⽤类型引用同⼀个对象。 - -以下例子,Cat对象里面有个Person对象,调用clone之后,克隆对象和原对象的Person引用的是同一个对象,这就是浅拷贝。 - -```java -public class Cat implements Cloneable { - private String name; - private Person owner; - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - Person p = new Person(18, "程序员大彬"); - c.owner = p; - - Cat cloneCat = (Cat) c.clone(); - p.setName("大彬"); - System.out.println(cloneCat.owner.getName()); - } - //output - //大彬 -} -``` - -#### 深拷贝 - -拷贝对象和原始对象的引用类型引用不同的对象。 - -以下例子,在clone函数中不仅调用了super.clone,而且调用Person对象的clone方法(Person也要实现Cloneable接口并重写clone方法),从而实现了深拷贝。可以看到,拷贝对象的值不会受到原对象的影响。 - -```java -public class Cat implements Cloneable { - private String name; - private Person owner; - - @Override - protected Object clone() throws CloneNotSupportedException { - Cat c = null; - c = (Cat) super.clone(); - c.owner = (Person) owner.clone();//拷贝Person对象 - return c; - } - - public static void main(String[] args) throws CloneNotSupportedException { - Cat c = new Cat(); - Person p = new Person(18, "程序员大彬"); - c.owner = p; - - Cat cloneCat = (Cat) c.clone(); - p.setName("大彬"); - System.out.println(cloneCat.owner.getName()); - } - //output - //程序员大彬 -} -``` - diff --git "a/Java/\345\271\266\345\217\221.md" "b/Java/\345\271\266\345\217\221.md" deleted file mode 100644 index 65ea9c9..0000000 --- "a/Java/\345\271\266\345\217\221.md" +++ /dev/null @@ -1,1166 +0,0 @@ - - - - -- [线程池](#%E7%BA%BF%E7%A8%8B%E6%B1%A0) - - [线程池原理](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%8E%9F%E7%90%86) - - [线程池大小](#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E5%B0%8F) - - [关闭线程池](#%E5%85%B3%E9%97%AD%E7%BA%BF%E7%A8%8B%E6%B1%A0) -- [executor框架](#executor%E6%A1%86%E6%9E%B6) - - [简介](#%E7%AE%80%E4%BB%8B) - - [ThreadPoolExecutor实例](#threadpoolexecutor%E5%AE%9E%E4%BE%8B) - - [Runnable和Callable的区别](#runnable%E5%92%8Ccallable%E7%9A%84%E5%8C%BA%E5%88%AB) - - [Future和FutureTask](#future%E5%92%8Cfuturetask) - - [execute()和submit()](#execute%E5%92%8Csubmit) - - [常用的线程池](#%E5%B8%B8%E7%94%A8%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0) - - [FixedThreadPool](#fixedthreadpool) - - [SingleThreadExecutor](#singlethreadexecutor) - - [CachedThreadPool](#cachedthreadpool) - - [ScheduledThreadPoolExecutor](#scheduledthreadpoolexecutor) - - [编码规范](#%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83) -- [JMM](#jmm) -- [进程线程](#%E8%BF%9B%E7%A8%8B%E7%BA%BF%E7%A8%8B) - - [线程状态](#%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81) - - [中断](#%E4%B8%AD%E6%96%AD) - - [常见方法](#%E5%B8%B8%E8%A7%81%E6%96%B9%E6%B3%95) - - [join](#join) - - [yield](#yield) - - [sleep](#sleep) - - [wait()和sleep()的区别](#wait%E5%92%8Csleep%E7%9A%84%E5%8C%BA%E5%88%AB) - - [创建线程的方法](#%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%96%B9%E6%B3%95) -- [线程间通信](#%E7%BA%BF%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1) - - [volatile](#volatile) - - [synchronized](#synchronized) - - [等待通知机制](#%E7%AD%89%E5%BE%85%E9%80%9A%E7%9F%A5%E6%9C%BA%E5%88%B6) -- [锁](#%E9%94%81) - - [synchronized](#synchronized-1) - - [释放锁](#%E9%87%8A%E6%94%BE%E9%94%81) - - [实现原理](#%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86) - - [锁的状态](#%E9%94%81%E7%9A%84%E7%8A%B6%E6%80%81) - - [ReentrantLock](#reentrantlock) - - [原理](#%E5%8E%9F%E7%90%86) - - [ReentrantLock和synchronized区别](#reentrantlock%E5%92%8Csynchronized%E5%8C%BA%E5%88%AB) - - [锁的分类](#%E9%94%81%E7%9A%84%E5%88%86%E7%B1%BB) - - [公平锁与非公平锁](#%E5%85%AC%E5%B9%B3%E9%94%81%E4%B8%8E%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81) - - [共享式与独占式锁](#%E5%85%B1%E4%BA%AB%E5%BC%8F%E4%B8%8E%E7%8B%AC%E5%8D%A0%E5%BC%8F%E9%94%81) - - [悲观锁与乐观锁](#%E6%82%B2%E8%A7%82%E9%94%81%E4%B8%8E%E4%B9%90%E8%A7%82%E9%94%81) - - [CAS](#cas) -- [并发工具](#%E5%B9%B6%E5%8F%91%E5%B7%A5%E5%85%B7) - - [CountDownLatch](#countdownlatch) - - [CyclicBarrier](#cyclicbarrier) - - [CyclicBarrier和CountDownLatch区别](#cyclicbarrier%E5%92%8Ccountdownlatch%E5%8C%BA%E5%88%AB) - - [Semaphore](#semaphore) -- [原子类](#%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [基本类型原子类](#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [数组类型原子类](#%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) - - [引用类型原子类](#%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8E%9F%E5%AD%90%E7%B1%BB) -- [AQS](#aqs) - - [原理](#%E5%8E%9F%E7%90%86-1) -- [Condition](#condition) - - [实现原理](#%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86-1) -- [其他](#%E5%85%B6%E4%BB%96) - - [Daemon Thread](#daemon-thread) -- [参考资料](#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99) - - - -> 首先给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - -## 线程池 - -**使用线程池的好处**: - -- **降低资源消耗**。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 -- **提高响应速度**。当任务到达时,任务可以不需要的等到线程创建就能立即执行。 -- **提高线程的可管理性**。统一管理线程,避免系统创建大量同类线程而导致消耗完内存。 - -``` -public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler); -``` -### 线程池原理 - -创建新的线程需要获取全局锁,通过这种设计可以尽量避免获取全局锁,当 ThreadPoolExecutor 完成预热之后(当前运行的线程数大于等于 corePoolSize),提交的大部分任务都会被放到 BlockingQueue。 - -![](http://img.dabin-coder.cn/image/thread-pool.png) - -ThreadPoolExecutor 的通用构造函数: - -``` -public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler); -``` - -- corePoolSize:当有新任务时,如果线程池中线程数没有达到线程池的基本大小,则会创建新的线程执行任务,否则将任务放入阻塞队列。当线程池中存活的线程数总是大于 corePoolSize 时,应该考虑调大 corePoolSize。 - -- maximumPoolSize:当阻塞队列填满时,如果线程池中线程数没有超过最大线程数,则会创建新的线程运行任务。否则根据拒绝策略处理新任务。非核心线程类似于临时借来的资源,这些线程在空闲时间超过 keepAliveTime 之后,就应该退出,避免资源浪费。 - -- BlockingQueue:存储等待运行的任务。 - -- keepAliveTime:**非核心线程**空闲后,保持存活的时间,此参数只对非核心线程有效。设置为0,表示多余的空闲线程会被立即终止。 - -- TimeUnit:时间单位 - - ```java - TimeUnit.DAYS - TimeUnit.HOURS - TimeUnit.MINUTES - TimeUnit.SECONDS - TimeUnit.MILLISECONDS - TimeUnit.MICROSECONDS - TimeUnit.NANOSECONDS - ``` -- ThreadFactory:每当线程池创建一个新的线程时,都是通过线程工厂方法来完成的。在 ThreadFactory 中只定义了一个方法 newThread,每当线程池需要创建新线程就会调用它。 - - ```java - public class MyThreadFactory implements ThreadFactory { - private final String poolName; - - public MyThreadFactory(String poolName) { - this.poolName = poolName; - } - - public Thread newThread(Runnable runnable) { - return new MyAppThread(runnable, poolName);//将线程池名字传递给构造函数,用于区分不同线程池的线程 - } - } - ``` - -- RejectedExecutionHandler:当队列和线程池都满了时,根据拒绝策略处理新任务。 - - ```java - AbortPolicy:默认的策略,直接抛出RejectedExecutionException - DiscardPolicy:不处理,直接丢弃 - DiscardOldestPolicy:将等待队列队首的任务丢弃,并执行当前任务 - CallerRunsPolicy:由调用线程处理该任务 - ``` - -### 线程池大小 - -如果线程池线程数量太小,当有大量请求需要处理,系统响应比较慢影响体验,甚至会出现任务队列大量堆积任务导致OOM。 - -如果线程池线程数量过大,大量线程可能会同时在争取 CPU 资源,这样会导致大量的上下文切换(cpu给线程分配时间片,当线程的cpu时间片用完后保存状态,以便下次继续运行),从而增加线程的执行时间,影响了整体执行效率。 - -**CPU 密集型任务(N+1)**: 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止某些原因导致的任务暂停(线程阻塞,如io操作,等待锁,线程sleep)而带来的影响。一旦某个线程被阻塞,释放了cpu资源,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。 - -**I/O 密集型任务(2N)**: 系统会用大部分的时间来处理 I/O 操作,而线程等待 I/O 操作会被阻塞,释放 cpu资源,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法:最佳线程数 = CPU核心数 * (1/CPU利用率) = CPU核心数 * (1 + (I/O耗时/CPU耗时)),一般可设置为2N。 - -### 关闭线程池 - -shutdown(): - -将线程池状态置为`SHUTDOWN`,并不会立即停止: - -- 停止接收外部提交的任务 -- 内部正在跑的任务和队列里等待的任务,会执行完 -- 等到第二步完成后,才真正停止 - -shutdownNow(): - -将线程池状态置为`STOP`。企图立即停止,事实上不一定: - -- 跟shutdown()一样,先停止接收外部提交的任务 -- 忽略队列里等待的任务 -- 尝试将正在跑的任务中断(不一定中断成功,取决于任务响应中断的逻辑) -- 返回未执行的任务列表 - - - -## executor框架 - -1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦。当提交一个Callable对象给ExecutorService,将得到一个Future对象,调用Future对象的get方法等待执行结果。Executor框架的内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。 - -### 简介 - -executor框架由3部分组成:任务、任务的执行、异步计算的结果 - -- 任务。需要实现的接口:Runnable和Callable接口。 -- 任务的执行。ExecutorService 是一个接口,用于定义线程池,调用它的 execute(Runnable)或者 submit(Runnable/Callable)执行任务。ExecutorService接口继承于Executor,有两个实现类`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。 -- 异步计算的结果。包括future接口和实现future接口的FutureTask,调用future.get()会阻塞当前线程直到任务完成,future.cancel()可以取消执行任务。 - -### ThreadPoolExecutor实例 - -使用 `ThreadPoolExecutor` 构造函数自定义参数的方式来创建线程池。 - -```java -public class ThreadPoolExecutorDemo { - private static final int CORE_POOL_SIZE = 5; - private static final int MAX_POOL_SIZE = 10; - private static final int QUEUE_CAPACITY = 100; - private static final long KEEP_ALIVE_TIME = 1L; - - public static void main(String[] args) throws ExecutionException, InterruptedException { - ThreadPoolExecutor executor = new ThreadPoolExecutor( - CORE_POOL_SIZE, - MAX_POOL_SIZE, - KEEP_ALIVE_TIME, - TimeUnit.SECONDS, - new ArrayBlockingQueue<>(QUEUE_CAPACITY), - new ThreadPoolExecutor.CallerRunsPolicy() - ); - - for (int i = 0; i < 10; i++) { - Callable worker = () -> { - System.out.println(Thread.currentThread().getName()); - return "ok"; - }; - Future f = executor.submit(worker); - f.get(); - } - executor.shutdown(); - while (!executor.isTerminated()) { - } - System.out.println("Finished all threads"); - } -} -``` - -### Runnable和Callable的区别 - -Runnable 任务执行后不能返回值或者抛出异常。Callable 任务执行后可以返回值或抛出异常。 - -``` -Executors.callable(Runnable task);//runnable转化为callable -ExecutorService.execute(Runnable); -ExecutorService.submit(Runnable/Callable);//submit callable任务有返回值 - -//返回值是泛型参数V -public interface Callable { - V call() throws Exception; -} -``` - -### Future和FutureTask - -Future 可以获取任务执行的结果、取消任务。调用 future.get()会阻塞当前线程直到任务返回结果。 - -```java -public interface Future { - boolean cancel(boolean mayInterruptIfRunning); - - boolean isCancelled(); - - boolean isDone(); - - V get() throws InterruptedException, ExecutionException; - - V get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException; -} -``` - -FutureTask 实现了 RunnableFuture 接口,而 RunnableFuture 实现了 Runnable 和 Future\ 接口。 - -### execute()和submit() - -`execute()`方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否。 - -`submit()`方法用于提交需要返回值的任务。线程池会返回一个 `Future` 类型的对象,通过这个 `Future` 对象可以判断任务是否执行成功,并且可以通过 `Future` 的 `get()`方法来获取返回值,`get()`方法会阻塞当前线程直到任务完成,而使用 `get(long timeout, TimeUnit unit)`方法则会阻塞当前线程一段时间后立即返回,无论任务是否执行完。 - -### 常用的线程池 - -常见的线程池有 FixedThreadPool、SingleThreadExecutor、CachedThreadPool 和 ScheduledThreadPool。这几个都是 ExecutorService (线程池)实例。 - -#### FixedThreadPool - -固定线程数的线程池。任何时间点,最多只有 nThreads 个线程处于活动状态执行任务。 - -``` -public static ExecutorService newFixedThreadPool(int nThreads) { - return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); -} -``` - -使用无界队列 LinkedBlockingQueue(队列容量为 Integer.MAX_VALUE),运行中的线程池不会拒绝任务,即不会调用RejectedExecutionHandler.rejectedExecution()方法。 - -maxThreadPoolSize 是无效参数,故将它的值设置为与 coreThreadPoolSize 一致。 - -keepAliveTime 也是无效参数,设置为0L,因为此线程池里所有线程都是核心线程,核心线程不会被回收(除非设置了executor.allowCoreThreadTimeOut(true))。 - -适用场景:适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务。需要注意的是,FixedThreadPool 不会拒绝任务,**在任务比较多的时候会导致 OOM。** - -#### SingleThreadExecutor - -只有一个线程的线程池。 - -``` -public static ExecutionService newSingleThreadExecutor() { - return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); -} -``` - -使用无界队列 LinkedBlockingQueue。线程池只有一个运行的线程,新来的任务放入工作队列,线程处理完任务就循环从队列里获取任务执行。保证顺序的执行各个任务。 - -适用场景:适用于串行执行任务的场景,一个任务一个任务地执行。**在任务比较多的时候也是会导致 OOM。** - -#### CachedThreadPool - -根据需要创建新线程的线程池。 - -``` -public static ExecutorService newCachedThreadPool() { - return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); -} -``` - -如果主线程提交任务的速度高于线程处理任务的速度时,`CachedThreadPool` 会不断创建新的线程。极端情况下,这样会导致耗尽 cpu 和内存资源。 - -使用没有容量的SynchronousQueue作为线程池工作队列,当线程池有空闲线程时,`SynchronousQueue.offer(Runnable task)`提交的任务会被空闲线程处理,否则会创建新的线程处理任务。 - -适用场景:用于并发执行大量短期的小任务。`CachedThreadPool`允许创建的线程数量为 Integer.MAX_VALUE ,**可能会创建大量线程,从而导致 OOM。** - -#### ScheduledThreadPoolExecutor - -在给定的延迟后运行任务,或者定期执行任务。在实际项目中基本不会被用到,因为有其他方案选择比如`quartz`。 - -使用的任务队列 `DelayQueue` 封装了一个 `PriorityQueue`,`PriorityQueue` 会对队列中的任务进行排序,时间早的任务先被执行(即`ScheduledFutureTask` 的 `time` 变量小的先执行),如果time相同则先提交的任务会被先执行(`ScheduledFutureTask` 的 `squenceNumber` 变量小的先执行)。 - -执行周期任务步骤: - -1. 线程从 `DelayQueue` 中获取已到期的 `ScheduledFutureTask(DelayQueue.take())`。到期任务是指 `ScheduledFutureTask`的 time 大于等于当前系统的时间; -2. 执行这个 `ScheduledFutureTask`; -3. 修改 `ScheduledFutureTask` 的 time 变量为下次将要被执行的时间; -4. 把这个修改 time 之后的 `ScheduledFutureTask` 放回 `DelayQueue` 中(`DelayQueue.add()`)。 - -![](http://img.dabin-coder.cn/image/scheduled-task.jpg) - -适用场景:周期性执行任务的场景,需要限制线程数量的场景。 - -#### 编码规范 - -阿里巴巴编码规约不允许使用Executors去创建线程池,而是通过ThreadPoolExecutor的方式手动创建线程池,这样子使用者会更加明确线程池的运行机制,避免资源耗尽的风险。 - -Executors 创建线程池对象的弊端: - -FixedThreadPool和SingleThreadPool。允许请求队列长度为 Integer.MAX_VALUE,可能堆积大量请求,从而导致OOM。 - -CachedThreadPool。创建的线程池允许的最大线程数是Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM。 - -![](http://img.dabin-coder.cn/image/executors-ali.png) - -正确示例(阿里巴巴编码规范): - -```java -//正例1 -ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build(); -//Common Thread Pool -ExecutorService pool = new ThreadPoolExecutor(5, 200, -0L, TimeUnit.MILLISECONDS, //0L keepAliveTime -new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); - -pool.execute(()-> System.out.println(Thread.currentThread().getName())); -pool.shutdown();//gracefully shutdown - -//正例2 -ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, //corePoolSize threadFactory -    new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()); -``` - -## JMM - -Java内存模型:线程之间的共享变量存储在主内存里,每个线程都有自己私有的本地内存,本地内存保存了共享变量的副本,线程对变量的操作都在本地内存中进行,不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方本地内存中的变量,线程之间值的传递都需要通过主内存来完成。 - -线程a和线程b要想进行数据交换一般要经过下面的步骤: - -1. 线程a把本地内存a中的更新过的共享变量刷新到主内存中去。 -2. 线程b到主内存中去读取线程a刷新过的共享变量,然后复制一份到本地内存b中去。 - -![](http://img.dabin-coder.cn/image/image-20210909233258929.png) - -本地内存是JMM的一个抽象概念,并不真实存在,它包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。 - -## 进程线程 - -进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。 -线程是比进程更小的执行单位,它是在一个进程中独立的控制流,一个进程可以启动多个线程,每条线程并行执行不同的任务。 - -### 线程状态 - -初始(NEW):线程被构建,还没有调用 start()。 - -运行(RUNNABLE):包括操作系统的就绪和运行两种状态。 - -阻塞(BLOCKED):一般是被动的,在抢占资源中得不到资源,被动的挂起在内存,等待资源释放将其唤醒。线程被阻塞会释放CPU,不释放内存。 - -等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。 - -超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。 - -终止(TERMINATED):表示该线程已经执行完毕。 - -![](http://img.dabin-coder.cn/image/image-20210909235618175.png) - -> 图片来源:Java并发编程的艺术 - -### 中断 - -线程中断即线程运行过程中被其他线程给打断了,它与 stop 最大的区别是:stop 是由系统强制终止线程,而线程中断则是给目标线程发送一个中断信号,如果目标线程没有接收线程中断的信号并结束线程,线程则不会终止,具体是否退出或者执行其他逻辑取决于目标线程。 - -线程中断三个重要的方法: - -**1、java.lang.Thread#interrupt** - -调用目标线程的interrupt()方法,给目标线程发一个中断信号,线程被打上中断标记。 - -**2、java.lang.Thread#isInterrupted()** - -判断目标线程是否被中断,不会清除中断标记。 - -**3、java.lang.Thread#interrupted** - -判断目标线程是否被中断,会清除中断标记。 - -```java -private static void test2() { - Thread thread = new Thread(() -> { - while (true) { - Thread.yield(); - - // 响应中断 - if (Thread.currentThread().isInterrupted()) { - System.out.println("Java技术栈线程被中断,程序退出。"); - return; - } - } - }); - thread.start(); - thread.interrupt(); -} -``` - -### 常见方法 - -#### join - -Thread.join(),在main中创建了thread线程,在main中调用了thread.join()/thread.join(long millis),main线程放弃cpu控制权,线程进入WAITING/TIMED_WAITING状态,等到thread线程执行完才继续执行main线程。 - -```java -public final void join() throws InterruptedException { - join(0); -} -``` - -#### yield - -Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。 - -```java -public static native void yield(); //static方法 -``` - -#### sleep - -Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,让出cpu资源,但不释放对象锁,指定时间到后又恢复运行。作用:给其它线程执行机会的最佳方式。 - -```java -public static native void sleep(long millis) throws InterruptedException;//static方法 -``` - -#### wait()和sleep()的区别 - -相同点: - -1. 使当前线程暂停运行,把机会交给其他线程 -2. 任何线程在等待期间被中断都会抛出InterruptedException - -不同点: - -1. wait() 是Object超类中的方法;而sleep()是线程Thread类中的方法 -2. 对锁的持有不同,wait()会释放锁,而sleep()并不释放锁 -3. 唤醒方法不完全相同,wait() 依靠notify或者notifyAll 、中断、达到指定时间来唤醒;而sleep()到达指定时间被唤醒 -4. 调用obj.wait()需要先获取对象的锁,而 Thread.sleep()不用 - -### 创建线程的方法 - -- 通过扩展Thread类来创建多线程 -- 通过实现Runnable接口来创建多线程,可实现线程间的资源共享 -- 实现Callable接口,通过FutureTask接口创建线程。 -- 使用Executor框架来创建线程池。 - -**继承 Thread 创建线程**代码如下。run()方法是由jvm创建完操作系统级线程后回调的方法,不可以手动调用,手动调用相当于调用普通方法。 - -```java -/** - * @author: 程序员大彬 - * @time: 2021-09-11 10:15 - */ -public class MyThread extends Thread { - public MyThread() { - } - - @Override - public void run() { - for (int i = 0; i < 10; i++) { - System.out.println(Thread.currentThread() + ":" + i); - } - } - - public static void main(String[] args) { - MyThread mThread1 = new MyThread(); - MyThread mThread2 = new MyThread(); - MyThread myThread3 = new MyThread(); - mThread1.start(); - mThread2.start(); - myThread3.start(); - } -} -``` - -**Runnable 创建线程代码**: - -```java -/** - * @author: 程序员大彬 - * @time: 2021-09-11 10:04 - */ -public class RunnableTest { - public static void main(String[] args){ - Runnable1 r = new Runnable1(); - Thread thread = new Thread(r); - thread.start(); - System.out.println("主线程:["+Thread.currentThread().getName()+"]"); - } -} - -class Runnable1 implements Runnable{ - @Override - public void run() { - System.out.println("当前线程:"+Thread.currentThread().getName()); - } -} -``` - -实现Runnable接口比继承Thread类所具有的优势: - -1. 资源共享,适合多个相同的程序代码的线程去处理同一个资源 -2. 可以避免java中的单继承的限制 -3. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类 - -**Callable 创建线程代码**: - -```java -/** - * @author: 程序员大彬 - * @time: 2021-09-11 10:21 - */ -public class CallableTest { - public static void main(String[] args) { - Callable1 c = new Callable1(); - - //异步计算的结果 - FutureTask result = new FutureTask<>(c); - - new Thread(result).start(); - - try { - //等待任务完成,返回结果 - int sum = result.get(); - System.out.println(sum); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - -} - -class Callable1 implements Callable { - - @Override - public Integer call() throws Exception { - int sum = 0; - - for (int i = 0; i <= 100; i++) { - sum += i; - } - return sum; - } -} -``` - -**使用 Executor 创建线程代码**: - -```java -/** - * @author: 程序员大彬 - * @time: 2021-09-11 10:44 - */ -public class ExecutorsTest { - public static void main(String[] args) { - //获取ExecutorService实例,生产禁用,需要手动创建线程池 - ExecutorService executorService = Executors.newCachedThreadPool(); - //提交任务 - executorService.submit(new RunnableDemo()); - } -} - -class RunnableDemo implements Runnable { - @Override - public void run() { - System.out.println("大彬"); - } -} -``` - - - -## 线程间通信 - -### volatile - -volatile是轻量级的同步机制,volatile保证变量对所有线程的可见性,不保证原子性。 - -1. 当对volatile变量进行写操作的时候,JVM会向处理器发送一条LOCK前缀的指令,将该变量所在缓存行的数据写回系统内存。 -2. 由于缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己的缓存是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行置为无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存中。 - -MESI(缓存一致性协议):当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,就会从内存重新读取。 - -volatile关键字的两个作用: - -1. 保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。 -2. 禁止进行指令重排序。 - -指令重排序是JVM为了优化指令,提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。Java编译器会在生成指令系列时在适当的位置会插入`内存屏障`指令来禁止处理器重排序。插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行。对一个volatile字段进行写操作,Java内存模型将在写操作后插入一个写屏障指令,这个指令会把之前的写入值都刷新到内存。 - -### synchronized - -保证线程对变量访问的可见性和排他性。synchronized 详细内容见下文锁部分。 - -### 等待通知机制 - -wait/notify为 Object 对象的方法,调用wait/notify需要先获得对象的锁。对象调用wait之后线程释放锁,将线程放到对象的等待队列,当通知线程调用此对象的notify()方法后,等待线程并不会立即从wait返回,需要等待通知线程释放锁(通知线程执行完同步代码块),等待队列里的线程获取锁,获取锁成功才能从wait()方法返回,即从wait方法返回前提是线程获得锁。 - -等待通知机制依托于同步机制,目的是确保等待线程从wait方法返回时能感知到通知线程对对象的变量值的修改。 - - - -## 锁 - -### synchronized - -较常用的用于保证线程安全的方式。当一个线程获取到锁时,其他线程都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程,被唤醒的线程才有机会获取到锁。 - -- 修饰实例方法,作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁 -- 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁(类的字节码文件) -- 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁 - -获取了类锁的线程和获取了对象锁的线程是不冲突的。 - -#### 释放锁 - -当方法或者代码块执行完毕后会自动释放锁,不需要做任何的操作。 -当一个线程执行的代码出现异常时,其所持有的锁会自动释放。 - -#### 实现原理 - -synchronized通过对象内部的监视器锁(monitor)实现。每个对象都有一个monitor,当对象的monitor被持有时,则它处于锁定的状态。 - -**代码块的同步**是使用monitorenter和monitorexit指令实现的,monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处或异常处。 - -```java -public class SynchronizedDemo { - public void method() { - synchronized (this) { - System.out.println("method start"); - } - } -} -``` - -线程访问同步块时,先执行monitorenter指令时尝试获取monitor,过程如下: - -1. 如果monitor的进入数entry count为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。 -2. 如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。 -3. 如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor。 - -线程退出同步块时会执行monitorexit指令,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor。 - -Synchronized底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。 - -![](http://img.dabin-coder.cn/image/synchronized-block.png) - -**方法的同步**不是通过添加monitorenter和monitorexit指令来完成,而是在其常量池中添加了ACC_SYNCHRONIZED标识符。JVM就是根据该标识符来实现方法的同步的:当线程调用方法时,会先检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,说明此方法是同步方法,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他线程无法再获得同一个monitor对象。 - -```java -public class SynchronizedMethod { - public synchronized void method() { - System.out.println("Hello World!"); - } -} -``` - -![](http://img.dabin-coder.cn/image/synchronized-method.png) - -#### 锁的状态 - -Synchronized是通过对象内部的监视器来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间。这种依赖于操作系统Mutex Lock所实现的锁我们称之为重量级锁。 - -JDK1.6中为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。 - -synchronized锁主要存在四种状态,依次是:偏向锁状态、轻量级锁状态、重量级锁状态,他们会随着竞争的激烈而逐渐升级。锁可以升级不可降级,这种策略是为了提高获得锁和释放锁的效率。 - -- 偏向锁:当线程访问同步块并获取锁时,会在对象头和锁记录中存储锁偏向的线程id,以后该线程进入和退出同步块时,只需简单测试一下对象头的mark word中是否存储着指向当前线程的偏向锁,如果测试成功,则线程获取锁成功,否则,需再测试一下mark word中偏向锁标识是否是1,是的话则使用CAS操作竞争锁。如果竞争成功,则将Mark Word中线程ID设置为当前线程ID,如果CAS获取偏向锁失败,则表示有竞争。当到达全局安全点时获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。 - **偏向锁偏向于第一个获得它的线程,如果程序运行过程,该锁没有被其他线程获取,那么持有偏向锁的线程就不需要进行同步。引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行的开销,因为轻量级锁的获取及释放使用了多次CAS原子指令,而偏向锁只在置换ThreadID的时候使用一次CAS原子指令。当存在锁竞争的时候,偏向锁会升级为轻量级锁。** - 适用场景:在锁无竞争的情况下使用,在线程没有执行完同步代码之前,没有其它线程去竞争锁,一旦有了竞争就升级为轻量级锁,升级为轻量级锁的时候需要撤销偏向锁,会做很多额外操作,导致性能下降。 - -- 轻量级锁 - 加锁过程:线程执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的mark word复制到锁记录(displaced mark word)中,然后线程尝试使用cas将对象头的mark word替换为指向锁记录的指针。如果成功,则当前线程获得锁,否则表示有其他线程竞争锁,当前线程便尝试使用自旋来获得锁。当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。 - 解锁过程:使用原子的cas操作将displaced mark word替换回到对象头,如果成功则解锁成功,否则表明有锁竞争,锁会膨胀成重量级锁。 - - **在没有多线程竞争的前提下,使用轻量级锁可以减少传统的重量级锁使用操作系统互斥量(申请互斥锁)产生的性能消耗,因为使用轻量级锁时,不需要申请互斥量。另外,轻量级锁的加锁和解锁都用到了CAS操作。如果没有竞争,轻量级锁使用 CAS 操作避免了使用互斥操作的开销。但如果存在锁竞争,除了互斥量开销外,还会额外发生CAS操作,因此在有锁竞争的情况下,轻量级锁比传统的重量级锁更慢!如果锁竞争激烈,那么轻量级锁将很快膨胀为重量级锁!** - -- 重量级锁:当一个线程获取到锁时,其他线程都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程,被唤醒的线程才有机会获取到锁。 - - synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中,保证了可见性。 - -- 自旋锁:一般线程持有锁的时间都不是太长,所以仅仅为了这一点时间去挂起线程/恢复线程比较浪费资源。自旋锁就是让该线程等待一段时间,执行一段无意义的循环,不会被立即挂起,看持有锁的线程是否会很快释放锁。如果持有锁的线程很快就释放了锁,那么自旋的效率就非常好,反之,自旋的线程就会白白消耗掉处理的资源,这样反而会带来性能上的浪费。所以自旋的次数必须要有一个限度,如果自旋超过了限定次数仍然没有获取到锁,则应该被挂起。 - -- 自适应自旋锁:JDK 1.6引入了更加聪明的自旋锁,即自适应自旋锁。所谓自适应就意味着自旋的次数不再是固定的,它是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。 - -- 锁消除:虚拟机即使编译器在运行时,如果检测到那些共享数据不可能存在竞争,那么就执行锁消除。 - -- 锁粗化:如果一系列的连续操作都对同一个对象反复加锁和解锁,那么会带来很多不必要的性能消耗,使用锁粗化减少锁操作的开销。 - -### ReentrantLock - -重入锁,支持一个线程对资源的重复加锁。该锁的还支持设置获取锁时的公平和非公平性。 - -使用lock时需要在try finally块进行解锁: - -```java -public static final Object get(String key) { - r.lock(); - try { - return map.get(key); - } finally { - r.unlock(); - } -} -``` - -#### 原理 - -ReentrantLock是通过组合自定义同步器来实现锁的获取与释放。当线程尝试获取同步状态时,首先判断当前线程是否为获取锁的线程来决定获取操作是否成功,如果是获取锁的线程再次请求,则将同步状态值进行增加并返回true,表示获取同步状态成功。获取同步状态失败,则该线程会被构造成node节点放到AQS同步队列中。 - -如果锁被获取了n次,那么前n-1次 tryRelease(int releases)方法必须返回false,第n次调用tryRelease()之后,同步状态完全释放(值为0),才会返回true。 - -### ReentrantLock和synchronized区别 - -1. 使用synchronized关键字实现同步,线程执行完同步代码块会自动释放锁,而ReentrantLock需要手动释放锁。 -2. synchronized是非公平锁,ReentrantLock可以设置为公平锁。 -3. ReentrantLock上等待获取锁的线程是可中断的,线程可以放弃等待锁。而synchonized会无限期等待下去。 -4. ReentrantLock 可以设置超时获取锁。在指定的截止时间之前获取锁,如果截止时间到了还没有获取到锁,则返回。 -5. ReentrantLock 的 tryLock() 方法可以尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回true,否则返回false。 - -### 锁的分类 - -#### 公平锁与非公平锁 - -按照线程访问顺序获取对象锁。synchronized 是非公平锁, Lock 默认是非公平锁,可以设置为公平锁,公平锁会影响性能。 - -```java -public ReentrantLock() { - sync = new NonfairSync(); -} - -public ReentrantLock(boolean fair) { - sync = fair ? new FairSync() : new NonfairSync(); -} -``` - -#### 共享式与独占式锁 - -共享式与独占式的最主要区别在于:同一时刻独占式只能有一个线程获取同步状态,而共享式在同一时刻可以有多个线程获取同步状态。例如读操作可以有多个线程同时进行,而写操作同一时刻只能有一个线程进行写操作,其他操作都会被阻塞。 - -#### 悲观锁与乐观锁 - -悲观锁,每次访问资源都会加锁,执行完同步代码释放锁,synchronized 和 ReentrantLock 属于悲观锁。 - -乐观锁,不会锁定资源,所有的线程都能访问并修改同一个资源,如果没有冲突就修改成功并退出,否则就会继续循环尝试。乐观锁最常见的实现就是CAS。 - -乐观锁一般来说有以下2种方式: - -1. 使用数据版本记录机制实现,这是乐观锁最常用的一种实现方式。给数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的version字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。 -2. 使用时间戳。数据库表增加一个字段,字段类型使用时间戳(timestamp),和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。 - -适用场景: - -- 悲观锁适合写操作多的场景。 -- 乐观锁适合读操作多的场景,不加锁可以提升读操作的性能。 - -##### CAS - -CAS全称 Compare And Swap,比较与交换,是乐观锁的主要实现方式。CAS 在不使用锁的情况下实现多线程之间的变量同步。ReentrantLock 内部的 AQS 和原子类内部都使用了 CAS。 - -CAS算法涉及到三个操作数: - -- 需要读写的内存值 V。 -- 进行比较的值 A。 -- 要写入的新值 B。 - -只有当 V 的值等于 A 时,才会使用原子方式用新值B来更新V的值,否则会继续重试直到成功更新值。 - -以 AtomicInteger 为例,AtomicInteger 的 getAndIncrement()方法底层就是CAS实现,关键代码是 `compareAndSwapInt(obj, offset, expect, update)`,其含义就是,如果`obj`内的`value`和`expect`相等,就证明没有其他线程改变过这个变量,那么就更新它为`update`,如果不相等,那就会继续重试直到成功更新值。 - -CAS 三大问题: - -1. **ABA问题**。CAS需要在操作值的时候检查内存值是否发生变化,没有发生变化才会更新内存值。但是如果内存值原来是A,后来变成了B,然后又变成了A,那么CAS进行检查时会发现值没有发生变化,但是实际上是有变化的。ABA问题的解决思路就是在变量前面添加版本号,每次变量更新的时候都把版本号加一,这样变化过程就从`A-B-A`变成了`1A-2B-3A`。 - - JDK从1.5开始提供了AtomicStampedReference类来解决ABA问题,原子更新带有版本号的引用类型。 - -2. **循环时间长开销大**。CAS操作如果长时间不成功,会导致其一直自旋,给CPU带来非常大的开销。 - -3. **只能保证一个共享变量的原子操作**。对一个共享变量执行操作时,CAS能够保证原子操作,但是对多个共享变量操作时,CAS是无法保证操作的原子性的。 - - Java从1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里来进行CAS操作。 - - - -## 并发工具 - -在JDK的并发包里提供了几个非常有用的并发工具类。CountDownLatch、CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段。 - -### CountDownLatch - -CountDownLatch用于某个线程等待其他线程**执行完任务**再执行,与thread.join()功能类似。常见的应用场景是开启多个线程同时执行某个任务,等到所有任务执行完再执行特定操作,如汇总统计结果。 - -``` -public class CountDownLatchDemo { - static final int N = 4; - static CountDownLatch latch = new CountDownLatch(N); - - public static void main(String[] args) throws InterruptedException { - - for(int i = 0; i < N; i++) { - new Thread(new Thread1()).start(); - } - - latch.await(1000, TimeUnit.MILLISECONDS); //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行;等待timeout时间后count值还没变为0的话就会继续执行 - System.out.println("task finished"); - } - - static class Thread1 implements Runnable { - - @Override - public void run() { - try { - System.out.println(Thread.currentThread().getName() + "starts working"); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - latch.countDown(); - } - } - } -} -``` - -运行结果: - -```java -Thread-0starts working -Thread-1starts working -Thread-2starts working -Thread-3starts working -task finished -``` - -### CyclicBarrier - -CyclicBarrier(同步屏障),用于一组线程互相等待到某个状态,然后这组线程再**同时**执行。 - -```java -public CyclicBarrier(int parties, Runnable barrierAction) { -} -public CyclicBarrier(int parties) { -} -``` - -参数parties指让多少个线程或者任务等待至某个状态;参数barrierAction为当这些线程都达到某个状态时会执行的内容。 - -```java -public class CyclicBarrierTest { - // 请求的数量 - private static final int threadCount = 10; - // 需要同步的线程数量 - private static final CyclicBarrier cyclicBarrier = new CyclicBarrier(5); - - public static void main(String[] args) throws InterruptedException { - // 创建线程池 - ExecutorService threadPool = Executors.newFixedThreadPool(10); - - for (int i = 0; i < threadCount; i++) { - final int threadNum = i; - Thread.sleep(1000); - threadPool.execute(() -> { - try { - test(threadNum); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (BrokenBarrierException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - }); - } - threadPool.shutdown(); - } - - public static void test(int threadnum) throws InterruptedException, BrokenBarrierException { - System.out.println("threadnum:" + threadnum + "is ready"); - try { - /**等待60秒,保证子线程完全执行结束*/ - cyclicBarrier.await(60, TimeUnit.SECONDS); - } catch (Exception e) { - System.out.println("-----CyclicBarrierException------"); - } - System.out.println("threadnum:" + threadnum + "is finish"); - } - -} -``` - -运行结果如下,可以看出CyclicBarrier是可以重用的: - -```java -threadnum:0is ready -threadnum:1is ready -threadnum:2is ready -threadnum:3is ready -threadnum:4is ready -threadnum:4is finish -threadnum:3is finish -threadnum:2is finish -threadnum:1is finish -threadnum:0is finish -threadnum:5is ready -threadnum:6is ready -... -``` - -当四个线程都到达barrier状态后,会从四个线程中选择一个线程去执行Runnable。 - -### CyclicBarrier和CountDownLatch区别 - -CyclicBarrier 和 CountDownLatch 都能够实现线程之间的等待。 - -CountDownLatch用于某个线程等待其他线程**执行完任务**再执行。CyclicBarrier用于一组线程互相等待到某个状态,然后这组线程再**同时**执行。 -CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,可用于处理更为复杂的业务场景。 - -### Semaphore - -Semaphore类似于锁,它用于控制同时访问特定资源的线程数量,控制并发线程数。 - -``` -public class SemaphoreDemo { - public static void main(String[] args) { - final int N = 7; - Semaphore s = new Semaphore(3); - for(int i = 0; i < N; i++) { - new Worker(s, i).start(); - } - } - - static class Worker extends Thread { - private Semaphore s; - private int num; - public Worker(Semaphore s, int num) { - this.s = s; - this.num = num; - } - - @Override - public void run() { - try { - s.acquire(); - System.out.println("worker" + num + " using the machine"); - Thread.sleep(1000); - System.out.println("worker" + num + " finished the task"); - s.release(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } -} -``` - -运行结果如下,可以看出并非按照线程访问顺序获取资源的锁,即 - -```java -worker0 using the machine -worker1 using the machine -worker2 using the machine -worker2 finished the task -worker0 finished the task -worker3 using the machine -worker4 using the machine -worker1 finished the task -worker6 using the machine -worker4 finished the task -worker3 finished the task -worker6 finished the task -worker5 using the machine -worker5 finished the task -``` - - - -## 原子类 - -### 基本类型原子类 - -使用原子的方式更新基本类型 - -- AtomicInteger:整型原子类 -- AtomicLong:长整型原子类 -- AtomicBoolean :布尔型原子类 - -AtomicInteger 类常用的方法: - -```java -public final int get() //获取当前的值 -public final int getAndSet(int newValue)//获取当前的值,并设置新的值 -public final int getAndIncrement()//获取当前的值,并自增 -public final int getAndDecrement() //获取当前的值,并自减 -public final int getAndAdd(int delta) //获取当前的值,并加上预期的值 -boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update) -public final void lazySet(int newValue)//最终设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。 -``` - -AtomicInteger 类主要利用 CAS (compare and swap) 保证原子操作,从而避免加锁的高开销。 - -### 数组类型原子类 - -使用原子的方式更新数组里的某个元素 - -- AtomicIntegerArray:整形数组原子类 -- AtomicLongArray:长整形数组原子类 -- AtomicReferenceArray :引用类型数组原子类 - -AtomicIntegerArray 类常用方法: - -```java -public final int get(int i) //获取 index=i 位置元素的值 -public final int getAndSet(int i, int newValue)//返回 index=i 位置的当前的值,并将其设置为新值:newValue -public final int getAndIncrement(int i)//获取 index=i 位置元素的值,并让该位置的元素自增 -public final int getAndDecrement(int i) //获取 index=i 位置元素的值,并让该位置的元素自减 -public final int getAndAdd(int i, int delta) //获取 index=i 位置元素的值,并加上预期的值 -boolean compareAndSet(int i, int expect, int update) //如果输入的数值等于预期值,则以原子方式将 index=i 位置的元素值设置为输入值(update) -public final void lazySet(int i, int newValue)//最终 将index=i 位置的元素设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。 -``` - -### 引用类型原子类 - -- AtomicReference:引用类型原子类 -- AtomicStampedReference:带有版本号的引用类型原子类。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。 -- AtomicMarkableReference :原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来 - - - -## AQS - -AQS定义了一套多线程访问共享资源的同步器框架,许多并发工具的实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch。 - -### 原理 - -AQS使用一个volatile的int类型的成员变量state来表示同步状态,通过CAS修改同步状态的值。 - -```java -private volatile int state;//共享变量,使用volatile修饰保证线程可见性 -``` - -同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态(独占或共享 )构造成为一个节点(Node)并将其加入同步队列并进行自旋,当同步状态释放时,会把首节中的后继节点对应的线程唤醒,使其再次尝试获取同步状态。 - -![](http://img.dabin-coder.cn/image/image-20210910000456607.png) - - - -## Condition - -任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,使用这些方法的前提是已经获取对象的锁,和 synchronized 配合使用。Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式。Condition是依赖Lock对象。 - -```java -Lock lock = new ReentrantLock(); -Condition condition = lock.newCondition(); -public void conditionWait() throws InterruptedException { - lock.lock(); - try { - condition.await(); - } finally { - lock.unlock(); - } -} -public void conditionSignal() throws InterruptedException { - lock.lock(); - try { - condition.signal(); - } finally { - lock.unlock(); - } -} -``` - -一般将Condition对象作为成员变量。当调用await()方法后,当前线程会释放锁进入等待队列。其他线程调用Condition对象的signal()方法,唤醒等待队列首节点的线程。 - -### 实现原理 - -每个Condition对象都包含着一个等待队列,如果一个线程成功获取了锁之后调用了Condition.await()方法,那么该线程将会释放同步状态、唤醒同步队列中的后继节点,然后构造成节点加入等待队列。只有当线程再次获取Condition相关联的锁之后,才能从await()方法返回。 - -![](http://img.dabin-coder.cn/image/condition-await.png) - -> 图片来源:Java并发编程的艺术 - -在Object的监视器模型上,一个对象拥有一个同步队列和等待队列。Lock通过AQS实现,AQS可以有多个Condition,所以Lock拥有一个同步队列和多个等待队列。 - -![](http://img.dabin-coder.cn/image/condition-wait-queue.png) - -> 图片来源:Java并发编程的艺术 - -线程获取了锁之后,调用Condition的signal()方法,会将等待队列的队首节点移到同步队列中,然后该节点的线程会尝试去获取同步状态。成功获取同步状态之后,线程将await()方法返回。 - -![](http://img.dabin-coder.cn/image/condition-signal.png) - -> 图片来源:Java并发编程的艺术 - - - -## 其他 - -### Daemon Thread - -在Java中有两类线程: - -- User Thread(用户线程) -- Daemon Thread(守护线程) - -只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。 - -Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是垃圾收集。 - -将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。 - - - -## 参考资料 - -[线程中断](https://zhuanlan.zhihu.com/p/45667127) - -[synchronized实现原理](https://www.cnblogs.com/paddix/p/5367116.html) - -[指令重排导致单例模式失效](https://blog.csdn.net/jiyiqinlovexx/article/details/50989328) - - - -> 本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础、MySQL、Spring Boot、MyBatis、Redis、RabbitMQ、计算机网络、数据结构与算法等等,欢迎大家提pr和star! -> -> github地址:https://github.com/Tyson0314/Java-learning -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/Java-learning diff --git "a/Java/\351\233\206\345\220\210.md" "b/Java/\351\233\206\345\220\210.md" deleted file mode 100644 index d626f12..0000000 --- "a/Java/\351\233\206\345\220\210.md" +++ /dev/null @@ -1,479 +0,0 @@ - - - - -- [ArrayList 简介](#arraylist-%E7%AE%80%E4%BB%8B) - - [Arraylist 和 Vector 的区别](#arraylist-%E5%92%8C-vector-%E7%9A%84%E5%8C%BA%E5%88%AB) - - [Arraylist 与 LinkedList 区别](#arraylist-%E4%B8%8E-linkedlist-%E5%8C%BA%E5%88%AB) -- [Map](#map) - - [HashMap](#hashmap) - - [hash算法](#hash%E7%AE%97%E6%B3%95) - - [resize](#resize) - - [put](#put) - - [红黑树](#%E7%BA%A2%E9%BB%91%E6%A0%91) - - [HashMap和HashTable](#hashmap%E5%92%8Chashtable) - - [LinkedHashMap](#linkedhashmap) - - [TreeMap](#treemap) -- [Set](#set) -- [Queue](#queue) -- [Iterator](#iterator) - - [ListIterator](#listiterator) -- [并发容器](#%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8) - - [ConcurrentHashMap](#concurrenthashmap) - - [put](#put-1) - - [扩容](#%E6%89%A9%E5%AE%B9) - - [ConcurrentHashMap 和 Hashtable](#concurrenthashmap-%E5%92%8C-hashtable) - - [CopyOnWrite](#copyonwrite) - - [ConcurrentLinkedQueue](#concurrentlinkedqueue) - - [阻塞队列](#%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97) - - [方法](#%E6%96%B9%E6%B3%95) - - [JDK提供的阻塞队列](#jdk%E6%8F%90%E4%BE%9B%E7%9A%84%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97) - - [原理](#%E5%8E%9F%E7%90%86) - - - -## ArrayList 简介 - -`ArrayList` 的底层是动态数组,它的容量能动态增长。在添加大量元素前,应用可以使用`ensureCapacity`操作增加 `ArrayList` 实例的容量。ArrayList 继承了 AbstractList ,并实现了 List 接口。 - -### Arraylist 和 Vector 的区别 - -1. ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。 -2. Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为操作Vector效率比较低。 - -### Arraylist 与 LinkedList 区别 - -1. ArrayList基于动态数组实现;LinkedList基于链表实现。 -2. 对于随机index访问的get和set方法,ArrayList的速度要优于LinkedList。因为ArrayList直接通过数组下标直接找到元素;LinkedList要移动指针遍历每个元素直到找到为止。 -3. 新增和删除元素,LinkedList的速度要优于ArrayList。因为ArrayList在新增和删除元素时,可能扩容和复制数组;LinkedList实例化对象需要时间外,只需要修改指针即可。 - -## Map - -以 Map 结尾的类都实现了 Map 接口,其他所有的类都实现了 Collection 接口。 - -![](http://img.dabin-coder.cn/image/Java-Collections.jpeg) - -### HashMap - -HashMap 使用数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的, 链表长度大于8(TREEIFY_THRESHOLD)时,会把链表转换为红黑树,红黑树节点个数小于6(UNTREEIFY_THRESHOLD)时才转化为链表,防止频繁的转化。 - -#### hash算法 - -Hash算法:取key的hashCode值、高位运算、取模运算。 - -``` -h=key.hashCode() //第一步 取hashCode值 -h^(h>>>16) //第二步 高位参与运算,减少冲突 -return h&(length-1); //第三步 取模运算 -``` - -在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的:这么做可以在数组比较小的时候,也能保证考虑到高低位都参与到Hash的计算中,可以减少冲突,同时不会有太大的开销。 - -#### resize - -1.8扩容机制:当元素个数大于threshold时,会进行扩容,使用2倍容量的数组代替原有数组。采用尾插入的方式将原数组元素拷贝到新数组。1.8扩容之后链表元素相对位置没有变化,而1.7扩容之后链表元素会倒置。 - -1.7链表新节点采用的是头插法,这样在线程一扩容迁移元素时,会将元素顺序改变,导致两个线程中出现元素的相互指向而形成循环链表,1.8采用了尾插法,避免了这种情况的发生。 - -原数组的元素在重新计算hash之后,因为数组容量n变为2倍,那么n-1的mask范围在高位多1bit。在元素拷贝过程不需要重新计算元素在数组中的位置,只需要看看原来的hash值新增的那个bit是1还是0,是0的话索引没变,是1的话索引变成“原索引+oldCap”(根据`e.hash & (oldCap - 1) == 0`判断) 。这样可以省去重新计算hash值的时间,而且由于新增的1bit是0还是1可以认为是随机的,因此resize的过程会均匀的把之前的冲突的节点分散到新的bucket。 - -#### put - -put方法流程: - -1. 如果table没有初始化就先进行初始化过程 -2. 使用hash算法计算key的索引 -3. 判断索引处有没有存在元素,没有就直接插入 -4. 如果索引处存在元素,则遍历插入,有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入 -5. 链表的数量大于阈值8,就要转换成红黑树的结构 -6. 添加成功后会检查是否需要扩容 - -![](http://img.dabin-coder.cn/image/hashmap-put.png) - -> 参考链接: -> -> http://www.importnew.com/20386.html -> -> https://www.cnblogs.com/yangming1996/p/7997468.html -> -> https://coolshell.cn/articles/9606.htm(HashMap 死循环) - - - -#### 红黑树 - -为什么使用红黑树而不使用AVL树? - -ConcurrentHashMap 在put的时候会加锁,使用红黑树插入速度更快,可以减少等待锁释放的时间。红黑树是对AVL树的优化,只要求部分平衡,用非严格的平衡来换取增删节点时候旋转次数的降低,提高了插入和删除的性能。 - -### HashMap和HashTable - -HashMap和Hashtable都实现了Map接口 - -1. HashMap可以接受为null的键值(key)和值(value),key为null的键值对放在下标为0的头结点的链表中,而Hashtable则不行。 -2. HashMap是非线程安全的,HashTable是线程安全的。Jdk1.5提供了ConcurrentHashMap,它是HashTable的替代。 -3. Hashtable很多方法是同步方法,在单线程环境下它比HashMap要慢。 -4. 哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。 - -### LinkedHashMap - -HashMap是无序的,迭代HashMap所得到元素的顺序并不是它们最初放到HashMap的顺序,即不能保持它们的插入顺序。 - -LinkedHashMap继承于HashMap,是HashMap和LinkedList的融合体,具备两者的特性。每次put操作都会将entry插入到双向链表的尾部。 - -![linkedhashmap](http://img.dabin-coder.cn/image/linkedhashmap.png) - -### TreeMap - -TreeMap是一个能比较元素大小的Map集合,会对传入的key进行了大小排序。可以使用元素的自然顺序,也可以使用集合中自定义的比较器来进行排序。 - -```java -public class TreeMap - extends AbstractMap - implements NavigableMap, Cloneable, java.io.Serializable { -} -``` - -TreeMap 的继承结构: - -![](http://img.dabin-coder.cn/image/image-20210905215046510.png) - -**TreeMap的特点:** - -1. TreeMap是有序的key-value集合,通过红黑树实现。根据键的自然顺序进行排序或根据提供的Comparator进行排序。 -2. TreeMap继承了AbstractMap,实现了NavigableMap接口,支持一系列的导航方法,给定具体搜索目标,可以返回最接近的匹配项。如floorEntry()、ceilingEntry()分别返回小于等于、大于等于给定键关联的Map.Entry()对象,不存在则返回null。lowerKey()、floorKey、ceilingKey、higherKey()只返回关联的key。 - -## Set - -HashSet 基于 HashMap 实现。放入HashSet中的元素实际上由HashMap的key来保存,而HashMap的value则存储了一个静态的Object对象。 - -```java -public class HashSet - extends AbstractSet - implements Set, Cloneable, java.io.Serializable { - static final long serialVersionUID = -5024744406713321676L; - - private transient HashMap map; //基于HashMap实现 - //... -} -``` - - - -## Queue - -ArrayDeque实现了双端队列,内部使用循环数组实现,默认大小为16。 - -特点: - -1. 在两端添加、删除元素的效率较高 - -2. 根据元素内容查找和删除的效率比较低。 - -3. 没有索引位置的概念,不能根据索引位置进行操作。 - -ArrayDeque和LinkedList都实现了Deque接口,如果只需要从两端进行操作,ArrayDeque效率更高一些。如果同时需要根据索引位置进行操作,或者经常需要在中间进行插入和删除(LinkedList有相应的 api,如add(int index, E e)),则应该选LinkedList。 - -ArrayDeque和LinkedList都是线程不安全的,可以使用Collections工具类中synchronizedXxx()转换成线程同步。 - -## Iterator - -Iterator模式用同一种逻辑来遍历集合。它可以把访问逻辑从不同类型的集合类中抽象出来,不需要了解集合内部实现便可以遍历集合元素,集合是数组还是链表实现的无所谓,统一使用 Iterator 提供的接口去遍历。 - -主要有三个方法:hasNext()、next()和remove()。 - -```java - for(Iterator it = c.iterater(); it.hasNext(); ) { ... } -``` - -### ListIterator - -Iterator的增强版,增加了以下功能: - -1. ListIterator有add()方法,可以向List中添加对象。 - -2. hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。 -3. nextIndex()和previousIndex()定位索引位置。 -4. set() 实现对象的修改。 - -```java -public interface ListIterator extends Iterator { - boolean hasNext(); - - E next(); - - boolean hasPrevious(); - - E previous(); - - int nextIndex(); - - int previousIndex(); - - void remove(); - - void set(E var1); - - void add(E var1); -} -``` - - - -## 并发容器 - -JDK 提供的这些容器大部分在 `java.util.concurrent` 包中。 - -- **ConcurrentHashMap:** 线程安全的 HashMap -- **CopyOnWriteArrayList:** 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vector. -- **ConcurrentLinkedQueue:** 高效的并发队列,使用链表实现。可以看做一个线程安全的 LinkedList,这是一个非阻塞队列。 -- **BlockingQueue:** 阻塞队列接口,JDK 内部通过链表、数组等方式实现了这个接口。非常适合用于作为数据共享的通道。 -- **ConcurrentSkipListMap:** 跳表的实现。使用跳表的数据结构进行快速查找。 - -### ConcurrentHashMap - -多线程环境下,使用Hashmap进行put操作会引起死循环,应该使用支持多线程的 ConcurrentHashMap。 - -```java -private static final int MAXIMUM_CAPACITY = 1 << 30; -private static final int DEFAULT_CAPACITY = 16; -static final int TREEIFY_THRESHOLD = 8; -static final int UNTREEIFY_THRESHOLD = 6; -static final int MIN_TREEIFY_CAPACITY = 64; -static final int MOVED = -1; // 表示正在转移 -static final int TREEBIN = -2; // 表示已经转换成树 -static final int RESERVED = -3; // hash for transient reservations -static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash -transient volatile Node[] table;//默认没初始化的数组,用来保存元素 -private transient volatile Node[] nextTable;//转移的时候用的数组 -/** - * 用来控制表初始化和扩容的,默认值为0,当在初始化的时候指定了大小,这会将这个大小保存在sizeCtl中,大小为数组的0.75 - * 当为负的时候,说明表正在初始化或扩张, - * -1表示初始化 - * -(1+n) n:表示活动的扩张线程 - */ -private transient volatile int sizeCtl; -​```JDK1.7中的ConcurrentHashmap主要使用Segment来实现减小锁粒度。Segment继承了ReentrantLock,所以它就是一种可重入锁。默认分配16个segment,允许16个线程并发执行。Segment维护了一个HashEntry**数组**,对于同一个Segment的操作才需考虑线程同步,不同的Segment则无需考虑。当要统计size时,比较统计前后modCount是否发生变化。如果没有变化,则直接返回size。否则,需要依次锁住所有的Segment来计算。当长度过长碰撞会很频繁,链表的增改删查操作都会消耗很长的时间,影响性能。 -``` - -JDK1.8 ConcurrentHashMap取消了segment分段锁,而采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,相比1.7锁定HashEntry数组,锁粒度更小,支持更高的并发量。当链表长度过长时,Node会转换成TreeNode,提高查找速度。 - -#### put - -在put的时候需要锁住Segment,保证并发安全。调用get的时候不加锁,因为node数组成员val和指针next是用volatile修饰的,更改后的值会立刻刷新到主存中,保证了可见性,node数组table也用volatile修饰,保证在运行过程对其他线程具有可见性。 - -```java -transient volatile Node[] table; - -static class Node implements Map.Entry { - volatile V val; - volatile Node next; -} -``` - -put 操作流程: - -1. 如果table没有初始化就先进行初始化过程 -2. 使用hash算法计算key的位置 -3. 如果这个位置为空则直接CAS插入,如果不为空的话,则取出这个节点来 -4. 如果取出来的节点的hash值是MOVED(-1)的话,则表示当前正在对这个数组进行扩容,复制到新的数组,则当前线程也去帮助复制 -5. 如果这个节点,不为空,也不在扩容,则通过synchronized来加锁,进行添加操作,这里有两种情况,一种是链表形式就直接遍历到尾端插入或者覆盖掉相同的key,一种是红黑树就按照红黑树结构插入 -6. 链表的数量大于阈值8,就会转换成红黑树的结构或者进行扩容(table长度小于64) -7. 添加成功后会检查是否需要扩容 - -#### 扩容 - -数组扩容transfer方法中会设置一个步长,表示一个线程处理的数组长度,最小值是16。在一个步长范围内只有一个线程会对其进行复制移动操作。 - -#### ConcurrentHashMap 和 Hashtable - -区别: - -1. Hashtable通过使用synchronized修饰方法的方式来实现多线程同步,因此,Hashtable的同步会锁住整个数组。在高并发的情况下,性能会非常差。ConcurrentHashMap采用了更细粒度的锁来提高在并发情况下的效率。注:Synchronized容器(同步容器)也是通过synchronized关键字来实现线程安全,在使用的时候会对所有的数据加锁。 -2. Hashtable默认的大小为11,当达到阈值后,每次按照下面的公式对容量进行扩充:newCapacity = oldCapacity * 2 + 1。ConcurrentHashMap默认大小是16,扩容时容量扩大为原来的2倍。 - -ConcurrentHashMap 和 Hashtable 的key和value不能为null。 - -HashMap.java 部分源码: - -```java - static final int hash(Object key) { - int h; - return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//key为null时,hash值为0 - } -``` - -ConcurrentHashMap.java 部分源码: - -```java - /** Implementation for put and putIfAbsent */ - final V putVal(K key, V value, boolean onlyIfAbsent) { - if (key == null || value == null) throw new NullPointerException(); - int hash = spread(key.hashCode()); - int binCount = 0; - ...... - } -``` - -ConcurrentHashmap和Hashtable都支持并发,当你通过get(k)获取对应的value时,如果获取到的是null时,无法判断是key 对应的 value 为 null,还是这个 key 从来没有做过映射,在多线程里面是模糊不清的,所以不让put null。HashMap用于非并发场景,可以通过contains(key)来判断是否存在key。而支持并发的Map在调用m.get(key)之后,再调用m.contains(key),两个调用之间可能有其他线程删除了key,得到的结果不准确,产生多线程安全问题。因此ConcurrentHashMap 和 Hashtable 的key和value不能为null。 - -### CopyOnWrite - -写时复制。当我们往容器添加元素时,不直接往容器添加,而是先将当前容器进行复制,复制出一个新的容器,然后往新的容器添加元素,添加完元素之后,再将原容器的引用指向新容器。这样做的好处就是可以对CopyOnWrite容器进行并发的读而不需要加锁,因为当前容器不会被修改。 - -```java - public boolean add(E e) { - final ReentrantLock lock = this.lock; - lock.lock(); //add方法需要加锁 - try { - Object[] elements = getArray(); - int len = elements.length; - Object[] newElements = Arrays.copyOf(elements, len + 1); //复制新数组 - newElements[len] = e; - setArray(newElements); //原容器的引用指向新容器 - return true; - } finally { - lock.unlock(); - } - } -``` - -从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。 - -CopyOnWriteArrayList中add方法添加的时候是需要加锁的,保证同步,避免了多线程写的时候复制出多个副本。读的时候不需要加锁,如果读的时候有其他线程正在向CopyOnWriteArrayList添加数据,还是可以读到旧的数据。 - -**缺点:** - -- 内存占用问题。由于CopyOnWrite的写时复制机制,在进行写操作的时候,内存里会同时驻扎两个对象的内存。 -- CopyOnWrite容器不能保证数据的实时一致性,可能读取到旧数据。 - -### ConcurrentLinkedQueue - -非阻塞队列。高效的并发队列,使用链表实现。可以看做一个线程安全的 LinkedList,通过 CAS 操作实现。 - -如果对队列加锁的成本较高则适合使用无锁的 ConcurrentLinkedQueue 来替代。适合在对性能要求相对较高,同时有多个线程对队列进行读写的场景。 - -**非阻塞队列中的几种主要方法:** -add(E e) : 将元素e插入到队列末尾,如果插入成功,则返回true;如果插入失败(即队列已满),则会抛出异常; -remove() :移除队首元素,若移除成功,则返回true;如果移除失败(队列为空),则会抛出异常; -offer(E e) :将元素e插入到队列末尾,如果插入成功,则返回true;如果插入失败(即队列已满),则返回false; -poll() :移除并获取队首元素,若成功,则返回队首元素;否则返回null; -peek() :获取队首元素,若成功,则返回队首元素;否则返回null - -对于非阻塞队列,一般情况下建议使用offer、poll和peek三个方法,不建议使用add和remove方法。因为使用offer、poll和peek三个方法可以通过返回值判断操作成功与否,而使用add和remove方法却不能达到这样的效果。 - -### 阻塞队列 - -阻塞队列是java.util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。并发包下很多高级同步类的实现都是基于BlockingQueue实现的。BlockingQueue 适合用于作为数据共享的通道。 - -使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。 - -阻塞队列和一般的队列的区别就在于: - -1. 多线程支持,多个线程可以安全的访问队列 -2. 阻塞操作,当队列为空的时候,消费线程会阻塞等待队列不为空;当队列满了的时候,生产线程就会阻塞直到队列不满。 - -#### 方法 - -| 方法\处理方式 | 抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 | -| ------------- | --------- | ---------- | -------- | ------------------ | -| 插入方法 | add(e) | offer(e) | put(e) | offer(e,time,unit) | -| 移除方法 | remove() | poll() | take() | poll(time,unit) | -| 检查方法 | element() | peek() | 不可用 | 不可用 | - -#### JDK提供的阻塞队列 - -JDK 7 提供了7个阻塞队列,如下 - -1、**ArrayBlockingQueue** - -有界阻塞队列,底层采用数组实现。ArrayBlockingQueue 一旦创建,容量不能改变。其并发控制采用可重入锁来控制,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不能保证线程访问队列的公平性,参数`fair`可用于设置线程是否公平访问队列。为了保证公平性,通常会降低吞吐量。 - -```java -private static ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(10,true);//fair -``` - -2、**LinkedBlockingQueue** - -LinkedBlockingQueue是一个用单向链表实现的有界阻塞队列,可以当做无界队列也可以当做有界队列来使用。通常在创建 LinkedBlockingQueue 对象时,会指定队列最大的容量。此队列的默认和最大长度为`Integer.MAX_VALUE`。此队列按照先进先出的原则对元素进行排序。与 ArrayBlockingQueue 相比起来具有更高的吞吐量。 - -3、**PriorityBlockingQueue** - -支持优先级的**无界**阻塞队列。默认情况下元素采取自然顺序升序排列。也可以自定义类实现`compareTo()`方法来指定元素排序规则,或者初始化PriorityBlockingQueue时,指定构造参数`Comparator`来进行排序。 - -PriorityBlockingQueue 只能指定初始的队列大小,后面插入元素的时候,如果空间不够的话会**自动扩容**。 - -PriorityQueue 的线程安全版本。不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报 ClassCastException 异常。它的插入操作 put 方法不会 block,因为它是无界队列(take 方法在队列为空的时候会阻塞)。 - -4、**DelayQueue** - -支持延时获取元素的无界阻塞队列。队列使用PriorityBlockingQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。 - -5、**SynchronousQueue** - -不存储元素的阻塞队列,每一个put必须等待一个take操作,否则不能继续添加元素。支持公平访问队列。 - -SynchronousQueue可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身不存储任何元素,非常适合传递性场景。SynchronousQueue的吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。 - -6、**LinkedTransferQueue** - -由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列,多了tryTransfer和transfer方法。 - -transfer方法:如果当前有消费者正在等待接收元素(take或者待时间限制的poll方法),transfer可以把生产者传入的元素立刻传给消费者。如果没有消费者等待接收元素,则将元素放在队列的tail节点,并等到该元素被消费者消费了才返回。 - -tryTransfer方法:用来试探生产者传入的元素能否直接传给消费者。如果没有消费者在等待,则返回false。和上述方法的区别是该方法无论消费者是否接收,方法立即返回。而transfer方法是必须等到消费者消费了才返回。 - -#### 原理 - -JDK使用通知模式实现阻塞队列。所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。 - -ArrayBlockingQueue使用Condition来实现: - -```java -private final Condition notEmpty; -private final Condition notFull; - -public ArrayBlockingQueue(int capacity, boolean fair) { - if (capacity <= 0) - throw new IllegalArgumentException(); - this.items = new Object[capacity]; - lock = new ReentrantLock(fair); - notEmpty = lock.newCondition(); - notFull = lock.newCondition(); -} - -public E take() throws InterruptedException { - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - while (count == 0) // 队列为空时,阻塞当前消费者 - notEmpty.await(); - return dequeue(); - } finally { - lock.unlock(); - } -} - -public void put(E e) throws InterruptedException { - checkNotNull(e); - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - while (count == items.length) - notFull.await(); - enqueue(e); - } finally { - lock.unlock(); - } -} - -private void enqueue(E x) { - final Object[] items = this.items; - items[putIndex] = x; - if (++putIndex == items.length) - putIndex = 0; - count++; - notEmpty.signal(); // 队列不为空时,通知消费者获取元素 -} -``` - diff --git a/README.md b/README.md index 88004f5..7826a37 100644 --- a/README.md +++ b/README.md @@ -55,33 +55,38 @@ ## 基础 -1. [**Java面试题精选**](Java/Java基础面试题.md) **精心整理的大厂Java面试题目,附有详细答案** (推荐 :+1:) -2. [Java8 新特性总结](Java/Java8.md) +1. [**Java面试题精选**](docs/java/java-basic.md) **精心整理的大厂Java面试题目,附有详细答案** (推荐 :+1:) +2. [Java8 新特性总结](docs/java/java8-all.md) ## 集合 -1. [Java集合高频面试题](Java/Java集合面试题.md)(**牛客点赞200+!推荐** :+1:) +1. [Java集合高频面试题](docs/java/java-collection.md)(**牛客点赞200+!推荐** :+1:) ## 并发 -1. [Java并发高频面试题(精华版)](Java/Java并发面试题.md) **精心整理的大厂Java并发编程面试题目,附有详细答案** (推荐 :+1:) +1. [Java并发高频面试题(精华版)](docs/java/java-concurrent.md) **精心整理的大厂Java并发编程面试题目,附有详细答案** (推荐 :+1:) ## JVM -1. [【大厂面试】——JVM高频面试题](Java/JVM高频面试题.md)(推荐 :+1:) +1. [【大厂面试】——JVM高频面试题](/docs/java/jvm.md)(推荐 :+1:) # 数据库 ## MySQL -1. [【大厂面试】—— MySQL高频面试题50道](数据库/MySQL高频面试题.md)(**知乎1k+收藏,推荐** :+1:) -2. [图解索引下推](https://mp.weixin.qq.com/s/W1XQYmihtSdbLWQKeNwZvQ)(推荐 :+1:) -3. [MySQL执行计划详解](数据库/MySQL执行计划.md)(推荐 :+1:) +- [MySQL高频面试题50道](docs/database/mysql.md)(**知乎1k+收藏,推荐** :+1:) + +**重要知识点**: + +- [8种最坑SQL语法](docs/advance/excellent-article/7-sql-optimize.md) + +- [MySQL执行计划详解](docs/database/mysql-execution-plan.md)(推荐 :+1:) + +- [图解索引下推](https://mp.weixin.qq.com/s/W1XQYmihtSdbLWQKeNwZvQ)(推荐 :+1:) ## Redis -1. [【大厂面试】——Redis30问](Redis/Redis面试题.md)(牛客高赞,推荐 :+1:) -2. [缓存穿透、缓存雪崩、缓存击穿](Redis/缓存穿透、缓存雪崩、缓存击穿.md) +1. [Redis高频面试题总结](docs/redis/redis.md)(牛客高赞,推荐 :+1:) ## ElasticSearch @@ -91,54 +96,52 @@ ## Spring -1. [Spring高频面试题30道](框架/Spring面试题.md)(推荐 :+1:) -2. [Spring用到哪些设计模式?](框架/Spring用到哪些设计模式.md) +1. [Spring高频面试题30道](docs/framework/spring.md)(推荐 :+1:) +2. [Spring用到哪些设计模式?]() todo ## Spring Boot [Spring Boot总结](框架/SpringBoot实战.md) -[SpringBoot面试题总结](框架/SpringBoot面试题总结.md) +[SpringBoot面试题总结](docs/framework/springboot.md) ## Spring MVC -[Spring MVC入门知识点](框架/SpringMVC.md) - -[Spring MVC面试题总结](框架/SpringMVC面试题.md) +[Spring MVC面试题总结](docs/framework/springmvc.md) ## Mybatis [Mybatis入门知识点](框架/深入浅出Mybatis技术原理与实战.md) -[Mybatis面试题总结](框架/Mybatis面试题.md) +[Mybatis面试题总结](docs/framework/mybatis.md) ## SpringCloud -[[SpringCloud面试题](https://topjavaer.cn/framework/springcloud-interview.html)(推荐 :+1:) +[[SpringCloud面试题](docs/framework/springcloud-interview.md)(推荐 :+1:) -[SpringCloud总结](框架/SpringCloud微服务实战.md) +[SpringCloud总结](docs/framework/springcloud-overview.md) ## Netty -[Netty实战笔记](框架/netty实战.md) +[Netty实战笔记](docs/framework/netty-overview.md) # 分布式 ## 微服务 -[微服务面试题](https://topjavaer.cn/distributed/micro-service.html) +[微服务面试题](docs/advance/distributed/4-micro-service.md) ## RPC -[RPC面试题](https://topjavaer.cn/distributed/rpc.html) +[RPC面试题](docs/advance/distributed/3-rpc.md) ## 全局唯一ID -[全局唯一ID](https://topjavaer.cn/distributed/global-unique-id.html) +[全局唯一ID](docs/advance/distributed/1-global-unique-id.md) ## 分布式事务 -[分布式事务总结](https://topjavaer.cn/distributed/distributed-transaction.html) +[分布式事务总结](docs/advance/distributed/6-distributed-transaction.md) ## 分布式架构 @@ -148,38 +151,30 @@ ## 限流 -[限流算法总结](https://topjavaer.cn/advance/concurrent/1-current-limiting.html) +[限流算法总结](docs/advance/concurrent/1-current-limiting.md) ## 负载均衡 -[负载均衡](https://topjavaer.cn/advance/concurrent/2-load-balance.html) +[负载均衡](docs/advance/concurrent/2-load-balance.md) # 消息队列 ## RabbitMQ -1. [消息队列面试题](消息队列/消息队列面试题.md) -2. [RabbitMQ面试题总结](消息队列/rabbitmq.md) (推荐 :+1:) -3. [Kafka面试题总结](消息队列/kafka.md) (推荐 :+1:) -4. [死信队列](消息队列/死信队列.md) +1. [消息队列面试题](docs/message-queue/mq.md) +2. [RabbitMQ面试题总结](docs/message-queue/rabbitmq.md) (推荐 :+1:) +3. [Kafka面试题总结](docs/message-queue/kafka.md) (推荐 :+1:) +4. [死信队列]() todo # 计算机网络 -[【大厂面试】—— 计算机网络常见面试题总结](计算机基础/网络/计算机网络高频面试题.md) (**知乎1k+收藏!推荐 :+1:**) +[计算机网络常见面试题总结](docs/computer-basic/network.md) (**知乎1k+收藏!推荐 :+1:**) # 数据结构与算法 -[如何高效的刷LeetCode?](https://www.zhihu.com/question/280279208/answer/2377906738) - -[120道Leetcode题解(高频)](https://topjavaer.cn/leetcode/hot120/) - -[常见数据结构总结](https://topjavaer.cn/computer-basic/data-structure.html) - -# 设计模式 - -[字节跳动大佬总结的设计模式PDF](https://t.1yb.co/y96J) - -[设计模式总结](https://topjavaer.cn/advance/design-pattern/) +- [常见数据结构总结](docs/computer-basic/data-structure.md) +- [如何高效的刷LeetCode?](https://www.zhihu.com/question/280279208/answer/2377906738) +- [120道Leetcode题解(高频)](https://topjavaer.cn/leetcode/hot120/) # 海量数据场景题 @@ -189,21 +184,49 @@ 4. [如何在100亿的数据中找到中位数](https://topjavaer.cn/mass-data/4-find-mid-num.html) 5. [找出最热门的查询串](https://topjavaer.cn/mass-data/5-find-hot-string.html) 6. [如何找出排名前500的数字](https://topjavaer.cn/mass-data/6-top-500-num.html) +7. [如何按照 query 的频度排序?](https://topjavaer.cn/mass-data/7-query-frequency-sort.html) +8. [大数据中 TopK 问题的常用套路](https://topjavaer.cn/mass-data/8-topk-template.html) + +# 系统设计 + +- [扫码登录](docs/advance/system-design/1-scan-code-login.md) +- [订单超时未支付自动取消](docs/advance/system-design/2-order-timeout-auto-cancel.md) +- [短链系统设计](docs/advance/system-design/3-short-url.md) +- [超卖问题](docs/advance/system-design/4-oversold.md) +- [秒杀系统设计](docs/advance/system-design/5-second-kill.md) +- [微信红包系统如何设计?](docs/advance/system-design/6-wechat-redpacket-design.md) +- [如何把一个文件较快的发送到100w个服务器?](docs/advance/system-design/7-file-send.md) + +# 安全 + +- [什么是JWT?](docs/advance/excellent-article/16-what-is-jwt.md) +- [单点登录(SSO)设计与实现](docs/advance/system-design/8-sso-design.md) + +# 编程实践 + +1. [线上接口很慢怎么办?](docs/practice/service-performance-optimization.md) +2. [干掉 “重复代码” 的技巧有哪些](docs/advance/excellent-article/4-remove-duplicate-code.md) # 大厂面经汇总 -- [字节跳动](./interview/1-byte-and-dance.md) -- [腾讯](./interview/2-tencent.md) -- [百度](./interview/3-baidu.md) -- [阿里](./interview/4-ali.md) -- [快手](./interview/5-kuaishou.md) -- [美团](./interview/6-meituan.md) -- [shopee](./interview/7-shopee.md) -- [京东](./interview/8-jingdong.md) -- [华为](./interview/9-huawei.md) -- [网易](./interview/10-netease.md) +- [字节跳动](docs/campus-recruit/interview/1-byte-and-dance.md) +- [腾讯](docs/campus-recruit/interview/2-tencent.md) +- [百度](docs/campus-recruit/interview/3-baidu.md) +- [阿里](docs/campus-recruit/interview/4-ali.md) +- [快手](docs/campus-recruit/interview/5-kuaishou.md) +- [美团](docs/campus-recruit/interview/6-meituan.md) +- [shopee](docs/campus-recruit/interview/7-shopee.md) +- [京东](docs/campus-recruit/interview/8-jingdong.md) +- [华为](docs/campus-recruit/interview/9-huawei.md) +- [网易](docs/campus-recruit/interview/10-netease.md) -# 其他优质文章 +# 设计模式 + +[字节跳动大佬总结的设计模式PDF](https://t.1yb.co/y96J) + +[设计模式总结](https://topjavaer.cn/advance/design-pattern/) + +# 优质文章 [优质文章汇总,持续更新中~](https://topjavaer.cn/advance/excellent-article/) @@ -211,13 +234,13 @@ # 工具 -[Git 超详细总结!](工具/git-overview.md)(推荐 :+1:) +[Git 超详细总结!](docs/tools/git-overview.md)(推荐 :+1:) -[Linux 常用命令总结!](工具/linux-overview.md) +[Linux 常用命令总结!](docs/tools/linux-overview.md) -[Docker 基础总结!](工具/docker-overview.md) +[Docker 基础总结!](docs/tools/docker-overview.md) -[Maven 基础总结!](tools/maven-overview.md) +[Maven 基础总结!](docs/tools/maven-overview.md) # 交流 @@ -249,6 +272,6 @@ | 2022.05.03 | 微信收款码 | *哈 | 2元 | | | 2022.06.12 | 微信收款码 | *可 | 8.8元 | | | 2022.10.19 | 微信收款码 | *斌 | 10元 | 支持一下,希望能持续更新 | - - +| 2022.11.16 | 支付宝收款码 | *雄 | 2元 | | +| 2022.12.02 | 微信收款码 | *军 | 5元 | | diff --git "a/Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" "b/Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" deleted file mode 100644 index ca08607..0000000 --- "a/Redis/\347\274\223\345\255\230\347\251\277\351\200\217\343\200\201\347\274\223\345\255\230\351\233\252\345\264\251\343\200\201\347\274\223\345\255\230\345\207\273\347\251\277.md" +++ /dev/null @@ -1,60 +0,0 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [缓存穿透](#%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F) -- [缓存雪崩](#%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9) -- [缓存击穿](#%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF) - - - -# 缓存穿透 - -缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,如果从DB查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了。 - -1. 缓存空值,不会查数据库 -2. 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,查询不存在的数据会被这个bitmap拦截掉,从而避免了对DB的查询压力。 - -布隆可以看成数据库的缩略版,用来判定是否存在值。启动的时候过滤器是要全表扫描的,数据库数据发生变化的时候会更新布隆过滤器。 - -布隆过滤器的原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,将元素通过散列函数映射之后会得到k个点,如果这些点有任何一个0,则被检元素一定不在,直接返回;如果都是1,则查询元素很可能存在,就会去查询redis和数据库。 - -![](E:/project/java/learn/Java-learning/img/bloom-filter.jpg) - -> 图片来源网络 - - - -# 缓存雪崩 - -缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重挂掉。 - -解决方法:在原有的失效时间基础上增加一个随机值,使得过期时间分散一些。 - -# 缓存击穿 - -缓存击穿:大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都落到数据库。缓存击穿是查询缓存中失效的 key,而缓存穿透是查询不存在的 key。 - -解决方法:加互斥锁(redis分布式锁或者使用ReentrantLock),第一个请求的线程可以拿到锁,拿到锁的线程查询到了数据之后设置缓存,其他的线程获取锁失败会等待50ms然后重新到缓存取数据,这样便可以避免大量的请求落到数据库。 - -```java -public String get(key) { - String value = redis.get(key); - if (value == null) { //代表缓存值过期 - String key_mutex = "mutext:key:" + key; - //设置30s的超时,防止del操作失败的时候,下次缓存过期一直不能load db - if (redis.set(key_mutex, 1, 'NX', 'PX', 30000) == 1) { //代表设置成功 - value = db.get(key); - redis.set(key, value, expire_secs); - redis.del(key_mutex); - } else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可 - sleep(50); - get(key); //重试 - } - } else { - return value; - } - } -``` - -SETNX:只有不存在的时候才设置,可以利用它来实现锁的效果。 \ No newline at end of file diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts new file mode 100644 index 0000000..be5e7ac --- /dev/null +++ b/docs/.vuepress/config.ts @@ -0,0 +1,86 @@ +import {defineUserConfig} from "vuepress"; +import theme from "./theme"; + +const {searchPlugin} = require('@vuepress/plugin-search') + +import { gitPlugin } from '@vuepress/plugin-git' + + +export default defineUserConfig({ + lang: "zh-CN", + title: "程序员大彬", + description: "自学转码之路", + base: "/", + dest: './public', + theme, + // 是否开启默认预加载 js + shouldPrefetch: (file, type) => false, + + head: [ + //meta + ["meta", { name: "robots", content: "all" }], + ["meta", {name: "author", content: "大彬"}], + [ + "meta", + { + "http-equiv": "Cache-Control", + content: "no-cache, no-store, must-revalidate", + }, + ], + ["meta", { "http-equiv": "Pragma", content: "no-cache" }], + ["meta", { "http-equiv": "Expires", content: "0" }], + ['meta', {name: 'baidu-site-verification', content: 'code-mtJaPDeFwy'}], + // ['meta', { name: 'google-site-verification', content: 'eGgkbT6uJR-WQeSkhhcB6RbnZ2RtF5poPf1ai-Fgmy8' }], + ['meta', {name: 'keywords', content: 'Java, Spring, Mybatis, SpringMVC, Springboot, 编程, 程序员, MySQL, Redis, 系统设计, 分布式, RPC, 高可用, 高并发'}], + [ + 'script', {}, ` + var _hmt = _hmt || []; + (function() { + var hm = document.createElement("script"); + hm.src = "https://hm.baidu.com/hm.js?f9b36644dd9e756e508a77f272a63e07"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(hm, s); + })(); + ` + ], + ], + + plugins: [ + searchPlugin({ + // 配置项 + }), + gitPlugin({ + createdTime: false, + updatedTime: false, + contributors: false, + }), + ], + //plugins: [ + // copyright({ + // disableCopy: true, + // global: true, + // disableSelection: true, + // author: "大彬", + // license: "MIT", + // hostname: "https://www.topjavaer.cn", + // }), + // [ + // 'vuepress-plugin-baidu-autopush' + // ], + // sitemapPlugin({ + // // 配置选项 + // hostname: "https:www.topjavaer.cn" + // }), + // photoSwipePlugin({ + // // 你的选项 + // }), + // readingTimePlugin({ + // // 你的选项 + // }), + // [ + // nprogressPlugin(), + // ], + // //['@vuepress/nprogress'], + //], +}) +; diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js new file mode 100644 index 0000000..42e09d7 --- /dev/null +++ b/docs/.vuepress/enhanceApp.js @@ -0,0 +1,13 @@ +export default ({router}) => { + router.beforeEach((to, from, next) => { + //对每个页面点击添加百度统计 + if(typeof _hmt!='undefined'){ + if (to.path) { + _hmt.push(['_trackPageview', to.fullPath]); + } + } + + // continue + next(); + }) +}; diff --git a/docs/.vuepress/navbar.ts b/docs/.vuepress/navbar.ts new file mode 100644 index 0000000..16989b2 --- /dev/null +++ b/docs/.vuepress/navbar.ts @@ -0,0 +1,276 @@ +import {navbar} from "vuepress-theme-hope"; + +export default navbar([ + + //"/", + //"/home", + { + text: "主页", + link: "/", + icon: "home", + }, + { + text: "校招", + icon: "campus", + children: [ + {text: "校招分享", link: "/campus-recruit/share"}, + {text: "简历应该这么写", link: "/campus-recruit/resume.md"}, + {text: "项目经验介绍", link: "/campus-recruit/project-experience.md"}, + {text: "编程语言", link: "/campus-recruit/program-language"}, + {text: "面经总结", link: "/campus-recruit/interview/"}, + {text: "秋招内推", link: "https://docs.qq.com/sheet/DYW9ObnpobXNRTXpq"}, + ], + }, + { + text: "Java", + icon: "java", + children: [ + {text: "基础", link: "/java/java-basic.md"}, + {text: "集合", link: "/java/java-collection.md"}, + {text: "并发", link: "/java/java-concurrent.md"}, + {text: "JVM", link: "/java/jvm.md"}, + {text: "Java8", link: "/java/java8"}, + ] + }, + { + text: "框架", + icon: "framework", + children: [ + { + text: "框架", + children: [ + {text: "Spring面试题", link: "/framework/spring.md"}, + {text: "SpringMVC面试题", link: "/framework/springmvc.md"}, + {text: "Mybatis面试题", link: "/framework/mybatis.md"}, + {text: "SpringBoot面试题", link: "/framework/springboot.md"}, + {text: "SpringCloud详解", link: "/framework/springcloud/"}, + {text: "SpringCloud面试题", link: "/framework/springcloud-interview.md"}, + {text: "Netty详解", link: "/framework/netty/"}, + ] + }, + { + text: "消息队列", + children: [ + {text: "消息队列面试题", link: "/message-queue/mq.md"}, + {text: "RabbitMQ面试题", link: "/message-queue/rabbitmq.md"}, + {text: "Kafka面试题", link: "/message-queue/kafka.md"}, + ] + } + ] + }, + { + text: "计算机基础", + icon: "computer", + children: [ + {text: "网络", link: "/computer-basic/network.md"}, + {text: "操作系统", link: "/computer-basic/operate-system.md"}, + {text: "算法", link: "/computer-basic/algorithm.md"}, + {text: "LeetCode题解", link: "/leetcode/hot120"}, + {text: "数据结构", link: "/computer-basic/data-structure.md"}, + ] + }, + { + text: "数据库", + icon: "db", + children: [ + { + text: "关系型数据库", + children: [ + //{text: "MySQL基础", children: ["/database/mysql-basic/"],}, + {text: "MySQL基础", link: "/database/mysql-basic/"}, + {text: "MySQL面试题", link: "/database/mysql.md"}, + {text: "MySQL执行计划详解", link: "/database/mysql-execution-plan.md"}, + ] + }, + { + text: "非关系型数据库", + children: [ + {text: "Redis基础", link: "/redis/redis-basic/"}, + {text: "Redis面试题", link: "/redis/redis.md"}, + {text: "ElasticSearch面试题", link: "https://mp.weixin.qq.com/s/Ffb8NDgavf9QAWYBm0qAVg"}, + ] + }, + ] + }, + { + text: "进阶之路", + icon: "win", + children: [ + { + text: "分布式", + icon: "distribute", + children: [ + {text: "全局唯一ID", link: "/advance/distributed/1-global-unique-id.md"}, + {text: "分布式锁", link: "/advance/distributed/2-distributed-lock.md"}, + {text: "RPC", link: "/advance/distributed/3-rpc.md"}, + {text: "微服务", link: "/advance/distributed/4-micro-service.md"}, + {text: "分布式架构", link: "/advance/distributed/5-distibuted-arch.md"}, + {text: "分布式事务", link: "/advance/distributed/6-distributed-transaction.md"}, + ] + }, + { + text: "高并发", + children: [ + {text: "限流", link: "/advance/concurrent/1-current-limiting.md"}, + {text: "负载均衡", link: "/advance/concurrent/2-load-balance.md"}, + ], + }, + { + text: "设计模式", + icon: "win", + children: [ + {text: "设计模式详解", link: "/advance/design-pattern/"}, + ], + }, + { + text: "系统设计", + children: [ + {text: "扫码登录设计", link: "/advance/system-design/1-scan-code-login.md"}, + {text: "超时订单自动取消", link: "/advance/system-design/2-order-timeout-auto-cancel.md"}, + {text: "短链系统设计", link: "/advance/system-design/3-short-url.md"}, + {text: "微信红包系统如何设计?", link: "/advance/system-design/6-wechat-redpacket-design.md"}, + {text: "单点登录设计与实现", link: "/advance/system-design/8-sso-design.md"}, + ] + }, + { + text: "海量数据", + children: [ + {text: "统计不同号码的个数", link: "/mass-data/1-count-phone-num.md"}, + {text: "出现频率最高的100个词", link: "/mass-data/2-find-hign-frequency-word.md"}, + {text: "查找两个大文件共同的URL", link: "/mass-data/3-find-same-url.md"}, + {text: "如何在100亿数据中找到中位数?", link: "/mass-data/4-find-mid-num.md"}, + {text: "如何查询最热门的查询串?", link: "/mass-data/5-find-hot-string.md"}, + {text: "如何找出排名前 500 的数?", link: "/mass-data/6-top-500-num.md"}, + {text: "如何按照 query 的频度排序?", link: "/mass-data/7-query-frequency-sort.md"}, + {text: "大数据中 TopK 问题的常用套路", link: "/mass-data/8-topk-template.md"}, + ] + }, + { + text: "优质文章", + children: [ + {text: "优质文章汇总", link: "/advance/excellent-article"}, + ] + }, + ] + }, + //{ + // text: "场景题", + // icon: "design", + // children: [ + // { + // text: "海量数据", + // children: [ + // {text: "统计不同号码的个数", link: "/mass-data/count-phone-num.md"}, + // {text: "出现频率最高的100个词", link: "/mass-data/find-hign-frequency-word.md"}, + // ] + // }, + // { + // text: "系统设计", + // children: [ + // {text: "扫码登录设计", link: "/system-design/scan-code-login.md"}, + // ] + // }, + // ] + //}, + { + text: "工具", + icon: "tool", + children: [ + { + text: "开发工具", + children: [ + {text: "Git详解", link: "/tools/git/"}, + {text: "Maven详解", link: "/tools/maven/"}, + {text: "Docker详解", link: "/tools/docker/"}, + {text: "Linux常用命令", link: "/tools/linux"}, + {text: "Nginx面试题", link: "https://mp.weixin.qq.com/s/SKKEeYxif0wWJo6n57rd6A"}, + ] + }, + { + text: "编程利器", + children: [ + {text: "markdown编辑器", link: "/tools/typora-overview.md"}, + ] + }, + ] + }, + { + text: "珍藏资源", + icon: "collection", + children: [ + { + text: "学习资源", + children: [ + {text: "计算机经典电子书PDF", link: "https://github.com/Tyson0314/java-books"}, + {text: "Leetcode刷题笔记", link: "/learning-resources/leetcode-note.md"}, + ] + }, + { + text: "学习路线", + children: [ + {text: "Java学习路线", link: "/learning-resources/java-learn-guide.md"}, + {text: "CS学习路线", link: "/learning-resources/cs-learn-guide.md"}, + ] + }, + + ] + }, + { + text: "关于", + icon: "about", + children: [ + {text: "关于我", link: "/about/introduce.md"}, + {text: "网站日记", link: "/other/site-diary.md"}, + {text: "联系我", link: "/about/contact.md"}, + {text: "留言区", link: "/other/leave-a-message.md"}, + ] + }, + + + //{ text: "Guide", icon: "creative", link: "/guide/" }, + //{ + // text: "Posts", + // icon: "edit", + // prefix: "/posts/", + // children: [ + // { + // text: "Articles 1-4", + // icon: "edit", + // prefix: "article/", + // children: [ + // { text: "Article 1", icon: "edit", link: "article1" }, + // { text: "Article 2", icon: "edit", link: "article2" }, + // "article3", + // "article4", + // ], + // }, + // { + // text: "Articles 5-12", + // icon: "edit", + // children: [ + // { + // text: "Article 5", + // icon: "edit", + // link: "article/article5", + // }, + // { + // text: "Article 6", + // icon: "edit", + // link: "article/article6", + // }, + // "article/article7", + // "article/article8", + // ], + // }, + // { text: "Article 9", icon: "edit", link: "article9" }, + // { text: "Article 10", icon: "edit", link: "article10" }, + // "article11", + // "article12", + // ], + //}, + //{ + // text: "Theme Docs", + // icon: "note", + // link: "https://vuepress-theme-hope.github.io/v2/", + //}, +]); diff --git a/docs/.vuepress/sidebar.ts b/docs/.vuepress/sidebar.ts new file mode 100644 index 0000000..d23d12d --- /dev/null +++ b/docs/.vuepress/sidebar.ts @@ -0,0 +1,176 @@ +import {sidebar} from "vuepress-theme-hope"; + +const {getChildren} = require("./vuepress-sidebar-auto/vuepress-sidebar-auto"); + +export default sidebar({ + "/database/mysql-basic/": [{ + text: "MySQL基础", + collapsable: false, + children: getChildren('./docs/database', 'mysql-basic'), + // children: ["1-data-type"], + }, + ], + "/redis/redis-basic/": [ + { + text: "Redis基础", + collapsable: false, + children: getChildren('./docs/redis', 'redis-basic'), + }, + ], + "/advance/design-pattern/": [ + { + text: "设计模式", + collapsable: false, + children: getChildren('./docs/advance', 'design-pattern'), + }, + ], + "/tools/docker/": [ + { + text: "Docker基础", + collapsable: false, + children: getChildren('./docs/tools', 'docker'), + }, + ], + "/tools/git/": [ + { + text: "Git基础", + collapsable: false, + children: getChildren('./docs/tools', 'git'), + }, + ], + "/leetcode/hot120": [ + { + text: "LeetCode题解", + collapsable: false, + children: getChildren('./docs/leetcode', 'hot120'), + }, + ], + "/tools/maven/": [ + { + text: "Maven基础", + collapsable: false, + children: getChildren('./docs/tools', 'maven'), + }, + ], + "/framework/netty/": [ + { + text: "Netty基础", + collapsable: false, + children: getChildren('./docs/framework', 'netty'), + }, + ], + "/framework/springcloud/": [ + { + text: "SpringCloud基础", + collapsable: false, + children: getChildren('./docs/framework', 'springcloud'), + }, + ], + "/java/java8/": [ + { + text: "java8新特性", + collapsable: false, + children: getChildren('./docs/java', 'java8'), + }, + ], + "/campus-recruit/interview/": [ + { + text: "面经合集", + collapsable: true, + children: getChildren('./docs/campus-recruit', 'interview'), + }, + ], + "/advance/excellent-article": [ + { + text: "优质文章汇总", + collapsable: false, + children: getChildren('./docs/advance', 'excellent-article'), + }, + ], + "/advance/concurrent": [ + { + text: "高并发", + collapsable: false, + children: getChildren('./docs/advance', 'concurrent'), + }, + ], + "/tools/linux/": [ + { + text: "linux常用命令", + collapsable: false, + children: getChildren('./docs/tools', 'linux'), + }, + ], + "/campus-recruit/program-language/": [ + { + text: "编程语言", + collapsable: true, + children: getChildren('./docs/campus-recruit', 'program-language'), + }, + ], + "/advance/system-design": [ + { + text: "系统设计", + collapsable: false, + children: getChildren('./docs/advance', 'system-design'), + }, + ], + "/campus-recruit/share": [ + { + text: "校招分享", + collapsable: false, + children: getChildren('./docs/campus-recruit', 'share'), + }, + ], + "/mass-data": [ + { + text: "海量数据", + collapsable: false, + children: getChildren('./docs', '/mass-data'), + }, + ], + + //'/': "auto", //不能放在数组第一个,否则会导致右侧栏无法使用 + //"/", + //"/home", + //"/slide", + //{ + // icon: "creative", + // text: "Guide", + // prefix: "/guide/", + // link: "/guide/", + // children: "structure", + //}, + //{ + // text: "Articles", + // icon: "note", + // prefix: "/posts/", + // children: [ + // { + // text: "Articles 1-4", + // icon: "note", + // collapsable: true, + // prefix: "article/", + // children: ["article1", "article2", "article3", "article4"], + // }, + // { + // text: "Articles 5-12", + // icon: "note", + // children: [ + // { + // text: "Articles 5-8", + // icon: "note", + // collapsable: true, + // prefix: "article/", + // children: ["article5", "article6", "article7", "article8"], + // }, + // { + // text: "Articles 9-12", + // icon: "note", + // children: ["article9", "article10", "article11", "article12"], + // }, + // ], + // }, + // ], + //}, +}); diff --git a/docs/.vuepress/styles/index.scss b/docs/.vuepress/styles/index.scss new file mode 100644 index 0000000..e69de29 diff --git a/docs/.vuepress/styles/palette.scss b/docs/.vuepress/styles/palette.scss new file mode 100644 index 0000000..e69de29 diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts new file mode 100644 index 0000000..a4c25a3 --- /dev/null +++ b/docs/.vuepress/theme.ts @@ -0,0 +1,166 @@ +import {hopeTheme} from "vuepress-theme-hope"; +import navbar from "./navbar"; +import sidebar from "./sidebar"; + +export default hopeTheme({ + hostname: "https://www.topjavaer.cn", + + author: { + name: "大彬", + url: "https://www.topjavaer.cn", + }, + + iconAssets: "//at.alicdn.com/t/c/font_3573089_m0vn9di8q9.css", + iconPrefix: "iconfont icon-", + //iconAssets: "iconfont", + + darkmode: "toggle", + + fullscreen: false, + + logo: "/logo.svg", + + repo: "Tyson0314/Java-learning", + + docsDir: "docs", + + // navbar + navbar: navbar, + + // sidebar + sidebar: sidebar, + headerDepth: 5, + collapsable: true, + + displayFooter: true, + + // footer: '
粤ICP备2022005190号-2 |' + + // '关于网站', + + footer: '粤ICP备2022005190号-2', + + pageInfo: ["Author", "Original", "Date", "Category", "Tag", "ReadingTime"], + + blog: { + description: "非科班自学转码选手,校招拿了多家互联网大厂offer", + intro: "https://mp.weixin.qq.com/s/84ZDT5d9TIbnyg-jeRKIIA", + medias: { + Github: "https://github.com/Tyson0314", + Gitee: "https://gitee.com/tysondai", + ZhiHu: "https://www.zhihu.com/people/dai-shu-bin-13", + }, + }, + + // encrypt: { + // config: { + // "/guide/encrypt.html": ["1234"], + // }, + // }, + + plugins: { + blog: { + autoExcerpt: true, + }, + + // If you don't need comment feature, you can remove following option + // The following config is for demo ONLY, if you need comment feature, please generate and use your own config, see comment plugin documentation for details. + // To avoid disturbing the theme developer and consuming his resources, please DO NOT use the following config directly in your production environment!!!!! + comment: { + /** + * Using Giscus + */ + provider: "Giscus", + repo: "Tyson0314/topjavaer", + repoId: "R_kgDOHxs_3g", + category: "Announcements", + categoryId: "DIC_kwDOHxs_3s4CQpxA", +// + /** + * Using Twikoo + */ + // provider: "Twikoo", + // envId: "https://twikoo.ccknbc.vercel.app", +// + /** + * Using Waline + */ + // provider: "Waline", + // serverURL: "https://vuepress-theme-hope-comment.vercel.app", + }, + + mdEnhance: { + enableAll: true, + presentation: { + plugins: ["highlight", "math", "search", "notes", "zoom"], + }, + }, + + //myplugin + copyright: { + disableCopy: true, + global: true, + author: "大彬", + license: "MIT", + hostname: "https://www.topjavaer.cn", + }, + baiduAutoPush: {}, + sitemapPlugin: { + // 配置选项 + hostname: "https:www.topjavaer.cn" + }, + photoSwipePlugin: { + // 你的选项 + }, + readingTimePlugin: {}, + + nprogressPlugin: {}, + + //searchPlugin: { + // appId: "xxx", + // apiKey: "xxxx", + // indexName: "topjavaer.cn", + // locales: { + // "/": { + // placeholder: "搜索文档", + // translations: { + // button: { + // buttonText: "搜索文档", + // buttonAriaLabel: "搜索文档", + // }, + // modal: { + // searchBox: { + // resetButtonTitle: "清除查询条件", + // resetButtonAriaLabel: "清除查询条件", + // cancelButtonText: "取消", + // cancelButtonAriaLabel: "取消", + // }, + // startScreen: { + // recentSearchesTitle: "搜索历史", + // noRecentSearchesText: "没有搜索历史", + // saveRecentSearchButtonTitle: "保存至搜索历史", + // removeRecentSearchButtonTitle: "从搜索历史中移除", + // favoriteSearchesTitle: "收藏", + // removeFavoriteSearchButtonTitle: "从收藏中移除", + // }, + // errorScreen: { + // titleText: "无法获取结果", + // helpText: "你可能需要检查你的网络连接", + // }, + // footer: { + // selectText: "选择", + // navigateText: "切换", + // closeText: "关闭", + // searchByText: "搜索提供者", + // }, + // noResultsScreen: { + // noResultsText: "无法找到相关结果", + // suggestedQueryText: "你可以尝试查询", + // }, + // }, + // }, + // }, + // }, + // }, + }, +}) +; diff --git a/docs/.vuepress/vuepress-sidebar-auto/vuepress-sidebar-auto.js b/docs/.vuepress/vuepress-sidebar-auto/vuepress-sidebar-auto.js new file mode 100644 index 0000000..29d0ca4 --- /dev/null +++ b/docs/.vuepress/vuepress-sidebar-auto/vuepress-sidebar-auto.js @@ -0,0 +1,92 @@ +//侧边栏 +// const autosidebar = require('vuepress-auto-sidebar-doumjun') +const fs = require('fs') +const path = require('path') + +/** + * 过滤所要导航的文件 + * 文件名 包含.md 但 不包含 README */ +function checkFileType(path) { + return path.includes(".md")&&(!path.includes("README")); +} + +/** + * 格式化文件路径*/ +function prefixPath(basePath, dirPath) { + let index = basePath.indexOf("/") +// 去除一级目录地址 + basePath = basePath.slice(index, path.length) +// replace用于处理windows电脑的路径用\表示的问题 + return path.join(basePath, dirPath).replace(/\\/g, "/") +} + +/** + * 截取文档路径*/ +function getPath(path,ele) { + let item=prefixPath(path,ele); + //if (item.split('/')[6]) { + // return item.split('/')[3] + '/' + item.split('/')[4]+ '/' + item.split('/')[5]+ '/' + item.split('/')[6] + //}else if (item.split('/')[5]) { + // return item.split('/')[3] + '/' + item.split('/')[4]+ '/' + item.split('/')[5] + //}else if (item.split('/')[4]) { + // return item.split('/')[3] + '/' + item.split('/')[4] + //} else { + // return item.split('/')[3] + //} + + if (item.split('/')[6]) { + return item.split('/')[4]+ '/' + item.split('/')[5]+ '/' + item.split('/')[6] + }else if (item.split('/')[5]) { + return item.split('/')[4]+ '/' + item.split('/')[5] + }else { + return item.split('/')[4] + } +} + +/** + * 递归获取分组信息并排序*/ +function getGroupChildren(path,ele,root) { + let pa = fs.readdirSync(path + "/" + ele + "/"); + let palist=pa; + // console.log("pathlist", pa) + pa = palist.sort(function (a, b) { + //console.log("a " + a, a.replace(".md", "").match(/^[^-]/)) + //console.log("b " + b, b.replace(".md", "").match(/^[^-]/)) + let num1 = a.split("-")[0] + let num2 = b.split("-")[0] + //console.log("num1", num1, "num2", num2) + //console.log(num1 - num2) + return num1 - num2 + //return a.replace(".md", "").match(/^[^-]/) - b.replace(".md", "").match(/^[^-]/) + //return a.replace(".md", "").match(/[^-]*$/) - b.replace(".md", "").match(/[^-]*$/) + }); + // console.log("after sort ", pa) + pa.forEach(function (item, index) { + let info = fs.statSync(path + "/" + ele + "/" + item); + if (info.isDirectory()) { + let children = []; + let group = {}; + group.title = item.split('-')[1]; + group.collapsable = true; + group.sidebarDepth = 4; + getGroupChildren(path + "/" + ele, item, children); + group.children=children; + root.push(group); + } else { + if (checkFileType(item)) { + root.push(getPath(path + "/" + ele, item)); + } + } + }) +} +/** + * 初始化*/ +function getChildren(path,ele){ + var root=[] + getGroupChildren(path,ele,root); + return root; +} + +// console.log("demo", getChildren('./docs','database/mysql-basic')) + +module.exports = {getChildren: getChildren}; diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c611e07 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,82 @@ +--- +home: true +icon: home +title: 主页 +heroImage: /logo.png +heroText: 程序员大彬 +tagline: 非科班自学转码之路 +actions: + - text: 来不及了,快上车 💡 + link: /java/java-basic.md + type: primary +features: + - title: 经典计算机书籍 + icon: repo + details: 大彬精心整理200本经典计算机书籍 + link: https://github.com/Tyson0314/java-books + - title: Leetcode算法笔记 + icon: note + details: 谷歌师兄整理的Leetcode算法笔记 + link: learning-resources/leetcode-note.html +projects: + - name: java-books + desc: 经典计算机书籍电子版 + link: https://github.com/Tyson0314/java-books + icon: /assets/img/vuepress.png + + - name: Leetcode算法手册 + desc: Leetcode算法手册 + link: learning-resources/leetcode-note.html + icon: /assets/img/vuepress-hope-logo.svg + + +--- + + + +大彬是**非科班**出身,大三开始自学Java,校招斩获**京东、携程、华为**等offer。作为一名转码选手,深感这一路的不易。 + +**希望我的分享可以帮助更多的小伙伴,我踩过的坑你们不要再踩**! + +[](http://img.dabin-coder.cn/image/微信群.png) +[](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247488751&idx=1&sn=507e27534b6ea5f4b3771b30e1fcf57e&chksm=ce98e9a9f9ef60bfbf1370899b49181bae5247e5935714f7ad9e3d06c0028a25c0bfc34d4441#rd) +[](https://space.bilibili.com/1729916794) +[](https://www.zhihu.com/people/dai-shu-bin-13) +[](https://github.com/Tyson0314/java-books) + +## 秋招提前批信息汇总 + +[秋招提前批及正式批信息汇总(含内推)](https://docs.qq.com/sheet/DYW9ObnpobXNRTXpq?tab=BB08J2) + +## 面试手册电子版 + +本网站所有内容已经汇总成**PDF电子版**,需要电子版的小伙伴,可以在公众号【**程序员大彬**】后台回复【**面试**】,即可获取~ + +## 学习路线 + +![](http://img.dabin-coder.cn/image/20220530232715.png) + +> 微信搜索【程序员大彬】,回复【学习路线】获取**高清图** + +## 交流群 + +学习路上,难免遇到很多坑,为方便大家交流求职和技术问题,我建了**求职&技术交流群**,在群里可以讨论技术、面试相关问题,也可以获得阿里、字节等大厂的内推机会! + +交流群学习氛围很浓厚,截个图给大家感受下。 + + + +![](http://img.dabin-coder.cn/image/交流群2.png) + + + +感兴趣的小伙伴可以扫描下方的二维码**加我微信**,**备注加群**,我拉你进群,一起学习成长! + +![](http://img.dabin-coder.cn/image/微信加群.png) + +## 参与贡献 + +1. 如果您对本项目有任何建议或发现文中内容有误的,欢迎提交 issues 进行指正。 +2. 对于文中我没有涉及到知识点,欢迎提交 PR。 +3. 如果您有文章推荐请以 markdown 格式到邮箱 `1713476357@qq.com`, +[中文技术文档的写作规范指南](https://github.com/ruanyf/document-style-guide)。 diff --git a/docs/about/contact.md b/docs/about/contact.md new file mode 100644 index 0000000..01e0eaa --- /dev/null +++ b/docs/about/contact.md @@ -0,0 +1,27 @@ +--- +sidebar: heading +--- + +## 联系我 + +如果有什么疑问或者建议,欢迎添加大彬微信进行交流~ + +
+

+
+ +## 交流群 + +学习路上,难免遇到很多坑,为方便大家交流求职和技术问题,我建了**求职&技术交流群**,在群里可以讨论技术、面试相关问题,也可以获得阿里、字节等大厂的内推机会! + +交流群学习氛围很浓厚,截个图给大家感受下。 + + + +![](http://img.dabin-coder.cn/image/交流群2.png) + + + +感兴趣的小伙伴可以扫描下方的二维码**加我微信**,**备注加群**,我拉你进群,一起学习成长! + +![](http://img.dabin-coder.cn/image/微信加群.png) diff --git a/docs/about/introduce.md b/docs/about/introduce.md new file mode 100644 index 0000000..6e8c6f1 --- /dev/null +++ b/docs/about/introduce.md @@ -0,0 +1,66 @@ +--- +sidebar: heading + +--- + +大家好,我是大彬~ + +我是非科班出身,本科学的不是计算机,大四开始自学Java,并且找到了中大厂的offer。自学路上遇到不少问题,每天晚上都是坚持到一两点才睡觉,**最终也拿到了30w的offer**。 + +![](http://img.dabin-coder.cn/image/image-20211206000941636.png) + +下面来说说自己的经历吧(附自学路线)。 + +## 接触编程 + +大学以前基本没碰过电脑,家里没电脑,也没去过网吧。高中的计算机课程,期末作业要完成一个自我介绍的PPT,也不会做,最后直接抄同桌的作业(复制粘贴都不会。。还得同桌教,捂脸)。 + +高考完一个月后,买了电脑,真正开始使用上了电脑。 + +大一上学期的时候,系里开了一门C语言的课程,这也是我第一次接触编程。教材是英文的,刚开始学还是挺头大的。每次课程作业,周围的同学都是一顿复制粘贴,我也一样嘿嘿。 + +记得在讲指针那一章的时候,听的一头雾水。稍微走神,回过头来,已经不知道讲的是啥了。 + +后面系里开设了兴趣小组,因为平时比较闲,也想着去捣鼓点东西,就去参加了。刚开始的时候,什么都不懂,老师推荐我学一下51单片机,拿了一本厚厚的51单片机的书籍,跟着书里的demo敲了一遍,发现了新天地!原来编程这么有意思! + +![](https://pic2.zhimg.com/80/v2-2ac0759cc48ed0d17b9ce46a13bb0f1e_720w.jpg) + +记得第一次跑出流水灯的时候,那叫一个激动啊,满满的都是成就感!后面也写了一些电机、红外遥控等demo。从那以后,激发了我学习编程的兴趣。 + +到了大二,辅导员在群里发布全国电子设计大赛的信息,参赛题跟四轴飞行器相关,那段时间对四轴飞行器比较感兴趣,于是约了两个小伙伴一块参加。距离比赛时间只有一个月,在那一个月的时间里,每天都是早出晚归,吃饭的时候还在想着哪一块代码出了bug。虽然最后没能获奖,但是在这个过程中,学到很多知识,编程能力也有了很大的提升。 + +## 决定转码 + +转眼间,大三开学,开始纠结考研还是工作,思考了一周时间,也进了系里的实验室体验了一把研究生生活,最后还是听从内心的想法,决定直接找工作。 + +我咨询了本专业的师兄师姐们往年的就业情况,他们大部分人还是找了互联网方向的工作。有一个在传统行业的师兄,也劝我投互联网公司的岗位,因为在传统行业加班也不少,但是工资贼低。。最后决定转行程序员,找后端相关的工作。 + +那么学习哪一种语言呢?当时有三个选择:c++,Java,python。 + +那段时间python比较火,但是经过一番深思熟虑之后,还是选择了Java。为什么选择Java呢? + +很简单,市场需求大,学习难度适中。相比科班同学来说,我缺乏系统的计算机基础知识,而距离秋招也只有不到一年时间,所以还是选择学习难度低一点的Java。 + +## 闭关自学 + +确定方向后,便开始制定学习路线。不得不说,Java要学的东西是真的多。。 + +自学期间遇到挺多问题,比如一些环境配置问题,有时候搞上好几天,很打击积极性。中途也有很多次怀疑自己的水平,是不是不适合干编程,差点就放弃了。幸好最后还是坚持了下来。 + +半年多的时间,除了平时上课,其他时间就是在图书馆。周末或者节假日,每天都是7点起床,八点到图书馆开始学习,到了晚上十点,图书馆闭馆,才回宿舍,每天都是图书馆最后走的一批。回到宿舍,洗完澡,继续肝到十二点多(卷王!)。 + +![img](https://pic3.zhimg.com/80/v2-25f6523ffc0ea6982c576b75458695dc_720w.jpg) + +> 很多人在问,大三才开始自学Java,来的及吗? 我觉得,还是看个人的投入程度和学习能力。有些人自学能力强一点,每天可以投入10小时及以上的时间去学习,那完全没问题。 + +自学过程还是挺辛苦的,要耐得住寂寞,最最重要的还是得坚持! + +我根据自己的自学经历,整理了一些学习过程中踩坑总结的经验,希望自学的小伙伴可以少走弯路: + +- **注重实践**,不要只是埋头看书,一定要多动手写代码。 +- 刚开始自学的时候,可以不用太深究细节,不然可能会怀疑自己的学习能力。等到后面有了一定的基础,回过头来重新回顾,可能会恍然大悟,没有当初想的那么难。 +- 可以适当加一些[交流群](https://topjavaer.cn/about/contact.html#%E4%BA%A4%E6%B5%81%E7%BE%A4),遇到不懂的知识点,多与其他人交流。 + +## 自学路线 + +具体学习路线[点这里](https://topjavaer.cn/learning-resources/java-learn-guide.html#%E8%87%AA%E5%AD%A6%E8%B7%AF%E7%BA%BF) \ No newline at end of file diff --git a/docs/advance/concurrent/1-current-limiting.md b/docs/advance/concurrent/1-current-limiting.md new file mode 100644 index 0000000..52003ff --- /dev/null +++ b/docs/advance/concurrent/1-current-limiting.md @@ -0,0 +1,139 @@ +# 限流算法 + +大多数情况下,我们不需要自己实现一个限流系统,但限流在实际应用中是一个非常微妙、有很多细节的系统保护手段,尤其是在高流量时,了解你所使用的限流系统的限流算法,将能很好地帮助你充分利用该限流系统达到自己的商业需求和目的,并规避一些使用限流系统可能带来的大大小小的问题。 + +## 令牌桶算法 + +令牌桶(token bucket)算法,指的是设计一个容器(即“桶”),由某个组件持续运行往该容器中添加令牌(token),令牌可以是简单的数字、字符或组合,也可以仅仅是一个计数,然后每个请求进入系统时,需要从桶中领取一个令牌,所有请求都必须有令牌才能进入后端系统。当令牌桶空时,拒绝请求;当令牌桶满时,不再往其中添加新的令牌。 +令牌桶算法的架构如图1所示: + +![](http://img.dabin-coder.cn/image/限流1.png) + +令牌桶算法的实现逻辑如下: + +首先会有一个定义的时间窗口的访问次数阈值,例如每天1000人,每秒5个请求之类,限流系统一般最小粒度是秒,再小就会因为实现和性能的原因而变得不准确或不稳定,假设是T秒内允许N个请求,那么令牌桶算法则会使令牌添加组件每T秒往令牌桶中添加N个令牌。 + +其次,令牌桶需要有一个最大值M,当令牌添加组件检测到令牌桶中已经有M个令牌时,剩余的令牌会被丢弃。反映到限流系统中,可以认为是当前系统允许的瞬时最大流量,但不是持续最大流量。例如令牌桶中的令牌最大数量是100个,每秒钟会往其中添加10个新令牌,当令牌满的时候,突然出现100 TPS的流量,这时候是可以承受的,但是假如连续两秒的100 TPS流量就不行,因为令牌添加速度是一秒10个,添加速度跟不上使用速度。 + +因此,凡是使用令牌桶算法的限流系统,我们都会注意到它在配置时要求两个参数: + +- 平均阈值(rate或average) +- 高峰阈值(burst或peak) + + +通过笔者的介绍,读者应该意识到,令牌桶算法的高峰阈值是有特指的,并不是指当前限流系统允许的最高流量。因为这一描述可能会使人认为只要低于该阈值的流量都可以,但事实上不是这样,因为只要高于添加速度的流量持续一段时间都会出现问题。 + +反过来说,令牌桶算法的限流系统不容易计算出它支持的最高流量,因为它能实时支持的最高流量取决于那整个时间段内的流量变化情况即令牌存量,而不是仅仅取决于一个瞬时的令牌量。 + +最后,当有组件请求令牌的时候,令牌桶会随机挑选一个令牌分发出去,然后将该令牌从桶中移除。注意,此时令牌桶不再做别的操作,令牌桶永远不会主动要求令牌添加组件补充新的令牌。 + +令牌桶算法有一个同一思想、方向相反的变种,被称为漏桶(leaky bucket)算法,它是令牌桶的一种改进,在商业应用中非常广泛。 + +漏桶算法的基本思想,是将请求看作水流,用一个底下有洞的桶盛装,底下的洞漏出水的速率是恒定的,所有请求进入系统的时候都会先进入这个桶,并慢慢由桶流出交给后台服务。桶有一个固定大小,当水流量超过这个大小的时候,多余的请求都会被丢弃。 + +漏桶算法的架构如图所示: + +![](http://img.dabin-coder.cn/image/限流2.png) + +漏桶算法的实现逻辑如下: + +- 首先会有一个容器存放请求,该容器有一个固定大小M,所有请求都会被先存放到该容器中。 +- 该容器会有一个转发逻辑,该转发以每T秒N个请求的速率循环发生。 +- 当容器中请求数已经达到M个时,拒绝所有新的请求。 + + +因此同样地,漏桶算法的配置也需要两个值:平均值(rate)和峰值(burst)。只是平均值这时候是用来表示漏出的请求数量,峰值则是表示桶中可以存放的请求数量。 + +注意:漏桶算法和缓冲的限流思想不是一回事! + +同样是将请求放在一个容器中,漏桶算法和缓冲不是一个用途,切不可搞混,它们的区别如下: + +- 漏桶算法中,存在桶中的请求会以恒定的速率被漏给后端业务服务器,而缓冲思想中,放在缓冲区域的请求只有等到后端服务器空闲下来了,才会被发出去。 +- 漏桶算法中,存在桶中的请求是原本就应该被系统处理的,是系统对外界宣称的预期,不应该被丢失,而缓冲思想中放在缓冲区域的请求仅仅是对意外状况的尽量优化,并没有任何强制要求这些请求可以被处理。 + + +漏桶算法和令牌桶算法在思想上非常接近,而实现方向恰好相反,它们有如下的相同和不同之处: + +- 令牌桶算法以固定速率补充可以转发的请求数量(令牌),而漏桶算法以固定速率转发请求; +- 令牌桶算法限制数量的是预算数,漏桶算法限制数量的是实际请求数; +- 令牌桶算法在有爆发式增长的流量时可以一定程度上接受,漏桶算法也是,但当流量爆发时,令牌桶算法会使业务服务器直接承担这种流量,而漏桶算法的业务服务器感受到的是一样的速率变化。 + + +因此,通过以上比较,我们会发现漏桶算法略优于令牌桶算法,因为漏桶算法对流量控制更平滑,而令牌桶算法在设置的数值范围内,会将流量波动忠实地转嫁到业务服务器头上。 + +漏桶算法在Nginx和分布式的限流系统例如Redis的限流功能中都有广泛应用,是目前业界最流行的算法之一。 + +## 时间窗口算法 + +时间窗口算法是比较简单、基础的限流算法,由于它比较粗略,不适合大型、流量波动大或者有更精细的流量控制需求的网站。 + +时间窗口算法根据确定时间窗口的方式,可以分为两种: + +- 固定时间窗口算法 +- 滑动时间窗口算法 + + +固定时间窗口算法最简单,相信如果让初次接触限流理念的读者去快速设计实现一个限流系统的话,也可以很快想到这种算法。这种算法即固定一个时间段内限定一个请求阈值,没有达到则让请求通过,达到数量阈值了就拒绝请求。步骤如下: + +- 先确定一个起始时间点,一般就是系统启动的时间。 +- 从起始时间点开始,根据我们的需求,设置一个最大值M,开始接受请求并从0开始为请求计数。 +- 在时间段T内,请求计数超过M时,拒绝所有剩下的请求。 +- 超过时间段T后,重置计数。 + + +固定时间窗口算法的思路固然简单,但是它的逻辑是有问题的,它不适合流量波动大和有精细控制流量需求的服务。让我们看以下例子: + +假设我们的时间段T是1秒,请求最大值是10,在第一秒内,请求数量分布是第500毫秒时有1个请求,第800毫秒时有9个请求,如图3所示: + +![](http://img.dabin-coder.cn/image/限流3.png) + +这是对于第一秒而言,这个请求分布是合理的。 + +此时第二秒的第200毫秒(即两秒中的第1200毫秒)内,又来了10个请求,如图4所示: + +![](http://img.dabin-coder.cn/image/限流4.png) + +单独看第二秒依然是合理的,但是两个时间段连在一起的时候,就出现了问题,如图5所示: + +![](http://img.dabin-coder.cn/image/限流5.png) + +从500毫秒到1200毫秒,短短700毫秒的时间内后端服务器就接收了20个请求,这显然违背了一开始我们希望1秒最多10个的初衷。这种远远大于预期流量的流量加到后端服务器头上,是会造成不可预料的后果的。因此,人们改进了固定窗口的算法,将其改为检查任何一个时间段都不超过请求数量阈值的时间窗口算法:滑动时间窗口算法。 + +滑动时间窗口算法要求当请求进入系统时,回溯过去的时间段T,找到其中的请求数量,然后决定是否接受当前请求,因此,滑动时间窗口算法需要记录时间段T内请求到达的时间点,逻辑如图6所示: + +![](http://img.dabin-coder.cn/image/限流6.png) + +解释如下: + +1、确定一个起始时间点,一般就是系统启动的时间,并记录该点为时间窗口的开始点。然后创建一个空的列表作为时间窗口内请求进入的时间戳记录。 + +2、当请求到来时,使用当前时间戳比较它是否在时间窗口起始点加上T时间段(从开始点到开始点+T就是时间窗口)内。 + +- 如果在,则查看当前时间窗口内记录的所有请求的数量: + - 如果超过,则拒绝请求。 + - 如果没有,则将该请求加入到时间戳记录中,并将请求交给后端业务服务器。 +- 如果不在,则查看时间戳记录,将时间戳最久远的记录删除,然后将时间窗口的开始点更新为第二久远的记录时间,然后回到步骤2,再次检查时间戳是否在时间窗口内。 + + +滑动时间窗口尽管有所改进,但依然不能很好应对某个时间段内突发大量请求,而令牌桶和漏桶算法就由于允许指定平均请求率和最大瞬时请求率,它比时间窗口算法控制更精确。 + +时间窗口算法可以通过多时间窗口来改进。例如,可以设置一个1秒10 TPS的时间窗口限流和一个500毫秒5 TPS的时间窗口限流,二者同时运行,如此就可以保证更精确的限流控制。 + +## 队列法 + +队列法与漏桶算法很类似,都是将请求放入到一个区域,然后业务服务器从中提取请求,但是队列法采用的是完全独立的外部系统,而不是依附于限流系统。队列法的架构如图7所示: + +![](http://img.dabin-coder.cn/image/限流7.png) + +与漏桶算法相比,队列法的优势如下: + +- 由业务逻辑层决定请求收取的速度。限流系统即队列不需要再关注流量的设置(例如T是多少,N是多少,M又是多少等等),只需要专注保留发送的请求,而业务服务器由于完全掌控消息的拉取,可以根据自身条件决定请求获取的速度,更加自由。 +- 完全将业务逻辑层保护起来,并且可以增加服务去消费这些请求。这一手段将业务服务器完全隐藏在了客户端后面,由队列去承担所有流量,也可以更好地保护自身不受到恶意流量的攻击。 +- 队列可以使用更健壮、更成熟的服务,这些服务比限流系统复杂,但能够承受大得多的流量。例如,业务服务器使用的是像阿里云或者AWS这样的消息队列的话,业务服务器就不用担心扩容的问题了,只要请求对实时性的要求不高。业务服务器由于使用了云服务,队列一端的扩容不用担心,而由于消息是自由决定拉取频率和处理速度,自身的扩容压力也就不那么大了。 + + +但队列法最大的缺陷,就是服务器不能直接与客户端沟通,因此只适用于客户端令业务服务器执行任务且不要求响应的用例,所有客户端需要有实质响应的服务都不能使用。例如,业务服务器提供的服务是消息发送服务,那么这种模式就可以的,但如果客户端是请求某些用户信息,那这种方式就完全不可行了。 + + + +> 本文摘录自《深入浅出大型网站架构设计》 \ No newline at end of file diff --git a/docs/advance/concurrent/2-load-balance.md b/docs/advance/concurrent/2-load-balance.md new file mode 100644 index 0000000..968d6d0 --- /dev/null +++ b/docs/advance/concurrent/2-load-balance.md @@ -0,0 +1,164 @@ +# 高可用——负载均衡 + +## **一、 什么是负载均衡?** + +**什么是负载均衡?** + +记得第一次接触 Nginx 是在实验室,那时候在服务器部署网站需要用 Nginx 。Nginx 是一个服务组件,用来反向代理、负载平衡和 HTTP 缓存等。那么这里的 负载均衡 是什么? + +负载均衡(LB,Load Balance),是一种技术解决方案。用来在多个资源(一般是服务器)中分配负载,达到最优化资源使用,避免过载。 + + + +![](http://img.dabin-coder.cn/image/负载均衡1.jpg) + + + +资源,相当于每个服务实例的执行操作单元,负载均衡就是将大量的数据处理操作分摊到多个操作单元进行执行,用来解决互联网分布式系统的大流量、高并发和高可用的问题。那什么是高可用呢? + +## **二、什么是高可用?** + +**首先了解什么是高可用?** + +这是 CAP 定理是分布式系统的基础,也是分布式系统的 3 个指标: + +1. Consistency(一致性) +2. Availability(可用性) +3. Partition tolerance(分区容错性) + +那高可用(High Availability)是什么?高可用,简称 HA,是系统一种特征或者指标,通常是指,提供一定性能上的服务运行时间,高于平均正常时间段。反之,消除系统服务不可用的时间。 + +衡量系统是否满足高可用,就是当一台或者多台服务器宕机的时候,系统整体和服务依然正常可用。 + +举个例子,一些知名的网站保证 4 个 9 以上的可用性,也就是可用性超过 99.99%。那 0.01% 就是所谓故障时间的百分比。比如电商网站有赞,服务不可用会造成商家损失金钱和用户。那么在提高可用性基础上同时,对系统宕机和服务不可用会有补偿。 + + + +![](http://img.dabin-coder.cn/image/负载均衡2.jpg) + + + +比如下单服务,可以使用带有负载均衡的多个下单服务实例,代替单一的下单服务实例,即使用冗余的方式来提高可靠性。 + +总而言之,负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一。一般通过负载均衡,冗余同一个服务实例的方式,解决分布式系统的大流量、高并发和高可用的问题。负载均衡核心关键:在于是否分配均匀。 + +## **三、常见的负载均衡案例** + + + +![](http://img.dabin-coder.cn/image/负载均衡3.jpg) + + + +场景1:微服务架构中,网关路由到具体的服务实例 hello: + +- 两个相同的服务实例 hello service ,一个端口 8000 ,另一个端口 8082 +- 通过 Kong 的负载均衡 LB 功能,让请求均匀的分发到两个 hello 服务实例 +- Kong 的负载均衡策略算法很多:默认 weighted-round-robin 算法,还有 consumer: consumer id 作为 hash 算法输入值等 + + + +![](http://img.dabin-coder.cn/image/负载均衡4.jpg) + + + +场景2:微服务架构中,A 服务调用 B 服务的集群。通过了 Ribbon 客户端负载均衡组件: + +- 负载均衡策略算法并不高级,最简单的是随机选择和轮循 + +## **四、互联网分布式系统解决方案** + + + +![](http://img.dabin-coder.cn/image/负载均衡5.jpg) + + + +常见的互联网分布式系统架构分为几层,一般如下: + +- 客户端层:比如用户浏览器、APP 端 +- 反向代理层:技术选型 Nignx 或者 F5 等 +- Web 层:前后端分离场景下, Web 端可以用 NodeJS 、 RN 、Vue +- 业务服务层:用 Java 、Go,一般互联网公司,技术方案选型就是 SC 或者 Spring Boot + Dubbo 服务化 +- 数据存储层:DB 选型 MySQL ,Cache 选型 Redis ,搜索选型 ES 等 + +一个请求从第 1 层到第 4 层,层层访问都需要负载均衡。即每个上游调用下游多个业务方的时候,需要均匀调用。这样整体系统来看,就比较负载均衡 + +**第 1 层:客户端层 -> 反向代理层 的负载均衡** + +客户端层 -> 反向代理层的负载均衡如何实现呢? + +答案是:DNS 的轮询。 DNS 可以通过 A (Address,返回域名指向的 IP 地址)设置多个 IP 地址。比如这里访问 [http://bysocket.com](https://link.zhihu.com/?target=http%3A//bysocket.com) 的 DNS 配置了 ip1 和 ip2 。为了反向代理层的高可用,至少会有两条 A 记录。这样冗余的两个 ip 对应的 nginx 服务实例,防止单点故障。 + +每次请求 [http://bysocket.com](https://link.zhihu.com/?target=http%3A//bysocket.com) 域名的时候,通过 DNS 轮询,返回对应的 ip 地址,每个 ip 对应的反向代理层的服务实例,也就是 nginx 的外网ip。这样可以做到每一个反向代理层实例得到的请求分配是均衡的。 + +**第 2 层:反向代理层 -> Web 层 的负载均衡** + +反向代理层 -> Web 层 的负载均衡如何实现呢? + +是通过反向代理层的负载均衡模块处理。比如 nginx 有多种均衡方法: + +1. 请求轮询。请求按时间顺序,逐一分配到 web 层服务,然后周而复始。如果 web 层服务 down 掉,自动剔除 + +```text +upstream web-server { +server ip3; +server ip4; +} +``` + +ip 哈希。按照 ip 的哈希值,确定路由到对应的 web 层。只要是用户的 ip 是均匀的,那么请求到 Web 层也是均匀的。 + +1. 还有个好处就是同一个 ip 的请求会分发到相同的 web 层服务。这样每个用户固定访问一个 web 层服务,可以解决 session 的问题。 + +```text +upstream web-server { +ip_hash; +server ip3; +server ip4; +} +``` + +1. weight 权重 、 fair、url_hash 等 + +**第 3 层:Web 层 -> 业务服务层 的负载均衡** + +Web 层 -> 业务服务层 的负载均衡如何实现呢? + +比如 Dubbo 是一个服务治理方案,包括服务注册、服务降级、访问控制、动态配置路由规则、权重调节、负载均衡。其中一个特性就是智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。 + +为了避免避免单点故障和支持服务的横向扩容,一个服务通常会部署多个实例,即 Dubbo 集群部署。会将多个服务实例成为一个服务提供方,然后根据配置的随机负载均衡策略,在20个 Provider 中随机选择了一个来调用,假设随机到了第7个 Provider。LoadBalance 组件从提供者地址列表中,使用均衡策略,选择选一个提供者进行调用,如果调用失败,再选另一台调用。 + +Dubbo内置了4种负载均衡策略: + +- RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。 +- RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。 +- LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。 +- ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。 + +同样,因为业务的需要,也可以实现自己的负载均衡策略 + +**第 4 层:业务服务层 -> 数据存储层 的负载均衡** + +数据存储层的负载均衡,一般通过 DBProxy 实现。比如 MySQL 分库分表。 + +当单库或者单表访问太大,数据量太大的情况下,需要进行垂直拆分和水平拆分两个维度。比如水平切分规则: + +- Range 、 时间 +- hash 取模,订单根据店铺ID 等 + +但伴随着这块的负载会出现下面的问题,需要解决: + +- 分布式事务 +- 跨库 join 等 + +现状分库分表的产品方案很多:当当 sharding-jdbc、阿里的 Cobar 等 + +## **五、小结** + +对外看来,负载均衡是一个系统或软件的整体。对内看来,层层上下游调用。只要存在调用,就需要考虑负载均衡这个因素。所以负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一。考虑主要是如何让下游接收到的请求是均匀分布的: + +- 第 1 层:客户端层 -> 反向代理层 的负载均衡。通过 DNS 轮询 +- 第 2 层:反向代理层 -> Web 层 的负载均衡。通过 Nginx 的负载均衡模块 +- 第 3 层:Web 层 -> 业务服务层 的负载均衡。通过服务治理框架的负载均衡模块 +- 第 4 层:业务服务层 -> 数据存储层 的负载均衡。通过数据的水平分布,数据均匀了,理论上请求也会均匀。比如通过买家ID分片类似 \ No newline at end of file diff --git a/docs/advance/concurrent/README.md b/docs/advance/concurrent/README.md new file mode 100644 index 0000000..b495d0c --- /dev/null +++ b/docs/advance/concurrent/README.md @@ -0,0 +1,4 @@ +## 高并发专题(更新中) + +- [限流算法](./1-current-limiting.md) +- [负载均衡](./2-load-balance.md) diff --git "a/\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" b/docs/advance/design-pattern-all.md similarity index 100% rename from "\345\205\266\344\273\226/\350\256\276\350\256\241\346\250\241\345\274\217.md" rename to docs/advance/design-pattern-all.md diff --git a/docs/advance/design-pattern/1-principle.md b/docs/advance/design-pattern/1-principle.md new file mode 100644 index 0000000..cec9d65 --- /dev/null +++ b/docs/advance/design-pattern/1-principle.md @@ -0,0 +1,9 @@ +# 设计模式的六大原则 + +- 开闭原则:对扩展开放,对修改关闭,多使用抽象类和接口。 +- 里氏替换原则:基类可以被子类替换,使用抽象类继承,不使用具体类继承。 +- 依赖倒转原则:要依赖于抽象,不要依赖于具体,针对接口编程,不针对实现编程。 +- 接口隔离原则:使用多个隔离的接口,比使用单个接口好,建立最小的接口。 +- 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用,通过中间类建立联系。 +- 合成复用原则:尽量使用合成/聚合,而不是使用继承。 + diff --git a/docs/advance/design-pattern/10-observer.md b/docs/advance/design-pattern/10-observer.md new file mode 100644 index 0000000..0ad3819 --- /dev/null +++ b/docs/advance/design-pattern/10-observer.md @@ -0,0 +1,17 @@ +# 观察者模式 + +定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。 + +主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。 + +多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。其作用是让主题对象和观察者松耦合。 + +观察者模式所涉及的角色有: + +- 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。 +- 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。 +- 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。 +- 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。 + + + diff --git a/docs/advance/design-pattern/11-proxy.md b/docs/advance/design-pattern/11-proxy.md new file mode 100644 index 0000000..33e71a8 --- /dev/null +++ b/docs/advance/design-pattern/11-proxy.md @@ -0,0 +1,77 @@ +# 代理模式 + +代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问。 + +## 静态代理 + +静态代理:代理类在编译阶段生成,程序运行前就已经存在,在编译阶段将通知织入Java字节码中。 + +缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。同时,一旦接口增加方法,目标对象与代理对象都要维护。 + +## 动态代理 + +动态代理:代理类在程序运行时创建,在内存中临时生成一个代理对象,在运行期间对业务方法进行增强。 + +**JDK动态代理** + +JDK实现代理只需要使用newProxyInstance方法: + +```java +static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h ) +``` + +三个入参: + +- ClassLoader loader:指定当前目标对象使用的类加载器 +- Class[] interfaces:目标对象实现的接口的类型 +- InvocationHandler:当代理对象调用目标对象的方法时,会触发事件处理器的invoke方法() + +示例代码: + +``` +public class DynamicProxyDemo { + + public static void main(String[] args) { + //被代理的对象 + MySubject realSubject = new RealSubject(); + + //调用处理器 + MyInvacationHandler handler = new MyInvacationHandler(realSubject); + + MySubject subject = (MySubject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), + realSubject.getClass().getInterfaces(), handler); + + System.out.println(subject.getClass().getName()); + subject.rent(); + } +} + +interface MySubject { + public void rent(); +} +class RealSubject implements MySubject { + + @Override + public void rent() { + System.out.println("rent my house"); + } +} +class MyInvacationHandler implements InvocationHandler { + + private Object subject; + + public MyInvacationHandler(Object subject) { + this.subject = subject; + } + + @Override + public Object invoke(Object object, Method method, Object[] args) throws Throwable { + System.out.println("before renting house"); + //invoke方法会拦截代理对象的方法调用 + Object o = method.invoke(subject, args); + System.out.println("after rentint house"); + return o; + } +} +``` + diff --git a/docs/advance/design-pattern/12-builder.md b/docs/advance/design-pattern/12-builder.md new file mode 100644 index 0000000..201ee16 --- /dev/null +++ b/docs/advance/design-pattern/12-builder.md @@ -0,0 +1,79 @@ +# 建造者模式 + +建造者模式:封装一个对象的构造过程,并允许按步骤构造。 + +有两种形式:传统建造者模式和传统建造者模式变种。 + +传统建造者模式: + +```java +public class Computer { + private final String cpu;//必须 + private final String ram;//必须 + private final int usbCount;//可选 + private final String keyboard;//可选 + private final String display;//可选 + + private Computer(Builder builder){ + this.cpu=builder.cpu; + this.ram=builder.ram; + this.usbCount=builder.usbCount; + this.keyboard=builder.keyboard; + this.display=builder.display; + } + public static class Builder{ + private String cpu;//必须 + private String ram;//必须 + private int usbCount;//可选 + private String keyboard;//可选 + private String display;//可选 + + public Builder(String cup,String ram){ + this.cpu=cup; + this.ram=ram; + } + public Builder setDisplay(String display) { + this.display = display; + return this; + } + //set... + public Computer build(){ + return new Computer(this); + } + } +} + +public class ComputerDirector { + public void makeComputer(ComputerBuilder builder){ + builder.setUsbCount(); + builder.setDisplay(); + builder.setKeyboard(); + } +} +``` + +传统建造者模式变种,链式调用: + +```java +public class LenovoComputerBuilder extends ComputerBuilder { + private Computer computer; + public LenovoComputerBuilder(String cpu, String ram) { + computer=new Computer(cpu,ram); + } + @Override + public void setUsbCount() { + computer.setUsbCount(4); + } + //... + @Override + public Computer getComputer() { + return computer; + } +} + +Computer computer=new Computer.Builder("因特尔","三星") + .setDisplay("三星24寸") + .setKeyboard("罗技") + .setUsbCount(2) + .build(); +``` diff --git a/docs/advance/design-pattern/2-singleton.md b/docs/advance/design-pattern/2-singleton.md new file mode 100644 index 0000000..3af2c2b --- /dev/null +++ b/docs/advance/design-pattern/2-singleton.md @@ -0,0 +1,94 @@ +# 单例模式 + +需要对实例字段使用线程安全的延迟初始化,使用双重检查锁定的方案;需要对静态字段使用线程安全的延迟初始化,使用静态内部类的方案。 + +## 饿汉模式 + +JVM在类的初始化阶段,会执行类的静态方法。在执行类的初始化期间,JVM会去获取Class对象的锁。这个锁可以同步多个线程对同一个类的初始化。 + +饿汉模式只在类加载的时候创建一次实例,没有多线程同步的问题。单例没有用到也会被创建,而且在类加载之后就被创建,内存就被浪费了。 + +``` +public class Singleton { + private static Singleton instance = new Singleton(); + private Singleton() {} + public static Singleton newInstance() { + return instance; + } +} +``` +## 双重检查锁定 + +双重校验锁先判断 instance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。 + +instance使用static修饰的原因:getInstance为静态方法,因为静态方法的内部不能直接使用非静态变量,只有静态成员才能在没有创建对象时进行初始化,所以返回的这个实例必须是静态的。 + +``` +public class Singleton { + private static volatile Singleton instance = null; //volatile + private Singleton(){} + public static Singleton getInstance() { + if (instance == null) { + synchronized (Singleton.class) { + if (instance == null) { + instance = new Singleton(); + } + } + } + return instance; + } +} +``` +为什么两次判断`instance == null`: + +| Time | Thread A | Thread B | +| ---- | -------------------- | -------------------- | +| T1 | 检查到`instance`为空 | | +| T2 | | 检查到`instance`为空 | +| T3 | | 初始化对象`A` | +| T4 | | 返回对象`A` | +| T5 | 初始化对象`B` | | +| T6 | 返回对象`B` | | + +`new Singleton()`会执行三个动作:分配内存空间、初始化对象和对象引用指向内存地址。 + +```java +memory = allocate();  // 1:分配对象的内存空间 +ctorInstance(memory);  // 2:初始化对象 +instance = memory;   // 3:设置instance指向刚分配的内存地址 +``` + +由于指令重排优化的存在,导致初始化对象和将对象引用指向内存地址的顺序是不确定的。在某个线程创建单例对象时,会为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化。若紧接着另外一个线程来调用getInstance,取到的是未初始化的对象,程序就会出错。volatile 可以禁止指令重排序,保证了先初始化对象再赋值给instance变量。 + +| Time | Thread A | Thread B | +| :--- | :----------------------- | :--------------------------------------- | +| T1 | 检查到`instance`为空 | | +| T2 | 获取锁 | | +| T3 | 再次检查到`instance`为空 | | +| T4 | 为`instance`分配内存空间 | | +| T5 | 将`instance`指向内存空间 | | +| T6 | | 检查到`instance`不为空 | +| T7 | | 访问`instance`(此时对象还未完成初始化) | +| T8 | 初始化`instance` | | + +## 静态内部类 + +它与饿汉模式一样,也是利用了类初始化机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。 + +![](http://img.dabin-coder.cn/image/singleton-class-init.png) + +基于类初始化的方案的实现代码更简洁。 + +``` +public class Instance { + private static class InstanceHolder { + public static Instance instance = new Instance(); + } + private Instance() {} + public static Instance getInstance() { + return InstanceHolder.instance ;  // 这里将导致InstanceHolder类被初始化 + } +} +``` +但基于volatile的双重检查锁定的方案有一个额外的优势:除了可以对静态字段实现延迟初始化外,还可以对实例字段实现延迟初始化。字段延迟初始化降低了初始化类或创建实例的开销,但增加了访问被延迟初始化的字段的开销。在大多数时候,正常的初始化要优于延迟初始化。 + diff --git a/docs/advance/design-pattern/3-factory.md b/docs/advance/design-pattern/3-factory.md new file mode 100644 index 0000000..42cadbd --- /dev/null +++ b/docs/advance/design-pattern/3-factory.md @@ -0,0 +1,91 @@ +# 工厂模式 + +工厂模式是用来封装对象的创建。 + +## 简单工厂模式 + +把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化,这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。 + +```java + public class ShapeFactory { + public static final String TAG = "ShapeFactory"; + public static Shape getShape(String type) { + Shape shape = null; + if (type.equalsIgnoreCase("circle")) { + shape = new CircleShape(); + } else if (type.equalsIgnoreCase("rect")) { + shape = new RectShape(); + } else if (type.equalsIgnoreCase("triangle")) { + shape = new TriangleShape(); + } + return shape; + } + } +``` + +优点:只需要一个工厂创建对象,代码量少。 + +缺点:系统扩展困难,新增产品需要修改工厂逻辑,当产品较多时,会造成工厂逻辑过于复杂,不利于系统扩展和维护。 + +## 工厂方法模式 + +针对不同的对象提供不同的工厂。每个对象都有一个与之对应的工厂。 + +```java +public interface Reader { + void read(); +} + +public class JpgReader implements Reader { + @Override + public void read() { + System.out.print("read jpg"); + } +} + +public class PngReader implements Reader { + @Override + public void read() { + System.out.print("read png"); + } +} + +public interface ReaderFactory { + Reader getReader(); +} + +public class JpgReaderFactory implements ReaderFactory { + @Override + public Reader getReader() { + return new JpgReader(); + } +} + +public class PngReaderFactory implements ReaderFactory { + @Override + public Reader getReader() { + return new PngReader(); + } +} +``` + +客户端通过子类来指定创建对应的对象。 + +```java +ReaderFactory factory=new JpgReaderFactory(); +Reader reader=factory.getReader(); +reader.read(); +``` + +优点:增加新的产品类时无须修改现有系统,只需增加新产品和对应的工厂类即可。 + +## 抽象工厂模式 + +抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 + +多了一层抽象,减少了工厂的数量(HpMouseFactory和HpKeyboFactory合并为HpFactory)。 + +![](http://img.dabin-coder.cn/image/抽象工厂.png) + + + diff --git a/docs/advance/design-pattern/4-template.md b/docs/advance/design-pattern/4-template.md new file mode 100644 index 0000000..c5a00dc --- /dev/null +++ b/docs/advance/design-pattern/4-template.md @@ -0,0 +1,82 @@ +# 模板模式 + +模板模式:一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 这种类型的设计模式属于行为型模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 + +**模板模式**主要由抽象模板(Abstract Template)角色和具体模板(Concrete Template)角色组成。 + +- 抽象模板(Abstract Template): 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。 +- 具体模板(Concrete Template): 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。 + +示例图如下: + +![](http://img.dabin-coder.cn/image/模板方法.jpg) + +以游戏为例。创建一个抽象类,它的模板方法被设置为 final,这样它就不会被重写。 + +```java +public abstract class Game { + abstract void initialize(); + abstract void startPlay(); + abstract void endPlay(); + + //模板 + public final void play(){ + //初始化游戏 + initialize(); + + //开始游戏 + startPlay(); + + //结束游戏 + endPlay(); + } +} +``` + +Football类: + +```java +public class Football extends Game { + + @Override + void endPlay() { + System.out.println("Football Game Finished!"); + } + + @Override + void initialize() { + System.out.println("Football Game Initialized! Start playing."); + } + + @Override + void startPlay() { + System.out.println("Football Game Started. Enjoy the game!"); + } +} +``` + +使用Game的模板方法 play() 来演示游戏的定义方式。 + +```java +public class TemplatePatternDemo { + public static void main(String[] args) { + + Game game = new Cricket(); + game.play(); + System.out.println(); + game = new Football(); + game.play(); + } +} +``` + +**模板模式优点** : + +1. 封装不变部分,扩展可变部分。 +2. 提取公共代码,便于维护。 +3. 行为由父类控制,子类实现。 + +**模板模式缺点**: + +- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。 + diff --git a/docs/advance/design-pattern/5-strategy.md b/docs/advance/design-pattern/5-strategy.md new file mode 100644 index 0000000..197681b --- /dev/null +++ b/docs/advance/design-pattern/5-strategy.md @@ -0,0 +1,111 @@ +# 策略模式 + +策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。 + +其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。 + +**策略模式**主要由这三个角色组成,环境角色(Context)、抽象策略角色(Strategy)和具体策略角色(ConcreteStrategy)。 + +- 环境角色(Context):持有一个策略类的引用,提供给客户端使用。 +- 抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 +- 具体策略角色(ConcreteStrategy):包装了相关的算法或行为。 + +示例图如下: + +![](http://img.dabin-coder.cn/image/策略模式.png) + +以计算器为例,如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。 + +但是在这些方法中,我们发现其基本方法是固定的,这时我们就可以通过策略模式来进行开发,可以有效避免通过if/else来进行判断,即使后续增加其他的计算规则也可灵活进行调整。 + +首先定义一个抽象策略角色,并拥有一个计算的方法。 + +```java +interface CalculateStrategy { + int doOperation(int num1, int num2); +} +``` + +然后再定义加减乘除这些具体策略角色并实现方法。代码如下: + +```java +class OperationAdd implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 + num2; + } +} + +class OperationSub implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 - num2; + } +} + +class OperationMul implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 * num2; + } +} + +class OperationDiv implements CalculateStrategy { + @Override + public int doOperation(int num1, int num2) { + return num1 / num2; + } +} +``` + +最后在定义一个环境角色,提供一个计算的接口供客户端使用。代码如下: + +```java +class CalculatorContext { + private CalculateStrategy strategy; + + public CalculatorContext(CalculateStrategy strategy) { + this.strategy = strategy; + } + + public int executeStrategy(int num1, int num2) { + return strategy.doOperation(num1, num2); + } +} +``` + +测试代码如下: + +```java +public static void main(String[] args) { + int a=4,b=2; + CalculatorContext context = new CalculatorContext(new OperationAdd()); + System.out.println("a + b = "+context.executeStrategy(a, b)); + + CalculatorContext context2 = new CalculatorContext(new OperationSub()); + System.out.println("a - b = "+context2.executeStrategy(a, b)); + + CalculatorContext context3 = new CalculatorContext(new OperationMul()); + System.out.println("a * b = "+context3.executeStrategy(a, b)); + + CalculatorContext context4 = new CalculatorContext(new OperationDiv()); + System.out.println("a / b = "+context4.executeStrategy(a, b)); +} +``` + +**策略模式优点:** + +- 扩展性好,可以在不修改对象结构的情况下,为新的算法进行添加新的类进行实现; +- 灵活性好,可以对算法进行自由切换; + +**策略模式缺点:** + +- 使用策略类变多,会增加系统的复杂度。; +- 客户端必须知道所有的策略类才能进行调用; + +**使用场景:** + +- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为; + 一个系统需要动态地在几种算法中选择一种; +- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现; + diff --git a/docs/advance/design-pattern/6-chain.md b/docs/advance/design-pattern/6-chain.md new file mode 100644 index 0000000..512b777 --- /dev/null +++ b/docs/advance/design-pattern/6-chain.md @@ -0,0 +1,190 @@ +# 责任链模式 + +为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。 + +在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。 + +**责任链模式是一种对象行为型模式,其主要优点如下。** + +1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。 +2. 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。 +3. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。 +4. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。 +5. 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。 + +代码实现如下: + +请假条类 + +```java +public class LeaveRequest { + //姓名 + private String name; + // 请假天数 + private int num; + // 请假内容 + private String content; + + public LeaveRequest(String name, int num, String content) { + this.name = name; + this.num = num; + this.content = content; + } + + public String getName() { + return name; + } + + public int getNum() { + return num; + } + + public String getContent() { + return content; + } + +} +``` + +处理类 + +```java +public abstract class Handler { + protected final static int NUM_ONE = 1; + protected final static int NUM_THREE = 3; + protected final static int NUM_SEVEN = 7; + + //该领导处理的请假天数区间 + private int numStart; + private int numEnd; + + + //领导上还有领导 + private Handler nextHandler; + + //设置请假天数范围 + public Handler(int numStart) { + this.numStart = numStart; + } + + //设置请假天数范围 + public Handler(int numStart, int numEnd) { + this.numStart = numStart; + this.numEnd = numEnd; + } + + //设置上级领导 + public void setNextHandler(Handler nextHandler) { + this.nextHandler = nextHandler; + } + + //提交请假条 + public final void submit(LeaveRequest leaveRequest) { + if (this.numStart == 0) { + return; + } + //请假天数达到领导处理要求 + if (leaveRequest.getNum() >= this.numStart) { + this.handleLeave(leaveRequest); + + //如果还有上级 并且请假天数超过当前领导的处理范围 + if (this.nextHandler != null && leaveRequest.getNum() > numEnd) { + //继续提交 + this.nextHandler.submit(leaveRequest); + } else { + System.out.println("流程结束!!!"); + } + } + } + + //各级领导处理请假条方法 + protected abstract void handleLeave(LeaveRequest leave); + +} +``` + +小组长类 + +```java +public class GroupLeader extends Handler { + //1-3天的假 + public GroupLeader() { + super(Handler.NUM_ONE, Handler.NUM_THREE); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("小组长审批通过:同意!"); + } +} +``` + +部门经理类 + +```java +public class Manager extends Handler { + //3-7天的假 + public Manager() { + super(Handler.NUM_THREE, Handler.NUM_SEVEN); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("部门经理审批通过:同意!"); + } +} +``` + +总经理类 + +```java +public class GeneralManager extends Handler{ + //7天以上的假 + public GeneralManager() { + super(Handler.NUM_THREE, Handler.NUM_SEVEN); + } + + @Override + protected void handleLeave(LeaveRequest leave) { + System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!"); + System.out.println("总经理审批通过:同意!"); + } +} +``` + +测试类 + +```java +public class Client { + public static void main(String[] args) { + //请假条 + LeaveRequest leave = new LeaveRequest("小庄", 3, "出去旅游"); + + //各位领导 + Manager manager = new Manager(); + GroupLeader groupLeader = new GroupLeader(); + GeneralManager generalManager = new GeneralManager(); + + /* + * 小组长上司是经理 经理上司是总经理 + */ + groupLeader.setNextHandler(manager); + manager.setNextHandler(generalManager); + + //提交 + groupLeader.submit(leave); + + } +} +``` + +应用场景: + +1. 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。 +2. 可动态指定一组对象处理请求,或添加新的处理者。 +3. 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。 + +[参考链接](https://segmentfault.com/a/1190000040450513) + diff --git a/docs/advance/design-pattern/7-iterator.md b/docs/advance/design-pattern/7-iterator.md new file mode 100644 index 0000000..a54bdf7 --- /dev/null +++ b/docs/advance/design-pattern/7-iterator.md @@ -0,0 +1,30 @@ +# 迭代器模式 + +提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示。 + +把在元素之间游走的责任交给迭代器,而不是聚合对象。 + +**应用实例:**JAVA 中的 iterator。 + +**优点:** 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。 + +**缺点:**由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。 + +**使用场景:** 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。 + +**迭代器模式在JDK中的应用** + +ArrayList的遍历: + +```java +Iterator iter = null; + +System.out.println("ArrayList:"); +iter = arrayList.iterator(); +while (iter.hasNext()) { + System.out.print(iter.next() + "\t"); +} +``` + + + diff --git a/docs/advance/design-pattern/8-decorator.md b/docs/advance/design-pattern/8-decorator.md new file mode 100644 index 0000000..55b4d1c --- /dev/null +++ b/docs/advance/design-pattern/8-decorator.md @@ -0,0 +1,20 @@ +# 装饰模式 + +装饰者模式(decorator pattern):动态地将责任附加到对象上, 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案。 + +装饰模式以对客户端透明的方式拓展对象的功能,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。 + +比如设置FileInputStream,先用BufferedInputStream装饰它,再用自己写的LowerCaseInputStream过滤器去装饰它。 + +``` +InputStream in = new LowerCaseInputStream( + new BufferedInputStream( + new FileInputStream("test.txt"))); +``` +在装饰模式中的角色有: + +- 抽象组件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。 +- 具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类。 +- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。 +- 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。 + diff --git a/docs/advance/design-pattern/9-adapter.md b/docs/advance/design-pattern/9-adapter.md new file mode 100644 index 0000000..bc2624d --- /dev/null +++ b/docs/advance/design-pattern/9-adapter.md @@ -0,0 +1,18 @@ +# 适配器模式 +适配器模式将现成的对象通过适配变成我们需要的接口。 适配器让原本接口不兼容的类可以合作。 + +适配器模式有类的适配器模式和对象的适配器模式两种不同的形式。 + +对象适配器模式通过组合对象进行适配。 + +![](http://img.dabin-coder.cn/image/适配器对象适配,png) + +类适配器通过继承来完成适配。 + +![](http://img.dabin-coder.cn/image/适配器-类继承,png) + +适配器模式的**优点**: + +1. 更好的复用性。系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。 +2. 更好的扩展性。在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。 + diff --git a/docs/advance/design-pattern/README.md b/docs/advance/design-pattern/README.md new file mode 100644 index 0000000..a1e777f --- /dev/null +++ b/docs/advance/design-pattern/README.md @@ -0,0 +1,25 @@ +--- +title: 设计模式 +icon: design +date: 2022-08-07 +category: 设计模式 +star: true +--- + +**本专栏是大彬学习设计模式基础知识的学习笔记,如有错误,可以在评论区指出**~ + +![](http://img.dabin-coder.cn/image/设计模式.jpg) +## 设计模式详解 + +- [设计模式的六大原则](./1-principle.md) +- [单例模式](./2-singleton.md) +- [工厂模式](./3-factory.md) +- [模板模式](./4-template.md) +- [策略模式](./5-strategy.md) +- [责任链模式](./6-chain.md) +- [迭代器模式](./7-iterator.md) +- [装饰模式](./8-decorator.md) +- [适配器模式](./9-adapter.md) +- [观察者模式](./10-observer.md) +- [代理模式](./11-proxy.md) +- [建造者模式](./12-builder.md) diff --git "a/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" b/docs/advance/distributed/1-global-unique-id.md similarity index 97% rename from "\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" rename to docs/advance/distributed/1-global-unique-id.md index 0871efa..a28fe0d 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\205\250\345\261\200\345\224\257\344\270\200ID.md" +++ b/docs/advance/distributed/1-global-unique-id.md @@ -1,10 +1,12 @@ +# 全局唯一ID生成方案 + 传统的单体架构的时候,我们基本是单库然后业务单表的结构。每个业务表的ID一般我们都是从1增,通过`AUTO_INCREMENT=1`设置自增起始值,但是在分布式服务架构模式下分库分表的设计,使得多个库或多个表存储相同的业务数据。这种情况根据数据库的自增ID就会产生相同ID的情况,不能保证主键的唯一性。 ![](http://img.dabin-coder.cn/image/20220508235751.png) 如上图,如果第一个订单存储在 DB1 上则订单 ID 为1,当一个新订单又入库了存储在 DB2 上订单 ID 也为1。我们系统的架构虽然是分布式的,但是在用户层应是无感知的,重复的订单主键显而易见是不被允许的。那么针对分布式系统如何做到主键唯一性呢? -# UUID +## UUID UUID (Universally Unique Identifier),通用唯一识别码的缩写。UUID是由一组32位数的16进制数字所构成,所以UUID理论上的总数为 1632=2128,约等于 3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。 @@ -52,7 +54,7 @@ public static void main(String[] args) { - 信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,暴露使用者的位置。 - 对MySQL索引不利:如果作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能,可以查阅 Mysql 索引原理 B+树的知识。 -# 数据库生成 +## 数据库生成 是不是一定要基于外界的条件才能满足分布式唯一ID的需求呢,我们能不能在我们分布式数据库的基础上获取我们需要的ID? @@ -71,7 +73,7 @@ public static void main(String[] args) { 但是缺点也很明显,首先它强依赖DB,当DB异常时整个系统不可用。虽然配置主从复制可以尽可能的增加可用性,但是数据一致性在特殊情况下难以保证。主从切换时的不一致可能会导致重复发号。还有就是ID发号性能瓶颈限制在单台MySQL的读写性能。 -# 使用redis实现 +## 使用redis实现 Redis实现分布式唯一ID主要是通过提供像 *INCR* 和 *INCRBY* 这样的自增原子命令,由于Redis自身的单线程的特点所以能保证生成的 ID 肯定是唯一有序的。 @@ -83,7 +85,7 @@ Redis 实现分布式全局唯一ID,它的性能比较高,生成的数据是 当然现在Redis的使用性很普遍,所以如果其他业务已经引进了Redis集群,则可以资源利用考虑使用Redis来实现。 -# 雪花算法-Snowflake +## 雪花算法-Snowflake Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。 @@ -290,7 +292,7 @@ public static void main(String[] args) { 很多其他类雪花算法也是在此思想上的设计然后改进规避它的缺陷,后面介绍的百度 UidGenerator 和 美团分布式ID生成系统 Leaf 中snowflake模式都是在 snowflake 的基础上演进出来的。 -# 百度-UidGenerator +## 百度-UidGenerator [百度的 UidGenerator](https://github.com/baidu/uid-generator) 是百度开源基于Java语言实现的唯一ID生成器,是在雪花算法 snowflake 的基础上做了一些改进。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略,适用于docker等虚拟化环境下实例自动重启、漂移等场景。 @@ -323,7 +325,7 @@ PRIMARY KEY(ID) COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB; ``` -## DefaultUidGenerator 实现 +### DefaultUidGenerator 实现 DefaultUidGenerator 就是正常的根据时间戳和机器位还有序列号的生成方式,和雪花算法很相似,对于时钟回拨也只是抛异常处理。仅有一些不同,如以秒为为单位而不再是毫秒和支持Docker等虚拟化环境。 @@ -371,7 +373,7 @@ protected synchronized long nextId() { ``` -## CachedUidGenerator 实现 +### CachedUidGenerator 实现 而官方建议的性能较高的 CachedUidGenerator 生成方式,是使用 RingBuffer 缓存生成的id。数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值(2^13 = 8192)。可通过 boostPower 配置进行扩容,以提高 RingBuffer 读写吞吐量。 @@ -382,13 +384,13 @@ Tail指针、Cursor指针用于环形数组上读写slot: - Cursor指针 表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过rejectedTakeBufferHandler指定TakeRejectPolicy -[![img](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142503899-1530677221.png)](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142503899-1530677221.png) +![](http://img.dabin-coder.cn/image/20220706225625.png) CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)。 由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。 -[![img](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142450492-1894906450.png)](https://img2018.cnblogs.com/blog/1162587/201907/1162587-20190707142450492-1894906450.png) +![](http://img.dabin-coder.cn/image/20220706225530.png) RingBuffer填充时机 @@ -399,13 +401,13 @@ RingBuffer填充时机 - 周期填充 通过Schedule线程,定时补全空闲slots。可通过scheduleInterval配置,以应用定时填充功能,并指定Schedule时间间隔。 -# 美团Leaf +## 美团Leaf Leaf是美团基础研发平台推出的一个分布式ID生成服务,名字取自德国哲学家、数学家莱布尼茨的著名的一句话:“There are no two identical leaves in the world”,世间不可能存在两片相同的叶子。 Leaf 也提供了两种ID生成的方式,分别是 Leaf-segment 数据库方案和 Leaf-snowflake 方案。 -## Leaf-segment 数据库方案 +### Leaf-segment 数据库方案 Leaf-segment 数据库方案,是在上文描述的在使用数据库的方案上,做了如下改变: @@ -444,7 +446,7 @@ CREATE TABLE `leaf_alloc` ( 对于这种方案依然存在一些问题,它仍然依赖 DB的稳定性,需要采用主从备份的方式提高 DB的可用性,还有 Leaf-segment方案生成的ID是趋势递增的,这样ID号是可被计算的,例如订单ID生成场景,通过订单id号相减就能大致计算出公司一天的订单量,这个是不能忍受的。 -## Leaf-snowflake方案 +### Leaf-snowflake方案 Leaf-snowflake方案完全沿用 snowflake 方案的bit位设计,对于workerID的分配引入了Zookeeper持久顺序节点的特性自动对snowflake节点配置 wokerID。避免了服务规模较大时,动手配置成本太高的问题。 @@ -466,7 +468,7 @@ Leaf-snowflake是按照下面几个步骤启动的: 在性能上官方提供的数据目前 Leaf 的性能在4C8G 的机器上QPS能压测到近5w/s,TP999 1ms。 -# 总结 +## 总结 以上基本列出了所有常用的分布式ID生成方式,其实大致分类的话可以分为两类: @@ -482,4 +484,4 @@ Leaf-snowflake是按照下面几个步骤启动的: -[参考链接](https://www.cnblogs.com/jajian/p/11101213.html) \ No newline at end of file +[参考链接](https://www.cnblogs.com/jajian/p/11101213.html) diff --git "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" b/docs/advance/distributed/2-distributed-lock.md similarity index 99% rename from "\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" rename to docs/advance/distributed/2-distributed-lock.md index 8a65dd1..07c5445 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\210\206\345\270\203\345\274\217\351\224\201.md" +++ b/docs/advance/distributed/2-distributed-lock.md @@ -1,3 +1,5 @@ +# 分布式锁 + ## 为什么要使用分布式锁 在单机环境下,当存在多个线程可以同时改变某个变量(可变共享变量)时,就会出现线程安全问题。这个问题可以通过 JAVA 提供的 volatile、ReentrantLock、synchronized 以及 concurrent 并发包下一些线程安全的类等来避免。 @@ -252,4 +254,4 @@ ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它 ## 参考链接 -https://mp.weixin.qq.com/s/xQknd6xsVDPBr4TbETTk2A \ No newline at end of file +https://mp.weixin.qq.com/s/xQknd6xsVDPBr4TbETTk2A diff --git "a/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" b/docs/advance/distributed/3-rpc.md similarity index 99% rename from "\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" rename to docs/advance/distributed/3-rpc.md index beade88..30ec852 100644 --- "a/\345\210\206\345\270\203\345\274\217/\350\277\234\347\250\213\350\260\203\347\224\250.md" +++ b/docs/advance/distributed/3-rpc.md @@ -1,3 +1,5 @@ +# RPC + ## RPC简介 RPC,英文全名remote procedure call,即远程过程调用。就是说一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。 @@ -116,4 +118,4 @@ Protobuf有个缺点就是要传输每一个类的结构都要生成对应的pro 1. 对性能要求不高的场景,可以采用基于XML的SOAP协议 2. 性能和间接性有比较高要求的场景,那么Hessian、Protobuf、Thrift、Avro都可以。 3. 基于前后端分离,或者独立的对外API服务,选用JSON是比较好的,对于调试、可读性都很不错。 -4. Avro设计理念偏于动态类型语言,那么这类的场景使用Avro是可以的。 \ No newline at end of file +4. Avro设计理念偏于动态类型语言,那么这类的场景使用Avro是可以的。 diff --git a/docs/advance/distributed/4-micro-service.md b/docs/advance/distributed/4-micro-service.md new file mode 100644 index 0000000..0803aaa --- /dev/null +++ b/docs/advance/distributed/4-micro-service.md @@ -0,0 +1,183 @@ +# 微服务 + +## 什么是微服务? + +微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务和服务之间采用轻量级的通信机制进行协作。每个服务可以被独立的部署到生产环境。 + +[从单体应用到微服务](https://www.zhihu.com/question/65502802/answer/802678798) + +单体系统的缺点: + +1. 修改一个小功能,就需要将整个系统重新部署上线,影响其他功能的运行; +2. 功能模块互相依赖,强耦合,扩展困难。如果出现性能瓶颈,需要对整体应用进行升级,虽然影响性能的可能只是其中一个小模块; + +单体系统的优点: + +1. 容易部署,程序单一,不存在分布式集群的复杂部署环境; +2. 容易测试,没有复杂的服务调用关系。 + +微服务的**优点**: + +1. 不同的服务可以使用不同的技术; +2. 隔离性。一个服务不可用不会导致其他服务不可用; +3. 可扩展性。某个服务出现性能瓶颈,只需对此服务进行升级即可; +4. 简化部署。服务的部署是独立的,哪个服务出现问题,只需对此服务进行修改重新部署; + +微服务的**缺点**: + +1. 网络调用频繁。性能相对函数调用较差。 +2. 运维成本增加。系统由多个独立运行的微服务构成,需要设计一个良好的监控系统对各个微服务的运行状态进行监控。 + + + +## 分布式和微服务的区别 + +从概念理解,分布式服务架构强调的是服务化以及服务的**分散化**,微服务则更强调服务的**专业化和精细分工**; + +从实践的角度来看,**微服务架构通常是分布式服务架构**,反之则未必成立。 + +一句话概括:分布式:分散部署;微服务:分散能力。 + + + +## 服务怎么划分? + +横向拆分:按照不同的业务域进行拆分,例如订单、营销、风控、积分资源等。形成独立的业务领域微服务集群。 + +纵向拆分:把一个业务功能里的不同模块或者组件进行拆分。例如把公共组件拆分成独立的原子服务,下沉到底层,形成相对独立的原子服务层。这样一纵一横,就可以实现业务的服务化拆分。 + +要做好微服务的分层:梳理和抽取核心应用、公共应用,作为独立的服务下沉到核心和公共能力层,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求 + +总之,微服务的设计一定要 **渐进式** 的,总的原则是 **服务内部高内聚,服务之间低耦合。** + + ## 微服务设计原则 +**单一职责原则** + +意思是每个微服务只需要实现自己的业务逻辑就可以了,比如订单管理模块,它只需要处理订单的业务逻辑就可以了,其它的不必考虑。 + +**服务自治原则** + +意思是每个微服务从开发、测试、运维等都是独立的,包括存储的数据库也都是独立的,自己就有一套完整的流程,我们完全可以把它当成一个项目来对待。不必依赖于其它模块。 + +**轻量级通信原则** + +首先是通信的语言非常的轻量,第二,该通信方式需要是跨语言、跨平台的,之所以要跨平台、跨语言就是为了让每个微服务都有足够的独立性,可以不受技术的钳制。 + +**接口明确原则** + +由于微服务之间可能存在着调用关系,为了尽量避免以后由于某个微服务的接口变化而导致其它微服务都做调整,在设计之初就要考虑到所有情况,让接口尽量做的更通用,更灵活,从而尽量避免其它模块也做调整。 + + + +## 微服务之间是如何通讯的? + +**1、RPC** + +优点:简单,常见。因为没有中间件代理,系统更简单 + +缺点: + +1. 只支持请求/响应的模式,不支持别的,比如通知、发布/订阅 +2. 降低了可用性,因为客户端和服务端在请求过程中必须都是可用的 + +**2、消息队列** + +除了标准的基于RPC通信的微服务架构,还有基于消息队列通信的微服务架构,这种架构下的微服务采用发送消息(Publish Message)与监听消息(Subscribe Message)的方式来实现彼此之间的交互。 + +网易的蜂巢平台就采用了基于消息队列的微服务架构设计思路,如下图所示,微服务之间通过RabbitMQ传递消息,实现通信。 + +与上面几种微服务架构相比,基于消息队列的微服务架构并不多,案例也相对较少,更多地体现为一种与业务相关的设计经验,各家有各家的实现方式,缺乏公认的设计思路与参考架构,也没有形成一个知名的开源平台。因此,如果需要实施这种微服务架构,则基本上需要项目组自己从零开始去设计实现一个微服务架构基础平台,其代价是成本高、风险大。 + +**优点**: + +- 把客户端和服务端解耦,更松耦合提高可用性,因为消息中间件缓存了消息,直到消费者可以消费 +- 支持很多通信机制比如通知、发布/订阅等 + +**缺点**: + +- 缺乏公认的设计思路与参考架构,也没有形成一个知名的开源平台 +- 成本高、风险大 + +## 熔断器 + +雪崩效应:假如存在这样的调用链路,a服务->b服务->c服务,当c服务挂了的时候,b服务调用c服务会等待超时,a服务调用b服务也会等待超时,调用方长时间等不到相应而占用线程,如果有大量的请求过来,就会造成线程池打满,导致整个链路的服务奔溃。 + +为了解决分布式系统的雪崩效应,分布式系统引进了**熔断器机制** 。 + +当一个服务的处理用户请求的失败次数在一定时间内小于设定的阀值时,熔断器出于关闭状态,服务正常。 + +当服务处理用户请求失败次数在一定时间内大于设定的阀值时,说明服务出现故障,打开熔断器,这时所有的请求会快速返回失败的错误信息,不执行业务逻辑,从而防止故障的蔓延。 + +当处于打开状态的熔断器时,一段时间后出于半打开状态,并执行一定数量的请求,剩余的请求会执行快速失败,若执行请求失败了,则继续打开熔断器,若成功了,则将熔断器关闭。 + +## 服务网关 + +### 何为网关? + +通俗一点的讲:网关就是要去别的网络的时候,把报文首先发送到的那台设备。稍微专业一点的术语,网关就是当前主机的默认路由。 + +网关一般就是一台路由器,有点像“一个小区中的一个邮局”,小区里面的住户互相是知道怎么走,但是要向外地投递东西就不知道了,怎么办?把地址写好送到本小区的邮局就好了。 + +那么,怎么区分是“本小区”和“外地小区”的呢?根据IP地址 + 掩码。如果是在一个范围内的,就是本小区(局域网内部),如果掩不住的,就是外地的。 + +例如,你的机器的IP地址是:192.168.0.2/24,网关是192.168.0.1 + +如果机器访问的IP地址范围是:192.168.0.1~192.168.0.254的,说明是一个小区的邻居,你的机器就直接发送了(和网关没任何关系)。如果你访问的IP地址不是这个范围的,则就投递到192.168.0.1上,让这台设备来转发。 + +参考:https://www.zhihu.com/question/362842680/answer/951412213 + +### 何为API网关 + +假设你正在开发一个电商网站,那么这里会涉及到很多后端的微服务,比如会员、商品、推荐服务等等。 + +那么这里就会遇到一个问题,APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话,可以给每个业务都分配一个独立的域名(`https://service.api.company.com`),但这种方式会有几个问题: + +- 每个业务都会需要鉴权、限流、权限校验等逻辑,如果每个业务都各自为战,自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。 +- 如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝、亚马逊打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微服务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名 +- 每上线一个新的服务,都需要运维参与,申请域名、配置Nginx等,当上线、下线服务器时,同样也需要运维参与,另外采用域名这种方式,对于环境的隔离也不太友好,调用者需要自己根据域名自己进行判断。 +- 另外还有一个问题,后端每个微服务可能采用了不同的协议,比如HTTP、AMQP、自定义TCP协议等,但是你不可能要求客户端去适配这么多种协议,这是一项非常有挑战的工作,项目会变的非常复杂且很难维护。 + +更好的方式是采用API网关(也叫做服务网关),实现一个API网关**接管所有的入口流量**,类似Nginx的作用,将所有用户的请求转发给后端的服务器,但网关做的不仅仅只是简单的转发,也会针对流量做一些扩展,比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等,这样将通用的逻辑抽出来,由网关统一去做,业务方也能够更专注于业务逻辑,提升迭代的效率。 + +![](http://img.dabin-coder.cn/image/20220508185101.jpg) + +通过引入API网关,客户端只需要与API网关交互,而不用与各个业务方的接口分别通讯,但多引入一个组件就多引入了一个潜在的故障点,因此要实现一个高性能、稳定的网关,也会涉及到很多点。 + +网关层通常以集群的形式存在。并在服务网关层前通常会加上Nginx 用来负载均衡。 + +**服务网关基本功能**: + +![](http://img.dabin-coder.cn/image/20220508120340.png) + +- 智能路由:接收**外部**一切请求,并转发到后端的对外服务。注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。 +- 权限校验:网关可以做一些用户身份认证,权限认证,防止非法请求操作API 接口,对内部服务起到保护作用 +- API监控:监控经过网关的请求,以及网关本身的一些性能指标(gc等) +- 限流:与监控配合,进行限流操作 +- API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志 + +当然,网关实现这些功能,需要做高可用,否则网关很可能成为架构的瓶颈,最常用的网关组件Zuul、Nginx + +## 服务配置统一管理 + +在微服务架构中,需要有统一管理配置文件的组件,例如:SpringCloud Config组件、阿里的Diamond、百度的Disconf、携程的Apollo等 + +## 服务链路追踪 + +在微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与、参与顺序,是每个请求链路清晰可见,便于问题快速定位。 + +常用链路追踪组件有Google的Dapper、Twitter 的Zipkin,以及阿里Eagleeye。 + + + +## 微服务框架 + +市面常用微服务框架有:Spring Cloud 、Dubbo 、kubernetes + +- 从功能模块上考虑,Dubbo缺少很多功能模块,例如网关、链路追踪等 +- 从学习成本上考虑,Dubbo 版本趋于稳定,稳定完善、可以即学即用,难度简单,Spring cloud 基于Spring Boot,需要先掌握Spring Boot ,例外Spring cloud 大多为英文文档,要求学习者有一定的英文阅读能力 +- 从开发风格考虑,Dubbo倾向于xml的配置方式,Spring cloud 基于Spring Boot ,采用基于注解和JavaBean配置方式的敏捷开发 +- 从开发速度上考虑,Spring cloud 具有更高的开发和部署速度 +- 从通信方式上考虑,Spring cloud 基于HTTP Restful 风格,服务于服务之间完全无关、无耦合。Dubbo 基于远程调用,对接口、平台和语言有强依赖性,如果需要实现跨平台,需要有额外的中间件。 + +所以Dubbo专注于服务治理;Spring Cloud关注于微服务架构生态。 + diff --git a/docs/advance/distributed/5-distibuted-arch.md b/docs/advance/distributed/5-distibuted-arch.md new file mode 100644 index 0000000..30b0b32 --- /dev/null +++ b/docs/advance/distributed/5-distibuted-arch.md @@ -0,0 +1,3 @@ +# 分布式架构,微服务、限流、熔断.... + +[分布式架构,微服务、限流、熔断....](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247490543&idx=1&sn=ee34bee96511d5e548381e0576f8b484&chksm=ce98e6a9f9ef6fbf7db9c2b6d2fed26853a3bc13a50c3228ab57bea55afe0772008cdb1f957b&token=1594696656&lang=zh_CN#rd) \ No newline at end of file diff --git a/docs/advance/distributed/6-distributed-transaction.md b/docs/advance/distributed/6-distributed-transaction.md new file mode 100644 index 0000000..7b3e256 --- /dev/null +++ b/docs/advance/distributed/6-distributed-transaction.md @@ -0,0 +1,197 @@ +# 分布式事务 + +## 简介 + +### 事务 + +事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。事务应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。 + +### 分布式事务 + +分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务的特性。 + +### 强一致性、弱一致性、最终一致性 + +**强一致性** + +任何一次读都能读到某个数据的最近一次写的数据。系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。简言之,在任意时刻,所有节点中的数据是一样的。 + +**弱一致性** + +数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。 + +**最终一致性** + +不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致状态。 + +由于分布式事务方案,无法做到完全的ACID的保证,没有一种完美的方案,能够解决掉所有业务问题。因此在实际应用中,会根据业务的不同特性,选择最适合的分布式事务方案。 + +## 分布式事务的基础 + +### CAP理论 + +**Consistency**(一致性):数据一致更新,所有数据变动都是同步的(强一致性)。 + +**Availability**(可用性):好的响应性能。 + +**Partition tolerance**(分区容错性) :可靠性。 + +定理:任何分布式系统**只可同时满足二点**,没法三者兼顾。 + +CA系统(放弃P):指将所有数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上,就不会存在网络分区。所以强一致性以及可用性得到满足。 + +CP系统(放弃A):如果要求数据在各个服务器上是强一致的,然而网络分区会导致同步时间无限延长,那么如此一来可用性就得不到保障了。坚持事务ACID(原子性、一致性、隔离性和持久性)的传统数据库以及对结果一致性非常敏感的应用通常会做出这样的选择。 + +AP系统(放弃C):这里所说的放弃一致性,并不是完全放弃数据一致性,而是放弃数据的强一致性,而保留数据的最终一致性。如果即要求系统高可用又要求分区容错,那么就要放弃一致性了。因为一旦发生网络分区,节点之间将无法通信,为了满足高可用,每个节点只能用本地数据提供服务,这样就会导致数据不一致。一些遵守BASE原则数据库,(如:Cassandra、CouchDB等)往往会放宽对一致性的要求(满足最终一致性即可),一次来获取基本的可用性。 + +### BASE理论 + +BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展。 + +1. 基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。 +2. 软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。 +3. 最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。 + +BASE解决了CAP中理论没有网络延迟,在BASE中用软状态和最终一致,保证了延迟后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。 + +## 分布式事务解决方案 + +分布式事务的实现主要有以下 6 种方案: + +- 2PC 方案 +- TCC 方案 +- 本地消息表 +- MQ事务 +- Saga事务 +- 最大努力通知方案 + +### 2PC方案 + +2PC方案分为两阶段: + +第一阶段:事务管理器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交. + +第二阶段:事务协调器要求每个数据库提交数据,或者回滚数据。 + +优点: 尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,对于MySQL是从5.5开始支持。 + +缺点: + +- 单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。 +- 同步阻塞:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。 +- 数据不一致:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。 + +总的来说,2PC方案比较简单,成本较低,但是其单点问题,以及不能支持高并发(由于同步阻塞)依然是其最大的弱点。 + +### TCC + +TCC 的全称是:`Try`、`Confirm`、`Cancel`。 + +- **Try 阶段**:这个阶段说的是对各个服务的资源做检测以及对资源进行 **锁定或者预留**。 +- **Confirm 阶段**:这个阶段说的是在各个服务中执行实际的操作。 +- **Cancel 阶段**:如果任何一个服务的业务方法执行出错,那么这里就需要 **进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚) +- + +举个简单的例子如果你用100元买了一瓶水, Try阶段:你需要向你的钱包检查是否够100元并锁住这100元,水也是一样的。 + +如果有一个失败,则进行cancel(释放这100元和这一瓶水),如果cancel失败不论什么失败都进行重试cancel,所以需要保持幂等。 + +如果都成功,则进行confirm,确认这100元扣,和这一瓶水被卖,如果confirm失败无论什么失败则重试(会依靠活动日志进行重试)。 + +这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个**事务回滚实际上是严重依赖于你自己写代码来回滚和补偿**了,会造成补偿代码巨大。 + +### 本地消息表 + +本地消息表的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理。 + +![](http://img.dabin-coder.cn/image/本地消息表.png) + +对于本地消息队列来说核心是把大事务转变为小事务。还是举上面用100元去买一瓶水的例子。 + +1.当你扣钱的时候,你需要在你扣钱的服务器上新增加一个本地消息表,你需要把你扣钱和写入减去水的库存到本地消息表放入同一个事务(依靠数据库本地事务保证一致性。 + +2.这个时候有个定时任务去轮询这个本地事务表,把没有发送的消息,扔给商品库存服务器,叫他减去水的库存,到达商品服务器之后这个时候得先写入这个服务器的事务表,然后进行扣减,扣减成功后,更新事务表中的状态。 + +3.商品服务器通过定时任务扫描消息表或者直接通知扣钱服务器,扣钱服务器本地消息表进行状态更新。 + +4.针对一些异常情况,定时扫描未成功处理的消息,进行重新发送,在商品服务器接到消息之后,首先判断是否是重复的,如果已经接收,在判断是否执行,如果执行在马上又进行通知事务,如果未执行,需要重新执行需要由业务保证幂等,也就是不会多扣一瓶水。 + +本地消息队列是BASE理论,是最终一致模型,适用于对一致性要求不高的。实现这个模型时需要注意重试的幂等。 + +### MQ事务 + +基于 MQ 的分布式事务方案其实是对本地消息表的封装,将本地消息表基于 MQ 内部,其他方面的协议基本与本地消息表一致。 + +MQ事务方案整体流程和本地消息表的流程很相似,如下图: + +![](http://img.dabin-coder.cn/image/MQ事务方案.png) + +从上图可以看出和本地消息表方案唯一不同就是将本地消息表存在了MQ内部,而不是业务数据库中。 + +那么MQ内部的处理尤为重要,下面主要基于 RocketMQ 4.3 之后的版本介绍 MQ 的分布式事务方案。 + +在本地消息表方案中,保证事务主动方发写业务表数据和写消息表数据的一致性是基于数据库事务,RocketMQ 的事务消息相对于普通 MQ提供了 2PC 的提交接口,方案如下: + +**正常情况:事务主动方发消息** + +![](http://img.dabin-coder.cn/image/事务主动方发消息.png) + +这种情况下,事务主动方服务正常,没有发生故障,发消息流程如下: + +- 发送方向 MQ 服务端(MQ Server)发送 half 消息。 +- MQ Server 将消息持久化成功之后,向发送方 ack 确认消息已经发送成功。 +- 发送方开始执行本地事务逻辑。 +- 发送方根据本地事务执行结果向 MQ Server 提交二次确认(commit 或是 rollback)。 +- MQ Server 收到 commit 状态则将半消息标记为可投递,订阅方最终将收到该消息;MQ Server 收到 rollback 状态则删除半消息,订阅方将不会接受该消息。 + +**异常情况:事务主动方消息恢复** + +![](http://img.dabin-coder.cn/image/事务主动方消息恢复.png) + +在断网或者应用重启等异常情况下,图中 4 提交的二次确认超时未到达 MQ Server,此时处理逻辑如下: + +- MQ Server 对该消息发起消息回查。 +- 发送方收到消息回查后,需要检查对应消息的本地事务执行的最终结果。 +- 发送方根据检查得到的本地事务的最终状态再次提交二次确认。 +- MQ Server基于 commit/rollback 对消息进行投递或者删除。 + +**优点** + +相比本地消息表方案,MQ 事务方案优点是: + +- 消息数据独立存储 ,降低业务系统与消息系统之间的耦合。 +- 吞吐量大于使用本地消息表方案。 + +**缺点** + +- 一次消息发送需要两次网络请求(half 消息 + commit/rollback 消息) 。 +- 业务处理服务需要实现消息状态回查接口。 + +### Saga事务 + +Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。 + +Saga的实现有很多种方式,其中最流行的两种方式是: + +- **基于事件的方式**。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应。 +- **基于命令的方式**。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务。 + +### 最大努力通知方案 + +最大努力通知也称为定期校对,是对MQ事务方案的进一步优化。它在事务主动方增加了消息校对的接口,如果事务被动方没有接收到消息,此时可以调用事务主动方提供的消息校对的接口主动获取。 + +最大努力通知的整体流程如下图: + +![](http://img.dabin-coder.cn/image/最大努力通知方案.png) + +在可靠消息事务中,事务主动方需要将消息发送出去,并且消息接收方成功接收,这种可靠性发送是由事务主动方保证的; + +但是最大努力通知,事务主动方尽最大努力(重试,轮询....)将事务发送给事务接收方,但是仍然存在消息接收不到,此时需要事务被动方主动调用事务主动方的消息校对接口查询业务消息并消费,这种通知的可靠性是由事务被动方保证的。 + +最大努力通知适用于业务通知类型,例如微信交易的结果,就是通过最大努力通知方式通知各个商户,既有回调通知,也有交易查询接口。 + +## 参考文章 + +https://www.pdai.tech/md/arch/arch-z-transection.html + +https://juejin.cn/post/6844903647197806605#heading-15 diff --git a/docs/advance/distributed/README.md b/docs/advance/distributed/README.md new file mode 100644 index 0000000..b2e29b3 --- /dev/null +++ b/docs/advance/distributed/README.md @@ -0,0 +1,8 @@ +## 目录 + +- [全局唯一ID生成方案](./1-global-unique-id.md) +- [分布式锁](./2-distributed-lock.md) +- [RPC](./3-rpc.md) +- [微服务](./4-micro-service.md) +- [分布式架构,微服务、限流、熔断....](./6-distibuted-arch.md) +- [分布式事务](./7-distributed-transaction.md) diff --git a/docs/advance/excellent-article/1-redis-stock-minus.md b/docs/advance/excellent-article/1-redis-stock-minus.md new file mode 100644 index 0000000..7fa632c --- /dev/null +++ b/docs/advance/excellent-article/1-redis-stock-minus.md @@ -0,0 +1,317 @@ +# Redis 如何实现库存扣减操作和防止被超卖? + +电商当项目经验已经非常普遍了,不管你是包装的还是真实的,起码要能讲清楚电商中常见的问题,比如库存的操作怎么防止商品被超卖 + +解决方案: +- 基于数据库单库存 +- 基于数据库多库存 +- 基于redis + +基于redis实现扣减库存的具体实现 +- 初始化库存回调函数(IStockCallback) +- 扣减库存服务(StockService) +- 调用 + +![](http://img.dabin-coder.cn/image/库存扣减1.png) + +------ + +在日常开发中有很多地方都有类似扣减库存的操作,比如电商系统中的商品库存,抽奖系统中的奖品库存等。 + +## **解决方案** + +1. 使用mysql数据库,使用一个字段来存储库存,每次扣减库存去更新这个字段。 +2. 还是使用数据库,但是将库存分层多份存到多条记录里面,扣减库存的时候路由一下,这样子增大了并发量,但是还是避免不了大量的去访问数据库来更新库存。 +3. 将库存放到redis使用redis的incrby特性来扣减库存。 + +## **分析** + +在上面的第一种和第二种方式都是基于数据来扣减库存。 + +### 基于数据库单库存 + +第一种方式在所有请求都会在这里等待锁,获取锁有去扣减库存。在并发量不高的情况下可以使用,但是一旦并发量大了就会有大量请求阻塞在这里,导致请求超时,进而整个系统雪崩;而且会频繁的去访问数据库,大量占用数据库资源,所以在并发高的情况下这种方式不适用。 + +### 基于数据库多库存 + +第二种方式其实是第一种方式的优化版本,在一定程度上提高了并发量,但是在还是会大量的对数据库做更新操作大量占用数据库资源。 + +**基于数据库来实现扣减库存还存在的一些问题:** + +- 用数据库扣减库存的方式,扣减库存的操作必须在一条语句中执行,不能先selec在update,这样在并发下会出现超扣的情况。如: + +``` +update number set x=x-1 where x > 0 +``` + +- MySQL自身对于高并发的处理性能就会出现问题,一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。 +- 当减库存和高并发碰到一起的时候,由于操作的库存数目在同一行,就会出现争抢InnoDB行锁的问题,导致出现互相等待甚至死锁,从而大大降低MySQL的处理性能,最终导致前端页面出现超时异常。 + +### 基于redis + +针对上述问题的问题我们就有了第三种方案,将库存放到缓存,利用redis的incrby特性来扣减库存,解决了超扣和性能问题。但是一旦缓存丢失需要考虑恢复方案。比如抽奖系统扣奖品库存的时候,初始库存=总的库存数-已经发放的奖励数,但是如果是异步发奖,需要等到MQ消息消费完了才能重启redis初始化库存,否则也存在库存不一致的问题。 + +## **基于redis实现扣减库存的具体实现** + +- 我们使用redis的lua脚本来实现扣减库存 +- 由于是分布式环境下所以还需要一个分布式锁来控制只能有一个服务去初始化库存 +- 需要提供一个回调函数,在初始化库存的时候去调用这个函数获取初始化库存 + +### 初始化库存回调函数(IStockCallback ) + +``` +/** + * 获取库存回调 + */ +public interface IStockCallback { + + /** + * 获取库存 + * @return + */ + int getStock(); +} +``` + +### 扣减库存服务(StockService) + +``` +/** + * 扣库存 + * + */ +@Service +public class StockService { + Logger logger = LoggerFactory.getLogger(StockService.class); + + /** + * 不限库存 + */ + public static final long UNINITIALIZED_STOCK = -3L; + + /** + * Redis 客户端 + */ + @Autowired + private RedisTemplate redisTemplate; + + /** + * 执行扣库存的脚本 + */ + public static final String STOCK_LUA; + + static { + /** + * + * @desc 扣减库存Lua脚本 + * 库存(stock)-1:表示不限库存 + * 库存(stock)0:表示没有库存 + * 库存(stock)大于0:表示剩余库存 + * + * @params 库存key + * @return + * -3:库存未初始化 + * -2:库存不足 + * -1:不限库存 + * 大于等于0:剩余库存(扣减之后剩余的库存) + * redis缓存的库存(value)是-1表示不限库存,直接返回1 + */ + StringBuilder sb = new StringBuilder(); + sb.append("if (redis.call('exists', KEYS[1]) == 1) then"); + sb.append(" local stock = tonumber(redis.call('get', KEYS[1]));"); + sb.append(" local num = tonumber(ARGV[1]);"); + sb.append(" if (stock == -1) then"); + sb.append(" return -1;"); + sb.append(" end;"); + sb.append(" if (stock >= num) then"); + sb.append(" return redis.call('incrby', KEYS[1], 0 - num);"); + sb.append(" end;"); + sb.append(" return -2;"); + sb.append("end;"); + sb.append("return -3;"); + STOCK_LUA = sb.toString(); + } + + /** + * @param key 库存key + * @param expire 库存有效时间,单位秒 + * @param num 扣减数量 + * @param stockCallback 初始化库存回调函数 + * @return -2:库存不足; -1:不限库存; 大于等于0:扣减库存之后的剩余库存 + */ + public long stock(String key, long expire, int num, IStockCallback stockCallback) { + long stock = stock(key, num); + // 初始化库存 + if (stock == UNINITIALIZED_STOCK) { + RedisLock redisLock = new RedisLock(redisTemplate, key); + try { + // 获取锁 + if (redisLock.tryLock()) { + // 双重验证,避免并发时重复回源到数据库 + stock = stock(key, num); + if (stock == UNINITIALIZED_STOCK) { + // 获取初始化库存 + final int initStock = stockCallback.getStock(); + // 将库存设置到redis + redisTemplate.opsForValue().set(key, initStock, expire, TimeUnit.SECONDS); + // 调一次扣库存的操作 + stock = stock(key, num); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } finally { + redisLock.unlock(); + } + + } + return stock; + } + + /** + * 加库存(还原库存) + * + * @param key 库存key + * @param num 库存数量 + * @return + */ + public long addStock(String key, int num) { + + return addStock(key, null, num); + } + + /** + * 加库存 + * + * @param key 库存key + * @param expire 过期时间(秒) + * @param num 库存数量 + * @return + */ + public long addStock(String key, Long expire, int num) { + boolean hasKey = redisTemplate.hasKey(key); + // 判断key是否存在,存在就直接更新 + if (hasKey) { + return redisTemplate.opsForValue().increment(key, num); + } + + Assert.notNull(expire,"初始化库存失败,库存过期时间不能为null"); + RedisLock redisLock = new RedisLock(redisTemplate, key); + try { + if (redisLock.tryLock()) { + // 获取到锁后再次判断一下是否有key + hasKey = redisTemplate.hasKey(key); + if (!hasKey) { + // 初始化库存 + redisTemplate.opsForValue().set(key, num, expire, TimeUnit.SECONDS); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } finally { + redisLock.unlock(); + } + + return num; + } + + /** + * 获取库存 + * + * @param key 库存key + * @return -1:不限库存; 大于等于0:剩余库存 + */ + public int getStock(String key) { + Integer stock = (Integer) redisTemplate.opsForValue().get(key); + return stock == null ? -1 : stock; + } + + /** + * 扣库存 + * + * @param key 库存key + * @param num 扣减库存数量 + * @return 扣减之后剩余的库存【-3:库存未初始化; -2:库存不足; -1:不限库存; 大于等于0:扣减库存之后的剩余库存】 + */ + private Long stock(String key, int num) { + // 脚本里的KEYS参数 + List keys = new ArrayList<>(); + keys.add(key); + // 脚本里的ARGV参数 + List args = new ArrayList<>(); + args.add(Integer.toString(num)); + + long result = redisTemplate.execute(new RedisCallback() { + @Override + public Long doInRedis(RedisConnection connection) throws DataAccessException { + Object nativeConnection = connection.getNativeConnection(); + // 集群模式和单机模式虽然执行脚本的方法一样,但是没有共同的接口,所以只能分开执行 + // 集群模式 + if (nativeConnection instanceof JedisCluster) { + return (Long) ((JedisCluster) nativeConnection).eval(STOCK_LUA, keys, args); + } + + // 单机模式 + else if (nativeConnection instanceof Jedis) { + return (Long) ((Jedis) nativeConnection).eval(STOCK_LUA, keys, args); + } + return UNINITIALIZED_STOCK; + } + }); + return result; + } + +} +``` + +### 调用 + +``` +@RestController +public class StockController { + + @Autowired + private StockService stockService; + + @RequestMapping(value = "stock", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Object stock() { + // 商品ID + long commodityId = 1; + // 库存ID + String redisKey = "redis_key:stock:" + commodityId; + long stock = stockService.stock(redisKey, 60 * 60, 2, () -> initStock(commodityId)); + return stock >= 0; + } + + /** + * 获取初始的库存 + * + * @return + */ + private int initStock(long commodityId) { + // TODO 这里做一些初始化库存的操作 + return 1000; + } + + @RequestMapping(value = "getStock", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Object getStock() { + // 商品ID + long commodityId = 1; + // 库存ID + String redisKey = "redis_key:stock:" + commodityId; + + return stockService.getStock(redisKey); + } + + @RequestMapping(value = "addStock", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Object addStock() { + // 商品ID + long commodityId = 2; + // 库存ID + String redisKey = "redis_key:stock:" + commodityId; + + return stockService.addStock(redisKey, 2); + } +} +``` + diff --git a/docs/advance/excellent-article/10-file-upload.md b/docs/advance/excellent-article/10-file-upload.md new file mode 100644 index 0000000..35655eb --- /dev/null +++ b/docs/advance/excellent-article/10-file-upload.md @@ -0,0 +1,341 @@ +# 大文件上传时如何做到秒传? + +大家好,我是大彬~ + +文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上传到一半中断后,继续上传却只能重头开始上传,这种让人不爽的体验。 + +那有没有比较好的上传体验呢,答案有的,就是下边要介绍的几种上传方式 + +## 秒传 + +### 1、什么是秒传 + +通俗的说,你把要上传的东西上传,服务器会先做**MD5**校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让**MD5**改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5就变了,就不会秒传了. + +### 2、本文实现的秒传核心逻辑 + +**a**、利用redis的set方法存放文件上传状态,其中key为文件上传的md5,value为是否上传完成的标志位, + +**b**、当标志位true为上传已经完成,此时如果有相同文件上传,则进入秒传逻辑。如果标志位为false,则说明还没上传完成,此时需要在调用set的方法,保存块号文件记录的路径,其中key为上传文件md5加一个固定前缀,value为块号文件记录路径 + +## 分片上传 + +### 1、什么是分片上传 + +分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。 + +### 2、分片上传的场景 + +1.大文件上传 + +2.网络环境环境不好,存在需要重传风险的场景 + +## 断点续传 + +### 1、什么是断点续传 + +断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。本文的断点续传主要是针对断点上传场景。 + +#### 2、应用场景 + +断点续传可以看成是分片上传的一个衍生,因此可以使用分片上传的场景,都可以使用断点续传。 + +#### 3、实现断点续传的核心逻辑 + +在分片上传的过程中,如果因为系统崩溃或者网络中断等异常因素导致上传中断,这时候客户端需要记录上传的进度。在之后支持再次上传时,可以继续从上次上传中断的地方进行继续上传。 + +为了避免客户端在上传之后的进度数据被删除而导致重新开始从头上传的问题,服务端也可以提供相应的接口便于客户端对已经上传的分片数据进行查询,从而使客户端知道已经上传的分片数据,从而从下一个分片数据开始继续上传。 + +#### 4、实现流程步骤 + +a、方案一,常规步骤 + +- 将需要上传的文件按照一定的分割规则,分割成相同大小的数据块; +- 初始化一个分片上传任务,返回本次分片上传唯一标识; +- 按照一定的策略(串行或并行)发送各个分片数据块; +- 发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件。 + +b、方案二、本文实现的步骤 + +- 前端(客户端)需要根据固定大小对文件进行分片,请求后端(服务端)时要带上分片序号和大小 +- 服务端创建conf文件用来记录分块位置,conf文件长度为总分片数,每上传一个分块即向conf文件中写入一个127,那么没上传的位置就是默认的0,已上传的就是Byte.MAX_VALUE 127(这步是实现断点续传和秒传的核心步骤) +- 服务器按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件。 + +#### 5、分片上传/断点上传代码实现 + +a、前端采用百度提供的webuploader的插件,进行分片。因本文主要介绍服务端代码实现,webuploader如何进行分片,具体实现可以查看如下链接: + +> http://fex.baidu.com/webuploader/getting-started.html + +b、后端用两种方式实现文件写入,一种是用**RandomAccessFile**,如果对**RandomAccessFile**不熟悉的朋友,可以查看如下链接: + +> https://blog.csdn.net/dimudan2015/article/details/81910690 + +另一种是使用**MappedByteBuffer**,对**MappedByteBuffer**不熟悉的朋友,可以查看如下链接进行了解: + +> https://www.jianshu.com/p/f90866dcbffc + +## 后端进行写入操作的核心代码 + +### 1、RandomAccessFile实现方式 + +``` +@UploadMode(mode = UploadModeEnum.RANDOM_ACCESS) +@Slf4j +public class RandomAccessUploadStrategy extends SliceUploadTemplate { + + @Autowired + private FilePathUtil filePathUtil; + + @Value("${upload.chunkSize}") + private long defaultChunkSize; + + @Override + public boolean upload(FileUploadRequestDTO param) { + RandomAccessFile accessTmpFile = null; + try { + String uploadDirPath = filePathUtil.getPath(param); + File tmpFile = super.createTmpFile(param); + accessTmpFile = new RandomAccessFile(tmpFile, "rw"); + //这个必须与前端设定的值一致 + long chunkSize = Objects.isNull(param.getChunkSize()) ? defaultChunkSize * 1024 * 1024 + : param.getChunkSize(); + long offset = chunkSize * param.getChunk(); + //定位到该分片的偏移量 + accessTmpFile.seek(offset); + //写入该分片数据 + accessTmpFile.write(param.getFile().getBytes()); + boolean isOk = super.checkAndSetUploadProgress(param, uploadDirPath); + return isOk; + } catch (IOException e) { + log.error(e.getMessage(), e); + } finally { + FileUtil.close(accessTmpFile); + } + return false; + } + +} +``` + +### 2、MappedByteBuffer实现方式 + +``` +@UploadMode(mode = UploadModeEnum.MAPPED_BYTEBUFFER) +@Slf4j +public class MappedByteBufferUploadStrategy extends SliceUploadTemplate { + + @Autowired + private FilePathUtil filePathUtil; + + @Value("${upload.chunkSize}") + private long defaultChunkSize; + + @Override + public boolean upload(FileUploadRequestDTO param) { + + RandomAccessFile tempRaf = null; + FileChannel fileChannel = null; + MappedByteBuffer mappedByteBuffer = null; + try { + String uploadDirPath = filePathUtil.getPath(param); + File tmpFile = super.createTmpFile(param); + tempRaf = new RandomAccessFile(tmpFile, "rw"); + fileChannel = tempRaf.getChannel(); + + long chunkSize = Objects.isNull(param.getChunkSize()) ? defaultChunkSize * 1024 * 1024 + : param.getChunkSize(); + //写入该分片数据 + long offset = chunkSize * param.getChunk(); + byte[] fileData = param.getFile().getBytes(); + mappedByteBuffer = fileChannel +.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length); + mappedByteBuffer.put(fileData); + boolean isOk = super.checkAndSetUploadProgress(param, uploadDirPath); + return isOk; + + } catch (IOException e) { + log.error(e.getMessage(), e); + } finally { + + FileUtil.freedMappedByteBuffer(mappedByteBuffer); + FileUtil.close(fileChannel); + FileUtil.close(tempRaf); + + } + + return false; + } + +} +``` + +### 3、文件操作核心模板类代码 + +``` +@Slf4j +public abstract class SliceUploadTemplate implements SliceUploadStrategy { + + public abstract boolean upload(FileUploadRequestDTO param); + + protected File createTmpFile(FileUploadRequestDTO param) { + + FilePathUtil filePathUtil = SpringContextHolder.getBean(FilePathUtil.class); + param.setPath(FileUtil.withoutHeadAndTailDiagonal(param.getPath())); + String fileName = param.getFile().getOriginalFilename(); + String uploadDirPath = filePathUtil.getPath(param); + String tempFileName = fileName + "_tmp"; + File tmpDir = new File(uploadDirPath); + File tmpFile = new File(uploadDirPath, tempFileName); + if (!tmpDir.exists()) { + tmpDir.mkdirs(); + } + return tmpFile; + } + + @Override + public FileUploadDTO sliceUpload(FileUploadRequestDTO param) { + + boolean isOk = this.upload(param); + if (isOk) { + File tmpFile = this.createTmpFile(param); + FileUploadDTO fileUploadDTO = this.saveAndFileUploadDTO(param.getFile().getOriginalFilename(), tmpFile); + return fileUploadDTO; + } + String md5 = FileMD5Util.getFileMD5(param.getFile()); + + Map map = new HashMap<>(); + map.put(param.getChunk(), md5); + return FileUploadDTO.builder().chunkMd5Info(map).build(); + } + + /** + * 检查并修改文件上传进度 + */ + public boolean checkAndSetUploadProgress(FileUploadRequestDTO param, String uploadDirPath) { + + String fileName = param.getFile().getOriginalFilename(); + File confFile = new File(uploadDirPath, fileName + ".conf"); + byte isComplete = 0; + RandomAccessFile accessConfFile = null; + try { + accessConfFile = new RandomAccessFile(confFile, "rw"); + //把该分段标记为 true 表示完成 + System.out.println("set part " + param.getChunk() + " complete"); + //创建conf文件文件长度为总分片数,每上传一个分块即向conf文件中写入一个127,那么没上传的位置就是默认0,已上传的就是Byte.MAX_VALUE 127 + accessConfFile.setLength(param.getChunks()); + accessConfFile.seek(param.getChunk()); + accessConfFile.write(Byte.MAX_VALUE); + + //completeList 检查是否全部完成,如果数组里是否全部都是127(全部分片都成功上传) + byte[] completeList = FileUtils.readFileToByteArray(confFile); + isComplete = Byte.MAX_VALUE; + for (int i = 0; i < completeList.length && isComplete == Byte.MAX_VALUE; i++) { + //与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE + isComplete = (byte) (isComplete & completeList[i]); + System.out.println("check part " + i + " complete?:" + completeList[i]); + } + + } catch (IOException e) { + log.error(e.getMessage(), e); + } finally { + FileUtil.close(accessConfFile); + } + boolean isOk = setUploadProgress2Redis(param, uploadDirPath, fileName, confFile, isComplete); + return isOk; + } + + /** + * 把上传进度信息存进redis + */ + private boolean setUploadProgress2Redis(FileUploadRequestDTO param, String uploadDirPath, + String fileName, File confFile, byte isComplete) { + + RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class); + if (isComplete == Byte.MAX_VALUE) { + redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), "true"); + redisUtil.del(FileConstant.FILE_MD5_KEY + param.getMd5()); + confFile.delete(); + return true; + } else { + if (!redisUtil.hHasKey(FileConstant.FILE_UPLOAD_STATUS, param.getMd5())) { + redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), "false"); + redisUtil.set(FileConstant.FILE_MD5_KEY + param.getMd5(), + uploadDirPath + FileConstant.FILE_SEPARATORCHAR + fileName + ".conf"); + } + + return false; + } + } +/** + * 保存文件操作 + */ + public FileUploadDTO saveAndFileUploadDTO(String fileName, File tmpFile) { + + FileUploadDTO fileUploadDTO = null; + + try { + + fileUploadDTO = renameFile(tmpFile, fileName); + if (fileUploadDTO.isUploadComplete()) { + System.out + .println("upload complete !!" + fileUploadDTO.isUploadComplete() + " name=" + fileName); + //TODO 保存文件信息到数据库 + + } + + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + + } + return fileUploadDTO; + } +/** + * 文件重命名 + * + * @param toBeRenamed 将要修改名字的文件 + * @param toFileNewName 新的名字 + */ + private FileUploadDTO renameFile(File toBeRenamed, String toFileNewName) { + //检查要重命名的文件是否存在,是否是文件 + FileUploadDTO fileUploadDTO = new FileUploadDTO(); + if (!toBeRenamed.exists() || toBeRenamed.isDirectory()) { + log.info("File does not exist: {}", toBeRenamed.getName()); + fileUploadDTO.setUploadComplete(false); + return fileUploadDTO; + } + String ext = FileUtil.getExtension(toFileNewName); + String p = toBeRenamed.getParent(); + String filePath = p + FileConstant.FILE_SEPARATORCHAR + toFileNewName; + File newFile = new File(filePath); + //修改文件名 + boolean uploadFlag = toBeRenamed.renameTo(newFile); + + fileUploadDTO.setMtime(DateUtil.getCurrentTimeStamp()); + fileUploadDTO.setUploadComplete(uploadFlag); + fileUploadDTO.setPath(filePath); + fileUploadDTO.setSize(newFile.length()); + fileUploadDTO.setFileExt(ext); + fileUploadDTO.setFileId(toFileNewName); + + return fileUploadDTO; + } +} +``` + +## 总结 + +在实现分片上传的过程,需要前端和后端配合,比如前后端的上传块号的文件大小,前后端必须得要一致,否则上传就会有问题。其次文件相关操作正常都是要搭建一个文件服务器的,比如使用**fastdfs**、**hdfs**等。 + +本示例代码在电脑配置为4核内存8G情况下,上传24G大小的文件,上传时间需要30多分钟,主要时间耗费在前端的**md5**值计算,后端写入的速度还是比较快。 + +如果项目组觉得自建文件服务器太花费时间,且项目的需求仅仅只是上传下载,那么推荐使用阿里的oss服务器,其介绍可以查看官网: + +> https://help.aliyun.com/product/31815.html + +阿里的oss它本质是一个对象存储服务器,而非文件服务器,因此如果有涉及到大量删除或者修改文件的需求,oss可能就不是一个好的选择。 + +文末提供一个oss表单上传的链接demo,通过oss表单上传,可以直接从前端把文件上传到oss服务器,把上传的压力都推给oss服务器: + +> https://www.cnblogs.com/ossteam/p/4942227.html \ No newline at end of file diff --git a/docs/advance/excellent-article/11-8-architect-pattern.md b/docs/advance/excellent-article/11-8-architect-pattern.md new file mode 100644 index 0000000..7ec3181 --- /dev/null +++ b/docs/advance/excellent-article/11-8-architect-pattern.md @@ -0,0 +1,3 @@ +# 8种架构模式 + +[8种架构模式](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247490779&idx=2&sn=eff9e8cf9b15c29630514a137f102701&chksm=ce98e19df9ef688bd9c7b775658c704a51b7961347a7aabf70e6c555cb57560aa5e8b1e497a1&token=1170645384&lang=zh_CN#rd) \ No newline at end of file diff --git a/docs/advance/excellent-article/12-mysql-table-max-rows.md b/docs/advance/excellent-article/12-mysql-table-max-rows.md new file mode 100644 index 0000000..d8f5381 --- /dev/null +++ b/docs/advance/excellent-article/12-mysql-table-max-rows.md @@ -0,0 +1,212 @@ +# MySQL最大建议行数 2000w,靠谱吗? + +## **1 背景** + +作为在后端圈开车的多年老司机,是不是经常听到过,“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”,“你这个表数据都马上要到 2000w 了,难怪查询速度慢” + +这些名言民语就和 “群里只讨论技术,不开车,开车速度不要超过 120 码,否则自动踢群”,只听过,没试过,哈哈。 + +下面我们就把车速踩到底,干到 180 码试试……. + +## **2 实验** + +实验一把看看… + +建一张表 + +``` +CREATE TABLE person( +id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键', +person_id tinyint not null comment '用户id', +person_name VARCHAR(200) comment '用户名称', +gmt_create datetime comment '创建时间', +gmt_modified datetime comment '修改时间' +) comment '人员信息表'; +``` + +插入一条数据 + +``` +insert into person values(1,1,'user_1', NOW(), now()); +``` + +利用 mysql 伪列 rownum 设置伪列起始点为 1 + +``` +select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init; +set @i=1; +``` + +运行下面的 sql,连续执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w , 如此下去即可实现千万测试数据的插入,如果不想翻倍翻倍的增加数据,而是想少量,少量的增加,有个技巧,就是在 SQL 的后面增加 where 条件,如 id > 某一个值去控制增加的数据量即可。 + +``` +insert into person(id, person_id, person_name, gmt_create, gmt_modified) + +select @i:=@i+1, + +left(rand()*10,10) as person_id, + +concat('user_',@i%2048), + +date_add(gmt_create,interval + @i*cast(rand()*100 as signed) SECOND), + +date_add(date_add(gmt_modified,interval +@i*cast(rand()*100 as signed) SECOND), interval + cast(rand()*1000000 as signed) SECOND) + +from person; +``` + +此处需要注意的是,也许你在执行到近 800w 或者 1000w 数据的时候,会报错:`The total number of locks exceeds the lock table size`,这是由于你的临时表内存设置的不够大,只需要扩大一下设置参数即可。 + +``` +SET GLOBAL tmp_table_size =512*1024*1024; (512M) +SET global innodb_buffer_pool_size= 1*1024*1024*1024 (1G); +``` + +先来看一组测试数据,这组数据是在 mysql8.0 的版本,并且是在我本机上,由于本机还跑着 idea , 浏览器等各种工具,所以并不是机器配置就是用于数据库配置,所以测试数据只限于参考。 + +![](http://img.dabin-coder.cn/image/max-row1.png) + +![](http://img.dabin-coder.cn/image/max-row2.png) + +看到这组数据似乎好像真的和标题对应,当数据达到 2000w 以后,查询时长急剧上升;难道这就是铁律吗? + +那下面我们就来看看这个建议值 2kw 是怎么来的? + +## **3 单表数量限制** + +首先我们先想想数据库单表行数最大多大? + +``` +CREATE TABLE person( +id int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键', +person_id tinyint not null comment '用户id', +person_name VARCHAR(200) comment '用户名称', +gmt_create datetime comment '创建时间', +gmt_modified datetime comment '修改时间' +) comment '人员信息表'; +``` + +看看上面的建表 sql,id 是主键,本身就是唯一的,也就是说主键的大小可以限制表的上限,如果主键声明 int 大小,也就是 32 位,那么支持 `2^32-1 ~~21` 亿;如果是 bigint,那就是 `2^62-1` ?(`36893488147419103232`),难以想象这个的多大了,一般还没有到这个限制之前,可能数据库已经爆满了!! + +有人统计过,如果建表的时候,自增字段选择无符号的 bigint , 那么自增长最大值是 `18446744073709551615`,按照一秒新增一条记录的速度,大约什么时候能用完? + +![](http://img.dabin-coder.cn/image/max-row3.png) + +## **4 表空间** + +下面我们再来看看索引的结构,对了,我们下面讲内容都是基于 Innodb 引擎的,大家都知道 Innodb 的索引内部用的是 B+ 树 + +![](http://img.dabin-coder.cn/image/max-row4.png) + +这张表数据,在硬盘上存储也是类似如此的,它实际是放在一个叫 `person.ibd` (innodb data)的文件中,也叫做表空间;虽然数据表中,他们看起来是一条连着一条,但是实际上在文件中它被分成很多小份的数据页,而且每一份都是 16K。大概就像下面这样,当然这只是我们抽象出来的,在表空间中还有段、区、组等很多概念,但是我们需要跳出来看。 + +![](http://img.dabin-coder.cn/image/max-row5.png) + +## **5 页的数据结构** + +因为每个页只有 16K 的大小,但是如果数据很多,那一页肯定就放不下这些数据,那数据肯定就会被分到其他的页中,所以为了把这些页关联起来,肯定就会有记录前后页地址,方便找到对应页;同时每页都是唯一的,那就会需要有一个唯一标志来标记页,就是页号; + +页中会记录数据所以会存在读写操作,读写操作会存在中断或者其他异常导致数据不全等,那就会需要有校验机制,所以里面还有会校验码,而读操作最重要的就是效率问题,如果按照记录一个个进行遍历,那肯定是很费劲的,所以这里面还会为数据生成对应的页目录(`Page Directory`); 所以实际页的内部结构像是下面这样的。 + +![](http://img.dabin-coder.cn/image/max-row6.png) + +从图中可以看出,一个 InnoDB 数据页的存储空间大致被划分成了 7 个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。 + +在页的 7 个组成部分中,我们自己存储的记录会按照我们指定的行格式存储到 `User Records` 部分。 + +但是在一开始生成页的时候,其实并没有 `User Records` 这个部分,每当我们插入一条记录,都会从 `Free Space` 部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到 `User Records` 部分,当 `Free Space` 部分的空间全部被 `User Records` 部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了。 + +这个过程的图示如下: + +![](http://img.dabin-coder.cn/image/max-row7.png) + +刚刚上面说到了数据的新增的过程。 + +那下面就来说说,数据的查找过程,假如我们需要查找一条记录,我们可以把表空间中的每一页都加载到内存中,然后对记录挨个判断是不是我们想要的,在数据量小的时候,没啥问题,内存也可以撑;但是现实就是这么残酷,不会给你这个局面;为了解决这问题,mysql 中就有了索引的概念;大家都知道索引能够加快数据的查询,那到底是怎么个回事呢?下面我就来看看。 + +## **6 索引的数据结构** + +在 mysql 中索引的数据结构和刚刚描述的页几乎是一模一样的,而且大小也是 16K, 但是在索引页中记录的是页 (数据页,索引页) 的最小主键 id 和页号,以及在索引页中增加了层级的信息,从 0 开始往上算,所以页与页之间就有了上下层级的概念。 + +![](http://img.dabin-coder.cn/image/max-row8.png)看到这个图之后,是不是有点似曾相似的感觉,是不是像一棵二叉树啊,对,没错!它就是一棵树,只不过我们在这里只是简单画了三个节点,2 层结构的而已,如果数据多了,可能就会扩展到 3 层的树,这个就是我们常说的 B+ 树,最下面那一层的 page level =0, 也就是叶子节点,其余都是非叶子节点。 + +![](http://img.dabin-coder.cn/image/max-row9.png) + +看上图中,我们是单拿一个节点来看,首先它是一个非叶子节点(索引页),在它的内容区中有 id 和 页号地址两部分,这个 id 是对应页中记录的最小记录 id 值,页号地址是指向对应页的指针;而数据页与此几乎大同小异,区别在于数据页记录的是真实的行数据而不是页地址,而且 id 的也是顺序的。 + +## **7 单表建议值** + +下面我们就以 3 层,2 分叉(实际中是 M 分叉)的图例来说明一下查找一个行数据的过程。 + +比如说我们需要查找一个 id=6 的行数据,因为在非叶子节点中存放的是页号和该页最小的 id,所以我们从顶层开始对比,首先看页号 10 中的目录,有 `[id=1, 页号 = 20]`,`[id=5, 页号 = 30]`, 说明左侧节点最小 id 为 1,右侧节点最小 id 是 5;`6>5`, 那按照二分法查找的规则,肯定就往右侧节点继续查找,找到页号 30 的节点后,发现这个节点还有子节点(非叶子节点),那就继续比对,同理,`6>5&&6<7`, 所以找到了页号 60,找到页号 60 之后,发现此节点为叶子节点(数据节点),于是将此页数据加载至内存进行一一对比,结果找到了 `id=6 `的数据行。 + +从上述的过程中发现,我们为了查找 id=6 的数据,总共查询了三个页,如果三个页都在磁盘中(未提前加载至内存),那么最多需要经历三次的磁盘 IO。 + +需要注意的是,图中的页号只是个示例,实际情况下并不是连续的,在磁盘中存储也不一定是顺序的。 + +![](http://img.dabin-coder.cn/image/max-row10.png)至此, + +我们大概已经了解了表的数据是怎么个结构了,也大概知道查询数据是个怎么的过程了,这样我们也就能大概估算这样的结构能存放多少数据了。 + +从上面的图解我们知道 B+ 数的叶子节点才是存在数据的,而非叶子节点是用来存放索引数据的。 + +所以,同样一个 16K 的页,非叶子节点里的每条数据都指向新的页,而新的页有两种可能 + +- 如果是叶子节点,那么里面就是一行行的数据 +- 如果是非叶子节点的话,那么就会继续指向新的页 + +假设 + +- 非叶子节点内指向其他页的数量为 x +- 叶子节点内能容纳的数据行数为 y +- B+ 数的层数为 z + +如下图中所示 + +`Total =x^(z-1) *y `也就是说总数会等于 x 的 `z-1` 次方 与 Y 的乘积。 + +![](http://img.dabin-coder.cn/image/max-row11.png) + +> X =? + +在文章的开头已经介绍了页的结构,索引也也不例外,都会有 `File Header (38 byte)`、`Page Header (56 Byte)`、`Infimum + Supermum(26 byte)`、`File Trailer(8byte)`, 再加上页目录,大概 1k 左右,我们就当做它就是 1K, 那整个页的大小是 16K, 剩下 15k 用于存数据,在索引页中主要记录的是主键与页号,主键我们假设是 Bigint (8 byte), 而页号也是固定的(4Byte), 那么索引页中的一条数据也就是 12byte; 所以 `x=15*1024/12≈1280` 行。 + +> Y=? + +叶子节点和非叶子节点的结构是一样的,同理,能放数据的空间也是 15k;但是叶子节点中存放的是真正的行数据,这个影响的因素就会多很多,比如,字段的类型,字段的数量;每行数据占用空间越大,页中所放的行数量就会越少;这边我们暂时按一条行数据 1k 来算,那一页就能存下 15 条,`Y≈15`。 + +算到这边了,是不是心里已经有谱了啊 + +- 根据上述的公式,`Total =x^(z-1) y`,已知 `x=1280,y=15` +- 假设 B+ 树是两层,那就是 Z =2, `Total = (1280 ^1 )15 = 19200` +- 假设 B+ 树是三层,那就是 Z =3, `Total = (1280 ^2) *15 = 24576000 (约 2.45kw)` + +哎呀,妈呀!这不是正好就是文章开头说的最大行数建议值 2000w 嘛!对的,一般 B+ 数的层级最多也就是 3 层,你试想一下,如果是 4 层,除了查询的时候磁盘 IO 次数会增加,而且这个 Total 值会是多少,大概应该是 3 百多亿吧,也不太合理,所以,3 层应该是比较合理的一个值。 + +到这里难道就完了? + +no + +我们刚刚在说 Y 的值时候假设的是 1K ,那比如我实际当行的数据占用空间不是 1K , 而是 5K, 那么单个数据页最多只能放下 3 条数据 + +同样,还是按照 Z=3 的值来计算,那 `Total = (1280 ^2) *3 = 4915200 (近 500w)` + +所以,在保持相同的层级(相似查询性能)的情况下,在行数据大小不同的情况下,其实这个最大建议值也是不同的,而且影响查询性能的还有很多其他因素,比如,数据库版本,服务器配置,sql 的编写等等,MySQL 为了提高性能,会将表的索引装载到内存中。在 `InnoDB buffer size` 足够的情况下,其能完成全加载进内存,查询不会有问题。 + +但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降,所以增加硬件配置(比如把内存当磁盘使),可能会带来立竿见影的性能提升哈。 + +## **8 总结** + +Mysql 的表数据是以页的形式存放的,页在磁盘中不一定是连续的。 + +页的空间是 16K, 并不是所有的空间都是用来存放数据的,会有一些固定的信息,如,页头,页尾,页码,校验码等等。在 B+ 树中,叶子节点和非叶子节点的数据结构是一样的,区别在于,叶子节点存放的是实际的行数据,而非叶子节点存放的是主键和页号。 + +索引结构不会影响单表最大行数,2kw 也只是推荐值,超过了这个值可能会导致 B + 树层级更高,影响查询性能。 + +## **9 参考** + +- *https://www.jianshu.com/p/cf5d381ef637* +- *https://www.modb.pro/db/139052* +- *《MYSQL 内核:INNODB 存储引擎 卷 1》* + +*来源:my.oschina.net/u/4090830/blog/5559454* \ No newline at end of file diff --git a/docs/advance/excellent-article/13-order-by-work.md b/docs/advance/excellent-article/13-order-by-work.md new file mode 100644 index 0000000..5c7b0ee --- /dev/null +++ b/docs/advance/excellent-article/13-order-by-work.md @@ -0,0 +1,263 @@ +# order by是怎么工作的? + +在你开发应用的时候,一定会经常碰到需要根据指定的字段排序来显示结果的需求。还是以我们前面举例用过的市民表为例,假设你要查询城市是“杭州”的所有人名字,并且按照姓名排序返回前 1000 个人的姓名、年龄。 + +假设这个表的部分定义是这样的: + +```r +CREATE TABLE `t` ( + `id` int(11) NOT NULL, + `city` varchar(16) NOT NULL, + `name` varchar(16) NOT NULL, + `age` int(11) NOT NULL, + `addr` varchar(128) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `city` (`city`) +) ENGINE=InnoDB; +``` + +这时,你的 SQL 语句可以这么写: + +```csharp +select city,name,age from t where city='杭州' order by name limit 1000 ; +``` + +这个语句看上去逻辑很清晰,但是你了解它的执行流程吗?今天,我就和你聊聊这个语句是怎么执行的,以及有什么参数会影响执行的行为。 + +# 全字段排序 + +前面我们介绍过索引,所以你现在就很清楚了,为避免全表扫描,我们需要在 city 字段加上索引。 + +在 city 字段上创建索引之后,我们用 explain 命令来看看这个语句的执行情况。 + +![img](https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/MySQL%E5%AE%9E%E6%88%9845%E8%AE%B2/assets/826579b63225def812330ef6c344a303.png) + +图 1 使用 explain 命令查看语句的执行情况 + +Extra 这个字段中的“Using filesort”表示的就是需要排序,MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer。 + +为了说明这个 SQL 查询语句的执行过程,我们先来看一下 city 这个索引的示意图。 + +![](http://img.dabin-coder.cn/image/order-by-1.png) + +图 2 city 字段的索引示意图 + +从图中可以看到,满足 city='杭州’条件的行,是从 ID_X 到 ID_(X+N) 的这些记录。 + +通常情况下,这个语句执行流程如下所示 : + +1. 初始化 sort_buffer,确定放入 name、city、age 这三个字段; +2. 从索引 city 找到第一个满足 city='杭州’条件的主键 id,也就是图中的 ID_X; +3. 到主键 id 索引取出整行,取 name、city、age 三个字段的值,存入 sort_buffer 中; +4. 从索引 city 取下一个记录的主键 id; +5. 重复步骤 3、4 直到 city 的值不满足查询条件为止,对应的主键 id 也就是图中的 ID_Y; +6. 对 sort_buffer 中的数据按照字段 name 做快速排序; +7. 按照排序结果取前 1000 行返回给客户端。 + +我们暂且把这个排序过程,称为全字段排序,执行流程的示意图如下所示,下一篇文章中我们还会用到这个排序。 + +![](http://img.dabin-coder.cn/image/order-by-10.png) + +图 3 全字段排序 + +图中“按 name 排序”这个动作,可能在内存中完成,也可能需要使用外部排序,这取决于排序所需的内存和参数 sort_buffer_size。 + +sort_buffer_size,就是 MySQL 为排序开辟的内存(sort_buffer)的大小。如果要排序的数据量小于 sort_buffer_size,排序就在内存中完成。但如果排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序。 + +你可以用下面介绍的方法,来确定一个排序语句是否使用了临时文件。 + +```sql +/* 打开 optimizer_trace,只对本线程有效 */ +SET optimizer_trace='enabled=on'; + +/* @a 保存 Innodb_rows_read 的初始值 */ +select VARIABLE_VALUE into @a from performance_schema.session_status where variable_name = 'Innodb_rows_read'; + +/* 执行语句 */ +select city, name,age from t where city='杭州' order by name limit 1000; + +/* 查看 OPTIMIZER_TRACE 输出 */ +SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G + +/* @b 保存 Innodb_rows_read 的当前值 */ +select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read'; + +/* 计算 Innodb_rows_read 差值 */ +select @b-@a; +``` + +这个方法是通过查看 OPTIMIZER_TRACE 的结果来确认的,你可以从 number_of_tmp_files 中看到是否使用了临时文件。 + +![](http://img.dabin-coder.cn/image/order-by-2.png) + +图 4 全排序的 OPTIMIZER_TRACE 部分结果 + +number_of_tmp_files 表示的是,排序过程中使用的临时文件数。你一定奇怪,为什么需要 12 个文件?内存放不下时,就需要使用外部排序,外部排序一般使用归并排序算法。可以这么简单理解,**MySQL 将需要排序的数据分成 12 份,每一份单独排序后存在这些临时文件中。然后把这 12 个有序文件再合并成一个有序的大文件。** + +如果 sort_buffer_size 超过了需要排序的数据量的大小,number_of_tmp_files 就是 0,表示排序可以直接在内存中完成。 + +否则就需要放在临时文件中排序。sort_buffer_size 越小,需要分成的份数越多,number_of_tmp_files 的值就越大。 + +接下来,我再和你解释一下图 4 中其他两个值的意思。 + +我们的示例表中有 4000 条满足 city='杭州’的记录,所以你可以看到 examined_rows=4000,表示参与排序的行数是 4000 行。 + +sort_mode 里面的 packed_additional_fields 的意思是,排序过程对字符串做了“紧凑”处理。即使 name 字段的定义是 varchar(16),在排序过程中还是要按照实际长度来分配空间的。 + +同时,最后一个查询语句 select @b-@a 的返回结果是 4000,表示整个执行过程只扫描了 4000 行。 + +这里需要注意的是,为了避免对结论造成干扰,我把 internal_tmp_disk_storage_engine 设置成 MyISAM。否则,select @b-@a 的结果会显示为 4001。 + +这是因为查询 OPTIMIZER_TRACE 这个表时,需要用到临时表,而 internal_tmp_disk_storage_engine 的默认值是 InnoDB。如果使用的是 InnoDB 引擎的话,把数据从临时表取出来的时候,会让 Innodb_rows_read 的值加 1。 + +# rowid 排序 + +在上面这个算法过程里面,只对原表的数据读了一遍,剩下的操作都是在 sort_buffer 和临时文件中执行的。但这个算法有一个问题,就是如果查询要返回的字段很多的话,那么 sort_buffer 里面要放的字段数太多,这样内存里能够同时放下的行数很少,要分成很多个临时文件,排序的性能会很差。 + +所以如果单行很大,这个方法效率不够好。 + +那么,**如果 MySQL 认为排序的单行长度太大会怎么做呢?** + +接下来,我来修改一个参数,让 MySQL 采用另外一种算法。 + +```java +SET max_length_for_sort_data = 16; +``` + +max_length_for_sort_data,是 MySQL 中专门控制用于排序的行数据的长度的一个参数。它的意思是,如果单行的长度超过这个值,MySQL 就认为单行太大,要换一个算法。 + +city、name、age 这三个字段的定义总长度是 36,我把 max_length_for_sort_data 设置为 16,我们再来看看计算过程有什么改变。 + +新的算法放入 sort_buffer 的字段,只有要排序的列(即 name 字段)和主键 id。 + +但这时,排序的结果就因为少了 city 和 age 字段的值,不能直接返回了,整个执行流程就变成如下所示的样子: + +1. 初始化 sort_buffer,确定放入两个字段,即 name 和 id; +2. 从索引 city 找到第一个满足 city='杭州’条件的主键 id,也就是图中的 ID_X; +3. 到主键 id 索引取出整行,取 name、id 这两个字段,存入 sort_buffer 中; +4. 从索引 city 取下一个记录的主键 id; +5. 重复步骤 3、4 直到不满足 city='杭州’条件为止,也就是图中的 ID_Y; +6. 对 sort_buffer 中的数据按照字段 name 进行排序; +7. 遍历排序结果,取前 1000 行,并按照 id 的值回到原表中取出 city、name 和 age 三个字段返回给客户端。 + +这个执行流程的示意图如下,我把它称为 rowid 排序。 + +![](http://img.dabin-coder.cn/image/order-by-23.png) + +图 5 rowid 排序 + +对比图 3 的全字段排序流程图你会发现,rowid 排序多访问了一次表 t 的主键索引,就是步骤 7。 + +需要说明的是,最后的“结果集”是一个逻辑概念,实际上 MySQL 服务端从排序后的 sort_buffer 中依次取出 id,然后到原表查到 city、name 和 age 这三个字段的结果,不需要在服务端再耗费内存存储结果,是直接返回给客户端的。 + +根据这个说明过程和图示,你可以想一下,这个时候执行 select @b-@a,结果会是多少呢? + +现在,我们就来看看结果有什么不同。 + +首先,图中的 examined_rows 的值还是 4000,表示用于排序的数据是 4000 行。但是 select @b-@a 这个语句的值变成 5000 了。 + +因为这时候除了排序过程外,在排序完成后,还要根据 id 去原表取值。由于语句是 limit 1000,因此会多读 1000 行。 + +![](http://img.dabin-coder.cn/image/order-by-4.png) + +图 6 rowid 排序的 OPTIMIZER_TRACE 部分输出 + +从 OPTIMIZER_TRACE 的结果中,你还能看到另外两个信息也变了。 + +- sort_mode 变成了 ,表示参与排序的只有 name 和 id 这两个字段。 +- number_of_tmp_files 变成 10 了,是因为这时候参与排序的行数虽然仍然是 4000 行,但是每一行都变小了,因此需要排序的总数据量就变小了,需要的临时文件也相应地变少了。 + +# 全字段排序 VS rowid 排序 + +我们来分析一下,从这两个执行流程里,还能得出什么结论。 + +如果 MySQL 实在是担心排序内存太小,会影响排序效率,才会采用 rowid 排序算法,这样排序过程中一次可以排序更多行,但是需要再回到原表去取数据。 + +如果 MySQL 认为内存足够大,会优先选择全字段排序,把需要的字段都放到 sort_buffer 中,这样排序后就会直接从内存里面返回查询结果了,不用再回到原表去取数据。 + +这也就体现了 MySQL 的一个设计思想:**如果内存够,就要多利用内存,尽量减少磁盘访问。** + +对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘读,因此不会被优先选择。 + +这个结论看上去有点废话的感觉,但是你要记住它,下一篇文章我们就会用到。 + +看到这里,你就了解了,MySQL 做排序是一个成本比较高的操作。那么你会问,是不是所有的 order by 都需要排序操作呢?如果不排序就能得到正确的结果,那对系统的消耗会小很多,语句的执行时间也会变得更短。 + +其实,并不是所有的 order by 语句,都需要排序操作的。从上面分析的执行过程,我们可以看到,MySQL 之所以需要生成临时表,并且在临时表上做排序操作,**其原因是原来的数据都是无序的。** + +你可以设想下,如果能够保证从 city 这个索引上取出来的行,天然就是按照 name 递增排序的话,是不是就可以不用再排序了呢? + +确实是这样的。 + +所以,我们可以在这个市民表上创建一个 city 和 name 的联合索引,对应的 SQL 语句是: + +```sql +alter table t add index city_user(city, name); +``` + +作为与 city 索引的对比,我们来看看这个索引的示意图。 + +![](http://img.dabin-coder.cn/image/order-by-5.png) + +图 7 city 和 name 联合索引示意图 + +在这个索引里面,我们依然可以用树搜索的方式定位到第一个满足 city='杭州’的记录,并且额外确保了,接下来按顺序取“下一条记录”的遍历过程中,只要 city 的值是杭州,name 的值就一定是有序的。 + +这样整个查询过程的流程就变成了: + +1. 从索引 (city,name) 找到第一个满足 city='杭州’条件的主键 id; +2. 到主键 id 索引取出整行,取 name、city、age 三个字段的值,作为结果集的一部分直接返回; +3. 从索引 (city,name) 取下一个记录主键 id; +4. 重复步骤 2、3,直到查到第 1000 条记录,或者是不满足 city='杭州’条件时循环结束。 + +![](http://img.dabin-coder.cn/image/order-by-9.png) + +图 8 引入 (city,name) 联合索引后,查询语句的执行计划 + +可以看到,这个查询过程不需要临时表,也不需要排序。接下来,我们用 explain 的结果来印证一下。 + +![](http://img.dabin-coder.cn/image/order-by-6.png) + +图 9 引入 (city,name) 联合索引后,查询语句的执行计划 + +从图中可以看到,Extra 字段中没有 Using filesort 了,也就是不需要排序了。而且由于 (city,name) 这个联合索引本身有序,所以这个查询也不用把 4000 行全都读一遍,只要找到满足条件的前 1000 条记录就可以退出了。也就是说,在我们这个例子里,只需要扫描 1000 次。 + +既然说到这里了,我们再往前讨论,**这个语句的执行流程有没有可能进一步简化呢?**不知道你还记不记得,我在第 5 篇文章[《 深入浅出索引(下)》]中,和你介绍的覆盖索引。 + +这里我们可以再稍微复习一下。**覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键索引上去取数据。** + +按照覆盖索引的概念,我们可以再优化一下这个查询语句的执行流程。 + +针对这个查询,我们可以创建一个 city、name 和 age 的联合索引,对应的 SQL 语句就是: + +```sql +alter table t add index city_user_age(city, name, age); +``` + +这时,对于 city 字段的值相同的行来说,还是按照 name 字段的值递增排序的,此时的查询语句也就不再需要排序了。这样整个查询语句的执行流程就变成了: + +1. 从索引 (city,name,age) 找到第一个满足 city='杭州’条件的记录,取出其中的 city、name 和 age 这三个字段的值,作为结果集的一部分直接返回; +2. 从索引 (city,name,age) 取下一个记录,同样取出这三个字段的值,作为结果集的一部分直接返回; +3. 重复执行步骤 2,直到查到第 1000 条记录,或者是不满足 city='杭州’条件时循环结束。 + +![](http://img.dabin-coder.cn/image/order-by-7.png) + +图 10 引入 (city,name,age) 联合索引后,查询语句的执行流程 + +然后,我们再来看看 explain 的结果。 + +![](http://img.dabin-coder.cn/image/order-by-8.png) + +图 11 引入 (city,name,age) 联合索引后,查询语句的执行计划 + +可以看到,Extra 字段里面多了“Using index”,表示的就是使用了覆盖索引,性能上会快很多。 + +当然,这里并不是说要为了每个查询能用上覆盖索引,就要把语句中涉及的字段都建上联合索引,毕竟索引还是有维护代价的。这是一个需要权衡的决定。 + +# 小结 + +今天这篇文章,我和你介绍了 MySQL 里面 order by 语句的几种算法流程。 + +在开发系统的时候,你总是不可避免地会使用到 order by 语句。你心里要清楚每个语句的排序逻辑是怎么实现的,还要能够分析出在最坏情况下,每个语句的执行对系统资源的消耗,这样才能做到下笔如有神,不犯低级错误。 + +> 内容摘录自丁奇的《MySQL45讲》 \ No newline at end of file diff --git a/docs/advance/excellent-article/14-architect-forward.md b/docs/advance/excellent-article/14-architect-forward.md new file mode 100644 index 0000000..f4ce67c --- /dev/null +++ b/docs/advance/excellent-article/14-architect-forward.md @@ -0,0 +1,49 @@ +### 传统单体应用架构 + +十多年前主流的应用架构都是单体应用,部署形式就是一台服务器加一个数据库,在这种架构下,运维人员会小心翼翼地维护这台服务器,以保证服务的可用性。 + +![](http://img.dabin-coder.cn/image/架构演进1.png) + +#### 单体应用架构面临的问题 + +随着业务的增长,这种最简单的单体应用架构很快就面临两个问题。首先,这里只有一台服务器,如果这台服务器出现故障,例如硬件损坏,那么整个服务就会不可用;其次,业务量变大之后,一台服务器的资源很快会无法承载所有流量。 + +解决这两个问题最直接的方法就是在流量入口加一个负载均衡器,使单体应用同时部署到多台服务器上,这样服务器的单点问题就解决了,与此同时,这个单体应用也具备了水平伸缩的能力。 + +![单体架构(水平伸缩)](http://img.dabin-coder.cn/image/架构演进2.png) + +### 微服务架构 + +#### 1. 微服务架构演进出通用服务 + +随着业务的进一步增长,更多的研发人员加入到团队中,共同在单体应用上开发特性。由于单体应用内的代码没有明确的物理边界,大家很快就会遇到各种冲突,需要人工协调,以及大量的 conflict merge 操作,研发效率直线下降。 + +因此大家开始把单体应用拆分成一个个可以独立开发、独立测试、独立部署的微服务应用,服务和服务之间通过 API 通讯,如 HTTP、GRPC 或者 DUBBO。基于领域驱动设计中 Bounded Context 拆分的微服务架构能够大幅提升中大型团队的研发效率。 + +#### 2. 微服务架构给运维带来挑战 + +应用从单体架构演进到微服务架构,从物理的角度看,分布式就成了默认选项,这时应用架构师就不得不面对分布式带来的新挑战。在这个过程中,大家都会开始使用一些分布式服务和框架,例如缓存服务 Redis,配置服务 ACM,状态协调服务 ZooKeeper,消息服务 Kafka,还有通讯框架如 GRPC 或者 DUBBO,以及分布式追踪系统等。 + +除分布式环境带来的挑战之外,微服务架构给运维也带来新挑战。研发人员原来只需要运维一个应用,现在可能需要运维十个甚至更多的应用,这意味着安全 patch 升级、容量评估、故障诊断等事务的工作量呈现成倍增长,这时,应用分发标准、生命周期标准、观测标准、自动化弹性等能力的重要性也更加凸显。 + +![](http://img.dabin-coder.cn/image/微服务架构.png) + +### 云原生 + +#### 1. 基于云产品架构 + +一个架构是否是云原生,就看这个架构是否是长在云上的,这是对“云原生”的简单理解。这个“长在云上”不是简单地说用云的 IaaS 层服务,比如简单的 ECS、OSS 这些基本的计算存储;而是应该理解成有没有使用云上的分布式服务,比如 Redis、Kafka 等,这些才是直接影响到业务架构的服务。微服务架构下,分布式服务是必要的,原来大家都是自己研发这样的服务,或者基于开源版本自己运维这样的服务。而到了云原生时代,业务则可以直接使用云服务。 + +另外两个不得不提的技术就是 Docker 和 Kubenetes,其中,前者标准化了应用分发的标准,不论是 Spring Boot 写的应用,还是 NodeJS 写的应用,都以镜像的方式分发;而后者在前者的技术上又定义了应用生命周期的标准,一个应用从启动到上线,到健康检查,再到下线,都有了统一的标准。 + +#### 2. 应用生命周期托管 + +有了应用分发的标准和生命周期的标准,云就能提供标准化的应用托管服务。包括应用的版本管理、发布、上线后的观测、自愈等。例如对于无状态的应用来说,一个底层物理节点的故障根本不会影响到研发,因为应用托管服务基于标准化应用生命周期可以自动完成腾挪工作,在故障物理节点上将应用的容器下线,在新的物理节点上启动同等数量的应用容器。可以看出,云原生进一步释放了价值红利。 + +在此基础上,由于应用托管服务能够感知到应用运行期的数据,例如业务流量的并发、cpu load、内存占用等,业务就可以配置基于这些指标的伸缩规则,再由平台执行这些规则,根据业务流量的实际情况增加或者减少容器数量,这就是最基本的 auto scaling——自动伸缩。这能够帮助用户避免在业务低峰期限制资源,节省成本,提升运维效率。 + +### 本文总结 + +在架构的演进过程中,研发运维人员逐渐把关注点从机器上移走,希望更多地由平台系统管理机器,而不是由人去管理,这就是一个对 Serverless 的朴素理解。 + +> 本文部分内容摘抄自网络 \ No newline at end of file diff --git a/docs/advance/excellent-article/15-http-vs-rpc.md b/docs/advance/excellent-article/15-http-vs-rpc.md new file mode 100644 index 0000000..4c1647b --- /dev/null +++ b/docs/advance/excellent-article/15-http-vs-rpc.md @@ -0,0 +1,265 @@ +> 原文链接:https://www.jianshu.com/p/9d42b926d40d + +## 既然有 HTTP 请求,为什么还要用 RPC 调用? + +一直以来都没有深究过RPC和HTTP的区别,不都是写一个服务然后在客户端调用么? + +HTTP和RPC最本质的区别,就是 **RPC 主要是基于 TCP/IP 协议的**,而 **HTTP 服务主要是基于 HTTP 协议的**。 + +我们都知道 HTTP 协议是在传输层协议 TCP 之上的,所以效率来看的话,RPC 当然是要更胜一筹啦! + +HTTP和RPC的相同点是,底层通讯都是基于socket,都可以实现远程调用,都可以实现服务调用服务 + +### HTTP 的本质 + +首先你要明确 HTTP 是一个协议,是一个超文本传输协议。 + +HTTP 它是协议,不是运输通道。 + +它基于 TCP/IP 来传输文本、图片、视频、音频等。 + +重点来了。 + +HTTP 不提供数据包的传输功能,也就是数据包从浏览器到服务端再来回的传输和它没关系。 + +这是 TCP/IP 干的。 + +那 HTTP 有啥用?我们来分析一波。 + +我们上网要么就是获取一些信息来看,要么就是修改一些信息。 + +比如你用浏览器刷微博就是获取信息,发微博就是修改信息。 + +所以说浏览器需要告知服务器它需要什么,这次的请求是要获取哪些信息?发怎么样的微博。 + +这就涉及到浏览器和服务器之间的通信交互。 + +而交互就需要一种格式。 + +像你我之间的谈话就用中文,你要突然换成俄语我听不懂那不就 GG 了。 + +所以说 HTTP 它规定了一种格式,一种通信格式,大家都用这个格式来交谈。 + +这样不论你是什么服务器、什么浏览器都能顺利的交流,减少交互的成本。 + +就像全世界如果都讲中文,那我们不就不需要学英文了,那不就较少交互的成本了。 + +不像现在我们还得学英文,不然就看不懂文档等等。 + +万一之后俄语又起来了,咱还得对接俄文,这交互成本是不是就上来了。 + +而网络世界还好,咱们现在的 Web 交互基本上就是 HTTP 了。 + +其实 HTTP 协议的格式很像我们信封,有个固定的格式。 + +![](http://img.dabin-coder.cn/image/http-rpc1.png) + +左上角写邮编,右上角贴邮票,然后地址姓名啥的依次来。 + +因为计算机是很死板的,不像我们人一样有一种立体扫描感,所以要规定先写头、再写尾。 + +你要是先写尾,再写头计算机就认不出来了。 + +所以 HTTP 就规定了请求先搞请求行、再搞请求报头、再搞请求体。 + +响应就状态行、响应报头、响应体。 + +![](http://img.dabin-coder.cn/image/http-rpc2.png) + +所以 HTTP 的本质是什么? + +**就是客户端和服务端约定好的一种通信格式。** + +### HTTP 和 RPC 的关系 + +HTTP 和 RPC 其实是两个维度的东西, HTTP 指的是通信协议。 + +而 RPC 则是远程调用,其对应的是本地调用。 + +RPC 的通信可以用 HTTP 协议,也可以自定义协议,是不做约束的。 + +像之前的单体时代,我们的 service 调用就是自己实现的方法,是本地进程内的调用。 + +``` +public User getUserById(Long id) { + return userDao.getUserById(id); // 这叫本地调用 + } +``` + +现在都是微服务了,根据业务模块做了不同的拆分,像用户的服务不用我这个小组负责,我这小组只要写订单服务就行了。 + +但是我们服务需要用到用户的信息,于是我们需要调用用户小组的服务,于是代码变成了以下这种 + +``` +public User getUserById(Long id) { + return userConsumer.getUserById(id); // 这是远程调用,逻辑是用户小组的服务实现的。 + } +``` + +可能还有些小伙伴不太清楚,再来看个图。 + +![](http://img.dabin-coder.cn/image/http-rpc3.png) + +把之前的用户实现拆分出来弄了一个用户服务,订单相关的也拆成了订单服务,都单独部署。 + +这样订单相关的服务要获取用户的信息就需要远程调用了。 + +可以看到 RPC 就是通过网络进行远程调用,订单服务其实就是客户端,而用户服务是服务端。 + +这又涉及到交互了,所以也需要约定一个格式,至于要不要用 HTTP 这个格式,就是大家自己看着办。 + +至此相信你对 HTTP 是啥也清楚了。 + +RPC 和 HTTP 的之间的关系也清楚了。 + +### 那为什么要有 RPC? + +可能你常听到什么什么之间是 RPC 调用的,那你有没有想过为什么要 RPC, 我们直接 WebClient HTTP 调用不行么? + +其实 RPC 调用是因为服务的拆分,或者本身公司内部的多个服务之间的通信。 + +服务的拆分独立部署,那服务间的调用就必然需要网络通信,用 WebClient 调用当然可行,但是比较麻烦。 + +我们想即使服务被拆分了但是使用起来还是和之前本地调用一样方便。 + +所以就出现了 RPC 框架,来屏蔽这些底层调用细节,使得我们编码上还是和之前本地调用相差不多。 + +并且 HTTP 协议比较的冗余,RPC 都是内部调用所以不需要太考虑通用性,只要公司内部保持格式统一即可。 + +所以可以做各种定制化的协议来使得通信更高效。 + +比如规定 yes 代表 yes的练级攻略,你看是不是更高效了,少传输的 5 个字。 + +就像特殊行动的暗号,高效简洁! + +所以公司内部服务的调用一般都用 RPC,而 HTTP 的优势在于通用,大家都认可这个协议。 + +所以三方平台提供的接口都是通过 HTTP 协议调用的。 + +所以现在知道为什么我们调用第三方都是 HTTP ,公司内部用 RPC 了吧? + +上面这段话看起来仿佛 HTTP 和 RPC 是对等关系,不过相信大家看了之前的解析心里应该都有数了。 + +下面来具体说一说 RPC 服务和 HTTP 服务的区别。 + +#### OSI 网络七层模型 + +在说 RPC 和 HTTP 的区别之前,我觉的有必要了解一下 OSI 的七层网络结构模型( + +![](http://img.dabin-coder.cn/image/http-rpc4.png) + +它可以分为以下几层:(从上到下) + +- **第一层:应用层。**定义了用于在网络中进行通信和传输数据的接口。 +- **第二层:表示层。**定义不同的系统中数据的传输格式,编码和解码规范等。 +- **第三层:会话层。**管理用户的会话,控制用户间逻辑连接的建立和中断。 +- **第四层:传输层。**管理着网络中的端到端的数据传输。 +- **第五层:网络层。**定义网络设备间如何传输数据。 +- **第六层:链路层。**将上面的网络层的数据包封装成数据帧,便于物理层传输。 +- **第七层:物理层。**这一层主要就是传输这些二进制数据。 + +![](http://img.dabin-coder.cn/image/http-rpc5.png) + +> **实际应用过程中,五层协议结构里面是没有表示层和会话层的。应该说它们和应用层合并了。** + +我们应该将重点放在应用层和传输层这两个层面。因为 HTTP 是应用层协议,而 TCP 是传输层协议。 + +好,知道了网络的分层模型以后我们可以更好地理解为什么 RPC 服务相比 HTTP 服务要 Nice 一些! + +### RPC 服务 + +从三个角度来介绍 RPC 服务,分别是: + +- **RPC 架构** +- **同步异步调用** +- **流行的 RPC 框架** + +**RPC 架构** + +先说说 RPC 服务的基本架构吧。我们可以很清楚地看到,一个完整的 RPC 架构里面包含了四个核心的组件。 + +分别是: + +- **Client** +- **Server** +- **Client Stub** +- **Server Stub(这个Stub大家可以理解为存根)** + +![](http://img.dabin-coder.cn/image/http-rpc6.png) + +分别说说这几个组件: + +- **客户端(Client),**服务的调用方。 +- **服务端(Server),**真正的服务提供者。 +- **客户端存根,**存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。微信搜索公众号:Linux技术迷,回复:linux 领取资料 。 +- 服务端存根,接收客户端发送过来的消息,将消息解包,并调用本地的方法。 + +RPC 主要是用在大型企业里面,因为大型企业里面系统繁多,业务线复杂,而且效率优势非常重要的一块,这个时候 RPC 的优势就比较明显了。 + +![](http://img.dabin-coder.cn/image/http-rpc7.png) + +比如我们有一个处理订单的系统服务,先声明它的所有的接口,然后将整个项目打包,服务端这边引入,然后实现相应的功能,客户端这边也只需要引入就可以调用了。 + +为什么这么做? + +主要是为了减少客户端这边的包大小,因为每一次打包发布的时候,包太多总是会影响效率。 + +另外也是将客户端和服务端解耦,提高代码的可移植性。 + +**同步调用与异步调用** + +什么是同步调用?什么是异步调用? + +同步调用就是客户端等待调用执行完成并返回结果。 + +异步调用就是客户端不等待调用执行完成返回结果,不过依然可以通过回调函数等接收到返回结果的通知。如果客户端并不关心结果,则可以变成一个单向的调用。 + +#### 流行的 RPC 框架 + +目前流行的开源 RPC 框架还是比较多的。下面重点介绍三种: + +**①gRPC** 是 Google 最近公布的开源软件,基于最新的 HTTP2.0 协议,并支持常见的众多编程语言。 + +我们知道 HTTP2.0 是基于二进制的 HTTP 协议升级版本,目前各大浏览器都在快马加鞭的加以支持。 + +这个 RPC 框架是基于 HTTP 协议实现的,底层使用到了 Netty 框架的支持。 + +**②Thrift** 是 Facebook 的一个开源项目,主要是一个跨语言的服务开发框架。它有一个代码生成器来对它所定义的 IDL 定义文件自动生成服务代码框架。 + +用户只要在其之前进行二次开发就行,对于底层的 RPC 通讯等都是透明的。不过这个对于用户来说的话需要学习特定领域语言这个特性,还是有一定成本的。 + +**③Dubbo** 是阿里集团开源的一个极为出名的 RPC 框架,在很多互联网公司和企业应用中广泛使用。协议和序列化框架都可以插拔是及其鲜明的特色。 + +### HTTP 服务 + +通常,我们的开发模式一直定性为 HTTP 接口开发,也就是我们常说的 RESTful 风格的服务接口。 + +的确,对于在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。 + +利用现成的 HTTP 协议进行传输。 + +平时的工作主要就是进行接口的开发,还要写一大份接口文档,严格地标明输入输出是什么?说清楚每一个接口的请求方法,以及请求参数需要注意的事项等。 + +![](http://img.dabin-coder.cn/image/http-rpc8.png) + +比如下面这个例子: + +``` +POST http://www.httpexample.com/restful/buyer/info/shar +``` + +接口可能返回一个 JSON 字符串或者是 XML 文档。然后客户端再去处理这个返回的信息,从而可以比较快速地进行开发。 + +但是对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC 框架的好处就显示出来了,首先就是长链接,不必每次通信都要像 HTTP 一样去 3 次握手什么的,减少了网络开销。 + +其次就是 RPC 框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。 + +### 小结 + +RPC 服务和 HTTP 服务还是存在很多的不同点的,一般来说,RPC 服务主要是针对大型企业的,而 HTTP 服务主要是针对小企业的,因为 RPC 效率更高,而 HTTP 服务开发迭代会更快。 + +很多RPC框架包含了重试机制,路由策略,负载均衡策略,高可用策略,流量控制策略等等。如果应用进程之间只使用HTTP协议通信,显然是无法完成上述功能的。 + +总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。 + +一定不要为了使用 RPC 而每个项目都用 RPC,而是要因地制宜,具体情况具体分析。 \ No newline at end of file diff --git a/docs/advance/excellent-article/16-what-is-jwt.md b/docs/advance/excellent-article/16-what-is-jwt.md new file mode 100644 index 0000000..2f317c0 --- /dev/null +++ b/docs/advance/excellent-article/16-what-is-jwt.md @@ -0,0 +1,167 @@ +JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。 + +## 传统的session认证 + +http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。 + +这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来. + +#### 基于session认证所显露的问题 + +**Session**: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。 + +**扩展性**: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。 + +**CSRF**: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。 + +## 基于token的鉴权机制 + +基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。 + +流程上是这样的: + +- 用户使用用户名密码来请求服务器 +- 服务器进行验证用户的信息 +- 服务器通过验证发送给用户一个token +- 客户端存储token,并在每次请求时附送上这个token值 +- 服务端验证token值,并返回数据 + +这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持`CORS(跨来源资源共享)`策略,一般我们在服务端这么做就可以了`Access-Control-Allow-Origin: *`。 + +## JWT长什么样? + +JWT是由三段信息构成的,将这三段信息文本用`.`链接一起就构成了Jwt字符串。就像这样: + +```css +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW +``` + +## JWT的构成 + +第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature). + +### header + +jwt的头部承载两部分信息: + +- 声明类型,这里是jwt +- 声明加密的算法 通常直接使用 HMAC SHA256 + +完整的头部就像下面这样的JSON: + +```bash +{ + 'typ': 'JWT', + 'alg': 'HS256' +} +``` + +然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分. + +```undefined +eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 +``` + +### playload + +载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分 + +- 标准中注册的声明 +- 公共的声明 +- 私有的声明 + +**标准中注册的声明** (建议但不强制使用) : + +- **iss**: jwt签发者 +- **sub**: jwt所面向的用户 +- **aud**: 接收jwt的一方 +- **exp**: jwt的过期时间,这个过期时间必须要大于签发时间 +- **nbf**: 定义在什么时间之前,该jwt都是不可用的. +- **iat**: jwt的签发时间 +- **jti**: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。 + +**公共的声明** : + 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密. + +**私有的声明** : + 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。 + +定义一个payload: + +```json +{ + "sub": "1234567890", + "name": "John Doe", + "admin": true +} +``` + +然后将其进行base64加密,得到Jwt的第二部分。 + +```undefined +eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 +``` + +### signature + +jwt的第三部分是一个签证信息,这个签证信息由三部分组成: + +- header (base64后的) +- payload (base64后的) +- secret + +这个部分需要base64加密后的header和base64加密后的payload使用`.`连接组成的字符串,然后通过header中声明的加密方式进行加盐`secret`组合加密,然后就构成了jwt的第三部分。 + +```csharp +// javascript +var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); + +var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ +``` + +将这三部分用`.`连接成一个完整的字符串,构成了最终的jwt: + +```css + eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ +``` + +**注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。** + +### 如何应用 + +一般是在请求头里加入`Authorization`,并加上`Bearer`标注: + +```bash +fetch('api/user/1', { + headers: { + 'Authorization': 'Bearer ' + token + } +}) +``` + +服务端会验证token,如果验证通过就会返回相应的资源。整个流程就是这样的: + +![](http://img.dabin-coder.cn/image/jwt.png) + +## 总结 + +### 优点 + +- 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。 +- 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。 +- 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。 +- 它不需要在服务端保存会话信息, 所以它易于应用的扩展 + +### 安全相关 + +- 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。 +- 保护好secret私钥,该私钥非常重要。 +- 如果可以,请使用https协议 + + + +## 参考链接 + +- [什么是 JWT](https://www.jianshu.com/p/576dbf44b2ae) + +- [JSON Web Token 入门教程](https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html) \ No newline at end of file diff --git a/docs/advance/excellent-article/2-spring-transaction.md b/docs/advance/excellent-article/2-spring-transaction.md new file mode 100644 index 0000000..d9fcf4f --- /dev/null +++ b/docs/advance/excellent-article/2-spring-transaction.md @@ -0,0 +1,111 @@ +# @Transactional 事务注解详解 + +## Spring事务的传播行为 + +**先简单介绍一下Spring事务的传播行为:** + +所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在`TransactionDefinition`定义中括了如下几个表示传播行为的常量: + +- `TransactionDefinition.PROPAGATION_REQUIRED`:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 +- `TransactionDefinition.PROPAGATION_REQUIRES_NEW`:创建一个新的事务,如果当前存在事务,则把当前事务挂起。 +- `TransactionDefinition.PROPAGATION_SUPPORTS`:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 +- `TransactionDefinition.PROPAGATION_NOT_SUPPORTED`:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 +- `TransactionDefinition.PROPAGATION_NEVER`:以非事务方式运行,如果当前存在事务,则抛出异常。 +- `TransactionDefinition.PROPAGATION_MANDATORY`:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 +- `TransactionDefinition.PROPAGATION_NESTED`:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于`TransactionDefinition.PROPAGATION_REQUIRED`。‍ + +## Spring事务的回滚机制 + +**然后说一下Spring事务的回滚机制:** + +Spring的AOP即声明式事务管理默认是针对`unchecked exception`回滚。Spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行`commit or rollback`(Spring默认取决于是否抛出`runtimeException`)。 + +如果你在方法中有`try{}catch(Exception e){}`处理,那么try里面的代码块就脱离了事务的管理,若要事务生效需要在catch中`throw new RuntimeException ("xxxxxx");`这一点也是面试中会问到的事务失效的场景。 + +## @Transactional注解实现原理 + +再简单介绍一下`@Transactional`注解底层实现方式吧,毫无疑问,是通过动态代理,那么动态代理又分为JDK自身和CGLIB,这个也不多赘述了,毕竟今天的主题是如何将`@Transactional`对于事物的控制应用到炉火纯青。哈哈~ + +第一点要注意的就是在`@Transactional`注解的方法中,再调用本类中的其他方法method2时,那么method2方法上的`@Transactional`注解是不!会!生!效!的!但是加上也并不会报错,拿图片简单帮助理解一下吧。这一点也是面试中会问到的事务失效的场景。 + +![](http://img.dabin-coder.cn/image/spring事务1.png) + +通过代理对象在目标对象前后进行方法增强,也就是事务的开启提交和回滚。那么继续调用本类中其他方法是怎样呢,如下图: + +![](http://img.dabin-coder.cn/image/spring事务2.png) + +可见目标对象内部的自我调用,也就是通过this.指向的目标对象将不会执行方法的增强。 + +先说第二点需要注意的地方,等下说如何解决上面第一点的问题。第二点就是`@Transactional`注解的方法必须是公共方法,就是必须是public修饰符!!! + +至于这个的原因,发表下个人的理解吧,因为JVM的动态代理是基于接口实现的,通过代理类将目标方法进行增强,想一下也是啦,没有权限访问那么你让我怎么进行,,,好吧,这个我也没有深入研究底层,个人理解个人理解。 + +在这里我也放个问题吧,希望有高手可以回复指点指点我,因为JVM动态代理是基于接口实现的,那么是不是service层都要按照接口和实现类的开发模式,注解才会生效呢,就是说`controller`层直接调用没有接口的service层,加了注解也一样不起作用吧,这个懒了,没有测试,其一是因为没有人会这么开发吧,其二是我就认为是不起作用的,哈哈。 + +**下面来解决一下第一点的问题,如何在方法中调用本类中其他方法呢。** + +通过`AopContext.currentProxy ()`获取到本类的代理对象,再去调用就好啦。因为这个是CGLIB实现,所以要开启AOP,当然也很简单,在springboot启动类上加上注解`@EnableAspectJAutoProxy(exposeProxy = true)`就可以啦,这个依赖大家自行搜一下就好啦。要注意,注意,代理对象调用的方法也要是public修饰符,否则方法中获取不到注入的bean,会报空指针错误。 + +emmmm,我先把调用的方式和结果说下吧。自己简单写了代码,有点粗糙,就不要介意啦,嘿嘿。。。 + +Controller中调用Service + +``` +@RestController +public class TransactionalController { + + @Autowired + private TransactionalService transactionalService; + + @PostMapping("transactionalTest") + public void transacionalTest(){ + transactionalService.transactionalMethod(); + } +} +``` + +Service中实现对事务的控制:接口 + +``` +public interface TransactionalService { + void transactionalMethod(); +} +``` + +Service中实现对事务的控制:实现类(各种情况的说明都写在图片里了,这样方便阅读,有助于快速理解吧) + +![](http://img.dabin-coder.cn/image/spring事务3.png) + +![](http://img.dabin-coder.cn/image/spring事务4.png) + +上面两种情况不管使不使用代理调用方法1和方法2,方法`transactionalMethod`都处在一个事务中,四条更新操作全部失败。 + +那么有人可能会有疑问了,在方法1和方法2上都加`@Transactional`注解呢?答案是结果和上面是一致的。 + +小结只要方法`transactionalMethod`上有注解,并且方法1和方法2都处于当前事务中(不使用代理调用,方法1和方法2上的`@Transactional`注解是不生效的;使用代理,需要方法1和方法2都处在`transactionalMethod`方法的事务中,默认或者嵌套事务均可,当然也可以不加`@Transactional`注解),那么整体保持事务一致性。 + +如果想要方法1和方法2均单独保持事务一致性怎么办呢,刚说过了,如果不是用代理调用`@Transactional`注解是不生效的,所以一定要使用代理调用实现,然后让方法1和方法2分别单独开启新的事务,便OK啦。下面摆上图片。 + +![](http://img.dabin-coder.cn/image/spring事务5.png) + +![](http://img.dabin-coder.cn/image/spring事务6.png) + +这两种情况都是方法1和方法2均处在单独的事务中,各自保持事务的一致性。 + +接下来进行进一步的优化,可以在`transactionalMethod`方法中分别对方法1和方法2进行控制。要将代码的艺术发挥到极致嘛,下面装逼开始。 + +![](http://img.dabin-coder.cn/image/spring事务7.png) + +代码太长了,超过屏幕了,粘贴出来截的图,红框注释需要仔细看,希望不要影响你的阅读体验,至此,本篇关于`@Transactioinal`注解的使用就到此为止啦, + +简单总结一下吧: + +1、就是`@Transactional`注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。 + +2、方法必须是public修饰符。否则注解不会生效,但是加了注解也没啥毛病,不会报错,只是没卵用而已。 + +3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强。 + + + +> 原文:blog.csdn.net/fanxb92/article/details/81296005 \ No newline at end of file diff --git a/docs/advance/excellent-article/3-springboot-auto-assembly.md b/docs/advance/excellent-article/3-springboot-auto-assembly.md new file mode 100644 index 0000000..c8eb437 --- /dev/null +++ b/docs/advance/excellent-article/3-springboot-auto-assembly.md @@ -0,0 +1,544 @@ +# Spring Boot 自动装配原理 + +首先,先看SpringBoot的主配置类: + +``` +@SpringBootApplication +public class StartEurekaApplication +{ + public static void main(String[] args) + { + SpringApplication.run(StartEurekaApplication.class, args); + } +} +``` + +点进@SpringBootApplication来看,发现@SpringBootApplication是一个组合注解。 + +``` +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@SpringBootConfiguration +@EnableAutoConfiguration +@ComponentScan(excludeFilters = { + @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), + @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) +public @interface SpringBootApplication { + +} +``` + +首先我们先来看 @SpringBootConfiguration: + +``` +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Configuration +public @interface SpringBootConfiguration { +} +``` + +可以看到这个注解除了元注解以外,就只有一个@Configuration,那也就是说这个注解相当于@Configuration,所以这两个注解作用是一样的,它让我们能够去注册一些额外的Bean,并且导入一些额外的配置。 + +那@Configuration还有一个作用就是把该类变成一个配置类,不需要额外的XML进行配置。所以@SpringBootConfiguration就相当于@Configuration。进入@Configuration,发现@Configuration核心是@Component,说明Spring的配置类也是Spring的一个组件。 + +``` +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface Configuration { + @AliasFor( + annotation = Component.class + ) + String value() default ""; +} +``` + +继续来看下一个@EnableAutoConfiguration,这个注解是开启自动配置的功能。 + +``` +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@AutoConfigurationPackage +@Import({AutoConfigurationImportSelector.class}) +public @interface EnableAutoConfiguration { + String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; + + Class[] exclude() default {}; + + String[] excludeName() default {}; +} +``` + +可以看到它是由 @AutoConfigurationPackage,@Import(EnableAutoConfigurationImportSelector.class)这两个而组成的,我们先说@AutoConfigurationPackage,他是说:让包中的类以及子包中的类能够被自动扫描到spring容器中。 + +``` +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import({Registrar.class}) +public @interface AutoConfigurationPackage { +} +``` + +使用@Import来给Spring容器中导入一个组件 ,这里导入的是Registrar.class。来看下这个Registrar: + +``` +static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { + Registrar() { + } + + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { + AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()); + } + + public Set determineImports(AnnotationMetadata metadata) { + return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata)); + } + } +``` + +就是通过以上这个方法获取扫描的包路径,可以debug查看具体的值: + +![](http://img.dabin-coder.cn/image/springboot自动配置1.png)那metadata是什么呢,可以看到是标注在@SpringBootApplication注解上的DemosbApplication,也就是我们的主配置类Application: + +![](http://img.dabin-coder.cn/image/springboot自动配置2.png)其实就是将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器。因此我们要把DemoApplication放在项目的最高级中(最外层目录)。 + +看看注解@Import(AutoConfigurationImportSelector.class),@Import注解就是给Spring容器中导入一些组件,这里传入了一个组件的选择器:AutoConfigurationImportSelector。 + +![](http://img.dabin-coder.cn/image/springboot自动配置3.png)可以从图中看出AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector,ImportSelector有一个方法为:selectImports。将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。 + +``` +public String[] selectImports(AnnotationMetadata annotationMetadata) { + if (!this.isEnabled(annotationMetadata)) { + return NO_IMPORTS; + } else { + AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); + AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = + this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); + return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); + } +} +``` + +会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件。 + +![](http://img.dabin-coder.cn/image/springboot自动配置4.png)有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。那是如何获取到这些配置类的呢,看看下面这个方法: + +``` +protected AutoConfigurationImportSelector.AutoConfigurationEntry + getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { + if (!this.isEnabled(annotationMetadata)) { + return EMPTY_ENTRY; + } else { + AnnotationAttributes attributes = this.getAttributes(annotationMetadata); + List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); + configurations = this.removeDuplicates(configurations); + Set exclusions = this.getExclusions(annotationMetadata, attributes); + this.checkExcludedClasses(configurations, exclusions); + configurations.removeAll(exclusions); + configurations = this.filter(configurations, autoConfigurationMetadata); + this.fireAutoConfigurationImportEvents(configurations, exclusions); + return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); + } +} +``` + +我们可以看到getCandidateConfigurations()这个方法,他的作用就是引入系统已经加载好的一些类,到底是那些类呢: + +``` +protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { + List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); + Assert.notEmpty(configurations, + "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); + return configurations; +} +public static List loadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader) { + String factoryClassName = factoryClass.getName(); + return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); +} +``` + +会从META-INF/spring.factories中获取资源,然后通过Properties加载资源: + +``` +private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { + MultiValueMap result = (MultiValueMap)cache.get(classLoader); + if (result != null) { + return result; + } else { + try { + Enumeration urls = classLoader != + null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); + LinkedMultiValueMap result = new LinkedMultiValueMap(); + + while(urls.hasMoreElements()) { + URL url = (URL)urls.nextElement(); + UrlResource resource = new UrlResource(url); + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + Iterator var6 = properties.entrySet().iterator(); + + while(var6.hasNext()) { + Map.Entry entry = (Map.Entry)var6.next(); + String factoryClassName = ((String)entry.getKey()).trim(); + String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); + int var10 = var9.length; + + for(int var11 = 0; var11 < var10; ++var11) { + String factoryName = var9[var11]; + result.add(factoryClassName, factoryName.trim()); + } + } + } + + cache.put(classLoader, result); + return result; + } catch (IOException var13) { + throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); + } + } +} +``` + +可以知道SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置类都帮我们完成了。如下图可以发现Spring常见的一些类已经自动导入。 + +![](http://img.dabin-coder.cn/image/springboot自动配置5.png)接下来看@ComponentScan注解,@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }),这个注解就是扫描包,然后放入spring容器。 + +``` +@ComponentScan(excludeFilters = { + @Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}), + @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})}) +public @interface SpringBootApplication {} +``` + +总结下@SpringbootApplication:就是说,他已经把很多东西准备好,具体是否使用取决于我们的程序或者说配置。 + +接下来继续看run方法: + +``` +public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +``` + +来看下在执行run方法到底有没有用到哪些自动配置的东西,我们点进run: + +``` +public ConfigurableApplicationContext run(String... args) { + //计时器 + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + ConfigurableApplicationContext context = null; + Collection exceptionReporters = new ArrayList(); + this.configureHeadlessProperty(); + //监听器 + SpringApplicationRunListeners listeners = this.getRunListeners(args); + listeners.starting(); + + Collection exceptionReporters; + try { + ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); + ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); + this.configureIgnoreBeanInfo(environment); + Banner printedBanner = this.printBanner(environment); + //准备上下文 + context = this.createApplicationContext(); + exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); + //预刷新context + this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); + //刷新context + this.refreshContext(context); + //刷新之后的context + this.afterRefresh(context, applicationArguments); + stopWatch.stop(); + if (this.logStartupInfo) { + (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); + } + + listeners.started(context); + this.callRunners(context, applicationArguments); + } catch (Throwable var10) { + this.handleRunFailure(context, var10, exceptionReporters, listeners); + throw new IllegalStateException(var10); + } + + try { + listeners.running(context); + return context; + } catch (Throwable var9) { + this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); + throw new IllegalStateException(var9); + } +} +``` + +那我们关注的就是 refreshContext(context); 刷新context,我们点进来看。 + +``` +private void refreshContext(ConfigurableApplicationContext context) { + refresh(context); + if (this.registerShutdownHook) { + try { + context.registerShutdownHook(); + } + catch (AccessControlException ex) { + // Not allowed in some environments. + } + } +} +``` + +我们继续点进refresh(context); + +``` +protected void refresh(ApplicationContext applicationContext) { + Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); + ((AbstractApplicationContext) applicationContext).refresh(); +} +``` + +他会调用 ((AbstractApplicationContext) applicationContext).refresh();方法,我们点进来看: + +``` +public void refresh() throws BeansException, IllegalStateException { + synchronized (this.startupShutdownMonitor) { + // Prepare this context for refreshing. + prepareRefresh(); + // Tell the subclass to refresh the internal bean factory. + ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); + // Prepare the bean factory for use in this context. + prepareBeanFactory(beanFactory); + + try { + // Allows post-processing of the bean factory in context subclasses. + postProcessBeanFactory(beanFactory); + // Invoke factory processors registered as beans in the context. + invokeBeanFactoryPostProcessors(beanFactory); + // Register bean processors that intercept bean creation. + registerBeanPostProcessors(beanFactory); + // Initialize message source for this context. + initMessageSource(); + // Initialize event multicaster for this context. + initApplicationEventMulticaster(); + // Initialize other special beans in specific context subclasses. + onRefresh(); + // Check for listener beans and register them. + registerListeners(); + // Instantiate all remaining (non-lazy-init) singletons. + finishBeanFactoryInitialization(beanFactory); + // Last step: publish corresponding event. + finishRefresh(); + }catch (BeansException ex) { + if (logger.isWarnEnabled()) { + logger.warn("Exception encountered during context initialization - " + + "cancelling refresh attempt: " + ex); + } + // Destroy already created singletons to avoid dangling resources. + destroyBeans(); + // Reset 'active' flag. + cancelRefresh(ex); + // Propagate exception to caller. + throw ex; + }finally { + // Reset common introspection caches in Spring's core, since we + // might not ever need metadata for singleton beans anymore... + resetCommonCaches(); + } + } +} +``` + +由此可知,就是一个spring的bean的加载过程。继续来看一个方法叫做 onRefresh(): + +``` +protected void onRefresh() throws BeansException { + // For subclasses: do nothing by default. +} +``` + +他在这里并没有直接实现,但是我们找他的具体实现: + +![](http://img.dabin-coder.cn/image/springboot自动配置6.png)比如Tomcat跟web有关,我们可以看到有个ServletWebServerApplicationContext: + +``` +@Override +protected void onRefresh() { + super.onRefresh(); + try { + createWebServer(); + } + catch (Throwable ex) { + throw new ApplicationContextException("Unable to start web server", ex); + } +} +``` + +可以看到有一个createWebServer();方法他是创建web容器的,而Tomcat不就是web容器,那是如何创建的呢,我们继续看: + +``` +private void createWebServer() { + WebServer webServer = this.webServer; + ServletContext servletContext = getServletContext(); + if (webServer == null && servletContext == null) { + ServletWebServerFactory factory = getWebServerFactory(); + this.webServer = factory.getWebServer(getSelfInitializer()); + } + else if (servletContext != null) { + try { + getSelfInitializer().onStartup(servletContext); + } + catch (ServletException ex) { + throw new ApplicationContextException("Cannot initialize servlet context", + ex); + } + } + initPropertySources(); +} +``` + +factory.getWebServer(getSelfInitializer());他是通过工厂的方式创建的。 + +``` +public interface ServletWebServerFactory { + WebServer getWebServer(ServletContextInitializer... initializers); +} +``` + +可以看到 它是一个接口,为什么会是接口。因为我们不止是Tomcat一种web容器。 + +![](http://img.dabin-coder.cn/image/springboot自动配置7.png) + +我们看到还有Jetty,那我们来看TomcatServletWebServerFactory: + +``` +@Override +public WebServer getWebServer(ServletContextInitializer... initializers) { + Tomcat tomcat = new Tomcat(); + File baseDir = (this.baseDirectory != null) ? this.baseDirectory + : createTempDir("tomcat"); + tomcat.setBaseDir(baseDir.getAbsolutePath()); + Connector connector = new Connector(this.protocol); + tomcat.getService().addConnector(connector); + customizeConnector(connector); + tomcat.setConnector(connector); + tomcat.getHost().setAutoDeploy(false); + configureEngine(tomcat.getEngine()); + for (Connector additionalConnector : this.additionalTomcatConnectors) { + tomcat.getService().addConnector(additionalConnector); + } + prepareContext(tomcat.getHost(), initializers); + return getTomcatWebServer(tomcat); +} +``` + +那这块代码,就是我们要寻找的内置Tomcat,在这个过程当中,我们可以看到创建Tomcat的一个流程。 + +如果不明白的话, 我们在用另一种方式来理解下,大家要应该都知道stater举点例子。 + +``` + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-freemarker + +``` + +首先自定义一个stater。 + +``` + + org.springframework.boot + spring-boot-starter-parent + 2.1.4.RELEASE + + +com.zgw +gw-spring-boot-starter +1.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-autoconfigure + + +``` + +我们先来看maven配置写入版本号,如果自定义一个stater的话必须依赖spring-boot-autoconfigure这个包,我们先看下项目目录。 + +![](http://img.dabin-coder.cn/image/springboot自动配置8.png)img + +``` +public class GwServiceImpl implements GwService{ + @Autowired + GwProperties properties; + + @Override + public void Hello() + { + String name=properties.getName(); + System.out.println(name+"说:你们好啊"); + } +} +``` + +我们做的就是通过配置文件来定制name这个是具体实现。 + +``` +@Component +@ConfigurationProperties(prefix = "spring.gwname") +public class GwProperties { + + String name="zgw"; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} +``` + +这个类可以通过@ConfigurationProperties读取配置文件。 + +``` +@Configuration +@ConditionalOnClass(GwService.class) //扫描类 +@EnableConfigurationProperties(GwProperties.class) //让配置类生效 +public class GwAutoConfiguration { + + /** + * 功能描述 托管给spring + * @author zgw + * @return + */ + @Bean + @ConditionalOnMissingBean + public GwService gwService() + { + return new GwServiceImpl(); + } +} +``` + +这个为配置类,为什么这么写因为,spring-boot的stater都是这么写的,我们可以参照他仿写stater,以达到自动配置的目的,然后我们在通过spring.factories也来进行配置。 + +``` +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.gw.GwAutoConfiguration +``` + +然后这样一个简单的stater就完成了,然后可以进行maven的打包,在其他项目引入就可以使用。 + +> 来源:cnblogs.com/jing99/p/11504113.html \ No newline at end of file diff --git a/docs/advance/excellent-article/4-remove-duplicate-code.md b/docs/advance/excellent-article/4-remove-duplicate-code.md new file mode 100644 index 0000000..8408294 --- /dev/null +++ b/docs/advance/excellent-article/4-remove-duplicate-code.md @@ -0,0 +1,595 @@ +# 干掉 “重复代码” 的技巧有哪些 + +软件工程师和码农最大的区别就是平时写代码时习惯问题,码农很喜欢写重复代码而软件工程师会利用各种技巧去干掉重复的冗余代码。 + +业务同学抱怨业务开发没有技术含量,用不到**设计模式**、**Java 高级特性**、**OOP**,平时写代码都在堆 **CRUD**,个人成长无从谈起。 + +其实,我认为不是这样的。设计模式、OOP 是前辈们在大型项目中积累下来的经验,通过这些方法论来改善大型项目的可维护性。反射、注解、泛型等高级特性在框架中大量使用的原因是,框架往往需要以同一套算法来应对不同的数据结构,而这些特性可以帮助减少重复代码,提升项目可维护性。 + +在我看来,可维护性是大型项目成熟度的一个重要指标,而提升可维护性非常重要的一个手段就是减少代码重复。那为什么这样说呢? + +- 如果多处重复代码实现完全相同的功能,很容易修改一处忘记修改另一处,造成 Bug +- 有一些代码并不是完全重复,而是相似度很高,修改这些类似的代码容易改(复制粘贴)错,把原本有区别的地方改为了一样。 + +今天,我就从业务代码中最常见的三个需求展开,聊聊如何使用 Java 中的一些高级特性、设计模式,以及一些工具消除重复代码,才能既优雅又高端。通过今天的学习,也希望改变你对业务代码没有技术含量的看法。 + +## 1. 利用工厂模式 + 模板方法模式,消除 if…else 和重复代码 + +假设要开发一个购物车下单的功能,针对不同用户进行不同处理: + +- 普通用户需要收取运费,运费是商品价格的 10%,无商品折扣; +- VIP 用户同样需要收取商品价格 10% 的快递费,但购买两件以上相同商品时,第三件开始享受一定折扣; +- 内部用户可以免运费,无商品折扣。 + +我们的目标是实现三种类型的购物车业务逻辑,把入参 Map 对象(Key 是商品 ID,Value 是商品数量),转换为出参购物车类型 Cart。 + +先实现针对普通用户的购物车处理逻辑: + +``` +//购物车 +@Data +public class Cart { + //商品清单 + private List items = new ArrayList<>(); + //总优惠 + private BigDecimal totalDiscount; + //商品总价 + private BigDecimal totalItemPrice; + //总运费 + private BigDecimal totalDeliveryPrice; + //应付总价 + private BigDecimal payPrice; +} +//购物车中的商品 +@Data +public class Item { + //商品ID + private long id; + //商品数量 + private int quantity; + //商品单价 + private BigDecimal price; + //商品优惠 + private BigDecimal couponPrice; + //商品运费 + private BigDecimal deliveryPrice; +} +//普通用户购物车处理 +public class NormalUserCart { + public Cart process(long userId, Map items) { + Cart cart = new Cart(); + + //把Map的购物车转换为Item列表 + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + + //处理运费和商品优惠 + itemList.stream().forEach(item -> { + //运费为商品总价的10% + item.setDeliveryPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())).multiply(new BigDecimal("0.1"))); + //无优惠 + item.setCouponPrice(BigDecimal.ZERO); + }); + + //计算商品总价 + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算运费总价 + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算总优惠 + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //应付总价=商品总价+运费总价-总优惠 + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } +} +``` + +然后实现针对 VIP 用户的购物车逻辑。与普通用户购物车逻辑的不同在于,VIP 用户能享受同类商品多买的折扣。所以,这部分代码只需要额外处理多买折扣部分: + +``` +public class VipUserCart { + + + public Cart process(long userId, Map items) { + ... + + + itemList.stream().forEach(item -> { + //运费为商品总价的10% + item.setDeliveryPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())).multiply(new BigDecimal("0.1"))); + //购买两件以上相同商品,第三件开始享受一定折扣 + if (item.getQuantity() > 2) { + item.setCouponPrice(item.getPrice() + .multiply(BigDecimal.valueOf(100 - Db.getUserCouponPercent(userId)).divide(new BigDecimal("100"))) + .multiply(BigDecimal.valueOf(item.getQuantity() - 2))); + } else { + item.setCouponPrice(BigDecimal.ZERO); + } + }); + + + ... + return cart; + } +} +``` + +最后是免运费、无折扣的内部用户,同样只是处理商品折扣和运费时的逻辑差异: + +``` +public class InternalUserCart { + + + public Cart process(long userId, Map items) { + ... + + itemList.stream().forEach(item -> { + //免运费 + item.setDeliveryPrice(BigDecimal.ZERO); + //无优惠 + item.setCouponPrice(BigDecimal.ZERO); + }); + + ... + return cart; + } +} +``` + +对比一下代码量可以发现,三种购物车 **70%** 的代码是重复的。原因很简单,虽然不同类型用户计算运费和优惠的方式不同,但整个购物车的初始化、统计总价、总运费、总优惠和支付价格的逻辑都是一样的。 + +正如我们开始时提到的,代码重复本身不可怕,可怕的是漏改或改错。比如,写 VIP 用户购物车的同学发现商品总价计算有 Bug,不应该是把所有 Item 的 price 加在一起,而是应该把所有 Item 的 **price\*quantity** 加在一起。 + +这时,他可能会只修改 VIP 用户购物车的代码,而忽略了普通用户、内部用户的购物车中,重复的逻辑实现也有相同的 Bug。 + +有了三个购物车后,我们就需要根据不同的用户类型使用不同的购物车了。如下代码所示,使用三个 if 实现不同类型用户调用不同购物车的 process 方法: + +``` +@GetMapping("wrong") +public Cart wrong(@RequestParam("userId") int userId) { + //根据用户ID获得用户类型 + String userCategory = Db.getUserCategory(userId); + //普通用户处理逻辑 + if (userCategory.equals("Normal")) { + NormalUserCart normalUserCart = new NormalUserCart(); + return normalUserCart.process(userId, items); + } + //VIP用户处理逻辑 + if (userCategory.equals("Vip")) { + VipUserCart vipUserCart = new VipUserCart(); + return vipUserCart.process(userId, items); + } + //内部用户处理逻辑 + if (userCategory.equals("Internal")) { + InternalUserCart internalUserCart = new InternalUserCart(); + return internalUserCart.process(userId, items); + } + + return null; +} +``` + +电商的营销玩法是多样的,以后势必还会有更多用户类型,需要更多的购物车。我们就只能不断增加更多的购物车类,一遍一遍地写重复的购物车逻辑、写更多的 if 逻辑吗? + +当然不是,相同的代码应该只在一处出现! + +如果我们熟记抽象类和抽象方法的定义的话,这时或许就会想到,是否可以把重复的逻辑定义在抽象类中,三个购物车只要分别实现不同的那份逻辑呢? + +其实,这个模式就是**模板方法模式**。我们在父类中实现了购物车处理的流程模板,然后把需要特殊处理的地方留空白也就是留抽象方法定义,让子类去实现其中的逻辑。由于父类的逻辑不完整无法单独工作,因此需要定义为抽象类。 + +如下代码所示,AbstractCart 抽象类实现了购物车通用的逻辑,额外定义了两个抽象方法让子类去实现。其中,processCouponPrice 方法用于计算商品折扣,processDeliveryPrice 方法用于计算运费。 + +``` +public abstract class AbstractCart { + //处理购物车的大量重复逻辑在父类实现 + public Cart process(long userId, Map items) { + + Cart cart = new Cart(); + + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + //让子类处理每一个商品的优惠 + itemList.stream().forEach(item -> { + processCouponPrice(userId, item); + processDeliveryPrice(userId, item); + }); + //计算商品总价 + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算总运费 + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算总折扣 + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算应付价格 + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } + + //处理商品优惠的逻辑留给子类实现 + protected abstract void processCouponPrice(long userId, Item item); + //处理配送费的逻辑留给子类实现 + protected abstract void processDeliveryPrice(long userId, Item item); +} +``` + +有了这个抽象类,三个子类的实现就非常简单了。普通用户的购物车 **NormalUserCart**,实现的是 0 优惠和 10% 运费的逻辑: + +``` +@Service(value = "NormalUserCart") +public class NormalUserCart extends AbstractCart { + + @Override + protected void processCouponPrice(long userId, Item item) { + item.setCouponPrice(BigDecimal.ZERO); + } + + @Override + protected void processDeliveryPrice(long userId, Item item) { + item.setDeliveryPrice(item.getPrice() + .multiply(BigDecimal.valueOf(item.getQuantity())) + .multiply(new BigDecimal("0.1"))); + } +} +``` + +VIP 用户的购物车 VipUserCart,直接继承了 NormalUserCart,只需要修改多买优惠策略: + +``` +@Service(value = "VipUserCart") +public class VipUserCart extends NormalUserCart { + + @Override + protected void processCouponPrice(long userId, Item item) { + if (item.getQuantity() > 2) { + item.setCouponPrice(item.getPrice() + .multiply(BigDecimal.valueOf(100 - Db.getUserCouponPercent(userId)).divide(new BigDecimal("100"))) + .multiply(BigDecimal.valueOf(item.getQuantity() - 2))); + } else { + item.setCouponPrice(BigDecimal.ZERO); + } + } +} +``` + +内部用户购物车 InternalUserCart 是最简单的,直接设置 0 运费和 0 折扣即可: + +``` +@Service(value = "InternalUserCart") +public class InternalUserCart extends AbstractCart { + @Override + protected void processCouponPrice(long userId, Item item) { + item.setCouponPrice(BigDecimal.ZERO); + } + + @Override + protected void processDeliveryPrice(long userId, Item item) { + item.setDeliveryPrice(BigDecimal.ZERO); + } +} +``` + +抽象类和三个子类的实现关系图,如下所示: + +![](http://img.dabin-coder.cn/image/重复代码1.png) + +是不是比三个独立的购物车程序简单了很多呢?接下来,我们再看看如何能避免三个 if 逻辑。 + +或许你已经注意到了,定义三个购物车子类时,我们在 **@Service** 注解中对 Bean 进行了命名。既然三个购物车都叫 XXXUserCart,那我们就可以把用户类型字符串拼接 UserCart 构成购物车 Bean 的名称,然后利用 Spring 的 IoC 容器,通过 Bean 的名称直接获取到 **AbstractCart**,调用其 process 方法即可实现通用。 + +其实,这就是工厂模式,只不过是借助 Spring 容器实现罢了: + +``` +@GetMapping("right") +public Cart right(@RequestParam("userId") int userId) { + String userCategory = Db.getUserCategory(userId); + AbstractCart cart = (AbstractCart) applicationContext.getBean(userCategory + "UserCart"); + return cart.process(userId, items); +} +``` + +试想, 之后如果有了新的用户类型、新的用户逻辑,是不是完全不用对代码做任何修改,只要新增一个 XXXUserCart 类继承 AbstractCart,实现特殊的优惠和运费处理逻辑就可以了? + +**这样一来,我们就利用工厂模式 + 模板方法模式,不仅消除了重复代码,还避免了修改既有代码的风险**。这就是设计模式中的**开闭原则**:对修改关闭,对扩展开放。 + +## 2. 利用注解 + 反射消除重复代码 + +是不是有点兴奋了,业务代码居然也能 OOP 了。我们再看一个三方接口的调用案例,同样也是一个普通的业务逻辑。 + +假设银行提供了一些 API 接口,对参数的序列化有点特殊,不使用 JSON,而是需要我们把参数依次拼在一起构成一个大字符串。 + +- 按照银行提供的 API 文档的顺序,把所有参数构成定长的数据,然后拼接在一起作为整个字符串。 + +- 因为每一种参数都有固定长度,未达到长度时需要做填充处理: + +- - 字符串类型的参数不满长度部分需要以下划线右填充,也就是字符串内容靠左; + - 数字类型的参数不满长度部分以 0 左填充,也就是实际数字靠右; + - 货币类型的表示需要把金额向下舍入 2 位到分,以分为单位,作为数字类型同样进行左填充。 + +- 对所有参数做 MD5 操作作为签名(为了方便理解,Demo 中不涉及加盐处理)。 + +比如,创建用户方法和支付方法的定义是这样的: + +![](http://img.dabin-coder.cn/image/重复代码2.png) + +代码很容易实现,直接根据接口定义实现填充操作、加签名、请求调用操作即可: + +``` +public class BankService { + + //创建用户方法 + public static String createUser(String name, String identity, String mobile, int age) throws IOException { + StringBuilder stringBuilder = new StringBuilder(); + //字符串靠左,多余的地方填充_ + stringBuilder.append(String.format("%-10s", name).replace(' ', '_')); + //字符串靠左,多余的地方填充_ + stringBuilder.append(String.format("%-18s", identity).replace(' ', '_')); + //数字靠右,多余的地方用0填充 + stringBuilder.append(String.format("%05d", age)); + //字符串靠左,多余的地方用_填充 + stringBuilder.append(String.format("%-11s", mobile).replace(' ', '_')); + //最后加上MD5作为签名 + stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString())); + return Request.Post("http://localhost:45678/reflection/bank/createUser") + .bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON) + .execute().returnContent().asString(); + } + + //支付方法 + public static String pay(long userId, BigDecimal amount) throws IOException { + StringBuilder stringBuilder = new StringBuilder(); + //数字靠右,多余的地方用0填充 + stringBuilder.append(String.format("%020d", userId)); + //金额向下舍入2位到分,以分为单位,作为数字靠右,多余的地方用0填充 + stringBuilder.append(String.format("%010d", amount.setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue())); + //最后加上MD5作为签名 + stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString())); + return Request.Post("http://localhost:45678/reflection/bank/pay") + .bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON) + .execute().returnContent().asString(); + } +} +``` + +可以看到,这段代码的重复粒度更细: + +- 三种标准数据类型的处理逻辑有重复,稍有不慎就会出现 Bug; +- 处理流程中字符串拼接、加签和发请求的逻辑,在所有方法重复; +- 实际方法的入参的参数类型和顺序,不一定和接口要求一致,容易出错; +- 代码层面针对每一个参数硬编码,无法清晰地进行核对,如果参数达到几十个、上百个,出错的概率极大。 + +那应该如何改造这段代码呢?没错,就是要用注解和反射! + +使用注解和反射这两个武器,就可以针对银行请求的所有逻辑均使用一套代码实现,不会出现任何重复。 + +要实现接口逻辑和逻辑实现的剥离,首先需要以 POJO 类(只有属性没有任何业务逻辑的数据类)的方式定义所有的接口参数。比如,下面这个创建用户 API 的参数: + +``` +@Data +public class CreateUserAPI { + private String name; + private String identity; + private String mobile; + private int age; +} +``` + +有了接口参数定义,我们就能通过自定义注解为接口和所有参数增加一些元数据。如下所示,我们定义一个接口 API 的注解 BankAPI,包含接口 URL 地址和接口说明: + +``` +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@Inherited +public @interface BankAPI { + String desc() default ""; + String url() default ""; +} +``` + +然后,我们再定义一个自定义注解 @BankAPIField,用于描述接口的每一个字段规范,包含参数的次序、类型和长度三个属性: + +``` +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Documented +@Inherited +public @interface BankAPIField { + int order() default -1; + int length() default -1; + String type() default ""; +} +``` + +接下来,注解就可以发挥威力了。 + +如下所示,我们定义了 CreateUserAPI 类描述创建用户接口的信息,通过为接口增加 @BankAPI 注解,来补充接口的 URL 和描述等元数据;通过为每一个字段增加 @BankAPIField 注解,来补充参数的顺序、类型和长度等元数据: + +``` +@BankAPI(url = "/bank/createUser", desc = "创建用户接口") +@Data +public class CreateUserAPI extends AbstractAPI { + @BankAPIField(order = 1, type = "S", length = 10) + private String name; + @BankAPIField(order = 2, type = "S", length = 18) + private String identity; + @BankAPIField(order = 4, type = "S", length = 11) //注意这里的order需要按照API表格中的顺序 + private String mobile; + @BankAPIField(order = 3, type = "N", length = 5) + private int age; +} +``` + +另一个 PayAPI 类也是类似的实现: + +``` +@BankAPI(url = "/bank/pay", desc = "支付接口") +@Data +public class PayAPI extends AbstractAPI { + @BankAPIField(order = 1, type = "N", length = 20) + private long userId; + @BankAPIField(order = 2, type = "M", length = 10) + private BigDecimal amount; +} +``` + +这 2 个类继承的 AbstractAPI 类是一个空实现,因为这个案例中的接口并没有公共数据可以抽象放到基类。 + +通过这 2 个类,我们可以在几秒钟内完成和 API 清单表格的核对。理论上,如果我们的核心翻译过程(也就是把注解和接口 API 序列化为请求需要的字符串的过程)没问题,只要注解和表格一致,API 请求的翻译就不会有任何问题。 + +以上,我们通过注解实现了对 API 参数的描述。接下来,我们再看看反射如何配合注解实现动态的接口参数组装: + +- 第 3 行代码中,我们从类上获得了 BankAPI 注解,然后拿到其 URL 属性,后续进行远程调用。 +- 第 6~9 行代码,使用 stream 快速实现了获取类中所有带 BankAPIField 注解的字段,并把字段按 order 属性排序,然后设置私有字段反射可访问。 +- 第 12~38 行代码,实现了反射获取注解的值,然后根据 BankAPIField 拿到的参数类型,按照三种标准进行格式化,将所有参数的格式化逻辑集中在了这一处。 +- 第 41~48 行代码,实现了参数加签和请求调用。 + +``` +private static String remoteCall(AbstractAPI api) throws IOException { + //从BankAPI注解获取请求地址 + BankAPI bankAPI = api.getClass().getAnnotation(BankAPI.class); + bankAPI.url(); + StringBuilder stringBuilder = new StringBuilder(); + Arrays.stream(api.getClass().getDeclaredFields()) //获得所有字段 + .filter(field -> field.isAnnotationPresent(BankAPIField.class)) //查找标记了注解的字段 + .sorted(Comparator.comparingInt(a -> a.getAnnotation(BankAPIField.class).order())) //根据注解中的order对字段排序 + .peek(field -> field.setAccessible(true)) //设置可以访问私有字段 + .forEach(field -> { + //获得注解 + BankAPIField bankAPIField = field.getAnnotation(BankAPIField.class); + Object value = ""; + try { + //反射获取字段值 + value = field.get(api); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + //根据字段类型以正确的填充方式格式化字符串 + switch (bankAPIField.type()) { + case "S": { + stringBuilder.append(String.format("%-" + bankAPIField.length() + "s", value.toString()).replace(' ', '_')); + break; + } + case "N": { + stringBuilder.append(String.format("%" + bankAPIField.length() + "s", value.toString()).replace(' ', '0')); + break; + } + case "M": { + if (!(value instanceof BigDecimal)) + throw new RuntimeException(String.format("{} 的 {} 必须是BigDecimal", api, field)); + stringBuilder.append(String.format("%0" + bankAPIField.length() + "d", ((BigDecimal) value).setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue())); + break; + } + default: + break; + } + }); + //签名逻辑 + stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString())); + String param = stringBuilder.toString(); + long begin = System.currentTimeMillis(); + //发请求 + String result = Request.Post("http://localhost:45678/reflection" + bankAPI.url()) + .bodyString(param, ContentType.APPLICATION_JSON) + .execute().returnContent().asString(); + log.info("调用银行API {} url:{} 参数:{} 耗时:{}ms", bankAPI.desc(), bankAPI.url(), param, System.currentTimeMillis() - begin); + return result; +} +``` + +可以看到,所有处理参数排序、填充、加签、请求调用的核心逻辑,都汇聚在了 remoteCall 方法中。有了这个核心方法,BankService 中每一个接口的实现就非常简单了,只是参数的组装,然后调用 remoteCall 即可。 + +``` +//创建用户方法 +public static String createUser(String name, String identity, String mobile, int age) throws IOException { + CreateUserAPI createUserAPI = new CreateUserAPI(); + createUserAPI.setName(name); + createUserAPI.setIdentity(identity); + createUserAPI.setAge(age); + createUserAPI.setMobile(mobile); + return remoteCall(createUserAPI); +} +//支付方法 +public static String pay(long userId, BigDecimal amount) throws IOException { + PayAPI payAPI = new PayAPI(); + payAPI.setUserId(userId); + payAPI.setAmount(amount); + return remoteCall(payAPI); +} +``` + +其实,**许多涉及类结构性的通用处理,都可以按照这个模式来减少重复代码**。 + +反射给予了我们在不知晓类结构的时候,按照固定的逻辑处理类的成员;而注解给了我们为这些成员补充元数据的能力,使得我们利用反射实现通用逻辑的时候,可以从外部获得更多我们关心的数据。 + +## 3. 利用属性拷贝工具消除重复代码 + +最后,我们再来看一种业务代码中经常出现的代码逻辑,实体之间的转换复制。 + +对于三层架构的系统,考虑到层之间的解耦隔离以及每一层对数据的不同需求,通常每一层都会有自己的 POJO 作为数据实体。比如,数据访问层的实体一般叫作 DataObject 或 DO,业务逻辑层的实体一般叫作 Domain,表现层的实体一般叫作 Data Transfer Object 或 DTO。 + +这里我们需要注意的是,如果手动写这些实体之间的赋值代码,同样容易出错。 + +对于复杂的业务系统,实体有几十甚至几百个属性也很正常。就比如 ComplicatedOrderDTO 这个数据传输对象,描述的是一个订单中的几十个属性。如果我们要把这个 DTO 转换为一个类似的 DO,复制其中大部分的字段,然后把数据入库,势必需要进行很多属性映射赋值操作。就像这样,密密麻麻的代码是不是已经让你头晕了? + +``` +ComplicatedOrderDTO orderDTO = new ComplicatedOrderDTO(); +ComplicatedOrderDO orderDO = new ComplicatedOrderDO(); +orderDO.setAcceptDate(orderDTO.getAcceptDate()); +orderDO.setAddress(orderDTO.getAddress()); +orderDO.setAddressId(orderDTO.getAddressId()); +orderDO.setCancelable(orderDTO.isCancelable()); +orderDO.setCommentable(orderDTO.isComplainable()); //属性错误 +orderDO.setComplainable(orderDTO.isCommentable()); //属性错误 +orderDO.setCancelable(orderDTO.isCancelable()); +orderDO.setCouponAmount(orderDTO.getCouponAmount()); +orderDO.setCouponId(orderDTO.getCouponId()); +orderDO.setCreateDate(orderDTO.getCreateDate()); +orderDO.setDirectCancelable(orderDTO.isDirectCancelable()); +orderDO.setDeliverDate(orderDTO.getDeliverDate()); +orderDO.setDeliverGroup(orderDTO.getDeliverGroup()); +orderDO.setDeliverGroupOrderStatus(orderDTO.getDeliverGroupOrderStatus()); +orderDO.setDeliverMethod(orderDTO.getDeliverMethod()); +orderDO.setDeliverPrice(orderDTO.getDeliverPrice()); +orderDO.setDeliveryManId(orderDTO.getDeliveryManId()); +orderDO.setDeliveryManMobile(orderDO.getDeliveryManMobile()); //对象错误 +``` + +**如果不是代码中有注释,你能看出其中的诸多问题吗?** + +如果原始的 DTO 有 100 个字段,我们需要复制 90 个字段到 DO 中,保留 10 个不赋值,最后应该如何校验正确性呢?数数吗?即使数出有 90 行代码,也不一定正确,因为属性可能重复赋值。 + +有的时候字段命名相近,比如 complainable 和 commentable,容易搞反(第 7 和第 8 行),或者对两个目标字段重复赋值相同的来源字段(比如第 28 行) + +明明要把 DTO 的值赋值到 DO 中,却在 set 的时候从 DO 自己取值(比如第 20 行),导致赋值无效。 + +这段代码并不是我随手写出来的,而是一个真实案例。有位同学就像代码中那样把经纬度赋值反了,因为落库的字段实在太多了。这个 Bug 很久都没发现,直到真正用到数据库中的经纬度做计算时,才发现一直以来都存错了。 + +修改方法很简单,可以使用类似 BeanUtils 这种 Mapping 工具来做 Bean 的转换,copyProperties 方法还允许我们提供需要忽略的属性: + +``` +ComplicatedOrderDTO orderDTO = new ComplicatedOrderDTO(); +ComplicatedOrderDO orderDO = new ComplicatedOrderDO(); +BeanUtils.copyProperties(orderDTO, orderDO, "id"); +return orderDO; +``` + +## 总结 + +第一种代码重复是,有多个并行的类实现相似的代码逻辑。我们可以考虑提取相同逻辑在父类中实现,差异逻辑通过抽象方法留给子类实现。使用类似的模板方法把相同的流程和逻辑固定成模板,保留差异的同时尽可能避免代码重复。同时,可以使用 Spring 的 IoC 特性注入相应的子类,来避免实例化子类时的大量 if…else 代码。 + +第二种代码重复是,使用硬编码的方式重复实现相同的数据处理算法。我们可以考虑把规则转换为自定义注解,作为元数据对类或对字段、方法进行描述,然后通过反射动态读取这些元数据、字段或调用方法,实现规则参数和规则定义的分离。也就是说,把变化的部分也就是规则的参数放入注解,规则的定义统一处理。 + +第三种代码重复是,业务代码中常见的 DO、DTO、VO 转换时大量字段的手动赋值,遇到有上百个属性的复杂类型,非常非常容易出错。我的建议是,不要手动进行赋值,考虑使用 Bean 映射工具进行。此外,还可以考虑采用单元测试对所有字段进行赋值正确性校验。 \ No newline at end of file diff --git a/docs/advance/excellent-article/5-jvm-optimize.md b/docs/advance/excellent-article/5-jvm-optimize.md new file mode 100644 index 0000000..e60b862 --- /dev/null +++ b/docs/advance/excellent-article/5-jvm-optimize.md @@ -0,0 +1,94 @@ +# 一次简单的 *JVM* 调优,拿去写到简历里 + +大家好,我是大彬。 + +JVM调优一直是面试官很喜欢问的问题。周末在网上看到一篇JVM调优的文章,给大家分享一下。 + +> 来源地址:https://zhenbianshu.github.io + +## **背景** + +最近对负责的项目进行了一次性能优化,其中包括对 JVM 参数的调整,算是进行了一次简单的 JVM 调优,JVM 参数调整之后,服务的整体性能有 5% 左右的提升,还算不错。 + +先介绍一下项目的基本情况: + +项目是一个高 QPS 压力的 web 服务,单机 QPS 一直维持在 1.5K 以上,由于旧机器的”拖累”,配置的堆大小是 8G,其中 young 区是 4G,垃圾回收器用的是 parNew + CMS。 + +## **旧状** + +首先是查看当前 GC 的情况,主要是使用 `jstat` 查看 GC 的概况,再查看 gc log,分析单次 gc 的详细状况。 + +使用 `jstat -gcutil pid 1000` 每隔一秒打印一次 gc 统计信息。 + +![](http://img.dabin-coder.cn/image/jvm调优1.png) + +可以看到,单次 gc 平均耗时是 60ms 左右,还算可以接受,但 YGC 非常频繁,基本上每秒一次,有的时候还会一秒两次,在一秒两次的时候,服务对业务响应时长的压力就会变得很大。 + +接着查看 gc log,打印 gc log 需要在 JVM 启动参数里添加以下参数: + +- `-XX:+PrintGCDateStamps`:打印 gc 发生的时间戳。 +- `-XX:+PrintTenuringDistribution`:打印 gc 发生时的分代信息。 +- `-XX:+PrintGCApplicationStoppedTime`:打印 gc 停顿时长 +- `-XX:+PrintGCApplicationConcurrentTime`:打印 gc 间隔的服务运行时长 +- `-XX:+PrintGCDetails`:打印 gc 详情,包括 gc 前/内存等。 +- `-Xloggc:../gclogs/gc.log.date`:指定 gc log 的路径 + +看到的 gc log 形如: + +![](http://img.dabin-coder.cn/image/jvm调优2.png) + +单次 GC 方面并不能直接看出问题,但可以看到 gc 前有很多次 18ms 左右的停顿。 + +## **分析和调整** + +### YGC 频繁 + +直接查看 gc log 并不直观,我们可以借用一些可视化工具来帮助我们分析, `[gceasy](https://gceasy.io/)` 是个挺不错的网站,我们把 gc log 上传上去后, gceasy 可以帮助我们生成各个维度的图表帮助分析。 + +查看 gceasy 生成的报告,发现我们服务的 gc 吞吐量是 95%,它指的是 JVM 运行业务代码的时长占 JVM 总运行时长的比例,这个比例确实有些低了,运行 100 分钟就有 5 分钟在执行 gc。幸好这些 GC 中绝大多数都是 YGC,单次时长可控且分布平均,这使得我们服务还能平稳运行。 + +解决这个问题要么是减少对象的创建,要么就增大 young 区。前者不是一时半会儿都解决的,需要查找代码里可能有问题的点,分步优化。 + +而后者虽然改一下配置就行,但以我们对 GC 最直观的印象来说,增大 young 区,YGC 的时长也会迅速增大。 + +其实这点不必太过担心,我们知道 YGC 的耗时是由 `GC 标记 + GC 复制` 组成的,相对于 GC 复制,GC 标记是非常快的。而 young 区内大多数对象的生命周期都非常短,如果将 young 区增大一倍,GC 标记的时长会提升一倍,但到 GC 发生时被标记的对象大部分已经死亡, GC 复制的时长肯定不会提升一倍,所以我们可以放心增大 young 区大小。 + +由于低内存旧机器都被换掉了,我把堆大小调整到了 12G,young 区保留为 8G。 + +### 分代调整 + +除了 GC 太频繁之外,GC 后各分代的平均大小也需要调整。 + +![](http://img.dabin-coder.cn/image/jvm调优3.png) + +我们知道 GC 的提升机制,每次 GC 后,JVM 存活代数大于 `MaxTenuringThreshold` 的对象提升到老年代。当然,JVM 还有动态年龄计算的规则:按照年龄从小到大对其所占用的大小进行累积,当累积的某个年龄大小超过了 survivor 区的一半时,取这个年龄和 MaxTenuringThreshold 中更小的一个值,作为新的晋升年龄阈值,但看各代总的内存大小,是达不到 survivor 区的一半的。 + +![](http://img.dabin-coder.cn/image/jvm调优4.png) + +所以这十五个分代内的对象会一直在两个 survivor 区之间来回复制,再观察各分代的平均大小,可以看到,四代以上的对象已经有一半都会保留到老年区了,所以可以将这些对象直接提升到老年代,以减少对象在两个 survivor 区之间复制的性能开销。 + +所以我把 MaxTenuringThreshold 的值调整为 4,将存活超过四代的对象直接提升到老年代。 + +### 偏向锁停顿 + +还有一个问题是 gc log 里有很多 18ms 左右的停顿,有时候连续有十多条,虽然每次停顿时长不长,但连续多次累积的时间也非常可观。 + +是因为 1.8 之后 JVM 对锁进行了优化,添加了偏向锁的概念,避免了很多不必要的加锁操作,但偏向锁一旦遇到锁竞争,取消锁需要进入 `safe point`,导致 STW。 + +解决方式很简单,JVM 启动参数里添加 `-XX:-UseBiasedLocking` 即可。 + +## **结果** + +调整完 JVM 参数后先是对服务进行压测,发现性能确实有提升,也没有发生严重的 GC 问题,之后再把调整好的配置放到线上机器进行灰度,同时收集 gc log,再次进行分析。 + +由于 young 区大小翻倍了,所以 YGC 的频率减半了,GC 的吞量提升到了 97.75%。平均 GC 时长略有上升,从 60ms 左右提升到了 66ms,还是挺符合预期的。 + +由于 CMS 在进行 GC 时也会清理 young 区,CMS 的时长也受到了影响,CMS 的最终标记和并发清理阶段耗时增加了,也比较正常。 + +另外我还统计了对业务的影响,之前因为 GC 导致超时的请求大大减少了。 + +## **小结** + +总之,这是一次挺成功的 GC 调整,让我对 GC 有了更深的理解,但由于没有深入到 old 区,之前学习到的 CMS 相关的知识还没有复习到。 + +不过性能优化并不是一朝一夕的事,需要时刻关注问题,及时做出调整。 \ No newline at end of file diff --git a/docs/advance/excellent-article/6-spring-three-cache.md b/docs/advance/excellent-article/6-spring-three-cache.md new file mode 100644 index 0000000..d47222b --- /dev/null +++ b/docs/advance/excellent-article/6-spring-three-cache.md @@ -0,0 +1,119 @@ +# Spring 为何需要三级缓存解决循环依赖,而不是二级缓存? + +## **前言** + +在使用spring框架的日常开发中,bean之间的循环依赖太频繁了,spring已经帮我们去解决循环依赖问题,对我们开发者来说是无感知的,下面具体分析一下spring是如何解决bean之间循环依赖,为什么要使用到三级缓存,而不是二级缓存? + +## **bean生命周期** + +首先大家需要了解一下bean在spring中的生命周期,bean在spring的加载流程,才能够更加清晰知道spring是如何解决循环依赖的。 + +![](http://img.dabin-coder.cn/image/三级依赖1.png) + +我们在spring的BeanFactory工厂列举了很多接口,代表着bean的生命周期,我们主要记住的是我圈红线圈出来的接口, 再结合spring的源码来看这些接口主要是在哪里调用的 + +![](http://img.dabin-coder.cn/image/三级依赖2.png) + +AbstractAutowireCapableBeanFactory类的doCreateBean方法是创建bean的开始,我们可以看到首先需要实例化这个bean,也就是在堆中开辟一块内存空间给这个对象,createBeanInstance方法里面逻辑大概就是采用反射生成实例对象,进行到这里表示对象还并未进行属性的填充,也就是@Autowired注解的属性还未得到注入 + +![](http://img.dabin-coder.cn/image/三级依赖3.png) + +我们可以看到第二步就是填充bean的成员属性,populateBean方法里面的逻辑大致就是对使用到了注入属性的注解就会进行注入,如果在注入的过程发现注入的对象还没生成,则会跑去生产要注入的对象,第三步就是调用initializeBean方法初始化bean,也就是调用我们上述所提到的接口 + +![](http://img.dabin-coder.cn/image/三级缓存4.png) + +可以看到initializeBean方法中,首先调用的是使用的Aware接口的方法,我们具体看一下invokeAwareMethods方法中会调用Aware接口的那些方法 + +![](http://img.dabin-coder.cn/image/三级缓存5.png) + +我们可以知道如果我们实现了BeanNameAware,BeanClassLoaderAware,BeanFactoryAware三个Aware接口的话,会依次调用setBeanName(), setBeanClassLoader(), setBeanFactory()方法,再看applyBeanPostProcessorsBeforeInitialization源码 + +![](http://img.dabin-coder.cn/image/三级缓存6.png) + +发现会如果有类实现了BeanPostProcessor接口,就会执行postProcessBeforeInitialization方法,这里需要注意的是:如果多个类实现BeanPostProcessor接口,那么多个实现类都会执行postProcessBeforeInitialization方法,可以看到是for循环依次执行的,还有一个注意的点就是如果加载A类到spring容器中,A类也重写了BeanPostProcessor接口的postProcessBeforeInitialization方法,这时要注意A类的postProcessBeforeInitialization方法并不会得到执行,因为A类还未加载完成,还未完全放到spring的singletonObjects一级缓存中。 + +再看一个注意的点 + +![](http://img.dabin-coder.cn/image/三级缓存7.png) + +![](http://img.dabin-coder.cn/image/三级缓存8.png) + +可以看到ApplicationContextAwareProcessor也实现了BeanPostProcessor接口,重写了postProcessBeforeInitialization方法,方法里面并调用了invokeAwareInterfaces方法,而invokeAwareInterfaces方法也写着如果实现了众多的Aware接口,则会依次执行相应的方法,值得注意的是ApplicationContextAware接口的setApplicationContext方法,再看一下invokeInitMethods源码 + +![](http://img.dabin-coder.cn/image/三级缓存9.png) + +发现如果实现了InitializingBean接口,重写了afterPropertiesSet方法,则会调用afterPropertiesSet方法,最后还会调用是否指定了init-method,可以通过标签,或者@Bean注解的initMethod指定,最后再看一张applyBeanPostProcessorsAfterInitialization源码图 + +![](http://img.dabin-coder.cn/image/三级缓存10.png) + +发现跟之前的postProcessBeforeInitialization方法类似,也是循环遍历实现了BeanPostProcessor的接口实现类,执行postProcessAfterInitialization方法。整个bean的生命执行流程就如上面截图所示,哪个接口的方法在哪里被调用,方法的执行流程。 + +最后,对bean的生命流程进行一个流程图的总结 + +![](http://img.dabin-coder.cn/image/三级缓存11.png) + +## **三级缓存解决循环依赖** + +上一小节对bean的生命周期做了一个整体的流程分析,对spring如何去解决循环依赖的很有帮助。前面我们分析到填充属性时,如果发现属性还未在spring中生成,则会跑去生成属性对象实例。 + +![](http://img.dabin-coder.cn/image/三级缓存12.png) + +我们可以看到填充属性的时候,spring会提前将已经实例化的bean通过ObjectFactory半成品暴露出去,为什么称为半成品是因为这时候的bean对象实例化,但是未进行属性填充,是一个不完整的bean实例对象 + +![](http://img.dabin-coder.cn/image/三级缓存13.png) + +spring利用singletonObjects, earlySingletonObjects, singletonFactories三级缓存去解决的,所说的缓存其实也就是三个Map + +![](http://img.dabin-coder.cn/image/三级缓存14.png) + +可以看到三级缓存各自保存的对象,这里重点关注二级缓存earlySingletonObjects和三级缓存singletonFactory,一级缓存可以进行忽略。前面我们讲过先实例化的bean会通过ObjectFactory半成品提前暴露在三级缓存中 + +![](http://img.dabin-coder.cn/image/三级缓存15.png) + +singletonFactory是传入的一个匿名内部类,调用ObjectFactory.getObject()最终会调用getEarlyBeanReference方法。再来看看循环依赖中是怎么拿其它半成品的实例对象的。 + +我们假设现在有这样的场景AService依赖BService,BService依赖AService + +\1. AService首先实例化,实例化通过ObjectFactory半成品暴露在三级缓存中 + +\2. 填充属性BService,发现BService还未进行过加载,就会先去加载BService + +\3. 再加载BService的过程中,实例化,也通过ObjectFactory半成品暴露在三级缓存 + +\4. 填充属性AService的时候,这时候能够从三级缓存中拿到半成品的ObjectFactory + +![](http://img.dabin-coder.cn/image/三级缓存16.png) + +拿到ObjectFactory对象后,调用ObjectFactory.getObject()方法最终会调用getEarlyBeanReference()方法,getEarlyBeanReference这个方法主要逻辑大概描述下如果bean被AOP切面代理则返回的是beanProxy对象,如果未被代理则返回的是原bean实例。 + +这时我们会发现能够拿到bean实例(属性未填充),然后从三级缓存移除,放到二级缓存earlySingletonObjects中,而此时B注入的是一个半成品的实例A对象,不过随着B初始化完成后,A会继续进行后续的初始化操作,最终B会注入的是一个完整的A实例,因为在内存中它们是同一个对象。 + +下面是重点,我们发现这个二级缓存好像显得有点多余,好像可以去掉,只需要一级和三级缓存也可以做到解决循环依赖的问题??? + +只要两个缓存确实可以做到解决循环依赖的问题,但是有一个前提这个bean没被AOP进行切面代理,如果这个bean被AOP进行了切面代理,那么只使用两个缓存是无法解决问题,下面来看一下bean被AOP进行了切面代理的场景 + +![](http://img.dabin-coder.cn/image/三级缓存17.png) + +我们发现AService的testAopProxy被AOP代理了,看看传入的匿名内部类的getEarlyBeanReference返回的是什么对象。 + +![](http://img.dabin-coder.cn/image/三级缓存18.png) + +发现singletonFactory.getObject()返回的是一个AService的代理对象,还是被CGLIB代理的。再看一张再执行一遍singletonFactory.getObject()返回的是否是同一个AService的代理对象 + +![](http://img.dabin-coder.cn/image/三级缓存19.png) + +我们会发现再执行一遍singleFactory.getObject()方法又是一个新的代理对象,这就会有问题了,因为AService是单例的,每次执行singleFactory.getObject()方法又会产生新的代理对象。 + +假设这里只有一级和三级缓存的话,我每次从三级缓存中拿到singleFactory对象,执行getObject()方法又会产生新的代理对象,这是不行的,因为AService是单例的,所有这里我们要借助二级缓存来解决这个问题,将执行了singleFactory.getObject()产生的对象放到二级缓存中去,后面去二级缓存中拿,没必要再执行一遍singletonFactory.getObject()方法再产生一个新的代理对象,保证始终只有一个代理对象。还有一个注意的点 + +![](http://img.dabin-coder.cn/image/三级缓存20.png) + +既然singleFactory.getObject()返回的是代理对象,那么注入的也应该是代理对象,我们可以看到注入的确实是经过CGLIB代理的AService对象。所以如果没有AOP的话确实可以两级缓存就可以解决循环依赖的问题,如果加上AOP,两级缓存是无法解决的,不可能每次执行singleFactory.getObject()方法都给我产生一个新的代理对象,所以还要借助另外一个缓存来保存产生的代理对象 + +## **总结** + +前面先讲到bean的加载流程,了解了bean加载流程对spring如何解决循环依赖的问题很有帮助,后面再分析到spring为什么需要利用到三级缓存解决循环依赖问题,而不是二级缓存。网上可以试试AOP的情形,实践一下就能明白二级缓存为什么解决不了AOP代理的场景了 + +在工作中,一直认为编程代码不是最重要的,重要的是在工作中所养成的编程思维。 + +原文:cnblogs.com/semi-sub/p/13548479.html \ No newline at end of file diff --git a/docs/advance/excellent-article/7-sql-optimize.md b/docs/advance/excellent-article/7-sql-optimize.md new file mode 100644 index 0000000..af16f92 --- /dev/null +++ b/docs/advance/excellent-article/7-sql-optimize.md @@ -0,0 +1,421 @@ +# 8种最坑SQL语法 + +> 本文已经收录到Github仓库,该仓库包含**计算机基础、Java基础、多线程、JVM、常见框架、分布式、微服务、设计模式、架构**等核心知识点,欢迎star~ +> +> 地址:https://github.com/Tyson0314/Java-learning + +大家好,我是大彬~ + +今天给大家分享几个SQL常见的“坏毛病”及优化技巧。 + +**SQL语句的执行顺序:** + +![](http://img.dabin-coder.cn/image/sql优化1.png) + +## 1、LIMIT 语句 + +分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如对于下面简单的语句,一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引。这样条件排序都能有效的利用到索引,性能迅速提升。 + +``` +SELECT * +FROM operation +WHERE type = 'SQLStats' + AND name = 'SlowLog' +ORDER BY create_time +LIMIT 1000, 10; +``` + +好吧,可能90%以上的 DBA 解决该问题就到此为止。但当 LIMIT 子句变成 “LIMIT 1000000,10” 时,程序员仍然会抱怨:我只取10条记录为什么还是慢? + +要知道数据库也并不知道第1000000条记录从什么地方开始,即使有索引也需要从头计算一次。出现这种性能问题,多数情形下是程序员偷懒了。 + +在前端数据浏览翻页,或者大数据分批导出等场景下,是可以将上一页的最大值当成参数作为查询条件的。SQL 重新设计如下: + +``` +SELECT * +FROM operation +WHERE type = 'SQLStats' +AND name = 'SlowLog' +AND create_time > '2017-03-16 14:00:00' +ORDER BY create_time limit 10; +``` + +在新设计下查询时间基本固定,不会随着数据量的增长而发生变化。 + +## 2、隐式转换 + +SQL语句中查询变量和字段定义类型不匹配是另一个常见的错误。比如下面的语句: + +``` +mysql> explain extended SELECT * + > FROM my_balance b + > WHERE b.bpn = 14000000123 + > AND b.isverified IS NULL ; +mysql> show warnings; +| Warning | 1739 | Cannot use ref access on index 'bpn' due to type or collation conversion on field 'bpn' +``` + +其中字段 bpn 的定义为 varchar(20),MySQL 的策略是将字符串转换为数字之后再比较。函数作用于表字段,索引失效。 + +上述情况可能是应用程序框架自动填入的参数,而不是程序员的原意。现在应用框架很多很繁杂,使用方便的同时也小心它可能给自己挖坑。 + +## 3、关联更新、删除 + +虽然 MySQL5.6 引入了物化特性,但需要特别注意它目前仅仅针对查询语句的优化。对于更新或删除需要手工重写成 JOIN。 + +比如下面 UPDATE 语句,MySQL 实际执行的是循环/嵌套子查询(DEPENDENT SUBQUERY),其执行时间可想而知。 + +``` +UPDATE operation o +SET status = 'applying' +WHERE o.id IN (SELECT id + FROM (SELECT o.id, + o.status + FROM operation o + WHERE o.group = 123 + AND o.status NOT IN ( 'done' ) + ORDER BY o.parent, + o.id + LIMIT 1) t); +``` + +执行计划: + +``` ++----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+ +| 1 | PRIMARY | o | index | | PRIMARY | 8 | | 24 | Using where; Using temporary | +| 2 | DEPENDENT SUBQUERY | | | | | | | | Impossible WHERE noticed after reading const tables | +| 3 | DERIVED | o | ref | idx_2,idx_5 | idx_5 | 8 | const | 1 | Using where; Using filesort | ++----+--------------------+-------+-------+---------------+---------+---------+-------+------+-----------------------------------------------------+ +``` + +重写为 JOIN 之后,子查询的选择模式从 DEPENDENT SUBQUERY 变成 DERIVED,执行速度大大加快,从7秒降低到2毫秒。 + +``` +UPDATE operation o + JOIN (SELECT o.id, + o.status + FROM operation o + WHERE o.group = 123 + AND o.status NOT IN ( 'done' ) + ORDER BY o.parent, + o.id + LIMIT 1) t + ON o.id = t.id +SET status = 'applying' +``` + +执行计划简化为: + +``` ++----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+ +| 1 | PRIMARY | | | | | | | | Impossible WHERE noticed after reading const tables | +| 2 | DERIVED | o | ref | idx_2,idx_5 | idx_5 | 8 | const | 1 | Using where; Using filesort | ++----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------------------------------+ +``` + +## 4、混合排序 + +MySQL 不能利用索引进行混合排序。但在某些场景,还是有机会使用特殊方法提升性能的。 + +``` +SELECT * +FROM my_order o + INNER JOIN my_appraise a ON a.orderid = o.id +ORDER BY a.is_reply ASC, + a.appraise_time DESC +LIMIT 0, 20 +``` + +执行计划显示为全表扫描: + +``` ++----+-------------+-------+--------+-------------+---------+---------+---------------+---------+-+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra ++----+-------------+-------+--------+-------------+---------+---------+---------------+---------+-+ +| 1 | SIMPLE | a | ALL | idx_orderid | NULL | NULL | NULL | 1967647 | Using filesort | +| 1 | SIMPLE | o | eq_ref | PRIMARY | PRIMARY | 122 | a.orderid | 1 | NULL | ++----+-------------+-------+--------+---------+---------+---------+-----------------+---------+-+ +``` + +由于 is_reply 只有0和1两种状态,我们按照下面的方法重写后,执行时间从1.58秒降低到2毫秒。 + +``` +SELECT * +FROM ((SELECT * + FROM my_order o + INNER JOIN my_appraise a + ON a.orderid = o.id + AND is_reply = 0 + ORDER BY appraise_time DESC + LIMIT 0, 20) + UNION ALL + (SELECT * + FROM my_order o + INNER JOIN my_appraise a + ON a.orderid = o.id + AND is_reply = 1 + ORDER BY appraise_time DESC + LIMIT 0, 20)) t +ORDER BY is_reply ASC, + appraisetime DESC +LIMIT 20; +``` + +## 5、EXISTS语句 + +MySQL 对待 EXISTS 子句时,仍然采用嵌套子查询的执行方式。如下面的 SQL 语句: + +``` +SELECT * +FROM my_neighbor n + LEFT JOIN my_neighbor_apply sra + ON n.id = sra.neighbor_id + AND sra.user_id = 'xxx' +WHERE n.topic_status < 4 + AND EXISTS(SELECT 1 + FROM message_info m + WHERE n.id = m.neighbor_id + AND m.inuser = 'xxx') + AND n.topic_type <> 5 +``` + +执行计划为: + +``` ++----+--------------------+-------+------+-----+------------------------------------------+---------+-------+---------+ -----+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+--------------------+-------+------+ -----+------------------------------------------+---------+-------+---------+ -----+ +| 1 | PRIMARY | n | ALL | | NULL | NULL | NULL | 1086041 | Using where | +| 1 | PRIMARY | sra | ref | | idx_user_id | 123 | const | 1 | Using where | +| 2 | DEPENDENT SUBQUERY | m | ref | | idx_message_info | 122 | const | 1 | Using index condition; Using where | ++----+--------------------+-------+------+ -----+------------------------------------------+---------+-------+---------+ -----+ +``` + +去掉 exists 更改为 join,能够避免嵌套子查询,将执行时间从1.93秒降低为1毫秒。 + +``` +SELECT * +FROM my_neighbor n + INNER JOIN message_info m + ON n.id = m.neighbor_id + AND m.inuser = 'xxx' + LEFT JOIN my_neighbor_apply sra + ON n.id = sra.neighbor_id + AND sra.user_id = 'xxx' +WHERE n.topic_status < 4 + AND n.topic_type <> 5 +``` + +新的执行计划: + +``` ++----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+ +| 1 | SIMPLE | m | ref | | idx_message_info | 122 | const | 1 | Using index condition | +| 1 | SIMPLE | n | eq_ref | | PRIMARY | 122 | ighbor_id | 1 | Using where | +| 1 | SIMPLE | sra | ref | | idx_user_id | 123 | const | 1 | Using where | ++----+-------------+-------+--------+ -----+------------------------------------------+---------+ -----+------+ -----+ +``` + +## 6、条件下推 + +外部查询条件不能够下推到复杂的视图或子查询的情况有: + +1、聚合子查询; + +2、含有 LIMIT 的子查询; + +3、UNION 或 UNION ALL 子查询; + +4、输出字段中的子查询; + +如下面的语句,从执行计划可以看出其条件作用于聚合子查询之后: + +``` +SELECT * +FROM (SELECT target, + Count(*) + FROM operation + GROUP BY target) t +WHERE target = 'rm-xxxx' ++----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+ +| 1 | PRIMARY | | ref | | | 514 | const | 2 | Using where | +| 2 | DERIVED | operation | index | idx_4 | idx_4 | 519 | NULL | 20 | Using index | ++----+-------------+------------+-------+---------------+-------------+---------+-------+------+-------------+ +``` + +确定从语义上查询条件可以直接下推后,重写如下: + +``` +SELECT target, + Count(*) +FROM operation +WHERE target = 'rm-xxxx' +GROUP BY target +``` + +执行计划变为: + +``` ++----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+ +| 1 | SIMPLE | operation | ref | idx_4 | idx_4 | 514 | const | 1 | Using where; Using index | ++----+-------------+-----------+------+---------------+-------+---------+-------+------+--------------------+ +``` + +关于 MySQL 外部条件不能下推的详细解释说明请参考以前文章:MySQL · 性能优化 · 条件下推到物化表 http://mysql.taobao.org/monthly/2016/07/08 + +## 7、提前缩小范围 + +先上初始 SQL 语句: + +``` +SELECT * +FROM my_order o + LEFT JOIN my_userinfo u + ON o.uid = u.uid + LEFT JOIN my_productinfo p + ON o.pid = p.pid +WHERE ( o.display = 0 ) + AND ( o.ostaus = 1 ) +ORDER BY o.selltime DESC +LIMIT 0, 15 +``` + +该SQL语句原意是:先做一系列的左连接,然后排序取前15条记录。从执行计划也可以看出,最后一步估算排序记录数为90万,时间消耗为12秒。 + +``` ++----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+ +| 1 | SIMPLE | o | ALL | NULL | NULL | NULL | NULL | 909119 | Using where; Using temporary; Using filesort | +| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | o.uid | 1 | NULL | +| 1 | SIMPLE | p | ALL | PRIMARY | NULL | NULL | NULL | 6 | Using where; Using join buffer (Block Nested Loop) | ++----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+----------------------------------------------------+ +``` + +由于最后 WHERE 条件以及排序均针对最左主表,因此可以先对 my_order 排序提前缩小数据量再做左连接。SQL 重写后如下,执行时间缩小为1毫秒左右。 + +``` +SELECT * +FROM ( +SELECT * +FROM my_order o +WHERE ( o.display = 0 ) + AND ( o.ostaus = 1 ) +ORDER BY o.selltime DESC +LIMIT 0, 15 +) o + LEFT JOIN my_userinfo u + ON o.uid = u.uid + LEFT JOIN my_productinfo p + ON o.pid = p.pid +ORDER BY o.selltime DESC +limit 0, 15 +``` + +再检查执行计划:子查询物化后(select_type=DERIVED)参与 JOIN。虽然估算行扫描仍然为90万,但是利用了索引以及 LIMIT 子句后,实际执行时间变得很小。 + +``` ++----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+ +| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 15 | Using temporary; Using filesort | +| 1 | PRIMARY | u | eq_ref | PRIMARY | PRIMARY | 4 | o.uid | 1 | NULL | +| 1 | PRIMARY | p | ALL | PRIMARY | NULL | NULL | NULL | 6 | Using where; Using join buffer (Block Nested Loop) | +| 2 | DERIVED | o | index | NULL | idx_1 | 5 | NULL | 909112 | Using where | ++----+-------------+------------+--------+---------------+---------+---------+-------+--------+----------------------------------------------------+ +``` + +## 8、中间结果集下推 + +再来看下面这个已经初步优化过的例子(左连接中的主表优先作用查询条件): + +``` +SELECT a.*, + c.allocated +FROM ( + SELECT resourceid + FROM my_distribute d + WHERE isdelete = 0 + AND cusmanagercode = '1234567' + ORDER BY salecode limit 20) a +LEFT JOIN + ( + SELECT resourcesid, sum(ifnull(allocation, 0) * 12345) allocated + FROM my_resources + GROUP BY resourcesid) c +ON a.resourceid = c.resourcesid +``` + +那么该语句还存在其它问题吗?不难看出子查询 c 是全表聚合查询,在表数量特别大的情况下会导致整个语句的性能下降。 + +其实对于子查询 c,左连接最后结果集只关心能和主表 resourceid 能匹配的数据。因此我们可以重写语句如下,执行时间从原来的2秒下降到2毫秒。 + +``` +SELECT a.*, + c.allocated +FROM ( + SELECT resourceid + FROM my_distribute d + WHERE isdelete = 0 + AND cusmanagercode = '1234567' + ORDER BY salecode limit 20) a +LEFT JOIN + ( + SELECT resourcesid, sum(ifnull(allocation, 0) * 12345) allocated + FROM my_resources r, + ( + SELECT resourceid + FROM my_distribute d + WHERE isdelete = 0 + AND cusmanagercode = '1234567' + ORDER BY salecode limit 20) a + WHERE r.resourcesid = a.resourcesid + GROUP BY resourcesid) c +ON a.resourceid = c.resourcesid +``` + +但是子查询 a 在我们的SQL语句中出现了多次。这种写法不仅存在额外的开销,还使得整个语句显的繁杂。使用 WITH 语句再次重写: + +``` +WITH a AS +( + SELECT resourceid + FROM my_distribute d + WHERE isdelete = 0 + AND cusmanagercode = '1234567' + ORDER BY salecode limit 20) +SELECT a.*, + c.allocated +FROM a +LEFT JOIN + ( + SELECT resourcesid, sum(ifnull(allocation, 0) * 12345) allocated + FROM my_resources r, + a + WHERE r.resourcesid = a.resourcesid + GROUP BY resourcesid) c +ON a.resourceid = c.resourcesid +``` + +## 总结 + +数据库编译器产生执行计划,决定着SQL的实际执行方式。但是编译器只是尽力服务,所有数据库的编译器都不是尽善尽美的。 + +上述提到的多数场景,在其它数据库中也存在性能问题。了解数据库编译器的特性,才能避规其短处,写出高性能的SQL语句。 + +程序员在设计数据模型以及编写SQL语句时,要把算法的思想或意识带进来。 + +编写复杂SQL语句要养成使用 WITH 语句的习惯。简洁且思路清晰的SQL语句也能减小数据库的负担 。 + +> 来源:yq.aliyun.com/articles/72501 \ No newline at end of file diff --git a/docs/advance/excellent-article/8-interface-idempotent.md b/docs/advance/excellent-article/8-interface-idempotent.md new file mode 100644 index 0000000..ff3ae6a --- /dev/null +++ b/docs/advance/excellent-article/8-interface-idempotent.md @@ -0,0 +1,88 @@ +# 面试官:如何保证接口幂等性?一口气说了12种方法! + +大家好,我是大彬~ + +今天来聊聊接口幂等性。 + +什么是接口幂等性?如何保证接口幂等性? + +## 什么是接口幂等性? + +首先看看幂等性的概念: + +幂等性原本是数学上的概念,用在接口上就可以理解为:**同一个接口,多次发出同一个请求,必须保证操作只执行一次**。调用接口发生异常并且重复尝试时,总是会造成系统所无法承受的损失,所以必须阻止这种现象的发生。 + +比如下面这些情况,如果没有实现接口幂等性会有很严重的后果:支付接口,重复支付会导致多次扣钱 ;订单接口,同一个订单可能会多次创建。 + +## 为什么会产生接口幂等性问题? + +那么,什么情况下,会产生接口幂等性的问题呢? + +- 网络波动, 可能会引起重复请求 +- 用户重复操作,用户在操作时候可能会无意触发多次下单交易,甚至没有响应而有意触发多次交易应用 +- 使用了失效或超时重试机制(Nginx重试、RPC重试或业务层重试等) +- 页面重复刷新 +- 使用浏览器后退按钮重复之前的操作,导致重复提交表单 +- 使用浏览器历史记录重复提交表单 +- 浏览器重复的HTTP请求 +- 定时任务重复执行 +- 用户双击提交按钮 + +## 如何保证接口幂等性? + +那么最关键的来了,如何保证接口幂等性? + +解决办法分为两个方向,一个方向是客户端防止重复调用,一个是服务端进行校验。当然,客户端防止重复提交并不是绝对可靠的,优点是实现起来比较简单。 + +### **按钮只可操作一次** + +一般是提交后把按钮置灰或loding状态,消除用户因为重复点击而产生的重复记录,比如添加操作,由于点击两次而产生两条记录 + +### **token机制** + +功能上允许重复提交,但要保证重复提交不产生副作用,比如点击n次只产生一条记录,具体实现就是进入页面时申请一个token,然后后面所有的请求都带上这个token,后端根据token来避免重复请求。 + +![](http://img.dabin-coder.cn/image/接口幂等.png) + +### **使用Post/Redirect/Get模式** + +在提交后执行页面重定向,这就是所谓的Post-Redirect—Get(PRG)模式,简单来说就是当用户提交连表单后,跳转到一个重定向的信息页面,这样就避免用户按F5刷新导致的重复提交,而且也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退导致同样重复提交的问题。 + +### **在session存放特殊标志** + +在服务端,生成一个唯一的标识符,将它存入session,同时前端获取这个标识符的值将它写入表单的隐藏中,用于用户输入信息后点击一起提交,在服务器端,获取表单中隐藏字段的值,与session中的唯一标识符比较,相等说明是首次提交,就处理本次请求,然后将session中的唯一标识符移除,不相等则表示是重复提交,不再做处理。 + +### **使用唯一索引防止新增脏数据** + +利用数据库唯一索引机制,当数据重复时,插入数据库会抛出异常,保证不会出现脏数据。 + +### **乐观锁** + +如果更新已有数据,可以进行加锁更新,也可以设计表结构时使用乐观锁,通过version来做乐观锁,这样既能保证执行效率,又能保证幂等, 乐观锁的version版本在更新业务数据要自增 +update table set version = version + 1 where id = #{id} and version = #{version} +示例: 当有重复请求的时候,第一个请求会获取当前商品的version版本号,得到的version为1,紧接着由于第一个请求还没更新商品的version,第二个请求获取的version依然也是1, 这时候第一个请求操作更新的时候带上version并作为条件并且自增更新,这时候商品的version就会变成2,当第二个请求去操作更新的时候明显version不一致导致更新失败。 + +### **select + insert or update or delete** + +该方案就是操作之前先查询一下,符合要求再插入,该方案在没有并发的系统中可以解决幂等问题,在单JVM有并发的时候可以用JVM加锁来保证幂等性,在分布式环境它是无法保证幂等性,可以使用分布式来保证。 + +### **分布式锁** + +如果是分布式系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁。要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)。 + +### **状态机幂等** + +在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。注意:订单等单据类业务,存在很长的状态流转,一定要深刻理解状态机,对业务系统设计能力提高有很大帮助 。 + +### **防重表** + +以支付为例: 使用唯一主键去做防重表的唯一索引,比如使用订单号作为防重表的唯一索引,每一次请求都根据订单号向防重表中插入一条数据,插入成功说明可以处理后面的业务,当处理完业务逻辑之后删除防重表中的订单号数据,后续如果有重复请求,则会因为防重表唯一索引原因导致插入失败,直接返回操作失败,直到第一次请求返回结果,可以看出防重表作用就是加锁的功能。 +注: 最好结合状态机幂等先判断一下 + +### **缓冲队列** + +将请求都快速地接收下来后放入缓冲队列中,后续使用异步任务处理队列中的数据,过滤掉重复的请求,该解决方案优点是同步处理改成异步处理、高吞吐量,缺点则是不能及时地返回请求结果,需要后续轮询得处理结果。 + +### **全局唯一号** + +比如通过source来源 + 唯一序列号传入给后端,后端来判断请求是否重复,在并发时只能处理一个请求,其他相同并发请求要么返回请求重复,要么等待前面请求执行完成后再执行。 \ No newline at end of file diff --git a/docs/advance/excellent-article/9-jvm-optimize-param.md b/docs/advance/excellent-article/9-jvm-optimize-param.md new file mode 100644 index 0000000..01e0774 --- /dev/null +++ b/docs/advance/excellent-article/9-jvm-optimize-param.md @@ -0,0 +1,242 @@ +# 美团面试:熟悉哪些JVM调优参数? + +今天来熟悉一下,关于`JVM`调优常用的一些参数。 + +X或者XX开头的都是非标准化参数 + +![](http://img.dabin-coder.cn/image/jvm参数1.png) + +意思就是说标准化参数不会变,非标准化参数可能在每个`JDK`版本中有所变化,但是就目前来看X开头的非标准化的参数改变的也是非常少。 + +``` +格式:-XX:[+-] 表示启用或者禁用name属性。 +例子:-XX:+UseG1GC(表示启用G1垃圾收集器) +``` + +`-XX:+PrintCommandLineFlags`查看当前`JVM`设置过的相关参数: + +![](http://img.dabin-coder.cn/image/jvm参数2.png) + +## JVM参数分类 + +根据`JVM`参数开头可以区分参数类型,共三类:“`-`”、“`-X`”、“`-XX`”, + +标准参数(-):所有的JVM实现都必须实现这些参数的功能,而且向后兼容; + +例子:`-verbose:class`,`-verbose:gc`,`-verbose:jni……` + +非标准参数(-X):默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容; + +例子:`Xms20m`,`-Xmx20m`,`-Xmn20m`,`-Xss128k……` + +非Stable参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用; + +例子:`-XX:+PrintGCDetails`,`-XX:-UseParallelGC`,`-XX:+PrintGCTimeStamps……` + +## 堆参数设置 + +``` +-Xms` 初始堆大小,ms是memory start的简称 ,等价于`-XX:InitialHeapSize``-Xmx` 最大堆大小,mx是memory max的简称 ,等价于参数`-XX:MaxHeapSize +``` + +> 注意:在通常情况下,服务器项目在运行过程中,堆空间会不断的收缩与扩张,势必会造成不必要的系统压力。 +> +> 所以在生产环境中,`JVM`的`Xms`和`Xmx`要设置成大小一样的,能够避免`GC`在调整堆大小带来的不必要的压力。 + +`-XX:NewSize=n` 设置年轻代大小`-XX:NewRatio=n` 设置年轻代和年老代的比值。 + +如:`-XX:NewRatio=3`,表示年轻代与年老代比值为`1:3`,年轻代占整个年轻代年老代和的1/4,`默认新生代和老年代的比例=1:2`。`-XX:SurvivorRatio=n` 年轻代中Eden区与两个Survivor区的比值。 + +注意Survivor区有两个,默认是8,表示:`Eden:S0:S1=8:1:1` + +如:`-XX:SurvivorRatio=3`,表示`Eden:Survivor`=3:2,一个Survivor区占整个年轻代的1/5。 + +## 元空间参数 + +**-XX:MetaspaceSize**:`Metaspace` 空间初始大小,如果不设置的话,默认是20.79M,这个初始大小是触发首次 `Metaspace Full GC`的阈值。 + +例如:`-XX:MetaspaceSize=256M` + +**-XX:MaxMetaspaceSize**:`Metaspace` 最大值,默认不限制大小,但是线上环境建议设置。 + +例如:`-XX:MaxMetaspaceSize=256M` + +**-XX:MinMetaspaceFreeRatio**:最小空闲比,当 `Metaspace` 发生 GC 后,会计算 `Metaspace` 的空闲比,如果空闲比(空闲空间/当前 `Metaspace` 大小)小于此值,就会触发 `Metaspace` 扩容。默认值是 40 ,也就是 40%,例如 -XX:MinMetaspaceFreeRatio=40 + +**-XX:MaxMetaspaceFreeRatio**:最大空闲比,当 `Metaspace`发生 GC 后,会计算 `Metaspace` 的空闲比,如果空闲比(空闲空间/当前 Metaspace 大小)大于此值,就会触发 `Metaspace` 释放空间。默认值是 70 ,也就是 70%,例如 -`XX:MaxMetaspaceFreeRatio=70` + +> 建议将 `MetaspaceSize` 和 `MaxMetaspaceSize`设置为同样大小,避免频繁扩容。 + +## 栈参数设置 + +**-Xss**:栈空间大小,栈是线程独占的,所以是一个线程使用栈空间的大小。 + +例如:`-Xss256K`,如果不设置此参数,默认值是`1M`,一般来讲设置成 `256K` 就足够了。 + +## 收集器参数设置 + +Serial垃圾收集器(新生代) + +> 开启:-XX:+UseSerialGC 关闭:-XX:-UseSerialGC //新生代使用Serial 老年代则使用SerialOld + +ParNew垃圾收集器(新生代) + +> 开启 -XX:+UseParNewGC 关闭 -XX:-UseParNewGC //新生代使用功能ParNew 老年代则使用功能CMS + +Parallel Scavenge收集器(新生代) + +> 开启 -XX:+UseParallelOldGC 关闭 -XX:-UseParallelOldGC //新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器 + +ParallelOl垃圾收集器(老年代) + +> 开启 -XX:+UseParallelGC 关闭 -XX:-UseParallelGC //新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器 + +CMS垃圾收集器(老年代) + +> 开启 -XX:+UseConcMarkSweepGC 关闭 -XX:-UseConcMarkSweepGC + +G1垃圾收集器 + +> 开启 -XX:+UseG1GC 关闭 -XX:-UseG1GC + +## GC策略参数配置 + +GC停顿时间,垃圾收集器会尝试用各种手段达到这个时间,比如减小年轻代 + +> -XX:MaxGCPauseMillis + +堆占用了多少比例的时候触发GC,就即触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45% + +> -XX:InitiatingHeapOccupancyPercent=n + +新生代可容纳的最大对象,大于则直接会分配到老年代,0代表没有限制。 + +> -XX:PretenureSizeThreshold=1000000 // + +进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,默认值7 + +> -XX:InitialTenuringThreshol=7 + +升级老年代年龄,最大值15 + +> -XX:MaxTenuringThreshold + +GC并行执行线程数 + +> -XX:ParallelGCThreads=16 + +禁用 System.gc(),由于该方法默认会触发 FGC,并且忽略参数中的 UseG1GC 和 UseConcMarkSweepGC,因此必要时可以禁用该方法。 + +> -XX:-+DisableExplicitGC + +设置吞吐量大小,默认99 + +> XX:GCTimeRatio + +打开自适应策略,各个区域的比率,晋升老年代的年龄等参数会被自动调整。以达到吞吐量,停顿时间的平衡点。 + +> XX:UseAdaptiveSizePolicy + +设置GC时间占用程序运行时间的百分比 + +> GCTimeRatio + +## Dump异常快照 + +``` +-XX:+HeapDumpOnOutOfMemoryError +-XX:HeapDumpPath +``` + +堆内存出现`OOM`的概率是所有内存耗尽异常中最高的,出错时的堆内信息对解决问题非常有帮助。 + +所以给`JVM`设置这个参数(`-XX:+HeapDumpOnOutOfMemoryError`),让`JVM`遇到`OOM`异常时能输出堆内信息,并通过(`-XX:+HeapDumpPath`)参数设置堆内存溢出快照输出的文件地址。 + +这对于特别是对相隔数月才出现的`OOM`异常尤为重要。 + +``` +-Xms10M -Xmx10M -Xmn2M -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError +-XX:HeapDumpPath=D:\study\log_hprof\gc.hprof +-XX:OnOutOfMemoryError +``` + +表示发生`OOM后`,运行`jconsole.exe`程序。 + +这里可以不用加“”,因为`jconsole.exe`路径Program Files含有空格。利用这个参数,我们可以在系统`OOM`后,自定义一个脚本,可以用来发送邮件告警信息,可以用来重启系统等等。 + +``` +-XX:OnOutOfMemoryError="C:\Program Files\Java\jdk1.8.0_151\bin\jconsole.exe" +``` + +## 8G内存的服务器该如何设置 + +``` +java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0 +``` + +`-Xmx3500m` 设置`JVM`最大可用内存为3550M。 + +`-Xms3500m` 设置`JVM``初始`内存为`3550m`。此值可以设置与`-Xmx`相同,以避免每次垃圾回收完成后JVM重新分配内存。`-Xmn2g` 设置年轻代大小为`2G`。 + +> 整个堆大小=年轻代大小 + 年老代大小 + 方法区大小 + +`-Xss128k` 设置每个线程的堆栈大小。 + +`JDK1.5`以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。 + +`-XX:NewRatio=4` 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 。 + +`-XX:SurvivorRatio=4` 设置年轻代中Eden区与Survivor区的大小比值。 + +设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6 `-XX:MaxPermSize=16m` 设置持久代大小为16m。 + +`-XX:MaxTenuringThreshold=0` 设置垃圾最大年龄。 + +如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代即被回收的概论。 + +## 项目中,GC日志配置 + +比如,我们启动一个user-service项目: + +``` + java + -XX:+PrintGCDetails -XX:+PrintGCDateStamps + -XX:+UseGCLogFileRotation + -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 + -XX:GCLogFileSize=20M + -Xloggc:/opt/user-service-gc-%t.log + -jar user-service-1.0-SNAPSHOT.jar +``` + +参数解释: + +``` + -Xloggc:/opt/app/ard-user/user-service-gc-%t.log 设置日志目录和日志名称 + -XX:+UseGCLogFileRotation 开启滚动生成日志 + -XX:NumberOfGCLogFiles=5 滚动GC日志文件数,默认0,不滚动 + -XX:GCLogFileSize=20M GC文件滚动大小,需开启UseGCLogFileRotation + -XX:+PrintGCDetails 开启记录GC日志详细信息(包括GC类型、各个操作使用的时间),并且在程序运行结束打印出JVM的内存占用情况 + -XX:+ PrintGCDateStamps 记录系统的GC时间 + -XX:+PrintGCCause 产生GC的原因(默认开启) +``` + +## 项目中没用过怎么办? + +对于很多没用过的人来说,面试官问项目中这些参数是怎么用?此时,很容易选择妥协,傻傻的回答**没用过**。 + +偷偷的告诉你,很多面试官也没有用过。 + +另外,你可以自己搞个小项目,把`JVM`参数设置小点,使用测试工具`JMeter`,多线程测试一下。 + +在代码里可以自己编造以下问题: + +> 内存溢出 +> +> 内存泄漏 +> +> 栈溢出 + +然后使用`JVM`参数进行调优,或者通过`JVM`工具和相关命令找到问题,然后解决问题。 + +> 自己一定要动手,别人永远是别人的,自己体会了自己经历了,那才是自己的。 + diff --git a/docs/advance/excellent-article/README.md b/docs/advance/excellent-article/README.md new file mode 100644 index 0000000..871d2b0 --- /dev/null +++ b/docs/advance/excellent-article/README.md @@ -0,0 +1,19 @@ + +## 优质文章汇总 + +- [Redis如何实现库存扣减操作和防止被超卖?](./1-redis-stock-minus.md) +- [@Transactional事务注解详解](./2-spring-transaction.md) +- [SpringBoot自动装配原理](./3-springboot-auto-assembly.md) +- [干掉“重复代码”的技巧有哪些](./4-remove-duplicate-code.md) +- [一次简单的 *JVM* 调优,拿去写到简历里](./5-jvm-optimize.md) +- [Spring为何需要三级缓存解决循环依赖,而不是二级缓存?](./6-spring-three-cache.md) +- [8种最坑SQL语法](./7-sql-optimize.md) +- [面试官:如何保证接口幂等性?一口气说了12种方法!](./8-interface-idempotent.md) +- [美团面试:熟悉哪些JVM调优参数?](./9-jvm-optimize-param.md) +- [大文件上传时如何做到秒传?](./10-file-upload.md) +- [8种架构模式](./11-8-architect-pattern.md) +- [MySQL最大建议行数 2000w,靠谱吗?](./12-mysql-table-max-rows.md) +- [order by是怎么工作的?](./13-order-by-work.md) +- [架构的演进](./14-architect-forward.md) +- [有了HTTP,为啥还要用RPC](./15-http-vs-rpc.md) +- [什么是JWT](./16-what-is-jwt.md) \ No newline at end of file diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" b/docs/advance/system-design/1-scan-code-login.md similarity index 51% rename from "\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" rename to docs/advance/system-design/1-scan-code-login.md index 9b2fa63..71dcfd9 100644 --- "a/\347\263\273\347\273\237\350\256\276\350\256\241/\346\211\253\347\240\201\347\231\273\345\275\225\345\216\237\347\220\206.md" +++ b/docs/advance/system-design/1-scan-code-login.md @@ -1,22 +1,20 @@ -本期是【**大厂面试**】系列文章的第**31**期 +--- +sidebar: heading +--- -回复【**手册**】获取大彬精心整理的**大厂面试手册**。 +> 回复【**手册**】获取大彬精心整理的**大厂面试手册**。 -## 面试开始 +## 扫码登录原理 -旁白:通过微信聊天方式模拟现场面试 +今天给大家介绍下扫码登录功能是怎么设计的。 -**面试官**:**看你简历上写了做过扫码登录的功能** +扫码登录功能主要分为三个阶段:**待扫描、已扫描待确认、已确认**。 -**面试官**:**详细介绍下怎么设计的?** +整体流程图如下图。 -大彬:嗯,扫码登录功能主要分为三个阶段:**待扫描、已扫描待确认、已确认**。 +![](http://img.dabin-coder.cn/image/整个流程.png) -大彬:整体流程图如下图。 - -![](E:\b站\视频素材\图片\二维码扫描\整个流程.png) - -大彬:下面分阶段来看看设计原理。 +下面分阶段来看看设计原理。 **1、待扫描阶段** @@ -32,7 +30,7 @@ 这个阶段的交互过程如下图所示。 -![](E:\b站\视频素材\图片\二维码扫描\第一阶段.png) +![](http://img.dabin-coder.cn/image/第一阶段.png) **2、已扫描待确认阶段** @@ -46,13 +44,13 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 PC 端的二维码更新为已扫描,请在手机端确认。 -**面试官**:**打断一下,这里为什么要有手机端确认的操作?** +**这里为什么要有手机端确认的操作?** -大彬:假设没有确认这个环节,很容易就会被坏人拦截token去冒充登录。所以二维码扫描一定要有这个确认的页面,让用户去确认是否进行登录。 +假设没有确认这个环节,很容易就会被坏人拦截token去冒充登录。所以二维码扫描一定要有这个确认的页面,让用户去确认是否进行登录。 -大彬:另外,二维码扫描确认之后,再往用户app或手机等发送登录提醒的通知,告知如果不是本人登录的,则建议用户立即修改密码。 +另外,二维码扫描确认之后,再往用户app或手机等发送登录提醒的通知,告知如果不是本人登录的,则建议用户立即修改密码。 -大彬:这个阶段是交互过程如下图所示。 +这个阶段是交互过程如下图所示。 ![](http://img.dabin-coder.cn/image/20220411002823.png) @@ -68,18 +66,9 @@ PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 P ![](http://img.dabin-coder.cn/image/20220411002832.png) -大彬:以上就是整个扫码登录功能的详细设计! - -**面试官**:**点赞!** - - +以上就是整个扫码登录功能的详细设计! -## 点关注,不迷路 -大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 -希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ -后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 -![](http://img.dabin-coder.cn/image/公众号.jpg) diff --git a/docs/advance/system-design/2-order-timeout-auto-cancel.md b/docs/advance/system-design/2-order-timeout-auto-cancel.md new file mode 100644 index 0000000..9269d0d --- /dev/null +++ b/docs/advance/system-design/2-order-timeout-auto-cancel.md @@ -0,0 +1,616 @@ +--- +sidebar: heading +--- + +# 订单30分钟未支付自动取消怎么实现? + +**目录** + +- 了解需求 +- 方案 1:数据库轮询 +- 方案 2:JDK 的延迟队列 +- 方案 3:时间轮算法 +- 方案 4:redis 缓存 +- 方案 5:使用消息队列 + +## 了解需求 + +在开发中,往往会遇到一些关于延时任务的需求。 + +例如 + +- 生成订单 30 分钟未支付,则自动取消 +- 生成订单 60 秒后,给用户发短信 + +对上述的任务,我们给一个专业的名字来形容,那就是延时任务。那么这里就会产生一个问题,这个延时任务和定时任务的区别究竟在哪里呢?一共有如下几点区别 + +定时任务有明确的触发时间,延时任务没有 + +定时任务有执行周期,而延时任务在某事件触发后一段时间内执行,没有执行周期 + +定时任务一般执行的是批处理操作是多个任务,而延时任务一般是单个任务 + +下面,我们以判断订单是否超时为例,进行方案分析 + +## 方案 1:数据库轮询 + +### 思路 + +该方案通常是在小型项目中使用,即通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行 update 或 delete 等操作 + +### 实现 + +可以用 quartz 来实现的,简单介绍一下 + +maven 项目引入一个依赖如下所示 + +``` + + org.quartz-scheduler + quartz + 2.2.2 + +``` + +调用 Demo 类 MyJob 如下所示 + +``` +package com.rjzheng.delay1; + +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; + +public class MyJob implements Job { + + public void execute(JobExecutionContext context) throws JobExecutionException { + System.out.println("要去数据库扫描啦。。。"); + } + + public static void main(String[] args) throws Exception { + // 创建任务 + JobDetail jobDetail = JobBuilder.newJob(MyJob.class) + .withIdentity("job1", "group1").build(); + // 创建触发器 每3秒钟执行一次 + Trigger trigger = TriggerBuilder + .newTrigger() + .withIdentity("trigger1", "group3") + .withSchedule( + SimpleScheduleBuilder + .simpleSchedule() + .withIntervalInSeconds(3). + repeatForever()) + .build(); + Scheduler scheduler = new StdSchedulerFactory().getScheduler(); + // 将任务及其触发器放入调度器 + scheduler.scheduleJob(jobDetail, trigger); + // 调度器开始调度任务 + scheduler.start(); + } + +} +``` + +运行代码,可发现每隔 3 秒,输出如下 + +``` +要去数据库扫描啦。。。 +``` + +### 优点 + +简单易行,支持集群操作 + +### 缺点 + +- 对服务器内存消耗大 +- 存在延迟,比如你每隔 3 分钟扫描一次,那最坏的延迟时间就是 3 分钟 +- 假设你的订单有几千万条,每隔几分钟这样扫描一次,数据库损耗极大 + +## 方案 2:JDK 的延迟队列 + +### 思路 + +该方案是利用 JDK 自带的 DelayQueue 来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入 DelayQueue 中的对象,是必须实现 Delayed 接口的。 + +DelayedQueue 实现工作流程如下图所示 + +![](http://img.dabin-coder.cn/image/订单取消1.png) + +其中 Poll():获取并移除队列的超时元素,没有则返回空 + +take():获取并移除队列的超时元素,如果没有则 wait 当前线程,直到有元素满足超时条件,返回结果。 + +### 实现 + +定义一个类 OrderDelay 实现 Delayed,代码如下 + +``` +package com.rjzheng.delay2; + +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +public class OrderDelay implements Delayed { + + private String orderId; + + private long timeout; + + OrderDelay(String orderId, long timeout) { + this.orderId = orderId; + this.timeout = timeout + System.nanoTime(); + } + + public int compareTo(Delayed other) { + if (other == this) { + return 0; + } + OrderDelay t = (OrderDelay) other; + long d = (getDelay(TimeUnit.NANOSECONDS) - t.getDelay(TimeUnit.NANOSECONDS)); + return (d == 0) ? 0 : ((d < 0) ? -1 : 1); + } + + // 返回距离你自定义的超时时间还有多少 + public long getDelay(TimeUnit unit) { + return unit.convert(timeout - System.nanoTime(), TimeUnit.NANOSECONDS); + } + + void print() { + System.out.println(orderId + "编号的订单要删除啦。。。。"); + } + +} +``` + +运行的测试 Demo 为,我们设定延迟时间为 3 秒 + +``` +package com.rjzheng.delay2; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.TimeUnit; + +public class DelayQueueDemo { + + public static void main(String[] args) { + List list = new ArrayList(); + list.add("00000001"); + list.add("00000002"); + list.add("00000003"); + list.add("00000004"); + list.add("00000005"); + + DelayQueue queue = newDelayQueue < OrderDelay > (); + long start = System.currentTimeMillis(); + for (int i = 0; i < 5; i++) { + //延迟三秒取出 + queue.put(new OrderDelay(list.get(i), TimeUnit.NANOSECONDS.convert(3, TimeUnit.SECONDS))); + try { + queue.take().print(); + System.out.println("After " + (System.currentTimeMillis() - start) + " MilliSeconds"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + +} +``` + +输出如下 + +``` +00000001编号的订单要删除啦。。。。 +After 3003 MilliSeconds +00000002编号的订单要删除啦。。。。 +After 6006 MilliSeconds +00000003编号的订单要删除啦。。。。 +After 9006 MilliSeconds +00000004编号的订单要删除啦。。。。 +After 12008 MilliSeconds +00000005编号的订单要删除啦。。。。 +After 15009 MilliSeconds +``` + +可以看到都是延迟 3 秒,订单被删除 + +### 优点 + +效率高,任务触发时间延迟低。 + +### 缺点 + +- 服务器重启后,数据全部消失,怕宕机 +- 集群扩展相当麻烦 +- 因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常 +- 代码复杂度较高 + +## 方案 3:时间轮算法 + +### 思路 + +先上一张时间轮的图(这图到处都是啦) + +![](http://img.dabin-coder.cn/image/订单取消2.png) + +时间轮算法可以类比于时钟,如上图箭头(指针)按某一个方向按固定频率轮动,每一次跳动称为一个 tick。这样可以看出定时轮由个 3 个重要的属性参数,ticksPerWheel(一轮的 tick 数),tickDuration(一个 tick 的持续时间)以及 timeUnit(时间单位),例如当 ticksPerWheel=60,tickDuration=1,timeUnit=秒,这就和现实中的始终的秒针走动完全类似了。 + +如果当前指针指在 1 上面,我有一个任务需要 4 秒以后执行,那么这个执行的线程回调或者消息将会被放在 5 上。那如果需要在 20 秒之后执行怎么办,由于这个环形结构槽数只到 8,如果要 20 秒,指针需要多转 2 圈。位置是在 2 圈之后的 5 上面(20 % 8 + 1) + +### 实现 + +我们用 Netty 的 HashedWheelTimer 来实现 + +给 Pom 加上下面的依赖 + +``` + + io.netty + netty-all + 4.1.24.Final + +``` + +测试代码 HashedWheelTimerTest 如下所示 + +``` +package com.rjzheng.delay3; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; + +import java.util.concurrent.TimeUnit; + +public class HashedWheelTimerTest { + + static class MyTimerTask implements TimerTask { + + boolean flag; + + public MyTimerTask(boolean flag) { + this.flag = flag; + } + + public void run(Timeout timeout) throws Exception { + System.out.println("要去数据库删除订单了。。。。"); + this.flag = false; + } + } + + public static void main(String[] argv) { + MyTimerTask timerTask = new MyTimerTask(true); + Timer timer = new HashedWheelTimer(); + timer.newTimeout(timerTask, 5, TimeUnit.SECONDS); + int i = 1; + while (timerTask.flag) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(i + "秒过去了"); + i++; + } + } + +} +``` + +输出如下 + +``` +1秒过去了 +2秒过去了 +3秒过去了 +4秒过去了 +5秒过去了 +要去数据库删除订单了。。。。 +6秒过去了 +``` + +### 优点 + +效率高,任务触发时间延迟时间比 delayQueue 低,代码复杂度比 delayQueue 低。 + +### 缺点 + +- 服务器重启后,数据全部消失,怕宕机 +- 集群扩展相当麻烦 +- 因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常 + +## 方案 4:redis 缓存 + +### 思路一 + +利用 redis 的 zset,zset 是一个有序集合,每一个元素(member)都关联了一个 score,通过 score 排序来取集合中的值 + +添加元素:ZADD key score member [[score member][score member] …] + +按顺序查询元素:ZRANGE key start stop [WITHSCORES] + +查询元素 score:ZSCORE key member + +移除元素:ZREM key member [member …] + +测试如下 + +``` +添加单个元素 +redis> ZADD page_rank 10 google.com +(integer) 1 + +添加多个元素 +redis> ZADD page_rank 9 baidu.com 8 bing.com +(integer) 2 + +redis> ZRANGE page_rank 0 -1 WITHSCORES +1) "bing.com" +2) "8" +3) "baidu.com" +4) "9" +5) "google.com" +6) "10" + +查询元素的score值 +redis> ZSCORE page_rank bing.com +"8" + +移除单个元素 +redis> ZREM page_rank google.com +(integer) 1 + +redis> ZRANGE page_rank 0 -1 WITHSCORES +1) "bing.com" +2) "8" +3) "baidu.com" +4) "9" +``` + +那么如何实现呢?我们将订单超时时间戳与订单号分别设置为 score 和 member,系统扫描第一个元素判断是否超时,具体如下图所示 + +![](http://img.dabin-coder.cn/image/订单取消3.png) + +### 实现一 + +``` +package com.rjzheng.delay4; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.Tuple; + +import java.util.Calendar; +import java.util.Set; + +public class AppTest { + + private static final String ADDR = "127.0.0.1"; + + private static final int PORT = 6379; + + private static JedisPool jedisPool = new JedisPool(ADDR, PORT); + + public static Jedis getJedis() { + return jedisPool.getResource(); + } + + //生产者,生成5个订单放进去 + public void productionDelayMessage() { + for (int i = 0; i < 5; i++) { + //延迟3秒 + Calendar cal1 = Calendar.getInstance(); + cal1.add(Calendar.SECOND, 3); + int second3later = (int) (cal1.getTimeInMillis() / 1000); + AppTest.getJedis().zadd("OrderId", second3later, "OID0000001" + i); + System.out.println(System.currentTimeMillis() + "ms:redis生成了一个订单任务:订单ID为" + "OID0000001" + i); + } + } + + //消费者,取订单 + + public void consumerDelayMessage() { + Jedis jedis = AppTest.getJedis(); + while (true) { + Set items = jedis.zrangeWithScores("OrderId", 0, 1); + if (items == null || items.isEmpty()) { + System.out.println("当前没有等待的任务"); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + continue; + } + int score = (int) ((Tuple) items.toArray()[0]).getScore(); + Calendar cal = Calendar.getInstance(); + int nowSecond = (int) (cal.getTimeInMillis() / 1000); + if (nowSecond >= score) { + String orderId = ((Tuple) items.toArray()[0]).getElement(); + jedis.zrem("OrderId", orderId); + System.out.println(System.currentTimeMillis() + "ms:redis消费了一个任务:消费的订单OrderId为" + orderId); + } + } + } + + public static void main(String[] args) { + AppTest appTest = new AppTest(); + appTest.productionDelayMessage(); + appTest.consumerDelayMessage(); + } + +} +``` + +此时对应输出如下 + +![](http://img.dabin-coder.cn/image/订单取消4.png) + +可以看到,几乎都是 3 秒之后,消费订单。 + +然而,这一版存在一个致命的硬伤,在高并发条件下,多消费者会取到同一个订单号,我们上测试代码 ThreadTest + +``` +package com.rjzheng.delay4; + +import java.util.concurrent.CountDownLatch; + +public class ThreadTest { + + private static final int threadNum = 10; + private static CountDownLatch cdl = newCountDownLatch(threadNum); + + static class DelayMessage implements Runnable { + public void run() { + try { + cdl.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + AppTest appTest = new AppTest(); + appTest.consumerDelayMessage(); + } + } + + public static void main(String[] args) { + AppTest appTest = new AppTest(); + appTest.productionDelayMessage(); + for (int i = 0; i < threadNum; i++) { + new Thread(new DelayMessage()).start(); + cdl.countDown(); + } + } + +} +``` + +输出如下所示 + +![](http://img.dabin-coder.cn/image/订单取消5.png) + +显然,出现了多个线程消费同一个资源的情况。 + +### 解决方案 + +(1)用分布式锁,但是用分布式锁,性能下降了,该方案不细说。 + +(2)对 ZREM 的返回值进行判断,只有大于 0 的时候,才消费数据,于是将 consumerDelayMessage()方法里的 + +``` +if(nowSecond >= score){ + String orderId = ((Tuple)items.toArray()[0]).getElement(); + jedis.zrem("OrderId", orderId); + System.out.println(System.currentTimeMillis()+"ms:redis消费了一个任务:消费的订单OrderId为"+orderId); +} +``` + +修改为 + +``` +if (nowSecond >= score) { + String orderId = ((Tuple) items.toArray()[0]).getElement(); + Long num = jedis.zrem("OrderId", orderId); + if (num != null && num > 0) { + System.out.println(System.currentTimeMillis() + "ms:redis消费了一个任务:消费的订单OrderId为" + orderId); + } +} +``` + +在这种修改后,重新运行 ThreadTest 类,发现输出正常了 + +### 思路二 + +该方案使用 redis 的 Keyspace Notifications,中文翻译就是键空间机制,就是利用该机制可以在 key 失效之后,提供一个回调,实际上是 redis 会给客户端发送一个消息。是需要 redis 版本 2.8 以上。 + +### 实现二 + +在 redis.conf 中,加入一条配置 + +notify-keyspace-events Ex + +运行代码如下 + +``` +package com.rjzheng.delay5; + +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPubSub; + +public class RedisTest { + + private static final String ADDR = "127.0.0.1"; + private static final int PORT = 6379; + private static JedisPool jedis = new JedisPool(ADDR, PORT); + private static RedisSub sub = new RedisSub(); + + public static void init() { + new Thread(new Runnable() { + public void run() { + jedis.getResource().subscribe(sub, "__keyevent@0__:expired"); + } + }).start(); + } + + public static void main(String[] args) throws InterruptedException { + init(); + for (int i = 0; i < 10; i++) { + String orderId = "OID000000" + i; + jedis.getResource().setex(orderId, 3, orderId); + System.out.println(System.currentTimeMillis() + "ms:" + orderId + "订单生成"); + } + } + + static class RedisSub extends JedisPubSub { + @Override + public void onMessage(String channel, String message) { + System.out.println(System.currentTimeMillis() + "ms:" + message + "订单取消"); + + } + } +} +``` + +输出如下 + +![](http://img.dabin-coder.cn/image/订单取消6.png) + +可以明显看到 3 秒过后,订单取消了 + +ps:redis 的 pub/sub 机制存在一个硬伤,官网内容如下 + +原:Because Redis Pub/Sub is fire and forget currently there is no way to use this feature if your application demands reliable notification of events, that is, if your Pub/Sub client disconnects, and reconnects later, all the events delivered during the time the client was disconnected are lost. + +翻: Redis 的发布/订阅目前是即发即弃(fire and forget)模式的,因此无法实现事件的可靠通知。也就是说,如果发布/订阅的客户端断链之后又重连,则在客户端断链期间的所有事件都丢失了。因此,方案二不是太推荐。当然,如果你对可靠性要求不高,可以使用。 + +### 优点 + +(1) 由于使用 Redis 作为消息通道,消息都存储在 Redis 中。如果发送程序或者任务处理程序挂了,重启之后,还有重新处理数据的可能性。 + +(2) 做集群扩展相当方便 + +(3) 时间准确度高 + +### 缺点 + +需要额外进行 redis 维护 + +## 方案 5:使用消息队列 + +### 思路 + +我们可以采用 rabbitMQ 的延时队列。RabbitMQ 具有以下两个特性,可以实现延迟队列 + +RabbitMQ 可以针对 Queue 和 Message 设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为 dead letter + +lRabbitMQ 的 Queue 可以配置 x-dead-letter-exchange 和 x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了 deadletter,则按照这两个参数重新路由。结合以上两个特性,就可以模拟出延迟消息的功能,具体的,我改天再写一篇文章,这里再讲下去,篇幅太长。 + +### 优点 + +高效,可以利用 rabbitmq 的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。 + +### 缺点 + +本身的易用度要依赖于 rabbitMq 的运维.因为要引用 rabbitMq,所以复杂度和成本变高。 \ No newline at end of file diff --git a/docs/advance/system-design/3-file-send.md b/docs/advance/system-design/3-file-send.md new file mode 100644 index 0000000..181e862 --- /dev/null +++ b/docs/advance/system-design/3-file-send.md @@ -0,0 +1,17 @@ +--- +sidebar: heading +--- + +## 如何把一个文件较快的发送到100w个服务器? + +可以采用p2p网络形式,比如树状形式,单个节点既可以从其他节点接收服务又可以向其他节点提供服务。 + +不过,树状结构会有什么问题呢? + +第一,如果树上的某一个节点坏掉了,那么从这个节点往下的所有服务器全部接收不到文件。 + +第二,如果树中的某条路径,因为网络因素等原因,传递速度比较慢,导致传递时间比较长,这样会使传递效率退化。 + +改进的方案如下: + +可以使用**连通图**。100W台服务器相当于有100W个节点的连通图。我们可以在图里生成多颗不同的生成树,在进行数据下发时,同时按照多颗不同的树去传递数据。这样就可以避免某个中间节点宕机,影响到后续的节点。同时这种传递方法实际上是一种依据时间的广度优先遍历,可以避免某条路径过长造成的效率低下。 diff --git "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" b/docs/advance/system-design/3-short-url.md similarity index 61% rename from "\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" rename to docs/advance/system-design/3-short-url.md index 7b0003c..484c646 100644 --- "a/\347\263\273\347\273\237\350\256\276\350\256\241/\347\263\273\347\273\237\350\256\276\350\256\241.md" +++ b/docs/advance/system-design/3-short-url.md @@ -1,62 +1,8 @@ -# 超卖问题 +--- +sidebar: heading +--- -先到数据库查询库存,在减库存。不是原子操作,会有超卖问题。 -通过加排他锁解决该问题。 - -- 开始事务。 -- 查询库存,并显式的设置排他锁:SELECT * FROM table_name WHERE … FOR UPDATE -- 生成订单。 -- 去库存,update会隐式的设置排他锁:UPDATE products SET count=count-1 WHERE id=1 -- commit,释放锁。 - -也可以通过乐观锁实现。使用版本号实现乐观锁。 - -假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。 - -然后直接update的时候,只有其中一个先update了,同时更新了版本号。 - -那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了,则放弃此次update,重试直到成功。 - -```mysql -select version from goods WHERE id= 1001 -update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version); -``` - -# 秒杀系统 - -## 系统的特点 - -- 高性能:秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键 -- 一致性:秒杀商品减库存的实现方式同样关键,有限数量的商品在同一时刻被很多倍的请求同时来减库存,在大并发更新的过程中都要保证数据的准确性。 -- 高可用:秒杀时会在一瞬间涌入大量的流量,为了避免系统宕机,保证高可用,需要做好流量限制 - -## 优化思路 - -- 后端优化:将请求尽量拦截在系统上游 - - 限流:屏蔽掉无用的流量,允许少部分流量走后端。假设现在库存为 10,有 1000 个购买请求,最终只有 10 个可以成功,99% 的请求都是无效请求 - - 削峰:秒杀请求在时间上高度集中于某一个时间点,瞬时流量容易压垮系统,因此需要对流量进行削峰处理,缓冲瞬时流量,尽量让服务器对资源进行平缓处理 - - 异步:将同步请求转换为异步请求,来提高并发量,本质也是削峰处理。在真实的秒杀场景中,有三个核心流程:而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。 - - 利用缓存:创建订单时,每次都需要先查询判断库存,只有少部分成功的请求才会创建订单,因此可以将商品信息放在缓存中,减少数据库查询 - - 负载均衡:利用 Nginx 做负载均衡,使用多个服务器并发处理请求,减少单个服务器压力 -- 前端优化: - - 限流:使用验证码等,来分散用户的请求 - - 禁止重复提交:限定每个用户发起一次秒杀后,需等待才可以发起另一次请求,从而减少用户的重复请求 - - 本地标记:用户成功秒杀到商品后,将提交按钮置灰,禁止用户再次提交请求 - - 动静分离:使用CDN缓存静态页面资源,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率 -- 防作弊优化: - - 隐藏秒杀接口:如果秒杀地址直接暴露,在秒杀开始前可能会被恶意用户来刷接口,因此需要在没到秒杀开始时间不能获取秒杀接口,只有秒杀开始了,才返回秒杀地址 url 和验证 MD5,用户拿到这两个数据才可以进行秒杀 - - 同一个账号多次发出请求:在前端优化的禁止重复提交可以进行优化;也可以使用 Redis 标志位,每个用户的所有请求都尝试在 Redis 中插入一个 `userId_secondsKill` 标志位,成功插入的才可以执行后续的秒杀逻辑,其他被过滤掉,执行完秒杀逻辑后,删除标志位 - - 多个账号一次性发出多个请求:一般这种请求都来自同一个 IP 地址,可以检测 IP 的请求频率,如果过于频繁则弹出一个验证码 - - 多个账号不同 IP 发起不同请求:这种一般都是僵尸账号,检测账号的活跃度或者等级等信息,来进行限制。比如微博抽奖,用 iphone 的年轻女性用户中奖几率更大。通过用户画像限制僵尸号无法参与秒杀或秒杀不能成功 - - - -## 参考资料 - -[如何设计一个秒杀系统](https://gongfukangee.github.io/2019/06/09/SecondsKill/#%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%89%B9%E7%82%B9) - -[秒杀系统如何设计](https://www.teqng.com/2021/09/07/%E9%9D%A2%E9%9C%B8%EF%BC%9A%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%EF%BC%9F/) # 短链系统 diff --git a/docs/advance/system-design/4-oversold.md b/docs/advance/system-design/4-oversold.md new file mode 100644 index 0000000..1a74058 --- /dev/null +++ b/docs/advance/system-design/4-oversold.md @@ -0,0 +1,30 @@ +--- +sidebar: heading +--- + + + +# 超卖问题 + +先到数据库查询库存,在减库存。不是原子操作,会有超卖问题。 + +通过加排他锁解决该问题。 + +- 开始事务。 +- 查询库存,并显式的设置排他锁:SELECT * FROM table_name WHERE … FOR UPDATE +- 生成订单。 +- 去库存,update会隐式的设置排他锁:UPDATE products SET count=count-1 WHERE id=1 +- commit,释放锁。 + +也可以通过乐观锁实现。使用版本号实现乐观锁。 + +假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。 + +然后直接update的时候,只有其中一个先update了,同时更新了版本号。 + +那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了,则放弃此次update,重试直到成功。 + +```mysql +select version from goods WHERE id= 1001 +update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version); +``` diff --git a/docs/advance/system-design/5-second-kill.md b/docs/advance/system-design/5-second-kill.md new file mode 100644 index 0000000..da8eb16 --- /dev/null +++ b/docs/advance/system-design/5-second-kill.md @@ -0,0 +1,45 @@ +--- +sidebar: heading +--- + + + +# 秒杀系统 + +## 系统的特点 + +- 高性能:秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键 +- 一致性:秒杀商品减库存的实现方式同样关键,有限数量的商品在同一时刻被很多倍的请求同时来减库存,在大并发更新的过程中都要保证数据的准确性。 +- 高可用:秒杀时会在一瞬间涌入大量的流量,为了避免系统宕机,保证高可用,需要做好流量限制 + +## 优化思路 + +- 后端优化:将请求尽量拦截在系统上游 + + - 限流:屏蔽掉无用的流量,允许少部分流量走后端。假设现在库存为 10,有 1000 个购买请求,最终只有 10 个可以成功,99% 的请求都是无效请求 + - 削峰:秒杀请求在时间上高度集中于某一个时间点,瞬时流量容易压垮系统,因此需要对流量进行削峰处理,缓冲瞬时流量,尽量让服务器对资源进行平缓处理 + - 异步:将同步请求转换为异步请求,来提高并发量,本质也是削峰处理。在真实的秒杀场景中,有三个核心流程:而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。 + - 利用缓存:创建订单时,每次都需要先查询判断库存,只有少部分成功的请求才会创建订单,因此可以将商品信息放在缓存中,减少数据库查询 + - 负载均衡:利用 Nginx 做负载均衡,使用多个服务器并发处理请求,减少单个服务器压力 + +- 前端优化: + + - 限流:使用验证码等,来分散用户的请求 + - 禁止重复提交:限定每个用户发起一次秒杀后,需等待才可以发起另一次请求,从而减少用户的重复请求 + - 本地标记:用户成功秒杀到商品后,将提交按钮置灰,禁止用户再次提交请求 + - 动静分离:使用CDN缓存静态页面资源,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率 + +- 防作弊优化: + + - 隐藏秒杀接口:如果秒杀地址直接暴露,在秒杀开始前可能会被恶意用户来刷接口,因此需要在没到秒杀开始时间不能获取秒杀接口,只有秒杀开始了,才返回秒杀地址 url 和验证 MD5,用户拿到这两个数据才可以进行秒杀 + - 同一个账号多次发出请求:在前端优化的禁止重复提交可以进行优化;也可以使用 Redis 标志位,每个用户的所有请求都尝试在 Redis 中插入一个 `userId_secondsKill` 标志位,成功插入的才可以执行后续的秒杀逻辑,其他被过滤掉,执行完秒杀逻辑后,删除标志位 + - 多个账号一次性发出多个请求:一般这种请求都来自同一个 IP 地址,可以检测 IP 的请求频率,如果过于频繁则弹出一个验证码 + - 多个账号不同 IP 发起不同请求:这种一般都是僵尸账号,检测账号的活跃度或者等级等信息,来进行限制。比如微博抽奖,用 iphone 的年轻女性用户中奖几率更大。通过用户画像限制僵尸号无法参与秒杀或秒杀不能成功 + + + + ## 参考资料 + + [如何设计一个秒杀系统](https://gongfukangee.github.io/2019/06/09/SecondsKill/#%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%89%B9%E7%82%B9) + + [秒杀系统如何设计](https://www.teqng.com/2021/09/07/%E9%9D%A2%E9%9C%B8%EF%BC%9A%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%EF%BC%9F/) \ No newline at end of file diff --git a/docs/advance/system-design/6-wechat-redpacket-design.md b/docs/advance/system-design/6-wechat-redpacket-design.md new file mode 100644 index 0000000..6bd0599 --- /dev/null +++ b/docs/advance/system-design/6-wechat-redpacket-design.md @@ -0,0 +1,134 @@ +--- +sidebar: heading + +--- + +## 微信红包后台系统设计 + +### **背景** + +微信作为一款国民应用,已经进入每个互联网用户手中,微信支付作为其杀手级功能,在每一次佳节期间都会产生巨大流量,以2017年除夕为例,峰值QPS在76w左右,整个系统核心功能和金融相关,需要做好高可用。 + +我们先了解下微信红包支付的流程: + +![](http://img.dabin-coder.cn/image/image-20221129002112859.png) + +一个发红包的流程经过抽象可以得到如下路径:包 -> 发 -> 抢 -> 拆 + +微信红包的核心知识如下: + +1. 包红包:系统给每个红包分配一个唯一ID,也就是发红包的订单号,然后将红包发送给用户,红包的个数,红包金额写入到存储。 +2. 发红包:用户使用微信支付完成付款,微信红包后台收到微信支付成功的通知。红包系统将红包发送订单状态更新,更新为用户已支付,并写入用户发红包记录表,这样用户可以在钱包中找到用户的发红包流水和收发红包的记录,之后微信红包系统调用微信通知,将微信红包信息发送到微信群。 +3. 抢红包:微信群中的用户收到红包消息之后,点开红包,开始抢红包,这个过程微信红包系统会检查红包是否已经被抢完,是否已经过期,是否已经抢过等验证逻辑。 +4. 拆红包:拆红包是整个发红包流程最复杂的一个操作,需要查询这个红包的红包订单,判断用户是否可以拆包,计算本次可拆到的红包金额。记录抢红包流水。 + +最后的拆红包过程类似于一个秒杀活动的过程,需要做好库存扣减和秒杀记录的操作。更新库存就是更新红包发送的订单,写入秒杀记录就是写入红包领取的信息流水。还需要以用户为中心记录用户整体的红包领取记录。最后调用支付系统将拆红包后的金额转入用户零钱中,成功之后更新抢红包的订单状态为转账成功。 + +![](http://img.dabin-coder.cn/image/image-20221129002128841.png) + +### **架构** + +接下来我们在了解下微信红包的整体架构: + +![](http://img.dabin-coder.cn/image/image-20221129002141666.png) + +**可用性** + +影响系统可用性的指标有哪些呢? + +\- 计划外逻辑:很多意想不到的因素都可能对我们的系统可用性带来挑战,系统需要可以应对所有可能的故障,有些故障无法避免,那么我们是否可以缩短故障周期进行快速修复或是止损呢? + +1. 系统级故障:主机,操作系统,[中间件](https://cloud.tencent.com/product/tdmq?from=10680),数据库,网络,电源等 +2. 数据和中介故障:人员操作,硬盘故障 +3. 其他:自然灾害,人为破坏,供电问题 + +\- 计划内逻辑:主要是业务升级或迭代导致,或是[运维](https://cloud.tencent.com/solution/operation?from=10680)的主从操作导致,或是一些定时的备份逻辑等。这一些因素需要做到精细化的方案,可以避免或是降低影响。 + +1. 日常任务:备份,容量规划,用户和安全管理 +2. 运维升级相关:数据库维护升级,应用维护升级,中间件运维升级,网络维护,操作系统维护升级 + +总结来说做好可用性,对外做好预案降低影响,对内做好容量规划和流程制定。 + +那么微信红包架构在可用性上做了哪些事情呢? + +1. 业务逻辑层:部署方案,异步化,降级与柔性可用 +2. 订单存储层:SET化,DB故障自愈能力建设 + +### **部署方案** + +上海深圳两地部署,同城三园区部署,每个园区容量冗余1/3。 + +在部署上的收益:就近接入,单机,单IDC故障不影响正常业务,避免宏观单点。 + +弊端:资源,需要做好数据同步。 + +**异步化方案** + +基本思路:简化关键路径,快慢分类 + +方案: + +![](http://img.dabin-coder.cn/image/image-20221129002154044.png) + +用户记录,零钱入账等非关键路径可以使用MQ异步执行,增加对账机制兜底保障,实现最终一致性。 + +思考: + +- 需要正确识别业务的核心关键路径 +- 异步化MQ需要做好生产消费只有一次 +- [分布式事务](https://cloud.tencent.com/product/dtf?from=10680)的一致性 + +**分库分表 + SET化** + +方案一:分库分表 + +![](http://img.dabin-coder.cn/image/image-20221129002210589.png) + +方案特点 + +- 分为10个物理DB,每个物理DB分10个库,每个库分10个表,总共100张。 +- 订单顺序生成,订单后三位分库分表,所有物理DB均匀分库分表,每个订单server与所有物理DB相连 + +存在的问题:db连接数过高,容量的水平扩容问题 + +方案二:SET化 + +![](http://img.dabin-coder.cn/image/image-20221129002222281.png) + +方案特点: + +垂直stick,分而治之,将同一个红包ID的所有请求stick到同一台server,使得订单DB和订单server垂直stick在一起。 + +同一个SET中DB接入机器对等,三园区部署 + +解决DB连接数问题 + +思考: + +1.DB层如何做到自愈? + +答:监控单位时间内每个逻辑表的错误数,超过阈值后,通知订单生成系统屏蔽该号段,业务逻辑层重新生成红包id重试,对于已发的红包,没有增量,需要等机器恢复后超时退款。 + +2.如何解决DB锁竞争? + +![](http://img.dabin-coder.cn/image/image-20221129002235645.png) + +答:将stick到同一台server上的所有请求接收到进程后,按照红包ID排队,然后串行的进入worker进程进行处理,从而达到排队的效果,为防止server中请求队列过载导致队列被降级,从而所有请求涌进DB,系统增加了server服务器同部署的memcached,用于控制拆同一个红包请求并发数,用于请求队列过载降级。 + +3.冷热数据如何分离? + +答:随着红包数量越来越大,单表数据也逐渐增加,DB性能和单表数据量有一定相关性,当单表数据量达到一定程度后,DB性能大幅度下降,影响系统性能稳定性,采用冷热分离,将历史数据和热数据分开存储。 + +比如可以按照天纬度分库分表逻辑,按照31天分。 + +4.如何平衡扩容? + +![](http://img.dabin-coder.cn/image/image-20221129002245215.png) + +### **总结** + +做到系统的高可用,我们需要了解系统的核心流程,需要了解业务的周期性高峰,做好流量异常监控,告警。做好依赖治理,复杂度治理,需要区分核心服务和非核心服务,做拆分部署和容量规划。 + + + +> 来源:https://cloud.tencent.com/developer/article/1637408 \ No newline at end of file diff --git a/docs/advance/system-design/7-file-send.md b/docs/advance/system-design/7-file-send.md new file mode 100644 index 0000000..e9190ef --- /dev/null +++ b/docs/advance/system-design/7-file-send.md @@ -0,0 +1,17 @@ +--- +sidebar: heading +--- + +## 如何把一个文件较快的发送到100w个服务器? + +可以采用p2p网络形式,比如树状形式,单个节点既可以从其他节点接收服务又可以向其他节点提供服务。 + +不过,树状结构会有什么问题呢? + +第一,如果树上的某一个节点坏掉了,那么从这个节点往下的所有服务器全部接收不到文件。 + +第二,如果树中的某条路径,因为网络因素等原因,传递速度比较慢,导致传递时间比较长,这样会使传递效率退化。 + +改进的方案如下: + +可以使用**连通图**。100W台服务器相当于有100W个节点的连通图。我们可以在图里生成多颗不同的生成树,在进行数据下发时,同时按照多颗不同的树去传递数据。这样就可以避免某个中间节点宕机,影响到后续的节点。同时这种传递方法实际上是一种依据时间的广度优先遍历,可以避免某条路径过长造成的效率低下。 \ No newline at end of file diff --git a/docs/advance/system-design/8-sso-design.md b/docs/advance/system-design/8-sso-design.md new file mode 100644 index 0000000..e0a4604 --- /dev/null +++ b/docs/advance/system-design/8-sso-design.md @@ -0,0 +1,113 @@ +# 单点登录(SSO)的设计与实现 + +## 一、前言 + +### 1、SSO说明 + +SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。https://baike.baidu.com/item/SSO/3451380 + +例如访问在网易账号中心(http://reg.163.com/ )登录之后 +访问以下站点都是登录状态 + +- 网易直播 [http://v.163.com](http://v.163.com/) +- 网易博客 [http://blog.163.com](http://blog.163.com/) +- 网易花田 [http://love.163.com](http://love.163.com/) +- 网易考拉 [https://www.kaola.com](https://www.kaola.com/) +- 网易Lofter [http://www.lofter.com](http://www.lofter.com/) + +### 2、设计目标 + +本篇文章也主要是为了探讨如何设计&实现一个SSO系统 + +以下为需要实现的核心功能: + +- 单点登录 +- 单点登出 +- 支持跨域单点登录 +- 支持跨域单点登出 + +## 二、SSO设计与实现 + +### 1、核心应用与依赖 + +![](http://img.dabin-coder.cn/image/sso-system.png-kblb.png) + +| 应用/模块/对象 | 说明 | +| ---------------- | ----------------------------------- | +| 前台站点 | 需要登录的站点 | +| SSO站点-登录 | 提供登录的页面 | +| SSO站点-登出 | 提供注销登录的入口 | +| SSO服务-登录 | 提供登录服务 | +| SSO服务-登录状态 | 提供登录状态校验/登录信息查询的服务 | +| SSO服务-登出 | 提供用户注销登录的服务 | +| 数据库 | 存储用户账户信息 | +| 缓存 | 存储用户的登录信息,通常使用Redis | + +### 2、用户登录状态的存储与校验 + +常见的Web框架对于Session的实现都是生成一个SessionId存储在浏览器Cookie中。然后将Session内容存储在服务器端内存中。 + +用户登录成功之后,生成AuthToken交给客户端保存。如果是浏览器,就保存在Cookie中。如果是手机App就保存在App本地缓存中。本篇主要探讨基于Web站点的SSO。 + +用户在浏览需要登录的页面时,客户端将AuthToken提交给SSO服务校验登录状态/获取用户登录信息 + +对于登录信息的存储,建议采用Redis,使用Redis集群来存储登录信息,既可以保证高可用,又可以线性扩充。同时也可以让SSO服务满足负载均衡/可伸缩的需求。 + +| 对象 | 说明 | +| --------- | ------------------------------------------------------------ | +| AuthToken | 直接使用UUID/GUID即可,如果有验证AuthToken合法性需求,可以将UserName+时间戳加密生成,服务端解密之后验证合法性 | +| 登录信息 | 通常是将UserId,UserName缓存起来 | + +### 3、用户登录/登录校验 + +- 登录时序图 + +![](http://img.dabin-coder.cn/image/sso-login-sequence.png-kbrb.png) + +按照上图,用户登录后Authtoken保存在Cookie中。 domian= test. com +浏览器会将domain设置成 .test.com, +这样访问所有*.test.com的web站点,都会将Authtoken携带到服务器端。 +然后通过SSO服务,完成对用户状态的校验/用户登录信息的获取 + +- 登录信息获取/登录状态校验 + +![](http://img.dabin-coder.cn/image/sso-logincheck-sequence.png-kbrb.png) + +### 4、用户登出 + +用户登出时要做的事情很简单: + +1. 服务端清除缓存(Redis)中的登录状态 +2. 客户端清除存储的AuthToken + +- 登出时序图 + +![](http://img.dabin-coder.cn/image/sso-logout-sequence.png-kbrb.png) + +### 5、跨域登录、登出 + +前面提到过,核心思路是客户端存储AuthToken,服务器端通过Redis存储登录信息。由于客户端是将AuthToken存储在Cookie中的。所以跨域要解决的问题,就是如何解决Cookie的跨域读写问题。 + +解决跨域的核心思路就是: + +- 登录完成之后通过回调的方式,将AuthToken传递给主域名之外的站点,该站点自行将AuthToken保存在当前域下的Cookie中。 +- 登出完成之后通过回调的方式,调用非主域名站点的登出页面,完成设置Cookie中的AuthToken过期的操作。 +- 跨域登录(主域名已登录) + +![](http://img.dabin-coder.cn/image/sso-crossdomain-login-loggedin-sequence.png-kbrb.png) + +- 跨域登录(主域名未登录) + +![](http://img.dabin-coder.cn/image/sso-crossdomain-login-unlogin-sequence.png-kbrb.png) + +- 跨域登出 + +![](http://img.dabin-coder.cn/image/sso-crossdomain-logout-sequence.png-kbrb.png) + +## 三、备注 + +- 关于方案 + +这次设计方案更多是提供实现思路。如果涉及到APP用户登录等情况,在访问SSO服务时,增加对APP的签名验证就好了。当然,如果有无线网关,验证签名不是问题。 + +> 本文授权转载自Ken,原文链接:https://ken.io/note/sso-design-implement \ No newline at end of file diff --git a/docs/advance/system-design/README.md b/docs/advance/system-design/README.md new file mode 100644 index 0000000..3f910a9 --- /dev/null +++ b/docs/advance/system-design/README.md @@ -0,0 +1,11 @@ +# 场景设计题(高频) + +- [扫码登录](./1-scan-code-login.md) +- [订单超时未支付自动取消](./2-order-timeout-auto-cancel.md) +- [短链系统设计](./3-short-url.md) +- [超卖问题](./4-oversold.md) +- [秒杀系统设计](./5-second-kill.md) +- [微信红包系统如何设计?](./6-wechat-redpacket-design.md) +- [如何把一个文件较快的发送到100w个服务器?](./7-file-send.md) +- [单点登录(SSO)设计与实现](./8-sso-design.md) + diff --git "a/docs/advance/system-design/\345\233\276\347\211\207 - \345\277\253\346\215\267\346\226\271\345\274\217.lnk" "b/docs/advance/system-design/\345\233\276\347\211\207 - \345\277\253\346\215\267\346\226\271\345\274\217.lnk" new file mode 100644 index 0000000000000000000000000000000000000000..3339de15c648ffb7fb91870a19e7771331fbe803 GIT binary patch literal 705 zcmeZaU|?VrVFHp233^lsJJ*K zzPPfuBsG`8*(xTqIJKxaCZw`BKQAUAGr6R+D7Bb@ApxRiK?INnft1wZ?2`NfU5hkh zgR){n1{a}+?czV@JMS=5&1P%ZCct;e_{YD!&jed<6qGl*medoH&j&h`lYwDDAkb{X z;DF$_277NgGjzHy|8YThNpYHzDacNc#qvN5@_YzGB||YoK0_XZ0)qyFGlLaF3_~bT zB$c5ENNR$VfsY{Q{sXnP+ShA0A!j35TiRk2FZIdz_`q0NM 参考:https://segmentfault.com/a/1190000040241465 \ No newline at end of file diff --git a/interview/1-byte-and-dance.md b/docs/campus-recruit/interview/1-byte-and-dance.md similarity index 100% rename from interview/1-byte-and-dance.md rename to docs/campus-recruit/interview/1-byte-and-dance.md diff --git a/interview/10-netease.md b/docs/campus-recruit/interview/10-netease.md similarity index 100% rename from interview/10-netease.md rename to docs/campus-recruit/interview/10-netease.md diff --git a/interview/2-tencent.md b/docs/campus-recruit/interview/2-tencent.md similarity index 98% rename from interview/2-tencent.md rename to docs/campus-recruit/interview/2-tencent.md index c37e35f..b47ade5 100644 --- a/interview/2-tencent.md +++ b/docs/campus-recruit/interview/2-tencent.md @@ -33,7 +33,7 @@ 8. 算法题:最长回文串 9. 为什么连接的时候是三次握手,关闭的时候却是四次握手? ## 四面 -1. 自我介绍 就背景进行一些提问 +1. 自我介绍 2. 简单说说计算机网络 3. 简单描述一下从浏览器输入一个地址到服务端整个交互过程 4. 说说数据结构 diff --git a/interview/3-baidu.md b/docs/campus-recruit/interview/3-baidu.md similarity index 100% rename from interview/3-baidu.md rename to docs/campus-recruit/interview/3-baidu.md diff --git a/interview/4-ali.md b/docs/campus-recruit/interview/4-ali.md similarity index 100% rename from interview/4-ali.md rename to docs/campus-recruit/interview/4-ali.md diff --git a/interview/5-kuaishou.md b/docs/campus-recruit/interview/5-kuaishou.md similarity index 100% rename from interview/5-kuaishou.md rename to docs/campus-recruit/interview/5-kuaishou.md diff --git a/interview/6-meituan.md b/docs/campus-recruit/interview/6-meituan.md similarity index 100% rename from interview/6-meituan.md rename to docs/campus-recruit/interview/6-meituan.md diff --git a/interview/7-shopee.md b/docs/campus-recruit/interview/7-shopee.md similarity index 100% rename from interview/7-shopee.md rename to docs/campus-recruit/interview/7-shopee.md diff --git a/interview/8-jingdong.md b/docs/campus-recruit/interview/8-jingdong.md similarity index 100% rename from interview/8-jingdong.md rename to docs/campus-recruit/interview/8-jingdong.md diff --git a/interview/9-huawei.md b/docs/campus-recruit/interview/9-huawei.md similarity index 100% rename from interview/9-huawei.md rename to docs/campus-recruit/interview/9-huawei.md diff --git a/interview/README.md b/docs/campus-recruit/interview/README.md similarity index 100% rename from interview/README.md rename to docs/campus-recruit/interview/README.md diff --git a/docs/campus-recruit/layoffs-solution.md b/docs/campus-recruit/layoffs-solution.md new file mode 100644 index 0000000..4059bff --- /dev/null +++ b/docs/campus-recruit/layoffs-solution.md @@ -0,0 +1,24 @@ +今年确实是互联网寒冬啊! + +从2022年5月中旬以来,包括腾讯、阿里巴巴、字节跳动、美团、拼多多、快手、百度、京东、网易等在内的十余家企业被爆出裁员消息。 + +也有一些校招毁约的公司,真的是。。。 + +对于2023届的同学,这里给几个建议: + +1. **准备充足**,再去面试!今年行情不好,很多互联网中大厂都在缩招,hc比往年少,所以更要准备充分,争取多拿几个offer,才有主动选择的余地! +2. **多投简历**,不要有“非大厂不进”的心态。今年秋招会比往年难些,毕竟僧多粥少,建议海投简历,争取多一些面试机会。 +3. 找师兄师姐**内推**。内推可以避免在简历关被筛掉,见过太多学历不好的同学,投了很多简历,最终面试的机会寥寥无几。多找一些内推渠道,包括你的师兄师姐、牛客网、一些求职交流裙等。 +4. **选择好方向**,不要“三心二意”。有些同学没有规划好自己的职业发展,在秋招会投递多个方向,比如前段时间我的读者就投了嵌入式工程师、Java后台工程师、测试工程师,大彬不建议大家这么做。虽然投递多个岗位方向,可以多几个面试机会,但是相应的你得多准备几个岗位的知识复习,精力会分散。就Java后台的知识点,没有半个月一个月的时间,是复习不完的(大佬除外)。因此,建议大家秋招之前就定好方向,专注一个方向进行复习。 +5. 多看看银行、研究所等**国企**的机会,相对稳定。近两年很多公司爆出校招毁约的劣迹,而国企一般不会轻易毁约,这算是一个优势。 +6. **打好基础**。校招比较注重基础知识,包括操作系统、计算机网络、数据结构与算法等(针对开发岗位),小伙伴们一定要把基础巩固好,不要等到面试的时候,一问三不知,成了秋招的“炮灰”。 + + + +最后,互联网行业,**年年都是最难的一年**,大家放好心态,面试没过也不用气馁,面试通过与否跟很多因素相关(自身知识储备、竞争者的水平等等),面试完多复盘,相信大家最终都能找到自己满意的offer! + + + +码字不易,如果觉得对你有帮助,可以**点个赞**鼓励一下! + +我是 [@程序员大彬](https://zhuanlan.zhihu.com/people/dai-shu-bin-13) ,专注分享互联网校招、自学CS经验,欢迎大家关注~ \ No newline at end of file diff --git a/docs/campus-recruit/program-language/README.md b/docs/campus-recruit/program-language/README.md new file mode 100644 index 0000000..bd940fa --- /dev/null +++ b/docs/campus-recruit/program-language/README.md @@ -0,0 +1,5 @@ +# 编程语言(更新中) + +- [Java和Golang怎么选?](./java-or-golang.md) +- [Java和C++怎么选?](./java-or-c++.md) + diff --git a/docs/campus-recruit/program-language/java-or-c++.md b/docs/campus-recruit/program-language/java-or-c++.md new file mode 100644 index 0000000..b4dc813 --- /dev/null +++ b/docs/campus-recruit/program-language/java-or-c++.md @@ -0,0 +1,34 @@ +--- +sidebar: heading +--- + +# Java和C++怎么选? + +很多读者私底下问过我这个问题:Java和c++应该选择哪个?哪个好就业、前景更好? + +首先,Java和C++都是主流的编程语言,不存在哪个好哪个差的说法,学得好的话,都很有前途。 + +下面我从几个方面来比较Java和C++的差异。 + +## 学习难度 + +毫无疑问,C++相对于Java更难学。C++面向底层,而Java面向上层。C++要求对于计算机底层的知识更高,更难,学习C++更有利于理解计算机基础。 + +## 使用场景 + +Java 是大型 web 应用后台的首选语言,像淘宝和京东这些大型电商系统的 web 服务器都选用Java技术栈。很多大数据相关的框架,都是用 Java 开发的,所以在大数据领域 Java 有着天然的优势。另外,移动端安卓APP开发语言也是Java。 + +C++在人工智能、机器学习、计算机视觉与图像识别、自动驾驶等新兴技术领域运用更多,这些领域对性能、效率要求更高。 + +## 市场需求 + +从招聘网站的数据来看,Java开发需求是大于C++的,而且相比于C++,Java更好入门,比Java简单一些,很适合短期学习快速上手工作。如果你想从事后台开发方向,那么建议你选择Java,因为互联网公司在后台开发方向招的 Java 程序员会更多一些。C++ 主要是底层应用开发、语音、图形图像、音视频、游戏等方面用得多。 + +## 发展前景 + +Java 和 C++是两门主流的热门开发语言,一直名列世界编程语言排行榜的前几位。在 TIOBE2022 年 5 月最新的世界编程语言排行榜中,C++和 Java 依然稳定在前几位。两者目前发展前景都很好,暂时不存在谁替代谁或者被其他编程语言替代的情况。 + + + +最后,每个人学习能力、职业规划、兴趣不一样,对于选择哪种编程语言,应该根据自身的具体情况,选择相应的编程语言,做出最优的选择。 + diff --git a/docs/campus-recruit/program-language/java-or-golang.md b/docs/campus-recruit/program-language/java-or-golang.md new file mode 100644 index 0000000..0579891 --- /dev/null +++ b/docs/campus-recruit/program-language/java-or-golang.md @@ -0,0 +1,73 @@ +--- +sidebar: heading +--- + +# Java和Golang怎么选? + +大家好,我是大彬~ + +最近有读者问了我一个问题:Java和Golang怎么选?下面分享我的看法。 + +作为非科班转码的选手,曾经也很纠结这个问题。 + +Java是当前使用最热门的编程语言,Go最近也很火,很多公司比如bilibili后台转向Go开发,头条的后台只用Python和Go。根据最新2022年2月份的TIOBE编程语言指数排行榜,排名前三的分别是Python、C和Java,Go排名在第11位。 + +以下从三个方面来分析: + +## 一、编程语言 + + 从编程语言本身来说,Java在1995年5月首次推出,Go在2009年11月正式推出。 + + 1、Java + +两种语言各有特点,Java经历了20多年,一直在不断更新推出新版本。2009年Oracle收购Sun公司后,Java发展得到了大力支持,现在使用非常多的Java8发布于2014年,当前最新版本是Java18,于2022年3月份发布。和早期版本相比,从Java8开始,吸收了越来越多的现代化编程语言的优点,比如lambda表达式。 + +Java 要求开发人员更多地地关注程序的业务逻辑,知道如何创建、过滤、修改和存储数据。系统底层和数据库方面的东西都是通过配置和注解来完成的(比如通过 Spring Boot 等通用框架)。 + +2、Go + +Go由Google的三位大神开发,Robert Griesemer,Rob Pike 及 Ken Thompson,是一种静态强类型、编译型语言,语法与C相近,功能更丰富。在2016年,Go被软件评价公司TIOBE 选为“TIOBE 2016 年最佳语言”。 + +Go 不是面向对象编程语言。Go 没有类似 Java 的继承机制,因为它没有通过继承实现传统的多态性。实际上,它没有对象,只有结构体。它可以通过接口和让结构体实现接口来模拟一些面向对象特性。此外,你可以在结构体中嵌入结构体,但内部结构体无法访问外部结构体的数据和方法。Go 使用组合而不是继承将一些行为和数据组合在一起。 + +Go 是一种命令式语言,Java 是一种声明式语言。Go 没有依赖注入,我们需要显式地将所有东西包装在一起。因此,在使用 Go 时尽量少用“魔法”之类的东西。一切代码对于代码评审人员来说都应该是显而易见的。Go 程序员应该了解 Go 代码如何使用内存、文件系统和其他资源。 + +## 二、学习难度 + + 1、Java + +Java是一种静态面向对象编程语言,继承了很多的C++优点,功能强大、简单易用、跨平台可移植,具有多线程、分布式等特点。入门学习不难,随着项目经验的积累逐步提升进阶。 + +2、Go + +Go也是一种静态的编译型语言,语法和C相近,但是采用了不同的变量声明方式。Go支持垃圾回收功能,并行模型是以通信顺序进程为基础,自1.8版本开始支持插件Plugin,能动态加载部分函数。从2.0开始支持泛型。 + + 相比Java,Go内嵌了关联数组数据库类型,也称为哈希表Hashes或字典Dictionaries,就像字符串类型一样。 Go 也没有继承多态性。被嵌入到结构体里的结构体只知道其自己的方法,对“宿主”结构体的方法一无所知。 + +对于Java开发人员来说,这尤其具有挑战性。 不过,随着时间的推移,我开始意识到这种处理多态性的方法只是另一种思维方式,而且是有道理的,因为组合比继承更加可靠,并且运行时间是可变的。 错误处理。在 Go 中,完全由你来决定返回什么错误以及如何返回错误,因此作为开发人员,你需要负责返回和传递错误。毫无疑问的是,错误可能会被隐藏掉,这是一个痛点。时刻要记得检查错误并把它们传递出去,这有点烦人,而且不安全。 + +当然,你可以使用 linter 来检查隐藏的错误,但这只是一种辅助手段,不是真正的解决方案。在 Java 中,处理异常要方便得多。如果是 RuntimeException,甚至不必将其添加到函数的签名中。 + +## 三、发展前景 + +考虑发展前景的话,推荐学习Java语言。Java是当前的主流开发语言,普遍使用在Web开发、电商系统、企业信息管理等各种行业场景。 + +不信你打开招聘网站,搜搜Java和Go岗位的招聘量。如下图,同一地区,Java招聘岗位是500+,Go招聘岗位是175。由此看来,Java岗位的需求量还是比较多的(当然Java方向也比较卷)。 + +![](http://img.dabin-coder.cn/image/20220620084914.png) + +![](http://img.dabin-coder.cn/image/20220620084855.png) + +Java社区非常活跃,各种文档和学习资料非常丰富。因为使用广泛,所以很多同事朋友沟通交流。 开发框架也是降低学习难度的有力工具,Spring框架是Java开发时常用框架,有非常丰富的组件和易用的功能,Spring Boot和Spring Cloud更是简化了开发过程中的琐碎工作,自动化配置依赖模块、开箱即用和约定优于配置,这些策略使得Spring框架在快速开发领域非常受欢迎。 + +> 参考链接:https://juejin.cn/post/6960553709357154311 + + + +**如果你还在这两种语言之间犹豫不定的话,那就来卷Java吧。** + +下面附上Java学习路线,是我**自学Java过程踩坑**总结出来的,希望能帮到你们! + +## 四、Java学习路线 + +[点这里](https://topjavaer.cn/learning-resources/java-learn-guide.html#%E8%87%AA%E5%AD%A6%E8%B7%AF%E7%BA%BF) \ No newline at end of file diff --git a/docs/campus-recruit/project-experience.md b/docs/campus-recruit/project-experience.md new file mode 100644 index 0000000..6b13506 --- /dev/null +++ b/docs/campus-recruit/project-experience.md @@ -0,0 +1,124 @@ +--- +sidebar: heading +--- + +# 项目经验怎么回答 + +在面试时,经过寒暄后,一般面试官会让介绍项目经验 。常见的问法是,**说下你最近的一个项目**。 + + 根据我们的面试经验,发现有不少同学对此没准备,说起来磕磕巴巴,甚至有人说出项目经验从时间段或技术等方面和简历上的不匹配,这样就会造成如下的后果。 + +1. **第一印象就不好了**,至少会感觉你表述能力不强。 +2. 一般来说,面试官会根据你介绍的项目背景来提问题,假设面试时会问10个问题,那么至少有5个问题会根据所介绍的项目背景来问,如果没说好,那么就**没法很好地引导后继问题**了,就相当于把提问权完全交给面试官了。 + + 面试时7份靠能力,3份靠技能,而刚开始时的介绍项目又是技能中的重中之重,所以本文将从“**介绍**”和“**引导**”两大层面告诉大家如何准备面试时的项目介绍。 + + 好了,如下是正文内容。 + +## 准备项目描述 + + **在面试前准备项目描述,别害怕,因为面试官什么都不知道** + + 面试官是人,不是神,拿到你的简历的时候,是没法核实你的项目细节的。 + + 更何况,你做的项目是以月为单位算的,而面试官最多用30分钟来从你的简历上了解你的项目经验,所以你对项目的熟悉程度要远远超过面试官,所以你一点也不用紧张。 + + 如果你的工作经验比面试官还丰富的话,甚至还可以控制整个面试流程。 + +![](http://img.dabin-coder.cn/image/20220711000600.png) + + 既然面试官无法了解你的底细,那么他们怎么来验证你的项目经验和技术?下面总结了一些常用的提问方式。 + +![](http://img.dabin-coder.cn/image/20220711000648.png) + +## 准备项目的各种细节 + + **准备项目的各种细节,一旦被问倒了,就说明你没做过** + + 一般来说,在面试前,大家应当准备项目描述的说辞,自信些,因为这部分你说了算,流利些,因为你经过充分准备后,可以知道你要说些什么。而且这些是你实际的项目经验(不是学习经验,也不是培训经验),那么一旦让面试官感觉你都说不上来,那么可信度就很低了。 + + 不少人是拘泥于“项目里做了什么业务,以及代码实现的细节”,这就相当于把后继提问权直接交给面试官。下表列出了一些不好的回答方式。 + +![](http://img.dabin-coder.cn/image/20220711000705.png) + + 在避免上述不好的回答的同时,大家可以按下表所给出的要素准备项目介绍。如果可以,也请大家准备一下用英语描述。其实刚毕业的学生,或者工作经验较少的人,英语能力都差不多,但你说了,这就是质的进步。 + +![](http://img.dabin-coder.cn/image/20220711000721.png) + + 面试前,你一定要准备,一定要有自信,但也要避免如下的一些情况。 + +![](http://img.dabin-coder.cn/image/20220711000733.png) + +## 不露痕迹地说出面试官爱听的话 + + 在项目介绍的时候(当然包括后继的面试),面试官其实很想要听一些关键点,只要你说出来,而且回答相关问题比较好,这绝对是加分项。我在面试别人的时候,一旦这些关键点得到确认,我是绝对会在评语上加上一笔的。 + + 下面列些面试官爱听的关键点和对应的说辞。 + +![](http://img.dabin-coder.cn/image/20220711000746.png) + +## 一定要主动,面试官没有义务挖掘你的亮点 + + 面试时,面试官往往会特别提问:你项目里有什么亮点?或者你作为应聘者,有什么其他加分项能帮你成功应聘到这个岗位。即使这样问,还有些人直接说没有。 + + 我这样问已经是处于角色错位了,作为面试者,应当主动说出,而不是等着问,但请注意,说的时候要有技巧,找机会说,通常是找一些开放性的问题说。 + + 比如:在这个项目里用到了什么技术?你除了说一些基本的技术,比如Spring MVC,Hibernate,还有数据库方面的常规技术时,还得说,用到了Java内存管理,这样能减少对虚拟机内存的压力,或者说用到了大数据处理技术等。 + + 也就是说,得找一切机会说出你拿得出手的而且当前也非常热门的技术。 + + **记住:面试官不是你的亲戚,面试官很忙,能挖掘出你的亮点的面试官很少,而说出你的亮点是你的义务。** + + 我在面试别人过程中,根据不同的情况一般会给出如下的评语。 + + 1、回答很简答,但回答里能证明出他对框架等技术确实是做过,我会在评语里些“对框架了解一般,不知道一些深层次的知识(我都问了多次了你都回答很简答,那么对不起了,我只能这么写。 + + 或许你确实技术很强,那也没办法,谁让你不肯说呢?)”,同时会加一句“表达能力很一般,沟通能力不强”,这样即使他通过技术面试,后面的面试他也会很吃力。 + + 2、回答很简单,通过回答我没法验证他是在项目里做过这个技术,还是仅仅在平时学习中学过这个技术。 + + 我就会写“在简历中说用过XX技术,但对某些细节说不上来,没法看出在项目里用到这个技术”,如果这个技术是职务必需点,那么他通过面试的可能性就非常小。 + + 3、回答很简单,而且只通过嗯啊之类的虚词回答,经过提醒还这样,我会敷衍几句结束面试,直接写“技术很薄弱,没法通过面试”。 + + 4、虽然通过回答能很好地展示自己的技能,但逻辑调理不清晰,那么我会让他通过技术面试,但会写上“技能很好,但表达能力一般(或有待提高),请后继面试经理斟酌”。 + + 这样通过后继综合面试的机会就一般了,毕竟综合面试会着重考察表达能力交往能力等非技术因素。 + + 不管怎样,一旦回答简单,不主动说出你的擅长点,或没有条理很清楚地说出你的亮点,就算我让你通过面试,也不会写上“框架细节了解比较深,数据库应用比较熟练”等之类的好评语,你即使通过技术和后面的综合面试,工资也是比较低的。 + +## 一旦有低级错误,可能会直接出局 + + 面试过程中有些方面你是绝对不能出错,所以你在准备过程中需要尤其注意如下的因素。下面列了些会导致你直接出局的错误回答。 + +![](http://img.dabin-coder.cn/image/20220711000758.png) + +## 学会引导 + +引导篇:准备些加分点,在介绍时有意提到,但别说全 + + 在做项目介绍的时候,你可以穿插说出一些你的亮点,但请记得,不论在介绍项目还是在回答问题,你当前的职责不是说明亮点而是介绍项目,一旦你详细说,可能会让面试官感觉你跑题了。 + + 所以这时你可以一笔带过,比如你可以说,“我们的项目对数据要求比较大,忙的时候平均每小时要处理几十万条数据”,这样就可以把面试官引入“大数据”的方向。 + + 你在面试前可以根据职位的需求,准备好这种“一笔带过”的话。比如这个职位的需求点是Spring MVC框架,大数据高并发,要有数据库调优经验,那么介绍以往项目时,你就最好突出这些方面你的实际技能。 + +## 你可以引导,但不能自说自话 + + 如果你真的想应聘的话,一定要事先准备,只要别露出太明显的痕迹,面试官不会写上“似乎有准备,没法考察真实技能”这种话,更何况未必每个面试官都能感觉出你准备过。 但你不能凭着有准备而太强势,毕竟面试是面试官主导的。 + + 有时说话太多,主动扩展,问他数据库用什么,不仅回答数据库是什么,自己做了什么,甚至顺便会把大数据处理技术都说出来。其实可能会过犹不及,面试官就会重点考察你说的每个细节,因为怀疑你说的都是你从网上看的,而不是你项目中用到的。 + + 不过话说回来,他如果仅仅说,数据量比较大,但点到为止,不继续说后面的话,我就会深入去问,他自然有机会表达。同时请注意,一般在面试过程中,一旦你亮出加分点,但面试官没接嘴,这个加分点可能就不是项目必备的,也不是他所关注的,当前你就可以别再说了,或者等到你提问题的时候再说。 + +## 总结 + + 到这里,我们已经给出了介绍项目的一些技巧。这些技巧都是从 java web轻量级开发面试教程从摘录的。 + + 两句话,第一,面试前一定要准备,第二,本文给出是的方法,不是教条,大家可以按本文给出的方向结合自己的项目背景做准备,而不是死记硬背本文给出的一些说辞。 + + 当大家介绍好项目背景后,面试才刚刚开始,哪怕你说得再好,哪怕你把问题引导到你准备的范围里,这也得应付Java Web(比如Spring MVC,ORM等)、Java Core(多线程、集合、JDBC等)和数据库等方面的问题。希望大家有所收获。 + + + +> 链接:https://www.nowcoder.com/discuss/150755 \ No newline at end of file diff --git a/docs/campus-recruit/resume.md b/docs/campus-recruit/resume.md new file mode 100644 index 0000000..c34be4d --- /dev/null +++ b/docs/campus-recruit/resume.md @@ -0,0 +1,136 @@ +--- +sidebar: heading +--- + +很多同学刚开始找工作时,投出去很多简历,但是都石沉大海了,没有下文。 + +要知道,很多大公司HR经常一天要看几百份,甚至上千份简历,基本都是10秒内看一份简历,就是这**关键的10秒**,HR就决定了是进入面试还是PASS。因此,**掌握好写简历的技巧**非常重要! + +接下来聊一下怎么写好简历。 + +分成以下几个方面: + +- **简历模板** +- **基本信息** +- **教育经历** +- **专业技能** +- **项目经历(实习经历、工作经历)** +- **奖项荣誉** + +这些都是一个简历必要的信息。 + +## 简历模板 + +像我们搞技术的,选个简约的模板就可以了,不要太多花哨的东西,简历太过花里胡哨,往往会引起HR和面试官反感,很有可能就失去了这次面试机会。 + +像下面这份简历就是反例,不够简洁,不仅不能吸引到面试官,反而更容易被面试官PASS掉。 + +![](http://img.dabin-coder.cn/image/image-20210903002410309.png) + +而下面这份简历,相比之下就整洁很多,看起来清爽很多,也是我自己个人在用的简历模板。 + +![](http://img.dabin-coder.cn/image/image-20210904111225259.png) + +要注意,简历上不要出现错别字,如果简历上出现错别字,会给HR或者技术面试官留下很不好的印象。**所以写完简历以后一定要仔细检查,可以让朋友帮忙检查一下**。 + +还有比较重要的一点是,简历的格式保存为**PDF**之后,再往招聘网站或者邮箱投递,**不要使用word格式的**,因为word很多版本,容易出现版本不兼容的情况,导致排版混乱,影响你的面试。 + +## 基本信息 + +个人信息主要有: + +**姓名**:这个不用说了,总不该写错吧。 + +**电话**:记住填写自己常用的手机号码,有些同学有多个号码的,更要注意!还有就是,千万别写错号码,写错了用人方想电话联系就联系不上了,很可能就错过了这次机会。 + +**电子邮箱**:这个跟电话一样,也是很重要的联系方式。很多笔试面试邀请都是通过邮箱发出,offer发放也是直接发到邮箱,不可以出错。至于用什么邮箱,随个人喜好,保证能正常收到邮件就行。 + +**求职意向**:写明岗位,后端、前端、测试、运维等等。建议每投一个简历,把应聘岗位这一栏修改为对应要投的岗位名称,显得更有诚意,不要一份简历投遍所有公司。 + +**工作年限**:应届生,实习生等不需要写,工作的小伙伴就写上对应的年限。很重要的一点就是,不要造假,实事求是! + +**博客/开源项目**:没有的话,可不写。如果你有好的开源项目或者博客,面试会很加分。但是要有一定的含金量,不是烂大街的项目或者博客。 + +## 教育经历 + +教育经历的时间一般都是**从后往前**的,最高学历放在首位,记得千万不要学历造假! + +成绩排名这块,有个**小技巧**。如果你专业排名前5 ,那么可以直接写年级排名/总人数,比如 5/100 。如果你专业排名不高,那么建议换成Top 20%这样的描述,比 起20/100,看起来印象会更好。 + +## 专业技能 + +见过很多同学简历上出现精通两个字,精通Java、精通MySQL、精通Redis等等,切记不要用这个词,面试官自己可能都不敢说自己精通。一般写熟悉或者熟练掌握等,当然如果你真的牛,能够扛得住面试官的灵魂拷问,那写上精通也没问题。 + +可以到招聘网站上看看应聘岗位的岗位要求,下面是阿里巴巴国际事业部Java开发岗位的要求: + +![](http://img.dabin-coder.cn/image/image-20210904110034702.png) + +基本就是Java基础、并发、数据库、中间件、框架等,可以参考以下优秀模板: + +![](http://img.dabin-coder.cn/image/image-20220711224619409.png) + +要注意的地方: + +- **专业名词要写对**,区分好大小写,比如Java不要写成java或者JAVA、MySQL不要写成mysql等,注重细节,力争做好每一步。 +- **不要写一些跟技术无关的东西**,比如"PS/PR"、"驾照"、"会用OFFICE"、""会重装系统"等等... +- **最好不要写一些使用 xx 的经验**,比如接入微信 /支付宝支付、接入友盟分享SDK等等,这种基本对着文档撸就好了,没必要写上去。除非特别有技术含量的。 + +## 项目经历 + +项目经历(实习经历、工作经历)非常重要,建议按照以下格式来写。 + +> 对于校招来说,实习是很大的加分项!小伙伴们有机会能去实习的,一定要去实习! + +**项目名称**:主要负责的项目。 + +**项目介绍**:简要描述项目背景、项目内容。 + +**技术栈**:列举项目中的技术栈,如果是当下比较流行的技术,那面试的时候会比较加分。不是比较大众的技术也没关系,只要对所用的技术有深入的了解,面试的时候也能打动面试官。 + +**项目职责**:写清楚你在项目中的角色,以及个人职责,具体负责哪一块业务等等。可以重点突出**攻克的技术问题**,或者参与过的**性能优化**(最好有**数据支撑**,比如SQL执行时间从10秒到50毫秒、xx优化给公司节省了100w的服务器成本等),这些在面试中很加分,比较能体现个人的实战能力。 + +下面是一份写的还不错的简历(来源:牛客网),截取了项目经历部分,写的还不错,大家可以参考下。 + +![](http://img.dabin-coder.cn/image/image-20220711230732013.png) + +**注意**: + +1、**写到简历上的项目,一定是自己比较熟悉的,**面试官可能会深挖里面的一些细节,为什么这么设计,有没有其他替代方案等等,只有自己亲手做过的项目,才能应对面试官的逼问,不然很容易就gg了。 + +2、**项目数量不建议太多**,一般2-3个就可以了,把最有亮点的放在第一个。 + +3、**简历上的项目要贴合岗位要求**,比如你投的岗位是Java后端开发工程师,那么不建议在简历上写嵌入式、算法等不相关的项目。很多转行的同学可能就有这个问题。 + +4、**项目经历可以适当包装**,不要太离谱,能够自圆其说就可以。 + +5、**避免流水账式的介绍**,有部分同学会把项目经历写成日记一样,比如"从 xx 年开始做,先经历了 xx,然后发生了 xx"等等,洋洋洒洒几百字,非常不建议这么写。 + +6、**技术无关、很空泛的东西少写**,比如负责项目应用软件开发编码工作、编写相关的技术文档、提供技术支持等等,写了等于没写,没有提供有效的信息。 + +关于项目经历这块,面试常见的问题: + +- 负责项目的哪块内容? +- 选用这些技术的原因? +- xx功能怎么设计? +- 项目中遇到过什么疑难Bug? +- 使用一些开源框架的时候有没有遇到什么问题,怎么解决的? +- ... + +## 奖项荣誉 + +校招的话,如果拿到奖学金、ACM比赛拿过奖,可以写上去,会很加分。有些公司还很看重四六级证书,如果四六级比较高分,也可以放上去。 + +社招的话,一般比较看重项目经验,这一块可以弱化。 + +![](http://img.dabin-coder.cn/image/image-20210904102957363.png) + + + +以上就是一份简历必要的基本信息了,希望对你有帮助! + + + +另外,大彬精心整理了**23套精美简历模板**,有需要的小伙伴可以自行下载: + +[23套精美简历模板](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247489358&idx=1&sn=dd1b91f115438c29a4215c674b8761e4&chksm=ce98ea08f9ef631e2c8361269f28c01db73eca1ff5b91ba0a0ec8c9a6b9fdcb46a5e16c57020#rd) + diff --git a/docs/campus-recruit/share/1-23-backend.md b/docs/campus-recruit/share/1-23-backend.md new file mode 100644 index 0000000..a866f33 --- /dev/null +++ b/docs/campus-recruit/share/1-23-backend.md @@ -0,0 +1,108 @@ +--- +sidebar: heading +--- + +# 双非本,非科班的自我救赎之路 + +大家好,我是大彬~ + +今天跟大家分享一位学弟的**秋招经历**,他跟大彬一样,也是**非科班转码**的,在今年这样的环境下,能成功”上岸“,非常不容易。 + +![](http://img.dabin-coder.cn/image/image-20221113224821052.png) + +接下来一起看看他的经历(学弟花了周末两天时间写的,整整**5000**多字,非常用心),希望他的分享能帮助到正在参加校招的小伙伴们,以及后面的学弟学妹们! + +## 背景介绍 + +先简要说说我的基本情况吧,本人就读于山西某**二本**院校,专业生物方向。 + +大一期间,借助学校的平台报了一个非全的计算机专业的第二学历。 + +大二下开始真正接触到Java。 + +大三下学期(今年上半年)找到了一份实习,下半年七月开始投递简历,于是便打响了我的秋招之战,直到10月下旬,才有两家小公司的意向,其中一家为蚂蚁集团旗下某子公司,base又在老家郑州,也算是符合我的预期。诚然,不敢和大佬相比,本人既无学历光环,手中也无大厂offer。 + +但正如大彬网站首页所说:“**作为一名转码选手,深感这一路的不易**”,这一路走来也踩过不少坑,也积累了不少自己的见解,在这里和大家分享下我的经验,同时也当做是对我这两年的一个总结。大家有不同意见的,欢迎交流。 + +![](http://img.dabin-coder.cn/image/image-20221113224616682.png) + +## 修炼历程 + +### 我是如何与Java结缘的? + +都说兴趣是最好的老师,可能大多数转码的同学和我一样,基于各种原因对自己本专业没有学习的欲望。 + +我个人很喜欢理工科,恰巧大一军训结束后,我看到学校可以报一个非全的第二专业,然后就选择了计科。但真正和Java结缘是在大二,大一的时候学的都是像离散数学、操作系统、计算机网络原理这些科目,因为纯靠自学而且这些又都是计算机的底层知识(后来发现很有用),当时差点劝退我这个小白,于是就给自己制定了一个方针:“第一学历的考试及格就行,第二学历尽量认真去学”,就这样坚持了一个学期,后来经过验证,两边都没有耽误,效果还不错。但这时候我对于计算机的理解也仅仅只是那些理论上的东西,完全不知道如果要靠它吃饭的话需要具体学哪些东西又需要学到哪种程度? + +转机出现在大二下学期,因为需要学Java这门课,这也是我接触到的第一种编程语言(后来也学习了c++),然后一位朋友给我分享了B站老杜的Java教程,就发现Java不仅可以开发很酷的网站,也可以做出自己的小游戏,这就像打开了编程世界的大门,这些新奇的事物一扫前期理论知识带给我的枯燥感,每一个都吸引着我去不断的靠近它们,就这样我的Java修炼之路便开始了...... + +### 如何安排学习? + +>相信绝大多数的自学者都是按照网上的路线走的,但是学习路线上的内容那么多,我们需要从校招面试的角度去分析哪些是“常考点”,哪些是“低频考点”,这样我们才能把时间花在刀刃上,做到有针对性的准备校招。下面分享下本人的几点见解: + +- **JavaSE:**这一块我是分 **Java语言特性 + JUC + JVM**由浅入深逐渐去学习的。 + - **Java语言特性**:首先一定要熟练掌握语法,了解其新特性比如函数式编程、stream流的使用等。再者,像集合、IO流、反射、JDK动态代理、多线程这几块是高频面试题,尤其是集合方面,举个例子:面试官可能会以Map为切入点,问你HashMap的put流程,然后延伸到在JDK1.7和1.8的多线程环境下put的时候分别会出现什么问题?出现该问题的原因以及如何解决?像这种情况就得多背八股文了,有精力的也可以去扒源码来加深自己的理解。 + - **JUC:** 并发编程几乎也是**必问**,通过学习JUC能帮助你理解大部分问题。它考察的方式也很灵活,比如面试官可以直接问你理论知识,像线程池的七大参数、四种拒绝策略、线程池的执行原理等等,也可以给你一个场景让你去设计代码考察你的coding能力,我就曾经遇到过这样一个场景“项目中有一个main方法,执行具体的核心业务逻辑前需要开两个线程先校验参数,待参数校验完毕后,main方法才能执行核心业务逻辑,如何设计你的代码实现此需求?” 如果你对JUC下不太了解的话可能就会没有思路,反之,可能你一下子就会想到有一个CountDownLatch的类能解决这个问题。除此之外,像各种锁:ReentrantLock、Synchronized以及Synchronized是否被static关键字修饰、读写锁、可重入锁、CAS等、生产者和消费者问题、集合类不安全的解决方案等等,如果这些不理解的话,面试官随便问一下细节可能你就懵了。因为这一块知识稍微有点难度,建议大家在学习的时候可以从视频入门,在学习的过程中一定不要懒,自己多动手用代码去验证、去实现、弄懂它的大致原理,如果想在深入的话可以去网上找找大佬写的优质博客或读一些相关的书籍。 + - **JVM:** 对付校招的话,出现频率高的像JVM的内存区域,垃圾回收算法以及老年代用什么算法,CMS和G1的区别,程序计数器有什么用,虚拟机栈是否存在溢出以及什么情况下会溢出等等此类问题...我参考的是[**大彬的网站**](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247489295&idx=1&sn=9f82abc8f30b1d05ec7b50f25001e815&chksm=ce98ea49f9ef635f7b6eb0bbd5a22f5d38a113e46290241012e0bd3b5bc3248d773b4be144ee&token=1644038503&lang=zh_CN#rd)。不知道大家有没有遇到过这样的情况,比如你百度一个面试题,要么出来的是长篇大论(讲的很细,内容很多),要么寥寥几句,如果你直接按照搜来的答案说的话,要么很费时间,要么说不了几句就没了,而大彬网站中的大多数问题的答案属于你可以一字不用改动直接背给面试官的那种。当然,大家如果时间允许并且想要了解某个技术细节的话,不能只囫囵吞枣,还是要沉下心慢慢去思考的。 +- **算法:**经常听到有小伙伴问“算法到底要不要刷”,大家不坚定的态度无外乎是因为“工作中用不到”、“算法晦涩难懂,学起来枯燥”、“投入产出比高,需要长期投入才有效果”这几个因素。我想告诉大家的是,如果你想冲击大中厂的话,一定要去刷。就拿我这次秋招来说,做了几十家的笔试题,80%以上都有算法,更何况笔试是你秋招的第一道关卡,如果你算法题做不出来的话连面试都很难进。那如何规划呢,我的建议是如果你时间充足的话(比如正在大二或者大三上),学完JavaSE就能开始刷题了,这样一边刷题一边还能让你掌握语言特性。但是时间不充足的话(比如马上要找实习了技术栈还没学完,或者马上面临校园招聘了),这种情况下我还是建议先完善自己的技术栈,起码先把自己的技术体系形成闭环,待找到实习(工作)后再抽时间刷(我就是后者)。所以说,干什么都要趁早,**早,就是优势**。至于如何刷题,推荐大家去刷代码随想录,然后再刷剑指offer上的那70多道,两者加上接近三百道题了,(这时候已经能手撕大多数企业的题了),时间充裕的话还可以再刷刷hot100。注意,算法题也是需要**多多回顾**的,刷一遍是绝对不够的,建议多刷几遍,这样才能形成自己的理解做到活学活用。 + +- **数据库:** + + - MySQL:面试官经常从“MySQL架构、索引原理、事务原理与锁机制、日志机制、存储引擎执行细节”这几个方面去考察,也有一些笔试题中会出现场景题让你编写SQL。我推荐大家可以先过一遍小林的图解MySQL,这个讲的比较细也比较基础,然后有了基础之后再去看一下《MySQL45讲》会轻松很多,而且里面有很多真实的场景,你也可以稍加修饰吸收成你自己的经验来和面试官进行掰扯,45讲看完之后其实对数据库的各类面试题理解起来就很容易了,此时等到面试前再突击下大彬的MySQL面试题,效率直接起飞。至于SQL场景题的话,只能多练了,这个大家可以去牛客上刷SQL的在线编程题,刷到“SQL进阶挑战”完全就够了,不仅是应付笔试,面对以后工作用到的CRUD也是绰绰有余。 + - Redis: 面试常从“底层数据结构,主从复制,持久化、缓存一致性”等角度考察,学习路线和MySQL差不多,也是小林的图解 + 大彬的面试题 + +- **各种框架:** + + - 首先我想说一下框架在面试中的比重,大厂问的比较少,反倒小公司会问的多一点。该学到哪种程度呢,至少是springboot,像微服务那些是加分项,大厂的话不会太看中你的技术栈有多新,它们更注重你的基础。所以我觉得技术栈的话学到boot就没多大问题了,可以将后面的时间用来夯实你的基础。 + - 如何学习框架 + - 初级阶段:建议还是以视频为主吧,这样入门很快,毕竟框架也是实操性较强的东西,直接看视频效果会更直观一点。 + - 运用阶段:学完框架之后,就一定得多练多敲,一方面强化记忆,另一方面增强对这门技术的熟练度。比如可以从B站上找一个小项目练练手,或者从开源平台上找一些相关的Demo自己调试一下让它跑起来,扒开它的源码看自己能不能优化、改造某个功能等。这些都能让你快速升级,熟练掌握技术栈并养成自己的编程思想。 + - 质变阶段:当你对各类技术栈的使用已相当熟练,你可以去选择专攻某一个模块。比如你可以去研究spring中的某一个组件,比如Bean组件,IOC容器等。除此之外java中的轮子有很多,你也可以自己实现一个功能全面的rpc框架,也能写到你的简历上面,也能和面试官聊上一阵。 + +- **计算机基础:** + + 首先希望大家清楚,任何新技术的出现,都是为了完善旧技术的缺点,我们有学不完的技术,但是计算机基础的知识是永远不会变的。假如你不懂网络原理,可能你理解前后端用HTTP进行交互时就比较抽象、也无法实现自己的rpc框架...如果你不了解操作系统,也很难理解Redis中的大key对持久化的影响...对于校招来说,只需要好好准备操作系统和网络原理就行了。B站上也有很多资源,像王道考研的OS和网络,八股文的话可以看小林的图解,然后在看看大彬的面试题。 + + >可能细心的小伙伴已经发现了,我的路线总结下来基本上是 大彬 (面试)+ 小林图解(基础八股) + 代码随想录(刷题) + +### 遇到问题如何解决? + +>有句话是“旁观者清,近观者迷”,自学的过程本身就是孤独的,在这个过程中我们肯定也会遇到很多大大小小的问题,有时候自己碰到一个没法解决的问题就会陷在一个死胡同里好几天,不仅耽误学习进度,严重的时候还会影响我们的学习士气。当遇到这些情况时我们就要虚心地向别人请教、提问。我也加了很多的技术交流群,下面分享一下我对于"提问"的经验。 + +- 提问之前 + - 我们一定要尝试自己解决,不是说一遇到问题自己都懒得思考就直接去提问,可以和小伙伴交流、通过网上搜索,查阅一些论坛社区等手段来解决问题 + - 如果实在不能解决,就要梳理好自己要问什么,整理好你要表达的话语,尽量做到准确,简明,让别人一看就能明白你不懂的地方在哪。 +- 怎样提问 + - 第一点:因为你是求助者,一定要虚心。如果没有人回答你的问题也不要阴阳怪气,交流群本身是用来交流技术分享经验的一个地方。 + - 第二是准确描述你的问题的前因后果,比如你做过什么样的尝试,得到了什么样的结果,你想要的结果是什么 + +## 实习与秋招 + +>先插一句:无论是找实习还是准备秋招,**一定要趁早,早就是优势,早就代表着更多的机会!** + +### 我的实习历程 + +深知自己与别人的差距,于是我上半年二月份就开始在网上投实习的简历了,到四月底的时候找到了杭州一家公司,我仍清晰地记得那天收到offer时的心情,走上Java这条路以来,第一次感受到了被认可,这也给了我很大的一个信心让我坚定地在这条路上一直走下去。 + +相信大多数实习生进公司之后面对的都是边缘业务的CRUD,接触不到项目的核心,你如果想要得到更多的收获就得主动去找mentor要一些有挑战性的活,比如我实习期间承担难度最大的一件事就是完成了项目中分布式WebSocket的开发,从一开始确定技术解决方案,然后同mentor一起验证方案的可行性,再到具体编码实现,在整个流程中学到了很多东西,这后来也成为了我经常和面试官对线的地方,四个月的实习也是我成长最快的一段时间。 + +总之,我想告诉大家的是,如果自己的起点就比别人低,那就得自己去**争取更多的机会**,这样才能使自己一直**保持着竞争力**。 + +### 我的秋招历程 + +在实习期间的时候,我就开始投递了一小部分提前批(全GG),因为当时是七月份,并没有意识到到今年秋招的寒气,到八月份的时候我就辞职了,便全身心的转移到了秋招的战线上。 + +直到八月末九月初的时候已经投了100家左右,也做了将近二十多家的笔试,算法题平均都能a个75%,但是仅收到了两家面试,面试过程也都还算顺利,但还是都挂了,这个时候已经意识到形势的严峻了,我已经开始有点慌了,中间甚至有过放弃的念头,但我的直觉告诉我不能就这样灰头土脸的收场,无论结果怎样都要给自己一个合理的交代。 + +后来就每天边做笔试边投简历,也转变了投递策略,不能只局限在牛客和力扣上找公司,智联、BOSS、51JOB、甚至在抖音上碰到博主推的公司也开始投,全面广撒网。就这样战线一直拉到十月下旬。 + +两个月的秋招战线,可以说是我整个Java之路上最难熬的一段时间,经历了多次面试前的紧张、面试后的期待、收到感谢信后的失望,也感谢自己没有放弃吧,最后也算是拿到了这一行的敲门砖。 + +## 心得感悟 + +汝之蜜糖,彼之砒霜,这里引用某位网友的一段话“每个人都应经过自己的摸索,找到适合自己的路线。不管是应届生参加校招,还是在校生找实习,求职的过程都注定是**艰难且孤独**的,这时候不光要拼学历门槛、技术能力、语言表达能力,还要拼谁能沉得住气,谁能扛得住一次又一次面试失败后的打击。面试招聘常有金三银四和金九银十的说法,但这都是一个理想状态,在你实力没那么强的情况下,求职可能是一个比较长期的过程。不要给自己设置deadline,不是说十月之后就没有招聘,十月十一月,十二月,可能一家公司结束了招聘,又会有另外一家开始招聘。有人五月份六月份才拿到实习offer,而也有人在临近毕业五月甚至六月的时候才拿到自己满意的offer,一直面下去,**多复盘**,会有好结果的。” + +## 致谢 + +每个人在修炼的路上都是孤独的,我们只有怀着宗教般的意志和初恋般的热情,做任何事情都要抱着“流水不争先,争的是滔滔不绝”的态度去不断地提升自己,才有可能成就某种事业。作为一枚菜鸟小白,一路走来,受到了不少大佬的帮助,感谢我的那位朋友,感谢大彬,感谢卡哥,感谢小林,你们的帮助给这条路上的小白注入了源源不断的动力。最后,祝愿大家考研、找工作的伙伴都能顺利上岸! + diff --git a/docs/campus-recruit/share/2-no-offer.md b/docs/campus-recruit/share/2-no-offer.md new file mode 100644 index 0000000..cba7d19 --- /dev/null +++ b/docs/campus-recruit/share/2-no-offer.md @@ -0,0 +1,56 @@ +--- +sidebar: heading +--- + +# 非科班,秋招还没offer,该怎么办 + +前两天有个学弟微信私聊我,他是非科班的(985硕士,机械专业),因为秋招准备的比较晚,目前还没拿offer,感觉秋招已经没希望了,只能春招再战了。学弟很焦虑,作为一个985硕士,周围很多人都拿到offer了,只有他还在“苦苦挣扎”,问我有没有什么**学习建议**? + +学弟目前**基本情况**如下: + +**已经学习的知识**: + +- 计算机基础:操作系统、数据结构 、计网、组成原理、数据库 +- Java 基础、集合、JVM、Java并发 +- 框架:Spring Boot、Mybatis、SpringMVC、Spring Cloud +- LeetCode 刷了几百道题 +- 其他的像Redis、RabbitMQ、Kafka这些都学了 + +项目经验是烂大街的秒杀系统,没有什么亮点。 + +因为我也是非科班出身,比较了解转码人秋招的“**痛**”,周末花了时间整理了一下,给了几点**建议**: + +## 校招是最好的机会 + +一定要明白**校招的重要性**,如果校招没拿到offer,那么只能走社招,而社招跟校招的难度不是一个级别的,看重的是你的项目经历,只会更难。无论是秋招,还是春招,对于应届毕业生来说,都是拿offer的最好机会,一定要抓住这个机会!秋招没把握住机会,那么春招更应该加足马力,争取拿到满意的offer。 + +## 实习经验很重要 + +**特别对于非科班同学**。如果现在还没有实习经验,最好找一下实习。非科班选手,如果不是名校出身,学历不够突出,没有相关实习经验,可能简历都过不了。 + +## 项目经验同样很重要 + +现在大部分应届生简历上的项目都是秒杀商城、RPC、外卖系统等等,这些项目也不是说没亮点,只是亮点都差不多,给人的感觉就是抄网上现成的,不是从头到尾自己实现的。假如面试时让你介绍一下这个项目,**你觉得这个项目亮点在哪里?你自己实现的功能有哪些?有没有其他解决方案**?这些都是需要自己仔细去考虑的。 + +可以看看类似的开源项目,取长补短,**包装**自己的项目经验,当然,包装要适度,要经得住面试的“灵魂拷问”,否则得不偿失。 + +## 面向面试准备 + +多在网上搜索面经,看看心仪的公司面试是个什么难度,喜欢考察什么类型的问题,思考怎么去准备,有**针对性**的进行查漏补缺。 + +## 关于算法题 + +学弟刷了400道LeetCode题目了,如果不是“无效刷题”,其实已经完全够用了。挺多人刷题量非常大,但是到最后发现还是效果不好,一道题做完之后,隔了半个月再来看,依旧一头雾水,这样刷再多题也没用。**建议是每刷完一道题,将解题思路写下来**,方便后续复习查看,这样刷题的效率会更高。 + +## 抓住秋招的尾巴 + +**秋招尚未结束,抓住秋招的尾巴**。11月-12月这个时间段,会有公司针对秋招时没有招满的岗位进行补录,要抓住这个机会。秋招补录的流程很快,一般只有整个流程几天内可以走完。 + + + + + +最后,如果秋招面试过程有疑问、offer抉择问题、简历问题等,可以扫码加大彬的微信交流~ + +![](http://img.dabin-coder.cn/image/个人微信索隆.jpg) + diff --git a/docs/campus-recruit/share/README.md b/docs/campus-recruit/share/README.md new file mode 100644 index 0000000..38c2a9b --- /dev/null +++ b/docs/campus-recruit/share/README.md @@ -0,0 +1,5 @@ +# 校招分享(持续更新中) + +- [双非本,非科班的自我救赎之路](./1-23-backend.md) +- [非科班,秋招还没offer,该怎么办](./2-no-offer.md) + diff --git a/docs/computer-basic/algorithm.md b/docs/computer-basic/algorithm.md new file mode 100644 index 0000000..f0111d4 --- /dev/null +++ b/docs/computer-basic/algorithm.md @@ -0,0 +1,1440 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/数据结构与算法.jpg) + +## 二叉树的遍历 + +二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。 + +二叉树的先序、中序和后序属于深度优先遍历DFS,层次遍历属于广度优先遍历BFS。 + +![](http://img.dabin-coder.cn/image/前序中序后序.png) + +四种主要的遍历思想为: + +前序遍历:根结点 ---> 左子树 ---> 右子树 + +中序遍历:左子树---> 根结点 ---> 右子树 + +后序遍历:左子树 ---> 右子树 ---> 根结点 + +层次遍历:只需按层次遍历即可 + +### 前序遍历 + +遍历思路:根结点 ---> 左子树 ---> 右子树。 + +根据前序遍历的顺序,优先访问根结点,然后在访问左子树和右子树。所以,对于任意结点node,第一部分即直接访问之,之后在判断左子树是否为空,不为空时即重复上面的步骤,直到其为空。若为空,则需要访问右子树。注意,在访问过左孩子之后,需要反过来访问其右孩子,可以是栈这种数据结构来支持。对于任意一个结点node,具体步骤如下: + +1. 访问结点,并把结点node入栈,当前结点置为左孩子; +2. 判断结点node是否为空,若为空,则取出栈顶结点并出栈,将右孩子置为当前结点;否则重复a)步直到当前结点为空或者栈为空(可以发现栈中的结点就是为了访问右孩子才存储的) + +```java + +public void preOrderTraverse2(TreeNode root) { + LinkedList stack = new LinkedList<>(); + TreeNode pNode = root; + while (pNode != null || !stack.isEmpty()) { + if (pNode != null) { + System.out.print(pNode.val+" "); + stack.push(pNode); + pNode = pNode.left; + } else { //pNode == null && !stack.isEmpty() + TreeNode node = stack.pop(); + pNode = node.right; + } + } +} +``` + +### 中序遍历 + +遍历思路:左子树 ---> 根结点 ---> 右子树 + +```java + public List inorderTraversal(TreeNode root) { + List res = new ArrayList<>(); + Deque deque = new ArrayDeque<>(); + + while (!deque.isEmpty() || root != null) { + while (root != null) { + deque.push(root); + root = root.left; + } + root = deque.pop(); + res.add(root.val); + root = root.right; + } + + return res; + } +``` + +### 后序遍历 + +遍历思路:左子树 ---> 右子树 ---> 根结点。 + +使用 null 作为标志位,访问到 null 说明此次递归调用结束。 + +```java +class Solution { + public List postorderTraversal(TreeNode root) { + List res = new LinkedList<>(); + if (root == null) { + return res; + } + + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + root = stack.pop(); + if (root != null) { + stack.push(root);//最后访问 + stack.push(null); + if (root.right != null) { + stack.push(root.right); + } + if (root.left != null) { + stack.push(root.left); + } + } else { //值为null说明此次递归调用结束,将节点值存进结果 + res.add(stack.pop().val); + } + } + + return res; + } +} +``` + +### 层序遍历 + +只需要一个队列即可,先在队列中加入根结点。之后对于任意一个结点来说,在其出队列的时候,访问之。同时如果左孩子和右孩子有不为空的,入队列。 + +``` +public void levelTraverse(TreeNode root) { + if (root == null) { + return; + } + LinkedList queue = new LinkedList<>(); + queue.offer(root); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + System.out.print(node.val+" "); + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } +} +``` + +## 排序算法 + +常见的排序算法主要有:冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、基数排序。各种排序算法的时间空间复杂度、稳定性见下图。 + +![](http://img.dabin-coder.cn/image/排序算法时间空间复杂度.png) + +### 冒泡排序 + +冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 + +思路: + +- 比较相邻的元素。如果第一个比第二个大,就交换它们两个; +- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; +- 针对所有的元素重复以上的步骤,除了最后一个; +- 重复步骤1~3,直到排序完成。 + +代码实现: + +```java +public void bubbleSort(int[] arr) { + if (arr == null) { + return; + } + boolean flag; + for (int i = arr.length - 1; i > 0; i--) { + flag = false; + for (int j = 0; j < i; j++) { + if (arr[j] > arr[j + 1]) { + int tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + flag = true; + } + } + if (!flag) { + return; + } + } +} +``` + +### 插入排序 + +插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 + +算法描述: + +一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下: + +- 从第一个元素开始,该元素可以认为已经被排序; +- 取出下一个元素,在已经排序的元素序列中从后向前扫描; +- 如果该元素(已排序)大于新元素,将该元素移到下一位置; +- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置; +- 将新元素插入到该位置后; +- 重复步骤2~5。 + +代码实现: + +```java +public void insertSort(int[] arr) { + if (arr == null) { + return; + } + for (int i = 1; i < arr.length; i++) { + int tmp = arr[i]; + int j = i; + for (; j > 0 && tmp < arr[j - 1]; j--) { + arr[j] = arr[j - 1]; + } + arr[j] = tmp; + } +} +``` + +### 选择排序 + +表现**最稳定的排序算法之一**,因为**无论什么数据进去都是O(n2)的时间复杂度**,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间。 + +选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。 + +思路:n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下: + +- 初始状态:无序区为R[1..n],有序区为空; +- 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区; +- n-1趟结束,数组有序化了。 + +代码实现: + +```java + public void selectionSort(int[] arr) { + if (arr == null) { + return; + } + for (int i = 0; i < arr.length - 1; i++) { + for (int j = i + 1; j < arr.length; j++) { + if (arr[i] > arr[j]) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + } + } + } +``` + +### 希尔排序 + +希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。 + +**希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。** + +代码实现: + +```java +public static int[] ShellSort(int[] array) { + int len = array.length; + int temp, gap = len / 2; + while (gap > 0) { + for (int i = gap; i < len; i++) { + temp = array[i]; + int preIndex = i - gap; + while (preIndex >= 0 && array[preIndex] > temp) { + array[preIndex + gap] = array[preIndex]; + preIndex -= gap; + } + array[preIndex + gap] = temp; + } + gap /= 2; + } + return array; +} +``` + +### 基数排序 + +基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn),为数组长度,k为数组中的数的最大的位数; + +基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。 + +算法描述: + +- 取得数组中的最大数,并取得位数; +- arr为原始数组,从最低位开始取每个位组成radix数组; +- 对radix进行计数排序(利用计数排序适用于小范围数的特点); + +代码实现: + +```java +public static int[] RadixSort(int[] array) { + if (array == null || array.length < 2) + return array; + // 1.先算出最大数的位数; + int max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + int maxDigit = 0; + while (max != 0) { + max /= 10; + maxDigit++; + } + int mod = 10, div = 1; + ArrayList> bucketList = new ArrayList>(); + for (int i = 0; i < 10; i++) + bucketList.add(new ArrayList()); + for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) { + for (int j = 0; j < array.length; j++) { + int num = (array[j] % mod) / div; + bucketList.get(num).add(array[j]); + } + int index = 0; + for (int j = 0; j < bucketList.size(); j++) { + for (int k = 0; k < bucketList.get(j).size(); k++) + array[index++] = bucketList.get(j).get(k); + bucketList.get(j).clear(); + } + } + return array; +} +``` + +### 计数排序 + +计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。 + +计数排序(Counting sort)是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。 + +```java +public static int[] CountingSort(int[] array) { + if (array.length == 0) return array; + int bias, min = array[0], max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) + max = array[i]; + if (array[i] < min) + min = array[i]; + } + bias = 0 - min; + int[] bucket = new int[max - min + 1]; + Arrays.fill(bucket, 0); + for (int i = 0; i < array.length; i++) { + bucket[array[i] + bias]++; + } + int index = 0, i = 0; + while (index < array.length) { + if (bucket[i] != 0) { + array[index] = i - bias; + bucket[i]--; + index++; + } else + i++; + } + return array; +} +``` + + + +### 快速排序 + +快速排序是由**冒泡排序**改进而得到的,是一种排序执行效率很高的排序算法,它利用**分治法**来对待排序序列进行分治排序,它的思想主要是通过一趟排序将待排记录分隔成独立的两部分,其中的一部分比关键字小,后面一部分比关键字大,然后再对这前后的两部分分别采用这种方式进行排序,通过递归的运算最终达到整个序列有序。 + +快速排序的过程如下: + +1. 在待排序的N个记录中任取一个元素(通常取第一个记录)作为基准,称为基准记录; +2. 定义两个索引 left 和 right 分别表示首索引和尾索引,key 表示基准值; +3. 首先,尾索引向前扫描,直到找到比基准值小的记录,并替换首索引对应的值; +4. 然后,首索引向后扫描,直到找到比基准值大于的记录,并替换尾索引对应的值; +5. 若在扫描过程中首索引等于尾索引(left = right),则一趟排序结束;将基准值(key)替换首索引所对应的值; +6. 再进行下一趟排序时,待排序列被分成两个区:[0,left-1]和[righ+1,end] +7. 对每一个分区重复以上步骤,直到所有分区中的记录都有序,排序完成 + +快排为什么比冒泡效率高? + +快速排序之所以比较快,是因为相比冒泡排序,每次的交换都是跳跃式的,每次设置一个基准值,将小于基准值的都交换到左边,大于基准值的都交换到右边,这样不会像冒泡一样每次都只交换相邻的两个数,因此比较和交换的此数都变少了,速度自然更高。 + +快速排序的平均时间复杂度是O(nlgn),最坏时间复杂度是O(n^2)。 + +```java + public void quickSort(int[] arr) { + if (arr == null) { + return; + } + quickSortHelper(arr, 0, arr.length - 1); + } + private void quickSortHelper(int[] arr, int left, int right) { + if (left > right) { + return; + } + int tmp = arr[left]; + int i = left; + int j = right; + while (i < j) { + //j先走,最终循环终止时,j停留的位置就是arr[left]的正确位置 + //改为i<=j,则会进入死循环,[1,5,5,5,5]->[1] 5 [5,5,5]->[5,5,5],会死循环 + while (i < j && arr[j] >= tmp) { + j--; + } + while (i < j && arr[i] <= tmp) { + i++; + } + if (i < j) { + int tmp1 = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp1; + } else { + break; + } + } + + //当循环终止的时候,i=j,因为是j先走的,j所在位置的值小于arr[left],交换arr[j]和arr[left] + arr[left] = arr[j]; + arr[j] = tmp; + + quickSortHelper(arr, left, j - 1); + quickSortHelper(arr, j + 1, right); + } +``` + +### 归并排序 + +归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。 + +两路归并排序算法思路是递归处理。每个递归过程涉及三个步骤 + +- 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素 +- 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作 +- 合并: 合并两个排好序的子序列,生成排序结果 + +![](http://img.dabin-coder.cn/image/20220327151830.png) + +时间复杂度:对长度为n的序列,需进行logn次二路归并,每次归并的时间为O(n),故时间复杂度是O(nlgn)。 + +空间复杂度:归并排序需要辅助空间来暂存两个有序子序列归并的结果,故其辅助空间复杂度为O(n) + +```java +public class MergeSort { + public void mergeSort(int[] arr) { + if (arr == null || arr.length == 0) { + return; + } + //辅助数组 + int[] tmpArr = new int[arr.length]; + mergeSort(arr, tmpArr, 0, arr.length - 1); + } + + private void mergeSort(int[] arr, int[] tmpArr, int left, int right) { + if (left < right) { + int mid = (left + right) >> 1; + mergeSort(arr, tmpArr, left, mid); + mergeSort(arr, tmpArr, mid + 1, right); + merge(arr, tmpArr, left, mid, right); + } + } + + private void merge(int[] arr, int[] tmpArr, int left, int mid, int right) { + int i = left; + int j = mid + 1; + int tmpIndex = left; + while (i <= mid && j <= right) { + if (arr[i] < arr[j]) { + tmpArr[tmpIndex++] = arr[i]; + i++; + } else { + tmpArr[tmpIndex++] = arr[j]; + j++; + } + } + + while (i <= mid) { + tmpArr[tmpIndex++] = arr[i++]; + } + + while (j <= right) { + tmpArr[tmpIndex++] = arr[j++]; + } + + for (int m = left; m <= right; m++) { + arr[m] = tmpArr[m]; + } + } +} +``` + +### 堆排序 + +堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 + +![](https://img-blog.csdn.net/20150312212515074) + +**Top大问题**解决思路:使用一个固定大小的**最小堆**,当堆满后,每次添加数据的时候与堆顶元素比较,若小于堆顶元素,则舍弃,若大于堆顶元素,则删除堆顶元素,添加新增元素,对堆进行重新排序。 + +对于n个数,取Top m个数,时间复杂度为O(nlogm),这样在n较大情况下,是优于nlogn(其他排序算法)的时间复杂度的。 + +PriorityQueue 是一种基于优先级堆的优先级队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头。优先级队列用数组实现,但是数组大小可以动态增加,容量无限。 + +```java +//找出前k个最大数,采用小顶堆实现 +public static int[] findKMax(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>(k);//队列默认自然顺序排列,小顶堆,不必重写compare + + for (int num : nums) { + if (pq.size() < k) { + pq.offer(num); + } else if (pq.peek() < num) {//如果堆顶元素 < 新数,则删除堆顶,加入新数入堆 + pq.poll(); + pq.offer(num); + } + } + + int[] result = new int[k]; + for (int i = 0; i < k&&!pq.isEmpty(); i++) { + result[i] = pq.poll(); + } + return result; +} +``` + + + +## 动态规划 + +动态规划常常适用于有重叠子问题的问题。动态规划的基本思想:若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。 + +动态规划法试图仅仅解决每个子问题一次,一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次遇到同一个子问题的时候直接查表得到解。 + +动态规划的解题思路:1、状态定义;2、状态转移方程;3、初始状态。 + +### 不同路径 + +[不同路径](../leetcode/hot120/62-unique-paths.md) + +### 最长回文子串 + +从给定的字符串 `s` 中找到最长的回文子串的长度。 + +例如 `s = "babbad"` 的最长回文子串是 `"abba"` ,长度是 `4` 。 + +解题思路: + +1. 定义状态。`dp[i][j]` 表示子串 `s[i..j]` 是否为回文子串 + +2. 状态转移方程:`dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]` +3. 初始化的时候,单个字符一定是回文串,因此把对角线先初始化为 `true`,即 `dp[i][i] = true` 。 +4. 只要一得到 `dp[i][j] = true`,就记录子串的长度和起始位置 + +注意事项:总是先得到小子串的回文判定,然后大子串才能参考小子串的判断结果,即填表顺序很重要。 + +![](http://img.dabin-coder.cn/image/image-20201115230411764.png) + +时间复杂度O(N2),空间复杂度O(N2),因为使用了二维数组。 + +```java +public class Solution { + + public String longestPalindrome(String s) { + // 特判 + int len = s.length(); + if (len < 2) { + return s; + } + + int maxLen = 1; + int begin = 0; + + // dp[i][j] 表示 s[i, j] 是否是回文串 + boolean[][] dp = new boolean[len][len]; + char[] charArray = s.toCharArray(); + + for (int i = 0; i < len; i++) { + dp[i][i] = true; + } + for (int j = 1; j < len; j++) { + for (int i = 0; i < j; i++) { + if (charArray[i] != charArray[j]) { + dp[i][j] = false; + } else { + if (j - i < 3) { + dp[i][j] = true; + } else { + dp[i][j] = dp[i + 1][j - 1]; + } + } + + // 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置 + if (dp[i][j] && j - i + 1 > maxLen) { + maxLen = j - i + 1; + begin = i; + } + } + } + return s.substring(begin, begin + maxLen); //substring(i, j)截取i到j(不包含j)的字符串 + } +} +``` + + + +### 最大子数组和 + +**题目描述**:给你一个整数数组 `nums` ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 + +**示例**: + +```java +输入: nums = [-2,1,-3,4,-1,2,1,-5,4] +输出: 6 +解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 。 +``` + +1、首先确定dp数组(dp table)以及下标的含义。 + +dp[i]表示以nums[i]结尾的子数组的最大和。 + +2、确定递推公式。 + +`dp[i] = dp[i - 1] > 0 ? ( dp[i - 1] + nums[i]) : nums[i]` + +dp[i+1]取决于dp[i]的值,不需要使用数组保存状态,只需要一个变量sum来保存上一个状态即可。 + +3、dp数组如何初始化。 + +从递推公式可以看出来dp[i]是依赖于dp[i - 1]的状态,dp[0]就是递推公式的基础。 + +dp[0]应该是多少呢?根据dp[i]的定义,很明显dp[0]应为nums[0]即dp[0] = nums[0]。 + +示例代码如下: + +```java +class Solution { + public int maxSubArray(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + + int max = nums[0]; + int sum = 0; + + for (int num : nums) { + if (sum > 0) { + sum += num; + } else { + sum = num; + } + max = Math.max(max, sum); + } + + return max; + } +} +``` + +### 最长公共子序列 + +一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。 +例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。 + +动态规划。`dp[i][j]`表示text1以i-1结尾的子串和text2以j-1结尾的子串的最长公共子序列的长度。dp横坐标或纵坐标为0表示空字符串,`dp[0][j] = dp[i][0] = 0`,无需额外处理base case。 + +![](http://img.dabin-coder.cn/image/longestCommonSubsequence.png) + +```java +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + char[] arr1 = text1.toCharArray(); + char[] arr2 = text2.toCharArray(); + //dp[0][x]和dp[x][0]表示有一个为空字符串 + //dp[1][1]为text1第一个字符和text2第一个字符的最长公共子序列的长度 + //dp[i][j]表示text1以i-1结尾的子串和text2以j-1结尾的子串的最长公共子序列的长度 + int len1 = arr1.length; + int len2 = arr2.length; + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i < len1 + 1; i++) { + for (int j = 1; j < len2 + 1; j++) { + if (arr1[i - 1] == arr2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[len1][len2]; + } +} +``` + +`dp[i][j]`表示text1以i结尾的子串和text2以j结尾的子串的最长公共子序列的长度。需要处理base case。 + +```java +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + char[] arr1 = text1.toCharArray(); + char[] arr2 = text2.toCharArray(); + + int len1 = arr1.length; + int len2 = arr2.length; + //`dp[i][j]`表示text1以i结尾的子串和text2以j结尾的子串的最长公共子序列的长度。 + int[][] dp = new int[len1][len2]; + + if (arr1[0] == arr2[0]) { + dp[0][0] = 1; + } + for (int i = 1; i < len1; i++) { + if (arr1[i] == arr2[0]) { + dp[i][0] = 1; + } else { + dp[i][0] = dp[i - 1][0]; + } + } + for (int i = 1; i < len2; i++) { + if (arr1[0] == arr2[i]) { + dp[0][i] = 1; + } else { + dp[0][i] = dp[0][i - 1]; + } + } + + for (int i = 1; i < len1; i++) { + for (int j = 1; j < len2; j++) { + if (arr1[i] == arr2[j]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[len1 - 1][len2 - 1]; + } +} +``` + + + +### 接雨水 + +给定 `n` 个非负整数表示每个宽度为 `1` 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 + +![](http://img.dabin-coder.cn/image/接雨水.png) + +示例: + +```java +输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] +输出:6 +解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 +``` + +动态规划,使用两个数组空间。leftMax[i] 代表第 `i` 列左边(不包含自身)最高的墙的高度,rightMax[i] 代表第 `i` 列右边最高的墙的高度。 + +```java +class Solution { + public int trap(int[] height) { + int len = height.length; + int res = 0; + int[] leftMax = new int[len]; + int[] rightMax = new int[len]; + + for (int i = 1; i < len; i++) { + leftMax[i] = Math.max(leftMax[i - 1], height[i - 1]); + } + + for (int j = len - 2; j > 0; j--) { + rightMax[j] = Math.max(rightMax[j + 1], height[j + 1]); + } + + for (int i = 1; i < len - 1; i++) { + int min = Math.min(leftMax[i], rightMax[i]); + if (min > height[i]) { + res += min - height[i]; + } + } + + return res; + } +} +``` + + + +### 单词拆分 + +![](http://img.dabin-coder.cn/image/word-break.png) + +```java +class Solution { + public boolean wordBreak(String s, List wordDict) { + int len = s.length(), maxw = 0; + //dp[i]表示前i个字母组成的字符串是否可以被拆分 + boolean[] dp = new boolean[len + 1]; + //状态转移方程初始化条件 + dp[0] = true; + Set set = new HashSet(); + for(String str : wordDict){ + set.add(str); + maxw = Math.max(maxw, str.length()); + } + for(int i = 1; i < len + 1; i++){ + for(int j = i; j >= 0 && j >= i - maxw; j--){ + if(dp[j] && set.contains(s.substring(j, i))){ + dp[i] = true; + break; + } + } + } + return dp[len]; + } +} +``` + +## 回溯算法 + +回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。 + +### 组合总和 + +题目描述:给定一个**无重复元素**的数组 `candidates` 和一个目标数 `target` ,找出 `candidates` 中所有可以使数字和为 `target` 的组合。 + +示例: + +``` +输入:candidates = [2,3,6,7], target = 7, +输出: +[ + [7], + [2,2,3] +] +``` + +使用回溯算法。 + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> combinationSum2(int[] candidates, int target) { + if (candidates == null || candidates.length == 0) { + return ans; + } + Arrays.sort(candidates);//排序方便回溯剪枝 + Deque path = new ArrayDeque<>();//作为栈来使用,效率高于Stack;也可以作为队列来使用,效率高于LinkedList;线程不安全 + combinationSum2Helper(candidates, target, 0, path); + return ans; + } + + public void combinationSum2Helper(int[] arr, int target, int start, Deque path) { + if (target == 0) { + ans.add(new ArrayList(path)); + } + + for (int i = start; i < arr.length; i++) { + if (target < arr[i]) {//剪枝 + return; + } + if (i > start && arr[i] == arr[i - 1]) {//在一个层级,会产生重复 + continue; + } + path.addLast(arr[i]); + combinationSum2Helper(arr, target - arr[i], i + 1, path); + path.removeLast(); + } + } +} +``` + + + +### 全排列 + +给定一个 **没有重复** 数字的序列,返回其所有可能的全排列。 + +示例: + +``` +输入: [1,2,3] +输出: +[ + [1,2,3], + [1,3,2], + [2,1,3], + [2,3,1], + [3,1,2], + [3,2,1] +] +``` + +使用回溯。注意与组合总和的区别(数字有无顺序)。 + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> permute(int[] nums) { + boolean[] flag = new boolean[nums.length]; + ArrayDeque path = new ArrayDeque<>(); + permuteHelper(nums, flag, path); + + return ans; + } + + private void permuteHelper(int[] nums, boolean[] flag, ArrayDeque path) { + if (path.size() == nums.length) { + ans.add(new ArrayList<>(path)); + return; + } + for (int i = 0; i < nums.length; i++) { + if (flag[i]) { + continue;//继续循环 + } + path.addLast(nums[i]); + flag[i] = true; + permuteHelper(nums, flag, path); + path.removeLast(); + flag[i] = false; + } + } +} +``` + + + +### 全排列II + +给定一个可包含重复数字的序列,返回所有不重复的全排列。注意与组合总和的区别。 + +1、排序;2、同一层级相同元素剪枝。 + +![](http://img.dabin-coder.cn/image/permutations-ii.png) + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> permuteUnique(int[] nums) { + if (nums == null || nums.length == 0) { + return ans; + } + ArrayDeque path = new ArrayDeque<>(); + boolean[] used = new boolean[nums.length]; + Arrays.sort(nums);//切记 + dps(nums, used, path); + + return ans; + } + + private void dps(int[] nums, boolean[] used, ArrayDeque path) { + if (path.size() == nums.length) { + ans.add(new ArrayList<>(path)); + return; + } + for (int i = 0; i < nums.length; i++) { + if (used[i]) { + continue; + } + if ((i > 0 && nums[i] == nums[i - 1]) && !used[i - 1]) {//同一层相同的元素,剪枝 + continue;//继续循环,不是return退出循环 + } + path.addLast(nums[i]); + used[i] = true; + dps(nums, used, path); + path.removeLast(); + used[i] = false; + } + } +} +``` + +## 贪心算法 + +贪心算法,是寻找**最优解问题**的常用方法,这种方法模式一般将求解过程分成**若干个步骤**,但每个步骤都应用贪心原则,选取当前状态下**最好/最优的选择**(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。 + +**贪婪法的基本步骤:** + +1. 从某个初始解出发; +2. 采用迭代的过程,当可以向目标前进一步时,就根据局部最优策略,得到一部分解,缩小问题规模; +3. 将所有解综合起来。 + +### 买卖股票的最佳时机 II + +**题目描述**: + +给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 + +在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 + +返回 你能获得的 最大 利润 。 + +**示例**: + +```java +输入:prices = [1,2,3,4,5] +输出:4 +解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 +  总利润为 4 。 +``` + +思路:可以尽可能地完成更多的交易,但不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + +```java +//输入: [7,1,5,3,6,4] +//输出: 7 +class Solution { + public int maxProfit(int[] prices) { + int profit = 0; + for (int i = 1; i < prices.length; i++) { + int tmp = prices[i] - prices[i - 1]; + if (tmp > 0) { + profit += tmp; + } + } + + return profit; + } +} +``` + +### 跳跃游戏 + +**题目描述** + +给定一个非负整数数组 `nums` ,你最初位于数组的 **第一个下标** 。 + +数组中的每个元素代表你在该位置可以跳跃的最大长度。 + +判断你是否能够到达最后一个下标。 + +**示例**: + +```java +输入:nums = [2,3,1,1,4] +输出:true +解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。 +``` + +解题思路: + +1. 如果某一个作为 起跳点 的格子可以跳跃的距离是 3,那么表示后面 3 个格子都可以作为 起跳点 +2. 可以对每一个能作为 起跳点 的格子都尝试跳一次,把 能跳到最远的距离 不断更新 +3. 如果可以一直跳到最后,就成功了 + +```java +class Solution { + public boolean canJump(int[] nums) { + if (nums == null || nums.length == 0) { + return true; + } + + int maxIndex = nums[0]; + for (int i = 1; i < nums.length; i++) { + if (maxIndex >= i) { + maxIndex = Math.max(maxIndex, i + nums[i]); + } else { + return false; + } + } + + return true; + } +} +``` + +### 加油站 + +**题目描述** + +在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 + +你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 + +给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。 + +**示例** + +```java +输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2] +输出: 3 +解释: +从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油 +开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油 +开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油 +开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油 +开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油 +开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。 +因此,3 可为起始索引。 +``` + +**思路**: + +1. 遍历一周,总获得的油量少于要花掉的油量必然没有结果; +2. 先苦后甜,记录遍历时所存的油量最少的站点,由于题目有解只有唯一解,所以从当前站点的下一个站点开始是唯一可能成功开完全程的。 + +```java +class Solution { + public int canCompleteCircuit(int[] gas, int[] cost) { + int minIdx=0; + int sum=Integer.MAX_VALUE; + int num=0; + for (int i = 0; i < gas.length; i++) { + num+=gas[i]-cost[i]; + if(num 0) { + fast = fast.next; + } + + while (fast.next != null) { + fast = fast.next; + slow = slow.next; + } + slow.next = slow.next.next; + + return tmp.next; + } +} +``` + +### 三数之和 + +[题目链接](https://leetcode.cn/problems/3sum/) + +**题目描述** + +给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。 + +注意:答案中不可以包含重复的三元组。 + +**示例** + +```java +输入:nums = [-1,0,1,2,-1,-4] +输出:[[-1,-1,2],[-1,0,1]] +``` + +**思路**: + +- 首先对数组进行排序,排序后固定一个数 nums[i]nums[i],再使用左右指针指向 nums[i]nums[i]后面的两端,数字分别为 nums[L]nums[L] 和 +- nums[R]nums[R],计算三个数的和 sumsum 判断是否满足为 00,满足则添加进结果集 +- 如果 nums[i]nums[i]大于 00,则三数之和必然无法等于 00,结束循环 +- 如果 nums[i]nums[i] == nums[i-1]nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过 +- 当 sumsum == 00 时,nums[L]nums[L] == nums[L+1]nums[L+1] 则会导致结果重复,应该跳过,L++L++ +- 当 sumsum == 00 时,nums[R]nums[R] == nums[R-1]nums[R−1] 则会导致结果重复,应该跳过,R--R−− + +**参考代码**: + +```java +class Solution { + public List> threeSum(int[] nums) { + List> res = new ArrayList<>(); + Arrays.sort(nums); + + for (int i = 0; i < nums.length; i++) { + if (nums[i] > 0) { //最左边的数字大于0,则sum不会等于0,退出 + break; + } + if (i > 0 && nums[i] == nums[i - 1]) { //去重复 + continue; + } + + int left = i + 1; + int right = nums.length - 1; + + while (left < right) { + int sum = nums[i] + nums[left] + nums[right]; + if (sum == 0) { + res.add(Arrays.asList(nums[i], nums[left], nums[right])); ///array to list + while (left < right && nums[left] == nums[left + 1]) { + left++; + } + while (left < right && nums[right] == nums[right - 1]) { + right--; + } + left++; + right--; + } else if (sum > 0) { + right--; + } else { + left++; + } + } + } + + return res; + } +} +``` + +### 环形链表 + +[题目链接](https://leetcode.cn/problems/linked-list-cycle/) + +**题目描述** + +给你一个链表的头节点 head ,判断链表中是否有环。 + +如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。 + +如果链表中存在环 ,则返回 true 。 否则,返回 false 。 + +**示例** + +```java +输入:head = [3,2,0,-4], pos = 1 +输出:true +解释:链表中有一个环,其尾部连接到第二个节点。 +``` + +**思路** + +快慢指针。快指针每次走两步,慢指针走一步,相当于慢指针不动,快指针每次走一步,如果是环形链表,则一定会相遇。 + +```java +public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + + ListNode quick = head; + ListNode slow = head; + + while (quick != null && quick.next != null) { + slow = slow.next; + quick = quick.next.next; + + if (slow == quick) { + return true; + } + } + + return false; + } +} +``` + +### 环形链表II + +[题目链接](https://leetcode.cn/problems/linked-list-cycle-ii/) + +**题目描述** + +给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 + +如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 + +不允许修改 链表。 + +**示例** + +```java +输入:head = [3,2,0,-4], pos = 1 +输出:返回索引为 1 的链表节点 +解释:链表中有一个环,其尾部连接到第二个节点 +``` + +**解题思路** + +方法一:头结点到入环结点的距离为a,入环结点到相遇结点的距离为b,相遇结点到入环结点的距离为c。然后,当fast以slow的两倍速度前进并和slow相遇时,fast走过的距离是s的两倍,即有等式:a+b+c+b = 2(a+b) ,可以得出 a = c ,所以说,让fast和slow分别从相遇结点和头结点同时同步长出发,他们的相遇结点就是入环结点。 + +```java +public class Solution { + public ListNode detectCycle(ListNode head) { + ListNode fast = head; + ListNode slow = head; + + while (true) { + if (fast == null || fast.next == null) { + return null; + } + fast = fast.next.next; + slow = slow.next; + if (fast == slow) { + break; + } + } + + fast = head; + + while (slow != fast) { + slow = slow.next; + fast = fast.next; + } + + return fast; + } +} +``` + +方法二:先算出环的大小n,快指针先走n步,然后快慢指针一起走,相遇的地方即是环的入口。 + +```java +public class Solution { + public ListNode detectCycle(ListNode head) { + ListNode slow = head; + ListNode fast = head; + //快慢指针找出环的大小 + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (fast == slow) { + break; + } + } + + if (fast == null || fast.next == null) { + return null; + } + + int cycleSize = 1; + while (fast.next != slow) { + cycleSize++; + fast = fast.next; + } + + //快慢指针重新从链表首部出发,快指针先走sizeOfCycle步 + //然后两个指针同时一起走,步长为1,相遇节点即是环的入口 + fast = head; + slow = head; + while (cycleSize-- > 0) { + fast = fast.next; + } + while (fast != slow) { + fast = fast.next; + slow = slow.next; + } + + return fast; + } +} +``` + diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" b/docs/computer-basic/data-structure.md similarity index 62% rename from "\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" rename to docs/computer-basic/data-structure.md index 9bb6945..f486ac9 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225/\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ b/docs/computer-basic/data-structure.md @@ -1,3 +1,9 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/数据结构与算法.jpg) + ## 各种数据结构应用场景 - 栈:逆序输出;语法检查,符号成对判断;方法调用 @@ -77,21 +83,50 @@ ### AVL树 -平衡二叉搜索树,它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1。 +**平衡二叉搜索树**,它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1。 + +![](http://img.dabin-coder.cn/image/image-20220722233208322.png) - - 左左单旋转 - ![在这里插入图片描述](https://img-blog.csdn.net/20181005222022420?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) +简单了解一下**左旋与右旋**的概念。 -- 左右双旋转 - ![在这里插入图片描述](https://img-blog.csdn.net/20181005222244445?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) +左旋与右旋就是为了解决不平衡问题而产生的,我们构建一颗AVL树的过程会出现结点平衡因子(平衡因子就是二叉排序树中每个结点的左子树和右子树的高度差。)绝对值大于1的情况,这时就可以通过左旋或者右旋操作来达到平衡的目的。 -- 四种旋转情况 +四种旋转情况 + +![](http://img.dabin-coder.cn/image/四种旋转情况.png) + +### 红黑树 + +红黑树是对AVL树的优化,只要求部分平衡,用非严格的平衡来换取增删节点时候旋转次数的降低,提高了插入和删除的性能。查找性能并没有提高,查找的时间复杂度是O(logn)。红黑树通过左旋、右旋和变色维持平衡。 + +![](http://img.dabin-coder.cn/image/20220619165116.png) + +对于插入节点,AVL和红黑树都是最多两次旋转来实现平衡。对于删除节点,avl需要维护从被删除节点到根节点root这条路径上所有节点的平衡,旋转的量级为O(logN),而红黑树最多只需旋转3次。 - ![在这里插入图片描述](https://img-blog.csdnimg.cn/20181206115511699.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1R5c29uMDMxNA==,size_16,color_FFFFFF,t_70) +红黑树的特性: + +- 每个节点或者是黑色,或者是红色。 +- 根节点和叶子节点是黑色,叶子节点为空。 +- 红色节点的子节点必须是黑色的。 +- 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点,保证没有一条路径会比其他路径长一倍。 + +优点:相比avl树,红黑树插入删除的效率更高。红黑树维持红黑性质所做的红黑变换和旋转的开销,相较于avl树维持平衡的开销要小得多。 + +**应用场景** + +- Java ConcurrentHashMap & TreeMap +- C++ STL: map & set +- linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块 +- epoll在内核中的实现,用红黑树管理事件块 +- nginx中,用红黑树管理timer等 ### B树 -也称B-树,属于多叉树又名平衡多路查找树。规则: +也称B-树,属于多叉树又名平衡多路查找树。 + +![](http://img.dabin-coder.cn/image/B-树.png) + +规则: - 1<子节点数<=m,m代表一个树节点最多有多少个查找路径 - 每个节点最多有m-1个关键字,非根节点至少有m/2个关键字,根节点最少可以只有1个关键字 @@ -105,46 +140,81 @@ B-树的特性: B+树是B-树的变体,也是一种多路搜索树。B+的搜索与B-树基本相同,区别是B+树只有达到叶子结点才命中,B-树可以在非叶子结点命中。B+树更适合文件索引系统。 -B-和B+树的区别 +![](http://img.dabin-coder.cn/image/B+树.jpg) + +B-和B+树的区别: - B+树的非叶子结点不包含data,叶子结点使用链表连接,便于区间查找和遍历。B-树需要遍历整棵树,范围查询性能没有B+树好。 - B-树的非树节点存放数据和索引,搜索可能在非叶子结点结束,访问更快。 -### 红黑树 +## 图 -红黑树是对AVL树的优化,只要求部分平衡,用非严格的平衡来换取增删节点时候旋转次数的降低,提高了插入和删除的性能。查找性能并没有提高,查找的时间复杂度是O(logn)。红黑树通过左旋、右旋和变色维持平衡。 +图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为: G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。 -对于插入节点,AVL和红黑树都是最多两次旋转来实现平衡。对于删除节点,avl需要维护从被删除节点到根节点root这条路径上所有节点的平衡,旋转的量级为O(logN),而红黑树最多只需旋转3次。 +和线性表,树的差异: -特性: -(1) 每个节点或者是黑色,或者是红色。 -(2) 根节点和叶子节点是黑色,叶子节点为空。 -(4)红色节点的子节点必须是黑色的。 -(5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点,保证没有一条路径会比其他路径长一倍。 +- 线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我们则称之为顶点(Vertex)。 +- 线性表可以没有元素,称为空表;树中可以没有节点,称为空树;但是,在图中不允许没有顶点(有穷非空性)。 +- 线性表中的各元素是线性关系,树中的各元素是层次关系,而图中各顶点的关系是用边来表示(边集可以为空)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165116.png) +![](http://img.dabin-coder.cn/image/20220619165442.png) -优点:相比avl树,红黑树插入删除的效率更高。红黑树维持红黑性质所做的红黑变换和旋转的开销,相较于avl树维持平衡的开销要小得多。 +### 相关术语 -应用:主要用来存储有序的数据,Java中的TreeSet和TreeMap都是通过红黑树实现的。 +- 顶点的度 +顶点Vi的度(Degree)是指在图中与Vi相关联的边的条数。对于有向图来说,有入度(In-degree)和出度(Out-degree)之分,有向图顶点的度等于该顶点的入度和出度之和。 +- 邻接 -## 图 +若无向图中的两个顶点V1和V2存在一条边(V1,V2),则称顶点V1和V2邻接(Adjacent); + +若有向图中存在一条边,则称顶点V3与顶点V2邻接,且是V3邻接到V2或V2邻接直V3; + +- 路径 + +在无向图中,若从顶点Vi出发有一组边可到达顶点Vj,则称顶点Vi到顶点Vj的顶点序列为从顶点Vi到顶点Vj的路径(Path)。 + +- 连通 + +若从Vi到Vj有路径可通,则称顶点Vi和顶点Vj是连通(Connected)的。 + +- 权(Weight) + +有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight)。 -图由顶点集(vertex set)和边集(edge set)所组成。 +### 类型 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165442.png) +无向图 -图的存储结构有邻接矩阵、邻接表和边集数组三种。 +如果图中任意两个顶点之间的边都是无向边(简而言之就是没有方向的边),则称该图为无向图(Undirected graphs)。 -1、邻接矩阵 +无向图中的边使用小括号“()”表示; 比如 (V1,V2); -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165526.png) +有向图 -2、邻接表 +如果图中任意两个顶点之间的边都是有向边(简而言之就是有方向的边),则称该图为有向图(Directed graphs)。 -![](https://raw.githubusercontent.com/Tyson0314/img/master/20220619165617.png) +有向图中的边使用尖括号“<>”表示; 比如/ + +完全图 + +- `无向完全图`: 在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。(含有n个顶点的无向完全图有(n×(n-1))/2条边) +- `有向完全图: 在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。(含有n个顶点的有向完全图有n×(n-1)条边 + +### 图的存储结构 + +1、**邻接矩阵** + +图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。 + +![](http://img.dabin-coder.cn/image/20220619165526.png) + +2、**邻接表** + +邻接表由表头节点和表节点两部分组成,图中每个顶点均对应一个存储在数组中的表头节点。如果这个表头节点所对应的顶点存在邻接节点,则把邻接节点依次存放于表头节点所指向的单向链表中。 + +![](http://img.dabin-coder.cn/image/20220619165617.png) 下面给出建立图的邻接表中所使用的边结点类的定义 @@ -186,6 +256,8 @@ public interface Graph } ``` +### 图的遍历 + 深度优先遍历 ```java diff --git a/docs/computer-basic/network.md b/docs/computer-basic/network.md new file mode 100644 index 0000000..891bd71 --- /dev/null +++ b/docs/computer-basic/network.md @@ -0,0 +1,601 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/计算机网络知识.jpg) + +## 网络分层结构 + +计算机网络体系大致分为三种,OSI七层模型、TCP/IP四层模型和五层模型。一般面试的时候考察比较多的是五层模型。 + +![](http://img.dabin-coder.cn/image/tcp5layer2.png) + +**五层模型**:应用层、传输层、网络层、数据链路层、物理层。 + +- **应用层**:为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统DNS、HTTP协议、SMTP协议等。 +- **传输层**:负责向两台主机进程之间的通信提供数据传输服务。传输层的协议主要有传输控制协议TCP和用户数据协议UDP。 +- **网络层**:选择合适的路由和交换结点,确保数据及时传送。主要包括IP协议。 +- **数据链路层**:在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。 +- **物理层**:实现相邻节点间比特流的透明传输,尽可能屏蔽传输介质和物理设备的差异。 + +**ISO七层模型**是国际标准化组织(International Organization for Standardization)制定的一个用于计算机或通信系统间互联的标准体系。 + +- 应用层:网络服务与最终用户的一个接口,常见的协议有:**HTTP FTP SMTP SNMP DNS**. +- 表示层:数据的表示、安全、压缩。,确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。 +- 会话层:建立、管理、终止会话,对应主机进程,指本地主机与远程主机正在进行的会话. +- 传输层:定义传输数据的协议端口号,以及流控和差错校验,协议有**TCP UDP**. +- 网络层:进行逻辑地址寻址,实现不同网络之间的路径选择,协议有**ICMP IGMP IP等**. +- 数据链路层:在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路。 +- 物理层:建立、维护、断开物理连接。 + +**TCP/IP 四层模型** + +- 应用层:对应于OSI参考模型的(应用层、表示层、会话层)。 +- 传输层: 对应OSI的传输层,为应用层实体提供端到端的通信功能,保证了数据包的顺序传送及数据的完整性。 +- 网际层:对应于OSI参考模型的网络层,主要解决主机到主机的通信问题。 +- 网络接口层:与OSI参考模型的数据链路层、物理层对应。 + +## 三次握手 + +假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是`CLOSED`。 + +![](http://img.dabin-coder.cn/image/三次握手图解.png) + +1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位`SYN=1`,序列号`seq=x`。第一次握手前客户端的状态为`CLOSE`,第一次握手后客户端的状态为`SYN-SENT`。此时服务端的状态为`LISTEN`。 +2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位`SYN=1`,`ACK=1`,序列号`seq=y`,确认号`ack=x+1`。第二次握手前服务端的状态为`LISTEN`,第二次握手后服务端的状态为`SYN-RCVD`,此时客户端的状态为`SYN-SENT`。(其中`SYN=1`表示要和客户端建立一个连接,`ACK=1`表示确认序号有效) +3. 第三次握手:客户端收到服务端发来的报文后,会再向服务端发送报文,其中包含标志位`ACK=1`,序列号`seq=x+1`,确认号`ack=y+1`。第三次握手前客户端的状态为`SYN-SENT`,第三次握手后客户端和服务端的状态都为`ESTABLISHED`。**此时连接建立完成。** + +## 两次握手可以吗? + +之所以需要第三次握手,主要为了**防止已失效的连接请求报文段**突然又传输到了服务端,导致产生问题。 + +- 比如客户端A发出连接请求,可能因为网络阻塞原因,A没有收到确认报文,于是A再重传一次连接请求。 +- 然后连接成功,等待数据传输完毕后,就释放了连接。 +- 然后A发出的第一个连接请求等到连接释放以后的某个时间才到达服务端B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段。 +- 如果不采用三次握手,只要B发出确认,就建立新的连接了,**此时A不会响应B的确认且不发送数据,则B一直等待A发送数据,浪费资源。** + +## 四次挥手 + +![](http://img.dabin-coder.cn/image/四次挥手0.png) + +1. A的应用进程先向其TCP发出连接释放报文段(`FIN=1,seq=u`),并停止再发送数据,主动关闭TCP连接,进入`FIN-WAIT-1`(终止等待1)状态,等待B的确认。 +2. B收到连接释放报文段后即发出确认报文段(`ACK=1,ack=u+1,seq=v`),B进入`CLOSE-WAIT`(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 +3. A收到B的确认后,进入`FIN-WAIT-2`(终止等待2)状态,等待B发出的连接释放报文段。 +4. B发送完数据,就会发出连接释放报文段(`FIN=1,ACK=1,seq=w,ack=u+1`),B进入`LAST-ACK`(最后确认)状态,等待A的确认。 +5. A收到B的连接释放报文段后,对此发出确认报文段(`ACK=1,seq=u+1,ack=w+1`),A进入`TIME-WAIT`(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间`2MSL`(最大报文段生存时间)后,A才进入`CLOSED`状态。B收到A发出的确认报文段后关闭连接,若没收到A发出的确认报文段,B就会重传连接释放报文段。 + +## 第四次挥手为什么要等待2MSL? + +- **保证A发送的最后一个ACK报文段能够到达B**。这个`ACK`报文段有可能丢失,B收不到这个确认报文,就会超时重传连接释放报文段,然后A可以在`2MSL`时间内收到这个重传的连接释放报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到`CLOSED`状态,若A在`TIME-WAIT`状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的连接释放报文段,所以不会再发送一次确认报文段,B就无法正常进入到`CLOSED`状态。 +- **防止已失效的连接请求报文段出现在本连接中**。A在发送完最后一个`ACK`报文段后,再经过2MSL,就可以使这个连接所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段。 + +## 为什么是四次挥手? + +因为当Server端收到Client端的`SYN`连接请求报文后,可以直接发送`SYN+ACK`报文。**但是在关闭连接时,当Server端收到Client端发出的连接释放报文时,很可能并不会立即关闭SOCKET**,所以Server端先回复一个`ACK`报文,告诉Client端我收到你的连接释放报文了。只有等到Server端所有的报文都发送完了,这时Server端才能发送连接释放报文,之后两边才会真正的断开连接。故需要四次挥手。 + +## TCP有哪些特点? + +- TCP是**面向连接**的运输层协议。 +- **点对点**,每一条TCP连接只能有两个端点。 +- TCP提供**可靠交付**的服务。 +- TCP提供**全双工通信**。 +- **面向字节流**。 + +## 说说TCP报文首部有哪些字段,其作用又分别是什么? + +![](http://img.dabin-coder.cn/image/tcp报文.png) + +- **16位端口号**:源端口号,主机该报文段是来自哪里;目标端口号,要传给哪个上层协议或应用程序 +- **32位序号**:一次TCP通信(从TCP连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号。 +- **32位确认号**:用作对另一方发送的tcp报文段的响应。其值是收到的TCP报文段的序号值加1。 +- **4位头部长度**:表示tcp头部有多少个32bit字(4字节)。因为4位最大能标识15,所以TCP头部最长是60字节。 +- **6位标志位**:URG(紧急指针是否有效),ACk(表示确认号是否有效),PSH(缓冲区尚未填满),RST(表示要求对方重新建立连接),SYN(建立连接消息标志接),FIN(表示告知对方本端要关闭连接了) +- **16位窗口大小**:是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。 +- **16位校验和**:由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。 +- **16位紧急指针**:一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法。 + +## TCP和UDP的区别? + +1. TCP**面向连接**;UDP是无连接的,即发送数据之前不需要建立连接。 +2. TCP提供**可靠的服务**;UDP不保证可靠交付。 +3. TCP**面向字节流**,把数据看成一连串无结构的字节流;UDP是面向报文的。 +4. TCP有**拥塞控制**;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如实时视频会议等)。 +5. 每一条TCP连接只能是**点到点**的;UDP支持一对一、一对多、多对一和多对多的通信方式。 +6. TCP首部开销20字节;UDP的首部开销小,只有8个字节。 + +## TCP 和 UDP 分别对应的常见应用层协议有哪些? + +**基于TCP的应用层协议有:HTTP、FTP、SMTP、TELNET、SSH** + +- **HTTP**:HyperText Transfer Protocol(超文本传输协议),默认端口80 +- **FTP**: File Transfer Protocol (文件传输协议), 默认端口(20用于传输数据,21用于传输控制信息) +- **SMTP**: Simple Mail Transfer Protocol (简单邮件传输协议) ,默认端口25 +- **TELNET**: Teletype over the Network (网络电传), 默认端口23 +- **SSH**:Secure Shell(安全外壳协议),默认端口 22 + +**基于UDP的应用层协议:DNS、TFTP、SNMP** + +- **DNS** : Domain Name Service (域名服务),默认端口 53 +- **TFTP**: Trivial File Transfer Protocol (简单文件传输协议),默认端口69 +- **SNMP**:Simple Network Management Protocol(简单网络管理协议),通过UDP端口161接收,只有Trap信息采用UDP端口162。 + +## TCP的粘包和拆包 + +TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一**个完整的包可能会被TCP拆分成多个包进行发送**,**也有可能把多个小的包封装成一个大的数据包发送**,这就是所谓的TCP粘包和拆包问题。 + +**为什么会产生粘包和拆包呢?** + +- 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包; +- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包; +- 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包; +- 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。 + +**解决方案:** + +- 发送端将每个数据包封装为固定长度 +- 在数据尾部增加特殊字符进行分割 +- 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小。 + +## 说说TCP是如何确保可靠性的呢? + +- 首先,TCP的连接是基于**三次握手**,而断开则是基于**四次挥手**。确保连接和断开的可靠性。 +- 其次,TCP的可靠性,还体现在**有状态**;TCP会记录哪些数据发送了,哪些数据被接收了,哪些没有被接受,并且保证数据包按序到达,保证数据传输不出差错。 +- 再次,TCP的可靠性,还体现在**可控制**。它有数据包校验、ACK应答、**超时重传(发送方)**、失序数据重传(接收方)、丢弃重复数据、流量控制(滑动窗口)和拥塞控制等机制。 + +## 说下TCP的滑动窗口机制 + +TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据。 + +![](http://img.dabin-coder.cn/image/image-20210921112213523.png) + + +TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小。 + +## 详细讲一下拥塞控制? + +防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。 + +![](http://img.dabin-coder.cn/image/拥塞控制.jpg) + +**慢开始** + +把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。每经过一个传输轮次,拥塞窗口 cwnd 就加倍。 为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量。 + + 当 cwnd < ssthresh 时,使用慢开始算法。 + + 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。 + + 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。 + +**拥塞避免** + +让拥塞窗口cwnd缓慢地增大,每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长。 + +无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送 方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生 拥塞的路由器有足够时间把队列中积压的分组处理完毕。 + +**快重传** + +有时个别报文段会在网络中丢失,但实际上网络并未发生拥塞。如果发送方迟迟收不到确认,就会产生超时,就会误认为网络发生了拥塞。这就导致发送方错误地启动慢开始,把拥塞窗口cwnd又设置为1,因而降低了传输效率。 + +快重传算法可以避免这个问题。快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认,使发送方及早知道有报文段没有到达对方。 + +发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待重传计时器到期。由于发送方尽早重传未被确认的报文段,因此采用快重传后可以使整个网络吞吐量提高约20%。 + +**快恢复** + +当发送方连续收到三个重复确认,就会把慢开始门限ssthresh减半,接着把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大。 + +在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。 采用这样的拥塞控制方法使得TCP的性能有明显的改进。 + +## HTTP协议的特点? + +1. HTTP允许传输**任意类型**的数据。传输的类型由Content-Type加以标记。 +2. **无状态**。对于客户端每次发送的请求,服务器都认为是一个新的请求,上一次会话和下一次会话之间没有联系。 +3. 支持**客户端/服务器模式**。 + +## HTTP报文格式 + +HTTP请求由**请求行、请求头部、空行和请求体**四个部分组成。 + +- **请求行**:包括请求方法,访问的资源URL,使用的HTTP版本。`GET`和`POST`是最常见的HTTP方法,除此以外还包括`DELETE、HEAD、OPTIONS、PUT、TRACE`。 +- **请求头**:格式为“属性名:属性值”,服务端根据请求头获取客户端的信息,主要有`cookie、host、connection、accept-language、accept-encoding、user-agent`。 +- **请求体**:用户的请求数据如用户名,密码等。 + +**请求报文示例**: + +```java +POST /xxx HTTP/1.1 请求行 +Accept:image/gif.image/jpeg, 请求头部 +Accept-Language:zh-cn +Connection:Keep-Alive +Host:localhost +User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0) +Accept-Encoding:gzip,deflate + +username=dabin 请求体 +``` + +HTTP响应也由四个部分组成,分别是:**状态行、响应头、空行和响应体**。 + +- **状态行**:协议版本,状态码及状态描述。 +- **响应头**:响应头字段主要有`connection、content-type、content-encoding、content-length、set-cookie、Last-Modified,、Cache-Control、Expires`。 +- **响应体**:服务器返回给客户端的内容。 + +**响应报文示例**: + +```html +HTTP/1.1 200 OK +Server:Apache Tomcat/5.0.12 +Date:Mon,6Oct2003 13:23:42 GMT +Content-Length:112 + + + 响应体 + +``` + +## HTTP状态码有哪些? + +![](http://img.dabin-coder.cn/image/http-status-code.png) + +HTTP 状态码是服务器端返回给客户端的响应状态码,根据状态码我们就能知道服务器端想要给客户端表达的具体含义,比如 200 就表示请求访问成功,500 就表示服务器端程序出错等。HTTP 状态码可分为 5 大类: + +1. 1XX:消息状态码。 +2. 2XX:成功状态码。 +3. 3XX:重定向状态码。 +4. 4XX:客户端错误状态码。 +5. 5XX:服务端错误状态码。 + +这 5 大类中又包含了很多具体的状态码。 + +1XX为**消息状态码**,其中: + +- 100:Continue 继续。客户端应继续其请求。 +- 101:Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到 HTTP 的新版本协议。 + +2XX为**成功状态码**,其中: + +- **200:OK 请求成功。一般用于 GET 与 POST 请求。** +- 201:Created 已创建。成功请求并创建了新的资源。 +- 202:Accepted 已接受。已经接受请求,但未处理完成。 +- 203:Non-Authoritative Information 非授权信息。请求成功。但返回的 meta 信息不在原始的服务器,而是一个副本。 +- 204:No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档。 +- 205:Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域。 +- 206:Partial Content 部分内容。服务器成功处理了部分 GET 请求。 + +3XX为**重定向状态码**,其中: + +- 300:Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择。 +- **301:Moved Permanently 永久移动。请求的资源已被永久的移动到新 URI,返回信息会包括新的 URI,浏览器会自动定向到新 URI。今后任何新的请求都应使用新的 URI 代替。** +- **302:Found 临时移动,与 301 类似。但资源只是临时被移动。客户端应继续使用原有URI。** +- 303:See Other 查看其它地址。与 301 类似。使用 GET 和 POST 请求查看。 +- 304:Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源。 +- 305:Use Proxy 使用代理。所请求的资源必须通过代理访问。 +- 306:Unused 已经被废弃的 HTTP 状态码。 +- 307:Temporary Redirect 临时重定向。与 302 类似。使用 GET 请求重定向。 + +4XX为客户端**错误状态码**,其中: + +- 400:Bad Request 客户端请求的语法错误,服务器无法理解。 +- 401:Unauthorized 请求要求用户的身份认证。 +- 402:Payment Required 保留,将来使用。 +- 403:Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求。 +- **404:Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。** +- **405:Method Not Allowed 客户端请求中的方法被禁止。** +- 406:Not Acceptable 服务器无法根据客户端请求的内容特性完成请求。 +- 407:Proxy Authentication Required 请求要求代理的身份认证,与 401 类似,但请求者应当使用代理进行授权。 +- 408:Request Time-out 服务器等待客户端发送的请求时间过长,超时。 +- 409:Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突。 +- 410:Gone 客户端请求的资源已经不存在。410 不同于 404,如果资源以前有现在被永久删除了可使用 410 代码,网站设计人员可通过 301 代码指定资源的新位置。 +- 411:Length Required 服务器无法处理客户端发送的不带 Content-Length 的请求信息。 +- 412:Precondition Failed 客户端请求信息的先决条件错误。 +- 413:Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个 Retry-After 的响应信息。 +- 414:Request-URI Too Large 请求的 URI 过长(URI通常为网址),服务器无法处理。 +- 415:Unsupported Media Type 服务器无法处理请求附带的媒体格式。 +- 416:Requested range not satisfiable 客户端请求的范围无效。 +- 417:Expectation Failed 服务器无法满足 Expect 的请求头信息。 + +5XX为**服务端错误状态码**,其中: + +- **500:Internal Server Error 服务器内部错误,无法完成请求。** +- 501:Not Implemented 服务器不支持请求的功能,无法完成请求。 +- 502:Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应。 +- 503:Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中。 +- 504:Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求。 +- 505:HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理。 + +**总结一下**: + +HTTP 状态码分为 5 大类:1XX:表示消息状态码;2XX:表示成功状态码;3XX:表示重定向状态码;4XX:表示客户端错误状态码;5XX:表示服务端错误状态码。其中常见的具体状态码有:200:请求成功;301:永久重定向;302:临时重定向;404:无法找到此页面;405:请求的方法类型不支持;500:服务器内部出错。 + +## HTTP 协议包括哪些请求? + +HTTP协议中共定义了八种方法来表示对Request-URI指定的资源的不同操作方式,具体如下: + +- GET:向特定的资源发出请求。 +- POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 +- OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。 +- HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。 +- PUT:向指定资源位置上传其最新内容。 +- DELETE:请求服务器删除Request-URI所标识的资源。 +- TRACE:回显服务器收到的请求,主要用于测试或诊断。 +- CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 + +## HTTP状态码301和302的区别? + +- 301:(永久性转移)请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。 +- 302:(暂时性转移)服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应GET和HEAD请求的301代码类似,会自动将请求者转到不同的位置。 + +**举个形象的例子**:当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,打个比方说,我有一套房子,但是最近走亲戚去亲戚家住了,过两天我还回来的。而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的,就比如你的那套房子其实是租的,现在租期到了,你又在另一个地方找到了房子,之前租的房子不住了。 + +## URI和URL的区别 + +- URI,全称是Uniform Resource Identifier),中文翻译是统一资源标志符,主要作用是唯一标识一个资源。 +- URL,全称是Uniform Resource Location),中文翻译是统一资源定位符,主要作用是提供资源的路径。打个经典比喻吧,URI像是身份证,可以唯一标识一个人,而URL更像一个住址,可以通过URL找到这个人。 + +## POST和GET的区别? + +- GET 和 POST 最本质的区别是规范上的区别,在规范中,定义 GET 请求是用来获取资源的,也就是进行查询操作的,而 POST 请求是用来传输实体对象的,因此会使用 POST 来进行添加、修改和删除等操作。 +- GET请求参数通过URL传递,POST的参数放在请求体中。 +- GET 请求可以直接进行回退和刷新,不会对用户和程序产生任何影响;而 POST 请求如果直接回滚和刷新将会把数据再次提交。 +- GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把请求头和请求体一并发送出去;而对于POST,浏览器先发送请求头,服务器响应100 continue,浏览器再发送请求体。 +- GET 请求一般会被缓存,比如常见的 CSS、JS、HTML 请求等都会被缓存;而 POST 请求默认是不进行缓存的。 +- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 + +## 如何理解HTTP协议是无状态的 + +当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。简言之,服务器不会去记住你是谁,所以是无状态协议。 + +## HTTP长连接和短连接? + +HTTP短连接:浏览器和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。**HTTP1.0默认使用的是短连接**。 + +HTTP长连接:指的是**复用TCP连接**。多个HTTP请求可以复用同一个TCP连接,这就节省了TCP连接建立和断开的消耗。 + +**HTTP/1.1起,默认使用长连接**。要使用长连接,客户端和服务器的HTTP首部的Connection都要设置为keep-alive,才能支持长连接。 + +## HTTP 如何实现长连接? + +HTTP分为长连接和短连接,**本质上说的是TCP的长短连接**。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才具有真正的长连接和短连接这一说法哈。 + +TCP长连接可以复用一个TCP连接,来发起多次的HTTP请求,这样就可以减少资源消耗,比如一次请求HTML,如果是短连接的话,可能还需要请求后续的JS/CSS。 + +**如何设置长连接?** + +通过在头部(请求和响应头)设置**Connection**字段指定为`keep-alive`,HTTP/1.0协议支持,但是是默认关闭的,从HTTP/1.1以后,连接默认都是长连接。 + +## HTTP长连接在什么时候会超时? + +HTTP一般会有httpd守护进程,里面可以设置**keep-alive timeout**,当tcp连接闲置超过这个时间就会关闭,也可以在HTTP的header里面设置超时时间。 + +TCP 的**keep-alive**包含三个参数,支持在系统内核的net.ipv4里面设置;当 TCP 连接之后,闲置了**tcp_keepalive_time**,则会发生侦测包,如果没有收到对方的ACK,那么会每隔 tcp_keepalive_intvl再发一次,直到发送了**tcp_keepalive_probes**,就会丢弃该连接。 + +## HTTP1.1和 HTTP2.0的区别? + +HTTP2.0相比HTTP1.1支持的特性: + +* **新的二进制格式**:HTTP1.1 基于文本格式传输数据;HTTP2.0采用二进制格式传输数据,解析更高效。 + +* **多路复用**:在一个连接里,允许同时发送多个请求或响应,**并且这些请求或响应能够并行的传输而不被阻塞**,避免 HTTP1.1 出现的”队头堵塞”问题。 + +* **头部压缩**,HTTP1.1的header带有大量信息,而且每次都要重复发送;HTTP2.0 把header从数据中分离,并封装成头帧和数据帧,**使用特定算法压缩头帧**,有效减少头信息大小。并且HTTP2.0**在客户端和服务器端记录了之前发送的键值对,对于相同的数据,不会重复发送。**比如请求a发送了所有的头信息字段,请求b则**只需要发送差异数据**,这样可以减少冗余数据,降低开销。 + +* **服务端推送**:HTTP2.0允许服务器向客户端推送资源,无需客户端发送请求到服务器获取。 + +## HTTPS与HTTP的区别? + +1. HTTP是超文本传输协议,信息是**明文传输**;HTTPS则是具有**安全性**的ssl加密传输协议。 +2. HTTP和HTTPS用的端口不一样,HTTP端口是80,HTTPS是443。 +3. HTTPS协议**需要到CA机构申请证书**,一般需要一定的费用。 +4. HTTP运行在TCP协议之上;HTTPS运行在SSL协议之上,SSL运行在TCP协议之上。 + +## 什么是数字证书? + +服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:**证书内容、证书签名算法和签名**,签名是为了验证身份。 + +![](http://img.dabin-coder.cn/image/image-20211004111441594.png) + +服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。 + +**数字签名的制作过程**: + +1. CA使用证书签名算法对证书内容进行**hash运算**。 +2. 对hash后的值**用CA的私钥加密**,得到数字签名。 + +**浏览器验证过程**: + +1. 获取证书,得到证书内容、证书签名算法和数字签名。 +2. 用CA机构的公钥**对数字签名解密**(由于是浏览器信任的机构,所以浏览器会保存它的公钥)。 +3. 用证书里的签名算法**对证书内容进行hash运算**。 +4. 比较解密后的数字签名和对证书内容做hash运算后得到的哈希值,相等则表明证书可信。 + +## HTTPS原理 + +首先是TCP三次握手,然后客户端发起一个HTTPS连接建立请求,客户端先发一个`Client Hello`的包,然后服务端响应`Server Hello`,接着再给客户端发送它的证书,然后双方经过密钥交换,最后使用交换的密钥加解密数据。 + +1. **协商加密算法** 。在`Client Hello`里面客户端会告知服务端自己当前的一些信息,包括客户端要使用的TLS版本,支持的加密算法,要访问的域名,给服务端生成的一个随机数(Nonce)等。需要提前告知服务器想要访问的域名以便服务器发送相应的域名的证书过来。 + + ![](http://img.dabin-coder.cn/image/image-20210921104210833.png) + +2. 服务端响应`Server Hello`,告诉客户端服务端**选中的加密算法**。 + + ![](http://img.dabin-coder.cn/image/image-20210921105450791.png) + +3. 接着服务端给客户端发来了2个证书。第二个证书是第一个证书的签发机构(CA)的证书。 + + ![](http://img.dabin-coder.cn/image/image-20211004172007102.png) + +4. 客户端使用证书的认证机构CA公开发布的RSA公钥**对该证书进行验证**,下图表明证书认证成功。 + + ![](http://img.dabin-coder.cn/image/image-20210921105929268.png) + +5. 验证通过之后,浏览器和服务器通过**密钥交换算法**产生共享的**对称密钥**。 + + ![](http://img.dabin-coder.cn/image/image-20210921110025197.png) + + ![](http://img.dabin-coder.cn/image/image-20210921110155075.png) + +6. 开始传输数据,使用同一个对称密钥来加解密。 + + ![](http://img.dabin-coder.cn/image/image-20210921110315068.png) + +## DNS 的解析过程? + +1. 浏览器搜索**自己的DNS缓存** +2. 若没有,则搜索**操作系统中的DNS缓存和hosts文件** +3. 若没有,则操作系统将域名发送至**本地域名服务器**,本地域名服务器查询自己的DNS缓存,查找成功则返回结果,否则依次向**根域名服务器、顶级域名服务器、权限域名服务器**发起查询请求,最终返回IP地址给本地域名服务器 +4. 本地域名服务器将得到的IP地址返回给**操作系统**,同时自己也**将IP地址缓存起来** +5. 操作系统将 IP 地址返回给浏览器,同时自己也将IP地址缓存起来 +6. 浏览器得到域名对应的IP地址 + +## 浏览器中输入URL返回页面过程? + +1. **解析域名**,找到主机 IP。 +2. 浏览器利用 IP 直接与网站主机通信,**三次握手**,建立 TCP 连接。浏览器会以一个随机端口向服务端的 web 程序 80 端口发起 TCP 的连接。 +3. 建立 TCP 连接后,浏览器向主机发起一个HTTP请求。 +4. 参数从客户端传递到服务器端。 +5. 服务器端得到客户端参数之后,进行相应的业务处理,再将结果封装成 HTTP 包,返回给客户端。 +6. 服务器端和客户端的交互完成,断开 TCP 连接(4 次挥手)。 +7. 浏览器**解析响应内容,进行渲染**,呈现给用户。 + +![](http://img.dabin-coder.cn/image/输入url返回页面过程1.png) + +## DNS 域名解析的过程 + +在网络中定位是依靠 IP 进行身份定位的,所以 URL 访问的第一步便是先要得到服务器端的 IP 地址。而得到服务器的 IP 地址需要使用 DNS(Domain Name System,域名系统)域名解析,DNS 域名解析就是通过 URL 找到与之相对应的 IP 地址。 + +DNS 域名解析的大致流程如下: + +1. 先检**查浏览器中的 DNS 缓存**,如果浏览器中有对应的记录会直接使用,并完成解析; +2. 如果浏览器没有缓存,那就去**查询操作系统的缓存**,如果查询到记录就可以直接返回 IP 地址,完成解析; +3. 如果操作系统没有 DNS 缓存,就会去**查看本地 host 文件**,Windows 操作系统下,host 文件一般位于 "C:\Windows\System32\drivers\etc\hosts",如果 host 文件有记录则直接使用; +4. 如果本地 host 文件没有相应的记录,会**请求本地 DNS 服务器**,本地 DNS 服务器一般是由本地网络服务商如移动、联通等提供。通常情况下可通过 DHCP 自动分配,当然也可以自己手动配置。目前用的比较多的是谷歌提供的公用 DNS 是 8.8.8.8 和国内的公用 DNS 是 114.114.114.114。 +5. 如果本地 DNS 服务器没有相应的记录,就会**去根域名服务器查询**了。为了能更高效完成全球所有域名的解析请求,根域名服务器本身并不会直接去解析域名,而是会把不同的解析请求分配给下面的其他服务器去完成。 + +![](http://img.dabin-coder.cn/image/image-20221123001836666.png) + +> 图片来源于网络 + +## 什么是cookie和session? + +由于HTTP协议是无状态的协议,需要用某种机制来识具体的用户身份,用来跟踪用户的整个会话。常用的会话跟踪技术是cookie与session。 + +**cookie**就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。说得更具体一些:当用户使用浏览器访问一个支持cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体中的,而是存放于HTTP响应头;当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 自此,客户端再向服务器发送请求的时候,都会把相应的cookie存放在HTTP请求头再次发回至服务器。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。网站的登录界面中“请记住我”这样的选项,就是通过cookie实现的。 + +![](http://img.dabin-coder.cn/image/cookie.png) + +**cookie工作流程**: + +1. servlet创建cookie,保存少量数据,发送给浏览器。 +2. 浏览器获得服务器发送的cookie数据,将自动的保存到浏览器端。 +3. 下次访问时,浏览器将自动携带cookie数据发送给服务器。 + +**session原理**:首先浏览器请求服务器访问web站点时,服务器首先会检查这个客户端请求是否已经包含了一个session标识、称为SESSIONID,如果已经包含了一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用,如果客户端请求不包含session id,则服务器为此客户端创建一个session,并且生成一个与此session相关联的独一无二的sessionid存放到cookie中,这个sessionid将在本次响应中返回到客户端保存,这样在交互的过程中,浏览器端每次请求时,都会带着这个sessionid,服务器根据这个sessionid就可以找得到对应的session。以此来达到共享数据的目的。 这里需要注意的是,session不会随着浏览器的关闭而死亡,而是等待超时时间。 + +![](http://img.dabin-coder.cn/image/session.png) + +## cookie和session的区别? + +- **作用范围不同**,Cookie 保存在客户端,Session 保存在服务器端。 +- **有效期不同**,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。 +- **隐私策略不同**,Cookie 存储在客户端,容易被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。 +- **存储大小不同**, 单个 Cookie 保存的数据不能超过 4K;对于 Session 来说存储没有上限,但出于对服务器的性能考虑,Session 内不要存放过多的数据,并且需要设置 Session 删除机制。 + +## 什么是对称加密和非对称加密? + +**对称加密**:通信双方使用**相同的密钥**进行加密。特点是加密速度快,但是缺点是密钥泄露会导致密文数据被破解。常见的对称加密有`AES`和`DES`算法。 + +**非对称加密**:它需要生成两个密钥,**公钥和私钥**。公钥是公开的,任何人都可以获得,而私钥是私人保管的。公钥负责加密,私钥负责解密;或者私钥负责加密,公钥负责解密。这种加密算法**安全性更高**,但是**计算量相比对称加密大很多**,加密和解密都很慢。常见的非对称算法有`RSA`和`DSA`。 + +## 说说 WebSocket与socket的区别 + +Socket是一套标准,它完成了对TCP/IP的高度封装,屏蔽网络细节,以方便开发者更好地进行网络编程。Socket其实就是等于**IP地址 + 端口 + 协议**。 + +WebSocket是一个持久化的协议,它是伴随H5而出的协议,用来解决**http不支持持久化连接**的问题。 + +Socket一个是**网编编程的标准接口**,而WebSocket则是应用层通信协议。 + +## ARP协议的工作过程? + +ARP解决了同一个局域网上的主机和路由器IP和MAC地址的解析。 + +- 每台主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址的对应关系。 +- 当源主机需要将一个数据包要发送到目的主机时,会首先检查自己 ARP列表中是否存在该 IP地址对应的MAC地址,如果有,就直接将数据包发送到这个MAC地址;如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。此ARP请求数据包里包括源主机的IP地址、硬件地址、以及目的主机的IP地址。 +- 网络中所有的主机收到这个ARP请求后,会检查数据包中的目的IP是否和自己的IP地址一致。如果不相同就忽略此数据包;如果相同,该主机首先将发送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已经存在该IP的信息,则将其覆盖,然后给源主机发送一个 ARP响应数据包,告诉对方自己是它需要查找的MAC地址。 +- 源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。 +- 如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。 + +## ICMP协议的功能 + +ICMP,Internet Control Message Protocol ,Internet控制消息协议。 + +- ICMP协议是一种面向无连接的协议,用于传输出错报告控制信息。 +- 它是一个非常重要的协议,它对于网络安全具有极其重要的意义。它属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括**报告错误、交换受限控制和状态信息**等。 +- 当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。 + +比如我们日常使用得比较多的**ping**,就是基于ICMP的。 + +## 什么是DoS、DDoS、DRDoS攻击? + +- **DOS**: (Denial of Service),翻译过来就是拒绝服务,一切能引起DOS行为的攻击都被称为DOS攻击。最常见的DoS攻击就有**计算机网络宽带攻击**、**连通性攻击**。 +- **DDoS**: (Distributed Denial of Service),翻译过来是分布式拒绝服务。是指处于不同位置的多个攻击者同时向一个或几个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。常见的DDos有**SYN Flood、Ping of Death、ACK Flood、UDP Flood**等。 +- **DRDoS**: (Distributed Reflection Denial of Service),中文是分布式反射拒绝服务,该方式靠的是发送大量带有被害者IP地址的数据包给攻击主机,然后攻击主机对IP地址源做出大量回应,从而形成拒绝服务攻击。 + +## 什么是CSRF攻击,如何避免 + +CSRF,跨站请求伪造(英文全称是Cross-site request forgery),是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。 + +**怎么解决CSRF攻击呢?** + +- 检查Referer字段。 +- 添加校验token。 + +## 什么是XSS攻击? + +XSS,跨站脚本攻击(Cross-Site Scripting)。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的。XSS攻击一般分三种类型:**存储型 、反射型 、DOM型XSS** + +## 如何解决XSS攻击问题? + +- 对输入进行过滤,过滤标签等,只允许合法值。 +- HTML转义 +- 对于链接跳转,如` type -> mapping -> document -> field +``` + +这样吧,为了做个更直白的介绍,我在这里做个类比。但是切记,不要划等号,类比只是为了便于理解。 + +index 相当于 mysql 里的一张表。而 type 没法跟 mysql 里去对比,一个 index 里可以有多个 type,每个 type 的字段都是差不多的,但是有一些略微的差别。假设有一个 index,是订单 index,里面专门是放订单数据的。就好比说你在 mysql 中建表,有些订单是实物商品的订单,比如一件衣服、一双鞋子;有些订单是虚拟商品的订单,比如游戏点卡,话费充值。就两种订单大部分字段是一样的,但是少部分字段可能有略微的一些差别。 + +所以就会在订单 index 里,建两个 type,一个是实物商品订单 type,一个是虚拟商品订单 type,这两个 type 大部分字段是一样的,少部分字段是不一样的。 + +很多情况下,一个 index 里可能就一个 type,但是确实如果说是一个 index 里有多个 type 的情况(**注意**, `mapping types` 这个概念在 ElasticSearch 7. X 已被完全移除,详细说明可以参考[官方文档](https://github.com/elastic/elasticsearch/blob/6.5/docs/reference/mapping/removal_of_types.asciidoc)),你可以认为 index 是一个类别的表,具体的每个 type 代表了 mysql 中的一个表。每个 type 有一个 mapping,如果你认为一个 type 是具体的一个表,index 就代表多个 type 同属于的一个类型,而 mapping 就是这个 type 的**表结构定义**,你在 mysql 中创建一个表,肯定是要定义表结构的,里面有哪些字段,每个字段是什么类型。实际上你往 index 里的一个 type 里面写的一条数据,叫做一条 document,一条 document 就代表了 mysql 中某个表里的一行,每个 document 有多个 field,每个 field 就代表了这个 document 中的一个字段的值。 + +![](http://img.dabin-coder.cn/image/image-20221206001831784.png) + +你搞一个索引,这个索引可以拆分成多个 `shard` ,每个 shard 存储部分数据。拆分多个 shard 是有好处的,一是**支持横向扩展**,比如你数据量是 3T,3 个 shard,每个 shard 就 1T 的数据,若现在数据量增加到 4T,怎么扩展,很简单,重新建一个有 4 个 shard 的索引,将数据导进去;二是**提高性能**,数据分布在多个 shard,即多台服务器上,所有的操作,都会在多台机器上并行分布式执行,提高了吞吐量和性能。 + +接着就是这个 shard 的数据实际是有多个备份,就是说每个 shard 都有一个 `primary shard` ,负责写入数据,但是还有几个 `replica shard` 。 `primary shard` 写入数据之后,会将数据同步到其他几个 `replica shard` 上去。 + +![](http://img.dabin-coder.cn/image/image-20221206001848582.png) + +通过这个 replica 的方案,每个 shard 的数据都有多个备份,如果某个机器宕机了,没关系啊,还有别的数据副本在别的机器上呢。高可用了吧。 + +ES 集群多个节点,会自动选举一个节点为 master 节点,这个 master 节点其实就是干一些管理的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 master 节点宕机了,那么会重新选举一个节点为 master 节点。 + +如果是非 master 节点宕机了,那么会由 master 节点,让那个宕机节点上的 primary shard 的身份转移到其他机器上的 replica shard。接着你要是修复了那个宕机机器,重启了之后,master 节点会控制将缺失的 replica shard 分配过去,同步后续修改的数据之类的,让集群恢复正常。 + +说得更简单一点,就是说如果某个非 master 节点宕机了。那么此节点上的 primary shard 不就没了。那好,master 会让 primary shard 对应的 replica shard(在其他机器上)切换为 primary shard。如果宕机的机器修复了,修复后的节点也不再是 primary shard,而是 replica shard。 + +其实上述就是 ElasticSearch 作为分布式搜索引擎最基本的一个架构设计。 + + + +> 来源:https://github.com/doocs/advanced-java \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" b/docs/database/mysql-basic-all.md similarity index 94% rename from "\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" rename to docs/database/mysql-basic-all.md index 8c66844..49ffabd 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\345\237\272\347\241\200.md" +++ b/docs/database/mysql-basic-all.md @@ -1,8 +1,6 @@ -## 简介 +# 简介 -SQL 结构化查询语言。 - -### 数据类型 +## 数据类型 主要包括以下五大类: @@ -16,7 +14,7 @@ SQL 结构化查询语言。 其他数据类型:BINARY、VARBINARY、ENUM、SET、Geometry、Point、MultiPoint、LineString、MultiLineString、Polygon、GeometryCollection等 -#### 整型 +# 整型 | MySQL数据类型 | 含义(有符号) | | ------------- | ------------------------------------ | @@ -28,7 +26,7 @@ SQL 结构化查询语言。 int(m) m 用于指定显示宽度,int(5)表示5位数的宽度。注意显示宽度属性不能控制列可以存储的值范围,显示宽度属性通常由应用程序用于格式化整数值。 -#### 浮点型 +### 浮点型 | MySQL数据类型 | 含义 | | ------------- | ------------------------------------- | @@ -39,13 +37,13 @@ int(m) m 用于指定显示宽度,int(5)表示5位数的宽度。注意显示 不论是定点还是浮点类型,如果用户指定的精度超出精度范围,则会四舍五入进行处理。 -#### 定点数 +### 定点数 浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值,不会丢失精度。定点数以字符串形式存储。 decimal(m,d) 参数m是总个数,d是小数位。 -#### 字符串 +### 字符串 | MySQL数据类型 | 含义 | | ------------- | ------------------------------- | @@ -66,13 +64,13 @@ nvarchar(存储的是Unicode数据类型的字符)不管是一个字符还 text:不需要指定存储长度,能用varchar就不用text。 -#### 二进制数据(BLOB) +### 二进制数据(BLOB) 二进制数据类型可存储任何数据,如图像、多媒体、文档等。 BLOB和TEXT存储方式不同,TEXT以文本方式存储,英文存储区分大小写;而Blob是以二进制方式存储,不区分大小写。 -#### 日期时间类型 +### 日期时间类型 | MySQL数据类型 | 含义 | | ------------- | ----------------------------- | @@ -85,9 +83,9 @@ BLOB和TEXT存储方式不同,TEXT以文本方式存储,英文存储区分 -## 基本命令 +# 基本命令 -### 启动 +## 启动 启动服务:`service mysqld start` @@ -95,7 +93,7 @@ BLOB和TEXT存储方式不同,TEXT以文本方式存储,英文存储区分 启动客户端:`mysql -uroot -p` -u 后不要有空格(Ubuntu有空格) -### 数据库操作 +## 数据库操作 ```mysql SHOW DATABASES; @@ -104,7 +102,7 @@ USE db_name; DROP DATABASE db_name; ``` -### 表 +## 表 创建表:`create table user (id int, name varchar(10))` @@ -114,7 +112,7 @@ DROP DATABASE db_name; `SHOW CREATE db` | `SHOW CREATE table`:显示创建特定数据库或表的MySQL语句 -### 检索 +## 检索 检索不同的行: @@ -131,7 +129,7 @@ FROM products LIMIT 0, 5; #开始位置,行数|返回从第0行开始的5行数据 ``` -### 排序 +## 排序 ```mysql SELECT prod_name @@ -150,7 +148,7 @@ LIMIT 1; # 仅返回一行 子句顺序:FORM -- ORDER BY -- LIMIT,顺序不对会报错。 -### 过滤 +## 过滤 子句操作符: @@ -163,7 +161,7 @@ LIMIT 1; # 仅返回一行 | <= | 小于等于 | | BETWEEN | 两值之间 | -#### 不匹配检查: +### 不匹配检查: ```mysql SELECT vend_id, prod_name @@ -171,7 +169,7 @@ FROM products WHERE vend_id <> 1003; ``` -#### 范围查询: +### 范围查询: ```mysql SELECT prod_name, prod_price @@ -179,7 +177,7 @@ FROM products WHERE prod_price BETWEEN 5 AND 10; ``` -#### 空值检查 +### 空值检查 ```mysql SELECT prod_name @@ -187,7 +185,7 @@ FROM products WHERE prod_price IS NULL; ``` -#### 计算次序 +### 计算次序 ```mysql SELECT prod_name, prod_price @@ -195,7 +193,7 @@ FROM products WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10; # AND优先级大于OR ``` -#### IN 操作符 +### IN 操作符 ```mysql SELECT prod_name, product_price @@ -206,7 +204,7 @@ ORDER BY prod_name; IN操作符一般比OR操作符清单执行更快。IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。 -#### NOT操作符 +### NOT操作符 MySQL支持使用NOT 对IN 、BETWEEN 和EXISTS子句取反。 @@ -216,7 +214,7 @@ FROM products WHERE vend_id NOT IN (1002, 1003) ``` -#### LIKE操作符 +### LIKE操作符 % 匹配0到多个任意字符。 @@ -236,11 +234,11 @@ WHERE prod_name LIKE '_jet_'; 通配符搜索比其他简单搜索耗时,不能过度使用通配符。 -#### LIMIT +### LIMIT limit 0,4 :从第0条记录开始,取4条 -#### 正则表达式 +### 正则表达式 OR 匹配: @@ -316,9 +314,9 @@ ORDER BY prod_name; SELECT 'hello' REGEXP '[0-9]';#REGEXP检查返回0或1;此处返回0 ``` -## 计算字段 +# 计算字段 -### 拼接字段 +## 拼接字段 MySQL使用Concat()函数实现拼接。 @@ -331,7 +329,7 @@ ORDER BY vend_name; 返回值:`ACME (USA)` 使用别名:`SELECT dept AS department FROM t_dept;` -### 计算字段 +## 计算字段 ```mysql SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price @@ -339,9 +337,9 @@ FROM orderitems WHERE order_num = 2005; ``` -## 函数 +# 函数 -### 文本处理 +## 文本处理 ```mysql SELECT vend_name, Upper(vend_name) AS vend_name_upcase @@ -359,7 +357,7 @@ WHERE Soundex(cust_contact) = Soundex('Y Lie'); 返回数据:`Tyson Y lee` -### 日期处理函数 +## 日期处理函数 ![](http://img.dabin-coder.cn/image/20220530235607.png) 查找2005年9月的所有订单: @@ -378,13 +376,13 @@ FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9; ``` -### 数值处理函数 +## 数值处理函数 ![](http://img.dabin-coder.cn/image/20220530233617.png) -## 汇总数据 +# 汇总数据 -### 聚集函数 +## 聚集函数 Sum:求和 Avg:求平均数 @@ -406,7 +404,7 @@ FROM products WHERE vend_id = 1003; ``` -## 分组 +# 分组 单独地使用group by没意义,它只能显示出每组记录的第一条记录。 @@ -427,7 +425,7 @@ GROUP BY vend_id; GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。 -### 过滤分组 +## 过滤分组 having 用来分组查询后指定一些条件来输出查询结果,having作用和where类似,但是having只能用在group by场合,并且必须位于group by之后order by之前。 @@ -438,7 +436,7 @@ GROUP BY cust_id HAVING COUNT(*) >= 2; ``` -### having和where区别 +## having和where区别 ```mysql SELECT cust_id FROM orders GROUP BY cust_id HAVING COUNT(cust_id) >= 2; @@ -463,7 +461,7 @@ HAVING COUNT(*) >= 2; WHERE子句过滤所有prod_price至少为10的行。然后按vend_id分组数据,HAVING子句过滤计数为2或2以上的分组。 -### SELECT 子句顺序 +## SELECT 子句顺序 ```mysql SELECT @@ -477,7 +475,7 @@ LIMIT -## 子查询 +# 子查询 由于性能的限制,不能嵌套太多的子查询。 @@ -491,9 +489,9 @@ WHERE order_num IN (SELECT order_num -## 连接 +# 连接 -### 内连接 +## 内连接 找出供应商生产的产品。 @@ -513,7 +511,7 @@ WHERE vendors.vend_id = products.vend_id; 没有给出连接条件的话,会得到两张表的笛卡尔积。 -### 自连接 +## 自连接 找出生产nike的供应商生产的所有物品。 @@ -524,7 +522,7 @@ WHERE p1.vend_id = p2.vend_id AND p2.prod_id = 'nike'; ``` -### 自然连接 +## 自然连接 natural join是对两张表中字段名和数据类型都相同的字段进行**等值连接**,并返回符合条件的结果 。 @@ -536,7 +534,7 @@ SELECT * FROM role NATURAL JOIN user_role; ![](http://img.dabin-coder.cn/image/20220530235619.png) -### 内连接 +## 内连接 显示符合连接条件的记录。没有设置连接条件则返回笛卡尔积的结果。join 默认是 inner join。 @@ -559,7 +557,7 @@ SELECT * FROM role INNER JOIN user_role ON role.role_id = user_role.role_id ![](http://img.dabin-coder.cn/image/20220530235654.png) -### 外连接 +## 外连接 左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。 右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。 @@ -573,7 +571,7 @@ FROM customers LEFT OUTER JOIN orders ON customers.cust_id = order.cust_id; ``` -### 多表连接 +## 多表连接 ```mysql SELECT goal.player, eteam.teamname, game.stadium, game.mdate @@ -586,9 +584,9 @@ WHERE eteam.id = 'GRE' -## 组合查询 +# 组合查询 -### UNION +## UNION UNION中的每个查询必须包含相同的列、表达式或聚集函数。列数据类型必须兼容。 @@ -611,7 +609,7 @@ UNION 默认会去掉重复的行,使用 UNION ALL可以返回所有匹配行 -## 全文搜索 +# 全文搜索 为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有的索引和重新索引。 @@ -653,9 +651,9 @@ FROM productnotes; -## 表操作 +# 表操作 -### 创建表 +## 创建表 ```mysql CREATE TABLE productnotes @@ -670,7 +668,7 @@ CREATE TABLE productnotes 主键中只能使用NOT NULL值的列。 -### 更新表 +## 更新表 数据库表的更改不能撤销,应先做好备份。 @@ -708,7 +706,7 @@ MODIFY vend_phone CHAR(16); - 重新创建触发器、存储过程、索引和外键。 -### 约束 +## 约束 添加主键约束: @@ -737,19 +735,33 @@ ADD FOREIGN KEY(vendor_id) REFERENCES vendors(vendor_id); ALTER TABLE products DROP FOREIGN KEY vendor_id; ``` -### 删除表 +## 删除表 `DROP TABLE cumstomers` -### 重命名表 +## truncate、delete与drop区别 + +**相同点:** + +1. truncate和不带where子句的delete、以及drop都会删除表内的数据。 + +2. drop、truncate都是DDL语句(数据定义语言),执行后会自动提交。 + +**不同点:** + +1. truncate 和 delete 只删除数据不删除表的结构;drop 语句将删除表的结构被依赖的约束、触发器、索引; + +2. 速度,一般来说: drop> truncate > delete。 + +## 重命名表 `RENAME TABLE cusmtomers TO cust` -## 列操作 +# 列操作 -### 插入数据 +## 插入数据 MySQL用单条INSERT语句处理多个插入比使用多条INSERT语句快。 @@ -761,7 +773,7 @@ INSERT INTO customers(cust_name, cust_city) INSERT操作可能很耗时(特别是有很多索引需要更新时),而且它可能降低等待处理的SELECT语句的性能。降低INSERT语句的优先级:`INSERT LOW_PRIORITY INTO` -### 更新数据 +## 更新数据 如果用UPDATE语句更新多行,并且在更新这些行中的一行或多行时出一个现错误,则整个UPDATE操作被取消。为了在发生错误时也继续进行更新,可使用IGNORE关键字:`UPDATE IGNORE customers...` @@ -773,7 +785,7 @@ WHERE cust_id = 1005; 返回值是受影响的记录数。 -### 删除数据 +## 删除数据 如果想从表中删除所有行,不要使用DELETE。可使用TRUNCATE TABLE语句,它完成相同的工作,但速度更快(TRUNCATE实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)。 @@ -795,23 +807,9 @@ AND EXISTS WHERE b.id = a.id); ``` -### truncate、delete与drop区别 - -**相同点:** - -1. truncate和不带where子句的delete、以及drop都会删除表内的数据。 - -2. drop、truncate都是DDL语句(数据定义语言),执行后会自动提交。 - -**不同点:** - -1. truncate 和 delete 只删除数据不删除表的结构;drop 语句将删除表的结构被依赖的约束、触发器、索引; - -2. 速度,一般来说: drop> truncate > delete。 - -## 引擎 +# 引擎 InnoDB是一个可靠的事务处理引擎,它不支持全文本搜索; @@ -823,23 +821,23 @@ MyISAM是一个性能极高的引擎,它支持全文本搜索,但不支持 -## 视图 +# 视图 视图为虚拟的表。视图提供了一种MySQL的SELECT语句层次的封装,可用来简化数据处理以及重新格式化基础数据或保护基础数据。 -### 应用 +## 应用 - 重用SQL语句。 - 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。 - 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。 -### 限制 +## 限制 - 与表一样,视图必须唯一命名 - 视图不能索引,也不能有关联的触发器或默认值。 - 视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。 - ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。 -### 语法 +## 语法 `CREATE VIEW`:创建视图 @@ -848,7 +846,7 @@ MyISAM是一个性能极高的引擎,它支持全文本搜索,但不支持 `DROP VIEW viewname`:删除视图 `CREATE ORREPLACE VIEW`:更新视图,相当于先用`DROP`再用`CREATE` -### 简化复杂连接 +## 简化复杂连接 创建一个视图,返回订购了任意产品的客户列表。 ```mysql CREATE VIEW productcustomers AS @@ -863,20 +861,20 @@ SELECT cust_name, cust_contact FROM productcustomers WHERE prod_id = 'nike'; ``` -### 更新视图 +## 更新视图 对视图增加或删除行,实际上是对其基表增加或删除行。视图主要用于数据检索。 -## 存储过程 +# 存储过程 为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件。 为什么使用存储过程: - 把复杂处理进行封装,简化复杂的操作; - 提高性能,存储过程比单独SQL语句更快; -### 创建 +## 创建 返回产品平均价格的存储过程: ```mysql CREATE PROCEDURE productpricing() # 可以接受参数 @@ -886,12 +884,12 @@ BEGIN END; ``` BEGIN/END 用来限定存储过程体。此段代码仅创建了存储过程,未执行。 -### 调用 +## 调用 `CALL productpricing()` -### 删除 +## 删除 存储过程在创建之后,被保存在服务器上以供使用,直至被删除。 `DROP PROCEDURE productpricing IF EXISTS` -### 参数 +## 参数 MySQL支持IN(传递给存储过程)、OUT(从存储过程传出)和INOUT(对存储过程传入和传出)类型的参数。 接受订单号并返回该订单的金额: ```mysql @@ -908,7 +906,7 @@ END; ``` 调用存储过程:`CALL ordertotal(20, @total);` 显示订单金额:`SELECT @total;` -### 实例 +## 实例 获取订单税后金额(订单金额+税收)。 ```mysql CREATE PROCEDURE ordertotal( @@ -936,7 +934,7 @@ END; CALL ordertotal(20005, 1, @total); SELECT @total; ``` -### 查看 +## 查看 创建存储过程的 CREATE 语句。 ```mysql SHOW CREATE PROCEDURE ordertotal; @@ -949,9 +947,9 @@ SHOW CREATE PROCEDURE ordertotal; SHOW PROCEDURE status; ``` -## 游标 +# 游标 存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。MySQL游标只能用于存储过程(和函数)。 -### 创建游标 +## 创建游标 DECLARE 命名游标。存储过程处理完成后,游标便消失(游标只存在于存储过程)。定义游标之后,便可以打开它。 ```mysql CREATE PROCEDURE processorders() @@ -961,7 +959,7 @@ BEGIN SELECT order_num FROM orders; END; ``` -### 使用游标 +## 使用游标 `OPEN ordernumbers` 打开游标。 `CLOSE ordernumbers` CLOSE释放游标使用的所有内部内存和资源。 ```mysql @@ -1002,20 +1000,20 @@ END; -## 触发器 +# 触发器 -提供SQL语句自动执行的功能。DELETE/INSERT/UPDATE支持触发器,其他SQL语句不支持。 -### 创建 +触发器提供SQL语句自动执行的功能。DELETE/INSERT/UPDATE支持触发器,其他SQL语句不支持。 +## 创建 创建触发器四要素:1.唯一的触发器名(MySQL5规定触发器名在表中唯一,数据库没要求);2.触发器关联的表;3.相应的SQL语句;4.何时执行(处理之前或者之后)。 ```mysql CREATE TRIGGER newproduct AFTER INSERT ON products #插入之后执行 FOR EACH ROW SELECT 'product added'; #对每个插入行执行 ``` 只有表支持触发器,视图不支持。单一触发器不能与多个事件或多个表关联,如果需要对INSERT和UPDATE操作执行触发器,则应该定义两个触发器。 -### 删除 +## 删除 `DROP TRIGGER newproduct` -### 使用触发器 +## 使用触发器 INSERT 触发器可饮用名为 NEW 的虚拟表,访问被插入的行。NEW中的值也可以被更新(允许更改被插入的值)。 @@ -1048,7 +1046,7 @@ FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state); -## 事务处理 +# 事务处理 事务处理可以用来维护数据库的完整性。它保证成批的MySQL操作要么完全执行,要么完全不执行。 @@ -1056,6 +1054,8 @@ CREATE/DROP 操作不能回退,即便可以执行回退操作,回退不会 执行事务过程,一旦某个SQL失败,则之前执行成功的SQL会被自动撤销。 +## 语法 + ```mysql START TRANSACTION; DELETE FROM orderitems WHERE order_num = 20010; @@ -1065,7 +1065,7 @@ COMMIT; 当COMMIT或ROLLBACK语句执行后,事务会自动关闭。 -### 保留点 +## 保留点 为了支持回退部分事务处理,必须能在事务处理块中合适的位置放置占位符。这样,如果需要回退,可以回退到某个占位符。 @@ -1080,11 +1080,11 @@ ROLLBACK TO delete1; -## 权限 +# 权限 -### 管理用户 +MySQL用户账号和信息存储在名为mysql的MySQL数据库中。 -MySQL用户账号和信息存储在名为mysql的MySQL数据库中。获取用户账号列表。 +获取用户账号列表: ```mysql USE mysql; @@ -1108,15 +1108,16 @@ SELECT user FROM user; 撤销权限:`REVOKE SELECT, INSERT ON mall.* FROM tyson`,被撤销的访问权限必须存在,否则会出错。 GRANT和REVOKE可在几个层次上控制访问权限: - 整个服务器,使用GRANT ALL和REVOKE ALL; - 整个数据库,使用ON database.*; - 特定的表,使用ON database.table; - 特定的列; - 特定的存储过程。 +- 整个服务器,使用GRANT ALL和REVOKE ALL; +- 整个数据库,使用ON database.*; +- 特定的表,使用ON database.table; +- 特定的列; +- 特定的存储过程。 -## 优化性能 + +# 性能优化 使用EXPLAIN语句让MySQL解释它将如何执行一条SELECT语句。 @@ -1127,6 +1128,7 @@ GRANT和REVOKE可在几个层次上控制访问权限: LIKE很慢,最好是使用FULLTEXT而不是LIKE。 很多高性能的应用都会对关联查询进行分解,有如下的优势: + 1 、让缓存效率更高。如果某张表很少变化,那么基于该表的查询就可以重复利用查询缓存结果。 2 、将查询分解后,执行单个查询可以减少锁的竞争。 3 、在应用层做关联,可以更容易对数据库进行拆分,更容易做到高性能和可扩展。 @@ -1136,9 +1138,9 @@ LIKE很慢,最好是使用FULLTEXT而不是LIKE。 -## 索引 +# 索引 -### 创建索引 +## 创建索引 ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。 @@ -1157,7 +1159,7 @@ CREATE UNIQUE INDEX index_name ON table_name (column_list) 在创建索引时,可以规定索引能否包含重复值。如果不包含,则索引应该创建为PRIMARY KEY或UNIQUE索引。 -### 删除索引 +## 删除索引 ```mysql DROP INDEX index_name ON talbe_name @@ -1165,7 +1167,7 @@ ALTER TABLE table_name DROP INDEX index_name ALTER TABLE table_name DROP PRIMARY KEY #只有一个主键,不需要指定索引名 ``` -### 查看索引 +## 查看索引 ```mysql show index from tblname; diff --git a/docs/database/mysql-basic/1-data-type.md b/docs/database/mysql-basic/1-data-type.md new file mode 100644 index 0000000..6818dcc --- /dev/null +++ b/docs/database/mysql-basic/1-data-type.md @@ -0,0 +1,82 @@ +# 数据类型 + +主要包括以下五大类: + +整数类型:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT + +浮点数类型:FLOAT、DOUBLE、DECIMAL + +字符串类型:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM TEXT、LONGTEXT、TINY BLOB、BLOB、MEDIUM BLOB、LONG BLOB + +日期类型:Date、DateTime、TimeStamp、Time、Year + +其他数据类型:BINARY、VARBINARY、ENUM、SET、Geometry、Point、MultiPoint、LineString、MultiLineString、Polygon、GeometryCollection等 + +## 整型 + +| MySQL数据类型 | 含义(有符号) | +| ------------- | ------------------------------------ | +| tinyint(m) | 1个字节 范围(-128~127) | +| smallint(m) | 2个字节 范围(-32768~32767) | +| mediumint(m) | 3个字节 范围(-8388608~8388607) | +| int(m) | 4个字节 范围(-2147483648~2147483647) | +| bigint(m) | 8个字节 范围(+-9.22*10的18次方) | + +int(m) m 用于指定显示宽度,int(5)表示5位数的宽度。注意显示宽度属性不能控制列可以存储的值范围,显示宽度属性通常由应用程序用于格式化整数值。 + +## 浮点型 + +| MySQL数据类型 | 含义 | +| ------------- | ------------------------------------- | +| float(m,d) | 单精度浮点型 4字节 m总个数,d小数位 | +| double(m,d) | 双精度浮点型 8字节 m总个数,d小数位 | + +浮点型数据类型会有精度丢失的问题,比如小数位设置6位,存入0.45,0.45转换成二进制是个无限循环小数0.01110011100...,无法准确表示,存储的时候会发生精度丢失。 + +不论是定点还是浮点类型,如果用户指定的精度超出精度范围,则会四舍五入进行处理。 + +## 定点数 + +浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值,不会丢失精度。定点数以字符串形式存储。 + +decimal(m,d) 参数m是总个数,d是小数位。 + +## 字符串 + +| MySQL数据类型 | 含义 | +| ------------- | ------------------------------- | +| char(n) | 固定长度,最多255个字节 | +| varchar(n) | 可变长度,最多65535个字节 | +| tinytext | 可变长度,最多255个字节 | +| text | 可变长度,最多65535个字节 | +| mediumtext | 可变长度,最多2的24次方-1个字节 | +| longtext | 可变长度,最多2的32次方-1个字节 | + +查询速度:char > varchar > text + +char:定长,效率高,一般用于固定长度的表单提交数据存储 ;例如:身份证号,手机号,电话,密码等。char长度不足时,在右边使用空格填充,而varchar值保存时只保存需要的字符数。 + +varchar:不定长,效率偏低,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535。 + +nvarchar(存储的是Unicode数据类型的字符)不管是一个字符还是一个汉字,都存为2个字节 ,一般用作中文或者其他语言输入,这样不容易乱码 ;varchar存储汉字是2个字节,其他字符存为1个字节 ,varchar适合输入英文和数字。 + +text:不需要指定存储长度,能用varchar就不用text。 + +## 二进制数据(BLOB) + +二进制数据类型可存储任何数据,如图像、多媒体、文档等。 + +BLOB和TEXT存储方式不同,TEXT以文本方式存储,英文存储区分大小写;而Blob是以二进制方式存储,不区分大小写。 + +## 日期时间类型 + +| MySQL数据类型 | 含义 | +| ------------- | ----------------------------- | +| date | 日期 '2008-12-2' | +| time | 时间 '12:25:36' | +| datetime | 日期时间 '2008-12-2 22:06:44' | +| timestamp | 自动存储记录修改时间 | + +若定义一个字段为timestamp,这个字段里的时间数据会随其他字段修改的时候自动刷新,所以这个数据类型的字段可以存放这条记录最后被修改的时间。 + + diff --git a/docs/database/mysql-basic/10-view.md b/docs/database/mysql-basic/10-view.md new file mode 100644 index 0000000..f770fb5 --- /dev/null +++ b/docs/database/mysql-basic/10-view.md @@ -0,0 +1,50 @@ +# 视图 + +视图为虚拟的表。视图提供了一种MySQL的SELECT语句层次的封装,可用来简化数据处理以及重新格式化基础数据或保护基础数据。 + +## 应用 + +- 重用SQL语句。 +- 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。 +- 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。 + +## 限制 + +- 与表一样,视图必须唯一命名 +- 视图不能索引,也不能有关联的触发器或默认值。 +- 视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。 +- ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。 + +## 语法 + +`CREATE VIEW`:创建视图 + +`SHOW CREATE VIEW viewname`:查看创建视图的语句 + +`DROP VIEW viewname`:删除视图 + +`CREATE ORREPLACE VIEW`:更新视图,相当于先用`DROP`再用`CREATE` + +## 简化复杂连接 + +创建一个视图,返回订购了任意产品的客户列表。 + +```mysql +CREATE VIEW productcustomers AS +SELECT cust_name, orders, orderitems +FROM customers, orders, orderitems +WHERE orderitems.order_num = orders.order_num + AND customers.cust_id = orders.cust_id; +``` + +使用视图: + +```mysql +SELECT cust_name, cust_contact +FROM productcustomers +WHERE prod_id = 'nike'; +``` + +## 更新视图 + +对视图增加或删除行,实际上是对其基表增加或删除行。视图主要用于数据检索。 \ No newline at end of file diff --git a/docs/database/mysql-basic/11-procedure.md b/docs/database/mysql-basic/11-procedure.md new file mode 100644 index 0000000..f03c531 --- /dev/null +++ b/docs/database/mysql-basic/11-procedure.md @@ -0,0 +1,101 @@ +# 存储过程 + +为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件。 +为什么使用存储过程: + +- 把复杂处理进行封装,简化复杂的操作; +- 提高性能,存储过程比单独SQL语句更快; + +## 创建 + +返回产品平均价格的存储过程: + +```mysql +CREATE PROCEDURE productpricing() # 可以接受参数 +BEGIN + SELECT Avg(prod_price) AS priceaverage + FROM products; +END; +``` + +BEGIN/END 用来限定存储过程体。此段代码仅创建了存储过程,未执行。 + +## 调用 + +`CALL productpricing()` + +## 删除 + +存储过程在创建之后,被保存在服务器上以供使用,直至被删除。 +`DROP PROCEDURE productpricing IF EXISTS` + +## 参数 + +MySQL支持IN(传递给存储过程)、OUT(从存储过程传出)和INOUT(对存储过程传入和传出)类型的参数。 +接受订单号并返回该订单的金额: + +```mysql +CREATE PROCEDURE ordertotal( + IN ordernum INT, + OUT ordersum DECIMAL(8, 2) +) +BEGIN + SELECT Sum(item_price * quantity) + FROM orderitems + WHERE order_num = ordernum + INTO ordersum; +END; +``` + +调用存储过程:`CALL ordertotal(20, @total);` +显示订单金额:`SELECT @total;` + +## 实例 + +获取订单税后金额(订单金额+税收)。 + +```mysql +CREATE PROCEDURE ordertotal( + IN onum INT, + IN taxable BOOLEAN, # 是否计税 + OUT ototal DECIMAL(8, 2) +) COMMENT 'order total, adding tax' +BEGIN + DECLARE total DECIMAL(8, 2); + DECLARE taxrate INT DEFAULT 6; + + SELECT Sum(item_price * quanlity) + FROM orderitems + WHERE order_num = onum + INTO total; + + IF taxable THEN + SELECT total + (total / 100 * taxrate) INTO total; + END IF; + -- SELECT total INTO ototal; +END; +``` + +调用存储过程: + +```mysql +CALL ordertotal(20005, 1, @total); +SELECT @total; +``` + +## 查看 + +创建存储过程的 CREATE 语句。 + +```mysql +SHOW CREATE PROCEDURE ordertotal; +``` + +获得包括何时、由谁创建等详细信息的存储过程列表,使用`SHOW PROCEDURE STATUS LIKE 'ordertotal';` + +查看存储过程状态: + +```mysql +SHOW PROCEDURE status; +``` + diff --git a/docs/database/mysql-basic/12-cursor.md b/docs/database/mysql-basic/12-cursor.md new file mode 100644 index 0000000..dad75b4 --- /dev/null +++ b/docs/database/mysql-basic/12-cursor.md @@ -0,0 +1,58 @@ +# 游标 + +存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。MySQL游标只能用于存储过程(和函数)。 + +## 创建游标 + +DECLARE 命名游标。存储过程处理完成后,游标便消失(游标只存在于存储过程)。定义游标之后,便可以打开它。 + +```mysql +CREATE PROCEDURE processorders() +BEGIN + DECLARE ordernumbers CURSOR + FOR + SELECT order_num FROM orders; +END; +``` + +## 使用游标 + +`OPEN ordernumbers` 打开游标。 +`CLOSE ordernumbers` CLOSE释放游标使用的所有内部内存和资源。 + +```mysql +CREATE PROCEDURE processorders() +BEGIN + + DECLARE done BOOLEAN DEFAULT 0; + DECLARE o INT; + DECLARE t DECIMAL(8, 2); + + DECLARE ordernumbers CURSOR + FOR + SELECT order_num FROM orders; + + DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; #游标移到最后 + + CREATE TABLE IF NOT EXISTS ordertotals + (order_num INT, total DECIMAL(8,2)); + -- 打开游标 + OPEN ordernumbers; + + -- 循环 + REPEAT + FETCH ordernumbers INTO o; + CALL ordertotal(o, 1, t); + + -- 插入订单号和订单金额 + INSERT INTO ordertotals(order_num, total) + VALUES(o, t); + + -- done为1结束循环 + UNTIL done END REPEAT; + + CLOSE ordernumbers; +END; +``` + +存储过程还在运行中创建了一个新表,。这个表将保存存储过程生成的结果。FETCH取每个order_num,然后用CALL执行另一个存储过程,计算每个订单税后金额。最后,用INSERT保存每个订单的订单号和金额。 \ No newline at end of file diff --git a/docs/database/mysql-basic/13-trigger.md b/docs/database/mysql-basic/13-trigger.md new file mode 100644 index 0000000..f05b92f --- /dev/null +++ b/docs/database/mysql-basic/13-trigger.md @@ -0,0 +1,51 @@ +# 触发器 + +触发器提供SQL语句自动执行的功能。DELETE/INSERT/UPDATE支持触发器,其他SQL语句不支持。 + +## 创建 + +创建触发器四要素:1.唯一的触发器名(MySQL5规定触发器名在表中唯一,数据库没要求);2.触发器关联的表;3.相应的SQL语句;4.何时执行(处理之前或者之后)。 + +```mysql +CREATE TRIGGER newproduct AFTER INSERT ON products #插入之后执行 +FOR EACH ROW SELECT 'product added'; #对每个插入行执行 +``` + +只有表支持触发器,视图不支持。单一触发器不能与多个事件或多个表关联,如果需要对INSERT和UPDATE操作执行触发器,则应该定义两个触发器。 + +## 删除 + +`DROP TRIGGER newproduct` + +## 使用 + +INSERT 触发器可饮用名为 NEW 的虚拟表,访问被插入的行。NEW中的值也可以被更新(允许更改被插入的值)。 + +```mysql +CREATE TRIGGER neworder AFTER INSERT ON order +FOR EACH ROW SELECT NEW.order_num; #返回新的订单号 +``` + +DELETE 触发器可以引用名为 OLD 的虚拟表,访问被删除的行。OLD中的值全都是只读的,不能更新。 + +```mysql +CREATE TRIGGER deleteorder BEFORE DELETE ON orders +FOR EACH ROW +BEGIN + INSERT INTO archive_orders(order_num, cust_id) + VALUES(OLD.order_num, OLD.cust_id); +END; +``` + +订单删除之前保存订单信息到存档表。 + +UPDATE 触发器可以引用名为 OLD 的虚拟表访问以前的值,引用一个名为NEW的虚拟表访问新更新的值。NEW 值可被更新,OLD 值是只读的。 + +下面的例子保证州名缩写总是大写。 + +```mysql +CREATE TRIGGER updatevendor BEFORE UPDATE ON vendor +FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state); +``` + + diff --git a/docs/database/mysql-basic/14-transaction.md b/docs/database/mysql-basic/14-transaction.md new file mode 100644 index 0000000..1526284 --- /dev/null +++ b/docs/database/mysql-basic/14-transaction.md @@ -0,0 +1,32 @@ +# 事务处理 + +事务处理可以用来维护数据库的完整性。它保证成批的MySQL操作要么完全执行,要么完全不执行。 + +CREATE/DROP 操作不能回退,即便可以执行回退操作,回退不会有效果。 + +执行事务过程,一旦某个SQL失败,则之前执行成功的SQL会被自动撤销。 + +## 语法 + +```mysql +START TRANSACTION; +DELETE FROM orderitems WHERE order_num = 20010; +DELETE FROM orders WHERE order_num = 20010; +COMMIT; +``` + +当COMMIT或ROLLBACK语句执行后,事务会自动关闭。 + +## 保留点 + +为了支持回退部分事务处理,必须能在事务处理块中合适的位置放置占位符。这样,如果需要回退,可以回退到某个占位符。 + +保留点在事务处理完成后自动释放。 + +```mysql +... +SAVEPOINT delete1; +... +ROLLBACK TO delete1; +``` + diff --git a/docs/database/mysql-basic/15-permission.md b/docs/database/mysql-basic/15-permission.md new file mode 100644 index 0000000..e65754c --- /dev/null +++ b/docs/database/mysql-basic/15-permission.md @@ -0,0 +1,35 @@ +# 权限 + +MySQL用户账号和信息存储在名为mysql的MySQL数据库中。 + +获取用户账号列表: + +```mysql +USE mysql; +SELECT user FROM user; +``` + +创建用户账号:`CREATE USER tyson IDENTIFIED BY 'abc123'` + +修改密码:`SET PASSWORD FOR tyson = Password('xxx');`,新密码需传递到Password()函数进行加密。 + +设置当前用户密码:`SET PASSWORD = Password('xxx');` + +重命名账号:`RENAME USER tyson TO tom` + +删除用户账号:`DROP USER tyson` + +查看访问权限:`SHOW GRANTS FOR tyson`,返回`USAGE ON *.*`则表示没有权限。 + +授予访问权限:`GRANT SELECT ON mall.# TO tyson`,允许用户在mall数据库所有表使用SELECT。 + +撤销权限:`REVOKE SELECT, INSERT ON mall.* FROM tyson`,被撤销的访问权限必须存在,否则会出错。 + +GRANT和REVOKE可在几个层次上控制访问权限: + +- 整个服务器,使用GRANT ALL和REVOKE ALL; +- 整个数据库,使用ON database.*; +- 特定的表,使用ON database.table; +- 特定的列; +- 特定的存储过程。 + diff --git a/docs/database/mysql-basic/16-performace-optimization.md b/docs/database/mysql-basic/16-performace-optimization.md new file mode 100644 index 0000000..8fe6e47 --- /dev/null +++ b/docs/database/mysql-basic/16-performace-optimization.md @@ -0,0 +1,18 @@ +# 性能优化 + +使用EXPLAIN语句让MySQL解释它将如何执行一条SELECT语句。 + +如果一个简单的WHERE子句返回结果所花的时间太长,则可以断定其中使用的某些列就是需要索引的对象。 + +避免使用OR。通过使用多条SELECT语句和连接它们的UNION语句,会有极大的性能改进。 + +LIKE很慢,最好是使用FULLTEXT而不是LIKE。 + +很多高性能的应用都会对关联查询进行分解,有如下的优势: + +1 、让缓存效率更高。如果某张表很少变化,那么基于该表的查询就可以重复利用查询缓存结果。 +2 、将查询分解后,执行单个查询可以减少锁的竞争。 +3 、在应用层做关联,可以更容易对数据库进行拆分,更容易做到高性能和可扩展。 +4 、查询本身效率也可能会有所提升。例如 IN()代替关联查询,可能比随机的关联更高效。 +5 、减少冗余记录得查询。 +6 、更进一步,这样做相当于在应用中实现了哈希关联,而不是使用 MySQL 得嵌套循环关联。某些场景哈希关联得效率要高很多。 \ No newline at end of file diff --git a/docs/database/mysql-basic/17-index.md b/docs/database/mysql-basic/17-index.md new file mode 100644 index 0000000..a28dc43 --- /dev/null +++ b/docs/database/mysql-basic/17-index.md @@ -0,0 +1,36 @@ +# 索引 + +## 创建索引 + +ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。 + +```mysql +ALTER TABLE table_name ADD INDEX index_name (column_list) +ALTER TABLE table_name ADD UNIQUE (column_list) +ALTER TABLE table_name ADD PRIMARY KEY (column_list) +``` + +CREATE INDEX可对表增加普通索引或UNIQUE索引。 + +```mysql +CREATE INDEX index_name ON table_name (column_list) +CREATE UNIQUE INDEX index_name ON table_name (column_list) +``` + +在创建索引时,可以规定索引能否包含重复值。如果不包含,则索引应该创建为PRIMARY KEY或UNIQUE索引。 + +## 删除索引 + +```mysql +DROP INDEX index_name ON talbe_name +ALTER TABLE table_name DROP INDEX index_name +ALTER TABLE table_name DROP PRIMARY KEY #只有一个主键,不需要指定索引名 +``` + +## 查看索引 + +```mysql +show index from tblname; +show keys from tblname; +``` + diff --git a/docs/database/mysql-basic/2-basic-command.md b/docs/database/mysql-basic/2-basic-command.md new file mode 100644 index 0000000..621b0b4 --- /dev/null +++ b/docs/database/mysql-basic/2-basic-command.md @@ -0,0 +1,230 @@ +# 基本命令 +## 启动 + +启动服务:`service mysqld start` + +关闭服务:`service mysqld stop` + +启动客户端:`mysql -uroot -p` -u 后不要有空格(Ubuntu有空格) + +## 数据库操作 + +```mysql +SHOW DATABASES; +CREATE DATABASE db_name; +USE db_name; +DROP DATABASE db_name; +``` + +## 表 + +创建表:`create table user (id int, name varchar(10))` + +清空表数据:`truncate table user;` + +查看表结构:`desc table_name/select columns from table_name` + +`SHOW CREATE db` | `SHOW CREATE table`:显示创建特定数据库或表的MySQL语句 + +## 检索 + +检索不同的行: + +```mysql +SELECT DISTINCT vend_id +FROM products; +``` + +限制结果: + +```mysql +SELECT prod_name +FROM products +LIMIT 0, 5; #开始位置,行数|返回从第0行开始的5行数据 +``` + +## 排序 + +```mysql +SELECT prod_name +FROM products +ORDER BY prod_name, prod_price DESC; #先按名称排序,再按价格排序 | DESC降序排列,默认ASC升序 +``` + +找出最贵的物品: + +```mysql +SELECT prod_price +FROM products +ORDER BY prod_price DESC +LIMIT 1; # 仅返回一行 +``` + +子句顺序:FORM -- ORDER BY -- LIMIT,顺序不对会报错。 + +## 过滤 + +子句操作符: + +| 操作符 | 说明 | +| ------- | -------- | +| = | 等于 | +| <> | 不等于 | +| != | 不等于 | +| < | 小于 | +| <= | 小于等于 | +| BETWEEN | 两值之间 | + +### 不匹配检查: + +```mysql +SELECT vend_id, prod_name +FROM products +WHERE vend_id <> 1003; +``` + +### 范围查询: + +```mysql +SELECT prod_name, prod_price +FROM products +WHERE prod_price BETWEEN 5 AND 10; +``` + +### 空值检查 + +```mysql +SELECT prod_name +FROM products +WHERE prod_price IS NULL; +``` + +### 计算次序 + +```mysql +SELECT prod_name, prod_price +FROM products +WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10; # AND优先级大于OR +``` + +### IN 操作符 + +```mysql +SELECT prod_name, product_price +FROM products +WHERE vend_id IN (1002, 1003) +ORDER BY prod_name; +``` + +IN操作符一般比OR操作符清单执行更快。IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。 + +### NOT操作符 + +MySQL支持使用NOT 对IN 、BETWEEN 和EXISTS子句取反。 + +```mysql +SELECT prod_name, product_price +FROM products +WHERE vend_id NOT IN (1002, 1003) +``` + +### LIKE操作符 + +% 匹配0到多个任意字符。 + +```mysql +SELECT prod_id, prod_name +FROM products +WHERE prod_name LIKE '%jet%'; +``` + +_ 匹配单个字符。 + +```mysql +SELECT prod_id, prod_name +FROM products +WHERE prod_name LIKE '_jet_'; +``` + +通配符搜索比其他简单搜索耗时,不能过度使用通配符。 + +### LIMIT + +limit 0,4 :从第0条记录开始,取4条 + +### 正则表达式 + +OR 匹配: + +```mysql +SELECT prod_name +FROM products +WHERE prod_name REGEXP '1000|2000' +ORDER BY prod_name; +``` + +匹配特定字符: + +```mysql +SELECT prod_name +FROM products +WHERE prod_name REGEXP '[123] Rely' #匹配1或2或3 [^123]取反 +ORDER BY prod_name; +``` + +匹配范围: + +```mysql +SELECT prod_name +FROM products +WHERE prod_anem REGEXP '[1-5] Ton';#匹配1-5任意一个数字,[a-z]同理 +``` + +匹配特殊字符: + +```mysql +SELECT prod_name +FROM products +WHERE prod_anem REGEXP '\\.';#转义 +``` + +匹配多个实例: + +```mysql +SELECT prod_name +FROM products +WHERE prod_anem REGEXP '\\([0-9] sticks?\\)'; #?匹配它前面的任何字符出现0次或1次 +``` + +匹配连着的四个数: + +```mysql +SELECT prod_name +FROM products +WHERE prod_anem REGEXP '[[:digit:]]{4}'; #[:digit:]匹配任意数字 +``` + +定位符: + +| 元字符 | 说明 | +| ------- | -------- | +| ^ | 文本开始 | +| $ | 文本结束 | +| [[:<:]] | 词开始 | +| [[:>:]] | 词结束 | + +查找一个数(包括小数点开始的数)开始的所有产品: + +```mysql +SELECT prod_name +FROM products +WHERE prod_name REGEXP '^[0-9\\.]' +ORDER BY prod_name; +``` + +简单的正则表达式测试: + +```mysql +SELECT 'hello' REGEXP '[0-9]';#REGEXP检查返回0或1;此处返回0 +``` + diff --git a/docs/database/mysql-basic/3-function.md b/docs/database/mysql-basic/3-function.md new file mode 100644 index 0000000..80f3df4 --- /dev/null +++ b/docs/database/mysql-basic/3-function.md @@ -0,0 +1,42 @@ +# 函数 +## 文本处理 + +```mysql +SELECT vend_name, Upper(vend_name) AS vend_name_upcase +FROM vendors +ORDER BY vend_name; +``` + +Soundex()函数,匹配所有同音字符串。 + +```mysql +SELECT cust_name, cust_contact +FROM customers +WHERE Soundex(cust_contact) = Soundex('Y Lie'); +``` + +返回数据:`Tyson Y lee` + +## 日期处理函数 + +![](http://img.dabin-coder.cn/image/20220530235607.png) +查找2005年9月的所有订单: + +```mysql +SELECT cust_id, order_num +FROM orders +WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30'; +``` + +或者 + +```mysql +SELECT cust_id, order_num +FROM orders +WHERE Year(order_date) = 2005 AND Month(order_date) = 9; +``` + +## 数值处理函数 + +![](http://img.dabin-coder.cn/image/20220530233617.png) + diff --git a/docs/database/mysql-basic/4-sum.md b/docs/database/mysql-basic/4-sum.md new file mode 100644 index 0000000..c2f38ec --- /dev/null +++ b/docs/database/mysql-basic/4-sum.md @@ -0,0 +1,22 @@ +# 聚集函数 + +Sum:求和 +Avg:求平均数 +Max:求最大值 + Min:求最小值 + Count:求记录 + +```mysql +SELECT SUM(item_price*quanlity) AS total_price +FROM orderitems +WHERE order_num = 2005; +``` + +聚集不同值: + +```mysql +SELECT AVG(DISTINCT prod_price) AS avg_price #只考虑不同价格 +FROM products +WHERE vend_id = 1003; +``` + diff --git a/docs/database/mysql-basic/5-group.md b/docs/database/mysql-basic/5-group.md new file mode 100644 index 0000000..f839dea --- /dev/null +++ b/docs/database/mysql-basic/5-group.md @@ -0,0 +1,56 @@ +# 分组 + +单独地使用group by没意义,它只能显示出每组记录的第一条记录。 + +```mysql +SELECT * FROM orders +GROUP BY cust_id; +``` + +![](http://img.dabin-coder.cn/image/20220530233523.png) + +除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。 + +```mysql +SELECT vend_id, COUNT(*) AS num_prods #vend_id在GROUP BY子句给出 +FROM products +GROUP BY vend_id; +``` + +GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。 + +## 过滤分组 + +having 用来分组查询后指定一些条件来输出查询结果,having作用和where类似,但是having只能用在group by场合,并且必须位于group by之后order by之前。 + +```mysql +SELECT cust_id, COUNT(*) AS orders +FROM orders +GROUP BY cust_id +HAVING COUNT(*) >= 2; +``` + +## having和where区别 + +```mysql +SELECT cust_id FROM orders GROUP BY cust_id HAVING COUNT(cust_id) >= 2; +SELECT cust_id FROM orders GROUP BY cust_id WHERE COUNT(cust_id) >= 2; #Error Code : 1064 +``` + +第一个sql语句可以执行,但是第二个会报错。 + +- WHERE子句不起作用,因为过滤是基于分组聚集值而不是特定行值的。 + +- 二者作用的对象不同,where子句作用于表和视图,having作用于组。 + +- WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。 + +```mysql +SELECT vend_id, COUNT(*) AS num_prods +FROM products +WHERE prod_price >= 10 +GROUP BY vend_id +HAVING COUNT(*) >= 2; +``` + +WHERE子句过滤所有prod_price至少为10的行。然后按vend_id分组数据,HAVING子句过滤计数为2或2以上的分组。 diff --git a/docs/database/mysql-basic/6-join.md b/docs/database/mysql-basic/6-join.md new file mode 100644 index 0000000..359ab9f --- /dev/null +++ b/docs/database/mysql-basic/6-join.md @@ -0,0 +1,92 @@ +# 连接 +## 内连接 + +找出供应商生产的产品。 + +```mysql +SELECT vend_name, prod_name +FROM vendors INNER JOIN products +ON vendors.vend_id = products.vend_id; #连接条件使用on子句 +``` + +等价于: + +```mysql +SELECT vend_name, prod_name +FROM vendors, products +WHERE vendors.vend_id = products.vend_id; +``` + +没有给出连接条件的话,会得到两张表的笛卡尔积。 + +## 自连接 + +找出生产nike的供应商生产的所有物品。 + +```mysql +SELECT prod_id, prod_name +FROM products AS p1, products AS p2 +WHERE p1.vend_id = p2.vend_id + AND p2.prod_id = 'nike'; +``` + +## 自然连接 + +natural join是对两张表中字段名和数据类型都相同的字段进行**等值连接**,并返回符合条件的结果 。 + +```mysql +SELECT * FROM role NATURAL JOIN user_role; +``` + +返回结果: + +![](http://img.dabin-coder.cn/image/20220530235619.png) + +## 内连接 + +显示符合连接条件的记录。没有设置连接条件则返回笛卡尔积的结果。join 默认是 inner join。 + +```mysql +SELECT * FROM role INNNER JOIN user_role +``` + +返回结果: + +![](http://img.dabin-coder.cn/image/20220530235640.png) + +join…using(column)按指定的属性做等值连接。 +join…on tableA.column1 = tableB.column2 指定条件。 + +```mysql +SELECT * FROM role INNER JOIN user_role ON role.role_id = user_role.role_id +``` + +返回结果: + +![](http://img.dabin-coder.cn/image/20220530235654.png) + +## 外连接 + +左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。 +右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。 +在判定左表和右表时,要根据表名出现在Outer Join的左右位置关系。 + +查找所有客户及其订单,包括没有下过订单的客户。使用左外连接,保留左边表的所有记录。 + +```mysql +SELECT customer.cust_id, order.order_num +FROM customers LEFT OUTER JOIN orders +ON customers.cust_id = order.cust_id; +``` + +## 多表连接 + +```mysql +SELECT goal.player, eteam.teamname, game.stadium, game.mdate +FROM game JOIN goal +ON game.id = goal.matchid +JOIN eteam +ON eteam.id = goal.teamid +WHERE eteam.id = 'GRE' +``` + diff --git a/docs/database/mysql-basic/7-full-text-query.md b/docs/database/mysql-basic/7-full-text-query.md new file mode 100644 index 0000000..f122e0e --- /dev/null +++ b/docs/database/mysql-basic/7-full-text-query.md @@ -0,0 +1,39 @@ +# 全文搜索 +为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有的索引和重新索引。 + +启动全文搜索(仅在MyISAM数据库引擎中支持全文本搜索): + +```mysql +CREATE TABLE productnotes +( + note_id int NOT NULL AUTO_INCREMENT, + note_text text NULL, + PRIMARY KEY(note_id), + FULLTEXT(note_text) +) ENGINE=MyISAM; +``` + +在定义之后,MySQL自动维护该索引。在增加、更新或删除行时,索引随之自动更新。 + +不要在导入数据时使用FULLTEXT,。应该首先导入所有数据,然后再修改表,定义FULLTEXT,这样可以更快导入数据。 + +使用全文搜索: + +```mysql +SELECT note_text +FROM productnotes +WHERE Match(note_text) Against('shoe'); #Match指定搜索列,Against指定搜索词 +``` + +返回结果:`nike shoes is good`,搜索不区分大小写。 + +全文搜索会对返回结果进行排序,具有高等级的行先返回: + +```mysql +SELECT note_text, + Match(note_text) Against('shoes') AS rank #等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。 +FROM productnotes; +``` + +全文搜索数据是有索引的,速度快。 + diff --git a/docs/database/mysql-basic/8-table-operate.md b/docs/database/mysql-basic/8-table-operate.md new file mode 100644 index 0000000..e3f6fd9 --- /dev/null +++ b/docs/database/mysql-basic/8-table-operate.md @@ -0,0 +1,105 @@ +# 表操作 + +## 创建表 + +```mysql +CREATE TABLE productnotes +( + note_id int NOT NULL AUTO_INCREMENT, + note_text text NULL, + quanlity int NOT NULL DEFAULT 1, # 默认值,只支持常量 + PRIMARY KEY(note_id), + FULLTEXT(note_text) +) ENGINE=MyISAM; +``` + +主键中只能使用NOT NULL值的列。 + +## 更新表 + +数据库表的更改不能撤销,应先做好备份。 + +添加列: + +```mysql +ALTER TABLE vendors +ADD vend_phone CHAR(20); +``` + +删除列: + +```mysql +ALTER TABLE vendors +DROP COLUMN vend_phone; +``` + +更改列属性: + +```mysql +ALTER TABLE vendors +MODIFY vend_phone CHAR(16); +``` + +复杂的表结构更改一般需要手动删除过程: + +- 用新的列布局创建一个新表; + +- 使用INSERT SELECT语句,从旧表复制数据到新表; + +- 检验包含所需数据的新表; +- 重命名旧表(如果确定,可以删除它); + +- 用旧表原来的名字重命名新表; + +- 重新创建触发器、存储过程、索引和外键。 + +## 约束 + +添加主键约束: + +```mysql +ALTER TABLE vendors +ADD CONSTRAINT pk_vendors PRIMARY KEY(vend_id); +``` + +删除主键约束: + +```mysql +ALTER TABLE vendors +DROP PRIMARY KEY; +``` + +添加外键约束: + +```mysql +ALTER TABLE products +ADD FOREIGN KEY(vendor_id) REFERENCES vendors(vendor_id); +``` + +删除外键约束: + +```mysql +ALTER TABLE products DROP FOREIGN KEY vendor_id; +``` + +## 删除表 + +`DROP TABLE cumstomers` + +## truncate、delete与drop区别 + +**相同点:** + +1. truncate和不带where子句的delete、以及drop都会删除表内的数据。 + +2. drop、truncate都是DDL语句(数据定义语言),执行后会自动提交。 + +**不同点:** + +1. truncate 和 delete 只删除数据不删除表的结构;drop 语句将删除表的结构被依赖的约束、触发器、索引; + +2. 速度,一般来说: drop> truncate > delete。 + +## 重命名表 + +`RENAME TABLE cusmtomers TO cust` diff --git a/docs/database/mysql-basic/9-column-operate.md b/docs/database/mysql-basic/9-column-operate.md new file mode 100644 index 0000000..536c1ee --- /dev/null +++ b/docs/database/mysql-basic/9-column-operate.md @@ -0,0 +1,48 @@ +# 列操作 + +## 插入数据 + +MySQL用单条INSERT语句处理多个插入比使用多条INSERT语句快。 + +```mysql +INSERT INTO customers(cust_name, cust_city) + VALUES('Tyson', 'GD'), + ('sophia','GZ'); +``` + +INSERT操作可能很耗时(特别是有很多索引需要更新时),而且它可能降低等待处理的SELECT语句的性能。降低INSERT语句的优先级:`INSERT LOW_PRIORITY INTO` + +## 更新数据 + +如果用UPDATE语句更新多行,并且在更新这些行中的一行或多行时出一个现错误,则整个UPDATE操作被取消。为了在发生错误时也继续进行更新,可使用IGNORE关键字:`UPDATE IGNORE customers...` + +```mysql +UPDATE customers +SET cust_city = NULL +WHERE cust_id = 1005; +``` + +返回值是受影响的记录数。 + +## 删除数据 + +如果想从表中删除所有行,不要使用DELETE。可使用TRUNCATE TABLE语句,它完成相同的工作,但速度更快(TRUNCATE实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)。 + +```mysql +DELETE FROM customers +WHERE cust_id = 1006; +``` + +如果执行DELETE语句而不带WHERE子句,表的所有数据都将被删除。MySQL没有撤销操作,应该非常小心地使用UPDATE和DELETE。 + +delete使用别名的时候,要在delete和from间加上删除表的别名。 + +```mysql +DELETE a #加上删除表的别名 +FROM table1 a +WHERE a.status = 0 +AND EXISTS + (SELECT b.id FROM table2 b + WHERE b.id = a.id); +``` + diff --git a/docs/database/mysql-basic/README.md b/docs/database/mysql-basic/README.md new file mode 100644 index 0000000..bad4977 --- /dev/null +++ b/docs/database/mysql-basic/README.md @@ -0,0 +1,31 @@ +--- +title: MySQL基础 +icon: linux +date: 2022-08-06 +category: MySQL +star: true +--- + +**本专栏是大彬学习MySQL基础知识的学习笔记,如有错误,可以在评论区指出**~ + +![](http://img.dabin-coder.cn/image/MySQL知识点总结.jpg) + +## MySQL基础总结 + +- [数据类型](./1-data-type.md) +- [基本命令](./2-basic-command.md) +- [函数](./3-function.md) +- [聚集函数](./4-sum.md) +- [分组](./5-group.md) +- [连接](./6-join.md) +- [全文搜索](./7-full-text-query.md) +- [表操作](./8-table-operate.md) +- [列操作](./9-column-operate.md) +- [视图](./10-view.md) +- [存储过程](./11-procedure.md) +- [游标](./12-cursor.md) +- [触发器](./13-trigger.md) +- [事务处理](./14-transaction.md) +- [权限](./15-permission.md) +- [性能优化](./16-performace-optimization.md) +- [索引](./17-index.md) diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" b/docs/database/mysql-execution-plan.md similarity index 92% rename from "\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" rename to docs/database/mysql-execution-plan.md index eaffa77..ef0a178 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\346\211\247\350\241\214\350\256\241\345\210\222.md" +++ b/docs/database/mysql-execution-plan.md @@ -1,38 +1,6 @@ - - - - -- [id](#id) -- [select_type](#select_type) -- [table](#table) -- [partitions](#partitions) -- [type](#type) - - [system](#system) - - [const](#const) - - [eq_ref](#eq_ref) - - [ref](#ref) - - [ref_or_null](#ref_or_null) - - [index_merge](#index_merge) - - [range](#range) - - [index](#index) - - [all](#all) -- [possible_keys](#possible_keys) -- [key](#key) -- [ref](#ref-1) -- [rows](#rows) -- [filtered](#filtered) -- [extra](#extra) - - [using where](#using-where) - - [using index](#using-index) - - [Using where&Using index](#using-whereusing-index) - - [null](#null) - - [using index condition](#using-index-condition) - - [using temporary](#using-temporary) - - [filesort](#filesort) - - [using join buffer](#using-join-buffer) -- [参考资料](#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99) - - +--- +sidebar: heading +--- 使用 explain 输出 SELECT 语句执行的详细信息,包括以下信息: diff --git "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" b/docs/database/mysql.md similarity index 77% rename from "\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" rename to docs/database/mysql.md index 123d7cc..b22f3d5 100644 --- "a/\346\225\260\346\215\256\345\272\223/MySQL\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ b/docs/database/mysql.md @@ -1,3 +1,9 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/MySQL知识点总结.jpg) + ## 事务的四大特性? **事务特性ACID**:**原子性**(`Atomicity`)、**一致性**(`Consistency`)、**隔离性**(`Isolation`)、**持久性**(`Durability`)。 @@ -126,7 +132,7 @@ utf8 就像是阉割版的utf8mb4,只支持部分字符。比如`emoji`表情 而mysql支持的字符集里,第三列,**collation**,它是指**字符集的比较规则**。 -比如,**"debug"和"Debug"**是同一个单词,但它们大小写不同,该不该判为同一个单词呢。 +比如,"debug"和"Debug"是同一个单词,但它们大小写不同,该不该判为同一个单词呢。 这时候就需要用到collation了。 @@ -136,15 +142,11 @@ utf8 就像是阉割版的utf8mb4,只支持部分字符。比如`emoji`表情 如果`collation = utf8mb4_general_ci`,是指使用utf8mb4字符集的前提下,**挨个字符进行比较**(`general`),并且不区分大小写(`_ci,case insensitice`)。 -这种情况下,**"debug"和"Debug"是同一个单词**。 - -如果改成`collation=utf8mb4_bin`,就是指**挨个比较二进制位大小**。 - -于是**"debug"和"Debug"就不是同一个单词。** +这种情况下,"debug"和"Debug"是同一个单词。 如果改成`collation=utf8mb4_bin`,就是指**挨个比较二进制位大小**。 -于是**"debug"和"Debug"就不是同一个单词。** +于是"debug"和"Debug"就不是同一个单词。 **那utf8mb4对比utf8有什么劣势吗?** @@ -311,9 +313,13 @@ explain select user_id from user_like where blog_id = 1; ### 索引的设计原则? +- 对于经常作为查询条件的字段,应该建立索引,以提高查询速度 +- 为经常需要排序、分组和联合操作的字段建立索引 - 索引列的**区分度越高**,索引的效果越好。比如使用性别这种区分度很低的列作为索引,效果就会很差。 +- 避免给"大字段"建立索引。尽量使用数据量小的字段作为索引。因为`MySQL`在维护索引的时候是会将字段值一起维护的,那这样必然会导致索引占用更多的空间,另外在排序的时候需要花费更多的时间去对比。 - 尽量使用**短索引**,对于较长的字符串进行索引时应该指定一个较短的前缀长度,因为较小的索引涉及到的磁盘I/O较少,查询速度更快。 - 索引不是越多越好,每个索引都需要额外的物理空间,维护也需要花费时间。 +- 频繁增删改的字段不要建立索引。假设某个字段频繁修改,那就意味着需要频繁的重建索引,这必然影响MySQL的性能 - 利用**最左前缀原则**。 ### 索引什么时候会失效? @@ -391,15 +397,46 @@ ARCHIVE存储引擎非常适合存储大量独立的、作为历史记录的数 ## MyISAM和InnoDB的区别? -1. **是否支持行级锁** : `MyISAM` 只有表级锁,而`InnoDB` 支持行级锁和表级锁,默认为行级锁。 +1. **存储结构的区别**。每个MyISAM在磁盘上存储成三个文件。文件的名字以表的名字开始,扩展名指出文件类型。 .frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。InnoDB所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。 +2. **存储空间的区别**。MyISAM支持支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。当表在创建之后并导入数据之后,不会再进行修改操作,可以使用压缩表,极大的减少磁盘的空间占用。InnoDB需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。 +3. **可移植性、备份及恢复**。MyISAM数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。对于InnoDB,可行的方案是拷贝数据文件、备份 binlog,或者用mysqldump,在数据量达到几十G的时候就相对麻烦了。 +4. **是否支持行级锁**。MyISAM 只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。而InnoDB 支持行级锁和表级锁,默认为行级锁。行锁大幅度提高了多用户并发操作的性能。 +5. **是否支持事务和崩溃后的安全恢复**。 MyISAM 不提供事务支持。而InnoDB 提供事务支持,具有事务、回滚和崩溃修复能力。 +6. **是否支持外键**。MyISAM不支持,而InnoDB支持。 +7. **是否支持MVCC**。MyISAM不支持,InnoDB支持。应对高并发事务,MVCC比单纯的加锁更高效。 +8. **是否支持聚集索引**。MyISAM不支持聚集索引,InnoDB支持聚集索引。 +9. **全文索引**。MyISAM支持 FULLTEXT类型的全文索引。InnoDB不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。 +10. **表主键**。MyISAM允许没有任何索引和主键的表存在,索引都是保存行的地址。对于InnoDB,如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见)。 +11. **表的行数**。MyISAM保存有表的总行数,如果`select count(*) from table`;会直接取出该值。InnoDB没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了where条件后,MyISAM和InnoDB处理的方式都一样。 + +## MySQL有哪些锁? + +**按锁粒度分类**,有行级锁、表级锁和页级锁。 + +1. 行级锁是mysql中锁定粒度最细的一种锁。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁的类型主要有三类: + - Record Lock,记录锁,也就是仅仅把一条记录锁上; + - Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身; + - Next-Key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。 +2. 表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。 +3. 页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。 + +**按锁级别分类**,有共享锁、排他锁和意向锁。 + +1. 共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。 +2. 排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。 +3. 意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB 中的两个表锁: -2. **是否支持事务和崩溃后的安全恢复**: `MyISAM` 不提供事务支持。而`InnoDB `提供事务支持,具有事务、回滚和崩溃修复能力。 +意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁; -3. **是否支持外键:** `MyISAM`不支持,而`InnoDB`支持。 +意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。 -4. **是否支持MVCC** :`MyISAM`不支持,`InnoDB`支持。应对高并发事务,MVCC比单纯的加锁更高效。 +意向锁是 InnoDB 自动加的,不需要用户干预。 -5. `MyISAM`不支持聚集索引,`InnoDB`支持聚集索引。 +对于INSERT、UPDATE和DELETE,InnoDB 会自动给涉及的数据加排他锁;对于一般的SELECT语句,InnoDB 不会加任何锁,事务可以通过以下语句显式加共享锁或排他锁。 + +共享锁:`SELECT … LOCK IN SHARE MODE;` + +排他锁:`SELECT … FOR UPDATE;` ## MVCC 实现原理? @@ -412,8 +449,8 @@ MVCC(`Multiversion concurrency control`) 就是同一份数据保留多版本的 MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实现。 - `DB_TRX_ID`:当前事务id,通过事务id的大小判断事务的时间顺序。 -- `DB_ROLL_PRT`:回滚指针,指向当前行记录的上一个版本,通过这个指针将数据的多个版本连接在一起构成`undo log`版本链。 -- `DB_ROLL_ID`:主键,如果数据表没有主键,InnoDB会自动生成主键。 +- `DB_ROLL_PTR`:回滚指针,指向当前行记录的上一个版本,通过这个指针将数据的多个版本连接在一起构成`undo log`版本链。 +- `DB_ROW_ID`:主键,如果数据表没有主键,InnoDB会自动生成主键。 每条表记录大概是这样的: @@ -923,6 +960,162 @@ B+树中**非叶子节点存的是key + 指针**;**叶子节点存的是数据 * 读写分离。经典的数据库拆分方案,主库负责写,从库负责读 * 通过分库分表的方式进行优化,主要有垂直拆分和水平拆分 +## 说说count(1)、count(*)和count(字段名)的区别 + +嗯,先说说count(1) and count(字段名)的区别。 + +两者的主要区别是 + +1. count(1) 会统计表中的所有的记录数,包含字段为null 的记录。 +2. count(字段名) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。 + +接下来看看三者之间的区别。 + +执行效果上: + +- count(*)包括了所有的列,相当于行数,在统计结果的时候,**不会忽略列值为NULL** +- count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,**不会忽略列值为NULL** +- count(字段名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,**即某个字段值为NULL时,不统计**。 + +执行效率上: + +- 列名为主键,count(字段名)会比count(1)快 +- 列名不为主键,count(1)会比count(列名)快 +- 如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*) +- 如果有主键,则 select count(主键)的执行效率是最优的 +- 如果表只有一个字段,则 select count(*)最优。 + +## MySQL中DATETIME 和 TIMESTAMP有什么区别? + +嗯,`TIMESTAMP`和`DATETIME`都可以用来存储时间,它们主要有以下区别: + +1.表示范围 + +- DATETIME:1000-01-01 00:00:00.000000 到 9999-12-31 23:59:59.999999 +- TIMESTAMP:'1970-01-01 00:00:01.000000' UTC 到 '2038-01-09 03:14:07.999999' UTC + +`TIMESTAMP`支持的时间范围比`DATATIME`要小,容易出现超出的情况。 + +2.空间占用 + +- TIMESTAMP :占 4 个字节 +- DATETIME:在 MySQL 5.6.4 之前,占 8 个字节 ,之后版本,占 5 个字节 + +3.存入时间是否会自动转换 + +`TIMESTAMP`类型在默认情况下,insert、update 数据时,`TIMESTAMP`列会自动以当前时间(`CURRENT_TIMESTAMP`)填充/更新。`DATETIME`则不会做任何转换,也不会检测时区,你给什么数据,它存什么数据。 + +4.`TIMESTAMP`比较受时区timezone的影响以及MYSQL版本和服务器的SQL MODE的影响。因为`TIMESTAMP`存的是时间戳,在不同的时区得出的时间不一致。 + +5.如果存进NULL,两者实际存储的值不同。 + +- TIMESTAMP:会自动存储当前时间 now() 。 +- DATETIME:不会自动存储当前时间,会直接存入 NULL 值。 + +## 说说为什么不建议用外键? + +外键是一种约束,这个约束的存在,会保证表间数据的关系始终完整。外键的存在,并非全然没有优点。 + +外键可以保证数据的完整性和一致性,级联操作方便。而且使用外键可以将数据完整性判断托付给了数据库完成,减少了程序的代码量。 + +虽然外键能够保证数据的完整性,但是会给系统带来很多缺陷。 + +1、并发问题。在使用外键的情况下,每次修改数据都需要去另外一个表检查数据,需要获取额外的锁。若是在高并发大流量事务场景,使用外键更容易造成死锁。 + +2、扩展性问题。比如从`MySQL`迁移到`Oracle`,外键依赖于数据库本身的特性,做迁移可能不方便。 + +3、不利于分库分表。在水平拆分和分库的情况下,外键是无法生效的。将数据间关系的维护,放入应用程序中,为将来的分库分表省去很多的麻烦。 + +## 使用自增主键有什么好处? + +自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑,在查询的时候,效率也就更高。 + +## 自增主键保存在什么地方? + +不同的引擎对于自增值的保存策略不同: + +- MyISAM引擎的自增值保存在数据文件中。 +- 在MySQL8.0以前,InnoDB引擎的自增值是存在内存中。MySQL重启之后内存中的这个值就丢失了,每次重启后第一次打开表的时候,会找自增值的最大值max(id),然后将最大值加1作为这个表的自增值;MySQL8.0版本会将自增值的变更记录在redo log中,重启时依靠redo log恢复。 + +## 自增主键一定是连续的吗? + +不一定,有几种情况会导致自增主键不连续。 + +1、唯一键冲突导致自增主键不连续。当我们向一个自增主键的InnoDB表中插入数据的时候,如果违反表中定义的唯一索引的唯一约束,会导致插入数据失败。此时表的自增主键的键值是会向后加1滚动的。下次再次插入数据的时候,就不能再使用上次因插入数据失败而滚动生成的键值了,必须使用新滚动生成的键值。 + +2、事务回滚导致自增主键不连续。当我们向一个自增主键的InnoDB表中插入数据的时候,如果显式开启了事务,然后因为某种原因最后回滚了事务,此时表的自增值也会发生滚动,而接下里新插入的数据,也将不能使用滚动过的自增值,而是需要重新申请一个新的自增值。 + +3、批量插入导致自增值不连续。MySQL有一个批量申请自增id的策略: + +- 语句执行过程中,第一次申请自增id,分配1个自增id +- 1个用完以后,第二次申请,会分配2个自增id +- 2个用完以后,第三次申请,会分配4个自增id +- 依次类推,每次申请都是上一次的两倍(最后一次申请不一定全部使用) + +如果下一个事务再次插入数据的时候,则会基于上一个事务申请后的自增值基础上再申请。此时就出现自增值不连续的情况出现。 + +4、自增步长不是1,也会导致自增主键不连续。 + +## InnoDB的自增值为什么不能回收利用? + +主要为了提升插入数据的效率和并行度。 + +假设有两个并行执行的事务,在申请自增值的时候,为了避免两个事务申请到相同的自增 id,肯定要加锁,然后顺序申请。 + +假设事务 A 申请到了 id=2, 事务 B 申请到 id=3,那么这时候表 t 的自增值是 4,之后继续执行。 + +事务 B 正确提交了,但事务 A 出现了唯一键冲突。 + +如果允许事务 A 把自增 id 回退,也就是把表 t 的当前自增值改回 2,那么就会出现这样的情况:表里面已经有 id=3 的行,而当前的自增 id 值是 2。 + +接下来,继续执行的其他事务就会申请到 id=2,然后再申请到 id=3。这时,就会出现插入语句报错“主键冲突”。 + +而为了解决这个主键冲突,有两种方法: + +- 每次申请 id 之前,先判断表里面是否已经存在这个 id。如果存在,就跳过这个 id。但是,这个方法的成本很高。因为,本来申请 id 是一个很快的操作,现在还要再去主键索引树上判断 id 是否存在。 +- 把自增 id 的锁范围扩大,必须等到一个事务执行完成并提交,下一个事务才能再申请自增 id。这个方法的问题,就是锁的粒度太大,系统并发能力大大下降。 + +可见,这两个方法都会导致性能问题。 + +因此,InnoDB 放弃了“允许自增 id 回退”这个设计,语句执行失败也不回退自增 id。 + +## MySQL数据如何同步到Redis缓存? + +> 参考:https://cloud.tencent.com/developer/article/1805755 + +有两种方案: + +1、通过MySQL自动同步刷新Redis,**MySQL触发器+UDF函数**实现。 + +过程大致如下: + +1. 在MySQL中对要操作的数据设置触发器Trigger,监听操作 +2. 客户端向MySQL中写入数据时,触发器会被触发,触发之后调用MySQL的UDF函数 +3. UDF函数可以把数据写入到Redis中,从而达到同步的效果 + +2、**解析MySQL的binlog**,实现将数据库中的数据同步到Redis。可以通过canal实现。canal是阿里巴巴旗下的一款开源项目,基于数据库增量日志解析,提供增量数据订阅&消费。 + +canal的原理如下: + +1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议 +2. mysql master收到dump请求,开始推送binary log给canal +3. canal解析binary log对象(原始为byte流),将数据同步写入Redis。 + + + +## 为什么阿里Java手册禁止使用存储过程? + +先看看什么是存储过程。 + +存储过程是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。 + +存储过程主要有以下几个缺点。 + +1. **存储过程难以调试**。存储过程的开发一直缺少有效的 IDE 环境。SQL 本身经常很长,调试式要把句子拆开分别独立执行,非常麻烦。 +2. **移植性差**。存储过程的移植困难,一般业务系统总会不可避免地用到数据库独有的特性和语法,更换数据库时这部分代码就需要重写,成本较高。 +3. **管理困难**。存储过程的目录是扁平的,而不是文件系统那样的树形结构,脚本少的时候还好办,一旦多起来,目录就会陷入混乱。 +4. 存储过程是**只优化一次**,有的时候随着数据量的增加或者数据结构的变化,原来存储过程选择的执行计划也许并不是最优的了,所以这个时候需要手动干预或者重新编译了。 + ![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git a/docs/distributed/1-global-unique-id.md b/docs/distributed/1-global-unique-id.md new file mode 100644 index 0000000..4e95fe3 --- /dev/null +++ b/docs/distributed/1-global-unique-id.md @@ -0,0 +1,489 @@ +--- +sidebar: heading +--- + +传统的单体架构的时候,我们基本是单库然后业务单表的结构。每个业务表的ID一般我们都是从1增,通过`AUTO_INCREMENT=1`设置自增起始值,但是在分布式服务架构模式下分库分表的设计,使得多个库或多个表存储相同的业务数据。这种情况根据数据库的自增ID就会产生相同ID的情况,不能保证主键的唯一性。 + +![](http://img.dabin-coder.cn/image/20220508235751.png) + +如上图,如果第一个订单存储在 DB1 上则订单 ID 为1,当一个新订单又入库了存储在 DB2 上订单 ID 也为1。我们系统的架构虽然是分布式的,但是在用户层应是无感知的,重复的订单主键显而易见是不被允许的。那么针对分布式系统如何做到主键唯一性呢? + +## UUID + +UUID (Universally Unique Identifier),通用唯一识别码的缩写。UUID是由一组32位数的16进制数字所构成,所以UUID理论上的总数为 1632=2128,约等于 3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。 + +生成的UUID是由 `8-4-4-4-12`格式的数据组成,其中32个字符和4个连字符' - ',一般我们使用的时候会将连字符删除 `uuid.toString().replaceAll("-","")`。 + +目前UUID的产生方式有5种版本,每个版本的算法不同,应用范围也不同。 + +- **基于时间的UUID - 版本1**: + 这个一般是通过当前时间,随机数,和本地Mac地址来计算出来,可以通过 `org.apache.logging.log4j.core.util`包中的 `UuidUtil.getTimeBasedUuid()`来使用或者其他包中工具。由于使用了MAC地址,因此能够确保唯一性,但是同时也暴露了MAC地址,私密性不够好。 +- **DCE安全的UUID - 版本2** + DCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少用到。 +- **基于名字的UUID(MD5)- 版本3** + 基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。 +- **随机UUID - 版本4** + 根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但是重复的可能性可以忽略不计,因此该版本也是被经常使用的版本。JDK中使用的就是这个版本。 +- **基于名字的UUID(SHA1) - 版本5** + 和基于名字的UUID算法类似,只是散列值计算使用SHA1(Secure Hash Algorithm 1)算法。 + +我们 Java中 JDK自带的 UUID产生方式就是版本4根据随机数生成的 UUID 和版本3基于名字的 UUID,有兴趣的可以去看看它的源码。 + +```java +public static void main(String[] args) { + + //获取一个版本4根据随机字节数组的UUID。 + UUID uuid = UUID.randomUUID(); + System.out.println(uuid.toString().replaceAll("-","")); + + //获取一个版本3(基于名称)根据指定的字节数组的UUID。 + byte[] nbyte = {10, 20, 30}; + UUID uuidFromBytes = UUID.nameUUIDFromBytes(nbyte); + System.out.println(uuidFromBytes.toString().replaceAll("-","")); +} +``` + +得到的UUID结果, + +```undefined +59f51e7ea5ca453bbfaf2c1579f09f1d +7f49b84d0bbc38e9a493718013baace6 +``` + +虽然 UUID 生成方便,本地生成没有网络消耗,但是使用起来也有一些缺点, + +- 不易于存储:UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。 +- 信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,暴露使用者的位置。 +- 对MySQL索引不利:如果作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能,可以查阅 Mysql 索引原理 B+树的知识。 + +## 数据库生成 + +是不是一定要基于外界的条件才能满足分布式唯一ID的需求呢,我们能不能在我们分布式数据库的基础上获取我们需要的ID? + +由于分布式数据库的起始自增值一样所以才会有冲突的情况发生,那么我们将分布式系统中数据库的同一个业务表的自增ID设计成不一样的起始值,然后设置固定的步长,步长的值即为分库的数量或分表的数量。 + +以MySQL举例,利用给字段设置`auto_increment_increment`和`auto_increment_offset`来保证ID自增。 + +- auto_increment_offset:表示自增长字段从那个数开始,他的取值范围是1 .. 65535。 +- auto_increment_increment:表示自增长字段每次递增的量,其默认值是1,取值范围是1 .. 65535。 + +假设有三台机器,则DB1中order表的起始ID值为1,DB2中order表的起始值为2,DB3中order表的起始值为3,它们自增的步长都为3,则它们的ID生成范围如下图所示: + +![](http://img.dabin-coder.cn/image/20220509000004.png) + +通过这种方式明显的优势就是依赖于数据库自身不需要其他资源,并且ID号单调自增,可以实现一些对ID有特殊要求的业务。 + +但是缺点也很明显,首先它强依赖DB,当DB异常时整个系统不可用。虽然配置主从复制可以尽可能的增加可用性,但是数据一致性在特殊情况下难以保证。主从切换时的不一致可能会导致重复发号。还有就是ID发号性能瓶颈限制在单台MySQL的读写性能。 + +## 使用redis实现 + +Redis实现分布式唯一ID主要是通过提供像 *INCR* 和 *INCRBY* 这样的自增原子命令,由于Redis自身的单线程的特点所以能保证生成的 ID 肯定是唯一有序的。 + +但是单机存在性能瓶颈,无法满足高并发的业务需求,所以可以采用集群的方式来实现。集群的方式又会涉及到和数据库集群同样的问题,所以也需要设置分段和步长来实现。 + +为了避免长期自增后数字过大可以通过与当前时间戳组合起来使用,另外为了保证并发和业务多线程的问题可以采用 Redis + Lua的方式进行编码,保证安全。 + +Redis 实现分布式全局唯一ID,它的性能比较高,生成的数据是有序的,对排序业务有利,但是同样它依赖于redis,需要系统引进redis组件,增加了系统的配置复杂性。 + +当然现在Redis的使用性很普遍,所以如果其他业务已经引进了Redis集群,则可以资源利用考虑使用Redis来实现。 + +## 雪花算法-Snowflake + +Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。 + +- 第1位占用1bit,其值始终是0,可看做是符号位不使用。 +- 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是(1L<<41)/(1000L*3600*24*365)=69 年的时间。 +- 中间的10-bit位可表示机器数,即2^10 = 1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将 10-bit 分 5-bit 给 IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。 +- 最后12-bit位是自增序列,可表示2^12 = 4096个数。 + +这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。 + +![](http://img.dabin-coder.cn/image/20220508235958.png) + +Snowflake 的[Twitter官方原版](https://github.com/twitter/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala)是用Scala写的,对Scala语言有研究的同学可以去阅读下,以下是 Java 版本的写法。 + +```java +package com.jajian.demo.distribute; + +/** + * Twitter_Snowflake
+ * SnowFlake的结构如下(每部分用-分开):
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) + * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
+ * 加起来刚好64位,为一个Long型。
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 + */ +public class SnowflakeDistributeId { + + + // ==============================Fields=========================================== + /** + * 开始时间截 (2015-01-01) + */ + private final long twepoch = 1420041600000L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long datacenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long datacenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private long workerId; + + /** + * 数据中心ID(0~31) + */ + private long datacenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + //==============================Constructors===================================== + + /** + * 构造函数 + * + * @param workerId 工作ID (0~31) + * @param datacenterId 数据中心ID (0~31) + */ + public SnowflakeDistributeId(long workerId, long datacenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + // ==============================Methods========================================== + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + public synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) // + | (datacenterId << datacenterIdShift) // + | (workerId << workerIdShift) // + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } +} +``` + +测试的代码如下 + +```java +public static void main(String[] args) { + SnowflakeDistributeId idWorker = new SnowflakeDistributeId(0, 0); + for (int i = 0; i < 1000; i++) { + long id = idWorker.nextId(); +// System.out.println(Long.toBinaryString(id)); + System.out.println(id); + } +} +``` + +雪花算法提供了一个很好的设计思想,雪花算法生成的ID是趋势递增,不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的,而且可以根据自身业务特性分配bit位,非常灵活。 + +但是雪花算法强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。如果恰巧回退前生成过一些ID,而时间回退后,生成的ID就有可能重复。官方对于此并没有给出解决方案,而是简单的抛错处理,这样会造成在时间被追回之前的这段时间服务不可用。 + +很多其他类雪花算法也是在此思想上的设计然后改进规避它的缺陷,后面介绍的百度 UidGenerator 和 美团分布式ID生成系统 Leaf 中snowflake模式都是在 snowflake 的基础上演进出来的。 + +## 百度-UidGenerator + +[百度的 UidGenerator](https://github.com/baidu/uid-generator) 是百度开源基于Java语言实现的唯一ID生成器,是在雪花算法 snowflake 的基础上做了一些改进。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略,适用于docker等虚拟化环境下实例自动重启、漂移等场景。 + +在实现上,UidGenerator 提供了两种生成唯一ID方式,分别是 DefaultUidGenerator 和 CachedUidGenerator,官方建议如果有性能考虑的话使用 CachedUidGenerator 方式实现。 + +UidGenerator 依然是以划分命名空间的方式将 64-bit位分割成多个部分,只不过它的默认划分方式有别于雪花算法 snowflake。它默认是由 1-28-22-13 的格式进行划分。可根据你的业务的情况和特点,自己调整各个字段占用的位数。 + +- 第1位仍然占用1bit,其值始终是0。 +- 第2位开始的28位是时间戳,28-bit位可表示2^28个数,**这里不再是以毫秒而是以秒为单位**,每个数代表秒则可用(1L<<28)/ (3600*24*365) ≈ 8.51 年的时间。 +- 中间的 workId (数据中心+工作机器,可以其他组成方式)则由 22-bit位组成,可表示 2^22 = 4194304个工作ID。 +- 最后由13-bit位构成自增序列,可表示2^13 = 8192个数。 + +![](http://img.dabin-coder.cn/image/20220509000004.png) + +其中 workId (机器 id),最多可支持约420w次机器启动。内置实现为在启动时由数据库分配(表名为 WORKER_NODE),默认分配策略为用后即弃,后续可提供复用策略。 + +```sql +DROP TABLE IF EXISTS WORKER_NODE; +CREATE TABLE WORKER_NODE +( +ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id', +HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name', +PORT VARCHAR(64) NOT NULL COMMENT 'port', +TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER', +LAUNCH_DATE DATE NOT NULL COMMENT 'launch date', +MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time', +CREATED TIMESTAMP NOT NULL COMMENT 'created time', +PRIMARY KEY(ID) +) + COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB; +``` + +### DefaultUidGenerator 实现 + +DefaultUidGenerator 就是正常的根据时间戳和机器位还有序列号的生成方式,和雪花算法很相似,对于时钟回拨也只是抛异常处理。仅有一些不同,如以秒为为单位而不再是毫秒和支持Docker等虚拟化环境。 + +```java +protected synchronized long nextId() { + long currentSecond = getCurrentSecond(); + + // Clock moved backwards, refuse to generate uid + if (currentSecond < lastSecond) { + long refusedSeconds = lastSecond - currentSecond; + throw new UidGenerateException("Clock moved backwards. Refusing for %d seconds", refusedSeconds); + } + + // At the same second, increase sequence + if (currentSecond == lastSecond) { + sequence = (sequence + 1) & bitsAllocator.getMaxSequence(); + // Exceed the max sequence, we wait the next second to generate uid + if (sequence == 0) { + currentSecond = getNextSecond(lastSecond); + } + + // At the different second, sequence restart from zero + } else { + sequence = 0L; + } + + lastSecond = currentSecond; + + // Allocate bits for UID + return bitsAllocator.allocate(currentSecond - epochSeconds, workerId, sequence); +} +``` + +如果你要使用 DefaultUidGenerator 的实现方式的话,以上划分的占用位数可通过 spring 进行参数配置。 + +```xml + + + + + + + + + +``` + +### CachedUidGenerator 实现 + +而官方建议的性能较高的 CachedUidGenerator 生成方式,是使用 RingBuffer 缓存生成的id。数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值(2^13 = 8192)。可通过 boostPower 配置进行扩容,以提高 RingBuffer 读写吞吐量。 + +Tail指针、Cursor指针用于环形数组上读写slot: + +- Tail指针 + 表示Producer生产的最大序号(此序号从0开始,持续递增)。Tail不能超过Cursor,即生产者不能覆盖未消费的slot。当Tail已赶上curosr,此时可通过rejectedPutBufferHandler指定PutRejectPolicy +- Cursor指针 + 表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过rejectedTakeBufferHandler指定TakeRejectPolicy + +![](http://img.dabin-coder.cn/image/20220706225625.png) + +CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)。 + +由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。 + +![](http://img.dabin-coder.cn/image/20220706225530.png) + +RingBuffer填充时机 + +- 初始化预填充 + RingBuffer初始化时,预先填充满整个RingBuffer。 +- 即时填充 + Take消费时,即时检查剩余可用slot量(tail - cursor),如小于设定阈值,则补全空闲slots。阈值可通过paddingFactor来进行配置,请参考Quick Start中CachedUidGenerator配置。 +- 周期填充 + 通过Schedule线程,定时补全空闲slots。可通过scheduleInterval配置,以应用定时填充功能,并指定Schedule时间间隔。 + +## 美团Leaf + +Leaf是美团基础研发平台推出的一个分布式ID生成服务,名字取自德国哲学家、数学家莱布尼茨的著名的一句话:“There are no two identical leaves in the world”,世间不可能存在两片相同的叶子。 + +Leaf 也提供了两种ID生成的方式,分别是 Leaf-segment 数据库方案和 Leaf-snowflake 方案。 + +### Leaf-segment 数据库方案 + +Leaf-segment 数据库方案,是在上文描述的在使用数据库的方案上,做了如下改变: + +- 原方案每次获取ID都得读写一次数据库,造成数据库压力大。改为利用proxy server批量获取,每次获取一个segment(step决定大小)号段的值。用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力。 +- 各个业务不同的发号需求用 `biz_tag`字段来区分,每个biz-tag的ID获取相互隔离,互不影响。如果以后有性能需求需要对数据库扩容,不需要上述描述的复杂的扩容操作,只需要对biz_tag分库分表就行。 + +数据库表设计如下: + +```sql +CREATE TABLE `leaf_alloc` ( + `biz_tag` varchar(128) NOT NULL DEFAULT '' COMMENT '业务key', + `max_id` bigint(20) NOT NULL DEFAULT '1' COMMENT '当前已经分配了的最大id', + `step` int(11) NOT NULL COMMENT '初始步长,也是动态调整的最小步长', + `description` varchar(256) DEFAULT NULL COMMENT '业务key的描述', + `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`biz_tag`) +) ENGINE=InnoDB; +``` + +原来获取ID每次都需要写数据库,现在只需要把step设置得足够大,比如1000。那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。读写数据库的频率从1减小到了1/step,大致架构如下图所示: + +![](http://img.dabin-coder.cn/image/20220509000142.png) + +同时Leaf-segment 为了解决 TP999(满足千分之九百九十九的网络请求所需要的最低耗时)数据波动大,当号段使用完之后还是会hang在更新数据库的I/O上,TP999 数据会出现偶尔的尖刺的问题,提供了双buffer优化。 + +简单的说就是,Leaf 取号段的时机是在号段消耗完的时候进行的,也就意味着号段临界点的ID下发时间取决于下一次从DB取回号段的时间,并且在这期间进来的请求也会因为DB号段没有取回来,导致线程阻塞。如果请求DB的网络和DB的性能稳定,这种情况对系统的影响是不大的,但是假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢。 + +为了DB取号段的过程能够做到无阻塞,不需要在DB取号段的时候阻塞请求线程,即当号段消费到某个点时就异步的把下一个号段加载到内存中,而不需要等到号段用尽的时候才去更新号段。这样做就可以很大程度上的降低系统的 TP999 指标。详细实现如下图所示: + +![](http://img.dabin-coder.cn/image/20220509000258.png) + +采用双buffer的方式,Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复。 + +- 每个biz-tag都有消费速度监控,通常推荐segment长度设置为服务高峰期发号QPS的600倍(10分钟),这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响。 +- 每次请求来临时都会判断下个号段的状态,从而更新此号段,所以偶尔的网络抖动不会影响下个号段的更新。 + +对于这种方案依然存在一些问题,它仍然依赖 DB的稳定性,需要采用主从备份的方式提高 DB的可用性,还有 Leaf-segment方案生成的ID是趋势递增的,这样ID号是可被计算的,例如订单ID生成场景,通过订单id号相减就能大致计算出公司一天的订单量,这个是不能忍受的。 + +### Leaf-snowflake方案 + +Leaf-snowflake方案完全沿用 snowflake 方案的bit位设计,对于workerID的分配引入了Zookeeper持久顺序节点的特性自动对snowflake节点配置 wokerID。避免了服务规模较大时,动手配置成本太高的问题。 + +Leaf-snowflake是按照下面几个步骤启动的: + +- 启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下检查自己是否已经注册过(是否有该顺序子节点)。 +- 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。 +- 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。 + +![](http://img.dabin-coder.cn/image/20220509000333.png) + +为了减少对 Zookeeper的依赖性,会在本机文件系统上缓存一个workerID文件。当ZooKeeper出现问题,恰好机器出现问题需要重启时,能保证服务能够正常启动。 + +上文阐述过在类 snowflake算法上都存在时钟回拨的问题,Leaf-snowflake在解决时钟回拨的问题上是通过校验自身系统时间与 `leaf_forever/${self}`节点记录时间做比较然后启动报警的措施。 + +![](http://img.dabin-coder.cn/image/20220509000708.png) + +美团官方建议是由于强依赖时钟,对时间的要求比较敏感,在机器工作时NTP同步也会造成秒级别的回退,建议可以直接关闭NTP同步。要么在时钟回拨的时候直接不提供服务直接返回ERROR_CODE,等时钟追上即可。或者做一层重试,然后上报报警系统,更或者是发现有时钟回拨之后自动摘除本身节点并报警。 + +在性能上官方提供的数据目前 Leaf 的性能在4C8G 的机器上QPS能压测到近5w/s,TP999 1ms。 + +## 总结 + +以上基本列出了所有常用的分布式ID生成方式,其实大致分类的话可以分为两类: + +一种是类DB型的,根据设置不同起始值和步长来实现趋势递增,需要考虑服务的容错性和可用性。 + +另一种是类snowflake型,这种就是将64位划分为不同的段,每段代表不同的涵义,基本就是时间戳、机器ID和序列数。这种方案就是需要考虑时钟回拨的问题以及做一些 buffer的缓冲设计提高性能。 + +而且可通过将三者(时间戳,机器ID,序列数)划分不同的位数来改变使用寿命和并发数。 + +例如对于并发数要求不高、期望长期使用的应用,可增加时间戳位数,减少序列数的位数. 例如配置成{"workerBits":23,"timeBits":31,"seqBits":9}时, 可支持28个节点以整体并发量14400 UID/s的速度持续运行68年。 + +对于节点重启频率频繁、期望长期使用的应用, 可增加工作机器位数和时间戳位数, 减少序列数位数. 例如配置成{"workerBits":27,"timeBits":30,"seqBits":6}时, 可支持37个节点以整体并发量2400 UID/s的速度持续运行34年。 + + + +[参考链接](https://www.cnblogs.com/jajian/p/11101213.html) diff --git a/docs/distributed/2-distributed-lock.md b/docs/distributed/2-distributed-lock.md new file mode 100644 index 0000000..2e2e671 --- /dev/null +++ b/docs/distributed/2-distributed-lock.md @@ -0,0 +1,259 @@ +--- +sidebar: heading +--- + +## 为什么要使用分布式锁 + +在单机环境下,当存在多个线程可以同时改变某个变量(可变共享变量)时,就会出现线程安全问题。这个问题可以通过 JAVA 提供的 volatile、ReentrantLock、synchronized 以及 concurrent 并发包下一些线程安全的类等来避免。 + +而在多机部署环境,需要在多进程下保证线程的安全性,Java提供的这些API仅能保证在单个JVM进程内对多线程访问共享资源的线程安全,已经不满足需求了。这时候就需要使用分布式锁来保证线程安全。通过分布式锁,可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。 + +## 分布式锁应该具备哪些条件 + +在分析分布式锁的三种实现方式之前,先了解一下分布式锁应该具备哪些条件: + +1. 互斥性。在任意时刻,只有一个客户端能持有锁。 +2. 不会死锁。具备锁失效机制,防止死锁。即使有客户端在持有锁的期间崩溃而没有主动解锁,也要保证后续其他客户端能加锁。 +3. 加锁和解锁必须是同一个客户端。客户端a不能将客户端b的锁解开,即不能误解锁。 +4. 高性能、高可用的获取锁与释放锁。 +5. 具备可重入特性。 +6. 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。 + +## 分布式锁的三种实现方式 + +1. 基于数据库实现分布式锁; +2. 基于缓存(Redis等)实现分布式锁; +3. 基于Zookeeper实现分布式锁。 + +### 基于数据库的实现方式 + +**悲观锁** + +创建一张锁表,然后通过操作该表中的数据来实现加锁和解锁。当要锁住某个方法或资源时,就向该表插入一条记录,表中设置方法名为唯一键,这样多个请求同时提交数据库时,只有一个操作可以成功,判定操作成功的线程获得该方法的锁,可以执行方法内容;想要释放锁的时候就删除这条记录,其他线程就可以继续往数据库中插入数据获取锁。 + +**乐观锁** + +每次更新操作,都觉得不会存在并发冲突,只有更新失败后,才重试。 + +扣减余额就可以使用这种方案。 + +具体实现:增加个version字段,每次更新修改,都会自增加一,然后去更新余额时,把查出来的那个版本号,带上条件去更新,如果是上次那个版本号,就更新,如果不是,表示别人并发修改过了,就继续重试。 + +### 基于Redis的实现方式 + +#### 简单实现 + +Redis 2.6.12 之前的版本中采用 setnx + expire 方式实现分布式锁,在 Redis 2.6.12 版本后 setnx 增加了过期时间参数: + +```java +SET lockKey value NX PX expire-time +``` + +所以在Redis 2.6.12 版本后,只需要使用setnx就可以实现分布式锁了。 + +加锁逻辑: + +1. setnx争抢key的锁,如果已有key存在,则不作操作,过段时间继续重试,保证只有一个客户端能持有锁。 +2. value设置为 requestId(可以使用机器ip拼接当前线程名称),表示这把锁是哪个请求加的,在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 +3. 再用expire给锁加一个过期时间,防止异常导致锁没有释放。 + +解锁逻辑: + +首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。使用lua脚本实现原子操作,保证线程安全。 + +下面我们通过Jedis(基于java语言的redis客户端)来演示分布式锁的实现。 + +**Jedis实现分布式锁** + +引入Jedis jar包,在pom.xml文件增加代码: + +```xml + + redis.clients + jedis + 2.9.0 + +``` + +**加锁** + +调用jedis的set()实现加锁,加锁代码如下: + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-08-01 17:13 + */ +public class RedisTest { + + private static final String LOCK_SUCCESS = "OK"; + private static final String SET_IF_NOT_EXIST = "NX"; + private static final String SET_EXPIRE_TIME = "PX"; + + @Autowired + private JedisPool jedisPool; + + public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { + Jedis jedis = jedisPool.getResource(); + String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_EXPIRE_TIME, expireTime); + + if (LOCK_SUCCESS.equals(result)) { + return true; + } + return false; + } +} +``` + +各参数说明: + +- lockKey:使用key来当锁,需要保证key是唯一的。可以使用系统号拼接自定义的key。 +- requestId:表示这把锁是哪个请求加的,可以使用机器ip拼接当前线程名称。在解锁的时候需要判断当前请求是否持有锁,防止误解锁。比如客户端A加锁,在执行解锁之前,锁过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。 +- NX:意思是SET IF NOT EXIST,保证如果已有key存在,则不作操作,过段时间继续重试。NX参数保证只有一个客户端能持有锁。 +- PX:给key加一个过期的设置,具体时间由expireTime决定。 +- expireTime:设置key的过期时间,防止异常导致锁没有释放。 + +**解锁** + +首先需要获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁。这里使用lua脚本实现原子操作,保证线程安全。 + +使用eval命令执行Lua脚本的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。lua脚本如下: + +``` +//KEYS[1]是lockKey,ARGV[1]是requestId +String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; +Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); +``` + +Jedis的eval()方法源码如下: + +```java +public Object eval(String script, List keys, List args) { + return this.eval(script, keys.size(), getParams(keys, args)); +} +``` + +lua脚本的意思是:调用get获取锁(KEYS[1])对应的value值,检查是否与requestId(ARGV[1])相等,如果相等则调用del删除锁。否则返回0。 + +完整的解锁代码如下: + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-08-01 17:13 + */ +public class RedisTest { + private static final Long RELEASE_SUCCESS = 1L; + + @Autowired + private JedisPool jedisPool; + + public boolean releaseDistributedLock(String lockKey, String requestId) { + Jedis jedis = jedisPool.getResource(); + ////KEYS[1]是lockKey,ARGV[1]是requestId + String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; + Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); + + if (RELEASE_SUCCESS.equals(result)) { + return true; + } + return false; + } +} +``` + +#### RedLock + +前面的方案是基于**Redis单机版**的分布式锁讨论,还不是很完美。因为Redis一般都是集群部署的。 + +如果线程一在`Redis`的`master`节点上拿到了锁,但是加锁的`key`还没同步到`slave`节点。恰好这时,`master`节点发生故障,一个`slave`节点就会升级为`master`节点。线程二就可以顺理成章获取同个`key`的锁啦,但线程一也已经拿到锁了,锁的安全性就没了。 + +为了解决这个问题,Redis作者antirez提出一种高级的分布式锁算法:**Redlock**。它的核心思想是这样的: + +部署多个Redis master,以保证它们不会同时宕掉。并且这些master节点是完全相互独立的,相互之间不存在数据同步。同时,需要确保在这多个master实例上,是与在Redis单实例,使用相同方法来获取和释放锁。 + +我们假设当前有5个Redis master节点,在5台服务器上面运行这些Redis实例。 + +RedLock的实现步骤: + +1. 获取当前时间,以毫秒为单位。 +2. 按顺序向5个master节点请求加锁。客户端设置网络连接和响应超时时间,并且超时时间要小于锁的失效时间。(假设锁自动失效时间为10秒,则超时时间一般在5-50毫秒之间,我们就假设超时时间是50ms吧)。如果超时,跳过该master节点,尽快去尝试下一个master节点。 +3. 客户端使用当前时间减去开始获取锁时间(即步骤1记录的时间),得到获取锁使用的时间。当且仅当超过一半(N/2+1,这里是5/2+1=3个节点)的Redis master节点都获得锁,并且使用的时间小于锁失效时间时,锁才算获取成功。(如上图,10s> 30ms+40ms+50ms+4m0s+50ms) +4. 如果取到了锁,key的真正有效时间就变啦,需要减去获取锁所使用的时间。 +5. 如果获取锁失败(没有在至少N/2+1个master实例取到锁,有或者获取锁时间已经超过了有效时间),客户端要在所有的master节点上解锁(即便有些master节点根本就没有加锁成功,也需要解锁,以防止有些漏网之鱼)。 + +简化下步骤就是: + +- 按顺序向5个master节点请求加锁 +- 根据设置的超时时间来判断,是不是要跳过该master节点。 +- 如果大于等于3个节点加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功啦。 +- 如果获取锁失败,解锁! + +### 基于ZooKeeper的实现方式 + +ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下: + +(1)创建一个目录mylock; +(2)线程A想获取锁就在mylock目录下创建临时顺序节点; +(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁; +(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点; +(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。 + +这里推荐一个Apache的开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。 + +优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。 + +缺点:因为需要频繁的创建和删除节点,性能上不如Redis方式。 + +## 三种实现方式对比 + +**数据库分布式锁实现** + +优点: + +- 简单,使用方便,不需要引入`Redis、zookeeper`等中间件。 + +缺点: + +- 不适合高并发的场景 +- db操作性能较差; + +**Redis分布式锁实现** + +优点: + +- 性能好,适合高并发场景 +- 较轻量级 +- 有较好的框架支持,如Redisson + +缺点: + +- 过期时间不好控制 +- 需要考虑锁被别的线程误删场景 + +**Zookeeper分布式锁实现** + +缺点: + +- 性能不如redis实现的分布式锁 +- 比较重的分布式锁。 + +优点: + +- 有较好的性能和可靠性 +- 有封装较好的框架,如Curator + +**对比汇总** + +- 从性能角度(从高到低)Redis > Zookeeper >= 数据库; +- 从理解的难易程度角度(从低到高)数据库 > Redis > Zookeeper; +- 从实现的复杂性角度(从低到高)Zookeeper > Redis > 数据库; +- 从可靠性角度(从高到低)Zookeeper > Redis > 数据库。 + + + +## 参考链接 + +https://mp.weixin.qq.com/s/xQknd6xsVDPBr4TbETTk2A diff --git a/docs/distributed/2.1-rpc.md b/docs/distributed/2.1-rpc.md new file mode 100644 index 0000000..e213e29 --- /dev/null +++ b/docs/distributed/2.1-rpc.md @@ -0,0 +1,123 @@ +--- +sidebar: heading +--- + +## RPC简介 + +RPC,英文全名remote procedure call,即远程过程调用。就是说一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。 + +可以这么说,RPC就是要像调用本地的函数一样去调远程函数。 + +RPC是一个完整的远程调用方案,它通常包括通信协议和序列化协议。 + +其中,通信协议包含**http协议**(如gRPC使用http2)、**自定义报文的tcp协议**(如dubbo)。序列化协议包含**基于文本编码**的xml、json,**基于二进制编码**的protobuf、hessian等。 + +> protobuf 即 Protocol Buffers,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。protobuf 性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式。protobuf 是以二进制方式存储,占用空间小,但也带来了可读性差的缺点(二进制协议,因为不可读而难以调试,不好定位问题)。 +> +> Protobuf序列化协议相比JSON有什么优点? +> +> 1:序列化后体积相比Json和XML很小,适合网络传输 +> +> 2:支持跨平台多语言 +> +> 3:序列化反序列化速度很快,快于Json的处理速速 + +**一个完整的RPC过程,都可以用下面这张图来描述**: + +> stub说的都是“一小块代码”,通常是有个caller要调用callee的时候,中间需要一些特殊处理的逻辑,就会用这种“小块代码”去做。 + +![](http://img.dabin-coder.cn/image/20220508160414.png) + +1. 服务消费端(client)以本地调用的方式调用远程服务; +2. 客户端 Stub(client stub) 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(序列化):`RpcRequest`; +3. 客户端 Stub(client stub) 找到远程服务的地址,并将消息发送到服务提供端; +4. 服务端 Stub(桩)收到消息将消息反序列化为Java对象: `RpcRequest`; +5. 服务端 Stub(桩)根据`RpcRequest`中的类、方法、方法参数等信息调用本地的方法; +6. 服务端 Stub(桩)得到方法执行结果并将组装成能够进行网络传输的消息体:`RpcResponse`(序列化)发送至消费方; +7. 客户端 Stub(client stub)接收到消息并将消息反序列化为Java对象:`RpcResponse` ,这样也就得到了最终结果。 + +## RPC 解决了什么问题? + +让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。 + +## 常见的 RPC 框架有哪些? + +- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件。 +- **gRPC** :基于HTTP2。gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。 +- **Hessian:** Hessian是一个轻量级的remoting on http工具,使用简单的方法提供了RMI的功能。 采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。 +- **Thrift:** Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。 + +## 有了HTTP ,为啥还要用RPC进行服务调用? + +首先,RPC是一个完整的远程调用方案,它通常包括通信协议和序列化协议。而HTTP只是一个通信协议,不是一个完整的远程调用方案。这两者不是对等的概念,用来比较不太合适。 + +RPC框架可以使用 **HTTP协议**作为传输协议或者直接使用**自定义的TCP协议**作为传输协议,使用不同的协议一般也是为了适应不同的场景。 + +HTTP+Restful,其优势很大。它**可读性好**,且**应用广、跨语言的支持**。 + +但是使用该方案也有其缺点,这是与其优点相对应的: + +- 首先是**有用信息占比少**,毕竟HTTP工作在第七层,包含了大量的HTTP头等信息。 +- 其次是**效率低**,还是因为第七层的缘故,必须按照HTTP协议进行层层封装。 + +而使用**自定义tcp协议**的话,可以极大地精简了传输内容,这也是为什么有些后端服务之间会采用自定义tcp协议的rpc来进行通信的原因。 + +## 各种序列化技术 + +### XML + +XML序列化的好处在于可读性好,方便阅读和调试。但是序列化以后的字节码文件比较大,而且效率不高,适用于对性能要求不高,而且QPS较低的企业级内部系统之间的数据交换场景。同时XML又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。比如我们熟知的WebService,就是采用XML格式对数据进行序列化的。XML序列化/反序列化的实现方式有很多,熟知的方式有XStream和Java自带的XML序列化和反序列化两种。 + +### JSON + +JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于XML来说,JSON的字节流更小,而且可读性也非常好。现在JSON数据格式在企业运用是最普遍的。 + +JSON序列化常用的开源工具有很多: + +1. Jackson(https://github.com/FasterXML/jackson ) +2. 阿里开源的FastJson(https://github.com/alibaba/fastjon) +3. 谷歌的GSON(https://github.com/google/gson) + +这几种json的序列化工具中,jackson与fastjson要比GSON的性能好,但是jackson、GSON的稳定性腰比Fastjson好。而fastjson的优势在于提供的api非常容易使用。 + +### Hession + +Hessian是一个支持跨语言传输的二进制序列化协议,相对于Java默认的序列化机制来说,Hession具有更好的性能和易读性,而且支持多种不同的语言。 + +实际上Dubbo采用的就是Hessian序列化来实现,只不过Dubbo对Hessian进行了重构,性能更高。 + +### Avro + +Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据。动态语言友好,Avro提供的机制是动态语言可以方便的处理Avro数据。 + +### Kryo + +Kryo是一种非常成熟的序列化实现,已经在Hive、Storm中使用的比较广泛,不过它不能夸语言。目前Dubbo已经在2.6版本支持kyro的序列化机制。它的性能要由于之前的hessian2。 + +### Protobuf + +Protobuf是Google的一种数据交换格式,它独立于语言、独立于平台。Google提供了多种语言来实现,比如Java、C、Go、Python,每一种实现都包含了相应语言的编译器和库文件,Protobuf是一个纯粹的表示层协议,可以和各种传输层协议一起使用。 + +Protobuf使用比较广泛,主要是空间开销小和性能比较好,非常适合用于公司内部对性能要求高的RPC调用。另外由于解析性能比较高,序列化以后数据量相对较少,所以也可以应用在对象的持久化场景中。 + +但是要使用Protobuf会相对来说麻烦些,因为他有自己的语法,有自己的编译器,如果需要用到的话必须要去投入成本在这个技术的学习中。 + +Protobuf有个缺点就是要传输每一个类的结构都要生成对应的proto文件,如果某个类发生修改,还得重新生成该类对应的proto文件。 + +## 序列化技术的选型 + +### 技术层面 + +1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输性能。 +2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间。 +3. 序列化协议是否支持夸平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信需求,那么这个是必须要考虑的。 +4. 可扩展性、兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,这就要求我们来采用序列化协议具有良好的可扩展性、兼容性,比如现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务。 +5. 技术的流行程度,越流行的技术意味着使用的公司越多,那么很多坑都已经淌过并且得到了解决,技术解决方案也相对成熟。 +6. 学习难度和易用性。 + +### 选型建议 + +1. 对性能要求不高的场景,可以采用基于XML的SOAP协议 +2. 性能和间接性有比较高要求的场景,那么Hessian、Protobuf、Thrift、Avro都可以。 +3. 基于前后端分离,或者独立的对外API服务,选用JSON是比较好的,对于调试、可读性都很不错。 +4. Avro设计理念偏于动态类型语言,那么这类的场景使用Avro是可以的。 diff --git "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" b/docs/distributed/3-micro-service.md similarity index 99% rename from "\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" rename to docs/distributed/3-micro-service.md index c48afc0..2461831 100644 --- "a/\345\210\206\345\270\203\345\274\217/\345\276\256\346\234\215\345\212\241.md" +++ b/docs/distributed/3-micro-service.md @@ -1,3 +1,7 @@ +--- +sidebar: heading +--- + ## 什么是微服务? 微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务和服务之间采用轻量级的通信机制进行协作。每个服务可以被独立的部署到生产环境。 @@ -183,7 +187,7 @@ ### Spring Cloud基础知识 -[Spring Cloud基础知识](../框架/SpringCloud微服务实战.md) +[Spring Cloud基础知识](../framework/springcloud-overview.md) ### 什么是Service Mesh? diff --git a/docs/distributed/4-distibuted-arch.md b/docs/distributed/4-distibuted-arch.md new file mode 100644 index 0000000..30b0b32 --- /dev/null +++ b/docs/distributed/4-distibuted-arch.md @@ -0,0 +1,3 @@ +# 分布式架构,微服务、限流、熔断.... + +[分布式架构,微服务、限流、熔断....](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247490543&idx=1&sn=ee34bee96511d5e548381e0576f8b484&chksm=ce98e6a9f9ef6fbf7db9c2b6d2fed26853a3bc13a50c3228ab57bea55afe0772008cdb1f957b&token=1594696656&lang=zh_CN#rd) \ No newline at end of file diff --git a/docs/distributed/5-distributed-transaction.md b/docs/distributed/5-distributed-transaction.md new file mode 100644 index 0000000..66185b2 --- /dev/null +++ b/docs/distributed/5-distributed-transaction.md @@ -0,0 +1,199 @@ +--- +sidebar: heading +--- + +## 简介 + +### 事务 + +事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。事务应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。 + +### 分布式事务 + +分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务的特性。 + +### 强一致性、弱一致性、最终一致性 + +**强一致性** + +任何一次读都能读到某个数据的最近一次写的数据。系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。简言之,在任意时刻,所有节点中的数据是一样的。 + +**弱一致性** + +数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。 + +**最终一致性** + +不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致状态。 + +由于分布式事务方案,无法做到完全的ACID的保证,没有一种完美的方案,能够解决掉所有业务问题。因此在实际应用中,会根据业务的不同特性,选择最适合的分布式事务方案。 + +## 分布式事务的基础 + +### CAP理论 + +**Consistency**(一致性):数据一致更新,所有数据变动都是同步的(强一致性)。 + +**Availability**(可用性):好的响应性能。 + +**Partition tolerance**(分区容错性) :可靠性。 + +定理:任何分布式系统**只可同时满足二点**,没法三者兼顾。 + +CA系统(放弃P):指将所有数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上,就不会存在网络分区。所以强一致性以及可用性得到满足。 + +CP系统(放弃A):如果要求数据在各个服务器上是强一致的,然而网络分区会导致同步时间无限延长,那么如此一来可用性就得不到保障了。坚持事务ACID(原子性、一致性、隔离性和持久性)的传统数据库以及对结果一致性非常敏感的应用通常会做出这样的选择。 + +AP系统(放弃C):这里所说的放弃一致性,并不是完全放弃数据一致性,而是放弃数据的强一致性,而保留数据的最终一致性。如果即要求系统高可用又要求分区容错,那么就要放弃一致性了。因为一旦发生网络分区,节点之间将无法通信,为了满足高可用,每个节点只能用本地数据提供服务,这样就会导致数据不一致。一些遵守BASE原则数据库,(如:Cassandra、CouchDB等)往往会放宽对一致性的要求(满足最终一致性即可),一次来获取基本的可用性。 + +### BASE理论 + +BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展。 + +1. 基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。 +2. 软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。 +3. 最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。 + +BASE解决了CAP中理论没有网络延迟,在BASE中用软状态和最终一致,保证了延迟后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。 + +## 分布式事务解决方案 + +分布式事务的实现主要有以下 6 种方案: + +- 2PC 方案 +- TCC 方案 +- 本地消息表 +- MQ事务 +- Saga事务 +- 最大努力通知方案 + +### 2PC方案 + +2PC方案分为两阶段: + +第一阶段:事务管理器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交. + +第二阶段:事务协调器要求每个数据库提交数据,或者回滚数据。 + +优点: 尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,对于MySQL是从5.5开始支持。 + +缺点: + +- 单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。 +- 同步阻塞:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。 +- 数据不一致:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。 + +总的来说,2PC方案比较简单,成本较低,但是其单点问题,以及不能支持高并发(由于同步阻塞)依然是其最大的弱点。 + +### TCC + +TCC 的全称是:`Try`、`Confirm`、`Cancel`。 + +- **Try 阶段**:这个阶段说的是对各个服务的资源做检测以及对资源进行 **锁定或者预留**。 +- **Confirm 阶段**:这个阶段说的是在各个服务中执行实际的操作。 +- **Cancel 阶段**:如果任何一个服务的业务方法执行出错,那么这里就需要 **进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚) +- + +举个简单的例子如果你用100元买了一瓶水, Try阶段:你需要向你的钱包检查是否够100元并锁住这100元,水也是一样的。 + +如果有一个失败,则进行cancel(释放这100元和这一瓶水),如果cancel失败不论什么失败都进行重试cancel,所以需要保持幂等。 + +如果都成功,则进行confirm,确认这100元扣,和这一瓶水被卖,如果confirm失败无论什么失败则重试(会依靠活动日志进行重试)。 + +这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个**事务回滚实际上是严重依赖于你自己写代码来回滚和补偿**了,会造成补偿代码巨大。 + +### 本地消息表 + +本地消息表的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理。 + +![](http://img.dabin-coder.cn/image/本地消息表.png) + +对于本地消息队列来说核心是把大事务转变为小事务。还是举上面用100元去买一瓶水的例子。 + +1.当你扣钱的时候,你需要在你扣钱的服务器上新增加一个本地消息表,你需要把你扣钱和写入减去水的库存到本地消息表放入同一个事务(依靠数据库本地事务保证一致性。 + +2.这个时候有个定时任务去轮询这个本地事务表,把没有发送的消息,扔给商品库存服务器,叫他减去水的库存,到达商品服务器之后这个时候得先写入这个服务器的事务表,然后进行扣减,扣减成功后,更新事务表中的状态。 + +3.商品服务器通过定时任务扫描消息表或者直接通知扣钱服务器,扣钱服务器本地消息表进行状态更新。 + +4.针对一些异常情况,定时扫描未成功处理的消息,进行重新发送,在商品服务器接到消息之后,首先判断是否是重复的,如果已经接收,在判断是否执行,如果执行在马上又进行通知事务,如果未执行,需要重新执行需要由业务保证幂等,也就是不会多扣一瓶水。 + +本地消息队列是BASE理论,是最终一致模型,适用于对一致性要求不高的。实现这个模型时需要注意重试的幂等。 + +### MQ事务 + +基于 MQ 的分布式事务方案其实是对本地消息表的封装,将本地消息表基于 MQ 内部,其他方面的协议基本与本地消息表一致。 + +MQ事务方案整体流程和本地消息表的流程很相似,如下图: + +![](http://img.dabin-coder.cn/image/MQ事务方案.png) + +从上图可以看出和本地消息表方案唯一不同就是将本地消息表存在了MQ内部,而不是业务数据库中。 + +那么MQ内部的处理尤为重要,下面主要基于 RocketMQ 4.3 之后的版本介绍 MQ 的分布式事务方案。 + +在本地消息表方案中,保证事务主动方发写业务表数据和写消息表数据的一致性是基于数据库事务,RocketMQ 的事务消息相对于普通 MQ提供了 2PC 的提交接口,方案如下: + +**正常情况:事务主动方发消息** + +![](http://img.dabin-coder.cn/image/事务主动方发消息.png) + +这种情况下,事务主动方服务正常,没有发生故障,发消息流程如下: + +- 发送方向 MQ 服务端(MQ Server)发送 half 消息。 +- MQ Server 将消息持久化成功之后,向发送方 ack 确认消息已经发送成功。 +- 发送方开始执行本地事务逻辑。 +- 发送方根据本地事务执行结果向 MQ Server 提交二次确认(commit 或是 rollback)。 +- MQ Server 收到 commit 状态则将半消息标记为可投递,订阅方最终将收到该消息;MQ Server 收到 rollback 状态则删除半消息,订阅方将不会接受该消息。 + +**异常情况:事务主动方消息恢复** + +![](http://img.dabin-coder.cn/image/事务主动方消息恢复.png) + +在断网或者应用重启等异常情况下,图中 4 提交的二次确认超时未到达 MQ Server,此时处理逻辑如下: + +- MQ Server 对该消息发起消息回查。 +- 发送方收到消息回查后,需要检查对应消息的本地事务执行的最终结果。 +- 发送方根据检查得到的本地事务的最终状态再次提交二次确认。 +- MQ Server基于 commit/rollback 对消息进行投递或者删除。 + +**优点** + +相比本地消息表方案,MQ 事务方案优点是: + +- 消息数据独立存储 ,降低业务系统与消息系统之间的耦合。 +- 吞吐量大于使用本地消息表方案。 + +**缺点** + +- 一次消息发送需要两次网络请求(half 消息 + commit/rollback 消息) 。 +- 业务处理服务需要实现消息状态回查接口。 + +### Saga事务 + +Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。 + +Saga的实现有很多种方式,其中最流行的两种方式是: + +- **基于事件的方式**。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应。 +- **基于命令的方式**。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务。 + +### 最大努力通知方案 + +最大努力通知也称为定期校对,是对MQ事务方案的进一步优化。它在事务主动方增加了消息校对的接口,如果事务被动方没有接收到消息,此时可以调用事务主动方提供的消息校对的接口主动获取。 + +最大努力通知的整体流程如下图: + +![](http://img.dabin-coder.cn/image/最大努力通知方案.png) + +在可靠消息事务中,事务主动方需要将消息发送出去,并且消息接收方成功接收,这种可靠性发送是由事务主动方保证的; + +但是最大努力通知,事务主动方尽最大努力(重试,轮询....)将事务发送给事务接收方,但是仍然存在消息接收不到,此时需要事务被动方主动调用事务主动方的消息校对接口查询业务消息并消费,这种通知的可靠性是由事务被动方保证的。 + +最大努力通知适用于业务通知类型,例如微信交易的结果,就是通过最大努力通知方式通知各个商户,既有回调通知,也有交易查询接口。 + +## 参考文章 + +https://www.pdai.tech/md/arch/arch-z-transection.html + +https://juejin.cn/post/6844903647197806605#heading-15 diff --git "a/\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" "b/docs/distributed/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" similarity index 100% rename from "\345\210\206\345\270\203\345\274\217/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" rename to "docs/distributed/RocketMQ\345\256\236\347\216\260RPC\347\232\204\345\216\237\347\220\206.md" diff --git "a/\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" "b/docs/framework/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" similarity index 100% rename from "\346\241\206\346\236\266/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" rename to "docs/framework/Apollo\351\205\215\347\275\256\344\270\255\345\277\203.md" diff --git "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" b/docs/framework/mybatis.md similarity index 86% rename from "\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" rename to docs/framework/mybatis.md index 5dddfd8..def7ec9 100644 --- "a/\346\241\206\346\236\266/Mybatis\351\235\242\350\257\225\351\242\230.md" +++ b/docs/framework/mybatis.md @@ -1,3 +1,7 @@ +--- +sidebar: heading +--- + ## Mybatis是什么? - MyBatis框架是一个开源的数据持久层框架。 @@ -9,11 +13,16 @@ ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。 -## 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里? +## Mybatis和Hibernate的区别? -Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。 +主要有以下几点区别: -而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。 +1. Hibernate的**开发难度**大于MyBatis,主要由于Hibernate比较复杂,庞大,学习周期比较长。 +2. Hibernate属于**全自动**ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。 +3. **数据库扩展性**的区别。Hibernate与数据库具体的关联在XML中,所以HQL对具体是用什么数据库并不是很关心。MyBatis由于所有sql都是依赖数据库书写的,所以扩展性、迁移性比较差。 +4. **缓存机制**的区别。Hibernate的二级缓存配置在SessionFactory生成配置文件中进行详细配置,然后再在具体的表对象映射中配置那种缓存。MyBatis的二级缓存配置都是在每个具体的表对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓冲机制,并且MyBatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。 +5. **日志系统完善性**的区别。Hibernate日志系统非常健全,涉及广泛,而Mybatis则除了基本记录功能外,功能薄弱很多。 +6. **sql的优化上,Mybatis要比Hibernate方便很多**。由于Mybatis的sql都是写在xml里,因此优化sql比Hibernate方便很多。而Hibernate的sql很多都是自动生成的,无法直接维护sql;总之写sql的灵活度上Hibernate不及Mybatis。 ## MyBatis框架的优缺点及其适用的场合 diff --git "a/\346\241\206\346\236\266/netty\345\256\236\346\210\230.md" b/docs/framework/netty-overview.md similarity index 84% rename from "\346\241\206\346\236\266/netty\345\256\236\346\210\230.md" rename to docs/framework/netty-overview.md index 112aef3..af35a09 100644 --- "a/\346\241\206\346\236\266/netty\345\256\236\346\210\230.md" +++ b/docs/framework/netty-overview.md @@ -1,85 +1,6 @@ - - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [netty 核心组件](#netty-%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6) - - [NIO](#nio) -- [简单的 netty 应用程序](#%E7%AE%80%E5%8D%95%E7%9A%84-netty-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F) - - [Echo 服务器](#echo-%E6%9C%8D%E5%8A%A1%E5%99%A8) - - [ChannelHandler 和业务逻辑](#channelhandler-%E5%92%8C%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91) - - [引导服务器](#%E5%BC%95%E5%AF%BC%E6%9C%8D%E5%8A%A1%E5%99%A8) - - [Echo 客户端](#echo-%E5%AE%A2%E6%88%B7%E7%AB%AF) - - [ChannelHandler](#channelhandler) - - [引导客户端](#%E5%BC%95%E5%AF%BC%E5%AE%A2%E6%88%B7%E7%AB%AF) - - [构建和运行 Echo 服务器和客户端](#%E6%9E%84%E5%BB%BA%E5%92%8C%E8%BF%90%E8%A1%8C-echo-%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AF) -- [Netty 的组件和设计](#netty-%E7%9A%84%E7%BB%84%E4%BB%B6%E5%92%8C%E8%AE%BE%E8%AE%A1) - - [Channel 接口](#channel-%E6%8E%A5%E5%8F%A3) - - [EventLoop 接口](#eventloop-%E6%8E%A5%E5%8F%A3) - - [ChannelFuture 接口](#channelfuture-%E6%8E%A5%E5%8F%A3) - - [ChannelHandler](#channelhandler-1) - - [ChannelPipeline](#channelpipeline) - - [ChannelInitializer](#channelinitializer) - - [引导](#%E5%BC%95%E5%AF%BC) -- [传输](#%E4%BC%A0%E8%BE%93) - - [传输迁移](#%E4%BC%A0%E8%BE%93%E8%BF%81%E7%A7%BB) - - [传输 API](#%E4%BC%A0%E8%BE%93-api) - - [内置的传输](#%E5%86%85%E7%BD%AE%E7%9A%84%E4%BC%A0%E8%BE%93) - - [Epoll](#epoll) -- [ByteBuf](#bytebuf) - - [Upooled 缓冲区](#upooled-%E7%BC%93%E5%86%B2%E5%8C%BA) -- [ChannelHandler](#channelhandler-2) - - [Channel 的生命周期](#channel-%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) - - [ChannelHandler 的生命周期](#channelhandler-%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) - - [ChannelInboundHandler 接口](#channelinboundhandler-%E6%8E%A5%E5%8F%A3) - - [ChannelOutboundHandler 接口](#channeloutboundhandler-%E6%8E%A5%E5%8F%A3) - - [ChannelHandlerAdapter](#channelhandleradapter) - - [资源管理](#%E8%B5%84%E6%BA%90%E7%AE%A1%E7%90%86) -- [ChannelPipeline 接口](#channelpipeline-%E6%8E%A5%E5%8F%A3) - - [修改ChannelPipeline](#%E4%BF%AE%E6%94%B9channelpipeline) - - [ChannelHandlerContext 接口](#channelhandlercontext-%E6%8E%A5%E5%8F%A3) - - [异常处理](#%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86) -- [EventLoop 和线程模型](#eventloop-%E5%92%8C%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B) - - [EventLoop 接口](#eventloop-%E6%8E%A5%E5%8F%A3-1) - - [任务调度](#%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6) - - [实现细节](#%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82) -- [引导](#%E5%BC%95%E5%AF%BC-1) - - [引导客户端](#%E5%BC%95%E5%AF%BC%E5%AE%A2%E6%88%B7%E7%AB%AF-1) - - [引导服务器](#%E5%BC%95%E5%AF%BC%E6%9C%8D%E5%8A%A1%E5%99%A8-1) - - [在引导过程添加多个 ChannelHandler](#%E5%9C%A8%E5%BC%95%E5%AF%BC%E8%BF%87%E7%A8%8B%E6%B7%BB%E5%8A%A0%E5%A4%9A%E4%B8%AA-channelhandler) - - [关闭](#%E5%85%B3%E9%97%AD) -- [编解码器](#%E7%BC%96%E8%A7%A3%E7%A0%81%E5%99%A8) - - [解码器](#%E8%A7%A3%E7%A0%81%E5%99%A8) - - [抽象类 ByteToMessageDecoder](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-bytetomessagedecoder) - - [抽象类 ReplayingDecoder](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-replayingdecoder) - - [抽象类 MessageToMessageDecoder](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-messagetomessagedecoder) - - [TooLongFrameException 类](#toolongframeexception-%E7%B1%BB) - - [编码器](#%E7%BC%96%E7%A0%81%E5%99%A8) - - [抽象类 MessageToByteEncoder](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-messagetobyteencoder) - - [抽象类 MessageToMessageEncoder](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-messagetomessageencoder) - - [编解码器类](#%E7%BC%96%E8%A7%A3%E7%A0%81%E5%99%A8%E7%B1%BB) - - [抽象类 ByteToMessageCodec](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-bytetomessagecodec) - - [抽象类 MessageToMessageCodec](#%E6%8A%BD%E8%B1%A1%E7%B1%BB-messagetomessagecodec) - - [CombinedChannelDuplexHandler 类](#combinedchannelduplexhandler-%E7%B1%BB) -- [预置的 ChannelHandler 和编解码器](#%E9%A2%84%E7%BD%AE%E7%9A%84-channelhandler-%E5%92%8C%E7%BC%96%E8%A7%A3%E7%A0%81%E5%99%A8) - - [SSL/TLS](#ssltls) - - [HTTP/HTTPS 应用程序](#httphttps-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F) - - [添加 HTTP 支持](#%E6%B7%BB%E5%8A%A0-http-%E6%94%AF%E6%8C%81) - - [聚合 HTTP 消息](#%E8%81%9A%E5%90%88-http-%E6%B6%88%E6%81%AF) - - [HTTP 压缩](#http-%E5%8E%8B%E7%BC%A9) - - [HTTPS](#https) - - [WebSocket](#websocket) - - [空闲的连接和超时](#%E7%A9%BA%E9%97%B2%E7%9A%84%E8%BF%9E%E6%8E%A5%E5%92%8C%E8%B6%85%E6%97%B6) - - [基于分隔符的协议](#%E5%9F%BA%E4%BA%8E%E5%88%86%E9%9A%94%E7%AC%A6%E7%9A%84%E5%8D%8F%E8%AE%AE) - - [基于长度的协议](#%E5%9F%BA%E4%BA%8E%E9%95%BF%E5%BA%A6%E7%9A%84%E5%8D%8F%E8%AE%AE) - - [写大型数据](#%E5%86%99%E5%A4%A7%E5%9E%8B%E6%95%B0%E6%8D%AE) -- [ctx.write() 和 channel().write() 的区别](#ctxwrite-%E5%92%8C-channelwrite-%E7%9A%84%E5%8C%BA%E5%88%AB) - - - -## 简介 - -### netty 核心组件 +# 简介 + +## netty 核心组件 - Channel:传入和传出数据的载体,它可以连接或者断开连接。 @@ -87,25 +8,25 @@ - Future:提供了另一种在操作完成时通知应用程序的方式。 - 事件和 ChannelHandler -### NIO +## NIO 当一个 socket 建立好之后,Thread 会把这个连接请求交给 Selector,Selector 会不断去遍历所有的 Socket,一旦有一个 Socket 建立完成,它就会通知 Thread,然后 Thread 处理完数据在返回给客户端,这个过程是不阻塞的。 -## 简单的 netty 应用程序 +# 简单的 netty 应用程序 Echo 客户端和服务器之间的交互是非常简单的;在客户端建立一个连接之后,它会向服务 器发送一个或多个消息,反过来,服务器又会将每个消息回送给客户端。 -### Echo 服务器 +## Echo 服务器 所有的 netty 服务器都需要以下两个部分: - 一个 ChannelHandler,实现服务器对接受的客户端的数据的处理 - 引导服务器:配置服务器的启动代码,将服务器绑定到它要监听连接请求的端口上 -#### ChannelHandler 和业务逻辑 +**ChannelHandler 和业务逻辑** Echo 服务器需要实现 ChannelInboundHandler 方法,定义响应入站事件的方法。 @@ -134,7 +55,7 @@ public class EchoServerHandler extends ChannelInboundHandlerAdapter { ChannelHandler 有助于保持业务逻辑与网络处理代码的分离。 -#### 引导服务器 +**引导服务器** 1. 服务器监听端口; 2. 配置 Channel,将有关的入站事件消息通知给 EchoServerHandler。 @@ -180,7 +101,7 @@ public class EchoServer { } ``` -### Echo 客户端 +## Echo 客户端 Echo 客户端的功能: @@ -189,7 +110,7 @@ Echo 客户端的功能: 3. 接收服务器发送的消息; 4. 关闭连接。 -#### ChannelHandler +**ChannelHandler** 客户端也需要实现 ChannelInboundHandler,用于处理数据。 @@ -219,7 +140,7 @@ public class EchoClientHandler extends SimpleChannelInboundHandler { } ``` -#### 引导客户端 +**引导客户端** 客户端使用主机和端口参数来连接远程地址。 @@ -269,7 +190,7 @@ public class EchoClient { } ``` -### 构建和运行 Echo 服务器和客户端 +## 构建和运行 Echo 服务器和客户端 在服务器端,使用`mvn clean package`构建项目,然后在 idea 中配置 Edit Configurations,带参数运行服务器程序。 @@ -279,7 +200,7 @@ public class EchoClient { -## Netty 的组件和设计 +# Netty 的组件和设计 Channel -- Socket; @@ -289,11 +210,11 @@ ChannelFuture -- 异步通知; ChannelHandler -- 处理出站和入站数据; -### Channel 接口 +## Channel 接口 Netty 的Channel 接口所提供的API,大大地降低了直接使用Socket 类的复杂性。 -### EventLoop 接口 +## EventLoop 接口 EventLoop 用于处理连接的生命周期中所发生的事件。 @@ -307,11 +228,11 @@ Channel 和 EventLoop 的关系:Channel 会被注册到 EventLoop 上,在整 一个给定 Channel 的I/O 操作都是由相同的Thread 执行的,实际上消除了对于同步的需要。 -### ChannelFuture 接口 +## ChannelFuture 接口 Netty 中所有 io 操作都是异步的,ChannelFuture 接口用于在操作完成时得到通知。 -### ChannelHandler +## ChannelHandler ChannelHandler 的方法是由网络事件触发的。典型用途: @@ -323,7 +244,7 @@ ChannelHandler 的方法是由网络事件触发的。典型用途: 一些适配器类提供了 ChannelHandler 接口中的所有方法的默认实现。 -### ChannelPipeline +## ChannelPipeline 提供了 ChannelHandler 链的容器。当 Channel 被创建时,会被自动分配到它专属的 ChannelPipeline。 @@ -333,7 +254,7 @@ ChannelHandler 的方法是由网络事件触发的。典型用途: 当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler 和ChannelPipeline 之间的绑定。虽然这个对象可以被用于获取底层的Channel,但是它主要还是被用于写出站数据。 -### ChannelInitializer +## ChannelInitializer 作用是给 ChannelPipeline 安装 ChannelHandler。 @@ -343,15 +264,15 @@ ChannelHandler 安装到 ChannelPipeline 的过程: - 当ChannelInitializer.initChannel()方法被调用时,ChannelInitializer 将在 ChannelPipeline 中安装ChannelHandler; - ChannelInitializer 将它自己从ChannelPipeline 中移除。 -### 引导 +## 引导 Bootstrap 连接远程主机和端口,有一个 EventLoopGroup;ServerBootstrap 绑定到一个本地端口,有两个 EventLoopGroup。 -## 传输 +# 传输 -### 传输迁移 +## 传输迁移 Netty 为所有的传输提供了通用的 API,使得从阻塞传输到非阻塞传输的转换变得更加简单。 @@ -390,13 +311,13 @@ public class NettyNioServer { 只需要改动 SocketChannel 和 EventLoopGroup。 -### 传输 API +## 传输 API 每个 ChannelHandler 都会分配一个 ChannelPipeline 和 ChannelConfig。ChannelConfig 包含了该 Channel 的所有配置设置,并且支持热更新。 可以通过向 ChannelPipeline 添加 ChannelHandler 实例来增加应用程序的功能。 -### 内置的传输 +## 内置的传输 Channel 被注册到选择器 Selector 后,当 Channel 状态发生变化时可以得到通知。可能的状态变化有: @@ -409,29 +330,25 @@ Channel 被注册到选择器 Selector 后,当 Channel 状态发生变化时 > 高效地将数据从文件系统移动到网络接口,而不需要将其从内核空间复制到用户空间,其在像FTP 或者 > HTTP 这样的协议中可以显著地提升性能。它只能传输文件的原始内容,不能传输加密或者压缩的文件。 -#### Epoll +**Epoll** 用于 Linux 的本地非阻塞传输。Netty为Linux提供了一组NIO API,其以一种和它本身的设计更加一致的方式使用epoll,并且以一种更加轻量的方式使用中断。 -## ByteBuf +# ByteBuf Java NIO 提供了ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐。Netty 的ByteBuffer 替代品是ByteBuf,一个强大的实现,既解决了JDK API 的局限性,又为网络应用程序的开发者提供了更好的API。 - - - - -#### Upooled 缓冲区 +**Upooled 缓冲区** Upooled 工具类提供了静态的辅助方法来创建未池化的 ByteBuf 实例。 -## ChannelHandler +# ChannelHandler -### Channel 的生命周期 +## Channel 的生命周期 | 状态 | 描述 | | ------------------- | -------------------------------------------------- | @@ -444,7 +361,7 @@ Upooled 工具类提供了静态的辅助方法来创建未池化的 ByteBuf 实 ChannelRegistered -> ChannelActive -> ChannelInactive -> ChannelUnregistered -### ChannelHandler 的生命周期 +## ChannelHandler 的生命周期 | 方法 | 描述 | | --------------- | ----------------------------------------------- | @@ -452,7 +369,7 @@ ChannelRegistered -> ChannelActive -> ChannelInactive -> ChannelUnregistered | handlerRemoved | 从ChannelPipeline中移除ChannelHandler时被调用 | | exceptionCaught | 处理过程中在ChannelPipeline中有错误产生时被调用 | -### ChannelInboundHandler 接口 +## ChannelInboundHandler 接口 处理入站数据以及各种状态变化。 @@ -488,7 +405,7 @@ public class SimpleDiscardHandler } ``` -### ChannelOutboundHandler 接口 +## ChannelOutboundHandler 接口 ChannelOutboundHandler 一个强大的功能是可以按需推迟操作或者事件。 @@ -505,25 +422,25 @@ ChannelOutboundHandler 一个强大的功能是可以按需推迟操作或者事 ChannelPromise 是 ChannelFuture 的一个子类,ChannelOutboundHandler 中的大部分方法都需要一个 ChannelPromise参数,以便在操作完成时得到通知。 -### ChannelHandlerAdapter +## ChannelHandlerAdapter ChannelHandlerAdapter 提供了实用方法 isSharable(),如果其对应的实现被标注成 @Sharable,那么这个方法将返回true,表示它可以被添加到多个 ChannelPipeline 中。 共享 ChannelHandler 一个常见的用途是用于收集跨越多个 channel 的统计信息。 -### 资源管理 +## 资源管理 idea 配置 edit configuration -- vm options -- `-Dio.netty.leakDetectionLevel=ADVANCED ` -## ChannelPipeline 接口 +# ChannelPipeline 接口 每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline,这项关联是永久性的;Channel 既不能附加另外一个ChannelPipeline,也不能分离其当前的。 ChannelHandlerContext 使得 ChannelHandler 能够和它的 ChannelPipeline 以及其他的 ChannelHandler 交互。 -### 修改ChannelPipeline +## 修改ChannelPipeline ChannelHandler 可以通过添加、删除或者替换其他的ChannelHandler 来实时地修改ChannelPipeline 的布局。 @@ -541,11 +458,11 @@ ChannelPipeline 的用于访问ChannelHandler 的操作: | context | 返回和ChannelHandler绑定的ChannelHandlerContext | | names | 返回所有的ChannelHanlder名称 | -### ChannelHandlerContext 接口 +## ChannelHandlerContext 接口 ChannelHandlerContext 代表了ChannelHandler 和ChannelPipeline 之间的关联,每当有ChannelHandler 添加到ChannelPipeline 中时,都会创建ChannelHandlerContext。 -![ChannelHandler/ChannelPipeline/ChannelHandlerContext/Channel的关系](https://img2018.cnblogs.com/blog/1252910/201909/1252910-20190912194315417-1954624274.png) +![](http://img.dabin-coder.cn/image/netty1.png) | 方法 | 描述 | | --------------- | ---------------------------------------------------------- | @@ -553,7 +470,7 @@ ChannelHandlerContext 代表了ChannelHandler 和ChannelPipeline 之间的关联 | alloc | 返回相关联的Channel所配置的ByteBufAllocator | | bind | 绑定到给定的SocketAddress,并返回ChannelFuture | -### 异常处理 +## 异常处理 入站异常:在 ChannelInboundHandler 实现 exceptionCaught 方法。 @@ -596,9 +513,9 @@ public class OutboundExceptionHandler extends ChannelOutboundHandlerAdapter { -## EventLoop 和线程模型 +# EventLoop 和线程模型 -### EventLoop 接口 +## EventLoop 接口 EventLoop 构建在 java.util.concurrent 和 io.netty.channel 之上。EventLoop 继承了 ScheduledExecutorService。EventLoop 由一个永远不会改变的 Thread 驱动,同时任务可以直接提交给 EventLoop 实现。EventLoop 可能服务于多个 Channel。 @@ -606,7 +523,7 @@ Netty4中所有的 io 操作和事件都由 EventLoop 的 Thread 处理。Netty3 Netty 4 中所采用的线程模型,通过在同一个线程中处理某个给定的EventLoop 中所产生的所有事件,解决了这个问题。这提供了一个更加简单的执行体系架构,并且消除了在多个ChannelHandler 中进行同步的需要 -### 任务调度 +## 任务调度 使用 EventLoop 调度任务: @@ -634,27 +551,27 @@ ScheduledFuture future = ch.eventLoop().scheduleAtFixedRate( }, 60, 60, TimeUnit.SECONDES); ``` -### 实现细节 +## 实现细节 -![EventLoop执行逻辑](https://img2018.cnblogs.com/blog/1252910/201909/1252910-20190912194501807-1452675286.png) +![](http://img.dabin-coder.cn/image/netty-eventloop执行逻辑.png) -## 引导 +# 引导 配置 netty 应用程序,使它运行起来。服务器使用一个父 Channel 接受来自客户端的连接,并创建子 Channel 以用于它们之间的通信。客户端只需要一个 Channel 完成所有的网络交互。 引导类是 cloneable 的,在引导类实例上调用 clone() 就可以创建多个具有类似配置或者完全相同配置的 Channel。 -### 引导客户端 +## 引导客户端 BootStrap 类被用于客户端或者使用了无连接协议的应用程序中。 -### 引导服务器 +## 引导服务器 -![ServerBoostrap和ServerChannel](https://img2018.cnblogs.com/blog/1252910/201909/1252910-20190912194603147-253748270.png) +![](http://img.dabin-coder.cn/image/ServerBoostrap和ServerChannel.png) 在基类AbstractBootstrap有handler方法,目的是添加一个handler,监听Bootstrap的动作。 @@ -662,7 +579,7 @@ BootStrap 类被用于客户端或者使用了无连接协议的应用程序中 **handler在初始化时就会执行,而childHandler会在客户端成功connect后才执行。** -### 在引导过程添加多个 ChannelHandler +## 在引导过程添加多个 ChannelHandler 在 handler 传入 ChannelInitializer 的实现类,重写 initChannel 方法,在这个方法中添加多个 ChannelHandler。 @@ -687,7 +604,7 @@ try { } ``` -### 关闭 +## 关闭 关闭 EventLoopGroup,它将处理任何挂起的事件和任务,随后释放所有活动的线程。 @@ -699,17 +616,17 @@ future.syncUninterruptibly(); -## 编解码器 +# 编解码器 数据格式转化。编码器操作出站数据,解码器处理入站数据。继承自 ChannelInboundHandlerAdapter。数据编码或者解码完就会被传入 ChannelPipeline 的下一个 ChannelHandler。 -### 解码器 +## 解码器 ByteToMessageDecoder、ReplayingDecoder:将字节解码为消息。 MessageToMessageDecoder:将消息解码为另一种消息。 -#### 抽象类 ByteToMessageDecoder +**抽象类 ByteToMessageDecoder** ```java public class ToIntegerDecoder extends ByteToMessageDecoder { @@ -725,7 +642,7 @@ public class ToIntegerDecoder extends ByteToMessageDecoder { 调用 readInt() 方法前需要验证输入的 ByteBuf 是否具有足够的数据。 -#### 抽象类 ReplayingDecoder +**抽象类 ReplayingDecoder** 类型参数S 指定了用于状态管理的类型,其中Void 代表不需要状态管理。 @@ -743,7 +660,7 @@ public class ToIntegerDecoder2 extends ReplayingDecoder { 并不是所有的ByteBuf 操作都被支持,如果调用了一个不被支持的方法,将会抛出一个UnsupportedOperationException;ReplayingDecoder 稍慢于ByteToMessageDecoder。如果使用ByteToMessageDecoder 不会引入太多的复杂性,那么选用它。 -#### 抽象类 MessageToMessageDecoder +**抽象类 MessageToMessageDecoder** 两种消息格式的转换。 @@ -756,15 +673,15 @@ public class IntegerToStringDecoder extends MessageToMessageDecoder { } ``` -#### TooLongFrameException 类 +**TooLongFrameException 类** 解码器缓冲大量的数据以至于耗尽可用的内存,可以设置一个最大字节数的阈值,如果超出该阈值,则手动抛出一个TooLongFrameException。 -### 编码器 +## 编码器 消息编码为字节;消息编码为消息。 -#### 抽象类 MessageToByteEncoder +**抽象类 MessageToByteEncoder** ```java public class ShortToByteEncoder extends MessageToByteEncoder { @@ -776,7 +693,7 @@ public class ShortToByteEncoder extends MessageToByteEncoder { } ``` -#### 抽象类 MessageToMessageEncoder +**抽象类 MessageToMessageEncoder** ```java public class IntegerToStringEncoder extends MessageToMessageEncoder { @@ -788,19 +705,19 @@ public class IntegerToStringEncoder extends MessageToMessageEncoder { } ``` -### 编解码器类 +## 编解码器类 结合一个解码器和编码器可能会对可重用性造成影响。 -#### 抽象类 ByteToMessageCodec +**抽象类 ByteToMessageCodec** 结合了 ByteToMessageDecoder 和 MessageToByteEncoder。 -#### 抽象类 MessageToMessageCodec +**抽象类 MessageToMessageCodec** 定义:`public abstract class MessageToMessageCodec` -#### CombinedChannelDuplexHandler 类 +**CombinedChannelDuplexHandler 类** 可以实现一个编解码器,而又不必直接扩展抽象的编解码器类。 @@ -845,13 +762,13 @@ public class CombinedByteCharCodec extends CombinedChannelDuplexHandler { } ``` -### HTTP/HTTPS 应用程序 +## HTTP/HTTPS 应用程序 完整的 HTTP 请求(FullHttpRequest)包括请求头信息、若干个 HTTPContent 和 LastHttpContent。 @@ -887,7 +804,7 @@ HTTP 编解码器:HttpRequestEncoder、HttpResponseEncoder、HttpReqeustDecode HttpResponseDecoder:将字节解码为 HttpResponse、HttpContent 和 LastHttpContent。 -#### 添加 HTTP 支持 +**添加 HTTP 支持** ```java public class HttpPipelineInitializer extends ChannelInitializer { @@ -913,7 +830,7 @@ public class HttpPipelineInitializer extends ChannelInitializer { 判断是否是客户端,如果是客户端,则添加 HttpResponseDecoder 对服务器响应进行解码。 -#### 聚合 HTTP 消息 +**聚合 HTTP 消息** 由于 HTTP 请求和响应可能由多个部分组成,需要将它们聚合成完整的消息。Netty 提供了一个聚合器,可以将多个消息部分合并成 FullHttpRequest 或者 FullHttpResponse 消息。 @@ -945,7 +862,7 @@ HttpServerCodec 里面组合了HttpResponseEncoder和HttpRequestDecoder。 HttpClientCodec 里面组合了HttpRequestEncoder和HttpResponseDecoder。 -#### HTTP 压缩 +**HTTP 压缩** 当使用HTTP 时,建议服务器端开启压缩功能以尽可能多地减小传输数据的大小。Netty 为压缩和解压缩提供了ChannelHandler 实现,它们同时支持gzip 和deflate 编码。 @@ -975,7 +892,7 @@ public class HttpCompressionInitializer extends ChannelInitializer { } ``` -#### HTTPS +**HTTPS** 启动 HTTPS 只需要将 SslHandler 添加到 ChannelPipeline。 @@ -1004,11 +921,11 @@ public class HttpsCodecInitializer extends ChannelInitializer { } ``` -#### WebSocket +**WebSocket** WebSocket 在客户端和服务器之间提供了真正的双向数据交换。 -![WebSocket握手](https://img2018.cnblogs.com/blog/1252910/201909/1252910-20190912194009527-799081544.png) +![](http://img.dabin-coder.cn/image/netty-websocket协议.png) WebSocketFrame 类型: @@ -1067,11 +984,11 @@ public class WebSocketServerInitializer extends ChannelInitializer { > 要想为WebSocket 添加安全性,只需要将SslHandler 作为第一个ChannelHandler 添加到ChannelPipeline 中。 -### 空闲的连接和超时 +## 空闲的连接和超时 用于空闲连接以及超时的 ChannelHandler。 -![用于空闲连接以及超时的ChannelHandler](https://img2018.cnblogs.com/blog/1252910/201909/1252910-20190912194117618-854988800.png) +![](http://img.dabin-coder.cn/image/用于空闲连接以及超时的ChannelHandler.png) 发送心跳: @@ -1109,7 +1026,7 @@ public class IdleStateHandlerInitializer extends ChannelInitializer { 使用 IdleStateHandler 测试远程节点是否还活着,失活时关闭连接释放资源。 -### 基于分隔符的协议 +## 基于分隔符的协议 基于分隔符的协议的解码器 @@ -1203,7 +1120,7 @@ public class CmdHandlerInitializer extends ChannelInitializer { } ``` -### 基于长度的协议 +## 基于长度的协议 基于长度的协议的解码器: @@ -1235,7 +1152,7 @@ public class LengthBasedInitializer extends ChannelInitializer { } ``` -### 写大型数据 +## 写大型数据 当写大型数据到远程节点时,如果连接速度比较慢,数据依然不断的往内存写,可能导致内存耗尽。利用 NIO 的零拷贝特性,可以消除将文件内容从文件系统移动到网络栈的复制过程。应用程序需要做的就是实现一个 FileRegion 的接口。 @@ -1255,9 +1172,3 @@ channel.writeAndFlush(region).addListener( - - -## ctx.write() 和 channel().write() 的区别 - -https://blog.csdn.net/lalalahaitang/article/details/81563830 - diff --git a/docs/framework/netty/1-overview.md b/docs/framework/netty/1-overview.md new file mode 100644 index 0000000..d0b180b --- /dev/null +++ b/docs/framework/netty/1-overview.md @@ -0,0 +1,16 @@ +# 简介 + +## netty 核心组件 + +- Channel:传入和传出数据的载体,它可以连接或者断开连接。 + +- 回调:操作完成后通知相关方。 +- Future:提供了另一种在操作完成时通知应用程序的方式。 +- 事件和 ChannelHandler + +## NIO + +当一个 socket 建立好之后,Thread 会把这个连接请求交给 Selector,Selector 会不断去遍历所有的 Socket,一旦有一个 Socket 建立完成,它就会通知 Thread,然后 Thread 处理完数据在返回给客户端,这个过程是不阻塞的。 + + + diff --git a/docs/framework/netty/10-encoder-decoder.md b/docs/framework/netty/10-encoder-decoder.md new file mode 100644 index 0000000..ff7c7cb --- /dev/null +++ b/docs/framework/netty/10-encoder-decoder.md @@ -0,0 +1,146 @@ +# 编解码器 + +数据格式转化。编码器操作出站数据,解码器处理入站数据。继承自 ChannelInboundHandlerAdapter。数据编码或者解码完就会被传入 ChannelPipeline 的下一个 ChannelHandler。 + +## 解码器 + +ByteToMessageDecoder、ReplayingDecoder:将字节解码为消息。 + +MessageToMessageDecoder:将消息解码为另一种消息。 + +**抽象类 ByteToMessageDecoder** + +```java +public class ToIntegerDecoder extends ByteToMessageDecoder { + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf in, + List list) throws Exception { + if (in.readableBytes() >= 4) { + list.add(in.readInt()); + } + } +} +``` + +调用 readInt() 方法前需要验证输入的 ByteBuf 是否具有足够的数据。 + +**抽象类 ReplayingDecoder** + +类型参数S 指定了用于状态管理的类型,其中Void 代表不需要状态管理。 + +```java +public class ToIntegerDecoder2 extends ReplayingDecoder { + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf in, + List list) throws Exception { + list.add(in.readInt()); + } +} +``` + +如果没有足够的字节可用,这个readInt()方法的实现将会抛出一个Error,将在基类中被捕获并处理。当有更多的数据可供读取时,该decode()方法将会被再次调用。 + +并不是所有的ByteBuf 操作都被支持,如果调用了一个不被支持的方法,将会抛出一个UnsupportedOperationException;ReplayingDecoder 稍慢于ByteToMessageDecoder。如果使用ByteToMessageDecoder 不会引入太多的复杂性,那么选用它。 + +**抽象类 MessageToMessageDecoder** + +两种消息格式的转换。 + +```java +public class IntegerToStringDecoder extends MessageToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, Integer integer, List list) throws Exception { + list.add(String.valueOf(integer)); + } +} +``` + +**TooLongFrameException 类** + +解码器缓冲大量的数据以至于耗尽可用的内存,可以设置一个最大字节数的阈值,如果超出该阈值,则手动抛出一个TooLongFrameException。 + +## 编码器 + +消息编码为字节;消息编码为消息。 + +**抽象类 MessageToByteEncoder** + +```java +public class ShortToByteEncoder extends MessageToByteEncoder { + @Override + public void encode(ChannelHandlerContext ctx, Short msg, ByteBuf out) + throws Exception { + out.writeShort(msg); + } +} +``` + +**抽象类 MessageToMessageEncoder** + + ```java +public class IntegerToStringEncoder extends MessageToMessageEncoder { + @Override + public void encode(ChannelHandlerContext ctx, Integer msg + List out) throws Exception { + out.add(String.valueOf(msg)); + } +} + ``` + +## 编解码器类 + +结合一个解码器和编码器可能会对可重用性造成影响。 + +**抽象类 ByteToMessageCodec** + +结合了 ByteToMessageDecoder 和 MessageToByteEncoder。 + +**抽象类 MessageToMessageCodec** + +定义:`public abstract class MessageToMessageCodec` + +**CombinedChannelDuplexHandler 类** + +可以实现一个编解码器,而又不必直接扩展抽象的编解码器类。 + +```java +public class CombinedChannelDuplexHandler +``` + +ByteToCharDecoder 类: + +```java +public class ByteToCharDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + while (byteBuf.readableBytes() >= 2) { + list.add(byteBuf.readChar()); + } + } +} +``` + +CharToByteEncoder 类: + +```java +public class CharToByteEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext channelHandlerContext, Character character, ByteBuf byteBuf) throws Exception { + byteBuf.writeChar(character);//向byteBuf写入基本类型的值 + } +} +``` + +编解码器类: + +```java +public class CombinedByteCharCodec extends CombinedChannelDuplexHandler { + public CombinedByteCharCodec() { + super(new ByteToCharDecoder(), new CharToByteEncoder());//将委托实例传递给父类 + } +} +``` + + + diff --git a/docs/framework/netty/11-preset-channel-handler.md b/docs/framework/netty/11-preset-channel-handler.md new file mode 100644 index 0000000..7cba4b5 --- /dev/null +++ b/docs/framework/netty/11-preset-channel-handler.md @@ -0,0 +1,409 @@ +# 预置的 ChannelHandler 和编解码器 + +## SSL/TLS + +Java 提供了 javax.net.ssl 支持 SSL/TSL,用以实现数据安全。 + +![](http://img.dabin-coder.cn/image/sslhandler加解密.png) + +添加 SSL/TLS 支持: + +```java +public class SslChannelInitializer extends ChannelInitializer { + private final SslContext context; + private final boolean startTls; + + public SslChannelInitializer(SslContext context, boolean startTls) { + this.context = context; + this.startTls = startTls; + } + + @Override + protected void initChannel(Channel channel) throws Exception { + SSLEngine engine = context.newEngine(channel.alloc());//alloc返回channel所配置的ByteBufAllocator + channel.pipeline().addFirst("ssl", + new SslHandler(engine, startTls));//大多数情况SslHandler是第一个ChannelHandler + //这确保了所有其他的ChannelHandler处理数据之后,才会进行加密。 + } +} +``` + +## HTTP/HTTPS 应用程序 + +完整的 HTTP 请求(FullHttpRequest)包括请求头信息、若干个 HTTPContent 和 LastHttpContent。 + +完整的 HTTP 响应(FullHttpResponse)包括响应头信息、若干个 HTTPContent 和 LastHttpContent。 + +所有类型的 HTTP 消息都实现了 HttpObject 接口。 + +HTTP 编解码器:HttpRequestEncoder、HttpResponseEncoder、HttpReqeustDecoder 和 HttpResponseDecoder。 + +HttpResponseDecoder:将字节解码为 HttpResponse、HttpContent 和 LastHttpContent。 + +**添加 HTTP 支持** + +```java +public class HttpPipelineInitializer extends ChannelInitializer { + private final boolean client; + + public HttpPipelineInitializer(boolean client) { + this.client = client; + } + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + if (client) { + pipeline.addLast("decoder", new HttpResponseDecoder()); + pipeline.addLast("encoder", new HttpRequestEncoder()); + } else { + pipeline.addLast("decoder", new HttpRequestDecoder()); + pipeline.addLast("encoder", new HttpResponseEncoder()); + } + } +} +``` + +判断是否是客户端,如果是客户端,则添加 HttpResponseDecoder 对服务器响应进行解码。 + +**聚合 HTTP 消息** + +由于 HTTP 请求和响应可能由多个部分组成,需要将它们聚合成完整的消息。Netty 提供了一个聚合器,可以将多个消息部分合并成 FullHttpRequest 或者 FullHttpResponse 消息。 + +自动聚合 HTTP 的消息片段: + +```java +public class HttpAggregarotInitializer extends ChannelInitializer { + private final boolean isClient; + + public HttpAggregarotInitializer(boolean isClient) { + this.isClient = isClient; + } + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + if (isClient) { + pipeline.addLast("codec", new HttpClientCodec()); + } else { + pipeline.addLast("codec", new HttpServerCodec()); + } + pipeline.addLast("aggregator", //最大消息大小是512kb + new HttpObjectAggregator(512*1024)); + } +} +``` + +HttpServerCodec 里面组合了HttpResponseEncoder和HttpRequestDecoder。 + +HttpClientCodec 里面组合了HttpRequestEncoder和HttpResponseDecoder。 + +**HTTP 压缩** + +当使用HTTP 时,建议服务器端开启压缩功能以尽可能多地减小传输数据的大小。Netty 为压缩和解压缩提供了ChannelHandler 实现,它们同时支持gzip 和deflate 编码。 + +自动压缩 HTTP 消息: + +```java +public class HttpCompressionInitializer extends ChannelInitializer { + private final boolean isClient; + + public HttpCompressionInitializer(boolean isClient) { + this.isClient = isClient; + } + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + if (isClient) { + pipeline.addLast("codec", new HttpClientCodec()); + pipeline.addLast("decompressor", + new HttpContentDecompressor());//处理来自服务器的压缩内容 + } else { + pipeline.addLast("codec", new HttpServerCodec()); + pipeline.addLast("compressor", + new HttpContentCompressor());//服务器端压缩数据 + } + } +} +``` + +**HTTPS** + +启动 HTTPS 只需要将 SslHandler 添加到 ChannelPipeline。 + +```java +public class HttpsCodecInitializer extends ChannelInitializer { + private final SslContext context; + private final boolean isClient; + + public HttpsCodecInitializer(SslContext context, boolean isClient) { + this.context = context; + this.isClient = isClient; + } + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + SSLEngine engine = context.newEngine(channel.alloc()); + pipeline.addFirst("ssl", new SslHandler(engine));//添加SslHandler之后可以使用https + + if (isClient) { + pipeline.addLast("codec", new HttpClientCodec()); + } else { + pipeline.addLast("codec", new HttpServerCodec()); + } + } +} +``` + +**WebSocket** + +WebSocket 在客户端和服务器之间提供了真正的双向数据交换。 + +![](http://img.dabin-coder.cn/image/netty-websocket协议.png) + +WebSocketFrame 类型: + +| 名称 | 描述 | +| -------------------------- | ------------------------------------------------- | +| BinaryWebSocketFrame | 二进制数据帧 | +| TextWebSocketFrame | 文本数据帧 | +| ContinuationWebSocketFrame | 二进制和文本数据帧结合体 | +| CloseWebSocketFrame | 控制帧:一个close请求、关闭的状态码以及关闭的原因 | +| PingWebSocketFrame | 控制帧:请求一个PongWebSocketFrame | +| PongWebSocketFrame | 控制帧:对PingWebSocketFrame请求的响应 | + +WebSocketServerProtocolHandler 处理协议升级握手,以及三种控制帧--Close、Ping 和 Pong。Text和Binary数据帧将会被传递给下一个 ChannelHandler 进行处理。 + +```java +public class WebSocketServerInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) throws Exception { + channel.pipeline().addLast( + new HttpServerCodec(), + new HttpObjectAggregator(65536), + new WebSocketServerProtocolHandler("/websocket"),//升级握手 + new TextFrameHandler(), + new BinaryFrameHandler(), + new ContinuationFrameHandler()); + + } + public static final class TextFrameHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + //handle text frame + } + } + + public static final class BinaryFrameHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, BinaryWebSocketFrame binaryWebSocketFrame) throws Exception { + //handle binary frame + } + } + + public static final class ContinuationFrameHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, ContinuationWebSocketFrame continuationWebSocketFrame) throws Exception { + //handle continuation frame + } + } +} +``` + +> 要想为WebSocket 添加安全性,只需要将SslHandler 作为第一个ChannelHandler 添加到ChannelPipeline 中。 + +## 空闲的连接和超时 + +用于空闲连接以及超时的 ChannelHandler。 + +![](http://img.dabin-coder.cn/image/用于空闲连接以及超时的ChannelHandler.png) + +发送心跳: + +```java +public class IdleStateHandlerInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + //60s没有接受或发送数据,IdelStateHandler会使用IdleStateEvent调用fireUserEventTriggered() + pipeline.addLast(new IdleStateHandler( + 0, 0, 60, TimeUnit.SECONDS)); + pipeline.addLast(new HeartbeatHandler()); + } + + public static final class HeartbeatHandler extends + ChannelInboundHandlerAdapter { + //发送到远程节点的心跳信息 + private static final ByteBuf HEARTBEAT_SEQUENCE = + Unpooled.unreleasableBuffer(Unpooled.copiedBuffer( + "HEARTBEAT", CharsetUtil.ISO_8859_1)); + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + //连接空闲时间太长时,发送心跳消息,并在发送失败时关闭该连接 + ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()) + .addListener(ChannelFutureListener.CLOSE_ON_FAILURE); + } else { + super.userEventTriggered(ctx, evt);//传递给下一个ChannelInboundHandler + } + } + } +} +``` + +使用 IdleStateHandler 测试远程节点是否还活着,失活时关闭连接释放资源。 + +## 基于分隔符的协议 + +基于分隔符的协议的解码器 + +| 名称 | 描述 | +| -------------------------- | ----------------------------------------------------------- | +| DelimiterBasedFrameDecoder | 使用自定义分隔符提取帧的通用解码器 | +| LineBasedFrameDecoder | 提取由行尾符分隔的解码器,速度比DeimiterBasedFrameDecoder快 | + +分隔符提取帧: + +```java +public class LineBasedHandlerInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + //提取帧,并传给下一个ChannelHandler + pipeline.addLast(new LineBasedFrameDecoder(64*1024)); + pipeline.addLast(new FrameHandler());//接收数据帧 + } + + public static final class FrameHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { + //处理LineBasedFrameDecoder传进的帧 + } + } +``` + +示例:1.每个帧都由换行符(\n)分隔;2.每个帧由一系列的元素组成,每个元素都由的单个空格字符分隔;3.一个帧内容代表一个命令,定义为一个命令名称后面跟着数目可变的参数。 + +```java +public class CmdHandlerInitializer extends ChannelInitializer { + static final byte SPACE = (byte)' '; + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new CmdDecoder(64 * 1024)); + pipeline.addLast(new CmdHandler()); + } + + public static final class Cmd { + private final ByteBuf name; + private final ByteBuf args; + + public Cmd(ByteBuf name, ByteBuf args) { + this.name = name; + this.args = args; + } + + public ByteBuf getName() { + return name; + } + + public ByteBuf getArgs() { + return args; + } + } + + public static final class CmdDecoder + extends LineBasedFrameDecoder { + + public CmdDecoder(int maxLength) { + super(maxLength); + } + + @Override + protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { + ByteBuf frame = (ByteBuf) super.decode(ctx, buffer); + if (frame == null) { + return null; + } + //查找第一个空格字符的索引,空格前是命令名称,后面是参数 + int index = frame.indexOf(frame.readerIndex(), + frame.writerIndex(), SPACE); + return new Cmd(frame.slice(frame.readerIndex(), index), + frame.slice(index + 1, frame.writerIndex())); + } + } + + public static final class CmdHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, Cmd cmd) throws Exception { + //处理cmd + } + } +} +``` + +## 基于长度的协议 + +基于长度的协议的解码器: + +| 名称 | 描述 | +| ---------------------------- | ------------------------------------------------------------ | +| FixedLengthFrameDecoder | 提取固定长度的帧 | +| LengthFieldBasedFrameDecoder | 根据帧头部中的长度值提取帧;该字段的偏移量以及长度在构造函数中指定 | + +变长帧: + +```java +public class LengthBasedInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeLine = channel.pipeline(); + //帧起始的前8字节是帧长度 + pipeLine.addLast(new LengthFieldBasedFrameDecoder(64 * 1024, 0, 8)); + pipeLine.addLast(new FrameHandler()); + } + + public static class FrameHandler extends + SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { + //处理帧 + } + } +} +``` + +## 写大型数据 + +当写大型数据到远程节点时,如果连接速度比较慢,数据依然不断的往内存写,可能导致内存耗尽。利用 NIO 的零拷贝特性,可以消除将文件内容从文件系统移动到网络栈的复制过程。应用程序需要做的就是实现一个 FileRegion 的接口。 + +利用零拷贝特性(FileRegion)来传输一个文件的内容。 + +```java +FileInputStream in = new FileInputStream(File); +FileRegion region = new DefaultFileRegion(in.getChannel(), 0, file.length()); +channel.writeAndFlush(region).addListener( + new ChannelFuture(region).addListener( + new ChannelFutureListener() { + + } + ) +); +``` + + diff --git a/docs/framework/netty/2-make-your-app.md b/docs/framework/netty/2-make-your-app.md new file mode 100644 index 0000000..47ba51f --- /dev/null +++ b/docs/framework/netty/2-make-your-app.md @@ -0,0 +1,186 @@ +# 简单的 netty 应用程序 + +Echo 客户端和服务器之间的交互是非常简单的;在客户端建立一个连接之后,它会向服务 +器发送一个或多个消息,反过来,服务器又会将每个消息回送给客户端。 + +## Echo 服务器 + +所有的 netty 服务器都需要以下两个部分: + +- 一个 ChannelHandler,实现服务器对接受的客户端的数据的处理 +- 引导服务器:配置服务器的启动代码,将服务器绑定到它要监听连接请求的端口上 + +**ChannelHandler 和业务逻辑** + +Echo 服务器需要实现 ChannelInboundHandler 方法,定义响应入站事件的方法。 + +```java +@ChannelHandler.Sharable +public class EchoServerHandler extends ChannelInboundHandlerAdapter { + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf in = (ByteBuf) msg; + System.out.println("server reveived: " + in.toString(CharsetUtil.UTF_8)); + ctx.write(in);//将接受到的消息回传给发送者 + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close();//关闭channel + } +} +``` + +ChannelHandler 有助于保持业务逻辑与网络处理代码的分离。 + +**引导服务器** + +1. 服务器监听端口; +2. 配置 Channel,将有关的入站事件消息通知给 EchoServerHandler。 + +```java +public class EchoServer { + private final int port; + + public EchoServer(int port) { + this.port = port; + } + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.err.println( + "Usage: " + EchoServer.class.getSimpleName() + + " "); + } + int port = Integer.parseInt(args[0]); + new EchoServer(port).start(); + } + + public void start() throws Exception { + final EchoServerHandler serverHandler = new EchoServerHandler(); + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(group) + .channel(NioServerSocketChannel.class)//nio传输的channel + .localAddress(new InetSocketAddress(port)) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(serverHandler);//将serverHandler添加到自Channel的ChannelPipeline + } + }); + ChannelFuture future = bootstrap.bind().sync();//异步绑定到服务器,阻塞直到绑定成功 + future.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully().sync(); + } + } +} +``` + +## Echo 客户端 + +Echo 客户端的功能: + +1. 连接到服务器; +2. 发送消息; +3. 接收服务器发送的消息; +4. 关闭连接。 + +**ChannelHandler** + +客户端也需要实现 ChannelInboundHandler,用于处理数据。 + +```java +@ChannelHandler.Sharable +public class EchoClientHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + //当被通知的channel是活跃的时候发送消息 + ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); + } + + /** + * 每当接收数据就会调用此方法,服务器发送的数据可能被分块接收 + */ + @Override + public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { + System.out.println("client received: " + byteBuf.toString(CharsetUtil.UTF_8));//接收的消息 + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } +} +``` + +**引导客户端** + +客户端使用主机和端口参数来连接远程地址。 + +```java +public class EchoClient { + private final String host; + private final int port; + + public EchoClient(String host, int port) { + this.host = host; + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(group) + .channel(NioSocketChannel.class)//适用于nio传输的channel类型 + .remoteAddress(new InetSocketAddress(host, port)) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast( + new EchoClientHandler()); + } + }); + ChannelFuture future = bootstrap.connect().sync();//连接到远程节点,阻塞等待 + future.channel().closeFuture().sync();//阻塞直到channel关闭 + } finally { + group.shutdownGracefully().sync();//关闭线程池并释放所有的资源 + } + } + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println( + "Usage: " + EchoClient.class.getSimpleName() + + " "); + return; + } + + String host = args[0]; + int port = Integer.parseInt(args[1]); + new EchoClient(host, port).start(); + } +} +``` + +## 构建和运行 Echo 服务器和客户端 + +在服务器端,使用`mvn clean package`构建项目,然后在 idea 中配置 Edit Configurations,带参数运行服务器程序。 + +同理,客户端进行同样的配置,注意带多个参数的运行配置,参数中间使用空格隔开。 + +先运行服务器程序,在运行客户端程序,服务端接收到客户端发出的消息,控制台输出:`server reveived: Netty rocks!`,然后服务端将消息回传客户端,客户端控制台输出:`client received: Netty rocks!`,之后客户端便退出。 + + + diff --git a/docs/framework/netty/3-component.md b/docs/framework/netty/3-component.md new file mode 100644 index 0000000..b7b5b7f --- /dev/null +++ b/docs/framework/netty/3-component.md @@ -0,0 +1,70 @@ +# Netty 的组件和设计 + +Channel -- Socket; + +EventLoop -- 控制流、多线程处理、并发; + +ChannelFuture -- 异步通知; + +ChannelHandler -- 处理出站和入站数据; + +## Channel 接口 + +Netty 的Channel 接口所提供的API,大大地降低了直接使用Socket 类的复杂性。 + +## EventLoop 接口 + +EventLoop 用于处理连接的生命周期中所发生的事件。 + +Channel 和 EventLoop 的关系:Channel 会被注册到 EventLoop 上,在整个生命周期内使用 EventLoop 处理 io 事件。 + +一个EventLoop 在它的生命周期内只和一个Thread 绑定; + +一个Channel 在它的生命周期内只注册于一个EventLoop; + +一个EventLoop 可能会被分配给一个或多个Channel; + +一个给定 Channel 的I/O 操作都是由相同的Thread 执行的,实际上消除了对于同步的需要。 + +## ChannelFuture 接口 + +Netty 中所有 io 操作都是异步的,ChannelFuture 接口用于在操作完成时得到通知。 + +## ChannelHandler + +ChannelHandler 的方法是由网络事件触发的。典型用途: + +- 将数据从一种格式转换为另一种格式 +- 提供异常的通知 +- 提供Channel 变为活动的或者非活动的通知 +- 提供当Channel 注册到EventLoop 或者从EventLoop 注销时的通知 +- 提供有关用户自定义事件的通知 + +一些适配器类提供了 ChannelHandler 接口中的所有方法的默认实现。 + +## ChannelPipeline + +提供了 ChannelHandler 链的容器。当 Channel 被创建时,会被自动分配到它专属的 ChannelPipeline。 + +每一个事件都会流经 ChannelPipeline,被 ChannelHandler链处理,每一个 ChannelHandler 处理完数据会负责把事件传递给下一个 ChannelHandler,它们的顺序即是它们被安装的顺序。 + +从客户端应用程序角度来看,如果事件从客户端传递到服务端,那么称之为出站事件,反之则是入站事件。从服务端角度来看则相反。Netty 能区分 ChannelInboundHandler 和 ChannelOutboundHandler 实现,并确保数据在能在具有相同类型的 ChannelHandler 之间传递。 + +当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler 和ChannelPipeline 之间的绑定。虽然这个对象可以被用于获取底层的Channel,但是它主要还是被用于写出站数据。 + +## ChannelInitializer + +作用是给 ChannelPipeline 安装 ChannelHandler。 + +ChannelHandler 安装到 ChannelPipeline 的过程: + +- 一个 ChannelInitializer 的实现被注册到了 ServerBootstrap; +- 当ChannelInitializer.initChannel()方法被调用时,ChannelInitializer 将在 ChannelPipeline 中安装ChannelHandler; +- ChannelInitializer 将它自己从ChannelPipeline 中移除。 + +## 引导 + +Bootstrap 连接远程主机和端口,有一个 EventLoopGroup;ServerBootstrap 绑定到一个本地端口,有两个 EventLoopGroup。 + + + diff --git a/docs/framework/netty/4-transport.md b/docs/framework/netty/4-transport.md new file mode 100644 index 0000000..038459d --- /dev/null +++ b/docs/framework/netty/4-transport.md @@ -0,0 +1,66 @@ +# 传输 + +## 传输迁移 + +Netty 为所有的传输提供了通用的 API,使得从阻塞传输到非阻塞传输的转换变得更加简单。 + +```java +public class NettyNioServer { + public void server(int port) throws Exception { + final ByteBuf buf = Unpooled.copiedBuffer("hi!\r\n", + Charset.forName("UTF-8")); + EventLoopGroup group = new NioEventLoopGroup();//oio-->nio + try { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(group) + .channel(NioServerSocketChannel.class)//oio-->nio + .localAddress(new InetSocketAddress(port)) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() { + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(buf.duplicate()) + .addListener(ChannelFutureListener.CLOSE); + } + }); + } + }); + //绑定服务器以接受连接 + ChannelFuture future = bootstrap.bind().sync(); + future.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully().sync(); + } + } +} +``` + +只需要改动 SocketChannel 和 EventLoopGroup。 + +## 传输 API + +每个 ChannelHandler 都会分配一个 ChannelPipeline 和 ChannelConfig。ChannelConfig 包含了该 Channel 的所有配置设置,并且支持热更新。 + +可以通过向 ChannelPipeline 添加 ChannelHandler 实例来增加应用程序的功能。 + +## 内置的传输 + +Channel 被注册到选择器 Selector 后,当 Channel 状态发生变化时可以得到通知。可能的状态变化有: + +- 新的 Channel 已被接受并且就绪; +- Channel 连接已经完成; +- Channel 有已经就绪的可供读取的数据; +- Channel 可用于写数据。 + +> 零拷贝(zero-copy)是一种目前只有在使用NIO 和Epoll 传输时才可使用的特性。它使你可以快速 +> 高效地将数据从文件系统移动到网络接口,而不需要将其从内核空间复制到用户空间,其在像FTP 或者 +> HTTP 这样的协议中可以显著地提升性能。它只能传输文件的原始内容,不能传输加密或者压缩的文件。 + +**Epoll** + +用于 Linux 的本地非阻塞传输。Netty为Linux提供了一组NIO API,其以一种和它本身的设计更加一致的方式使用epoll,并且以一种更加轻量的方式使用中断。 + + + diff --git a/docs/framework/netty/6-channel-handler.md b/docs/framework/netty/6-channel-handler.md new file mode 100644 index 0000000..456ab40 --- /dev/null +++ b/docs/framework/netty/6-channel-handler.md @@ -0,0 +1,88 @@ +# ChannelHandler + +## Channel 的生命周期 + +| 状态 | 描述 | +| ------------------- | -------------------------------------------------- | +| ChannelUnregistered | Channel 已创建,但还未注册到 EventLoop | +| ChannelRegistered | Channel 已注册到了 EventLoop | +| ChannelActive | Channel 已经连接到它的远程节点,可以接受和发送数据 | +| ChannelInactive | Channel 没有连接到远程节点 | + +正常的生命周期: + +ChannelRegistered -> ChannelActive -> ChannelInactive -> ChannelUnregistered + +## ChannelHandler 的生命周期 + +| 方法 | 描述 | +| --------------- | ----------------------------------------------- | +| handlerAdded | 把ChanneHandler添加到ChannelPipeline时被调用 | +| handlerRemoved | 从ChannelPipeline中移除ChannelHandler时被调用 | +| exceptionCaught | 处理过程中在ChannelPipeline中有错误产生时被调用 | + +## ChannelInboundHandler 接口 + +处理入站数据以及各种状态变化。 + +| 方法 | 描述 | +| ------------------------ | ------------------------------------------------------------ | +| channelRead | 从Channel读取数据时被调用 | +| channelReadComplete | 从Channel上一个读操作完成时被调用 | +| channelWritablityChanged | Channel 的可写状态发生改变时被调用 | +| userEventTriggered | 当ChannelnboundHandler.fireUserEventTriggered()方法被调用时被调用,因为一个POJO 被传经了ChannelPipeline | + +ReferenceCountUtil 释放消息资源: + +```java +@Sharable +public class DiscardHandler extends ChannelInboundHandlerAdapter { + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + ReferenceCountUtil.release(msg); + } +} +``` + +SimpleChannelInboundHandler 会自动释放资源,所以不应该存储指向任何消息的引用供将来使用,因为这些引用都将会失效。 + +```java +public class SimpleDiscardHandler + extends SimpleChannelInboundHandler { + @Override + public void channelRead0(ChannelHandlerContext ctx, + Object msg) { + // No need to do anything special + } +} +``` + +## ChannelOutboundHandler 接口 + +ChannelOutboundHandler 一个强大的功能是可以按需推迟操作或者事件。 + +| 方法 | 描述 | +| ------------------------------------------------------------ | -------------------------------------------------- | +| bind(ChannelHandlerContext, SocketAddress, ChannelPromise) | 当请求将Channel绑定到本地地址时被调用 | +| connect(ChannelHandlerContext, SocketAddress, ChannelPromise) | 当请求连接到远程节点时被调用 | +| close(ChannelHandlerContext, ChannelPromise) | 当请求关闭Channel时被调用 | +| deregister(ChannelHandlerContext, ChannelPromise) | 当请求将Channel 从它的EventLoop 注销时被调用 | +| read(ChannelHandlerContext) | 当请求从Channel 读取更多的数据时被调用 | +| flush(ChannelHandlerContext) | 当请求通过Channel 将入队数据冲刷到远程节点时被调用 | +| write(ChannelHandlerContext, Object, ChannelPromise) | 当请求通过Channel 将数据写到远程节点时被调用 | + +ChannelPromise 是 ChannelFuture 的一个子类,ChannelOutboundHandler 中的大部分方法都需要一个 ChannelPromise参数,以便在操作完成时得到通知。 + + +## ChannelHandlerAdapter + +ChannelHandlerAdapter 提供了实用方法 isSharable(),如果其对应的实现被标注成 @Sharable,那么这个方法将返回true,表示它可以被添加到多个 ChannelPipeline 中。 + +共享 ChannelHandler 一个常见的用途是用于收集跨越多个 channel 的统计信息。 + +## 资源管理 + +idea 配置 edit configuration -- vm options -- `-Dio.netty.leakDetectionLevel=ADVANCED ` + + + diff --git a/docs/framework/netty/7-channel-pipeline.md b/docs/framework/netty/7-channel-pipeline.md new file mode 100644 index 0000000..5ee0792 --- /dev/null +++ b/docs/framework/netty/7-channel-pipeline.md @@ -0,0 +1,79 @@ +# ChannelPipeline 接口 + +每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline,这项关联是永久性的;Channel 既不能附加另外一个ChannelPipeline,也不能分离其当前的。 + +ChannelHandlerContext 使得 ChannelHandler 能够和它的 ChannelPipeline 以及其他的 ChannelHandler 交互。 + +## 修改ChannelPipeline + +ChannelHandler 可以通过添加、删除或者替换其他的ChannelHandler 来实时地修改ChannelPipeline 的布局。 + +| 方法 | 描述 | +| ----------------------------------- | ---------------------------------------- | +| addFirst/addBefore/addAfter/addLast | 将 ChannelHandler 添加到 ChannelPipeline | +| remove | 移除 | +| replace | 替换 | + +ChannelPipeline 的用于访问ChannelHandler 的操作: + +| 方法 | 描述 | +| ------- | ----------------------------------------------- | +| get | 返回ChannelHandler | +| context | 返回和ChannelHandler绑定的ChannelHandlerContext | +| names | 返回所有的ChannelHanlder名称 | + +## ChannelHandlerContext 接口 + +ChannelHandlerContext 代表了ChannelHandler 和ChannelPipeline 之间的关联,每当有ChannelHandler 添加到ChannelPipeline 中时,都会创建ChannelHandlerContext。 + +![](http://img.dabin-coder.cn/image/netty1.png) + +| 方法 | 描述 | +| --------------- | ---------------------------------------------------------- | +| fireChannelRead | 触发对下一个ChannelInboundHandler的channelRead()方法的调用 | +| alloc | 返回相关联的Channel所配置的ByteBufAllocator | +| bind | 绑定到给定的SocketAddress,并返回ChannelFuture | + +## 异常处理 + +入站异常:在 ChannelInboundHandler 实现 exceptionCaught 方法。 + +出站异常: + +1.添加ChannelFutureListener 到ChannelFuture + +```java + ChannelFuture future = channel.write(someMessage); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete (ChannelFuture f){ + if (!f.isSuccess()) { + f.cause().printStackTrace(); + f.channel().close(); + } + } + }); +``` + +2.添加ChannelFutureListener 到ChannelPromise: + +```java +public class OutboundExceptionHandler extends ChannelOutboundHandlerAdapter { + @Override + public void write(ChannelHandlerContext ctx, Object msg, + ChannelPromise promise) { + promise.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture f) { + if (!f.isSuccess()) { + f.cause().printStackTrace(); + f.channel().close(); + } + } + }); + } +} +``` + + + diff --git a/docs/framework/netty/8-eventloop-thread-model.md b/docs/framework/netty/8-eventloop-thread-model.md new file mode 100644 index 0000000..bd0130e --- /dev/null +++ b/docs/framework/netty/8-eventloop-thread-model.md @@ -0,0 +1,46 @@ +# EventLoop 和线程模型 + +## EventLoop 接口 + +EventLoop 构建在 java.util.concurrent 和 io.netty.channel 之上。EventLoop 继承了 ScheduledExecutorService。EventLoop 由一个永远不会改变的 Thread 驱动,同时任务可以直接提交给 EventLoop 实现。EventLoop 可能服务于多个 Channel。 + +Netty4中所有的 io 操作和事件都由 EventLoop 的 Thread 处理。Netty3只保证入站事件在 EventLoop(io 线程)执行,所有出站事件都由调用线程处理,可能是 io 线程或者别的线程,因此需要在 ChannelHandler 中对出站事件进行同步。 + +Netty 4 中所采用的线程模型,通过在同一个线程中处理某个给定的EventLoop 中所产生的所有事件,解决了这个问题。这提供了一个更加简单的执行体系架构,并且消除了在多个ChannelHandler 中进行同步的需要 + +## 任务调度 + +使用 EventLoop 调度任务: + +```java +Channel ch = ... +ScheduledFuture future = ch.eventLoop().schedule( + new Runnable() { + @Override + public void run() { + //逻辑 + } +}, 60, TimeUnit.SECONDS); +``` + +周期性任务: + +```java +Channel ch = ... +ScheduledFuture future = ch.eventLoop().scheduleAtFixedRate( + new Runnable() { + @Override + public void run() { + //逻辑 + } +}, 60, 60, TimeUnit.SECONDES); +``` + +## 实现细节 + +![](http://img.dabin-coder.cn/image/netty-eventloop执行逻辑.png) + + + + + diff --git a/docs/framework/netty/9-guide.md b/docs/framework/netty/9-guide.md new file mode 100644 index 0000000..93878bb --- /dev/null +++ b/docs/framework/netty/9-guide.md @@ -0,0 +1,57 @@ +# 引导 + +配置 netty 应用程序,使它运行起来。服务器使用一个父 Channel 接受来自客户端的连接,并创建子 Channel 以用于它们之间的通信。客户端只需要一个 Channel 完成所有的网络交互。 + +引导类是 cloneable 的,在引导类实例上调用 clone() 就可以创建多个具有类似配置或者完全相同配置的 Channel。 + +## 引导客户端 + +BootStrap 类被用于客户端或者使用了无连接协议的应用程序中。 + +## 引导服务器 + +![](http://img.dabin-coder.cn/image/ServerBoostrap和ServerChannel.png) + +在基类AbstractBootstrap有handler方法,目的是添加一个handler,监听Bootstrap的动作。 + +在服务端的ServerBootstrap中增加了一个方法childHandler,它的目的是添加handler,用来监听已经连接的客户端的Channel的动作和状态。 + +**handler在初始化时就会执行,而childHandler会在客户端成功connect后才执行。** + +## 在引导过程添加多个 ChannelHandler + +在 handler 传入 ChannelInitializer 的实现类,重写 initChannel 方法,在这个方法中添加多个 ChannelHandler。 + +```java +EventLoopGroup group = new NioEventLoopGroup(); +try { + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(group) + .channel(NioSocketChannel.class)//适用于nio传输的channel类型 + .remoteAddress(new InetSocketAddress(host, port)) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast( + new EchoClientHandler()); + } + }); + ChannelFuture future = bootstrap.connect().sync();//连接到远程节点,阻塞等待 + future.channel().closeFuture().sync();//阻塞直到channel关闭 +} finally { + group.shutdownGracefully().sync();//关闭线程池并释放所有的资源 +} +``` + +## 关闭 + +关闭 EventLoopGroup,它将处理任何挂起的事件和任务,随后释放所有活动的线程。 + +```java +Future future = group.shutdownGracefully();//释放所有资源,关闭Channel +// block until the group has shutdown +future.syncUninterruptibly(); +``` + + + diff --git a/docs/framework/netty/README.md b/docs/framework/netty/README.md new file mode 100644 index 0000000..b741147 --- /dev/null +++ b/docs/framework/netty/README.md @@ -0,0 +1,24 @@ +--- +title: Netty基础 +icon: netty +date: 2022-08-06 +category: netty +star: true +--- + +![](http://img.dabin-coder.cn/image/netty-img.png) + + + +## Netty总结 + +- [简介](./1-overview.md) +- [简单的netty应用程序](./2-make-your-app.md) +- [Netty的组件和设计](./3-component.md) +- [传输](./4-transport.md) +- [ChannelHandler](./6-channel-handler.md) +- [ChannelPipeline接口](./7-channel-pipeline.md) +- [EventLoop和线程模型](./8-eventloop-thread-model.md) +- [引导](./9-guide.md) +- [编解码器](./10-encoder-decoder.md) +- [预置的ChannelHandler和编解码器](./11-preset-channel-handler.md) diff --git "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" b/docs/framework/spring.md similarity index 92% rename from "\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" rename to docs/framework/spring.md index 82c11b5..64ab4ab 100644 --- "a/\346\241\206\346\236\266/Spring\351\235\242\350\257\225\351\242\230.md" +++ b/docs/framework/spring.md @@ -1,9 +1,15 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/Spring总结.jpg) + ## Spring的优点 - 通过控制反转和依赖注入实现**松耦合**。 - 支持**面向切面**的编程,并且把应用业务逻辑和系统服务分开。 - 通过切面和模板减少样板式代码。 -- 声明事物的支持。可以从单调繁冗的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 +- 声明式事务的支持。可以从单调繁冗的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 - 方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hessian、Quartz、MyBatis等)。 - 方便程序的测试。Spring支持Junit4,添加注解便可以测试Spring程序。 @@ -184,7 +190,7 @@ finishBeanFactoryInitialization(beanFactory); ## Bean的生命周期 -![](http://img.dabin-coder.cn/image/bean生命周期.png) +![](http://img.dabin-coder.cn/image/20220709213529.png) 1.调用bean的构造方法创建Bean @@ -194,17 +200,17 @@ finishBeanFactoryInitialization(beanFactory); 4.如果Bean实现了`BeanFactoryAware`接口,Spring将调用`setBeanFactory()`把bean factory设置给Bean -5.如果Bean实现了`ApplicationContextAware`接口,Spring容器将调用`setApplicationContext()`给Bean设置ApplictionContext +5.如果存在`BeanPostProcessor`,Spring将调用它们的`postProcessBeforeInitialization`(预初始化)方法,在Bean初始化前对其进行处理 -6.如果存在`BeanPostProcessor`,Spring将调用它们的`postProcessBeforeInitialization`(预初始化)方法,在Bean初始化前对其进行处理 +6.如果Bean实现了`InitializingBean`接口,Spring将调用它的`afterPropertiesSet`方法,然后调用xml定义的 init-method 方法,两个方法作用类似,都是在初始化 bean 的时候执行 -7.如果Bean实现了`InitializingBean`接口,Spring将调用它的`afterPropertiesSet`方法,然后调用xml定义的 init-method 方法,两个方法作用类似,都是在初始化 bean 的时候执行 +7.如果存在`BeanPostProcessor`,Spring将调用它们的`postProcessAfterInitialization`(后初始化)方法,在Bean初始化后对其进行处理 -8.如果存在`BeanPostProcessor`,Spring将调用它们的`postProcessAfterInitialization`(后初始化)方法,在Bean初始化后对其进行处理 +8.Bean初始化完成,供应用使用,这里分两种情况: -9.Bean初始化完成,供应用使用,直到应用被销毁 +8.1 如果Bean为单例的话,那么容器会返回Bean给用户,并存入缓存池。如果Bean实现了`DisposableBean`接口,Spring将调用它的`destory`方法,然后调用在xml中定义的 `destory-method`方法,这两个方法作用类似,都是在Bean实例销毁前执行。 -10.如果Bean实现了`DisposableBean`接口,Spring将调用它的`destory`方法,然后调用在xml中定义的 `destory-method`方法,这两个方法作用类似,都是在Bean实例销毁前执行 +8.2 如果Bean是多例的话,容器将Bean返回给用户,剩下的生命周期由用户控制。 ```java public interface BeanPostProcessor { @@ -270,9 +276,29 @@ public class SqlSessionFactoryBean implements FactoryBean, In Spring 将会在应用启动时创建 `SqlSessionFactory`,并使用 `sqlSessionFactory` 这个名字存储起来。 +## BeanFactory和ApplicationContext有什么区别? + +BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。 + +两者区别如下: + +1、功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。 + +ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。 + +2、加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。 + +而ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。 + +相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。 + +3、创建方式的区别。BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。 + +4、注册方式的区别。BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。 + ## Bean注入容器有哪些方式? -1、@Configuration + @Bean +1、**@Configuration + @Bean** @Configuration用来声明一个配置类,然后使用 @Bean 注解,用于声明一个bean,将其加入到Spring容器中。 @@ -288,7 +314,7 @@ public class MyConfiguration { } ``` -2、通过包扫描特定注解的方式 +2、**通过包扫描特定注解的方式** @ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有特定注解的bean,然后加至容器中。 @@ -310,7 +336,7 @@ public class Demo1 { } ``` -3、@Import注解导入 +3、**@Import注解导入** @Import注解平时开发用的不多,但是也是非常重要的,在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。 @@ -327,7 +353,7 @@ public class App { } ``` -4、实现BeanDefinitionRegistryPostProcessor进行后置处理。 +4、**实现BeanDefinitionRegistryPostProcessor进行后置处理。** 在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。 @@ -358,7 +384,7 @@ class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPos } ``` -5、使用FactoryBean接口 +5、**使用FactoryBean接口** 如下图代码,使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,这里没有向容器中直接注入 Person,而是注入 PersonFactoryBean,然后从容器中拿Person这个类型的bean。 @@ -669,11 +695,15 @@ public class OrderServiceImpl implements OrderService { ## Spring怎么解决循环依赖的问题? -构造器注入的循环依赖:Spring处理不了,直接抛出`BeanCurrentlylnCreationException`异常。 +首先,有两种Bean注入的方式。 -单例模式下属性注入的循环依赖:通过三级缓存处理循环依赖。 +构造器注入和属性注入。 -非单例循环依赖:无法处理。 +对于构造器注入的循环依赖,Spring处理不了,会直接抛出`BeanCurrentlylnCreationException`异常。 + +对于属性注入的循环依赖(单例模式下),是通过三级缓存处理来循环依赖的。 + +而非单例对象的循环依赖,则无法处理。 下面分析单例模式下属性注入的循环依赖是怎么处理的: @@ -913,4 +943,6 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple + + ![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" b/docs/framework/springboot.md similarity index 74% rename from "\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" rename to docs/framework/springboot.md index 7e70a4c..b12e0b1 100644 --- "a/\346\241\206\346\236\266/SpringBoot\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ b/docs/framework/springboot.md @@ -1,3 +1,7 @@ +--- +sidebar: heading +--- + ## Springboot的优点 - 内置servlet容器,不需要在服务器部署 tomcat。只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目 @@ -22,6 +26,16 @@ starter提供了一个自动化配置类,一般命名为 XXXAutoConfiguration 3. spring-boot-starter-data-Redis :提供 Redis 。 4. mybatis-spring-boot-starter :提供 MyBatis 。 +## Spring Boot 的核心注解是哪个? + +启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解: + +- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。 + +- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。 + +- @ComponentScan:Spring组件扫描。 + ## 自动配置原理 SpringBoot实现自动配置原理图解: @@ -291,10 +305,59 @@ public class SpringbootDemoApplication { hello.msg=大彬 ``` -## @Value原理 +## @Value注解的原理 @Value的解析就是在bean初始化阶段。BeanPostProcessor定义了bean初始化前后用户可以对bean进行操作的接口方法,它的一个重要实现类`AutowiredAnnotationBeanPostProcessor`为bean中的@Autowired和@Value注解的注入功能提供支持。 +## Spring Boot 需要独立的容器运行吗? + +不需要,内置了 Tomcat/ Jetty 等容器。 + +## Spring Boot 支持哪些日志框架? + +Spring Boot 支持 Java Util Logging, Log4j2, Lockback 作为日志框架,如果你使用 Starters 启动器,Spring Boot 将使用 Logback 作为默认日志框架,但是不管是那种日志框架他都支持将配置文件输出到控制台或者文件中。 + +## YAML 配置的优势在哪里 ? + +YAML 配置和传统的 properties 配置相比之下,有这些优势: + +- 配置有序 +- 简洁明了,支持数组,数组中的元素可以是基本数据类型也可以是对象 + +缺点就是不支持 @PropertySource 注解导入自定义的 YAML 配置。 + +## 什么是 Spring Profiles? + +在项目的开发中,有些配置文件在开发、测试或者生产等不同环境中可能是不同的,例如数据库连接、redis的配置等等。那我们如何在不同环境中自动实现配置的切换呢?Spring给我们提供了profiles机制给我们提供的就是来回切换配置文件的功能 + +Spring Profiles 允许用户根据配置文件(dev,test,prod 等)来注册 bean。因此,当应用程序在开发中运行时,只有某些 bean 可以加载,而在 PRODUCTION中,某些其他 bean 可以加载。假设我们的要求是 Swagger 文档仅适用于 QA 环境,并且禁用所有其他文档。这可以使用配置文件来完成。Spring Boot 使得使用配置文件非常简单。 + +## SpringBoot多数据源事务如何管理 + +第一种方式是在service层的@TransactionManager中使用transactionManager指定DataSourceConfig中配置的事务。 + +第二种是使用jta-atomikos实现分布式事务管理。 + +## spring-boot-starter-parent 有什么用 ? + +新创建一个 Spring Boot 项目,默认都是有 parent 的,这个 parent 就是 spring-boot-starter-parent ,spring-boot-starter-parent 主要有如下作用: + +1. 定义了 Java 编译版本。 +2. 使用 UTF-8 格式编码。 +3. 执行打包操作的配置。 +4. 自动化的资源过滤。 +5. 自动化的插件配置。 +6. 针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。 + +## Spring Boot 打成的 jar 和普通的 jar 有什么区别 ? + +- Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 `java -jar xxx.jar` 命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。 +- Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 `\BOOT-INF\classes` 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。 + +## SpringBoot多数据源拆分的思路 + +先在properties配置文件中配置两个数据源,创建分包mapper,使用@ConfigurationProperties读取properties中的配置,使用@MapperScan注册到对应的mapper包中 。 + ![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git a/docs/framework/springcloud-interview.md b/docs/framework/springcloud-interview.md new file mode 100644 index 0000000..7046b3c --- /dev/null +++ b/docs/framework/springcloud-interview.md @@ -0,0 +1,249 @@ +--- +sidebar: heading +--- + + +今天给大家分享SpringCloud高频面试题。 + +# Spring Cloud核心知识总结 + +下面是一张Spring Cloud核心组件关系图: + +![](http://img.dabin-coder.cn/image/springcloud1.png) + + + +从这张图中,其实我们是可以获取很多信息的,希望大家细细品尝。 + +话不多说,我们直接开始 Spring Cloud 连环炮。 + + +## 1、什么是Spring Cloud ? + +Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。 + +## 2、什么是微服务? + +微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分为一组小的服务,每个服务运行在其独立的自己的进程中,服务之间相互协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API),每个服务都围绕着具体的业务进行构建,并且能够被独立的构建在生产环境、类生产环境等。另外,应避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。 + +通俗地来讲: + +微服务就是一个独立的职责单一的服务应用程序。在 intellij idea 工具里面就是用maven开发的一个个独立的module,具体就是使用springboot 开发的一个小的模块,处理单一专业的业务逻辑,一个模块只做一个事情。 + +微服务强调的是服务大小,关注的是某一个点,具体解决某一个问题/落地对应的一个服务应用,可以看做是idea 里面一个 module。 + +## 3、Spring Cloud有什么优势 + +使用 Spring Boot 开发分布式微服务时,我们面临以下问题 + +- 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。 +- 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。 +- 冗余-分布式系统中的冗余问题。 +- 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。 +- 性能-问题 由于各种运营开销导致的性能问题。 +- 部署复杂性-Devops 技能的要求。 + +## 4、微服务之间如何独立通讯的? + +同步通信:dobbo通过 RPC 远程过程调用、springcloud通过 REST 接口json调用等。 + +异步:消息队列,如:`RabbitMq`、`ActiveM`、`Kafka`等消息队列。 + +## 5、 **什么是服务熔断?什么是服务降级?** + +熔断机制是应对雪崩效应的一种微服务链路保护机制。当某个微服务不可用或者响应时间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在Spring Cloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内调用20次,如果失败,就会启动熔断机制。 + +服务降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然水平下降,但好歹可用,比直接挂掉强。 + +`Hystrix`相关注解`@EnableHystrix`:开启熔断 `@HystrixCommand(fallbackMethod=”XXX”)`,声明一个失败回滚处理函数`XXX`,当被注解的方法执行超时(默认是1000毫秒),就会执行`fallback`函数,返回错误提示。 + +## 6、 请说说Eureka和zookeeper 的区别? + +Zookeeper保证了CP,Eureka保证了AP。 + +> A:高可用 +> +> C:一致性 +> +> P:分区容错性 + +1.当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。 + +2.Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现时发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点没有正常的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况: + +①、Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。 + +②、Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用) + +③、当网络稳定时,当前实例新的注册信息会被同步到其他节点。 + +因此,Eureka可以很好地应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪 + +## 7、SpringBoot和SpringCloud的区别? + +SpringBoot专注于快速方便得开发单个个体微服务。 + +SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来, + +为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 + +SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系. + +SpringBoot专注于快速、方便得开发单个微服务个体,SpringCloud关注全局的服务治理框架。 + +## 8、负载平衡的意义什么? + +在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一资源 的过载。使用多个组件进行负载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。 + +## 9、什么是Hystrix?它如何实现容错? + +Hystrix是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现故障是不可避免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。 + +通常对于使用微服务架构开发的系统,涉及到许多微服务。这些微服务彼此协作。 + +思考一下微服务: + +![](http://img.dabin-coder.cn/image/springcloud-microservice.png) + +假设如果上图中的微服务9失败了,那么使用传统方法我们将传播一个异常。但这仍然会导致整个系统崩溃。 + +随着微服务数量的增加,这个问题变得更加复杂。微服务的数量可以高达1000.这是hystrix出现的地方 我们将使用Hystrix在这种情况下的Fallback方法功能。我们有两个服务employee-consumer使用由employee-consumer公开的服务。 + +简化图如下所示 + +![](http://img.dabin-coder.cn/image/springcloud2.png) + +现在假设由于某种原因,employee-producer公开的服务会抛出异常。我们在这种情况下使用Hystrix定义了一个回退方法。这种后备方法应该具有与公开服务相同的返回类型。如果暴露服务中出现异常,则回退方法将返回一些值。 + +## 10、什么是Hystrix断路器?我们需要它吗? + +由于某些原因,employee-consumer公开服务会引发异常。在这种情况下使用Hystrix我们定义了一个回退方法。如果在公开服务中发生异常,则回退方法返回一些默认值。 + +![](http://img.dabin-coder.cn/image/springcloud3.png) + + + +如果firstPage method() 中的异常继续发生,则Hystrix电路将中断,并且员工使用者将一起跳过firtsPage方法,并直接调用回退方法。断路器的目的是给第一页方法或第一页方法可能调用的其他方法留出时间,并导致异常恢复。可能发生的情况是,在负载较小的情况下,导致异常的问题有更好的恢复机会 。 + + + +## 11、说说 RPC 的实现原理 + +首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编 解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服 务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。 + +## 12,eureka自我保护机制是什么? + +当Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁启动关闭客户端)节点会进入自我保护模式,保护注册信息,不再删除注册数据,故障恢复时,自动退出自我保护模式。 + +## 13,什么是Ribbon? + +ribbon是一个负载均衡客户端,可以很好地控制htt和tcp的一些行为。`feign默认集成了ribbon`。 + +## 14,什么是 Netflix Feign?它的优点是什么? + +Feign 是受到 Retrofit,JAXRS-2.0 和 WebSocket 启发的 java 客户端联编程序。 + +Feign 的第一个目标是将约束分母的复杂性统一到 http apis,而不考虑其稳定性。 + +特点: + +- Feign 采用的是基于接口的注解 +- Feign 整合了ribbon,具有负载均衡的能力 +- 整合了Hystrix,具有熔断的能力 + +使用方式 + +- 添加pom依赖。 +- 启动类添加`@EnableFeignClients` +- 定义一个接口`@FeignClient(name=“xxx”)`指定调用哪个服务 + +## 15, Ribbon和Feign的区别? + +1.**启动类注解不同**,Ribbon是@RibbonClient feign的是@EnableFeignClients;2.**服务指定的位置不同**,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明;3.**调用方式不同**,Ribbon需要自己构建http请求,模拟http请求。 + +## 16、Spring Cloud 的核心组件有哪些? + +- Eureka:服务注册于发现。 +- Feign:基于动态代理机制,根据注解和选择的机器,拼接请求 url 地址,发起请求。 +- Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。 +- Hystrix:提供线程池,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题。 +- Zuul:网关管理,由 Zuul 网关转发请求给对应的服务。 + +## 17、说说Spring Boot和Spring Cloud的关系 + +Spring Boot是Spring推出用于解决传统框架配置文件冗余,装配组件繁杂的基于Maven的解决方案,旨在快速搭建单个微服务而Spring Cloud专注于解决各个微服务之间的协调与配置,服务之间的通信,熔断,负载均衡等技术维度并相同,并且Spring Cloud是依赖于Spring Boot的,而Spring Boot并不是依赖与Spring Cloud,甚至还可以和Dubbo进行优秀的整合开发 + +总结 + +- SpringBoot专注于快速方便的开发单个个体的微服务 +- SpringCloud是关注全局的微服务协调整理治理框架,整合并管理各个微服务,为各个微服务之间提供,配置管理,服务发现,断路器,路由,事件总线等集成服务 +- Spring Boot不依赖于Spring Cloud,Spring Cloud依赖于Spring Boot,属于依赖关系 +- Spring Boot专注于快速,方便的开发单个的微服务个体,Spring Cloud关注全局的服务治理框架 + +## 18、说说微服务之间是如何独立通讯的? + +#### 远程过程调用(Remote Procedure Invocation) + +也就是我们常说的服务的注册与发现,直接通过远程过程调用来访问别的service。 + +**优点**:简单,常见,因为没有中间件代理,系统更简单 + +**缺点**:只支持请求/响应的模式,不支持别的,比如通知、请求/异步响应、发布/订阅、发布/异步响应,降低了可用性,因为客户端和服务端在请求过程中必须都是可用的。 + +#### 消息 + +使用异步消息来做服务间通信。服务间通过消息管道来交换消息,从而通信。 + +**优点**:把客户端和服务端解耦,更松耦合,提高可用性,因为消息中间件缓存了消息,直到消费者可以消费, 支持很多通信机制比如通知、请求/异步响应、发布/订阅、发布/异步响应。 + +**缺点**:消息中间件有额外的复杂。 + +## 19、Spring Cloud如何实现服务的注册? + +服务发布时,指定对应的服务名,将服务注册到 注册中心(`Eureka 、Zookeeper)`。 + +注册中心加`@EnableEurekaServer`,服务用`@EnableDiscoveryClient`,然后用ribbon或feign进行服务直接的调用发现。 + +## 20、什么是服务熔断? + +在复杂的分布式系统中,微服务之间的相互调用,有可能出现各种各样的原因导致服务的阻塞,在高并发场景下,服务的阻塞意味着线程的阻塞,导致当前线程不可用,服务器的线程全部阻塞,导致服务器崩溃,由于服务之间的调用关系是同步的,会对整个微服务系统造成服务雪崩 + +为了解决某个微服务的调用响应时间过长或者不可用进而占用越来越多的系统资源引起雪崩效应就需要进行服务熔断和服务降级处理。 + +所谓的服务熔断指的是某个服务故障或异常一起类似显示世界中的“保险丝"当某个异常条件被触发就直接熔断整个服务,而不是一直等到此服务超时。 + +服务熔断就是相当于我们电闸的保险丝,一旦发生服务雪崩的,就会熔断整个服务,通过维护一个自己的线程池,当线程达到阈值的时候就启动服务降级,如果其他请求继续访问就直接返回fallback的默认值 + +## 21、了解Eureka自我保护机制吗? + +当Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁启动关闭客户端)节点会进入自我保护模式,保护注册信息,不再删除注册数据,故障恢复时,自动退出自我保护模式。 + +## 22、熟悉 Spring Cloud Bus 吗? + +spring cloud bus 将分布式的节点用轻量的消息代理连接起来,它可以用于广播配置文件的更改或者服务直接的通讯,也可用于监控。如果修改了配置文件,发送一次请求,所有的客户端便会重新读取配置文件。 + +## 23、Spring Cloud 断路器有什么作用? + +当一个服务调用另一个服务由于网络原因或自身原因出现问题,调用者就会等待被调用者的响应,当更多的服务请求到这些资源导致更多的请求等待,发生连锁效应(雪崩效应)。一段时间内 达到一定的次数无法调用 并且多次监测没有恢复的迹象,这时候断路器完全打开 那么下次请求就不会请求到该服务。 + +半开:短时间内 有恢复迹象 断路器会将部分请求发给该服务,正常调用时 断路器关闭。关闭:当服务一直处于正常状态 能正常调用。 + +## 24、了解Spring Cloud Config 吗? + +在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件`Spring Cloud Config`,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。 + +在`Spring Cloud Config` 组件中,分两个角色,一是config server,二是config client。 + +使用方式: + +- 添加pom依赖 +- 配置文件添加相关配置 +- 启动类添加注解@EnableConfigServer + +## 25、说说你对Spring Cloud Gateway的理解 + +Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。 + +使用了一个RouteLocatorBuilder的bean去创建路由,除了创建路由RouteLocatorBuilder可以让你添加各种predicates和filters,predicates断言的意思,顾名思义就是根据具体的请求的规则,由具体的route去处理,filters是各种过滤器,用来对请求做各种判断和修改。 + +> 参考:http://1pgqu.cn/M0NZo \ No newline at end of file diff --git "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" b/docs/framework/springcloud-overview.md similarity index 96% rename from "\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" rename to docs/framework/springcloud-overview.md index aedbd7f..bdf3f70 100644 --- "a/\346\241\206\346\236\266/SpringCloud\345\276\256\346\234\215\345\212\241\345\256\236\346\210\230.md" +++ b/docs/framework/springcloud-overview.md @@ -1,4 +1,4 @@ -## 基础知识 +# 基础知识 微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行。 @@ -46,7 +46,7 @@ springcloud是一个基于Spring Boot实现的微服务架构开发工具。spri spring-boot-starter-actuator:该模块能够自动为Spring Boot 构建的应用提供一系列用于监控的端点。 -## 说说对SpringBoot 和SpringCloud的理解 +# 说说对SpringBoot 和SpringCloud的理解 - SpringBoot专注于快速方便的开发单个个体微服务。 - SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 @@ -55,19 +55,19 @@ spring-boot-starter-actuator:该模块能够自动为Spring Boot 构建的应 Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。 -## Spring Cloud Eureka +# Spring Cloud Eureka Spring Cloud Eureka实现微服务架构中的服务治理功能,使用 Netflix Eureka 实现服务注册与发现,包含客户端组件和服务端组件。服务治理是微服务架构中最为核心和基础的模块。 Eureka 服务端就是服务注册中心。Eureka 客户端用于处理服务的注册和发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中, 在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。 -### 服务注册与发现 +## 服务注册与发现 服务注册:在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,这样当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用。 服务发现:服务间的调用不是通过直接调用具体的实例地址,而是通过服务名发起调用。调用方需要向服务注册中心咨询服务,获取服务的实例清单,从而访问具体的服务实例。 -### 代码实例 +## 代码实例 添加依赖: @@ -110,14 +110,14 @@ eureka: 运行EurekaServerApplication,访问地址http://localhost:8001/可以看到Eureka注册中心的界面。 -### 高可用注册中心 +## 高可用注册中心 注册中心互相注册,形成一组互相注册的服务注册中心, 以实现服务清单的互相同步, 达到高可用的效果。 创建application-replica1.yml和 application-replica2.yml: ```yaml -# application-replica1.yml +-- application-replica1.yml server: port: 8002 spring: @@ -133,7 +133,7 @@ eureka: register-with-eureka: true -# application-replica2.yml +-- application-replica2.yml server: port: 8002 spring: @@ -172,7 +172,7 @@ eureka.client.serviceUrl.defaultZone=http://localhost:8002/eureka/, http://local -## Spring Cloud Ribbon +# Spring Cloud Ribbon Spring Cloud Ribbon 是基于HTTP和TCP的客户端负载均衡工具,基于Netflix Ribbon实现。Spring Cloud Ribbon 会**将REST请求转换为客户端负载均衡的服务调用**。 @@ -183,11 +183,11 @@ Spring Cloud Ribbon 是基于HTTP和TCP的客户端负载均衡工具,基于Ne 1. 服务提供者启动多个服务实例注册到服务注册中心; 2. 服务消费者直接通过调用被@LoadBalanced 注解修饰过的RestTemplate 来实现面向服务的接口调用。 -### RestTemplate +## RestTemplate RestTemplate是一个HTTP客户端,使用它我们可以方便的调用HTTP接口,支持GET、POST、PUT、DELETE等方法。 -### 代码实例 +## 代码实例 创建hello-service模块,用于给 Ribbon 提供服务调用。 @@ -304,11 +304,11 @@ com.tyson.helloservice.HelloController : /hello, host:DESKTOP-8F30VS1, service -## Spring Cloud Hystrix +# Spring Cloud Hystrix 在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于**长时间得不到响应而占用线程**,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。 -### 代码实例 +## 代码实例 创建 hystrix-service 模块。添加相关依赖: @@ -386,11 +386,11 @@ public CommonResult getDefaultUser(@PathVariable Long id) { -## Spring Cloud Feign +# Spring Cloud Feign 基于Netflix Feign 实现,整合了Spring Cloud Ribbon 与Spring Cloud Hystrix, 它提供了一种声明式服务调用的方式。 -### 负载均衡功能 +## 负载均衡功能 添加依赖: @@ -469,7 +469,7 @@ public class HelloFeignController { 启动eureka-service,多个hello-service,feign-service服务,多次调用http://localhost:8701/feign/hello/进行测试。 -### 服务降级功能 +## 服务降级功能 开启Hystrix功能: @@ -506,7 +506,7 @@ public interface HelloService { -## Spring Cloud Zuul +# Spring Cloud Zuul API网关,为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。 @@ -554,7 +554,7 @@ public class ZuulProxyApplication { } ``` -### 路由规则 +## 路由规则 将匹配`/userService/**`的请求路由到user-service服务上去,匹配`/feignService/**`的请求路由到feign-service上去。: @@ -569,7 +569,7 @@ zuul: 访问`http://localhost:8801/userService/user/1`可以发现请求路由到了user-service上了。 -### 访问前缀 +## 访问前缀 给网关路径添加前缀。 @@ -580,7 +580,7 @@ zuul: 需要访问`http://localhost:8801/proxy/user-service/user/1`才能访问到user-service中的接口。 -### header过滤 +## header过滤 默认情况下, Spring Cloud Zuul在请求路由时, 会过滤掉HTTP请求头信息中的一些敏感信息, 防止它们被传递到下游服务。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,包括Cookie、Set-Cookie、Authorization三个属性。这样的话,由于Cookie等信息被过滤掉,会导致应用无法登录和鉴权。为了避免这种情况,可以将敏感头设置为空。 @@ -598,7 +598,7 @@ zuul.routes..customSensitiveHeaders=true zuul.routes..sensitiveHeaders= ``` -### 重定向 +## 重定向 [zuul重定向问题](https://blog.csdn.net/wo18237095579/article/details/83540829) @@ -606,11 +606,11 @@ zuul.routes..sensitiveHeaders= ```yaml zuul: - # 此处解决后端服务重定向导致用户浏览的 host 变成 后端服务的 host 问题 + -- 此处解决后端服务重定向导致用户浏览的 host 变成 后端服务的 host 问题 add-host-header: true ``` -### 查看路由信息 +## 查看路由信息 通过SpringBoot Actuator来查看Zuul中的路由信息。 @@ -660,11 +660,11 @@ management: } ``` -### 过滤器 +## 过滤器 路由与过滤是Zuul的两大核心功能,路由功能负责将外部请求转发到具体的服务实例上去,是实现统一访问入口的基础,过滤功能负责对请求过程进行额外的处理,是请求校验过滤及服务聚合的基础。 -#### 过滤器类型 +**过滤器类型** Zuul中有以下几种典型的过滤器类型。 @@ -673,7 +673,7 @@ Zuul中有以下几种典型的过滤器类型。 - post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能; - error:请求在其他阶段发生错误时执行。 -#### 自定义过滤器 +**自定义过滤器** 添加PreLogFilter类继承ZuulFilter。在请求被转发到目标服务前打印请求日志。 @@ -728,7 +728,7 @@ public class PreLogFilter extends ZuulFilter { Remote host:0:0:0:0:0:0:0:1,method:GET,uri:/proxy/userService/user/1 ``` -#### 禁用过滤器 +**禁用过滤器** 在application.yml配置: @@ -739,7 +739,7 @@ zuul: disable: true ``` -### Ribbon和Hystrix的支持 +## Ribbon和Hystrix的支持 由于Zuul自动集成了Ribbon和Hystrix,所以Zuul天生就有负载均衡和服务容错能力,我们可以通过Ribbon和Hystrix的配置来配置Zuul中的相应功能。 @@ -763,7 +763,7 @@ zuul: ReadTimeout: 3000 #服务请求处理超时时间(毫秒) ``` -### 常用配置 +## 常用配置 ```yaml zuul: @@ -784,7 +784,7 @@ zuul: -## Spring Cloud Gateway +# Spring Cloud Gateway 为 SpringBoot 应用提供了API网关支持,具有强大的智能路由与过滤器功能。 @@ -797,7 +797,7 @@ zuul: ``` -### 配置路由 +## 配置路由 Gateway 提供了两种不同的方式用于配置路由,一种是通过yml文件来配置,另一种是通过Java Bean来配置。 @@ -840,11 +840,11 @@ Gateway 提供了两种不同的方式用于配置路由,一种是通过yml文 使用http://localhost:9201/user/getByUsername?username=macro测试。 -### Route Predicate +## Route Predicate Spring Cloud Gateway包括许多内置的Route Predicate工厂。 所有这些Predicate都与HTTP请求的不同属性匹配。 多个Route Predicate工厂可以进行组合。 -#### After Route Predicate +**After** Route Predicate 在指定时间之后的请求会匹配该路由。 @@ -859,7 +859,7 @@ spring: - After=2019-09-24T16:30:00+08:00[Asia/Shanghai] ``` -#### Cookie Route Predicate +**Cookie Route Predicate** 带有指定Cookie的请求会匹配该路由。 @@ -880,7 +880,7 @@ spring: curl http://localhost:9201/user/1 --cookie "username=tyson" ``` -#### Header Route Predicate +**Header Route Predicate** 带有指定请求头的请求会匹配该路由。 @@ -901,7 +901,7 @@ spring: curl http://localhost:9201/user/1 -H "X-Request-Id:123" ``` -#### Host Route Predicate +**Host Route Predicate** 带有指定Host的请求会匹配该路由。 @@ -922,11 +922,11 @@ spring: curl http://localhost:9201/user/1 -H "Host:www.macrozheng.com" ``` -### Route Filter +## Route Filter 路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。 -#### AddRequestParameter GatewayFilter +**AddRequestParameter GatewayFilter** 给请求添加参数的过滤器。 @@ -955,7 +955,7 @@ curl http://localhost:9201/user/getByUsername curl http://localhost:8201/user/getByUsername?username=macro ``` -#### StripPrefix GatewayFilter +**StripPrefix GatewayFilter** 对指定数量的路径前缀进行去除的过滤器。 @@ -980,7 +980,7 @@ curl http://localhost:9201/user-service/a/user/1 相当于发起请求:curl http://localhost:8201/user/1 -#### PrefixPate GatewayFilter +**PrefixPate GatewayFilter** 与StripPrefix过滤器恰好相反,会对原有路径进行增加操作的过滤器。 @@ -999,7 +999,7 @@ spring: 以上配置会对所有GET请求添加`/user`路径前缀。 -#### Hystrix GatewayFilter +**Hystrix GatewayFilter** 将断路器功能添加到网关路由中,使服务免受级联故障的影响,并提供服务降级处理。 @@ -1029,7 +1029,7 @@ public class FallbackController { } ``` -#### RequestRateLimiter GatewayFilter +**RequestRateLimiter GatewayFilter** 用于限流,使用RateLimiter实现来确定是否允许当前请求继续进行,如果请求太大默认会返回HTTP 429-太多请求状态。 @@ -1089,7 +1089,7 @@ logging: 多次请求该地址:http://localhost:9201/user/1 ,会返回状态码为429的错误。 -#### Retry GatewayFilter +**Retry GatewayFilter** 对路由请求进行重试的过滤器,可以根据路由请求返回的HTTP状态码来确定是否进行重试。 @@ -1114,9 +1114,9 @@ spring: basedOnPreviousValue: false ``` -### 结合注册中心使用 +## 结合注册中心使用 -#### 使用动态路由 +**使用动态路由** 以服务名为路径创建动态路由。 @@ -1154,7 +1154,7 @@ logging: 使用application-eureka.yml配置文件启动api-gateway服务,访问http://localhost:9201/user-service/user/1 ,可以路由到user-service的http://localhost:8201/user/1 处。 -#### 使用过滤器 +**使用过滤器** 在结合注册中心使用过滤器的时候,需要注意的是uri的协议为`lb`,这样才能启用Gateway的负载均衡功能。 @@ -1191,11 +1191,11 @@ logging: -## Spring Cloud Config +# Spring Cloud Config Spring Cloud Config分为服务端和客户端。服务端也称为分布式配置中心,它是个独立的微服务应用,用于从配置仓库获取配置信息供客户端使用。而客户端则是微服务架构中的各个微服务应用或者基础设施,可以从配置中心获取配置信息,在启动时加载配置。Spring Cloud Config 的配置中心默认采用Git来存储配置信息。 -### 准备配置信息 +## 准备配置信息 在Git仓库中添加好配置文件。 @@ -1206,7 +1206,7 @@ config: info: "config info for dev(master)" ``` -### 配置中心 +## 配置中心 创建config-server模块,在pom.xml中添加依赖: @@ -1256,7 +1256,7 @@ public class ConfigServerApplication { } ``` -### 获取配置信息 +## 获取配置信息 访问http://localhost:8901/master/config-dev来获取master分支上dev环境的配置信息。 @@ -1336,7 +1336,7 @@ public class ConfigClientController { 启动config-client服务,访问http://localhost:9001/configInfo,可以获取到dev分支下dev环境的配置。 -### 刷新配置 +## 刷新配置 当Git仓库中的配置信息更改后,我们可以通过SpringBoot Actuator的refresh端点来刷新客户端配置信息。 @@ -1380,7 +1380,7 @@ public class ConfigClientController { 访问http://localhost:9001/configInfo进行测试,可以发现配置信息已经刷新。 -### 安全认证 +## 安全认证 创建config-security-server模块,在pom.xml中添加相关依赖: @@ -1439,7 +1439,7 @@ spring: 使用application-security.yml启动config-client服务。访问http://localhost:9002/configInfo进行测试。 -### 配置中心集群 +## 配置中心集群 在微服务架构中,所有服务都从配置中心获取配置,配置中心一旦宕机,会发生很严重的问题。通过搭建配置中心集群避免该问题。 @@ -1465,13 +1465,13 @@ spring: -## Spring Cloud Bus +# Spring Cloud Bus 我们通常会使用消息代理来构建一个主题,然后把微服务架构中的所有服务都连接到这个主题上去,当我们向该主题发送消息时,所有订阅该主题的服务都会收到消息并进行消费。使用 Spring Cloud Bus 可以方便地构建起这套机制,所以 Spring Cloud Bus 又被称为消息总线。Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。 -## Spring Cloud Security +# Spring Cloud Security Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录、令牌中继、令牌交换等功能。 diff --git a/docs/framework/springcloud/1-basic.md b/docs/framework/springcloud/1-basic.md new file mode 100644 index 0000000..5764ebe --- /dev/null +++ b/docs/framework/springcloud/1-basic.md @@ -0,0 +1,48 @@ +# 基础知识 + +微服务是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行。 + +[从单体应用到微服务](https://www.zhihu.com/question/65502802/answer/802678798) + +单体系统的缺点: + +1. 修改一个小功能,就需要将整个系统重新部署上线,影响其他功能的运行; +2. 功能模块互相依赖,强耦合,扩展困难。如果出现性能瓶颈,需要对整体应用进行升级,虽然影响性能的可能只是其中一个小模块; + +单体系统的优点: + +1. 容易部署,程序单一,不存在分布式集群的复杂部署环境; +2. 容易测试,没有复杂的服务调用关系。 + +微服务的优点: + +1. 不同的服务可以使用不同的技术; +2. 隔离性。一个服务不可用不会导致其他服务不可用; +3. 可扩展性。某个服务出现性能瓶颈,只需对此服务进行升级即可; +4. 简化部署。服务的部署是独立的,哪个服务出现问题,只需对此服务进行修改重新部署; + +微服务的缺点: + +1. 网络调用频繁。性能相对函数调用较差。 +2. 运维成本增加。系统由多个独立运行的微服务构成,需要设计一个良好的监控系统对各个微服务的运行状态进行监控。 + +springcloud是一个基于Spring Boot实现的微服务架构开发工具。spring cloud包含多个子项目: + +- Spring Cloud Config:配置管理工具,支持使用Git存储配置内容, 可以使用它实现应用配置的外部化存储, 并支持客户端配置信息刷新、加密/解密配置内容等。 +- Spring Cloud Netflix:核心 组件,对多个Netflix OSS开源套件进行整合。 + - Eureka: 服务治理组件, 包含服务注册中心、服务注册与发现机制的实现。 + - Hystrix: 容错管理组件,实现断路器模式, 帮助服务依赖中出现的延迟和为故障提供强大的容错能力。 + - Ribbon: 客户端负载均衡的服务调用组件。 + - Feign: 基于Ribbon 和Hystrix 的声明式服务调用组件。 + - Zuul: 网关组件, 提供智能路由、访问过滤等功能。 + - Archaius: 外部化配置组件。 +- Spring Cloud Bus: 事件、消息总线, 用于传播集群中的状态变化或事件, 以触发后续的处理, 比如用来动态刷新配置等。 +- Spring Cloud Cluster: 针对ZooKeeper、Redis、Hazelcast、Consul 的选举算法和通用状态模式的实现。 +- Spring Cloud Consul: 服务发现与配置管理工具。 +- Spring Cloud ZooKeeper: 基于ZooKeeper 的服务发现与配置管理组件。 +- Spring Cloud Security:Spring Security组件封装,提供用户验证和权限验证,一般与Spring Security OAuth2 组一起使用,通过搭建授权服务,验证Token或者JWT这种形式对整个微服务系统进行安全验证 +- Spring Cloud Sleuth:分布式链路追踪组件,他分封装了Dapper、Zipkin、Kibana 的组件 +- Spring Cloud Stream:Spring Cloud框架的数据流操作包,可以封装RabbitMq,ActiveMq,Kafka,Redis等消息组件,利用Spring Cloud Stream可以实现消息的接收和发送 + +spring-boot-starter-actuator:该模块能够自动为Spring Boot 构建的应用提供一系列用于监控的端点。 + diff --git a/docs/framework/springcloud/10-bus.md b/docs/framework/springcloud/10-bus.md new file mode 100644 index 0000000..6f658f3 --- /dev/null +++ b/docs/framework/springcloud/10-bus.md @@ -0,0 +1,6 @@ +# Spring Cloud Bus + +我们通常会使用消息代理来构建一个主题,然后把微服务架构中的所有服务都连接到这个主题上去,当我们向该主题发送消息时,所有订阅该主题的服务都会收到消息并进行消费。使用 Spring Cloud Bus 可以方便地构建起这套机制,所以 Spring Cloud Bus 又被称为消息总线。Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。 + + + diff --git a/docs/framework/springcloud/11-security.md b/docs/framework/springcloud/11-security.md new file mode 100644 index 0000000..beefbe8 --- /dev/null +++ b/docs/framework/springcloud/11-security.md @@ -0,0 +1,28 @@ +# Spring Cloud Security + +Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录、令牌中继、令牌交换等功能。 + +OAuth 是一个验证授权(Authorization)的开放标准,所有人都有基于这个标准实现自己的OAuth。在OAuth之前,使用的是`HTTP Basic Authentication`(在浏览网页时候,浏览器会弹出一个登录验证的对话框),需要用户输入用户名和密码的形式进行验证, 这种形式是不安全的。OAuth的出现就是为了解决访问资源的安全性以及灵活性。OAuth使得第三方应用对资源的访问更加安全。 + +适用场景:[OAuth 2.0](https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html) + +有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。但是这种方法可能会导致用户密码泄露等问题。 + +OAuth在"客户端"(云冲印)与"服务提供商"(谷歌)之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。 + +"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。 + +![](http://img.dabin-coder.cn/image/20220530233149.png) + +(A)用户打开客户端以后,客户端要求用户给予授权。 + +(B)用户同意给予客户端授权。 + +(C)客户端使用上一步获得的授权,向认证服务器申请令牌。 + +(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。 + +(E)客户端使用令牌,向资源服务器申请获取资源。 + +(F)资源服务器确认令牌无误,同意向客户端开放资源。 + diff --git a/docs/framework/springcloud/2-springboot-springcloud-diff.md b/docs/framework/springcloud/2-springboot-springcloud-diff.md new file mode 100644 index 0000000..b92ce91 --- /dev/null +++ b/docs/framework/springcloud/2-springboot-springcloud-diff.md @@ -0,0 +1,9 @@ +# 说说对SpringBoot 和SpringCloud的理解 + +- SpringBoot专注于快速方便的开发单个个体微服务。 +- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 +- SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系。 +- SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。 + +Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。 + diff --git a/docs/framework/springcloud/3-eureka.md b/docs/framework/springcloud/3-eureka.md new file mode 100644 index 0000000..4148784 --- /dev/null +++ b/docs/framework/springcloud/3-eureka.md @@ -0,0 +1,117 @@ +# Spring Cloud Eureka + +Spring Cloud Eureka实现微服务架构中的服务治理功能,使用 Netflix Eureka 实现服务注册与发现,包含客户端组件和服务端组件。服务治理是微服务架构中最为核心和基础的模块。 + +Eureka 服务端就是服务注册中心。Eureka 客户端用于处理服务的注册和发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中, 在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。 + +## 服务注册与发现 + +服务注册:在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,这样当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用。 + +服务发现:服务间的调用不是通过直接调用具体的实例地址,而是通过服务名发起调用。调用方需要向服务注册中心咨询服务,获取服务的实例清单,从而访问具体的服务实例。 + +## 代码实例 + +添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + +``` + +启动服务注册中心功能: + +```java +@EnableEurekaServer +@SpringBootApplication +public class EurekaServerApplication { + public static void main(String[] args) { + SpringApplication.run(EurekaServerApplication.class, args); + } +} +``` + +在配置文件application.yml中添加Eureka注册中心的配置: + +```yaml +server: + port: 8002 +spring: + application: + name: eureka-server +eureka: + instance: + hostname: replica1 + client: + serviceUrl: + defaultZone: http://replica2:8003/eureka/ #注册到另一个Eureka注册中心 + fetch-registry: true + register-with-eureka: true +``` + +运行EurekaServerApplication,访问地址http://localhost:8001/可以看到Eureka注册中心的界面。 + +## 高可用注册中心 + +注册中心互相注册,形成一组互相注册的服务注册中心, 以实现服务清单的互相同步, 达到高可用的效果。 + +创建application-replica1.yml和 application-replica2.yml: + +```yaml +-- application-replica1.yml +server: + port: 8002 +spring: + application: + name: eureka-server +eureka: + instance: + hostname: replica1 + client: + serviceUrl: + defaultZone: http://replica2:8003/eureka/ #注册到另一个Eureka注册中心 + fetch-registry: true + + register-with-eureka: true + +-- application-replica2.yml +server: + port: 8002 +spring: + application: + name: eureka-server +eureka: + instance: + hostname: replica1 + client: + serviceUrl: + defaultZone: http://replica2:8003/eureka/ #注册到另一个Eureka注册中心 + fetch-registry: true + + register-with-eureka: true +``` + +修改hosts文件,让 serviceUrl 能在本地正确访问到: + +```java +127.0.0.1 replica1 +127.0.0.1 replica2 +``` + +通过spring.profiles.active属性来分别启动(或者设置idea -> edit configuration -> active profiles 属性): + +```java +java -jar eureka-server-1.0.0.jar --spring.profiles.active=replica1 +java -jar eureka-server-1.0.0.jar --spring.profiles.active=replica2 +``` + +在设置了多节点的服务注册中心之后, 服务提供方还需要做一些简单的配置才能将服务注册到Eureka Server 集群中: + +```properties +eureka.client.serviceUrl.defaultZone=http://localhost:8002/eureka/, http://localhost:8003/eureka/ +``` + + + diff --git a/docs/framework/springcloud/4-ribbon.md b/docs/framework/springcloud/4-ribbon.md new file mode 100644 index 0000000..696b40c --- /dev/null +++ b/docs/framework/springcloud/4-ribbon.md @@ -0,0 +1,132 @@ +# Spring Cloud Ribbon + +Spring Cloud Ribbon 是基于HTTP和TCP的客户端负载均衡工具,基于Netflix Ribbon实现。Spring Cloud Ribbon 会**将REST请求转换为客户端负载均衡的服务调用**。 + +在客户端节点会维护可访问的服务器清单,服务器清单来自服务注册中心,通过心跳维持服务器清单的健康性。 + +开启客户端负载均衡调用: + +1. 服务提供者启动多个服务实例注册到服务注册中心; +2. 服务消费者直接通过调用被@LoadBalanced 注解修饰过的RestTemplate 来实现面向服务的接口调用。 + +## RestTemplate + +RestTemplate是一个HTTP客户端,使用它我们可以方便的调用HTTP接口,支持GET、POST、PUT、DELETE等方法。 + +## 代码实例 + +创建hello-service模块,用于给 Ribbon 提供服务调用。 + +```java +@RestController +public class HelloController { + + @Autowired + private Registration registration; // 服务注册 + + @Autowired + private DiscoveryClient client; + + private static final Logger LOGGER = LoggerFactory.getLogger(HelloController.class); + + @RequestMapping(value = "/hello", method = RequestMethod.GET) + public String hello() throws Exception { + ServiceInstance instance = client.getInstances(registration.getServiceId()).get(0); + LOGGER.info("/hello, host:" + instance.getHost() + ", service_id:" + instance.getServiceId()); + return "Hello World"; + } +} +``` + +添加相关的依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-web + +``` + +配置端口和注册中心地址: + +```properties +spring.application.name=hello-service +eureka.client.serviceUrl.defaultZone=http://localhost:8002/eureka/, http://localhost:8003/eureka/ +server.port=8081 +``` + +创建ribbon-consumer模块,使用负载均衡调用hello-service服务。 + +添加相关依赖: + +```xml + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + +``` + +配置了端口、注册中心地址。 + +```properties +spring.application.name=ribbon-consumer +server.port=9000 +eureka.client.serviceUrl.defaultZone=http://localhost:8002/eureka/, http://localhost:8002/eureka/ +hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000 +service-url.hello-service = http://HELLO-SERVICE +``` + +使用@LoadBalanced注解赋予RestTemplate负载均衡的能力。 + +```java +@Configuration +public class RibbonConfig { + @Bean + @LoadBalanced + public RestTemplate restTemplate(){ + return new RestTemplate(); + } +} +``` + +创建ConsumerController,注入RestTemplate,使用其调用hello-service中提供的相关接口: + +```java +@RestController +public class ConsumerController { + + @Autowired + RestTemplate restTemplate; + + @Value("${service-url.hello-service}") + private String helloService; + + @RequestMapping(value="/ribbon-consumer", method = RequestMethod.GET) + public String helloConsumer() { + return restTemplate.getForEntity(helloService + "/hello", String.class).getBody(); + } +} +``` + +启动两个 hello-service 实例(8001/8002),调用接口 http://localhost:9000/ribbon-consumer 进行测试。 + +hello-service:8001和hello-service:8002交替输出: + +```java +com.tyson.helloservice.HelloController : /hello, host:DESKTOP-8F30VS1, service_id:HELLO-SERVICE +``` + + + diff --git a/docs/framework/springcloud/5-hystrix.md b/docs/framework/springcloud/5-hystrix.md new file mode 100644 index 0000000..78a8497 --- /dev/null +++ b/docs/framework/springcloud/5-hystrix.md @@ -0,0 +1,82 @@ +# Spring Cloud Hystrix + +在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于**长时间得不到响应而占用线程**,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。 + +## 代码实例 + +创建 hystrix-service 模块。添加相关依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + + + org.springframework.boot + spring-boot-starter-web + +``` + +配置 application.yml: + +```yaml +server: + port: 8401 +spring: + application: + name: hystrix-service +eureka: + client: + register-with-eureka: true + fetch-registry: true + service-url: + defaultZone: http://localhost:8001/eureka/ +service-url: + user-service: http://user-service +``` + +在启动类上添加@EnableCircuitBreaker来开启Hystrix的断路器功能: + +```java +@EnableCircuitBreaker +@EnableDiscoveryClient +@SpringBootApplication +public class HystrixServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(HystrixServiceApplication.class, args); + } +} +``` + +创建UserHystrixController接口用于调用user-service服务: + +```java +@GetMapping("/testFallback/{id}") +public CommonResult testFallback(@PathVariable Long id) { + return userService.getUser(id); +} +``` + +在UserService中添加调用方法与服务降级方法,方法上需要添加@HystrixCommand注解: + +```java +@HystrixCommand(fallbackMethod = "getDefaultUser") +public CommonResult getUser(Long id) { + return restTemplate.getForObject(userServiceUrl + "/user/{1}", CommonResult.class, id); +} + +public CommonResult getDefaultUser(@PathVariable Long id) { + User defaultUser = new User(-1L, "defaultUser", "123456"); + return new CommonResult<>(defaultUser); +} +``` + +关闭user-service服务测试 testFallback 接口,发现已经发生了服务降级。 + + + diff --git a/docs/framework/springcloud/6-feign.md b/docs/framework/springcloud/6-feign.md new file mode 100644 index 0000000..6398544 --- /dev/null +++ b/docs/framework/springcloud/6-feign.md @@ -0,0 +1,120 @@ +# Spring Cloud Feign + +基于Netflix Feign 实现,整合了Spring Cloud Ribbon 与Spring Cloud Hystrix, 它提供了一种声明式服务调用的方式。 + +## 负载均衡功能 + +添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.boot + spring-boot-starter-web + +``` + +配置application.yml: + +```yaml +server: + port: 8701 +spring: + application: + name: feign-service +eureka: + client: + register-with-eureka: true + fetch-registry: true + service-url: + defaultZone: http://localhost:8002/eureka/ +``` + +在启动类上添加@EnableFeignClients注解来启用Feign的客户端功能: + +```java +@EnableFeignClients +@EnableDiscoveryClient +@SpringBootApplication +public class FeignServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(FeignServiceApplication.class, args); + } + +} +``` + +添加HelloService接口(与hello-service HelloController定义的接口一致),绑定hello-service服务接口: + +```java +@FeignClient(value="hello-service") +public interface HelloService { + + @RequestMapping(value = "/hello", method = RequestMethod.GET) + String getHello(); +} +``` + +添加HelloFeignController,调用UserService完成服务调用: + +```java +@RestController +@RequestMapping("feign") +public class HelloFeignController { + @Autowired + private HelloService helloService; + + @GetMapping("/hello") + public String getHello() { + return helloService.getHello(); + } +} +``` + +启动eureka-service,多个hello-service,feign-service服务,多次调用http://localhost:8701/feign/hello/进行测试。 + +## 服务降级功能 + +开启Hystrix功能: + +```yaml +feign: + hystrix: + enabled: true #在Feign中开启Hystrix +``` + +添加服务降级实现类: + +```java +@Component +public class HelloFallbackService implements HelloService { + @Override + public String getHello() { + return "hello fallback"; + } +} +``` + +修改HelloService接口,设置服务降级处理类: + +```java +@FeignClient(value="hello-service", fallback = HelloFallbackService.class) +public interface HelloService { + + @GetMapping(value = "/hello") + String getHello(); +} +``` + +关闭hello-service服务,重新启动 feign-service,访问 http://localhost:8701/feign/hello 进行测试。 + + + diff --git a/docs/framework/springcloud/7-zuul.md b/docs/framework/springcloud/7-zuul.md new file mode 100644 index 0000000..5db1afd --- /dev/null +++ b/docs/framework/springcloud/7-zuul.md @@ -0,0 +1,278 @@ +# Spring Cloud Zuul + +API网关,为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。 + +添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + +``` + +配置application.yml: + +```yaml +server: + port: 8801 +spring: + application: + name: zuul-proxy +eureka: + client: + register-with-eureka: true + fetch-registry: true + service-url: + defaultZone: http://localhost:8001/eureka/ +``` + +启动API网关功能: + +```java +@EnableZuulProxy +@EnableDiscoveryClient +@SpringBootApplication +public class ZuulProxyApplication { + + public static void main(String[] args) { + SpringApplication.run(ZuulProxyApplication.class, args); + } + +} +``` + +## 路由规则 + +将匹配`/userService/**`的请求路由到user-service服务上去,匹配`/feignService/**`的请求路由到feign-service上去。: + +```yaml +zuul: + routes: #给服务配置路由 + user-service: + path: /userService/** + feign-service: + path: /feignService/** +``` + +访问`http://localhost:8801/userService/user/1`可以发现请求路由到了user-service上了。 + +## 访问前缀 + +给网关路径添加前缀。 + +```yaml +zuul: + prefix: /proxy #给网关路由添加前缀 +``` + +需要访问`http://localhost:8801/proxy/user-service/user/1`才能访问到user-service中的接口。 + +## header过滤 + +默认情况下, Spring Cloud Zuul在请求路由时, 会过滤掉HTTP请求头信息中的一些敏感信息, 防止它们被传递到下游服务。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,包括Cookie、Set-Cookie、Authorization三个属性。这样的话,由于Cookie等信息被过滤掉,会导致应用无法登录和鉴权。为了避免这种情况,可以将敏感头设置为空。 + +```yaml +zuul: + sensitive-headers: +``` + +也可以通过指定路由的参数来配置,仅对指定路由开启对敏感信息的传递,影响范围小,不至于引起其他服务的信息泄露。 + +```yaml +#方法一:对指定路由开启自定义敏感头 +zuul.routes..customSensitiveHeaders=true +#方法二:将指定路由的敏感头设置为空 +zuul.routes..sensitiveHeaders= +``` + +## 重定向 + +[zuul重定向问题](https://blog.csdn.net/wo18237095579/article/details/83540829) + +客户端通过 Zuul 请求认证服务,认证成功之后重定向到一个欢迎页,但是发现重定向的这个欢迎页的 host 变成了这个认证服务的 host,而不是 Zuul 的 host,如下图所示,直接暴露了认证服务的地址,我们可以在配置里面解决掉这个问题。 + +```yaml +zuul: + -- 此处解决后端服务重定向导致用户浏览的 host 变成 后端服务的 host 问题 + add-host-header: true +``` + +## 查看路由信息 + +通过SpringBoot Actuator来查看Zuul中的路由信息。 + +在pom.xml中添加相关依赖: + +```xml + + org.springframework.boot + spring-boot-starter-actuator + +``` + +修改zuul-proxy/application.yml,开启查看路由信息的断点: + +```yaml +management: + endpoints: + web: + exposure: + include: 'routes' +``` + +通过访问http://localhost:8801/actuator/routes查看简单路由信息。访问[http://localhost:8801/actuator/routes/details](http://localhost:8801/actuator/routes)查看详细路由信息。 + +``` +{ + "/proxy/userService/**": { + "id": "user-service", + "fullPath": "/proxy/userService/**", + "location": "user-service", + "path": "/**", + "prefix": "/proxy/userService", + "retryable": false, + "customSensitiveHeaders": false, + "prefixStripped": true + }, + "/proxy/feignService/**": { + "id": "feign-service", + "fullPath": "/proxy/feignService/**", + "location": "feign-service", + "path": "/**", + "prefix": "/proxy/feignService", + "retryable": false, + "customSensitiveHeaders": false, + "prefixStripped": true + } +} +``` + +## 过滤器 + +路由与过滤是Zuul的两大核心功能,路由功能负责将外部请求转发到具体的服务实例上去,是实现统一访问入口的基础,过滤功能负责对请求过程进行额外的处理,是请求校验过滤及服务聚合的基础。 + +**过滤器类型** + +Zuul中有以下几种典型的过滤器类型。 + +- pre:在请求被路由到目标服务前执行,比如权限校验、打印日志等功能; +- routing:在请求被路由到目标服务时执行,这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方; +- post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能; +- error:请求在其他阶段发生错误时执行。 + +**自定义过滤器** + +添加PreLogFilter类继承ZuulFilter。在请求被转发到目标服务前打印请求日志。 + +```java +@Component +public class PreLogFilter extends ZuulFilter { + private Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + /** + * 过滤器类型,有pre、routing、post、error四种。 + */ + @Override + public String filterType() { + return "pre"; + } + + /** + * 过滤器执行顺序,数值越小优先级越高。 + */ + @Override + public int filterOrder() { + return 1; + } + + /** + * 是否进行过滤,返回true会执行过滤。 + */ + @Override + public boolean shouldFilter() { + return true; + } + + /** + * 自定义的过滤器逻辑,当shouldFilter()返回true时会执行。 + */ + @Override + public Object run() throws ZuulException { + RequestContext requestContext = RequestContext.getCurrentContext(); + HttpServletRequest request = requestContext.getRequest(); + String host = request.getRemoteHost(); + String method = request.getMethod(); + String uri = request.getRequestURI(); + LOGGER.info("Remote host:{},method:{},uri:{}", host, method, uri); + return null; + } +} +``` + +添加过滤器后,访问http://localhost:8801/proxy/user-service/user/1,会打印如下日志: + +```java +Remote host:0:0:0:0:0:0:0:1,method:GET,uri:/proxy/userService/user/1 +``` + +**禁用过滤器** + +在application.yml配置: + +```yaml +zuul: + PreLogFilter: + pre: + disable: true +``` + +## Ribbon和Hystrix的支持 + +由于Zuul自动集成了Ribbon和Hystrix,所以Zuul天生就有负载均衡和服务容错能力,我们可以通过Ribbon和Hystrix的配置来配置Zuul中的相应功能。 + +- 可以使用Hystrix的配置来设置路由转发时HystrixCommand的执行超时时间: + + ```yaml + hystrix: + command: #用于控制HystrixCommand的行为 + default: + execution: + isolation: + thread: + timeoutInMilliseconds: 1000 #配置HystrixCommand执行的超时时间,执行超过该时间会进行服务降级处理 + ``` + +- 可以使用Ribbon的配置来设置路由转发时请求连接及处理的超时时间: + + ```yaml + ribbon: #全局配置 + ConnectTimeout: 1000 #服务请求连接超时时间(毫秒) + ReadTimeout: 3000 #服务请求处理超时时间(毫秒) + ``` + +## 常用配置 + +```yaml +zuul: + routes: #给服务配置路由 + user-service: + path: /userService/** + feign-service: + path: /feignService/** + ignored-services: user-service,feign-service #关闭默认路由配置 + prefix: /proxy #给网关路由添加前缀 + sensitive-headers: Cookie,Set-Cookie,Authorization #配置过滤敏感的请求头信息,设置为空就不会过滤 + add-host-header: true #设置为true重定向是会添加host请求头 + retryable: true # 关闭重试机制 + PreLogFilter: + pre: + disable: false #控制是否启用过滤器 +``` + + + diff --git a/docs/framework/springcloud/8-gateway.md b/docs/framework/springcloud/8-gateway.md new file mode 100644 index 0000000..377af66 --- /dev/null +++ b/docs/framework/springcloud/8-gateway.md @@ -0,0 +1,407 @@ +# Spring Cloud Gateway + +为 SpringBoot 应用提供了API网关支持,具有强大的智能路由与过滤器功能。 + +创建api-gateway模块,pom.xml添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-gateway + +``` + +## 配置路由 + +Gateway 提供了两种不同的方式用于配置路由,一种是通过yml文件来配置,另一种是通过Java Bean来配置。 + +1. 使用yml配置。修改application.yml。 + + ```yaml + server: + port: 9201 + service-url: + user-service: http://localhost:8201 + spring: + cloud: + gateway: + routes: + - id: path_route #路由的ID + uri: ${service-url.user-service}/user/{id} #匹配后路由地址 + predicates: # 断言,路径相匹配的进行路由 + - Path=/user/{id} + ``` + + 启动eureka-server,user-service和api-gateway服务,测试http://localhost:9201/user/1 + +2. 使用Java bean配置。 + + 添加相关配置类,并配置一个RouteLocator对象: + + ```java + @Configuration + public class GatewayConfig { + + @Bean + public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { + return builder.routes() + .route("path_route2", r -> r.path("/user/getByUsername") + .uri("http://localhost:8201/user/getByUsername")) + .build(); + } + } + ``` + + 使用http://localhost:9201/user/getByUsername?username=macro测试。 + +## Route Predicate + +Spring Cloud Gateway包括许多内置的Route Predicate工厂。 所有这些Predicate都与HTTP请求的不同属性匹配。 多个Route Predicate工厂可以进行组合。 + +**After** Route Predicate + +在指定时间之后的请求会匹配该路由。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: after_route + uri: ${service-url.user-service} + predicates: + - After=2019-09-24T16:30:00+08:00[Asia/Shanghai] +``` + +**Cookie Route Predicate** + +带有指定Cookie的请求会匹配该路由。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: cookie_route + uri: ${service-url.user-service} + predicates: + - Cookie=username,tyson +``` + +使用curl工具发送带有cookie为`username=macro`的请求可以匹配该路由。 + +``` +curl http://localhost:9201/user/1 --cookie "username=tyson" +``` + +**Header Route Predicate** + +带有指定请求头的请求会匹配该路由。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: header_route + uri: ${service-url.user-service} + predicates: + - Header=X-Request-Id, \d+ +``` + +使用curl工具发送带有请求头为`X-Request-Id:123`的请求可以匹配该路由。 + +``` +curl http://localhost:9201/user/1 -H "X-Request-Id:123" +``` + +**Host Route Predicate** + +带有指定Host的请求会匹配该路由。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: host_route + uri: ${service-url.user-service} + predicates: + - Host=**.macrozheng.com +``` + +使用curl工具发送带有请求头为`Host:www.macrozheng.com`的请求可以匹配该路由。 + +``` +curl http://localhost:9201/user/1 -H "Host:www.macrozheng.com" +``` + +## Route Filter + +路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。 + +**AddRequestParameter GatewayFilter** + +给请求添加参数的过滤器。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: add_request_parameter_route + uri: http://localhost:8201 + filters: + - AddRequestParameter=username, macro + predicates: + - Method=GET +``` + +以上配置会对GET请求添加`username=macro`的请求参数,通过curl工具使用以下命令进行测试。 + +``` +curl http://localhost:9201/user/getByUsername +``` + +相当于发起该请求: + +``` +curl http://localhost:8201/user/getByUsername?username=macro +``` + +**StripPrefix GatewayFilter** + +对指定数量的路径前缀进行去除的过滤器。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: strip_prefix_route + uri: http://localhost:8201 + predicates: + - Path=/user-service/** + filters: + - StripPrefix=2 +``` + +以上配置会把以`/user-service/`开头的请求的路径去除两位,通过curl工具使用以下命令进行测试。 + +``` +curl http://localhost:9201/user-service/a/user/1 +``` + +相当于发起请求:curl http://localhost:8201/user/1 + +**PrefixPate GatewayFilter** + +与StripPrefix过滤器恰好相反,会对原有路径进行增加操作的过滤器。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: prefix_path_route + uri: http://localhost:8201 + predicates: + - Method=GET + filters: + - PrefixPath=/user +``` + +以上配置会对所有GET请求添加`/user`路径前缀。 + +**Hystrix GatewayFilter** + +将断路器功能添加到网关路由中,使服务免受级联故障的影响,并提供服务降级处理。 + +要开启断路器功能,我们需要在pom.xml中添加Hystrix的相关依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + +``` + +然后添加相关服务降级的处理类: + +```java +@RestController +public class FallbackController { + + @GetMapping("/fallback") + public Object fallback() { + Map result = new HashMap<>(); + result.put("data",null); + result.put("message","Get request fallback!"); + result.put("code",500); + return result; + } +} +``` + +**RequestRateLimiter GatewayFilter** + +用于限流,使用RateLimiter实现来确定是否允许当前请求继续进行,如果请求太大默认会返回HTTP 429-太多请求状态。 + +在pom.xml中添加相关依赖: + +```xml + + org.springframework.boot + spring-boot-starter-data-redis-reactive + +``` + +添加限流策略的配置类,这里有两种策略一种是根据请求参数中的username进行限流,另一种是根据访问IP进行限流。 + +```java +@Configuration +public class RedisRateLimiterConfig { + @Bean + KeyResolver userKeyResolver() { + return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username")); + } + + @Bean + public KeyResolver ipKeyResolver() { + return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); + } +} +``` + +我们使用Redis来进行限流,所以需要添加Redis和RequestRateLimiter的配置,这里对所有的GET请求都进行了按IP来限流的操作。 + +```yaml +server: + port: 9201 +spring: + redis: + host: localhost + password: 123456 + port: 6379 + cloud: + gateway: + routes: + - id: requestratelimiter_route + uri: http://localhost:8201 + filters: + - name: RequestRateLimiter + args: + redis-rate-limiter.replenishRate: 1 #每秒允许处理的请求数量 + redis-rate-limiter.burstCapacity: 2 #每秒最大处理的请求数量 + key-resolver: "#{@ipKeyResolver}" #限流策略,对应策略的Bean + predicates: + - Method=GET +logging: + level: + org.springframework.cloud.gateway: debug +``` + +多次请求该地址:http://localhost:9201/user/1 ,会返回状态码为429的错误。 + +**Retry GatewayFilter** + +对路由请求进行重试的过滤器,可以根据路由请求返回的HTTP状态码来确定是否进行重试。 + +```yaml +spring: + cloud: + gateway: + routes: + - id: retry_route + uri: http://localhost:8201 + predicates: + - Method=GET + filters: + - name: Retry + args: + retries: 1 #需要进行重试的次数 + statuses: BAD_GATEWAY #返回哪个状态码需要进行重试,返回状态码为5XX进行重试 + backoff: + firstBackoff: 10ms + maxBackoff: 50ms + factor: 2 + basedOnPreviousValue: false +``` + +## 结合注册中心使用 + +**使用动态路由** + +以服务名为路径创建动态路由。 + +在pom.xml中添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + +``` + +添加application-eureka.yml配置文件: + +```yaml +server: + port: 9201 +spring: + application: + name: api-gateway + cloud: + gateway: + discovery: + locator: + enabled: true #开启从注册中心动态创建路由的功能 + lower-case-service-id: true #使用小写服务名,默认是大写 +eureka: + client: + service-url: + defaultZone: http://localhost:8001/eureka/ +logging: + level: + org.springframework.cloud.gateway: debug +``` + +使用application-eureka.yml配置文件启动api-gateway服务,访问http://localhost:9201/user-service/user/1 ,可以路由到user-service的http://localhost:8201/user/1 处。 + +**使用过滤器** + +在结合注册中心使用过滤器的时候,需要注意的是uri的协议为`lb`,这样才能启用Gateway的负载均衡功能。 + +修改application-eureka.yml文件,使用了PrefixPath过滤器,会为所有GET请求路径添加`/user`路径并路由。 + +```yaml +server: + port: 9201 +spring: + application: + name: api-gateway + cloud: + gateway: + routes: + - id: prefixpath_route + uri: lb://user-service #此处需要使用lb协议 + predicates: + - Method=GET + filters: + - PrefixPath=/user + discovery: + locator: + enabled: true +eureka: + client: + service-url: + defaultZone: http://localhost:8001/eureka/ +logging: + level: + org.springframework.cloud.gateway: debug +``` + +使用application-eureka.yml配置文件启动api-gateway服务,访问http://localhost:9201/1 ,可以路由到user-service的http://localhost:8201/user/1 处。 + + + diff --git a/docs/framework/springcloud/9-config.md b/docs/framework/springcloud/9-config.md new file mode 100644 index 0000000..ec5839a --- /dev/null +++ b/docs/framework/springcloud/9-config.md @@ -0,0 +1,274 @@ +# Spring Cloud Config + +Spring Cloud Config分为服务端和客户端。服务端也称为分布式配置中心,它是个独立的微服务应用,用于从配置仓库获取配置信息供客户端使用。而客户端则是微服务架构中的各个微服务应用或者基础设施,可以从配置中心获取配置信息,在启动时加载配置。Spring Cloud Config 的配置中心默认采用Git来存储配置信息。 + +## 准备配置信息 + +在Git仓库中添加好配置文件。 + +master分支下的配置信息: + +```yaml +config: + info: "config info for dev(master)" +``` + +## 配置中心 + +创建config-server模块,在pom.xml中添加依赖: + +```xml + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + +``` + +在application.yml中进行配置: + +```yaml +server: + port: 8901 +spring: + application: + name: config-server + cloud: + config: + server: + git: #配置存储配置信息的Git仓库 + uri: https://gitee.com/macrozheng/springcloud-config.git + username: macro + password: 123456 + clone-on-start: true #开启启动时直接从git获取配置 +eureka: + client: + service-url: + defaultZone: http://localhost:8001/eureka/ +``` + +在启动类添加@EnableConfigServer启动配置中心的功能。 + +```java +@EnableConfigServer +@EnableDiscoveryClient +@SpringBootApplication +public class ConfigServerApplication { + public static void main(String[] args) { + SpringApplication.run(ConfigServerApplication.class, args); + } +} +``` + +## 获取配置信息 + +访问http://localhost:8901/master/config-dev来获取master分支上dev环境的配置信息。 + +```json +{ + "name":"master", + "profiles":[ + "config-dev" + ], + "label":null, + "version":"caf6549c807a6dde1fbbe399ffca18dc886ac03d", + "state":null, + "propertySources":[ + ] +} +``` + +访问http://localhost:8901/master/config-dev.yml来获取master分支上dev环境的配置文件信息。 + +```yaml +config: + info: config info for dev(master) +``` + +创建config-client模块,在 pom.xml 中添加相关依赖。 + +```xml + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-web + +``` + +配置application.yml。 + +```yaml +server: + port: 9001 +spring: + application: + name: config-client + cloud: + config: #Config客户端配置 + profile: dev #启用配置后缀名称 + label: dev #分支名称 + uri: http://localhost:8901 #配置中心地址 + name: config #配置文件名称 +eureka: + client: + service-url: + defaultZone: http://localhost:8001/eureka/ +``` + +添加ConfigClientController用于获取配置。 + +```java +@RestController +public class ConfigClientController { + + @Value("${config.info}") + private String configInfo; + + @GetMapping("/configInfo") + public String getConfigInfo() { + return configInfo; + } +} +``` + +启动config-client服务,访问http://localhost:9001/configInfo,可以获取到dev分支下dev环境的配置。 + +## 刷新配置 + +当Git仓库中的配置信息更改后,我们可以通过SpringBoot Actuator的refresh端点来刷新客户端配置信息。 + +config-client增加依赖: + +```xml + + org.springframework.boot + spring-boot-starter-actuator + +``` + +application.yml开启refresh端点: + +```yaml +management: + endpoints: + web: + exposure: + include: 'refresh' +``` + +在ConfigClientController类添加@RefreshScope注解用于刷新配置: + +```java +@RestController +@RefreshScope +public class ConfigClientController { + + @Value("${config.info}") + private String configInfo; + + @GetMapping("/configInfo") + public String getConfigInfo() { + return configInfo; + } +} +``` + +重新启动config-client后,调用refresh端点进行配置刷新。 + +访问http://localhost:9001/configInfo进行测试,可以发现配置信息已经刷新。 + +## 安全认证 + +创建config-security-server模块,在pom.xml中添加相关依赖: + +```xml + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.boot + spring-boot-starter-security + +``` + +在application.yml中进行配置: + +```yaml +server: + port: 8905 +spring: + application: + name: config-security-server + cloud: + config: + server: + git: + uri: https://gitee.com/macrozheng/springcloud-config.git + username: + password: + clone-on-start: true #开启启动时直接从git获取配置 + security: #配置用户名和密码 + user: + name: + password: +``` + +然后启动config-security-server服务。 + +修改config-client的配置(添加application-security.yml配置文件,主要是配置了配置中心的用户名和密码): + +```yaml +server: + port: 9002 +spring: + application: + name: config-client + cloud: + config: + profile: dev #启用配置后缀名称 + label: dev #分支名称 + uri: http://localhost:8905 #配置中心地址 + name: config #配置文件名称 + username: + password: +``` + +使用application-security.yml启动config-client服务。访问http://localhost:9002/configInfo进行测试。 + +## 配置中心集群 + +在微服务架构中,所有服务都从配置中心获取配置,配置中心一旦宕机,会发生很严重的问题。通过搭建配置中心集群避免该问题。 + +1. 启动两个config-server分别运行在8902和8903端口上; + +2. 添加config-client的配置文件application-cluster.yml,主要是添加了从注册中心获取配置中心地址的配置并去除了配置中心uri的配置: + + ```yaml + spring: + cloud: + config: + profile: dev #启用环境名称 + label: dev #分支名称 + name: config #配置文件名称 + discovery: + enabled: true + service-id: config-server + eureka: + client: + service-url: + defaultZone: http://localhost:8001/eureka/ + ``` + + + diff --git a/docs/framework/springcloud/README.md b/docs/framework/springcloud/README.md new file mode 100644 index 0000000..e73d735 --- /dev/null +++ b/docs/framework/springcloud/README.md @@ -0,0 +1,22 @@ +--- +title: SpringCloud基础 +icon: cloud +date: 2022-08-06 +category: springcloud +star: true +--- + + +## SpringCloud总结 + +- [基础知识](./1-basic.md) +- [说说对SpringBoot和SpringCloud的理解](./2-springboot-springcloud-diff.md) +- [SpringCloudEureka](./3-eureka.md) +- [SpringCloudRibbon](./4-ribbon.md) +- [SpringCloudHystrix](./5-hystrix.md) +- [SpringCloudFeign](./6-feign.md) +- [SpringCloudZuul](./7-zuul.md) +- [SpringCloudGateway](./8-gateway.md) +- [SpringCloudConfig](./9-config.md) +- [SpringCloudBus](./10-bus.md) +- [SpringCloudSecurity](./11-security.md) diff --git a/docs/framework/springmvc.md b/docs/framework/springmvc.md new file mode 100644 index 0000000..523b82a --- /dev/null +++ b/docs/framework/springmvc.md @@ -0,0 +1,188 @@ +--- +sidebar: heading +--- + +## 说说你对 SpringMVC 的理解 + +SpringMVC是一种基于 Java 的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring框架的一个模块。 + +它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。 + +## 什么是MVC模式? + +MVC的全名是`Model View Controller`,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。 + +View,视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。 + +model,模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。 + +controller,控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。 + +## SpringMVC 有哪些优点? + +1. 与 Spring 集成使用非常方便,生态好。 +2. 配置简单,快速上手。 +3. 支持 RESTful 风格。 +4. 支持各种视图技术,支持各种请求资源映射策略。 + +## Spring MVC和Struts的区别 + +1. Spring MVC是基于方法开发,Struts2是基于类开发的。 + - Spring MVC会将用户请求的URL路径信息与Controller的某个方法进行映射,所有请求参数会注入到对应方法的形参上,生成Handler对象,对象中只有一个方法; + - Struts每处理一次请求都会实例一个Action,Action类的所有方法使用的请求参数都是Action类中的成员变量,随着方法增多,整个Action也会变得混乱。 +2. Spring MVC支持单例开发模式,Struts只能使用多例 + + - Struts由于只能通过类的成员变量接收参数,故只能使用多例。 +3. Struts2 的核心是基于一个Filter即StrutsPreparedAndExcuteFilter,Spring MVC的核心是基于一个Servlet即DispatcherServlet(前端控制器)。 +4. Struts处理速度稍微比Spring MVC慢,Struts使用了Struts标签,加载数据较慢。 + +## Spring MVC的工作原理 + +Spring MVC的工作原理如下: + +1. DispatcherServlet 接收用户的请求 +2. 找到用于处理request的 handler 和 Interceptors,构造成 HandlerExecutionChain 执行链 +3. 找到 handler 相对应的 HandlerAdapter +4. 执行所有注册拦截器的preHandler方法 +5. 调用 HandlerAdapter 的 handle() 方法处理请求,返回 ModelAndView +6. 倒序执行所有注册拦截器的postHandler方法 +7. 请求视图解析和视图渲染 + +![](http://img.dabin-coder.cn/image/spring_mvc原理.png) + +## Spring MVC的主要组件? + +- 前端控制器(DispatcherServlet):接收用户请求,给用户返回结果。 +- 处理器映射器(HandlerMapping):根据请求的url路径,通过注解或者xml配置,寻找匹配的Handler。 +- 处理器适配器(HandlerAdapter):Handler 的适配器,调用 handler 的方法处理请求。 +- 处理器(Handler):执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装到ModelAndView对象中。 +- 视图解析器(ViewResolver):将逻辑视图名解析成真正的视图View。 +- 视图(View):接口类,实现类可支持不同的View类型(JSP、FreeMarker、Excel等)。 + +## Spring MVC的常用注解由有哪些? +- @Controller:用于标识此类的实例是一个控制器。 +- @RequestMapping:映射Web请求(访问路径和参数)。 +- @ResponseBody:注解返回数据而不是返回页面 +- @RequestBody:注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。 +- @PathVariable:获得URL中路径变量中的值 +- @RestController:@Controller+@ResponseBody +- @ExceptionHandler标识一个方法为全局异常处理的方法。 + +## @Controller 注解有什么用? + +`@Controller` 注解标记一个类为 Spring Web MVC 控制器。Spring MVC 会将扫描到该注解的类,然后扫描这个类下面带有 `@RequestMapping` 注解的方法,根据注解信息,为这个方法生成一个对应的处理器对象,在上面的 HandlerMapping 和 HandlerAdapter组件中讲到过。 + +当然,除了添加 `@Controller` 注解这种方式以外,你还可以实现 Spring MVC 提供的 `Controller` 或者 `HttpRequestHandler` 接口,对应的实现类也会被作为一个处理器对象 + +## @RequestMapping 注解有什么用? + +`@RequestMapping` 注解,用于配置处理器的 HTTP 请求方法,URI等信息,这样才能将请求和方法进行映射。这个注解可以作用于类上面,也可以作用于方法上面,在类上面一般是配置这个控制器的 URI 前缀。 + +## @RestController 和 @Controller 有什么区别? + +`@RestController` 注解,在 `@Controller` 基础上,增加了 `@ResponseBody` 注解,更加适合目前前后端分离的架构下,提供 Restful API ,返回 JSON 数据格式。 + +## @RequestMapping 和 @GetMapping 注解有什么不同? + +1. `@RequestMapping`:可注解在类和方法上;`@GetMapping` 仅可注册在方法上 +2. `@RequestMapping`:可进行 GET、POST、PUT、DELETE 等请求方法;`@GetMapping` 是 `@RequestMapping` 的 GET 请求方法的特例。 + +## @RequestParam 和 @PathVariable 两个注解的区别 + +两个注解都用于方法参数,获取参数值的方式不同,`@RequestParam` 注解的参数从请求携带的参数中获取,而 `@PathVariable` 注解从请求的 URI 中获取 + +## @RequestBody和@RequestParam的区别 + +@RequestBody一般处理的是在ajax请求中声明contentType: "application/json; charset=utf-8"时候。也就是json数据或者xml数据。 + +@RequestParam一般就是在ajax里面没有声明contentType的时候,为默认的`x-www-form-urlencoded`格式时。 + +## Spring MVC的异常处理 + +可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。 + +- 使用系统定义好的异常处理器 SimpleMappingExceptionResolver +- 使用自定义异常处理器 +- 使用异常处理注解 + +## SpringMVC 用什么对象从后台向前台传递数据的? + +1. 将数据绑定到 request; +2. 返回 ModelAndView; +3. 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前端就可以通过el表达式拿到; +4. 绑定数据到 Session中。 + +## SpringMvc的Controller是不是单例模式? + +单例模式。在多线程访问的时候有线程安全问题,解决方案是在控制器里面不要写可变状态量,如果需要使用这些可变状态,可以使用ThreadLocal,为每个线程单独生成一份变量副本,独立操作,互不影响。 + +## 介绍下 Spring MVC 拦截器? + +Spring MVC 拦截器对应HandlerInterceor接口,该接口位于org.springframework.web.servlet的包中,定义了三个方法,若要实现该接口,就要实现其三个方法: + +1. **前置处理(preHandle()方法)**:该方法在执行控制器方法之前执行。返回值为Boolean类型,如果返回false,表示拦截请求,不再向下执行,如果返回true,表示放行,程序继续向下执行(如果后面没有其他Interceptor,就会执行controller方法)。所以此方法可对请求进行判断,决定程序是否继续执行,或者进行一些初始化操作及对请求进行预处理。 +2. **后置处理(postHandle()方法)**:该方法在执行控制器方法调用之后,且在返回ModelAndView之前执行。由于该方法会在DispatcherServlet进行返回视图渲染之前被调用,所以此方法多被用于处理返回的视图,可通过此方法对请求域中的模型和视图做进一步的修改。 +3. **已完成处理(afterCompletion()方法)**:该方法在执行完控制器之后执行,由于是在Controller方法执行完毕后执行该方法,所以该方法适合进行一些资源清理,记录日志信息等处理操作。 + +可以通过拦截器进行权限检验,参数校验,记录日志等操作 + +## SpringMvc怎么配置拦截器? + +有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可: + +```java + + + + + + + + + + +``` + +## Spring MVC 的拦截器和 Filter 过滤器有什么差别? + +有以下几点: + +- **功能相同**:拦截器和 Filter 都能实现相应的功能 +- **容器不同**:拦截器构建在 Spring MVC 体系中;Filter 构建在 Servlet 容器之上 +- **使用便利性不同**:拦截器提供了三个方法,分别在不同的时机执行;过滤器仅提供一个方法 + +## 什么是REST? + +REST,英文全称,Resource Representational State Transfer,对资源的访问状态的变化通过url的变化表述出来。 + +Resource:**资源**。资源是REST架构或者说整个网络处理的核心。 + +Representational:**某种表现形式**,比如用JSON,XML,JPEG等。 + +State Transfer:**状态变化**。通过HTTP method实现。 + +REST描述的是在网络中client和server的一种交互形式。用大白话来说,就是**通过URL就知道要什么资源,通过HTTP method就知道要干什么,通过HTTP status code就知道结果如何**。 + +举个例子: + +```java +GET /tasks 获取所有任务 +POST /tasks 创建新任务 +GET /tasks/{id} 通过任务id获取任务 +PUT /tasks/{id} 更新任务 +DELETE /tasks/{id} 删除任务 +``` + +GET代表获取一个资源,POST代表添加一个资源,PUT代表修改一个资源,DELETE代表删除一个资源。 + +server提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。用`HTTP Status Code`传递server的状态信息。比如最常用的 200 表示成功,500 表示Server内部错误等。 + +## 使用REST有什么优势呢? + +第一,**风格统一**了,不会出现`delUser/deleteUser/removeUser`各种命名的代码了。 + +第二,**面向资源**,一目了然,具有自解释性。 + +第三,**充分利用 HTTP 协议本身语义**。 + +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git a/docs/interview/concurrent/1-forbid-default-executor.md b/docs/interview/concurrent/1-forbid-default-executor.md new file mode 100644 index 0000000..186332f --- /dev/null +++ b/docs/interview/concurrent/1-forbid-default-executor.md @@ -0,0 +1,43 @@ +## 为什么阿里禁止使用Java内置线程池? + +首先要了解一下线程池 ThreadPoolExecutor 的参数及其作用。 + +ThreadPoolExecutor有以下这些参数。 + +1. **corePoolSize** 指定了线程池里的线程数量,核心线程池大小 + +2. maximumPoolSize 指定了线程池里的最大线程数量 + +3. **keepAliveTime** 当线程池线程数量大于corePoolSize时候,多出来的空闲线程,多长时间会被销毁。 + +4. **TimeUnit**时间单位。 + +5. workQueue 任务队列,用于存放提交但是尚未被执行的任务。 + +6. **threadFactory** 线程工厂,用于创建线程,一般可以用默认的 + +7. **RejectedExecutionHandler** 拒绝策略,所谓拒绝策略,是指将任务添加到线程池中时,线程池拒绝该任务所采取的相应策略。 + +阿里规约之所以强制要求手动创建线程池,也是和这些参数有关。 + +阿里规约上指出,线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的**运行规则**,规避资源耗尽的风险。 + +虽然Executor提供的四个静态方法创建线程池,但是不建议去使用这些静态方法创建线程池,因为这些方法创建的线程池,如果使用不当,可能会有OOM的风险。 + +比如**newFixedThreadPool**和**newSingleThreadExecutor**的问题是堆积的请求处理队列可能会耗费非常大的内存,甚至**OOM**。 + +**newCachedThreadPool**和**newScheduledThreadPool**的问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至**OOM**。 + + + +--end-- + +最后分享一份大彬精心整理的**大厂面试手册**,包含**操作系统、计算机网络、Java基础、JVM、分布式**等高频面试题,非常实用,有小伙伴靠着这份手册拿过字节offer~ + +![](http://img.dabin-coder.cn/image/面试手册1.png) + +![](http://img.dabin-coder.cn/image/面试手册.png) + +**手册获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**手册**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/image-20221207225029295.png) \ No newline at end of file diff --git a/docs/interview/java/1-create-object.md b/docs/interview/java/1-create-object.md new file mode 100644 index 0000000..fc88db5 --- /dev/null +++ b/docs/interview/java/1-create-object.md @@ -0,0 +1,9 @@ +## Java创建对象有几种方式? + +Java创建对象有以下几种方式: + +- 1、用new语句创建对象。 +- 2、使用反射机制创建对象,用Class类或Constructor类的newInstance()方法。 +- 3、调用对象的clone()方法。需要实现Cloneable接口,重写object类的clone方法。当调用一个对象的clone方法,JVM就会创建一个新的对象,将前面对象的内容全部拷贝进去。 +- 4、运用反序列化手段。需要让类实现Serializable接口,通过ObjectInputStream的readObject()方法反序列化类。当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象。 + diff --git a/docs/interview/java/2-3rd-interface.md b/docs/interview/java/2-3rd-interface.md new file mode 100644 index 0000000..978273d --- /dev/null +++ b/docs/interview/java/2-3rd-interface.md @@ -0,0 +1,13 @@ +## 对接第三方接口要考虑什么? + +嗯,需要考虑以下几点: + +1. 确认接口对接的网络协议,是https/http或者自定义的私有协议等。 +2. 约定好数据传参、响应格式(如application/json),弱类型对接强类型语言时要特别注意 +3. 接口安全方面,要确定身份校验方式,使用token、证书校验等 +4. 确认是否需要接口调用失败后的重试机制,保证数据传输的最终一致性。 +5. 日志记录要全面。接口出入参数,以及解析之后的参数值,都要用日志记录下来,方便定位问题(甩锅)。 + + + +参考:https://blog.csdn.net/gzt19881123/article/details/108791034 \ No newline at end of file diff --git a/docs/interview/java/3-design-interface.md b/docs/interview/java/3-design-interface.md new file mode 100644 index 0000000..7fb9f92 --- /dev/null +++ b/docs/interview/java/3-design-interface.md @@ -0,0 +1,11 @@ +## 设计接口要注意什么? + +1. 接口参数校验。接口必须校验参数,比如入参是否允许为空,入参长度是否符合预期。 +2. 设计接口时,充分考虑接口的可扩展性。思考接口是否可以复用,怎样保持接口的可扩展性。 +3. 串行调用考虑改并行调用。比如设计一个商城首页接口,需要查商品信息、营销信息、用户信息等等。如果是串行一个一个查,那耗时就比较大了。这种场景是可以改为并行调用的,降低接口耗时。 +4. 接口是否需要防重处理。涉及到数据库修改的,要考虑防重处理,可以使用数据库防重表,以唯一流水号作为唯一索引。 +5. 日志打印全面,入参出参,接口耗时,记录好日志,方便甩锅。 +6. 修改旧接口时,注意兼容性设计。 +7. 异常处理得当。使用finally关闭流资源、使用log打印而不是e.printStackTrace()、不要吞异常等等 +8. 是否需要考虑限流。限流为了保护系统,防止流量洪峰超过系统的承载能力。 + diff --git a/docs/interview/java/4-interface-slow.md b/docs/interview/java/4-interface-slow.md new file mode 100644 index 0000000..7823dc4 --- /dev/null +++ b/docs/interview/java/4-interface-slow.md @@ -0,0 +1,19 @@ +## 线上接口很慢怎么办? + +使用调用链跟踪,如zipkin,查看每一条路线的耗时情况,甚至包括此时 CPU 性能,然后再针对性能差的服务接口进行分析。 + +针对数据库性能优化问题,从设计上来说,设计表之前考虑好引擎,数据量,字段格式,索引等。 + +从 SQL 层面要利用好索引覆盖,尽量不回表,优化好 SQL。 + +从架构上来说,采用高可用的架构,如 MySQL 扩展的 MHA 架构 + +从业务代码层面来说,分析是不是代码问题,比如查询 SQL 过慢,返回超时,或者限流不合理等情况 + +如果数据量比较大的话,千万以及上亿级别,做好分表分库或者选用分布式数据库等 + +如果下游处理能力薄弱或者调用链路很深,考虑是否能够使用消息队列方式处理。 + + + +> 参考:https://youle.zhipin.com/questions/d260cce58d0333c9tnVy2tW8GFQ~.html \ No newline at end of file diff --git a/docs/interview/java/5-comparable-vs-comparator.md b/docs/interview/java/5-comparable-vs-comparator.md new file mode 100644 index 0000000..059a5b0 --- /dev/null +++ b/docs/interview/java/5-comparable-vs-comparator.md @@ -0,0 +1,14 @@ +## Comparable和Comparator有什么区别? + +Comparable 和 Comparator 都是用来进行元素排序的。它们之间的区别如下: + +1、字面含义不同。Comparable 是“比较”的意思,而 Comparator 是“比较器”的意思。 + +2、Comparable 是通过重写 compareTo 方法实现排序的,而 Comparator 是通过重写compare 方法实现排序的。 + +3、Comparable 必须由自定义类内部实现排序方法,而 Comparator 是外部定义并实现排序的。 + + + +总结一下:Comparable 可以看作是“对内”进行排序接口,而 Comparator 是“对外”进行排序的接口。 + diff --git a/docs/interview/java/README.md b/docs/interview/java/README.md new file mode 100644 index 0000000..ca6227c --- /dev/null +++ b/docs/interview/java/README.md @@ -0,0 +1,7 @@ + +## 目录 + +- [Java创建对象有几种方式?](./1-create-object.md) +- [对接第三方接口要考虑什么?](./2-3rd-interface.md) +- [设计接口要注意什么?](./3-design-interface.md) +- [线上接口很慢怎么办?](./4-interface-slow.md) diff --git a/docs/interview/javaweb/1-interceptor-filter.md b/docs/interview/javaweb/1-interceptor-filter.md new file mode 100644 index 0000000..3733c81 --- /dev/null +++ b/docs/interview/javaweb/1-interceptor-filter.md @@ -0,0 +1,27 @@ +## 过滤器和拦截器有什么区别? + +1、**实现原理不同**。 + +过滤器和拦截器底层实现不同。过滤器是基于函数回调的,拦截器是基于Java的反射机制(动态代理)实现的。一般自定义的过滤器中都会实现一个doFilter()方法,这个方法有一个FilterChain参数,而实际上它是一个回调接口。 + +2、**使用范围不同**。 + +过滤器实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。拦截器不仅能应用在web程序中,也可以用于Application、Swing等程序中。 + +3、**使用的场景不同**。 + +因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断的,比如:日志记录、权限判断等业务。而过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、响应数据压缩等功能。 + +4、**触发时机不同**。 + +过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。 + +拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。 + +5、**拦截的请求范围不同**。 + +请求的执行顺序是:请求进入容器 -> 进入过滤器 -> 进入 Servlet -> 进入拦截器 -> 执行控制器。可以看到过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法。 + + + +> 参考链接:https://segmentfault.com/a/1190000022833940 \ No newline at end of file diff --git a/docs/interview/mq/1-why-to-use-mq.md b/docs/interview/mq/1-why-to-use-mq.md new file mode 100644 index 0000000..f525539 --- /dev/null +++ b/docs/interview/mq/1-why-to-use-mq.md @@ -0,0 +1,32 @@ +## 为什么要使用消息队列? + +主要有以下几点原因: + +1、解**耦**。比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单操作失败。订单系统与库存系统耦合,这个时候如果使用消息队列,可以返回给用户成功,先把消息持久化,等库存系统恢复后,就可以正常消费减去库存了。 + +2、**异步**。将消息写入消息队列,非必要的业务逻辑以异步的方式运行,不影响主流程业务。 + +3、**削峰**。消费端慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。比如秒杀活动,一般会因为流量过大,从而导致流量暴增,应用挂掉。这个时候加上消息队列,服务器接收到用户的请求后,首先写入消息队列,如果消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。 + +总结一下,主要三点原因:**解耦、异步、削峰**。 + +## 那使用了消息队列会有什么缺点 + +- **系统可用性降低**。引入消息队列之后,如果消息队列挂了,可能会影响到业务系统的可用性。 +- **系统复杂性增加**。加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。 + + + + + +--- + + + +[整理了200本计算机经典书籍,含下载方式](https://github.com/Tyson0314/java-books) + +[Github疯传!谷歌师兄的LeetCode刷题笔记](https://topjavaer.cn/learning-resources/leetcode-note.html) + +[大彬花了一周收集的简历模板](https://mp.weixin.qq.com/s/JEG11UnWdO_Wi8-Qib89VQ) + +[学弟靠这本大厂面试手册,拿了字节跳动offer!](https://mp.weixin.qq.com/s/LVa4H5feXrjZL-DUtQQ0Yg) \ No newline at end of file diff --git a/docs/interview/network/1-input-url-return-page.md b/docs/interview/network/1-input-url-return-page.md new file mode 100644 index 0000000..555cff2 --- /dev/null +++ b/docs/interview/network/1-input-url-return-page.md @@ -0,0 +1,25 @@ +## 说说浏览器中输入URL返回页面过程 + +1. **解析域名**,找到主机 IP。 +2. 浏览器利用 IP 直接与网站主机通信,**三次握手**,建立 TCP 连接。浏览器会以一个随机端口向服务端的 web 程序 80 端口发起 TCP 的连接。 +3. 建立 TCP 连接后,浏览器向主机发起一个HTTP请求。 +4. 参数从客户端传递到服务器端。 +5. 服务器端得到客户端参数之后,进行相应的业务处理,再将结果封装成 HTTP 包,返回给客户端。 +6. 服务器端和客户端的交互完成,断开 TCP 连接(4 次挥手)。 +7. 浏览器**解析响应内容,进行渲染**,呈现给用户。 + +![](http://img.dabin-coder.cn/image/输入url返回页面过程1.png) + +## DNS 域名解析的过程详细讲讲 + +在网络中定位是依靠 IP 进行身份定位的,所以 URL 访问的第一步便是先要得到服务器端的 IP 地址。而得到服务器的 IP 地址需要使用 DNS(Domain Name System,域名系统)域名解析,DNS 域名解析就是通过 URL 找到与之相对应的 IP 地址。 + +DNS 域名解析的大致流程如下: + +1. 先检**查浏览器中的 DNS 缓存**,如果浏览器中有对应的记录会直接使用,并完成解析; +2. 如果浏览器没有缓存,那就去**查询操作系统的缓存**,如果查询到记录就可以直接返回 IP 地址,完成解析; +3. 如果操作系统没有 DNS 缓存,就会去**查看本地 host 文件**,Windows 操作系统下,host 文件一般位于 "C:\Windows\System32\drivers\etc\hosts",如果 host 文件有记录则直接使用; +4. 如果本地 host 文件没有相应的记录,会**请求本地 DNS 服务器**,本地 DNS 服务器一般是由本地网络服务商如移动、联通等提供。通常情况下可通过 DHCP 自动分配,当然也可以自己手动配置。目前用的比较多的是谷歌提供的公用 DNS 是 8.8.8.8 和国内的公用 DNS 是 114.114.114.114。 +5. 如果本地 DNS 服务器没有相应的记录,就会**去根域名服务器查询**了。为了能更高效完成全球所有域名的解析请求,根域名服务器本身并不会直接去解析域名,而是会把不同的解析请求分配给下面的其他服务器去完成。 + +![](http://img.dabin-coder.cn/image/image-20221123001836666.png) \ No newline at end of file diff --git a/docs/interview/network/2-http-status-code.md b/docs/interview/network/2-http-status-code.md new file mode 100644 index 0000000..d309c3f --- /dev/null +++ b/docs/interview/network/2-http-status-code.md @@ -0,0 +1,86 @@ +## 常见的 HTTP 状态码有哪些? + +HTTP 状态码是服务器端返回给客户端的响应状态码,根据状态码我们就能知道服务器端想要给客户端表达的具体含义,比如 200 就表示请求访问成功,500 就表示服务器端程序出错等。HTTP 状态码可分为 5 大类: + +1. 1XX:消息状态码。 +2. 2XX:成功状态码。 +3. 3XX:重定向状态码。 +4. 4XX:客户端错误状态码。 +5. 5XX:服务端错误状态码。 + +这 5 大类中又包含了很多具体的状态码。 + +1XX为**消息状态码**,其中: + +- 100:Continue 继续。客户端应继续其请求。 +- 101:Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到 HTTP 的新版本协议。 + +2XX为**成功状态码**,其中: + +- **200:OK 请求成功。一般用于 GET 与 POST 请求。** +- 201:Created 已创建。成功请求并创建了新的资源。 +- 202:Accepted 已接受。已经接受请求,但未处理完成。 +- 203:Non-Authoritative Information 非授权信息。请求成功。但返回的 meta 信息不在原始的服务器,而是一个副本。 +- 204:No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档。 +- 205:Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域。 +- 206:Partial Content 部分内容。服务器成功处理了部分 GET 请求。 + +3XX为**重定向状态码**,其中: + +- 300:Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择。 +- **301:Moved Permanently 永久移动。请求的资源已被永久的移动到新 URI,返回信息会包括新的 URI,浏览器会自动定向到新 URI。今后任何新的请求都应使用新的 URI 代替。** +- **302:Found 临时移动,与 301 类似。但资源只是临时被移动。客户端应继续使用原有URI。** +- 303:See Other 查看其它地址。与 301 类似。使用 GET 和 POST 请求查看。 +- 304:Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源。 +- 305:Use Proxy 使用代理。所请求的资源必须通过代理访问。 +- 306:Unused 已经被废弃的 HTTP 状态码。 +- 307:Temporary Redirect 临时重定向。与 302 类似。使用 GET 请求重定向。 + +4XX为客户端**错误状态码**,其中: + +- 400:Bad Request 客户端请求的语法错误,服务器无法理解。 +- 401:Unauthorized 请求要求用户的身份认证。 +- 402:Payment Required 保留,将来使用。 +- 403:Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求。 +- **404:Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。** +- **405:Method Not Allowed 客户端请求中的方法被禁止。** +- 406:Not Acceptable 服务器无法根据客户端请求的内容特性完成请求。 +- 407:Proxy Authentication Required 请求要求代理的身份认证,与 401 类似,但请求者应当使用代理进行授权。 +- 408:Request Time-out 服务器等待客户端发送的请求时间过长,超时。 +- 409:Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突。 +- 410:Gone 客户端请求的资源已经不存在。410 不同于 404,如果资源以前有现在被永久删除了可使用 410 代码,网站设计人员可通过 301 代码指定资源的新位置。 +- 411:Length Required 服务器无法处理客户端发送的不带 Content-Length 的请求信息。 +- 412:Precondition Failed 客户端请求信息的先决条件错误。 +- 413:Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个 Retry-After 的响应信息。 +- 414:Request-URI Too Large 请求的 URI 过长(URI通常为网址),服务器无法处理。 +- 415:Unsupported Media Type 服务器无法处理请求附带的媒体格式。 +- 416:Requested range not satisfiable 客户端请求的范围无效。 +- 417:Expectation Failed 服务器无法满足 Expect 的请求头信息。 + +5XX为**服务端错误状态码**,其中: + +- **500:Internal Server Error 服务器内部错误,无法完成请求。** +- 501:Not Implemented 服务器不支持请求的功能,无法完成请求。 +- 502:Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应。 +- 503:Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中。 +- 504:Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求。 +- 505:HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理。 + +**总结一下**: + +HTTP 状态码分为 5 大类:1XX:表示消息状态码;2XX:表示成功状态码;3XX:表示重定向状态码;4XX:表示客户端错误状态码;5XX:表示服务端错误状态码。其中常见的具体状态码有:200:请求成功;301:永久重定向;302:临时重定向;404:无法找到此页面;405:请求的方法类型不支持;500:服务器内部出错。 + + + +--end-- + +最后**推荐几份非常有用的资料**! + +[整理了200本计算机经典书籍,含下载方式](https://mp.weixin.qq.com/s/ynxpvDkTOdk0pY3S5nStZQ) + +[Github疯传!LeetCode刷题笔记(c/c++、Java、Go三个版本)](https://mp.weixin.qq.com/s/3QX1L9fUPAzGVTPrn6tMJQ) + +[大彬花了一周收集的简历模板](https://mp.weixin.qq.com/s/JEG11UnWdO_Wi8-Qib89VQ) + +[学弟靠这本大厂面试手册,拿了字节跳动offer!](https://mp.weixin.qq.com/s/LVa4H5feXrjZL-DUtQQ0Yg) + diff --git "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" b/docs/java/java-basic.md similarity index 91% rename from "Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" rename to docs/java/java-basic.md index bd5b11e..5a40bcb 100644 --- "a/Java/Java\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" +++ b/docs/java/java-basic.md @@ -1,3 +1,8 @@ +--- +sidebar: heading + +--- + ![](http://img.dabin-coder.cn/image/Java基础.jpg) ## Java的特点 @@ -1433,6 +1438,75 @@ server { 通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,这是浏览器允许的操作,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。 +## 设计接口要注意什么? + +1. **接口参数校验**。接口必须校验参数,比如入参是否允许为空,入参长度是否符合预期。 +2. 设计接口时,充分考虑接口的**可扩展性**。思考接口是否可以复用,怎样保持接口的可扩展性。 +3. **串行调用考虑改并行调用**。比如设计一个商城首页接口,需要查商品信息、营销信息、用户信息等等。如果是串行一个一个查,那耗时就比较大了。这种场景是可以改为并行调用的,降低接口耗时。 +4. 接口是否需要**防重**处理。涉及到数据库修改的,要考虑防重处理,可以使用数据库防重表,以唯一流水号作为唯一索引。 +5. **日志打印全面**,入参出参,接口耗时,记录好日志,方便甩锅。 +6. 修改旧接口时,注意**兼容性设计**。 +7. **异常处理得当**。使用finally关闭流资源、使用log打印而不是e.printStackTrace()、不要吞异常等等 +8. 是否需要考虑**限流**。限流为了保护系统,防止流量洪峰超过系统的承载能力。 + +## 过滤器和拦截器有什么区别? + +1、**实现原理不同**。 + +过滤器和拦截器底层实现不同。过滤器是基于函数回调的,拦截器是基于Java的反射机制(动态代理)实现的。一般自定义的过滤器中都会实现一个doFilter()方法,这个方法有一个FilterChain参数,而实际上它是一个回调接口。 + +2、**使用范围不同**。 + +过滤器实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。拦截器不仅能应用在web程序中,也可以用于Application、Swing等程序中。 + +3、**使用的场景不同**。 + +因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断的,比如:日志记录、权限判断等业务。而过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、响应数据压缩等功能。 + +4、**触发时机不同**。 + +过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。 + +拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。 + +5、**拦截的请求范围不同**。 + +请求的执行顺序是:请求进入容器 -> 进入过滤器 -> 进入 Servlet -> 进入拦截器 -> 执行控制器。可以看到过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法。 + +> 参考链接:https://segmentfault.com/a/1190000022833940 + +## 对接第三方接口要考虑什么? + +嗯,需要考虑以下几点: + +1. 确认接口对接的**网络协议**,是https/http或者自定义的私有协议等。 +2. 约定好**数据传参、响应格式**(如application/json),弱类型对接强类型语言时要特别注意 +3. **接口安全**方面,要确定身份校验方式,使用token、证书校验等 +4. 确认是否需要接口调用失败后的**重试**机制,保证数据传输的最终一致性。 +5. **日志记录要全面**。接口出入参数,以及解析之后的参数值,都要用日志记录下来,方便定位问题(甩锅)。 + +参考:https://blog.csdn.net/gzt19881123/article/details/108791034 + +## 后端接口性能优化有哪些方法? + +有以下这些方法: + +1、**优化索引**。给where条件的关键字段,或者`order by`后面的排序字段,加索引。 + +2、**优化sql语句**。比如避免使用select *、批量操作、避免深分页、提升group by的效率等 + +3、**避免大事务**。使用@Transactional注解这种声明式事务的方式提供事务功能,容易造成大事务,引发其他的问题。应该避免在事务中一次性处理太多数据,将一些跟事务无关的逻辑放到事务外面执行。 + +4、**异步处理**。剥离主逻辑和副逻辑,副逻辑可以异步执行,异步写库。比如用户购买的商品发货了,需要发短信通知,短信通知是副流程,可以异步执行,以免影响主流程的执行。 + +5、**降低锁粒度**。在并发场景下,多个线程同时修改数据,造成数据不一致的情况。这种情况下,一般会加锁解决。但如果锁加得不好,导致锁的粒度太粗,也会非常影响接口性能。 + +6、**加缓存**。如果表数据量非常大的话,直接从数据库查询数据,性能会非常差。可以使用Redis`和`memcached提升查询性能,从而提高接口性能。 + +7、**分库分表**。当系统发展到一定的阶段,用户并发量大,会有大量的数据库请求,需要占用大量的数据库连接,同时会带来磁盘IO的性能瓶颈问题。或者数据库表数据非常大,SQL查询即使走了索引,也很耗时。这时,可以通过分库分表解决。分库用于解决数据库连接资源不足问题,和磁盘IO的性能瓶颈问题。分表用于解决单表数据量太大,sql语句查询数据时,即使走了索引也非常耗时问题。 + +8、**避免在循环中查询数据库**。循环查询数据库,非常耗时,最好能在一次查询中获取所有需要的数据。 + ![](http://img.dabin-coder.cn/image/20220612101342.png) \ No newline at end of file diff --git "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" b/docs/java/java-collection.md similarity index 91% rename from "Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" rename to docs/java/java-collection.md index 5af404d..01492e9 100644 --- "a/Java/Java\351\233\206\345\220\210\351\235\242\350\257\225\351\242\230.md" +++ b/docs/java/java-collection.md @@ -1,10 +1,16 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/Java集合.jpg) + ## 常见的集合有哪些? Java集合类主要由两个接口**Collection**和**Map**派生出来的,Collection有三个子接口:List、Set、Queue。 Java集合框架图如下: -![](http://img.dabin-coder.cn/image/collections2.png) +![](http://img.dabin-coder.cn/image/collections.drawio.png) ![](http://img.dabin-coder.cn/image/map.png) @@ -124,7 +130,7 @@ return h&(length-1); //第三步 取模运算 在JDK1.8的实现中,优化了高位运算的算法,通过`hashCode()`的高16位异或低16位实现的:这么做可以在数组比较小的时候,也能保证考虑到高低位都参与到Hash的计算中,可以减少冲突,同时不会有太大的开销。 -## 为什么建议设置HashMap的容量? +### 为什么建议设置HashMap的容量? HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容条件就是当HashMap中的元素个数超过临界值时就会自动扩容(threshold = loadFactor * capacity)。 @@ -147,7 +153,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 5. 链表的数量大于阈值8,就要转换成红黑树的结构 6. 添加成功后会检查是否需要扩容 -![图片来源网络](http://img.dabin-coder.cn/image/hashmap-put.png) +![](http://img.dabin-coder.cn/image/map_put.png) ### 红黑树的特点? @@ -158,7 +164,7 @@ HashMap有扩容机制,就是当达到扩容条件时会进行扩容。扩容 ### 在解决 hash 冲突的时候,为什么选择先用链表,再转红黑树? -因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。所以,当元素个数小于8个的时候,采用链表结构可以保证查询性能。而当元素个数大于8个的时候并且数组容量大于64,会采用红黑树结构。因为红黑树搜索时间复杂度是 `O(logn)`,而链表是 `O(n)`,在n比较大的时候,使用红黑树可以加快查询速度。 +因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。所以,当元素个数小于8个的时候,采用链表结构可以保证查询性能。而当元素个数大于8个的时候并且数组容量大于等于64,会采用红黑树结构。因为红黑树搜索时间复杂度是 `O(logn)`,而链表是 `O(n)`,在n比较大的时候,使用红黑树可以加快查询速度。 ### HashMap 的长度为什么是 2 的幂次方? @@ -322,6 +328,28 @@ ListIterator 是 Iterator的增强版。 - ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。 - ListIterator只能用于遍历List及其子类,Iterator可用来遍历所有集合。 +## 如何让一个集合不能被修改? + +可以采用Collections包下的unmodifiableMap/unmodifiableList/unmodifiableSet方法,通过这个方法返回的集合,是不可以修改的。如果修改的话,会抛出 java.lang.UnsupportedOperationException异常。 + +```java +List list = new ArrayList<>(); +list.add("x"); +Collection clist = Collections.unmodifiableCollection(list); +clist.add("y"); // 运行时此行报错 +System.out.println(list. size()); +``` + +对于List/Set/Map集合,Collections包都有相应的支持。 + +**那使用final关键字进行修饰可以实现吗?** + +答案是不可以。 + +final关键字修饰的成员变量如果是是引用类型的话,则表示这个引用的地址值是不能改变的,但是这个引用所指向的对象里面的内容还是可以改变的。 + +而集合类都是引用类型,用final修饰的话,集合里面的内容还是可以修改的。 + ## 并发容器 JDK 提供的这些容器大部分在 `java.util.concurrent` 包中。 @@ -400,12 +428,22 @@ Copy-On-Write,写时复制。当我们往容器添加元素时,不直接往 ### CopyOnWriteArrayList -CopyOnWriteArrayList相当于线程安全的ArrayList,CopyOnWriteArrayList使用了一种叫写时复制的方法,当有新元素add到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组。 +**CopyOnWriteArrayList**是Java并发包中提供的一个并发容器。CopyOnWriteArrayList相当于线程安全的ArrayList,CopyOnWriteArrayList使用了一种叫写时复制的方法,当有新元素add到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组。 `CopyOnWriteArrayList`中add方法添加的时候是需要加锁的,保证同步,避免了多线程写的时候复制出多个副本。读的时候不需要加锁,如果读的时候有其他线程正在向`CopyOnWriteArrayList`添加数据,还是可以读到旧的数据。 CopyOnWrite并发容器用于读多写少的并发场景。 +**优点**: + +读操作性能很高,因为无需任何同步措施,比较适用于**读多写少**的并发场景。Java的list在遍历时,若中途有别的线程对list容器进行修改,则会抛出**ConcurrentModificationException**异常。而CopyOnWriteArrayList由于其"读写分离"的思想,遍历和修改操作分别作用在不同的list容器,所以在使用迭代器进行遍历时候,也就不会抛出ConcurrentModificationException异常了。 + +**缺点**: + +**一是内存占用问题**,毕竟每次执行写操作都要将原容器拷贝一份,数据量大时,对内存压力较大,可能会引起频繁GC; + +**二是无法保证实时性**,Vector对于读写操作均加锁同步,可以保证读和写的强一致性。而CopyOnWriteArrayList由于其实现策略的原因,写和读分别作用在新老不同容器上,在写操作执行过程中,读不会阻塞但读取到的却是老容器的数据。 + ### ConcurrentLinkedQueue 非阻塞队列。高效的并发队列,使用链表实现。可以看做一个线程安全的 `LinkedList`,通过 CAS 操作实现。 diff --git "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" b/docs/java/java-concurrent.md similarity index 84% rename from "Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" rename to docs/java/java-concurrent.md index 022a2fc..3b1ed25 100644 --- "a/Java/Java\345\271\266\345\217\221\351\235\242\350\257\225\351\242\230.md" +++ b/docs/java/java-concurrent.md @@ -1,7 +1,45 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/并发与多线程知识点总结.jpg) + ## 线程池 线程池:一个管理线程的池子。 +### 为什么平时都是使用线程池创建线程,直接new一个线程不好吗? + +嗯,手动创建线程有两个缺点 + +1. 不受控风险 +2. 频繁创建开销大 + +**为什么不受控**? + +系统资源有限,每个人针对不同业务都可以手动创建线程,并且创建线程没有统一标准,比如创建的线程有没有名字等。当系统运行起来,所有线程都在抢占资源,毫无规则,混乱场面可想而知,不好管控。 + +**频繁手动创建线程为什么开销会大?跟new Object() 有什么差别?** + +虽然Java中万物皆对象,但是new Thread() 创建一个线程和 new Object()还是有区别的。 + +new Object()过程如下: + +1. JVM分配一块内存 M +2. 在内存 M 上初始化该对象 +3. 将内存 M 的地址赋值给引用变量 obj + +创建线程的过程如下: + +1. JVM为一个线程栈分配内存,该栈为每个线程方法调用保存一个栈帧 +2. 每一栈帧由一个局部变量数组、返回值、操作数堆栈和常量池组成 +3. 每个线程获得一个程序计数器,用于记录当前虚拟机正在执行的线程指令地址 +4. 系统创建一个与Java线程对应的本机线程 +5. 将与线程相关的描述符添加到JVM内部数据结构中 +6. 线程共享堆和方法区域 + +创建一个线程大概需要1M左右的空间(Java8,机器规格2c8G)。可见,频繁手动创建/销毁线程的代价是非常大的。 + ### 为什么使用线程池? - **降低资源消耗**。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 @@ -427,31 +465,41 @@ Thread[线程 2,5,main]waiting get resource1 ### 线程都有哪些方法? -**join** +**start** -Thread.join(),在main中创建了thread线程,在main中调用了thread.join()/thread.join(long millis),main线程放弃cpu控制权,线程进入WAITING/TIMED_WAITING状态,等到thread线程执行完才继续执行main线程。 +用于启动线程。 -```java -public final void join() throws InterruptedException { - join(0); -} -``` +**getPriority** -**yield** +获取线程优先级,默认是5,线程默认优先级为5,如果不手动指定,那么线程优先级具有继承性,比如线程A启动线程B,那么线程B的优先级和线程A的优先级相同 -Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。 +**setPriority** -```java -public static native void yield(); //static方法 -``` +设置线程优先级。CPU会尽量将执行资源让给优先级比较高的线程。 -**sleep** +**interrupt** -Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,让出cpu资源,但不释放对象锁,指定时间到后又恢复运行。作用:给其它线程执行机会的最佳方式。 +告诉线程,你应该中断了,具体到底中断还是继续运行,由被通知的线程自己处理。 -```java -public static native void sleep(long millis) throws InterruptedException;//static方法 -``` +当对一个线程调用 interrupt() 时,有两种情况: + +1. 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。 + +2. 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true。不过,被设置中断标志的线程可以继续正常运行,不受影响。 + +interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。 + +**join** + +等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。 + +**yield** + +暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。 + +**sleep** + +使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,线程自动转为Runnable状态。 @@ -612,17 +660,13 @@ class SeasonThreadTask implements Runnable{ ## 线程间通信方式 -### volatile - -**volatile** 使用共享内存实现线程间相互通信。多个线程同时监听一个变量,当这个变量被某一个线程修改的时候,其他线程可以感知到这个变化。 +1、使用 Object 类的 **wait()/notify()**。Object 类提供了线程间通信的方法:`wait()`、`notify()`、`notifyAll()`,它们是多线程通信的基础。其中,`wait/notify` 必须配合 `synchronized` 使用,wait 方法释放锁,notify 方法不释放锁。wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了`notify()`,notify并不释放锁,只是告诉调用过`wait()`的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放,调用 `wait()` 的一个或多个线程就会解除 wait 状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运行。 -### wait 和 notify +2、使用 **volatile** 关键字。基于volatile关键字实现线程间相互通信,其底层使用了共享内存。简单来说,就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。 -`wait/notify`为Object对象的方法,调用`wait/notify`需要先获得对象的锁。对象调用`wait()`之后线程释放锁,将线程放到对象的等待队列,当通知线程调用此对象的`notify()`方法后,等待线程并不会立即从`wait()`返回,需要等待通知线程释放锁(通知线程执行完同步代码块),等待队列里的线程获取锁,获取锁成功才能从`wait()`方法返回,即从`wait()`方法返回前提是线程获得锁。 +3、使用JUC工具类 **CountDownLatch**。jdk1.5 之后在`java.util.concurrent`包下提供了很多并发编程相关的工具类,简化了并发编程开发,`CountDownLatch` 基于 AQS 框架,相当于也是维护了一个线程间共享变量 state。 -### join - -当在一个线程调用另一个线程的`join()`方法时,当前线程阻塞等待被调用join方法的线程执行完毕才能继续执行。`join()`是基于等待通知机制实现的。 +4、基于 **LockSupport** 实现线程间的阻塞和唤醒。`LockSupport` 是一种非常灵活的实现线程间阻塞和唤醒的工具,使用它不用关注是等待线程先进行还是唤醒线程先运行,但是得知道线程的名字。 ## ThreadLocal @@ -715,7 +759,19 @@ public class ThreadLocalDemo { ### ThreadLocal使用场景有哪些? -`ThreadLocal`适用场景:每个线程需要有自己单独的实例,且需要在多个方法中共享实例,即同时满足实例在线程间的隔离与方法间的共享,这种情况适合使用`ThreadLocal`。比如Java web应用中,每个线程有自己单独的`Session`实例,就可以使用`ThreadLocal`来实现。 +**场景1** + +ThreadLocal 用作保存每个线程独享的对象,为每个线程都创建一个副本,这样每个线程都可以修改自己所拥有的副本, 而不会影响其他线程的副本,确保了线程安全。 + +这种场景通常用于保存线程不安全的工具类,典型的使用的类就是 SimpleDateFormat。 + +假如需求为500个线程都要用到 SimpleDateFormat,使用线程池来实现线程的复用,否则会消耗过多的内存等资源,如果我们每个任务都创建了一个 simpleDateFormat 对象,也就是说,500个任务对应500个 simpleDateFormat 对象。但是这么多对象的创建是有开销的,而且这么多对象同时存在在内存中也是一种内存的浪费。可以将simpleDateFormat 对象给提取了出来,变成静态变量,但是这样一来就会有线程不安全的问题。我们想要的效果是,既不浪费过多的内存,同时又想保证线程安全。此时,可以使用 ThreadLocal来达到这个目的,每个线程都拥有一个自己的 simpleDateFormat 对象。 + +**场景2** + +ThreadLocal 用作每个线程内需要独立保存信息,以便供其他方法更方便地获取该信息的场景。每个线程获取到的信息可能都是不一样的,前面执行的方法保存了信息后,后续方法可以通过 ThreadLocal 直接获取到,避免了传参,类似于全局变量的概念。 + +比如Java web应用中,每个线程有自己单独的`Session`实例,就可以使用`ThreadLocal`来实现。 ## AQS原理 @@ -1093,6 +1149,46 @@ SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能 JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,支持并发访问、修改。 另外ConcurrentHashMap使用了一种不同的迭代方式。当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。 +## 怎么判断线程池的任务是不是执行完了? + +有几种方法: + +1、使用线程池的原生函数**isTerminated()**; + +executor提供一个原生函数isTerminated()来判断线程池中的任务是否全部完成。如果全部完成返回true,否则返回false。 + +2、**使用重入锁,维持一个公共计数**。 + +所有的普通任务维持一个计数器,当任务完成时计数器加一(这里要加锁),当计数器的值等于任务数时,这时所有的任务已经执行完毕了。 + +3、**使用CountDownLatch**。 + +它的原理跟第二种方法类似,给CountDownLatch一个计数值,任务执行完毕后,调用countDown()执行计数值减一。最后执行的任务在调用方法的开始调用await()方法,这样整个任务会阻塞,直到这个计数值为零,才会继续执行。 + +这种方式的**缺点**就是需要提前知道任务的数量。 + +4、**submit向线程池提交任务,使用Future判断任务执行状态**。 + +使用submit向线程池提交任务与execute提交不同,submit会有Future类型的返回值。通过future.isDone()方法可以知道任务是否执行完成。 + +## 什么是Future? + +在并发编程中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。 + +Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。 + +举个例子:比如去吃早点时,点了包子和凉菜,包子需要等3分钟,凉菜只需1分钟,如果是串行的一个执行,在吃上早点的时候需要等待4分钟,但是因为你在等包子的时候,可以同时准备凉菜,所以在准备凉菜的过程中,可以同时准备包子,这样只需要等待3分钟。Future就是后面这种执行模式。 + +Future接口主要包括5个方法: + +1. get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕 +2. get(long timeout,TimeUnit unit)做多等待timeout的时间就会返回结果 +3. cancel(boolean mayInterruptIfRunning)方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false。 +4. isDone()方法判断当前方法是否完成 +5. isCancel()方法判断当前方法是否取消 + + +> 参考链接:https://blog.csdn.net/u014209205/article/details/80598209 ![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/Java/Java8\346\226\260\347\211\271\346\200\247.md" b/docs/java/java8-all.md similarity index 87% rename from "Java/Java8\346\226\260\347\211\271\346\200\247.md" rename to docs/java/java8-all.md index efd2c16..86db8d6 100644 --- "a/Java/Java8\346\226\260\347\211\271\346\200\247.md" +++ b/docs/java/java8-all.md @@ -1,37 +1,8 @@ - - - - -- [函数式编程](#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B) -- [Lambda 表达式](#lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F) -- [函数式接口](#%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3) -- [内置的函数式接口](#%E5%86%85%E7%BD%AE%E7%9A%84%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3) - - [Predicate 断言](#predicate-%E6%96%AD%E8%A8%80) - - [Comparator](#comparator) - - [Consumer](#consumer) -- [Stream](#stream) - - [Filter 过滤](#filter-%E8%BF%87%E6%BB%A4) - - [Sorted 排序](#sorted-%E6%8E%92%E5%BA%8F) - - [Map 转换](#map-%E8%BD%AC%E6%8D%A2) - - [Match 匹配](#match-%E5%8C%B9%E9%85%8D) - - [Count 计数](#count-%E8%AE%A1%E6%95%B0) - - [Reduce](#reduce) - - [flatMap](#flatmap) -- [Parallel-Streams](#parallel-streams) -- [Map 集合](#map-%E9%9B%86%E5%90%88) -- [参考资料](#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99) - - - -> 本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础、MySQL、Spring Boot、MyBatis、Redis、RabbitMQ等等,欢迎大家提pr和star! -> -> github地址:https://github.com/Tyson0314/Java-learning -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/Java-learning - -## 函数式编程 +--- +sidebar: heading +--- + +# 函数式编程 面向对象编程:面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。面向对象编程可能需要多写很多重复的代码行。 @@ -47,9 +18,7 @@ 函数式编程:在某些编程语言中,如js、c++,我们可以直接写一个函数,然后在需要的时候进行调用,即函数式编程。 - - -## Lambda 表达式 +# Lambda 表达式 在Java8以前,使用`Collections`的sort方法对字符串排序的写法: @@ -75,7 +44,7 @@ names.sort((a, b) -> b.compareTo(a)); //简化写法二,省略入参类型,J 可以看到使用lambda表示式之后,代码变得很简短并且易于阅读。 -## 函数式接口 +# 函数式接口 Functional Interface:函数式接口,只包含一个抽象方法的接口。只有函数式接口才能缩写成 Lambda 表达式。@FunctionalInterface 定义类为一个函数式接口,如果添加了第二个抽象方法,编译器会立刻抛出错误提示。 @@ -100,11 +69,11 @@ public class FunctionalInterfaceTest { -## 内置的函数式接口 +# 内置的函数式接口 Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterface 注解,以用来支持 Lambda 表达式。 -### Predicate 断言 +## Predicate 断言 指定入参类型,并返回 boolean 值的函数式接口。用来组合一个复杂的逻辑判断。 @@ -114,7 +83,7 @@ Predicate predicate = (s) -> s.length() > 0; predicate.test("dabin"); // true ``` -### Comparator +## Comparator Java8 将 Comparator 升级成函数式接口,可以使用lambda表示式简化代码。 @@ -151,7 +120,7 @@ class Person { ``` -### Consumer +## Consumer Consumer 接口接收一个泛型参数,然后调用 accept,对这个参数做一系列消费操作。 @@ -249,11 +218,11 @@ public class ConsumersTest { } ``` -## Stream +# Stream 使用 `java.util.Stream` 对一个包含一个或多个元素的集合做各种操作,原集合不变,返回新集合。只能对实现了 `java.util.Collection` 接口的类做流的操作。`Map` 不支持 `Stream` 流。`Stream` 流支持同步执行,也支持并发执行。 -### Filter 过滤 +## Filter 过滤 Filter` 的入参是一个 `Predicate,用于筛选出我们需要的集合元素。原集合不变。filter 会过滤掉不符合特定条件的,下面的代码会过滤掉`nameList`中不以大彬开头的字符串。 @@ -284,7 +253,7 @@ public class StreamTest { } ``` -### Sorted 排序 +## Sorted 排序 自然排序,不改变原集合,返回排序后的集合。 @@ -333,7 +302,7 @@ list.stream().sorted(Comparator.comparing(Student::getAge).reversed()); list.stream().sorted(Comparator.comparing(Student::getAge)); ``` -### Map 转换 +## Map 转换 将每个字符串转为大写。 @@ -362,7 +331,7 @@ public class StreamTest2 { } ``` -### Match 匹配 +## Match 匹配 验证 nameList 中的字符串是否有以`大彬`开头的。 @@ -393,7 +362,7 @@ public class StreamTest3 { } ``` -### Count 计数 +## Count 计数 统计 `stream` 流中的元素总数,返回值是 `long` 类型。 @@ -426,7 +395,7 @@ public class StreamTest4 { } ``` -### Reduce +## Reduce 类似拼接。可以实现将 `list` 归约成一个值。它的返回类型是 `Optional` 类型。 @@ -458,7 +427,7 @@ public class StreamTest5 { ``` -### flatMap +## flatMap flatMap 用于将多个Stream连接成一个Stream。 @@ -521,7 +490,7 @@ public class StreamTest7 { -## Parallel-Streams +# Parallel-Streams 并行流。`stream` 流是支持**顺序**和**并行**的。顺序流操作是单线程操作,串行化的流无法带来性能上的提升,通常我们会使用多线程来并行执行任务,处理速度更快。 @@ -552,7 +521,7 @@ public class StreamTest7 { -## Map 集合 +# Map 集合 Java8 针对 map 操作增加了一些方法,非常方便 @@ -670,16 +639,8 @@ public class MapTest3 { -## 参考资料 +# 参考资料 `https://juejin.im/post/5c3d7c8a51882525dd591ac7#heading-16` - -最后给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ - -github地址:https://github.com/Tyson0314/java-books - -如果github访问不了,可以访问gitee仓库。 - -gitee地址:https://gitee.com/tysondai/java-books \ No newline at end of file diff --git a/docs/java/java8/1-functional-program.md b/docs/java/java8/1-functional-program.md new file mode 100644 index 0000000..e41f981 --- /dev/null +++ b/docs/java/java8/1-functional-program.md @@ -0,0 +1,16 @@ +# 函数式编程 + +面向对象编程:面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。面向对象编程可能需要多写很多重复的代码行。 + +```java + Runnable runnable = new Runnable() { + @Override + public void run() { + System.out.println("do something..."); + } + }; + +``` + +函数式编程:在某些编程语言中,如js、c++,我们可以直接写一个函数,然后在需要的时候进行调用,即函数式编程。 + diff --git a/docs/java/java8/2-lambda.md b/docs/java/java8/2-lambda.md new file mode 100644 index 0000000..ae09126 --- /dev/null +++ b/docs/java/java8/2-lambda.md @@ -0,0 +1,26 @@ +# Lambda 表达式 + +在Java8以前,使用`Collections`的sort方法对字符串排序的写法: + +```java +List names = Arrays.asList("dabin", "tyson", "sophia"); + +Collections.sort(names, new Comparator() { + @Override + public int compare(String a, String b) { + return b.compareTo(a); + } +}); +``` + +Java8 推荐使用lambda表达式,简化这种写法。 + +```java +List names = Arrays.asList("dabin", "tyson", "sophia"); + +Collections.sort(names, (String a, String b) -> b.compareTo(a)); //简化写法一 +names.sort((a, b) -> b.compareTo(a)); //简化写法二,省略入参类型,Java 编译器能够根据类型推断机制判断出参数类型 +``` + +可以看到使用lambda表示式之后,代码变得很简短并且易于阅读。 + diff --git a/docs/java/java8/3-functional-interface.md b/docs/java/java8/3-functional-interface.md new file mode 100644 index 0000000..f3f9b81 --- /dev/null +++ b/docs/java/java8/3-functional-interface.md @@ -0,0 +1,25 @@ +# 函数式接口 + +Functional Interface:函数式接口,只包含一个抽象方法的接口。只有函数式接口才能缩写成 Lambda 表达式。@FunctionalInterface 定义类为一个函数式接口,如果添加了第二个抽象方法,编译器会立刻抛出错误提示。 + +```java +@FunctionalInterface +interface Converter { + T convert(F from); +} + +public class FunctionalInterfaceTest { + public static void main(String[] args) { + Converter converter = (from) -> Integer.valueOf(from); + Integer converted = converter.convert("666"); + System.out.println(converted); + } + /** + * output + * 666 + */ +} +``` + + + diff --git a/docs/java/java8/4-inner-functional-interface.md b/docs/java/java8/4-inner-functional-interface.md new file mode 100644 index 0000000..5fcc9be --- /dev/null +++ b/docs/java/java8/4-inner-functional-interface.md @@ -0,0 +1,149 @@ +# 内置的函数式接口 + +Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterface 注解,以用来支持 Lambda 表达式。 + +## Predicate 断言 + +指定入参类型,并返回 boolean 值的函数式接口。用来组合一个复杂的逻辑判断。 + +```java +Predicate predicate = (s) -> s.length() > 0; + +predicate.test("dabin"); // true +``` + +## Comparator + +Java8 将 Comparator 升级成函数式接口,可以使用lambda表示式简化代码。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-05 23:24 + */ +public class ComparatorTest { + public static void main(String[] args) { + Comparator comparator = Comparator.comparing(p -> p.firstName); + + Person p1 = new Person("dabin", "wang"); + Person p2 = new Person("xiaobin", "wang"); + + // 打印-20 + System.out.println(comparator.compare(p1, p2)); + // 打印20 + System.out.println(comparator.reversed().compare(p1, p2)); + } + +} + +class Person { + public String firstName; + public String lastName; + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } +} +``` + + +## Consumer + +Consumer 接口接收一个泛型参数,然后调用 accept,对这个参数做一系列消费操作。 + +Consumer 源码: + +```java +@FunctionalInterface +public interface Consumer { + + void accept(T t); + + default Consumer andThen(Consumer after) { + Objects.requireNonNull(after); + return (T t) -> { accept(t); after.accept(t); }; + } +} +``` + +示例1: + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-05 23:41 + */ +public class ConsumerTest { + public static void main(String[] args) { + Consumer consumer = x -> { + int a = x + 6; + System.out.println(a); + System.out.println("大彬" + a); + }; + consumer.accept(660); + } + /** + * output + * 666 + * 大彬666 + */ +} +``` + +示例2:在stream里,对入参做一些操作,主要是用于forEach,对传入的参数,做一系列的业务操作。 + +```java +// CopyOnWriteArrayList +public void forEach(Consumer action) { + if (action == null) throw new NullPointerException(); + Object[] elements = getArray(); + int len = elements.length; + for (int i = 0; i < len; ++i) { + @SuppressWarnings("unchecked") E e = (E) elements[i]; + action.accept(e); + } +} + +CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); +list.add(1); +list.add(2); +//forEach需要传入Consumer参数 +list + .stream() + .forEach(System.out::println); +list.forEach(System.out::println); +``` + +示例3:addThen方法使用。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-05 23:59 + */ +public class ConsumersTest { + public static void main(String[] args) { + Consumer consumer1 = x -> System.out.println("first x : " + x); + Consumer consumer2 = x -> { + System.out.println("second x : " + x); + throw new NullPointerException("throw exception second"); + }; + Consumer consumer3 = x -> System.out.println("third x : " + x); + + consumer1.andThen(consumer2).andThen(consumer3).accept(1); + } + /** + * output + * first x : 1 + * second x : 1 + * Exception in thread "main" java.lang.NullPointerException: throw exception second + * at com.dabin.java8.ConsumersTest.lambda$main$1(ConsumersTest.java:15) + * ... + */ +} +``` + diff --git a/docs/java/java8/5-stream.md b/docs/java/java8/5-stream.md new file mode 100644 index 0000000..129f075 --- /dev/null +++ b/docs/java/java8/5-stream.md @@ -0,0 +1,272 @@ +# Stream + +使用 `java.util.Stream` 对一个包含一个或多个元素的集合做各种操作,原集合不变,返回新集合。只能对实现了 `java.util.Collection` 接口的类做流的操作。`Map` 不支持 `Stream` 流。`Stream` 流支持同步执行,也支持并发执行。 + +## Filter 过滤 + +Filter` 的入参是一个 `Predicate,用于筛选出我们需要的集合元素。原集合不变。filter 会过滤掉不符合特定条件的,下面的代码会过滤掉`nameList`中不以大彬开头的字符串。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("大彬1"); + nameList.add("大彬2"); + nameList.add("aaa"); + nameList.add("bbb"); + + nameList + .stream() + .filter((s) -> s.startsWith("大彬")) + .forEach(System.out::println); + } + /** + * output + * 大彬1 + * 大彬2 + */ +} +``` + +## Sorted 排序 + +自然排序,不改变原集合,返回排序后的集合。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest1 { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("大彬3"); + nameList.add("大彬1"); + nameList.add("大彬2"); + nameList.add("aaa"); + nameList.add("bbb"); + + nameList + .stream() + .filter((s) -> s.startsWith("大彬")) + .sorted() + .forEach(System.out::println); + } + /** + * output + * 大彬1 + * 大彬2 + * 大彬3 + */ +} +``` + +逆序排序: + +```java +nameList + .stream() + .sorted(Comparator.reverseOrder()); +``` + +对元素某个字段排序: + +```java +list.stream().sorted(Comparator.comparing(Student::getAge).reversed()); +list.stream().sorted(Comparator.comparing(Student::getAge)); +``` + +## Map 转换 + +将每个字符串转为大写。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest2 { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("aaa"); + nameList.add("bbb"); + + nameList + .stream() + .map(String::toUpperCase) + .forEach(System.out::println); + } + /** + * output + * AAA + * BBB + */ +} +``` + +## Match 匹配 + +验证 nameList 中的字符串是否有以`大彬`开头的。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest3 { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("大彬1"); + nameList.add("大彬2"); + + boolean startWithDabin = + nameList + .stream() + .map(String::toUpperCase) + .anyMatch((s) -> s.startsWith("大彬")); + + System.out.println(startWithDabin); + } + /** + * output + * true + */ +} +``` + +## Count 计数 + +统计 `stream` 流中的元素总数,返回值是 `long` 类型。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest4 { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("大彬1"); + nameList.add("大彬2"); + nameList.add("aaa"); + + long count = + nameList + .stream() + .map(String::toUpperCase) + .filter((s) -> s.startsWith("大彬")) + .count(); + + System.out.println(count); + } + /** + * output + * 2 + */ +} +``` + +## Reduce + +类似拼接。可以实现将 `list` 归约成一个值。它的返回类型是 `Optional` 类型。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:22 + */ +public class StreamTest5 { + public static void main(String[] args) { + List nameList = new ArrayList<>(); + nameList.add("大彬1"); + nameList.add("大彬2"); + + Optional reduced = + nameList + .stream() + .sorted() + .reduce((s1, s2) -> s1 + "#" + s2); + + reduced.ifPresent(System.out::println); + } + /** + * output + * 大彬1#大彬2 + */ +} +``` + + +## flatMap + +flatMap 用于将多个Stream连接成一个Stream。 + +下面的例子,把几个小的list转换到一个大的list。 + +```java +/** + * @description: 把几个小的list转换到一个大的list。 + * @author: 程序员大彬 + * @time: 2021-09-06 00:28 + */ +public class StreamTest6 { + public static void main(String[] args) { + List team1 = Arrays.asList("大彬1", "大彬2", "大彬3"); + List team2 = Arrays.asList("大彬4", "大彬5"); + + List> players = new ArrayList<>(); + players.add(team1); + players.add(team2); + + List flatMapList = players.stream() + .flatMap(pList -> pList.stream()) + .collect(Collectors.toList()); + + System.out.println(flatMapList); + } + /** + * output + * [大彬1, 大彬2, 大彬3, 大彬4, 大彬5] + */ +} +``` +下面的例子中,将words数组中的元素按照字符拆分,然后对字符去重。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:35 + */ +public class StreamTest7 { + public static void main(String[] args) { + List words = new ArrayList(); + words.add("大彬最强"); + words.add("大彬666"); + + //将words数组中的元素按照字符拆分,然后对字符去重 + List stringList = words.stream() + .flatMap(word -> Arrays.stream(word.split(""))) + .distinct() + .collect(Collectors.toList()); + stringList.forEach(e -> System.out.print(e + ", ")); + } + /** + * output + * 大, 彬, 最, 强, 6, + */ +} +``` + + + diff --git a/docs/java/java8/6-parallel-stream.md b/docs/java/java8/6-parallel-stream.md new file mode 100644 index 0000000..f1370c8 --- /dev/null +++ b/docs/java/java8/6-parallel-stream.md @@ -0,0 +1,31 @@ +# Parallel-Streams + +并行流。`stream` 流是支持**顺序**和**并行**的。顺序流操作是单线程操作,串行化的流无法带来性能上的提升,通常我们会使用多线程来并行执行任务,处理速度更快。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-06 00:05 + */ +public class StreamTest7 { + public static void main(String[] args) { + int max = 100; + List strs = new ArrayList<>(max); + for (int i = 0; i < max; i++) { + UUID uuid = UUID.randomUUID(); + strs.add(uuid.toString()); + } + + List sortedStrs = strs.stream().sorted().collect(Collectors.toList()); + System.out.println(sortedStrs); + } + /** + * output + * [029be6d0-e77e-4188-b511-f1571cdbf299, 02d97425-b696-483a-80c6-e2ef51c05d83, 0632f1e9-e749-4bce-8bac-1cf6c9e93afa, ...] + */ +} +``` + + + diff --git a/docs/java/java8/7-map.md b/docs/java/java8/7-map.md new file mode 100644 index 0000000..9eee660 --- /dev/null +++ b/docs/java/java8/7-map.md @@ -0,0 +1,118 @@ +# Map 集合 + +Java8 针对 map 操作增加了一些方法,非常方便 + +1、删除元素使用`removeIf()`方法。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-07 00:03 + */ +public class MapTest { + public static void main(String[] args) { + + Map map = new HashMap<>(); + map.put(1, "dabin1"); + map.put(2, "dabin2"); + + //删除value没有含有1的键值对 + map.values().removeIf(value -> !value.contains("1")); + + System.out.println(map); + } + /** + * output + * {1=dabin1} + */ +} +``` + +2、`putIfAbsent(key, value) ` 如果指定的 key 不存在,则 put 进去。 + +```java +/** + * @description: + * @author: 程序员大彬 + * @time: 2021-09-07 00:08 + */ +public class MapTest1 { + public static void main(String[] args) { + + Map map = new HashMap<>(); + map.put(1, "大彬1"); + + for (int i = 0; i < 3; i++) { + map.putIfAbsent(i, "大彬" + i); + } + map.forEach((id, val) -> System.out.print(val + ", ")); + } + /** + * output + * 大彬0, 大彬1, 大彬2 + */ +} +``` + +3、map 转换。 + +```java +/** + * @author: 程序员大彬 + * @time: 2021-09-07 08:15 + */ +public class MapTest2 { + public static void main(String[] args) { + Map map = new HashMap<>(); + map.put("1", 1); + map.put("2", 2); + + Map newMap = map.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> "大彬" + String.valueOf(e.getValue()))); + + newMap.forEach((key, val) -> System.out.print(val + ", ")); + } + /** + * output + * 大彬1, 大彬2, + */ +} +``` + +4、map遍历。 + +```java +/** + * @author: 程序员大彬 + * @time: 2021-09-07 08:31 + */ +public class MapTest3 { + public static void main(String[] args) { + Map map = new HashMap<>(); + map.put(1, "大彬1"); + map.put(2, "大彬2"); + + //方式1 + map.keySet().forEach(k -> { + System.out.print(map.get(k) + ", "); + }); + + //方式2 + map.entrySet().iterator().forEachRemaining(e -> System.out.print(e.getValue() + ", ")); + + //方式3 + map.entrySet().forEach(entry -> { + System.out.print(entry.getValue() + ", "); + }); + + //方式4 + map.values().forEach(v -> { + System.out.print(v + ", "); + }); + } +} +``` + + + diff --git a/docs/java/java8/README.md b/docs/java/java8/README.md new file mode 100644 index 0000000..0644930 --- /dev/null +++ b/docs/java/java8/README.md @@ -0,0 +1,11 @@ + +## Java8总结 + +- [函数式编程](./1-functional-program.md) +- [Lambda表达式](./2-lambda.md) +- [函数式接口](./3-functional-interface.md) +- [内置的函数式接口](./4-inner-functional-interface.md) +- [Stream](./5-stream.md) +- [Parallel-Streams](./6-parallel-stream.md) +- [Map集合](./7-map.md) + diff --git "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" b/docs/java/jvm.md similarity index 87% rename from "Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" rename to docs/java/jvm.md index 3f2af40..c29e00f 100644 --- "a/Java/JVM\351\253\230\351\242\221\351\235\242\350\257\225\351\242\230.md" +++ b/docs/java/jvm.md @@ -1,10 +1,20 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/JVM知识点总结.jpg) + +## 什么是JVM? + +JVM,全称Java Virtual Machine(Java虚拟机),是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由**一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等**组成。JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“**一次编译,到处运行的**”原因。 + ## 讲一下JVM内存结构? JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本地方法栈**、**堆**、**方法区**。 ![](http://img.dabin-coder.cn/image/jvm内存结构0.png) -### 程序计数器 +**程序计数器** 线程私有的,作为当前线程的行号指示器,用于记录当前虚拟机正在执行的线程指令地址。程序计数器主要有两个作用: @@ -13,7 +23,7 @@ JVM内存结构分为5大区域,**程序计数器**、**虚拟机栈**、**本 程序计数器是唯一一个不会出现 `OutOfMemoryError` 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。 -### 虚拟机栈 +**虚拟机栈** Java 虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:**局部变量表**、**操作数栈**、**动态链接**、**方法出口信息**。每一次函数调用都会有一个对应的栈帧被压入虚拟机栈,每一个函数调用结束后,都会有一个栈帧被弹出。 @@ -32,13 +42,13 @@ Java 虚拟机栈也是线程私有的,每个线程都有各自的 Java 虚拟 java -Xss2M ``` -### 本地方法栈 +**本地方法栈** 虚拟机栈为虚拟机执行 `Java` 方法服务,而本地方法栈则为虚拟机使用到的 `Native` 方法服务。`Native` 方法一般是用其它语言(C、C++等)编写的。 本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。 -### 堆 +**堆** 堆用于存放对象实例,是垃圾收集器管理的主要区域,因此也被称作`GC`堆。堆可以细分为:新生代(`Eden`空间、`From Survivor`、`To Survivor`空间)和老年代。 @@ -48,17 +58,17 @@ java -Xss2M java -Xms1M -Xmx2M ``` -### 方法区 +1.方法区 方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 对方法区进行垃圾回收的主要目标是**对常量池的回收和对类的卸载**。 -**永久代** +2.永久代 方法区是 JVM 的规范,而永久代`PermGen`是方法区的一种实现方式,并且只有 `HotSpot` 有永久代。对于其他类型的虚拟机,如`JRockit`没有永久代。由于方法区主要存储类的相关信息,所以对于动态生成类的场景比较容易出现永久代的内存溢出。 -**元空间** +3.元空间 JDK 1.8 的时候,`HotSpot`的永久代被彻底移除了,使用元空间替代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。两者最大的区别在于:元空间并不在虚拟机中,而是使用直接内存。 @@ -66,11 +76,11 @@ JDK 1.8 的时候,`HotSpot`的永久代被彻底移除了,使用元空间替 永久代内存受限于 JVM 可用内存,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是相比永久代内存溢出的概率更小。 -### 运行时常量池 +**运行时常量池** 运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。 -### 直接内存 +**直接内存** 直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 `OutOfMemoryError` 错误出现。 @@ -643,6 +653,30 @@ Java 内存中的对象由以下三部分组成:**对象头**、**实例数据 1. 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。 +## Object o = new Object()占用多少个字节? + +答案是16个字节。 + +首先先分析对象的内存布局。 + +在 JVM 中,Java对象保存在堆中时,由以下三部分组成: + +**对象头(Object Header)**:包括关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。由两个词`mark word`和`classpointer`组成,如果是数组对象的话,还会有一个`length field`。 + +- mark word:通常是一组位域,用于存储对象自身的运行时数据,如hashCode、GC分代年龄、锁同步信息等等。占用64个比特(64位系统),8个字节。 +- classpointer:类指针,是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。占用64个比特(64位系统),8个字节。开启压缩类指针后,占用32个比特,4个字节。 + +**实例数据(Instance Data)**:存储了代码中定义的各种字段的内容,包括从父类继承下来的字段和子类中定义的字段。如果对象无属性字段,则这里就不会有数据。根据字段类型的不同占不同的字节,例如boolean类型占1个字节,int类型占4个字节等等。为了提高存储空间的利用率,这部分数据的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响。 + +**对齐填充(Padding)**:对象可以有对齐数据也可以没有。默认情况下,Java虚拟机堆中对象的起始地址需要对齐至8的整数倍。如果一个对象的对象头和实例数据占用的总大小不到8字节的整数倍,则以此来填充对象大小至8字节的整数倍。 + +> **为什么要对齐填充**?字段内存对齐的其中一个原因,是让字段只出现在同一CPU的缓存行中。如果字段不是对齐的,那么就有可能出现跨缓存行的字段。也就是说,该字段的读取可能需要替换两个缓存行,而该字段的存储也会同时污染两个缓存行。这两种情况对程序的执行效率而言都是不利的。其实对其填充的最终目的是为了计算机**高效寻址**。 + +经过上面的分析之后,就可以知道Object o = new Object()具体占用多少内存了(以64位系统为例)。 + +- **在开启指针压缩的情况下**,markword占用8字节,classpointer占用4字节,Instance data无数据,总共是12字节,由于对象需要为8的整数倍,Padding会补充4个字节,总共占用16字节。 +- **在没有开启指针压缩的情况下**,markword占用8字节,classpointer占用8字节,Instance data无数据,也是占用16字节。 + ## main方法执行过程 以下是示例代码: @@ -695,6 +729,34 @@ class Person { - jstat 查看监控JVM的内存和GC情况,评估问题大概出在什么区域 - 使用MAT工具载入dump文件,分析大对象的占用情况 +## 什么是内存溢出和内存泄露? + +内存溢出指的是程序申请内存时,**没有足够的内存**供申请者使用,比如给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即内存溢出。 + +内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分**内存不可用**的情况。这种情况重启计算机可以解决,但也有可能再次发生内存泄露。内存泄露和硬件没有关系,它是由软件设计缺陷引起的。 + +像IO操作或者网络连接等,在使用完成之后没有调用close()方法将其连接关闭,那么它们占用的内存是不会自动被GC回收的,此时就会产生内存泄露。 + +比如操作数据库时,通过SessionFactory获取一个session: + +```java +Session session=sessionFactory.openSession(); +``` + +完成后我们必须调用session.close()方法关闭,否则就会产生内存泄露,因为sessionFactory这个长生命周期对象一直持有session这个短生命周期对象的引用。 + +那两者有什么不同呢? + +内存泄露可以通过完善代码来避免,内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。 + +如何避免内存泄露和溢出呢? + +1. **尽早释放无用对象的引用**。比如使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。 +2. **尽量少用静态变量**。因为静态变量是全局的,GC不会回收。 +3. **避免集中创建对象尤其是大对象**,如果可以的话尽量使用流操作。 +4. 尽量运用**池化技术**(数据库连接池等)以提高系统性能。 +5. **避免在循环中创建过多对象**。 + **参考资料** diff --git a/docs/learn/ghelper.md b/docs/learn/ghelper.md new file mode 100644 index 0000000..8c9e6da --- /dev/null +++ b/docs/learn/ghelper.md @@ -0,0 +1,63 @@ +**Ghelper是一款谷歌浏览器插件,用于访问google。** + +第一步:下载并安装**Chrome浏览器**。 + +Chrome下载链接:[点击下载](https://links.jianshu.com/go?to=https%3A%2F%2Fdl.softmgr.qq.com%2Foriginal%2FBrowser%2F87.0.4280.88_chrome_installer_32.exe) + +安装完成后我们可以准备Ghelper插件 + + + +第二步:下载Ghelper.crx插件 + +Ghelper可以在google play商店进行下载,需要访问google商店,无法直接下载的小伙伴,可以微信搜索「**程序员大彬**」或者扫描下面的二维码,发送关键字「**ghelper**」下载。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) + + + +第三步:在浏览器中安装插件 + + ①. 首先需要【打开浏览器】,在右上角找到【设置】按钮 + + ②. 找到【更多工具】选项 + + ③. 找到【扩展程序】 + +![](http://img.dabin-coder.cn/image/image-20221029164558200.png) + + ④. 打开【开发者选项】 + +![](http://img.dabin-coder.cn/image/image-20221029164617082.png) + +步骤④ + + ⑤. 将插件文件【拖拽】至界面中,点击【添加扩展程序】即可完成。 + +![](http://img.dabin-coder.cn/image/image-20221029164638825.png) + +拖拽 + +![](http://img.dabin-coder.cn/image/image-20221029164652442.png) + +确认添加 + +**至此添加完成** + +**最后可以通过右上角插件按钮管理已添加的插件** + +![image-20221029164706044](http://img.dabin-coder.cn/image/image-20221029164706044.png) + +图钉按钮可固定 + +**至此安装全部结束。** + + + +> 最后给大家分享一个Github仓库,上面有大彬整理的**300多本经典的计算机书籍PDF**,包括**C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生**等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ + +![](http://img.dabin-coder.cn/image/Image.png) + +![](http://img.dabin-coder.cn/image/image-20221030094126118.png) + +**Github地址**:https://github.com/Tyson0314/java-books \ No newline at end of file diff --git a/docs/learn/leetcode.md b/docs/learn/leetcode.md new file mode 100644 index 0000000..5eecf26 --- /dev/null +++ b/docs/learn/leetcode.md @@ -0,0 +1,25 @@ +在学习数据结构和算法,或者准备面试的小伙伴们,千万不要错过这份宝藏算法笔记! + +![](http://img.dabin-coder.cn/image/image-20210828120937311.png) + +![](http://img.dabin-coder.cn/image/image-20210828121035926.png) + +**手册获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**谷歌**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) + + + + + +--- + + + +> 最后给大家分享一个Github仓库,上面有大彬整理的**300多本经典的计算机书籍PDF**,包括**C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生**等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ + +![](http://img.dabin-coder.cn/image/Image.png) + +![](http://img.dabin-coder.cn/image/image-20221030094126118.png) + +**Github地址**:https://github.com/Tyson0314/java-books \ No newline at end of file diff --git a/docs/learn/manual.md b/docs/learn/manual.md new file mode 100644 index 0000000..f2129e9 --- /dev/null +++ b/docs/learn/manual.md @@ -0,0 +1,22 @@ +大家好,我是大彬~ + +最近抽空将小破站的**面试题汇总成PDF手册**了,方便小伙伴打印出来看。手册内容基本跟网站上的一致,包含**Java基础、MySQL、SpringBoot、MyBatis、Redis、RabbitMQ、计算机网络、数据结构与算法、微服务、场景题**等内容。 + +这份面试手册非常**详细**,并且有相应的**配图讲解**: + +![](http://img.dabin-coder.cn/image/image-20211127163043770.png) + +![](http://img.dabin-coder.cn/image/image-20211127151141076.png) + +![](http://img.dabin-coder.cn/image/image-20220316234337881.png) + +![](http://img.dabin-coder.cn/image/image-20211127150136157.png) + +![](http://img.dabin-coder.cn/image/image-20211127150322032.png) + +**手册获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**手册**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image//公众号.jpg) + +祝大家学习愉快! + diff --git a/docs/learning-resources/chang-gou-mall.md b/docs/learning-resources/chang-gou-mall.md new file mode 100644 index 0000000..51cc3fc --- /dev/null +++ b/docs/learning-resources/chang-gou-mall.md @@ -0,0 +1,15 @@ +畅购商城项目是一个B2C的电商网站,采用了微服务架构,并且使用了前后端分离的方式进行开发。 + +整个微服务的开发是基于SpringBoot的,OAuth2.0是用来进行授权操作的,JWT用来封装用户的授权信息,Spring AMQP是消息队列协议。然后就是一套Spring Cloud的微服务框架。 + +持久化技术栈选用了MyBatis。数据库采用了MySQL,消息队列选用了RabbitMQ,还实现了MySQL读写分离。支付接口就选择了微信支付。 + +项目架构图如下: + +![](http://img.dabin-coder.cn/image/畅购商城.jpg) + +这个项目比较适合在校生学习,推荐给大家。 + +**获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**畅购**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) \ No newline at end of file diff --git a/docs/learning-resources/cs-learn-guide.md b/docs/learning-resources/cs-learn-guide.md new file mode 100644 index 0000000..fa5ae59 --- /dev/null +++ b/docs/learning-resources/cs-learn-guide.md @@ -0,0 +1,273 @@ +--- +sidebar: heading +--- + +大家好,我是大彬~今天给大家分享CS自学路线。 + +首先看看计算机专业的培养体系,基本上每个学校都差不多: + +![](http://img.dabin-coder.cn/image/20220703110718.png) + +像计算机组成原理、操作系统等课程让我们了解计算机体系结构的基本知识和概念,计算机是怎么运行的,学习计算机的基本组成原理和内部运行机制,并探索硬、软件之间相互作用的关系,以及如何有效利用硬件提高系统性能。 + +计算机网络则是让你明白计算机网络的概念、原理和体系结构,知道计算机分层结构,物理层、数据链路层、介质访问子层、网络层、传输层和应用层的基本原理和协议,掌握以 TCP/IP 协议族为主的网络协议结构,并且了解网络新技术的最新发展。 + +编译原理则是介绍编译程序构造的原理与实践,让你明白高级语言都是如何被转换为另外一种语言的。学完编译原理,可以尝试自己去实现一个完整的小型面向对象语言的编译程序。 + +汇编语言则是高级语言在机器层面的表示,掌握这两种语言的对应可以将程序的执行与计算机的工作过程紧密联系起来,直接体现汇编语言本身固有的特点,即它是最易于将“程序”和“机器” 统一起来的一个结合点。 + +计算机专业课程里边,**计算机核心课程无非以下几个:** + +1. **计算机组成原理** +2. **操作系统** +3. **编译原理** +4. **计算机网络** +5. **数据结构与算法** +6. **数据库基础** + +![](http://img.dabin-coder.cn/image/20220703162734.png) + +## 操作系统 + +无论学习什么编程语言,和需要和操作系统打交道。如果对操作系统不熟悉,那么你在未来的学习路上将会遇到很多障碍,比如线程进程调度、内存分配、Java的虚拟机等知识,都会一头雾水。因此,只有把操作系统搞明白了,才能够更好地学习计算机的其他知识。 + +**书籍推荐** + +入门级别书籍:**《现代操作系统》、《操作系统导论》**,进阶:**《深入理解计算机系统》** + +强推《深入理解计算机系统》 这本书。 + +![](http://img.dabin-coder.cn/image/20220703132845.jpg) + +CSAPP是一本很好的书,糅合了计算机组成原理、操作系统、网络编程、并行程序设计原理等课程的基础知识。对于刚接触编程,或者像大彬这种非科班出身的人来说,这是一本指导性的书,它会告诉你,要想成为一个优秀的程序员,应当重点理解哪些计算机底层原理,告诉你应该在以后的自学过程中,应该重点学习哪些课程,比如操作系统和体系结构等。 + +**视频教程推荐** + +Udacity的Advanced OS公开课:https://www.classcentral.com/course/udacity-advanced-operating-systems-1016 + +还有国内不错的操作系统的课程,清华大学的公开课:https://www.xuetangx.com/course/THU08091000267/5883104?channel=search_result + +![](http://img.dabin-coder.cn/image/20220703132955.png) + +由清华大学两位老师向勇、陈渝讲授,同时配有一套完整的实验,实验内容是从无到有地建立起一个小却五脏俱全的操作系统,以主流操作系统为实例,以教学操作系统ucore为实验环境,讲授操作系统的概念、基本原理和实现技术,为学生从事操作系统软件研究和开发,以及充分利用操作系统功能进行应用软件研究和开发打下扎实的基础。 + +另外,推荐另一门MIT操作系统课程:**MIT6.268** + +课程地址:https://pdos.csail.mit.edu/6.828/2018/schedule.html + +![](http://img.dabin-coder.cn/image/20220626115851.png) + +MIT6.828 是一门非常值得学习的课程,广受好评,是**理论与实践相结合的经典**。 + +只要你跟着项目一步一步走,做完 6 个实验,就能实现一个简单的操作系统内核。 + +每个实验都有对应的知识点,学完理论知识后会有相应的练习,学习体验非常棒! + +**建议**在开始学习这门课之前先熟悉C和汇编,对计算机组成有一定了解。 + +**操作系统主要知识点**: + +- 操作系统的基础特征 +- 进程与线程的本质区别、以及各自的使用场景 +- 进程的几种状态 +- 进程通信方法的特点以及使用场景 +- 进程任务调度算法的特点以及使用场景 +- 死锁的原因、必要条件、死锁处理。手写死锁代码、Java是如何解决死锁的。 +- 线程实现的方式 +- 协程的作用 +- 内存管理的方式 +- 虚拟内存的作用,分页系统实现虚拟内存原理 +- 页面置换算法的原理 +- 静态链接和动态链接 + +## 计算机组成原理 + +计算机组成原理,主要学习计算机的基本组成原理和内部运行机制,并探索硬、软件之间相互作用的关系,以及如何有效利用硬件提高系统性能。 + +**书籍推荐** + +《计算机是怎样跑起来的》这本书相对比较基础,描述计算机各个方面。从单片机电路开始,汇编,结构化程序,数据结构于算法,面向对象,数据库,TCP/IP原理,加密解密,XML,软件工程统统有清晰描述,易于理解。在知识的整体理解基础上再阅读文档,学习编程会事半功倍。所以而推荐本书。 + +![](http://img.dabin-coder.cn/image/20220703123249.jpg) + +另外还有两本书也不错,推荐给大家《计算机组成与设计:硬件 / 软件接口》 、《深入理解计算机系统》 + +**视频推荐** + +计算机组成原理(哈工大刘宏伟): https://www.bilibili.com/video/BV1WW411Q7PF + +刘宏伟老师主讲,他的课不仅适合考研人,也非常适合初学者,初学者也听得懂。 + +![](http://img.dabin-coder.cn/image/20220703131541.png) + +【麻省理工学院-中文字幕版】计算机组成原理:https://www.bilibili.com/video/BV1kU4y177x9 + +课程为 MIT 6.004 Computation Structures, Spring 2017,如果英文不错,可以跟着学学,课程质量很高。 + +![](http://img.dabin-coder.cn/image/20220703131900.png) + + + +## 编译原理 + +编译原理介绍了编译程序构造的原理与实践,让你明白高级语言都是如何被转换为另外一种语言的。学完编译原理,可以尝试自己去实现一个完整的小型面向对象语言的编译程序。 + +**书籍推荐** + +**《编译原理》**和**《编译器设计 第二版》**。 + +特别是《编译器设计 第二版》这本书,对于对编译有兴趣的同学,这本书绝对是值得推荐的。 + +![](http://img.dabin-coder.cn/image/20220703133449.jpg) + +这本书覆盖了编译器从前端到后端的全部主题,很多算法都可以在 JVM C2 compiler 中找到对应实现。整体翻译很流畅,不愧是经典! + +哈工大的编译原理视频:https://www.bilibili.com/video/BV1zW411t7YE?p=1&vd_source=2b77c4a826e636ae19a4f75a4b2ca146 + +![](http://img.dabin-coder.cn/image/20220703132211.png) + +比起很多砖头书和博客,强太多!陈鄞老师的 PPT 做的很好,讲得也很通俗易懂,课程评价也很高。推荐! + +编译原理-国防科技大学:https://www.bilibili.com/video/BV12741147J3 + +课程前置知识:具备计算机程序设计语言和程序设计知识,对数据结构与算法、计算机原理、离散数学等相关知识有一定了解更好。视频简洁明了,适合多刷几遍。 + +![](http://img.dabin-coder.cn/image/20220703132547.png) + +## 数据结构和算法 + +为什么学习数据结构与算法?对于计算机专业的同学来说,这门课程是必修的,考研基本也是必考科目。对于程序员来说,数据结构与算法也是面试、笔试必备的非常重要的考察点。 + +数据结构与算法是程序员内功体现的重要标准之一,且数据结构也应用在各个方面。数据结构也蕴含一些面向对象的思想,故学好掌握数据结构对逻辑思维处理抽象能力有很大提升。 + +**书籍推荐** + +**《大话数据结构》和《算法图解》** + +《大话数据结构》 这本书最大的特点是,通篇以一种趣味方式来叙述,大量引用了各种各样的生活知识来类比,并充分运用图形语言来体现抽象内容,对数据结构所涉及到的一些经典算法做到逐行分析、多算法比较。这本书特别适合初学者。 + +![](http://img.dabin-coder.cn/image/20220703150022.jpg) + +《算法图解》是非常好的入门算法书,示例丰富,图文并茂,以让人容易理解的方式阐释了算法,旨在帮助程序员在日常项目中更好地发挥算法的能量。 + +很多学Java的同学,可能会问有没有Java版本的数据结构和算法书籍? + +当然有的,可以看看**《数据结构与算法分析 java语言描述》**这本书,用Java语言描述各种数据结构和算法,对于Java开发者来说,更容易理解。 + +**视频推荐** + +**UCSanDiego的数据结构与算法专项课程**:https://www.coursera.org/specializations/algorithms + +**浙大陈越姥姥的数据结构课程**: + +https://www.bilibili.com/video/BV1H4411N7oD + +![](http://img.dabin-coder.cn/image/20220703150635.png) + +浙江大学陈越姥姥和何钦铭教授联合授课,非常经典的课程。姥姥我的偶像! + +**小甲鱼的数据结构和算法课程**:https://www.bilibili.com/video/BV1jW411K7yg + +数据结构与算法主要学习以下内容: + +- 基本数据结构(数组、链表、栈、队列等) +- 树(二叉树、avl树、b树、红黑树等) +- 堆结构 +- 排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等及时间空间复杂度) +- 动态规划、回溯、贪心算法(多刷刷leetcode) +- 递归 +- 位运算 + +学完感觉还很吃力?可以借助一些刷题网站巩固下。下面推荐几个刷题网站。 + +### [牛客网](https://www.nowcoder.com/) + +![](http://img.dabin-coder.cn/image/20220619223253.png) + +作为牛客红名大佬,来给牛客宣传一波!(牛客打钱!) + +牛客网拥有超级丰富的 IT 题库,题库+面试+学习+求职+讨论,基本涵盖所有面试笔试题型,堪称"互联网求职神器"。在这里不仅可以刷题,还可以跟其他牛友讨论交流,一起成长。牛客上还会各种的内推机会,对于求职的同学也是极其不错的。 + +### [LeetCode](https://leetcode.cn/) + +![](http://img.dabin-coder.cn/image/20220619231232.png) + +**力扣,强推**!力扣虐我千百遍,我待力扣如初恋! + +从现在开始,每天一道力扣算法题,坚持几个月的时间,你会感谢我的(傲娇脸) + +我刚开始刷算法题的时候,就选择在力扣上刷。最初刷easy级别题目的时候,都感觉有点吃力,坚持半年之后,遇到中等题目甚至hard级别的题目都不慌了。 + +不过是熟能生巧罢了。 + +### [LintCode](https://www.lintcode.com/) + +![](http://img.dabin-coder.cn/image/20220619231320.png) + +与Leetcode类似的刷题网站。 + +LeetCode/LintCode的题目量差不多。LeetCode的**test case比较完备**,并且LeetCode有**讨论区**,看别人的代码还是比较有意义的。 + +LintCode的UI、tagging、filter更加灵活,更有优点,大家选择其中一个进行刷题即可。 + +## 计算机网络 + +计算机网络这门课需要学习计算机网络的概念、原理和体系结构,知道计算机分层结构,物理层、数据链路层、介质访问子层、网络层、传输层和应用层的基本原理和协议,掌握以 TCP/IP 协议族为主的网络协议结构,并且了解网络新技术的最新发展。 + +**书籍推荐** + +《计算机网络自顶向下方法》 + +![](http://img.dabin-coder.cn/image/20220703144400.jpg) + +这本书是经典的计算机网络教材,采用作者独创的自顶向下方法来讲授计算机网络的原理及其协议,自第1版出版以来已经被数百所大学和学院选作教材。书中从应用层讲起,然后展开,摆脱了从物理层开始的枯燥,直接接触应用实例,更能吸引读者的兴趣。而且,书上很多例子举的很好,生动形象。 + +**视频推荐** + +视频推荐中科大郑烇、杨坚全套《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》课程。这门课是2020年秋科大自动化系本科课程录制版,可与中科大学生一起完成专业知识的学习。 + +https://www.bilibili.com/video/BV1JV411t7ow?p=7&vd_source=2b77c4a826e636ae19a4f75a4b2ca146 + +![](http://img.dabin-coder.cn/image/20220703143955.png) + +另外还可以看看哈尔滨工业大学李全龙老师的计算机网络课程:https://www.bilibili.com/video/BV1Up411Z7hC + +![](http://img.dabin-coder.cn/image/20220703144500.png) + +**计算机网络核心知识点**: + +- 网络分层结构 +- TCP/IP +- 三次握手四次挥手 +- 滑动窗口、拥塞控制 +- HTTP/HTTPS +- 网络安全问题(CSRF、XSS、SQL注入等) + +## 数据库 + +互联网应用大多属于数据密集型应用,对于真实世界的数据密集型应用而言,除非你准备从基础组件的轮子造起,不然根本没那么多机会去摆弄花哨的数据结构和算法。 + +实际生产中,数据表就是数据结构,索引与查询就是算法。而应用代码往往扮演的是胶水的角色,处理IO与业务逻辑,其他大部分工作都是在数据系统之间搬运数据。在最宽泛的意义上,有状态的地方就有数据库。它无所不在,网站的背后、应用的内部,单机软件,区块链里,甚至在离数据库最远的Web浏览器中。 + +**书籍推荐** + +- 《MySQL必知必会》 +- 《高性能mysql》 + +《MySQL必知必会》主要是Mysql的基础语法,很好理解。后面有了基础再看《高性能mysql》,这本书主要讲解索引、SQL优化、高级特性等,很多Mysql相关面试题出自《高性能MySQL》这本书,值得一看。 + +**视频推荐** + +伯克利的 CS168 课程:https://archive.org/details/UCBerkeley_Course_Computer_Science_186 + +![](http://img.dabin-coder.cn/image/20220703152850.png) + +国内中国人民大学王珊老师的《数据库系统概论》:https://www.bilibili.com/video/BV1pW411W7Do + +![](http://img.dabin-coder.cn/image/20220703153133.png) + + + +码字不易,如果觉得对你有帮助,可以**点个赞**鼓励一下! + +我是 [@程序员大彬](https://zhuanlan.zhihu.com/people/dai-shu-bin-13) ,专注Java后端硬核知识分享,欢迎大家关注~ diff --git a/docs/learning-resources/java-learn-guide.md b/docs/learning-resources/java-learn-guide.md new file mode 100644 index 0000000..e785687 --- /dev/null +++ b/docs/learning-resources/java-learn-guide.md @@ -0,0 +1,810 @@ +--- +sidebar: heading +--- + +大家好,我是大彬~ + +我本科学的不是计算机,大四开始自学Java,并且找到了中大厂的offer。自学路上遇到不少问题,每天晚上都是坚持到一两点才睡觉,**最终也拿到了30w的offer**。 + +![](http://img.dabin-coder.cn/image/image-20211206000941636.png) + +在这里也提醒学弟学妹们,要尽早确定以后的方向,读研还是工作,找工作的话,也要尽快确定工作岗位,想转行的,需要花更多的时间准备。很多同学到了大四快毕业的时候,才思考自己未来要做什么,这个时候已经有点晚了。如果错过了校招,走社招渠道去找工作,难度将会提升一个等级,到时后悔也来不及! + +下面来说说自己的经历吧(附自学路线)。 + +## 接触编程 + +大学以前基本没碰过电脑,家里没电脑,也没去过网吧。高中的计算机课程,期末作业要完成一个自我介绍的PPT,也不会做,最后直接抄同桌的作业(复制粘贴都不会。。还得同桌教,捂脸)。 + +高考完一个月后,买了电脑,真正开始使用上了电脑。 + +大一上学期的时候,系里开了一门C语言的课程,这也是我第一次接触编程。教材是英文的,刚开始学还是挺头大的。每次课程作业,周围的同学都是一顿复制粘贴,我也一样嘿嘿。 + +记得在讲指针那一章的时候,听的一头雾水。稍微走神,回过头来,已经不知道讲的是啥了。 + +后面系里开设了兴趣小组,因为平时比较闲,也想着去捣鼓点东西,就去参加了。刚开始的时候,什么都不懂,老师推荐我学一下51单片机,拿了一本厚厚的51单片机的书籍,跟着书里的demo敲了一遍,发现了新天地!原来编程这么有意思! + +![](https://pic2.zhimg.com/80/v2-2ac0759cc48ed0d17b9ce46a13bb0f1e_720w.jpg) + +记得第一次跑出流水灯的时候,那叫一个激动啊,满满的都是成就感!后面也写了一些电机、红外遥控等demo。从那以后,激发了我学习编程的兴趣。 + +到了大二,辅导员在群里发布全国电子设计大赛的信息,参赛题跟四轴飞行器相关,那段时间对四轴飞行器比较感兴趣,于是约了两个小伙伴一块参加。距离比赛时间只有一个月,在那一个月的时间里,每天都是早出晚归,吃饭的时候还在想着哪一块代码出了bug。虽然最后没能获奖,但是在这个过程中,学到很多知识,编程能力也有了很大的提升。 + +## 决定转码 + +转眼间,大三开学,开始纠结考研还是工作,思考了一周时间,也进了系里的实验室体验了一把研究生生活,最后还是听从内心的想法,决定直接找工作。 + +我咨询了本专业的师兄师姐们往年的就业情况,他们大部分人还是找了互联网方向的工作。有一个在传统行业的师兄,也劝我投互联网公司的岗位,因为在传统行业加班也不少,但是工资贼低。。最后决定转行程序员,找后端相关的工作。 + +那么学习哪一种语言呢?当时有三个选择:c++,Java,python。 + +那段时间python比较火,但是经过一番深思熟虑之后,还是选择了Java。为什么选择Java呢? + +很简单,市场需求大,学习难度适中。相比科班同学来说,我缺乏系统的计算机基础知识,而距离秋招也只有不到一年时间,所以还是选择学习难度低一点的Java。 + +## 闭关自学 + +确定方向后,便开始制定学习路线。不得不说,Java要学的东西是真的多。。 + +自学期间遇到挺多问题,比如一些环境配置问题,有时候搞上好几天,很打击积极性。中途也有很多次怀疑自己的水平,是不是不适合干编程,差点就放弃了。幸好最后还是坚持了下来。 + +半年多的时间,除了平时上课,其他时间就是在图书馆。周末或者节假日,每天都是7点起床,八点到图书馆开始学习,到了晚上十点,图书馆闭馆,才回宿舍,每天都是图书馆最后走的一批。回到宿舍,洗完澡,继续肝到十二点多(卷王!)。 + +![img](https://pic3.zhimg.com/80/v2-25f6523ffc0ea6982c576b75458695dc_720w.jpg) + +> 很多人在问,大三才开始自学Java,来的及吗? 我觉得,还是看个人的投入程度和学习能力。有些人自学能力强一点,每天可以投入10小时及以上的时间去学习,那完全没问题。 + +自学过程还是挺辛苦的,要耐得住寂寞,最最重要的还是得坚持! + +我根据自己的自学经历,整理了一些学习过程中踩坑总结的经验,希望自学的小伙伴可以少走弯路: + +- **注重实践**,不要只是埋头看书,一定要多动手写代码。 +- 刚开始自学的时候,可以不用太深究细节,不然可能会怀疑自己的学习能力。等到后面有了一定的基础,回过头来重新回顾,可能会恍然大悟,没有当初想的那么难。 +- 可以适当加一些交流群,遇到不懂的知识点,多与其他人交流。 + +好了,下面给大家分享一下我的自学经验。 + +## 自学路线 + +首先看一下Java学习路线图: + +![](http://img.dabin-coder.cn/image/Java学习路线-gitmind-清晰.png) + +在这里也给大家分享一份精心整理的**大厂高频面试题PDF**,小伙伴靠着这份手册拿过阿里offer,需要的小伙伴可以自行下载: + +http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247485445&idx=1&sn=1c6e224b9bb3da457f5ee03894493dbc&chksm=ce98f543f9ef7c55325e3bf336607a370935a6c78dbb68cf86e59f5d68f4c51d175365a189f8#rd + +## Java + +![](http://img.dabin-coder.cn/image/Java基础.jpg) + +推荐书籍: + +- 《head first java》 +- 《JAVA核心技术卷》 + +head first系列的书籍讲解比较有趣,比较好理解。《JAVA核心技术卷》难度相对适中,内容也比较全面,部分章节(如Swing)可以跳过。 + +视频推荐动力节点老杜的视频教程,1000w的播放量!视频总体上质量很不错,讲解挺详细,适合新手。跟着老杜的视频学下来,可以学到很多知识! + +https://www.bilibili.com/video/BV1Rx411876f + +再次强调:**多敲代码!多敲代码!多敲代码!** + +学习编程就是看书加实践,要多动手,不然看过的知识点很快就会忘,而且多实践也会遇到很多坑,丰富经验。 可以到github上找一些项目练练手,通过做项目巩固知识,而且每实现一个功能之后,会有满满的成就感,也会激励你不断去学习。 + +**Java基础知识主要有:** + +- 面向对象特性 +- Java语言基础、循环、数组 ; 了解类和对象 + + - 掌握强制数据类型转换和自动类型提升规则; + - 常量如何声明及赋值; + - 循环的语法及作用; + - 数组的声明及定义; + - 掌握类的概念以及什么是对象。 +- 抽象类和接口 +- 数据类型、重写重载、封装继承多态 +- 容器类Map/List/Set等 +- 异常处理 +- 反射机制 +- 泛型 +- 常用类:String、时间类 +- 函数式编程 +- Stream API +- Lambda 表达式 +- IO流操作,多线程及Socket + - 掌握IO读写流相关的类,了解字节流,字符流和字符流缓冲区; + - 掌握线程的概念,多线程的创建、启动方式,锁和同步的概念及运用; + - 掌握Socket通信的概念,如何声明客户端服务端,如何完成双端数据通信。 + +## Java Web + +Java Web是一系列技术的综合,也是大多数Java开发者的技术方向。有必要学习一下。这部分可以看看视频教程。 + +视频推荐尚硅谷的JavaWeb全套教程,HTML/CSS/JavaScript等跟前端相关的可以倍速观看。 + +https://www.bilibili.com/video/BV1Y7411K7zz + +黑马程序员的Java web教程总体也不错 + +https://www.bilibili.com/video/BV1qv4y1o79t + +下面列举Java web需要掌握的知识点。 + +HTML: + +- 掌握网页的基本构成; +- 掌握HTML的基本语法; +- 表格的作用以及合并行、合并列; +- 表单标签的使用,提交方式get/post的区别; +- 框架布局的使用 + +CSS: + +- 掌握CSS的语法及作用,在html中的声明方式; +- 掌握CSS布局的函数使用; +- 掌握CSS外部样式的引入。 + +JavaScript: + +- 掌握JS的语法及作用,在HTML中的声明方式; +- 掌握JS的运行方式; +- 掌握JS中的变量声明、函数声明、参数传递等; +- 掌握HTML中的标签事件使用; +- 掌握JS中的DOM原型 + +jQuery: + +- 了解如何使用jQuery,下载最新版或者老版本的jQuery.js +- 掌握选择器、文档处理、属性、事件等语法及使用; +- 能够灵活使用选择器查找到想要查找的元素并操作他们的属性; +- 动态声明事件; +- 动态创建元素。 + +Servlet + +- 掌握Java中的Web项目目录结构; +- 掌握Java Web项目的重要中间件Tomcat; +- 掌握Servlet中的Request和Response; +- 掌握Servlet的基本运行过程。 +- 掌握Servlet的声明周期 + +Ajax + +- 掌握Ajax的基本概念; +- 掌握jQuery中的Ajax请求; +- 掌握JSON + +Filter、Listener: + +- 掌握Filter和Listener +- 掌握Session过滤器和编码过滤器 + +JSP数据交互 + +- JSP中如何编写Java代码,如何使用Java中的类; +- JSP中的参数传递。 + +状态管理Session和Cookie + +- 掌握Session、Cookie的作用及作用域; +- 掌握Session及Cookie的区别,存储位置,声明周期等; +- 掌握Session及Cookie分别在JSP和Cookie中的使用 + +## 框架 + +主流框架主要有: + +- spring:面向切面、依赖注入。 +- springboot:习惯优于配置、自动配置。目前很多公司内部都是使用Spring Boot。 +- springmvc:基于MVC架构模式的轻量级Web框架 +- Mybatis:orm框架。 +- springcloud + +### Spring + +![](http://img.dabin-coder.cn/image/Spring总结.jpg) + +大部分公司都会用到 Spring框架,必学!。主要理解 Spring 面向切面、依赖注入的特性,学会使用 Spring 构建应用程序。推荐书籍《Spring实战》,通过demo的方式带你一步步搭建Spring应用 + +视频推荐尚硅谷王泽老师的Spring5框架最新版教程,视频刚出不久,内容也是与时俱进,值得学习! + +https://www.bilibili.com/video/BV1Vf4y127N5 + +### SpringMVC + +SpringMVC是基于**MVC架构模式**的轻量级Web框架,对于初学者,需要掌握Web请求从发出到相应的这个过程,SpringMVC做了什么,还有MVC模式的思想。 + +视频推荐狂神说Java的SpringMVC最新教程。 + +【狂神说Java】SpringMVC最新教程IDEA版通俗易懂:https://www.bilibili.com/video/BV1aE41167Tu + +### Mybatis + +MyBatis 是一款优秀的持久层框架,MyBatis 帮助我们做了很多事情:建立连接、操作 Statment、ResultSet、处理 JDBC 相关异常等,简化了开发流程。推荐书籍《深入浅出Mybatis》。 + +视频推荐狂神说的Mybatis最新完整教程,b站播放量最高,获得了很多小伙伴的一致好评。 + +https://www.bilibili.com/video/BV1NE411Q7Nx + +### SpringBoot + +学完 SSM,就要进一步学习 SpringBoot 了,相信很多人在学了 Spring 之后,面对各种各样的配置,想必都会头疼。而 SpringBoot 的出现解决了这个问题,SpringBoot 去除了大量的 XML 配置文件,简化了复杂的依赖管理。书籍推荐《Spring Boot实战》。 + +视频推荐尚硅谷雷神的2021版最新SpringBoot2权威教程。 + +https://www.bilibili.com/video/BV1Et411Y7tQ + +### SpringCloud + +现在面试基本都会问到微服务相关的内容,最好了解下微服务相关的知识。服务注册与发现、负载均衡、服务降级、API网关等。推荐书籍《spring cloud微服务实战》 + +视频教程可以看看尚硅谷周阳老师的: + +https://www.bilibili.com/video/BV18E411x7eT + +## 并发 + +![](http://img.dabin-coder.cn/image/并发与多线程知识点总结.jpg) + +什么是并发编程,简单来说就是为了充分利用cpu,多个任务同时执行,快速完成任务。 + +并发编程的相关内容可以看看《JAVA并发编程实战》这本书。 + +视频推荐狂神说Java,很不错的视频: + +https://www.bilibili.com/video/BV1B7411L7tE + +主要知识点有: + +- 线程的概念以及案例 +- 线程池原理 +- 线程间通信方式 +- 锁(synchronized、ReentrantLock) +- 并发工具类(CountDownLatch/CyclicBarrier/Semaphore) +- 原子类 +- AQS +- Thread生命周期状态 +- Java内存模型 + +## Redis + +![](http://img.dabin-coder.cn/image/Redis知识点.jpg) + +用来缓存热点数据,加快读写速度,从而提高性能。现在Java后端的面试基本都会问到Redis。 + +书籍推荐《redis实战》和《redis设计与实现》。 + +视频推荐狂神说Java的Redis最新超详细版教程,不仅教你学Redis,还会教你学习的方式。 + +https://www.bilibili.com/video/BV1S54y1R7SB + +## 消息队列 + +消息队列是基础数据结构中`FIFO`的一种数据结构,用来解决应用解耦、异步消息、流量削锋等问题,可以实现高性能、高可用、可伸缩和最终一致性。 + +视频推荐黑马的RocketMQ教程和百知教育的RabbitMQ教程,两者挑一个学习就可以! + +【编程不良人】MQ消息中间件之RabbitMQ: + +https://www.bilibili.com/video/BV1dE411K7MG + +黑马程序员Java教程RocketMQ系统精讲: + +https://www.bilibili.com/video/BV1L4411y7mn + +## JVM + +![](http://img.dabin-coder.cn/image/JVM知识点总结.jpg) + +JVM也是面试经常会问的内容。Java开发者不用自己进行内存管理、垃圾回收,JVM帮我们做了,但是还是有必要了解下JVM的工作原理,这样在出现oom等问题的时候,才有思路去排查和解决问题。书籍推荐周老师的《深入理解Java虚拟机》。 + +视频推荐尚硅谷宋红康的全套课程,全套课程分为三个篇章:《内存与垃圾回收篇》、《字节码与类的加载篇》和《性能监控与调优篇》。 + +尚硅谷JVM全套教程: + +https://www.bilibili.com/video/BV1PJ411n7xZ + +JVM的基础知识: + +- jvm内存结构(程序计数器、虚拟机栈、本地方法栈、堆、方法区、运行时常量池、直接内存) +- 类加载过程 +- 双亲委派 +- 垃圾回收算法 +- 垃圾回收器 +- 调优工具(jsp/jstack/jstat/jmap,了解即可) + +## 计算机基础知识 + +学编程一定要打好计算机基础! + +对于非科班同学来说,与科班同学最大的差距在于**基本理论知识**。如果你是非科班自学编程的,想要进入大厂,那么计算机基础知识一定不能落下。 + +每一个合格的程序员,应该要知道计算机体系的结构,内在的逻辑是什么,要有自己的思考。 + +**总之,基本功非常重要!** + +### 操作系统 + +无论学习什么编程语言,和需要和操作系统打交道。如果对操作系统不熟悉,那么你在未来的学习路上将会遇到很多障碍,比如线程进程调度、内存分配、Java的虚拟机等知识,都会一头雾水。因此,只有把操作系统搞明白了,才能够更好地学习计算机的其他知识。 + +**书籍推荐** + +入门级别书籍:**《现代操作系统》、《操作系统导论》**,进阶:**《深入理解计算机系统》** + +强推《深入理解计算机系统》 这本书。 + +![](http://img.dabin-coder.cn/image/20220703132845.jpg) + +CSAPP是一本很好的书,糅合了计算机组成原理、操作系统、网络编程、并行程序设计原理等课程的基础知识。对于刚接触编程,或者像大彬这种非科班出身的人来说,这是一本指导性的书,它会告诉你,要想成为一个优秀的程序员,应当重点理解哪些计算机底层原理,告诉你应该在以后的自学过程中,应该重点学习哪些课程,比如操作系统和体系结构等。 + +**视频教程推荐** + +Udacity的Advanced OS公开课:https://www.classcentral.com/course/udacity-advanced-operating-systems-1016 + +还有国内不错的操作系统的课程,清华大学的公开课:https://www.xuetangx.com/course/THU08091000267/5883104?channel=search_result + +![](http://img.dabin-coder.cn/image/20220703132955.png) + +由清华大学两位老师向勇、陈渝讲授,同时配有一套完整的实验,实验内容是从无到有地建立起一个小却五脏俱全的操作系统,以主流操作系统为实例,以教学操作系统ucore为实验环境,讲授操作系统的概念、基本原理和实现技术,为学生从事操作系统软件研究和开发,以及充分利用操作系统功能进行应用软件研究和开发打下扎实的基础。 + +另外,推荐另一门MIT操作系统课程:**MIT6.268** + +课程地址:https://pdos.csail.mit.edu/6.828/2018/schedule.html + +![](http://img.dabin-coder.cn/image/20220626115851.png) + +MIT6.828 是一门非常值得学习的课程,广受好评,是**理论与实践相结合的经典**。 + +只要你跟着项目一步一步走,做完 6 个实验,就能实现一个简单的操作系统内核。 + +每个实验都有对应的知识点,学完理论知识后会有相应的练习,学习体验非常棒! + +**建议**在开始学习这门课之前先熟悉C和汇编,对计算机组成有一定了解。 + +**操作系统主要知识点**: + +- 操作系统的基础特征 +- 进程与线程的本质区别、以及各自的使用场景 +- 进程的几种状态 +- 进程通信方法的特点以及使用场景 +- 进程任务调度算法的特点以及使用场景 +- 死锁的原因、必要条件、死锁处理。手写死锁代码、Java是如何解决死锁的。 +- 线程实现的方式 +- 协程的作用 +- 内存管理的方式 +- 虚拟内存的作用,分页系统实现虚拟内存原理 +- 页面置换算法的原理 +- 静态链接和动态链接 + +### 数据结构和算法 + +![](http://img.dabin-coder.cn/image/数据结构与算法.jpg) + +为什么学习数据结构与算法?对于计算机专业的同学来说,这门课程是必修的,考研基本也是必考科目。对于程序员来说,数据结构与算法也是面试、笔试必备的非常重要的考察点。 + +数据结构与算法是程序员内功体现的重要标准之一,且数据结构也应用在各个方面。数据结构也蕴含一些面向对象的思想,故学好掌握数据结构对逻辑思维处理抽象能力有很大提升。 + +**书籍推荐** + +**《大话数据结构》和《算法图解》** + +《大话数据结构》 这本书最大的特点是,通篇以一种趣味方式来叙述,大量引用了各种各样的生活知识来类比,并充分运用图形语言来体现抽象内容,对数据结构所涉及到的一些经典算法做到逐行分析、多算法比较。这本书特别适合初学者。 + +![](http://img.dabin-coder.cn/image/20220703150022.jpg) + +《算法图解》是非常好的入门算法书,示例丰富,图文并茂,以让人容易理解的方式阐释了算法,旨在帮助程序员在日常项目中更好地发挥算法的能量。 + +很多学Java的同学,可能会问有没有Java版本的数据结构和算法书籍? + +当然有的,可以看看**《数据结构与算法分析 java语言描述》**这本书,用Java语言描述各种数据结构和算法,对于Java开发者来说,更容易理解。 + +**视频推荐** + +**UCSanDiego的数据结构与算法专项课程**:https://www.coursera.org/specializations/algorithms + +**浙大陈越姥姥的数据结构课程**: + +https://www.bilibili.com/video/BV1H4411N7oD + +![](http://img.dabin-coder.cn/image/20220703150635.png) + +浙江大学陈越姥姥和何钦铭教授联合授课,非常经典的课程。姥姥我的偶像! + +**小甲鱼的数据结构和算法课程**:https://www.bilibili.com/video/BV1jW411K7yg + +数据结构与算法主要学习以下内容: + +- 基本数据结构(数组、链表、栈、队列等) +- 树(二叉树、avl树、b树、红黑树等) +- 堆结构 +- 排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等及时间空间复杂度) +- 动态规划、回溯、贪心算法(多刷刷leetcode) +- 递归 +- 位运算 + +学完感觉还很吃力?可以借助一些刷题网站巩固下。下面推荐几个刷题网站。 + +### [牛客网](https://www.nowcoder.com/) + +![](http://img.dabin-coder.cn/image/20220619223253.png) + +作为牛客红名大佬,来给牛客宣传一波!(牛客打钱!) + +牛客网拥有超级丰富的 IT 题库,题库+面试+学习+求职+讨论,基本涵盖所有面试笔试题型,堪称"互联网求职神器"。在这里不仅可以刷题,还可以跟其他牛友讨论交流,一起成长。牛客上还会各种的内推机会,对于求职的同学也是极其不错的。 + +### [LeetCode](https://leetcode.cn/) + +![](http://img.dabin-coder.cn/image/20220619231232.png) + +**力扣,强推**!力扣虐我千百遍,我待力扣如初恋! + +从现在开始,每天一道力扣算法题,坚持几个月的时间,你会感谢我的(傲娇脸) + +我刚开始刷算法题的时候,就选择在力扣上刷。最初刷easy级别题目的时候,都感觉有点吃力,坚持半年之后,遇到中等题目甚至hard级别的题目都不慌了。 + +不过是熟能生巧罢了。 + +### [LintCode](https://www.lintcode.com/) + +![](http://img.dabin-coder.cn/image/20220619231320.png) + +与Leetcode类似的刷题网站。 + +LeetCode/LintCode的题目量差不多。LeetCode的**test case比较完备**,并且LeetCode有**讨论区**,看别人的代码还是比较有意义的。 + +LintCode的UI、tagging、filter更加灵活,更有优点,大家选择其中一个进行刷题即可。 + +### 数据库 + +![](http://img.dabin-coder.cn/image/MySQL知识点总结.jpg) + +互联网应用大多属于数据密集型应用,对于真实世界的数据密集型应用而言,除非你准备从基础组件的轮子造起,不然根本没那么多机会去摆弄花哨的数据结构和算法。 + +实际生产中,数据表就是数据结构,索引与查询就是算法。而应用代码往往扮演的是胶水的角色,处理IO与业务逻辑,其他大部分工作都是在数据系统之间搬运数据。在最宽泛的意义上,有状态的地方就有数据库。它无所不在,网站的背后、应用的内部,单机软件,区块链里,甚至在离数据库最远的Web浏览器中。 + +**书籍推荐** + +- 《MySQL必知必会》 +- 《高性能mysql》 + +《MySQL必知必会》主要是Mysql的基础语法,很好理解。后面有了基础再看《高性能mysql》,这本书主要讲解索引、SQL优化、高级特性等,很多Mysql相关面试题出自《高性能MySQL》这本书,值得一看。 + +**视频推荐** + +伯克利的 CS168 课程:https://archive.org/details/UCBerkeley_Course_Computer_Science_186 + +![](http://img.dabin-coder.cn/image/20220703152850.png) + +国内中国人民大学王珊老师的《数据库系统概论》:https://www.bilibili.com/video/BV1pW411W7Do + +![](http://img.dabin-coder.cn/image/20220703153133.png) + +MySQL基础知识: + +- 增删改查 +- 事务特性、隔离级别 +- 索引原理、优化 +- b+树 +- 最左匹配原则 +- 存储引擎 +- MVCC +- 执行计划 +- 分库分表 +- 日志,bin log/undo log/redo log +- ... + +### 计算机网络 + +![](http://img.dabin-coder.cn/image/计算机网络知识.jpg) + +计算机网络这门课需要学习计算机网络的概念、原理和体系结构,知道计算机分层结构,物理层、数据链路层、介质访问子层、网络层、传输层和应用层的基本原理和协议,掌握以 TCP/IP 协议族为主的网络协议结构,并且了解网络新技术的最新发展。 + +**书籍推荐** + +《计算机网络自顶向下方法》 + +![](http://img.dabin-coder.cn/image/20220703144400.jpg) + +这本书是经典的计算机网络教材,采用作者独创的自顶向下方法来讲授计算机网络的原理及其协议,自第1版出版以来已经被数百所大学和学院选作教材。书中从应用层讲起,然后展开,摆脱了从物理层开始的枯燥,直接接触应用实例,更能吸引读者的兴趣。而且,书上很多例子举的很好,生动形象。 + +**视频推荐** + +视频推荐中科大郑烇、杨坚全套《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》课程。这门课是2020年秋科大自动化系本科课程录制版,可与中科大学生一起完成专业知识的学习。 + +https://www.bilibili.com/video/BV1JV411t7ow?p=7&vd_source=2b77c4a826e636ae19a4f75a4b2ca146 + +![](http://img.dabin-coder.cn/image/20220703143955.png) + +另外还可以看看哈尔滨工业大学李全龙老师的计算机网络课程:https://www.bilibili.com/video/BV1Up411Z7hC + +![](http://img.dabin-coder.cn/image/20220703144500.png) + +**计算机网络核心知识点**: + +- 网络分层结构 +- TCP/IP +- 三次握手四次挥手 +- 滑动窗口、拥塞控制 +- HTTP/HTTPS +- 网络安全问题(CSRF、XSS、SQL注入等) + +### linux + +Linux 系统已经渗透到 IT 领域的各个角落,作为一名 IT 从业人员,不管你是专注于编程,还是专注于运维,都应该对 Linux 有所了解,甚至还要深入学习,掌握核心原理。 + +至少要熟悉常用的Linux命令。书籍推荐**《鸟哥的linux私房菜》**。 + +视频推荐: + +https://www.bilibili.com/video/BV1dW411M7xL + +## 设计模式 + +![](http://img.dabin-coder.cn/image/设计模式.jpg) + +设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。对于具有丰富的开发经验的开发人员,学习设计模式有助于了解在软件开发过程中所面临的问题的最佳解决方案;对于那些经验不足的开发人员,学习设计模式有助于通过一种简单快捷的方式来学习软件设计。 + +**为什么要学习设计模式**: + +- 设计模式是从许多优秀的软件系统中总结出能够实现可维护性、复用的设计方案,使用这些方案可以避免做一些重复性的工作 +- 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统 +- 学习设计模式将有助于初学者更加深入地理解面向对象思想 + +**设计模式分类**: + +**1.1 创建型模式** + +创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将模块中对象的创建和对象的使用分离。 + +创建型模式包括工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式 + +**1.2 结构型模式** + +结构型模式(Structural Pattern)描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。 + +结构型模式包括适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式 + +**1.3 行为型模式** + +行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。 + + 行为型模式包括策略模式、模板模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式等。 + +推荐秦疆老师**基于Java讲解的23种设计模式**视频教程。 + +https://www.bilibili.com/video/BV1mc411h719 + +## 工具 + +### Git + +Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 + +视频推荐:https://www.bilibili.com/video/BV1BE411g7SV + +### Maven + +Maven 是一个软件项目管理工具,可以对 Java 项目进行全自动构建,管理项目所需要的依赖。Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。 + +视频推荐: + +https://www.bilibili.com/video/BV1Ah411S7ZE + +### docker + +Docker 是一个开源的应用容器引擎。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 + +Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。 + +**Docker的应用场景** + +- Web 应用的自动化打包和发布。 +- 自动化测试和持续集成、发布。 +- 在服务型环境中部署和调整数据库或其他的后台应用。 + +视频推荐广州云科的docker入门教程,非常详细。 + +https://www.bilibili.com/video/BV11L411g7U1 + +## 项目 + +很多同学初学Java都会遇到一个问题,不知道去哪里找Java的项目练手。以前我也遇到这个问题,现在在这里分享下一些比较值得学习的项目。 + +首先给大家推荐几个Java项目的**视频教程**,都是B站上的视频,风评很好,讲解也非常详细,有兴趣的可以看一下~ + +尚硅谷尚筹网Java项目实战开发教程: + +https://www.bilibili.com/video/BV1bE411T7oZ + +尚硅谷Java微服务+分布式+全栈项目【尚医通】 + +https://www.bilibili.com/video/BV1V5411K7rT + +Java Web项目实战-畅购商城: + +https://www.bilibili.com/video/BV13J411k7aQ + +下面也推荐几个Github上比较优质的开源项目。 + +### newbee-mall + +star:7.8k + +https://github.com/newbee-ltd/newbee-mall + +newbee-mall 项目是一套电商系统,包括 newbee-mall 商城系统及 newbee-mall-admin 商城后台管理系统,基于 Spring Boot 2.X 及相关技术栈开发。 前台商城系统包含首页门户、商品分类、新品上线、首页轮播、商品推荐、商品搜索、商品展示、购物车、订单结算、订单流程、个人订单管理、会员中心、帮助中心等模块。 后台管理系统包含数据面板、轮播图管理、商品管理、订单管理、会员管理、分类管理、设置等模块。 + +![](http://img.dabin-coder.cn/image/image-20210827001950033.png) + +### litemall + +star:16.2k + +https://github.com/linlinjava/litemall + +又一个小商城。litemall = Spring Boot后端 + Vue管理员前端 + 微信小程序用户前端 + Vue用户移动端。 + +小商城功能: + +- 首页 +- 专题列表、专题详情 +- 分类列表、分类详情 +- 品牌列表、品牌详情 +- 新品首发、人气推荐 +- 优惠券列表、优惠券选择 +- ... + +![](http://img.dabin-coder.cn/image/litemall.png) + +![](http://img.dabin-coder.cn/image/litemall01.png) + +在这里也分享一份非常棒的Java学习笔记,**Github标星137k+**!这份笔记主要Java基础、容器、Java IO、并发和虚拟机等内容,排版精良,内容更是无可挑剔。 + +![](https://pic3.zhimg.com/80/v2-cdfb49d3d6562191415ae9771055807a_720w.jpg) + +需要的小伙伴可自行下载: + +http://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=100000392&idx=1&sn=f6c8e84651ce48f6ef5b0d496f0f6adf&chksm=4e98ffce79ef76d8dcebdc4787ae8b37760ec193574da9036e46954ae8954ebd56c78792726f#rd + +### eladmin + +star:16.2k + +https://github.com/elunez/eladmin + +一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统。项目采用分模块开发方式, 权限控制采用 RBAC,支持数据字典与数据权限管理,支持一键生成前后端代码,支持动态路由。 + +项目提供了非常详细的文档,地址是[https://el-admin.vip](https://el-admin.vip/) + +项目体验地址:[https://el-admin.xin](https://el-admin.xin/) + +使用的技术栈也比较新,给作者点赞! + +![](http://img.dabin-coder.cn/image/image-20210826235913747.png) + +![](http://img.dabin-coder.cn/image/image-20210826235952292.png) + +### vhr + +star:22.2k + +https://github.com/lenve/vhr + +微人事是一个前后端分离的人力资源管理系统,项目采用SpringBoot+Vue开发。项目加入常见的企业级应用所涉及到的技术点,例如 Redis、RabbitMQ 等。 + +![](http://img.dabin-coder.cn/image/vhr01.png) + + + +### Blog + +star1.2k + +https://github.com/zhisheng17/blog + +`My-Blog` 使用的是 Docker + SpringBoot + Mybatis + thymeleaf 打造的一个个人博客模板。此项目在 [Tale](https://github.com/otale/tale) 博客系统基础上进行修改的。 + +![](http://img.dabin-coder.cn/image/blog.png) + +### community + +star:1.8k + +https://github.com/codedrinker/community + +码问社区。开源论坛、问答系统,现有功能提问、回复、通知、最新、最热、消除零回复功能。技术栈 Spring、Spring Boot、MyBatis、MySQL/H2、Bootstrap。 + +![](http://img.dabin-coder.cn/image/image-20210826234936711.png) + + + +### vblog + +star:6.5k + +https://github.com/lenve/VBlog + +V部落,Vue+SpringBoot实现的多用户博客管理平台! + +后端主要采用了: + +1.SpringBoot +2.SpringSecurity +3.MyBatis +4.部分接口遵循Restful风格 +5.MySQL + +前端主要采用了: + +1.Vue +2.axios +3.ElementUI +4.vue-echarts +5.mavon-editor +6.vue-router + +![](http://img.dabin-coder.cn/image/20220505162337.png) + +### gpmall + +star:4.3k + +https://github.com/2227324689/gpmall + +【咕泡学院实战项目】基于SpringBoot+Dubbo构建的电商平台。业务模块划分,尽量贴合互联网公司的架构体系。所以,除了业务本身的复杂度不是很高之外,整体的架构基本和实际架构相差无几。 + +后端的主要架构是基于springboot+dubbo+mybatis。 + +![](http://img.dabin-coder.cn/image/20220505162427.png) + +![](http://img.dabin-coder.cn/image/20220505162154.png) + +### guns + +star:3.4k + +https://github.com/stylefeng/Guns + +Guns是一个现代化的Java应用开发框架,基于主流技术Spring Boot2,Guns的核心理念是提高开发人员开发效率,降低企业信息化系统的开发成本,提高企业整体开发水平。 + +Guns基于**插件化架构**,在建设系统时,可以自由组合细粒度模块依赖,实现不同功能的组合和剔除,让项目体积灵活控制,从而更方便地搭建不同的业务系统。 + +使用Guns可以快速开发出各类信息化管理系统,例如OA办公系统、项目管理系统、商城系统、供应链系统、客户关系管理系统等。 + +![](http://img.dabin-coder.cn/image/20220505162031.png) + +### music-website + +star:2.3k + +https://github.com/Yin-Hongwei/music-website + +音乐网站。客户端和管理端使用 **Vue** 框架来实现,服务端使用 **Spring Boot + MyBatis** 来实现,数据库使用了 **MySQL**。 + +前端技术栈:Vue3.0 + TypeScript + Vue-Router + Vuex + Axios + ElementPlus + Echarts。 + +![](http://img.dabin-coder.cn/image/20220505161944.jpg) + + + +以上就是Java自学的学习路线,内容不少,转行的小伙伴们加油! + + + +另外,上面提到的书籍,我已经整理了电子版,放到github上了,总共**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~(花了一个多月的时间整理的,希望对大家有帮助,欢迎star~) + +仓库持续更新中~ + +![](http://img.dabin-coder.cn/image/书单new.png) + +有需要的自取: + +github仓库:https://github.com/Tyson0314/java-books + + + +码字不易,小伙伴们觉得有帮助的话,点个赞呗 你的赞就是我创作的动力! + +我是 [@程序员大彬](https://zhuanlan.zhihu.com/people/a19ae109d127ec8dacde6bdaa3e83c7a) ,定期会分享Java后台硬核知识,欢迎大家关注~ diff --git a/docs/learning-resources/leetcode-note.md b/docs/learning-resources/leetcode-note.md new file mode 100644 index 0000000..5f29977 --- /dev/null +++ b/docs/learning-resources/leetcode-note.md @@ -0,0 +1,26 @@ +分享三份LeetCode刷题笔记,分别是**c/c++、Java、Go**版本的,每份笔记都挺详细,内容分别有**字符串、栈队列、树、排序、查找、BFS、DFS、贪心、动态规划**等等,每道题都包含解题思路、最佳解法、拓展题型等。 + +![](http://img.dabin-coder.cn/image/image-20221209234446942.png) + +**c/c++版本**: + +![](http://img.dabin-coder.cn/image/image-20221208235757286.png) + +**Java版本**: + +![](http://img.dabin-coder.cn/image/image-20221208235458520.png) + +**Go版本**: + +![](http://img.dabin-coder.cn/image/image-20221209000002484.png) + +正在学习数据结构和算法,或者准备面试的小伙伴们,千万不要错过这几份**宝藏笔记**! + +**手册获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**力扣**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) + +祝大家学习愉快! + + + diff --git a/docs/learning-resources/mysql-top.md b/docs/learning-resources/mysql-top.md new file mode 100644 index 0000000..e2e1414 --- /dev/null +++ b/docs/learning-resources/mysql-top.md @@ -0,0 +1,213 @@ +另外给大家推荐一套MySQL的教程,堪称 MySQL 教程的天花板(附**下载地址**) + +**此教程包含**:6 大范式讲解、7 大日志剖析、7 大 SQL 性能分析工具、9 大存储引擎剖析、10 大类 30 小类优化场景15 个不同锁的应用讲解、18 种创建索引的规则、300+张高清技术剖析图...... + +在学习MySQL的小伙伴千万不要错过! + +## 目录 + +``` +01-MySQL教程简介 +02-为什么使用数据库及数据库常用概念 +03-常见的DBMS的对比 +04-RDBMS和非RDBMS的对比 +05-ER模型与表记录的4种关系 +06-MySQL8.0的卸载 +07-MySQL8.0与5.7版本的下载、安装与配置 +08-MySQL安装常见问题_服务启动与用户登录 +09-MySQL的使用演示_MySQL5.7字符集的设置 +10-Navicat_SQLyog_dbeaver等工具的使用 +11-MySQL目录结构及前2章课后练习 +12-SQL概述与SQL分类 +13-SQL使用规范与数据的导入 +14-最基本的SELECT...FROM结构 +15-列的别名_去重_NULL_DESC等操作 +16-使用WHERE过滤数据 +17-第3章基本SELECT查询课后练习 +18-算术运算符的使用 +19-比较运算符的使用 +20-逻辑运算符与位运算符的使用 +21-第4章运算符课后练习 +22-ORDER BY实现排序操作 +23-LIMIT实现分页操作 +24-第5章排序与分页课后练习 +25-为什么需要多表的查询 +26-笛卡尔积的错误与正确的多表查询 +27-等值连接vs非等值连接、自连接vs非自连接 +28-SQL92与99语法如何实现内连接和外连接 +29-使用SQL99实现7种JOIN操作 +30-NATURAL JOIN与USING的使用 +31-第6章多表查询课后练习 +32-函数的分类 +33-数值类型的函数讲解 +34-字符串类型的函数讲解 +35-日期时间类型的函数讲解 +36-流程控制函数讲解 +37-加密解密_MySQL信息函数等讲解 +38-第7章单行函数课后练习 +39-5大常用的聚合函数 +40-GROUP BY的使用 +41-HAVING的使用与SQL语句执行过程 +42-第8章聚合函数课后练习 +43-子查询举例与子查询的分类 +44-单行子查询案例分析 +45-多行子查询案例分析 +46-相关子查询案例分析 +47-第9章子查询课后练习1 +48-第9章子查询课后练习2 +49-数据库的创建、修改与删除 +50-常见的数据类型_创建表的两种方式 +51-修改表_重命名表_删除表_清空表 +52-DCL中COMMIT与ROLLBACK的使用 +53-阿里MySQL命名规范及MySQL8DDL的原子化 +54-第10章创建管理表课后练习 +55-DML之添加数据 +56-DML之更新删除操作_MySQL8新特性之计算列 +57-DDL和DML的综合案例 +58-第11章增删改课后练习 +59-MySQL数据类型概述_字符集设置 +60-整型数据类型讲解 +61-浮点数、定点数与位类型讲解 +62-日期时间类型讲解 +63-文本字符串类型(含ENUM、SET)讲解 +64-二进制类型与JSON类型讲解 +65-小结及类型使用建议 +66-数据完整性与约束的分类 +67-非空约束的使用 +68-唯一性约束的使用 +69-主键约束的使用 +70-AUTO_INCREMENT +71-外键约束的使用 +72-检查约束与默认值约束 +73-第13章约束课后练习 +74-数据库对象与视图的理解 +75-视图的创建与查看 +76-更新视图数据与视图的删除 +77-第14章视图课后练习 +78-存储过程使用说明 +79-存储过程的创建与调用 +80-存储函数的创建与调用 +81-存储过程与函数的查看修改和删除 +82-第15章存储过程函数课后练习 +83-GLOBAL与SESSION系统变量的使用 +84-会话用户变量与局部变量的使用 +85-程序出错的处理机制 +86-分支结构IF的使用 +87-分支结构CASE的使用 +88-LOOP_WHILE_REPEAT三种循环结构 +89-LEAVE和ITERATE的使用 +90-游标的使用 +91-第16章课后练习 +92-创建触发器 +93-查看删除触发器_触发器课后练习 +94-MySQL8.0新特性_窗口函数的使用 +95-公用表表达式_课后练习_最后寄语 +96-MySQL高级特性篇章节概览 +97-CentOS环境的准备 +98-MySQL的卸载 +99-Linux下安装MySQL8.0与5.7版本 +100-SQLyog实现MySQL8.0和5.7的远程连接 +101-字符集的修改与底层原理说明 +102-比较规则_请求到响应过程中的编码与解码过程 +103-SQL大小写规范与sql_mode的设置 +104-MySQL目录结构与表在文件系统中的表示 +105-用户的创建_修改_删除 +106-用户密码的设置和管理 +107-权限管理与访问控制 +108-角色的使用 +109-配置文件、系统变量与MySQL逻辑架构 +110-SQL执行流程 +111-MySQL8.0和5.7中SQL执行流程的演示 +112-Oracle中SQL执行流程_缓冲池的使用 +113-设置表的存储引擎、InnoDB与MyISAM的对比 +114-Archive、CSV、Memory等存储引擎的使用 +115-为什么使用索引及索引的优缺点 +116-一个简单的索引设计方案 +117-索引的迭代设计方案 +118-聚簇索引、二级索引与联合索引的概念 +119-InnoDB中B+树注意事项_MyISAM的索引方案 +120-Hash索引、AVL树、B树与B+树对比 +121-InnoDB数据存储结构概述 +122-页结构之文件头部与文件尾部 +123-页结构之最小最大记录_行格式之记录头信息 +124-页结构之页目录与页头 +125-设置行格式与ibd文件剖析Compact行格式 +126-行溢出与Dynamic、Compressed、Redundant行格式 +127-区、段、碎片区与表空间结构 +128-索引的分类 +129-表中添加索引的三种方式 +130-删除索引与索引新特性:降序索引、隐藏索引 +131-适合创建索引的11种情况1 +132-适合创建索引的11种情况2 +133-不适合创建索引的7种情况 +134-数据库优化步骤_查看系统性能参数 +135-慢查询日志分析、SHOW PROFILE查看SQL执行成本 +136-EXPLAIN的概述与table、id字段剖析 +137-EXPLAIN中select_type、partitions、type、possible_keys、key、key_len剖析 +138-EXPLAIN中ref、rows、filtered、extra剖析 +139-EXPLAIN的4种格式与查看优化器重写SQL +140-trace分析优化器执行计划与Sys schema视图的使用 +141-数据准备与索引失效的11种情况1 +142-索引失效的11种情况2 +143-外连接与内连接的查询优化 +144-JOIN的底层原理 +145-子查询优化与排序优化 +146-GROUP BY优化、分页查询优化 +147-覆盖索引、字符串的前缀索引 +148-索引条件下推(ICP) +149-普通索引和唯一索引的选择、其它5个优化策略 +150-淘宝数据库的主键如何设计 +151-范式概述与第一范式 +152-第二范式与第三范式 +153-反范式化的应用 +154-巴斯范式、第四范式、第五范式和域键范式 +155-范式的实战案例 +156-ER建模与转换数据表的过程 +157-数据库的设计原则和日常SQL编写规范 +158-PowerDesigner创建概念、物理数据模型 +159-数据库调优整体步骤、优化MySQL服务器硬件和参数 +160-数据库结构优化、大表优化、其它3个策略 +161-事务的ACID特性与事务的状态 +162-显式事务与隐式事务 +163-事务的使用举例 +164-数据并发问题与4种隔离级别 +165-MySQL隔离级别的查看和设置 +166-读未提交隔离性下的演示 +167-读已提交和可重复读的隔离性下的演示 +168-幻读的演示与解决方案 +169-Redo日志和Undo日志的理解、为什么需要Redo日志 +170-Redo日志的刷盘策略与过程剖析 +171-写入Redo Log Buffer和Redo Log File的写入策略 +172-Undo日志的概述与写入过程 +173-锁的概述_读写的并发问题 +174-数据操作类型的角度理解S锁与X锁 +175-表锁之S锁、X锁、意向锁 +176-表锁之自增锁、元数据锁 +177-行锁之记录锁、间隙锁 +178-行锁之临键锁与插入意向锁 +179-页锁的理解、乐观锁与悲观锁的使用 +180-加锁方式划分:隐式锁与显式锁 +181-全局锁与死锁的理解 +182-锁的内存结构与监控策略 +183-MVCC解决读写问题 +184-MVCC三剑客:隐藏字段、UndoLog版本链、ReadView规则 +185-MVCC在读已提交和可重复读隔离级别下的操作流程 +186-MVCC在可重复读下解决幻读的流程 +187-六大日志文件的概述 +188-通用查询日志、错误日志 +189-binlog日志的参数设置与实现数据恢复演示 +190-binlog的删除、binlog的写入机制与两阶段提交 +191-中继日志、主从复制的步骤与原理剖析 +192-一主一从架构搭建与主从同步的实现 +193-binlog的format设置说明 +194-主从延迟问题与数据同步一致性问题解决 +195-数据备份概述与mysqldump实现逻辑备份数据 +196-演示mysql实现逻辑恢复数据 +197-物理备份和物理恢复的演示、表数据的导出与导入 +198-数据库迁移与如何删库不跑路 +199-最后寄语 +``` + +**获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**MySQL**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) \ No newline at end of file diff --git a/docs/learning-resources/mysql45-section.md b/docs/learning-resources/mysql45-section.md new file mode 100644 index 0000000..9b646dc --- /dev/null +++ b/docs/learning-resources/mysql45-section.md @@ -0,0 +1,19 @@ +MySQL 使用和面试中遇到的问题,很多人会通过搜索别人的经验来解决 ,零散不成体系。实际上只要理解了 MySQL 的底层工作原理,就能很快地直戳问题的本质。 + +MySQL45讲专栏通过探讨 MySQL 实战中最常见的 **36 个** 痛点问题,串起各个零散的知识点,配合 **100+** 手绘详解图,由线到面带你构建 MySQL 系统的学习路径。 + +专栏共包括两大模块。 + +**模块一,基础篇**。为你深入浅出地讲述 MySQL 核心知识,涵盖 MySQL 基础架构、日志系统、事务隔离、锁等内容。 + +**模块二,实践篇**。将从一个个关键的数据库问题出发,分析数据库原理,并给出实践指导。每个问题,都不只是简单地给出答案,而是从为什么要这么想、到底该怎样做出发,让你能够知其所以然,都将能够解决你平时工作中的一个疑惑点。 + +建议大家都去听听这个专栏,干货满满! + +![](http://img.dabin-coder.cn/image/mysql45.jpg) + + + +**手册获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**1003**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) \ No newline at end of file diff --git a/docs/learning-resources/sgg-java-learn.md b/docs/learning-resources/sgg-java-learn.md new file mode 100644 index 0000000..ec0ecbb --- /dev/null +++ b/docs/learning-resources/sgg-java-learn.md @@ -0,0 +1,33 @@ +尚硅谷的 java 教程,不用多说,在行业内是排前面的,java 相关的所有技术,尚硅谷基本上都有对应的视频教程,这里给大家分享尚硅谷 java 全套教程,200多G,**文末直接获取**。 + +## 全套视频共5部分 + +![](http://img.dabin-coder.cn/image/image-20220319142501022.png) + +## 基础必备 + +![](http://img.dabin-coder.cn/image/image-20220319142551879.png) + +## 微服务核心 + +![](http://img.dabin-coder.cn/image/image-20220319142612142.png) + +## 微服务生态 + +![](http://img.dabin-coder.cn/image/image-20220319142638848.png) + +![](http://img.dabin-coder.cn/image/image-20220319142651513.png) + +## 项目实战 + +![](http://img.dabin-coder.cn/image/image-20220319142705479.png) + +## 选学技术 + +![](http://img.dabin-coder.cn/image/image-20220319142723454.png) + +![](http://img.dabin-coder.cn/image/image-20220319142734177.png) + +## 获取方式 + +百度云链接: https://pan.baidu.com/s/1F5HJKF9o455_1_oqMhMOEw?pwd=dv9s 提取码: dv9s \ No newline at end of file diff --git a/docs/learning-resources/shang-chou.md b/docs/learning-resources/shang-chou.md new file mode 100644 index 0000000..356900d --- /dev/null +++ b/docs/learning-resources/shang-chou.md @@ -0,0 +1,13 @@ +尚筹网项目是一个众筹项目,整个项目分为后台管理与前台会员两大部分。其整体框架图如下: + +![](http://img.dabin-coder.cn/image/尚筹网.jpg) + +1、后台管理系统为单一架构,由SSM框架进行实现,同时整合SpringSecurity来对用户权限进行控制。 + +2、前台会员系统 前台会员系统为分布式微服务架构,由SpringBoot+SpringCloud进行实现,同时为了上传项目图片整合了oss服务,以及为了支付整合了阿里的支付API。 + +![](http://img.dabin-coder.cn/image/尚筹网1.jpg) + +**获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**尚筹网**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/公众号.jpg) \ No newline at end of file diff --git a/docs/learning-resources/springboot-guide.md b/docs/learning-resources/springboot-guide.md new file mode 100644 index 0000000..0426d5d --- /dev/null +++ b/docs/learning-resources/springboot-guide.md @@ -0,0 +1,21 @@ +# Alibaba官方上线!SpringBoot+SpringCloud全彩指南(终极版) + +**Alibaba**作为国内一线互联网大厂,其中**SpringCloudAlibaba**更是阿里微服务最具代表性的技术之一,很多人只知道SpringCloudAlibaba其实面向微服务技术基本上都有的下面就给大家**推荐一份**Alibaba官网最新版:Spring+SpringBoot+SpringCloud微服务全栈开发小册,带你全面掌握Spring全家桶的知识。 + +下面直接给大家展示**目录**: + +**SpringBoot** + +![](http://img.dabin-coder.cn/image/springboot-guide1.jpg) + +![](http://img.dabin-coder.cn/image/springboot-guide.jpg) + +**SpringCloudAlibaba** + +![](http://img.dabin-coder.cn/image/springboot-guide3.jpg) + +![](http://img.dabin-coder.cn/image/springboot-guide4.jpg) + +**高清pdf版获取方式**:微信搜索「**程序员大彬**」或者扫描下面的二维码,关注后发送关键字「**1001**」就可以找到下载链接了(**无套路,无解压密码**)。 + +![](http://img.dabin-coder.cn/image/image-20221207225029295.png) \ No newline at end of file diff --git a/docs/leetcode/README.md b/docs/leetcode/README.md new file mode 100644 index 0000000..c5a7b72 --- /dev/null +++ b/docs/leetcode/README.md @@ -0,0 +1,40 @@ +## 目录 + +- [1.两数之和-梦开始的地方!!](./hot120/1-two-sum.md) +- [3.无重复字符的最长子串](./hot120/3-longest-substring-without-repeating-characters.md) +- [5.最长回文子串](./hot120/5-longest-palindromic-substring.md) +- [7.整数反转](./hot120/7-reverse-integer.md) +- [15.三数之和](./hot120/15-3sum.md) +- [19.删除链表的倒数第N个结点](./hot120/19-remove-nth-node-from-end-of-list.md) +- [22.括号生成](./hot120/22-generate-parentheses.md) +- [28.对称的二叉树](./hot120/28-mirror-binary-tree.md) +- [40.组合总和II](./hot120/40-combination-sum-ii.md) +- [46.全排列](./hot120/46-permutations.md) +- [47.全排列II](./hot120/47-permutations-ii.md) +- [53.最大子数组和](./hot120/53-maximum-subarray.md) +- [55.跳跃游戏](./hot120/55-jump-game.md) +- [56.合并区间](./hot120/56-merge-intervals.md) +- [62.不同路径](./hot120/62-unique-paths.md) +- [92.反转链表II](./hot120/92-reverse-linked-list-ii.md) +- [98.验证二叉搜索树](./hot120/98-validate-binary-search-tree.md) +- [103.二叉树的锯齿形层序遍历](./hot120/103-binary-tree-zigzag-level-order-traversal.md) +- [104.二叉树的最大深度](./hot120/104-maximum-depth-of-binary-tree.md) +- [120.三角形最小路径和](./hot120/120-triangle.md) +- [121.买卖股票的最佳时机](./hot120/121-best-time-to-buy-and-sell-stock.md) +- [122.买卖股票的最佳时机II](./hot120/122-best-time-to-buy-and-sell-stock-ii.md) +- [131.分割回文串](./hot120/131-palindrome-partion.md) +- [133.克隆图](./hot120/133-clone-graph.md) +- [134.加油站](./hot120/134-gas-station.md) +- [141.环形链表II](./hot120/141-linked-list-cycle.md) +- [152.乘积最大子数组](./hot120/152-maximum-product-subarray.md) +- [160.相交链表](./hot120/160-intersection-of-two-linked-lists.md) +- [169.多数元素](./hot120/169-majority-element.md) +- [199.二叉树的右视图](./hot120/199-binary-tree-right-side-view.md) +- [200.岛屿数量](./hot120/200-number-of-islands.md) +- [206.反转链表](./hot120/206-reverse-linked-list.md) +- [215.数组中的第K个最大元素](./hot120/215-kth-largest-element-in-an-array.md) +- [234.回文链表](./hot120/234-palindrome-linked-list.md) +- [236.二叉树的最近公共祖先](./hot120/236-lowest-common-ancestor-of-a-binary-tree.md) +- [415.字符串相加](./hot120/415-add-strings.md) +- [543.二叉树的直径](./hot120/543-diameter-of-binary-tree.md) +- [1143.最长公共子序列](./hot120/1143-longest-common-subquence.md) diff --git a/docs/leetcode/hot120/1-two-sum.md b/docs/leetcode/hot120/1-two-sum.md new file mode 100644 index 0000000..c1fb3cc --- /dev/null +++ b/docs/leetcode/hot120/1-two-sum.md @@ -0,0 +1,49 @@ +# 1. 两数之和 + +[1. 两数之和](https://leetcode.cn/problems/two-sum/) + +**题目描述** + +给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 + +你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 + +你可以按任意顺序返回答案。 + +**示例** + +```java +输入:nums = [2,7,11,15], target = 9 +输出:[0,1] +解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 +``` + +**解题思路** + +- 遍历数组 nums,i 为当前下标,每个值都判断map中是否存在 `nums[i]` 的 key 值。 + +- 如果存在则找到了两个值,如果不存在则将当前的 `(target - nums[i],i)` 存入 map 中,继续遍历直到找到为止。 + +**参考代码**: + +```java +class Solution { + public int[] twoSum(int[] nums, int target) { + int[] result = new int[2]; + Map map = new HashMap<>(); + + for (int i = 0; i < nums.length; i++) { + if (map.containsKey(nums[i])) { + result[0] = map.get(nums[i]); + result[1] = i; + return result; + } + map.put(target - nums[i], i); + } + + return result; + } +} +``` + + diff --git a/docs/leetcode/hot120/103-binary-tree-zigzag-level-order-traversal.md b/docs/leetcode/hot120/103-binary-tree-zigzag-level-order-traversal.md new file mode 100644 index 0000000..103469b --- /dev/null +++ b/docs/leetcode/hot120/103-binary-tree-zigzag-level-order-traversal.md @@ -0,0 +1,69 @@ +# 103. 二叉树的锯齿形层序遍历 + +[103. 二叉树的锯齿形层序遍历](https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/) + +**题目描述** + +给你二叉树的根节点 `root` ,返回其节点值的 **锯齿形层序遍历** 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 + +**示例** + +``` +输入:root = [3,9,20,null,null,15,7] +输出:[[3],[20,9],[15,7]] +``` + +**解题思路** + +使用两个栈实现。 + +**代码实现** + +```java +class Solution { + public List> zigzagLevelOrder(TreeNode root) { + List> res = new ArrayList<>(); + + //判空 + if (root == null) { + return res; + } + Stack s1 = new Stack<>(); + Stack s2 = new Stack<>(); + + s1.push(root); + + while (!s1.isEmpty() || !s2.isEmpty()) { + List list = new ArrayList<>(); + if (!s1.isEmpty()) { + while (!s1.isEmpty()) { + TreeNode node = s1.pop(); + list.add(node.val); + if (node.left != null) { + s2.push(node.left); + } + if (node.right != null) { + s2.push(node.right); + } + } + } else { + while (!s2.isEmpty()) { + TreeNode node = s2.pop(); + list.add(node.val); + if (node.right != null) { + s1.push(node.right); + } + if (node.left != null) { + s1.push(node.left); + } + } + } + res.add(list); + } + + return res; + } +} +``` + + diff --git a/docs/leetcode/hot120/104-maximum-depth-of-binary-tree.md b/docs/leetcode/hot120/104-maximum-depth-of-binary-tree.md new file mode 100644 index 0000000..d2f3ef0 --- /dev/null +++ b/docs/leetcode/hot120/104-maximum-depth-of-binary-tree.md @@ -0,0 +1,52 @@ +# 104. 二叉树的最大深度 + +[题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/) + +**题目描述** + +给定一个二叉树,找出其最大深度。 + +二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 + +**说明:** 叶子节点是指没有子节点的节点。 + +**示例** + +```java +给定二叉树 [3,9,20,null,null,15,7], + 3 + / \ + 9 20 + / \ + 15 7 +返回它的最大深度 3 。 +``` + +**解题思路** + +找出终止条件:当前节点为空 +找出返回值:节点为空时说明高度为 0,所以返回 0;节点不为空时则分别求左右子树的高度的最大值,同时加1表示当前节点的高度,返回该数值 + +**参考代码**: + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; + } +} +``` + + diff --git a/docs/leetcode/hot120/11-container-with-most-water.md b/docs/leetcode/hot120/11-container-with-most-water.md new file mode 100644 index 0000000..7c016c3 --- /dev/null +++ b/docs/leetcode/hot120/11-container-with-most-water.md @@ -0,0 +1,52 @@ +# 11. 盛最多水的容器 + +[11. 盛最多水的容器](https://leetcode.cn/problems/container-with-most-water/) + +**题目描述** + +给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 + +找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 + +返回容器可以储存的最大水量。 + +说明:你不能倾斜容器。 + +![](http://img.dabin-coder.cn/image/1586272990587.png) + +**示例** + +```java +输入:[1,8,6,2,5,4,8,3,7] +输出:49 +解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 + +输入:height = [1,1] +输出:1 +``` + +**解题思路** + +左右指针,数字小的指针往数字大的指针移动,面积才有可能变大。注意左右指针数字相同的情况。 + +```java +class Solution { + public int maxArea(int[] height) { + int maxArea = 0; + int left = 0; + int right = height.length - 1; + + while(left < right) { + maxArea = Math.max(maxArea, Math.min(height[left], height[right]) * (right - left)); + if(height[left] > height[right]) { + right--; + } else { + left++; + } + } + + return maxArea; + } +} +``` + diff --git a/docs/leetcode/hot120/1143-longest-common-subquence.md b/docs/leetcode/hot120/1143-longest-common-subquence.md new file mode 100644 index 0000000..8d66be9 --- /dev/null +++ b/docs/leetcode/hot120/1143-longest-common-subquence.md @@ -0,0 +1,102 @@ +# 1143. 最长公共子序列 + +[原题链接](https://leetcode.cn/problems/longest-common-subsequence/) + +## 题目描述 + +给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 + +一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。 + +例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。 +两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。 + +示例: + +```java +输入:text1 = "abcde", text2 = "ace" +输出:3 +解释:最长公共子序列是 "ace" ,它的长度为 3 。 +``` + +## 解题思路 + +动态规划。 + +解法一:`dp[i][j]`表示text1以i-1结尾的子串和text2以j-1结尾的子串的最长公共子序列的长度。dp横坐标或纵坐标为0表示空字符串,`dp[0][j] = dp[i][0] = 0`,无需额外处理base case。 + +![](http://img.dabin-coder.cn/image/longestCommonSubsequence.png) + +```java +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + char[] arr1 = text1.toCharArray(); + char[] arr2 = text2.toCharArray(); + //dp[0][x]和dp[x][0]表示有一个为空字符串 + //dp[1][1]为text1第一个字符和text2第一个字符的最长公共子序列的长度 + //dp[i][j]表示text1以i-1结尾的子串和text2以j-1结尾的子串的最长公共子序列的长度 + int len1 = arr1.length; + int len2 = arr2.length; + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i < len1 + 1; i++) { + for (int j = 1; j < len2 + 1; j++) { + if (arr1[i - 1] == arr2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[len1][len2]; + } +} +``` + +解法二:`dp[i][j]`表示text1以i结尾的子串和text2以j结尾的子串的最长公共子序列的长度。需要处理base case。 + +```java +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + char[] arr1 = text1.toCharArray(); + char[] arr2 = text2.toCharArray(); + + int len1 = arr1.length; + int len2 = arr2.length; + //`dp[i][j]`表示text1以i结尾的子串和text2以j结尾的子串的最长公共子序列的长度。 + int[][] dp = new int[len1][len2]; + + if (arr1[0] == arr2[0]) { + dp[0][0] = 1; + } + for (int i = 1; i < len1; i++) { + if (arr1[i] == arr2[0]) { + dp[i][0] = 1; + } else { + dp[i][0] = dp[i - 1][0]; + } + } + for (int i = 1; i < len2; i++) { + if (arr1[0] == arr2[i]) { + dp[0][i] = 1; + } else { + dp[0][i] = dp[0][i - 1]; + } + } + + for (int i = 1; i < len1; i++) { + for (int j = 1; j < len2; j++) { + if (arr1[i] == arr2[j]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[len1 - 1][len2 - 1]; + } +} +``` + diff --git a/docs/leetcode/hot120/120-triangle.md b/docs/leetcode/hot120/120-triangle.md new file mode 100644 index 0000000..afea3eb --- /dev/null +++ b/docs/leetcode/hot120/120-triangle.md @@ -0,0 +1,47 @@ +# 120. 三角形最小路径和 + +[题目链接](https://leetcode.cn/problems/triangle/) + +**题目描述** + +给定一个三角形 triangle ,找出自顶向下的最小路径和。 + +每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。 + +**示例** + +```java +输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]] +输出:11 +解释:如下面简图所示: + 2 + 3 4 + 6 5 7 +4 1 8 3 +自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。 + +来源:力扣(LeetCode) +链接:https://leetcode.cn/problems/triangle +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +**解题思路** + +动态规划。 + +```java +class Solution { + public int minimumTotal(List> triangle) { + int size = triangle.size(); + int[] minLen = new int[size + 1];//+1 + for (int i = size - 1; i >= 0 ; i--) { + for (int j = 0; j <= i; j++) { + minLen[j] = Math.min(minLen[j], minLen[j + 1]) + triangle.get(i).get(j); + } + } + + return minLen[0]; + } +} +``` + diff --git a/docs/leetcode/hot120/121-best-time-to-buy-and-sell-stock.md b/docs/leetcode/hot120/121-best-time-to-buy-and-sell-stock.md new file mode 100644 index 0000000..2042f2f --- /dev/null +++ b/docs/leetcode/hot120/121-best-time-to-buy-and-sell-stock.md @@ -0,0 +1,41 @@ +# 121. 买卖股票的最佳时机 + +[原题链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/) + +## 题目描述 + +给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 + +你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 + +返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。 + +**示例**: + +```java +输入:[7,1,5,3,6,4] +输出:5 +解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 + 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。 +``` + +## 解题思路 + +动态规划。前i天的最大收益 = max{前i-1天的最大收益,第i天的价格-前i-1天中的最小价格} + +```java +class Solution { + public int maxProfit(int[] prices) { + int minPrice = Integer.MAX_VALUE; + int maxProfit = 0; + for (int i = 0; i < prices.length; i++) { + if (prices[i] < minPrice) { + minPrice = prices[i]; + } + maxProfit = Math.max(prices[i] - minPrice, maxProfit); + } + return maxProfit; + } +} +``` + diff --git a/docs/leetcode/hot120/122-best-time-to-buy-and-sell-stock-ii.md b/docs/leetcode/hot120/122-best-time-to-buy-and-sell-stock-ii.md new file mode 100644 index 0000000..0d5cca4 --- /dev/null +++ b/docs/leetcode/hot120/122-best-time-to-buy-and-sell-stock-ii.md @@ -0,0 +1,43 @@ +# 122. 买卖股票的最佳时机 II + +[题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/) + +**题目描述**: + +给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 + +在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 + +返回 你能获得的 最大 利润 。 + +**示例**: + +```java +输入:prices = [1,2,3,4,5] +输出:4 +解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 +  总利润为 4 。 +``` + +**解题思路** + +可以尽可能地完成更多的交易,但不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + +```java +//输入: [7,1,5,3,6,4] +//输出: 7 +class Solution { + public int maxProfit(int[] prices) { + int profit = 0; + for (int i = 1; i < prices.length; i++) { + int tmp = prices[i] - prices[i - 1]; + if (tmp > 0) { + profit += tmp; + } + } + + return profit; + } +} +``` + diff --git a/docs/leetcode/hot120/128-longest-consecutive-sequence.md b/docs/leetcode/hot120/128-longest-consecutive-sequence.md new file mode 100644 index 0000000..00e2aa2 --- /dev/null +++ b/docs/leetcode/hot120/128-longest-consecutive-sequence.md @@ -0,0 +1,54 @@ +# 128. 最长连续序列 + +[128. 最长连续序列](https://leetcode.cn/problems/longest-consecutive-sequence/) + +**题目描述**: + +给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 + +请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 + +**示例**: + +```java +输入:nums = [100,4,200,1,3,2] +输出:4 +解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 +``` + +**解题思路** + +将数组存入set。遍历数组,对`num[i]`前后连续的数字进行计数,并将set中的这些数字移除,避免重复计算。 + +比如`[10, 9, 8, 7, 11, 14]`,存入set。遍历第一个元素10,set移除10,10前面有7-8-9,后面有11,连续序列长度为5,将set中的7-8-9-11移除,后续遍历到7-8-9-11,直接跳过。 + +```java +class Solution { + public int longestConsecutive(int[] nums) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + + int len = 0; + int maxLen = 0; + for (int num : nums) { + len = 1; + if (set.remove(num)) { + int cur = num; + while (set.remove(--cur)) { + len++; + } + cur = num; + while (set.remove(++cur)) { + len++; + } + maxLen = maxLen > len ? maxLen : len; + } + } + + return maxLen; + } +} +``` + diff --git a/docs/leetcode/hot120/131-palindrome-partion.md b/docs/leetcode/hot120/131-palindrome-partion.md new file mode 100644 index 0000000..20d92a7 --- /dev/null +++ b/docs/leetcode/hot120/131-palindrome-partion.md @@ -0,0 +1,69 @@ +# 131. 分割回文串 + +[题目链接](https://leetcode.cn/problems/palindrome-partitioning/) + +**题目描述** + +给你一个字符串 `s`,请你将 `s` 分割成一些子串,使每个子串都是 **回文串** 。返回 `s` 所有可能的分割方案。 + +**回文串** 是正着读和反着读都一样的字符串。 + +**示例** + +``` +输入:s = "aab" +输出:[["a","a","b"],["aa","b"]] +``` + +**解题思路** + +[参考题解](https://leetcode-cn.com/problems/palindrome-partitioning/solution/hui-su-you-hua-jia-liao-dong-tai-gui-hua-by-liweiw/) + +使用动态规划预标记出哪一段属于回文串。 + +```java +class Solution { + public List> partition(String s) { + List> res = new ArrayList<>(); + + int len = s.length(); + if (s == null || len == 0) { + return res; + } + + boolean dp[][] = new boolean[len][len]; + char[] charArr = s.toCharArray(); + + for (int i = 0; i < len; i++) { + dp[i][i] = true; + } + + for (int right = 1; right < len; right++) { + for (int left = 0; left < right; left++) { + dp[left][right] = charArr[left] == charArr[right] && (right - left <= 2 || dp[left + 1][right - 1]); + } + } + + LinkedList path = new LinkedList<>(); + dfs(s, 0, res, path, dp); + + return res; + } + + private void dfs(String s, int start, List> res, LinkedList path, boolean[][] dp) { + if (start == s.length()) { + res.add(new ArrayList<>(path)); + return; + } + + for (int i = start; i < s.length(); i++) { + if (dp[start][i]) { + path.addLast(s.substring(start, i + 1)); + dfs(s, i + 1, res, path, dp); + path.removeLast(); + } + } + } +} +``` + diff --git a/docs/leetcode/hot120/133-clone-graph.md b/docs/leetcode/hot120/133-clone-graph.md new file mode 100644 index 0000000..8873b3b --- /dev/null +++ b/docs/leetcode/hot120/133-clone-graph.md @@ -0,0 +1,89 @@ +# 133.克隆图 + +[题目链接](https://leetcode.cn/problems/clone-graph/) + +**题目描述** + +给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。 + +图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。 + +```java +class Node { + public int val; + public List neighbors; +} +``` + +示例: + +```java +输入:adjList = [[2,4],[1,3],[2,4],[1,3]] +输出:[[2,4],[1,3],[2,4],[1,3]] +解释: +图中有 4 个节点。 +节点 1 的值是 1,它有两个邻居:节点 2 和 4 。 +节点 2 的值是 2,它有两个邻居:节点 1 和 3 。 +节点 3 的值是 3,它有两个邻居:节点 2 和 4 。 +节点 4 的值是 4,它有两个邻居:节点 1 和 3 。 +``` + +**解题思路** + +深度优先搜索。 + +```java +class Solution { + public Node cloneGraph(Node node) { + Map lookup = new HashMap<>(); + return dfs(node, lookup); + } + + private Node dfs(Node node, Map lookup) { + if (node == null) return null; + if (lookup.containsKey(node)) return lookup.get(node); + Node clone = new Node(node.val, new ArrayList<>()); + lookup.put(node, clone); + for (Node n : node.neighbors)clone.neighbors.add(dfs(n,lookup)); + return clone; + } +} +``` + +广度优先搜索。遍历图的过程,未访问过的节点放入队列。 + +```java +class Solution { + public Node cloneGraph(Node node) { + return bfs(node, new HashMap()); + } + + private Node bfs(Node root, HashMap visitedMap) { + if (root == null) { + return root; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + Node cloneNode = new Node(root.val, new ArrayList<>()); + visitedMap.put(root, cloneNode); + + while (queue.size() != 0) { + Node node = queue.poll(); + + for (Node n : node.neighbors) { + Node tmp = visitedMap.get(n); + if (tmp == null) { + queue.offer(n); //未访问过的放入队列 + tmp = new Node(n.val, new ArrayList<>()); + visitedMap.put(n, tmp); //标记访问过 + } + visitedMap.get(node).neighbors.add(tmp); + } + } + + return visitedMap.get(root); + } +} +``` + diff --git a/docs/leetcode/hot120/134-gas-station.md b/docs/leetcode/hot120/134-gas-station.md new file mode 100644 index 0000000..7d149db --- /dev/null +++ b/docs/leetcode/hot120/134-gas-station.md @@ -0,0 +1,50 @@ +# 134. 加油站 + +[134. 加油站](https://leetcode.cn/problems/gas-station/) + +**题目描述** + +在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 + +你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 + +给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。 + +**示例** + +```java +输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2] +输出: 3 +解释: +从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油 +开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油 +开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油 +开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油 +开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油 +开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。 +因此,3 可为起始索引。 +``` + +**解题思路**: + +1. 遍历一周,总获得的油量少于要花掉的油量必然没有结果; +2. 先苦后甜,记录遍历时所存的油量最少的站点,由于题目有解只有唯一解,所以从当前站点的下一个站点开始是唯一可能成功开完全程的。 + +```java +class Solution { + public int canCompleteCircuit(int[] gas, int[] cost) { + int minIdx=0; + int sum=Integer.MAX_VALUE; + int num=0; + for (int i = 0; i < gas.length; i++) { + num+=gas[i]-cost[i]; + if(num 0) { + fast = fast.next; + } + while (fast != slow) { + fast = fast.next; + slow = slow.next; + } + + return fast; + } +} +``` + diff --git a/docs/leetcode/hot120/148-sort-list.md b/docs/leetcode/hot120/148-sort-list.md new file mode 100644 index 0000000..3f13a87 --- /dev/null +++ b/docs/leetcode/hot120/148-sort-list.md @@ -0,0 +1,112 @@ +# 148. 排序链表 + +[148. 排序链表](https://leetcode.cn/problems/sort-list/) + +**题目描述** + +给你链表的头结点 `head` ,请将其按 **升序** 排列并返回 **排序后的链表** 。 + +**示例** + +```java +输入:head = [4,2,1,3] +输出:[1,2,3,4] +``` + +**解题思路** + +1、归并排序。 + +```java +//输入: 4->2->1->3 +//输出: 1->2->3->4 +class Solution { + public ListNode sortList(ListNode head) { + return mergeSort(head); + } + + public ListNode mergeSort(ListNode head) { + if (head == null || head.next == null) { + return head; + } + + ListNode fast = head, slow = head; + while (fast != null && fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + ListNode rHead = slow.next; + slow.next = null; //断开链表 + + ListNode l = mergeSort(head); + ListNode r = mergeSort(rHead); + + return merge(l, r); + } + + public ListNode merge(ListNode l, ListNode r) { + ListNode tmp = new ListNode(0); + ListNode cur = tmp; + + while (l != null && r != null) { + if (l.val > r.val) { + cur.next = r; + r = r.next; + } else { + cur.next = l; + l = l.next; + } + cur = cur.next; + } + + cur.next = l == null ? r : l; + + return tmp.next; + } +} +``` + +[排序链表快速排序](https://www.cnblogs.com/morethink/p/8452914.html) + +![](http://img.topjavaer.cn/image/sort-list.png) + +```java +//快速排序 +//链表头结点作为基准值key。使用两个指针p1和p2,这两个指针均往next方向移动,移动的过程中保持p1之前的key都小于选定的key,p1和p2之间的key都大于选定的key,那么当p2走到末尾时交换p1与key值便完成了一次切分。 +class Solution { + public ListNode sortList(ListNode head) { + return quickSort(head, null); + } + + private ListNode quickSort(ListNode head, ListNode tail) { + if (head != tail) { + ListNode node = quickSortHelper(head, tail); + quickSort(head, node); + quickSort(node.next, tail); + } + return head; + } + + private ListNode quickSortHelper(ListNode head, ListNode tail) { + ListNode p1 = head, p2 = head.next; + while (p2 != tail) { + if (p2.val < head.val) { + p1 = p1.next; + int tmp = p1.val; + p1.val = p2.val; + p2.val = tmp; + } + p2 = p2.next; + } + + if (p1 != head) { + int tmp = p1.val; + p1.val = head.val; + head.val = tmp; + } + + return p1; + } +} +``` + diff --git a/docs/leetcode/hot120/15-3sum.md b/docs/leetcode/hot120/15-3sum.md new file mode 100644 index 0000000..e24767f --- /dev/null +++ b/docs/leetcode/hot120/15-3sum.md @@ -0,0 +1,62 @@ +# 15. 三数之和 + +[题目链接](https://leetcode.cn/problems/3sum/) + +**题目描述** + +给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。 + +注意:答案中不可以包含重复的三元组。 + +**示例** + +```java +输入:nums = [-1,0,1,2,-1,-4] +输出:[[-1,-1,2],[-1,0,1]] +``` + +**解题思路** + +固定 3 个指针中最左(最小)数字的指针 k,双指针 i,j 分设在数组索引 k 两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合: + +- 当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即 3 个数字都大于 0 ,在此固定指针 k 之后不可能再找到结果了。 +- 当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。 +- i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动: + - 当s < 0时,i += 1并跳过所有重复的nums[i]; + - 当s > 0时,j -= 1并跳过所有重复的nums[j]; + - 当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。 + +**参考代码**: + +```java +class Solution { + public List> threeSum(int[] nums) { + Arrays.sort(nums); + List> res = new ArrayList<>(); + for(int k = 0; k < nums.length - 2; k++){ + if(nums[k] > 0) break; + if(k > 0 && nums[k] == nums[k - 1]) continue; + int i = k + 1, j = nums.length - 1; + while(i < j){ + int sum = nums[k] + nums[i] + nums[j]; + if(sum < 0){ + while(i < j && nums[i] == nums[++i]); + } else if (sum > 0) { + while(i < j && nums[j] == nums[--j]); + } else { + res.add(new ArrayList(Arrays.asList(nums[k], nums[i], nums[j]))); + while(i < j && nums[i] == nums[++i]); + while(i < j && nums[j] == nums[--j]); + } + } + } + return res; + } +} +``` + + + +> 作者:jyd +> 链接:https://leetcode.cn/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/ +> 来源:力扣(LeetCode) \ No newline at end of file diff --git a/docs/leetcode/hot120/152-maximum-product-subarray.md b/docs/leetcode/hot120/152-maximum-product-subarray.md new file mode 100644 index 0000000..3d4c41c --- /dev/null +++ b/docs/leetcode/hot120/152-maximum-product-subarray.md @@ -0,0 +1,45 @@ +# 152. 乘积最大子数组 + +[题目链接](https://leetcode.cn/problems/maximum-product-subarray/) + +**题目描述** + +给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 + +测试用例的答案是一个 32-位 整数。 + +子数组 是数组的连续子序列。 + +**示例** + +```java +输入: nums = [2,3,-2,4] +输出: 6 +解释: 子数组 [2,3] 有最大乘积 6。 +``` + +**解题思路** + +动态规划。 + +```java +class Solution { + public int maxProduct(int[] nums) { + int curMax = 1, curMin = 1;//保证i=1时,结果正确 + int max = Integer.MIN_VALUE; + for (int i = 0; i < nums.length; i++) { + if (nums[i] < 0) { + int tmp = curMax; + curMax = curMin; + curMin = tmp; + } + curMax = Math.max(curMax, curMax * nums[i]); + curMin = Math.min(curMin, curMin * nums[i]); + + max = Math.max(max, curMax);//[2,-2],当i=1时,curMax与curMin交换,curMax=1,max=2,故取max与curMax中最大值 + } + return max; + } +} +``` + diff --git a/docs/leetcode/hot120/160-intersection-of-two-linked-lists.md b/docs/leetcode/hot120/160-intersection-of-two-linked-lists.md new file mode 100644 index 0000000..e613359 --- /dev/null +++ b/docs/leetcode/hot120/160-intersection-of-two-linked-lists.md @@ -0,0 +1,39 @@ +# 160. 相交链表 + +[题目链接](https://leetcode.cn/problems/intersection-of-two-linked-lists/) + +**题目描述** + +给你两个单链表的头节点 `headA` 和 `headB` ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 `null` 。 + +**示例** + +```java +输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 +输出:Intersected at '8' +解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。 +从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。 +在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 +— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。 +``` + +**解题思路** + +两个指针a和b,a指向headA,b指向headB,两个指针同时出发。假如a先走到尽头,则a重新指向headB。然后b走到尽头,b重新指向headA。如果是相交链表,则a和b会相遇,否则a/b最终会指向null。 + +```java +public class Solution { + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + ListNode a = headA; + ListNode b = headB; + + while (a != b) { + a = a == null ? headB : a.next; + b = b == null ? headA : b.next; + } + + return a; + } +} +``` + diff --git a/docs/leetcode/hot120/169-majority-element.md b/docs/leetcode/hot120/169-majority-element.md new file mode 100644 index 0000000..2390101 --- /dev/null +++ b/docs/leetcode/hot120/169-majority-element.md @@ -0,0 +1,47 @@ +# 169. 多数元素 + +[169. 多数元素](https://leetcode.cn/problems/majority-element/) + +**题目描述** + +给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 + +你可以假设数组是非空的,并且给定的数组总是存在多数元素。 + +**示例** + +``` +输入:nums = [3,2,3] +输出:3 +``` + +**解题思路** + +**摩尔投票法** + +从第一个数开始count=1,遇到相同的就加1,遇到不同的就减1,减到0就重新换个数开始计数,总能找到最多的那个。 + +**代码实现** + +```java +class Solution { + public int majorityElement(int[] nums) { + int ret = nums[0]; + int count = 1; + for(int num : nums) { + if(num != ret) { + count--; + if(count == 0) { + count = 1; + ret = num; + } + } + else + count++; + } + return ret; + } +} +``` + + diff --git a/docs/leetcode/hot120/18-4sum .md b/docs/leetcode/hot120/18-4sum .md new file mode 100644 index 0000000..92ccdf0 --- /dev/null +++ b/docs/leetcode/hot120/18-4sum .md @@ -0,0 +1,76 @@ +# 18. 四数之和 + +[18. 四数之和](https://leetcode.cn/problems/4sum/) + +**题目描述** + +给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复): + +- 0 <= a, b, c, d < n +- a、b、c 和 d 互不相同 +- nums[a] + nums[b] + nums[c] + nums[d] == target + +你可以按 任意顺序 返回答案 。 + +**示例** + +```java +输入:nums = [1,0,-1,0,-2,2], target = 0 +输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]] + +输入:nums = [2,2,2,2,2], target = 8 +输出:[[2,2,2,2]] +``` + +**解题思路** + +**参考代码**: + +```java +class Solution { + public List> fourSum(int[] nums, int target) { + List> ans = new ArrayList<>(); + if (nums == null || nums.length < 4) { + return ans; + } + int len = nums.length; + + Arrays.sort(nums); + + for (int i = 0; i < len; i++) { + if (i > 0 && nums[i] == nums[i - 1]) { // forgot, 去重复 + continue; + } + for (int j = i + 1; j < len; j++) { + if (j > i + 1 && nums[j] == nums[j - 1]) {//j大于i+1才去重复 + continue; + } + int left = j + 1; + int right = len - 1; + while (left < right) { + int sum = nums[i] + nums[j] + nums[left] + nums[right]; + if (sum == target) { + ans.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right])); + while (left < right && nums[left] == nums[left + 1]) { + left++;//去重复 + } + while (left < right && nums[right] == nums[right - 1]) { + right--;//去重复 + } + left++;//forgot + right--;//forgot + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + } + + return ans; + } +} +``` + + diff --git a/docs/leetcode/hot120/19-remove-nth-node-from-end-of-list.md b/docs/leetcode/hot120/19-remove-nth-node-from-end-of-list.md new file mode 100644 index 0000000..101d663 --- /dev/null +++ b/docs/leetcode/hot120/19-remove-nth-node-from-end-of-list.md @@ -0,0 +1,55 @@ +# 19. 删除链表的倒数第 N 个结点 + +[原题链接](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/) + +**题目描述** + +给你一个链表,删除链表的倒数第 `n` 个结点,并且返回链表的头结点。 + +**示例** + +```java +输入:head = [1,2,3,4,5], n = 2 +输出:[1,2,3,5] +``` + +**解题思路** + +我们可以设想假设设定了双指针 p 和 q 的话,当 q 指向末尾的 NULL,p 与 q 之间相隔的元素个数为 n 时,那么删除掉 p 的下一个指针就完成了要求。 + +- 设置虚拟节点 dummyHead 指向 head +- 设定双指针 p 和 q,初始都指向虚拟节点 dummyHead +- 移动 q,直到 p 与 q 之间相隔的元素个数为 n +- 同时移动 p 与 q,直到 q 指向的为 NULL +- 将 p 的下一个节点指向下下个节点 + +![](http://img.dabin-coder.cn/image/删除链表nth.gif) + +> 作者:cxywushixiong +> 链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/solution/dong-hua-tu-jie-leetcode-di-19-hao-wen-ti-shan-chu/ +> 来源:力扣(LeetCode) + +**代码实现** + +```java +class Solution { + public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode dummy = new ListNode(-1); + dummy.next = head; + ListNode pre = dummy; + ListNode slow = head; + ListNode fast = head; + for(int i=0;i rightSideView(TreeNode root) { + List res = new ArrayList<>(); + if (root == null) { + return res; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { //先取size的值,再自减 + TreeNode node = queue.poll(); + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + if (size == 0) { //最右边的节点 + res.add(node.val); + } + } + } + + return res; + } +} +``` + diff --git a/docs/leetcode/hot120/20-valid-parentheses.md b/docs/leetcode/hot120/20-valid-parentheses.md new file mode 100644 index 0000000..62b4db6 --- /dev/null +++ b/docs/leetcode/hot120/20-valid-parentheses.md @@ -0,0 +1,56 @@ +# 20. 有效的括号 + +[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/) + +**题目描述** + +给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。 + +有效字符串需满足: + +- 左括号必须用相同类型的右括号闭合。 +- 左括号必须以正确的顺序闭合。 +- 每个右括号都有一个对应的相同类型的左括号。 + +**示例** + +```java +输入:s = "()" +输出:true + +输入:s = "()[]{}" +输出:true +``` + +**解题思路** + +使用栈实现。 + +```java +class Solution { + public boolean isValid(String s) { + Stack stack = new Stack<>(); + + for (int i = 0; i < s.length(); i++) { + switch (s.charAt(i)) { + case '(': + stack.push(')');//存进相反符号 + break; + case '[': + stack.push(']'); + break; + case '{': + stack.push('}'); + break; + default: + if (stack.isEmpty() || s.charAt(i) != stack.pop()) { + return false; + } + break; + } + } + return stack.isEmpty(); + } +} +``` + diff --git a/docs/leetcode/hot120/200-number-of-islands.md b/docs/leetcode/hot120/200-number-of-islands.md new file mode 100644 index 0000000..d44c3a1 --- /dev/null +++ b/docs/leetcode/hot120/200-number-of-islands.md @@ -0,0 +1,65 @@ +# 200. 岛屿数量 + +[题目链接](https://leetcode.cn/problems/number-of-islands/) + +**题目描述** + +给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 + +岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 + +此外,你可以假设该网格的四条边均被水包围。 + +**示例** + +```java +输入:grid = [ + ["1","1","1","1","0"], + ["1","1","0","1","0"], + ["1","1","0","0","0"], + ["0","0","0","0","0"] +] +输出:1 +``` + +**解题思路** + +深度优先遍历,使用isVisited数组记录元素是否被访问过。 + +```java +class Solution { + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + + boolean[][] isVisited = new boolean[grid.length][grid[0].length]; + int count = 0; + + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == '1' && !isVisited[i][j]) { + dfs(grid, isVisited, i, j); + count++; + } + } + } + + return count; + } + + private void dfs(char[][] grid, boolean[][] isVisited, int i, int j) { + if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0') { + return; + } + if (!isVisited[i][j]) { + isVisited[i][j] = true; + dfs(grid, isVisited, i + 1, j); + dfs(grid, isVisited, i - 1, j); + dfs(grid, isVisited, i, j + 1); + dfs(grid, isVisited, i, j - 1); + } + } +} +``` + diff --git a/docs/leetcode/hot120/206-reverse-linked-list.md b/docs/leetcode/hot120/206-reverse-linked-list.md new file mode 100644 index 0000000..4618e34 --- /dev/null +++ b/docs/leetcode/hot120/206-reverse-linked-list.md @@ -0,0 +1,44 @@ +# 206. 反转链表 + +[原题链接](https://leetcode.cn/problems/reverse-linked-list/) + +**题目描述** + +给你单链表的头节点 `head` ,请你反转链表,并返回反转后的链表。 + +**示例** + +```java +输入:head = [1,2,3,4,5] +输出:[5,4,3,2,1] +``` + +**解题思路**: + +1. 定义两个指针,第一个指针叫 pre,最初是指向 null 的。 +2. 第二个指针 cur 指向 head,然后不断遍历 cur。 +3. 每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位。 +4. 都迭代完了(cur 变成 null 了),pre 就是最后一个节点了。 + +```java +class Solution { + public ListNode reverseList(ListNode head) { + if (head == null) { + return null; + } + + ListNode pre = null; + ListNode cur = head; + ListNode tmp = null; + while (cur != null) { + tmp = cur.next; + cur.next = pre; + pre = cur; + cur = tmp; + } + + return pre; + } +} +``` + diff --git a/docs/leetcode/hot120/21-merge-two-sorted-lists.md b/docs/leetcode/hot120/21-merge-two-sorted-lists.md new file mode 100644 index 0000000..dd1ffc7 --- /dev/null +++ b/docs/leetcode/hot120/21-merge-two-sorted-lists.md @@ -0,0 +1,41 @@ +# 21. 合并两个有序链表 + +[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/) + +**题目描述** + +将两个升序链表合并为一个新的 **升序** 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 + +**示例** + +```java +输入:l1 = [1,2,4], l2 = [1,3,4] +输出:[1,1,2,3,4,4] +``` + +**参考代码** + +```java +class Solution { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + ListNode ans = new ListNode(0); + ListNode tmp = ans; + + while (l1 != null && l2!= null) { + if (l1.val > l2.val) { + tmp.next = l2; //tmp.next = new ListNode(l2.val); 没必要这么做 + l2 = l2.next; + } else { + tmp.next = l1; + l1 = l1.next; + } + tmp = tmp.next; + } + + tmp.next = l1 == null ? l2 : l1; + + return ans.next; + } +} +``` + diff --git a/docs/leetcode/hot120/215-kth-largest-element-in-an-array.md b/docs/leetcode/hot120/215-kth-largest-element-in-an-array.md new file mode 100644 index 0000000..dd22f4a --- /dev/null +++ b/docs/leetcode/hot120/215-kth-largest-element-in-an-array.md @@ -0,0 +1,94 @@ +# 215. 数组中的第K个最大元素 + +[题目链接](https://leetcode.cn/problems/kth-largest-element-in-an-array/) + +**题目描述** + +给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 + +请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 + +你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 + +**示例** + +```java +输入: [3,2,1,5,6,4], k = 2 +输出: 5 +``` + +**解题思路** + +利用快速排序,每次得到pivot的下标,与(arr.length-1)比较,相等则为所求元素。 + +```java +class Solution { + public int findKthLargest(int[] nums, int k) { + int left = 0; + int right = nums.length - 1; + int index = nums.length - k; + + while (left < right) { + int pivot = partition(nums, left, right); + if (pivot == index) { + return nums[pivot]; + } else if (index > pivot) { + left = pivot + 1; + } else { + right = pivot - 1; + } + } + + return nums[left]; + } + + private int partition(int[] nums, int left, int right) { + int i = left, j = right; + median3(nums, left, right); + int pivot = nums[left]; + + while (i < j) { + while (i < j && nums[j] >= pivot) { + j--; + } + + while (i < j && nums[i] <= pivot) { + i++; + } + + if (i < j) { + swap(nums, i, j); + } else { + break; + } + } + + nums[left] = nums[j]; + nums[j] = pivot; + + return j; + } + + private void median3(int[] nums, int left, int right) { + int mid = (left + right) / 2; + if (nums[left] > nums[mid]) { + swap(nums, left, mid); + } + if (nums[left] > nums[right]) { + swap(nums, left, right); + } + if (nums[mid] > nums[right]) { + swap(nums, mid, right); + } + + swap(nums, left, mid); + } + + private void swap(int[] nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } +} +``` + diff --git a/docs/leetcode/hot120/22-generate-parentheses.md b/docs/leetcode/hot120/22-generate-parentheses.md new file mode 100644 index 0000000..1b8afed --- /dev/null +++ b/docs/leetcode/hot120/22-generate-parentheses.md @@ -0,0 +1,105 @@ +22. # 22. 括号生成 + +[22. 括号生成](https://leetcode.cn/problems/generate-parentheses/) + +**题目描述** + +数字 `n` 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 **有效的** 括号组合。 + +**示例** + +```java +输入:n = 3 +输出:["((()))","(()())","(())()","()(())","()()()"] +``` + +**解题思路** + +深度优先算法。 + +> 作者:liweiwei1419 +> 链接:https://leetcode.cn/problems/generate-parentheses/solution/hui-su-suan-fa-by-liweiwei1419/ +> 来源:力扣(LeetCode) +> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +如果完成一件事情有很多种方法,并且每一种方法分成若干步骤,那多半就可以使用“回溯”算法完成。 + +“回溯”算法的基本思想是“尝试搜索”,一条路如果走不通(不能得到想要的结果),就回到上一个“路口”,尝试走另一条路。 + +因此,“回溯”算法的时间复杂度一般不低。如果能提前分析出,走这一条路并不能得到想要的结果,可以跳过这个分支,这一步操作叫“剪枝”。 + +做“回溯”算法问题的基本套路是: + +1、使用题目中给出的示例,画树形结构图,以便分析出递归结构; + +一般来说,树形图不用画完,就能够分析出递归结构和解题思路。 + +2、分析一个结点可以产生枝叶的条件、递归到哪里终止、是否可以剪枝、符合题意的结果在什么地方出现(可能在叶子结点,也可能在中间的结点); + +3、完成以上两步以后,就要编写代码实现上述分析的过程,使用代码在画出的树形结构上搜索符合题意的结果。 + +在树形结构上搜索结果集,使用的方法是执行一次“深度优先遍历”。在遍历的过程中,可能需要使用“状态变量”。 + +我们以 `n = 2` 为例,画树形结构图。 + +![](http://img.dabin-coder.cn/image/括号生成.jpg) + +画图以后,可以分析出的结论: + +- 左右都有可以使用的括号数量,即严格大于 0 的时候,才产生分支; +- 左边不受右边的限制,它只受自己的约束; +- 右边除了自己的限制以外,还收到左边的限制,即:右边剩余可以使用的括号数量一定得在严格大于左边剩余的数量的时候,才可以“节外生枝”; +- 在左边和右边剩余的括号数都等于 0 的时候结算。 + +参考代码如下: + +```java +import java.util.ArrayList; +import java.util.List; + +public class Solution { + + // 做减法 + + public List generateParenthesis(int n) { + List res = new ArrayList<>(); + // 特判 + if (n == 0) { + return res; + } + + // 执行深度优先遍历,搜索可能的结果 + dfs("", n, n, res); + return res; + } + + /** + * @param curStr 当前递归得到的结果 + * @param left 左括号还有几个可以使用 + * @param right 右括号还有几个可以使用 + * @param res 结果集 + */ + private void dfs(String curStr, int left, int right, List res) { + // 因为每一次尝试,都使用新的字符串变量,所以无需回溯 + // 在递归终止的时候,直接把它添加到结果集即可,注意与「力扣」第 46 题、第 39 题区分 + if (left == 0 && right == 0) { + res.add(curStr); + return; + } + + // 剪枝(如图,左括号可以使用的个数严格大于右括号可以使用的个数,才剪枝,注意这个细节) + if (left > right) { + return; + } + + if (left > 0) { + dfs(curStr + "(", left - 1, right, res); + } + + if (right > 0) { + dfs(curStr + ")", left, right - 1, res); + } + } +} +``` + diff --git a/docs/leetcode/hot120/234-palindrome-linked-list.md b/docs/leetcode/hot120/234-palindrome-linked-list.md new file mode 100644 index 0000000..c14efe2 --- /dev/null +++ b/docs/leetcode/hot120/234-palindrome-linked-list.md @@ -0,0 +1,56 @@ +# 234. 回文链表 + +[234. 回文链表](https://leetcode.cn/problems/palindrome-linked-list/) + +**题目描述** + +给你一个单链表的头节点 `head` ,请你判断该链表是否为回文链表。如果是,返回 `true` ;否则,返回 `false` 。 + +**示例** + +```java +给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 +``` + +**解题思路** + +快慢指针。 + +快指针走到末尾,慢指针刚好到中间。其中慢指针将前半部分反转。然后比较。 + +**参考代码**: + +```java + public boolean isPalindrome(ListNode head) { + if(head == null || head.next == null) { + return true; + } + ListNode slow = head, fast = head; + ListNode pre = head, prepre = null; + while(fast != null && fast.next != null) { + pre = slow; + slow = slow.next; + fast = fast.next.next; + pre.next = prepre; + prepre = pre; + } + if(fast != null) { + slow = slow.next; + } + while(pre != null && slow != null) { + if(pre.val != slow.val) { + return false; + } + pre = pre.next; + slow = slow.next; + } + return true; + } + +作者:nuan +链接:https://leetcode.cn/problems/palindrome-linked-list/solution/wo-de-kuai-man-zhi-zhen-du-cong-tou-kai-shi-gan-ju/ +来源:力扣(LeetCode) +著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 +``` + + diff --git a/docs/leetcode/hot120/236-lowest-common-ancestor-of-a-binary-tree.md b/docs/leetcode/hot120/236-lowest-common-ancestor-of-a-binary-tree.md new file mode 100644 index 0000000..4c6463a --- /dev/null +++ b/docs/leetcode/hot120/236-lowest-common-ancestor-of-a-binary-tree.md @@ -0,0 +1,41 @@ +# 236. 二叉树的最近公共祖先 + +[题目链接](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/) + +**题目描述** + +给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 + +百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。 + +**示例** + +```java +输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +输出:3 +解释:节点 5 和节点 1 的最近公共祖先是节点 3 。 +``` + +**解题思路** + +[后序遍历](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/) + +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || root == p || root == q) { + return root; + } + + TreeNode left = lowestCommonAncestor(root.left, p, q); + TreeNode right = lowestCommonAncestor(root.right, p, q); + + if (left != null && right != null) { + return root; + } else { + return left == null ? right : left; + } + } +} +``` + diff --git a/docs/leetcode/hot120/24-swap-nodes-in-pairs.md b/docs/leetcode/hot120/24-swap-nodes-in-pairs.md new file mode 100644 index 0000000..7cf73f9 --- /dev/null +++ b/docs/leetcode/hot120/24-swap-nodes-in-pairs.md @@ -0,0 +1,42 @@ +# 24. 两两交换链表中的节点 + +[两两交换链表中的节点](https://leetcode.cn/problems/swap-nodes-in-pairs/) + +**题目描述** + +给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 + +![](http://img.dabin-coder.cn/image/swap_ex1.jpg) + +**示例** + +```java +输入:head = [1,2,3,4] +输出:[2,1,4,3] +``` + +**解题思路** + +使用递归实现。 + +```java +class Solution { + public ListNode swapPairs(ListNode head) { + if (head == null) { + return head; + } + ListNode left = head; + ListNode right = head.next; + + if (right == null) { + right = left; + } else { + left.next = swapPairs(right.next); + right.next = left; + } + + return right; + } +} +``` + diff --git a/docs/leetcode/hot120/26-remove-duplicates-from-sorted-array.md b/docs/leetcode/hot120/26-remove-duplicates-from-sorted-array.md new file mode 100644 index 0000000..9c53f38 --- /dev/null +++ b/docs/leetcode/hot120/26-remove-duplicates-from-sorted-array.md @@ -0,0 +1,56 @@ +# 26. 删除有序数组中的重复项 + +[题目链接](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/) + +**题目描述** + +给你一个 **升序排列** 的数组 `nums` ,请你**[ 原地](http://baike.baidu.com/item/原地算法)** 删除重复出现的元素,使每个元素 **只出现一次** ,返回删除后数组的新长度。元素的 **相对顺序** 应该保持 **一致** 。 + +由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 `k` 个元素,那么 `nums` 的前 `k` 个元素应该保存最终结果。 + +将最终结果插入 `nums` 的前 `k` 个位置后返回 `k` 。 + +不要使用额外的空间,你必须在 **[原地 ](https://baike.baidu.com/item/原地算法)修改输入数组** 并在使用 O(1) 额外空间的条件下完成。 + +**示例**: + +```java +输入:nums = [1,1,2] +输出:2, nums = [1,2,_] +解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 +``` + +**参考代码** + +```java +class Solution { + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int left = 0; + int right = 1; + int count = 1; + + while (right < nums.length) { + if (nums[right] == nums[left]) { + if (count < 2) { + nums[++left] = nums[right++]; + } else { + right++; + } + count++; + } else { + count = 1; + nums[++left] = nums[right++]; + } + } + return left + 1; + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/27-remove-element.md b/docs/leetcode/hot120/27-remove-element.md new file mode 100644 index 0000000..285d5e0 --- /dev/null +++ b/docs/leetcode/hot120/27-remove-element.md @@ -0,0 +1,44 @@ +# 27. 移除元素 + +[移除元素](https://leetcode.cn/problems/remove-element/) + +**题目描述** + +给你一个数组 `nums` 和一个值 `val`,你需要 **[原地](https://baike.baidu.com/item/原地算法)** 移除所有数值等于 `val` 的元素,并返回移除后数组的新长度。 + +不要使用额外的数组空间,你必须仅使用 `O(1)` 额外空间并 **[原地 ](https://baike.baidu.com/item/原地算法)修改输入数组**。 + +元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 + +**示例** + +```java +输入:nums = [3,2,2,3], val = 3 +输出:2, nums = [2,2] +解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 +``` + +**解题思路** + +![](http://img.dabin-coder.cn/image/image-20221106172125452.png) + +> 作者:画手大鹏 +> 链接:https://leetcode.cn/problems/remove-element/solutions/10388/hua-jie-suan-fa-27-yi-chu-yuan-su-by-guanpengchn/ +> 来源:力扣(LeetCode) +> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +```java +class Solution { + public int removeElement(int[] nums, int val) { + int ans = 0; + for(int num: nums) { + if(num != val) { + nums[ans] = num; + ans++; + } + } + return ans; + } +} +``` + diff --git a/docs/leetcode/hot120/28-mirror-binary-tree.md b/docs/leetcode/hot120/28-mirror-binary-tree.md new file mode 100644 index 0000000..b1b1128 --- /dev/null +++ b/docs/leetcode/hot120/28-mirror-binary-tree.md @@ -0,0 +1,44 @@ +# 28. 对称的二叉树 + +[28. 对称的二叉树](https://leetcode.cn/problems/dui-cheng-de-er-cha-shu-lcof/) + +**题目描述** + +请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。 + +例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 + +**示例** + +```java +输入:root = [1,2,2,3,4,4,3] +输出:true +``` + +**解题思路** + +从顶至底递归,判断每对节点是否对称,从而判断树是否为对称二叉树。 + +```java +class Solution { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + return isMirror(root.left, root.right); + } + + public boolean isMirror(TreeNode node1, TreeNode node2) { + if (node1 == null && node2 == null) { + return true; + } + + if (node1 == null || node2 == null || node1.val != node2.val) { + return false; + } + + return isMirror(node1.left, node2.right) && isMirror(node1.right, node2.left); + } +} +``` + diff --git a/docs/leetcode/hot120/29-divide-two-integers.md b/docs/leetcode/hot120/29-divide-two-integers.md new file mode 100644 index 0000000..2f08002 --- /dev/null +++ b/docs/leetcode/hot120/29-divide-two-integers.md @@ -0,0 +1,65 @@ +# 29. 两数相除 + +[29. 两数相除](https://leetcode.cn/problems/divide-two-integers/) + +**题目描述** + +给定两个整数,被除数 `dividend` 和除数 `divisor`。将两数相除,要求不使用乘法、除法和 mod 运算符。 + +返回被除数 `dividend` 除以除数 `divisor` 得到的商。 + +整数除法的结果应当截去(`truncate`)其小数部分,例如:`truncate(8.345) = 8` 以及 `truncate(-2.7335) = -2` + +**示例** + +```java +输入: dividend = 10, divisor = 3 +输出: 3 +解释: 10/3 = truncate(3.33333..) = truncate(3) = 3 +``` + +**解题思路** + +Integer.MIN_VALUE 转为正数会溢出,故将 dividend 和 divisor 都转化为负数。**两个负数相加溢出会大于0**。 + +```java +class Solution { + //dividend / divisor + public int divide(int dividend, int divisor) { + if (dividend == Integer.MIN_VALUE && divisor == -1) { + return Integer.MAX_VALUE; + } + if (divisor == 1) { //不加上会超时 + return dividend; + } + int sign = 1; + if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) { + sign = -1; + } + int a = dividend > 0 ? -dividend : dividend; + int b = divisor > 0 ? -divisor : divisor; + if (a > b) { + return 0; + } + int ans = divideHelper(a, b); + + return sign > 0 ? ans : -ans; + } + + private int divideHelper(int a, int b) { + if (a > b) { + return 0; + } + + int count = 1; + int tmp = b; + while (tmp + tmp >= a && tmp + tmp < 0) { //两个负数相加溢出会大于0 + tmp += tmp; + count += count; + } + + return count + divideHelper(a - tmp, b); + } +} +``` + diff --git a/docs/leetcode/hot120/3-longest-substring-without-repeating-characters.md b/docs/leetcode/hot120/3-longest-substring-without-repeating-characters.md new file mode 100644 index 0000000..53b36f7 --- /dev/null +++ b/docs/leetcode/hot120/3-longest-substring-without-repeating-characters.md @@ -0,0 +1,59 @@ +# 3 . 无重复字符的最长子串 + +[题目链接](https://leetcode.cn/problems/longest-substring-without-repeating-characters/) + +**题目描述** + +给定一个字符串 `s` ,请你找出其中不含有重复字符的 **最长子串** 的长度。 + +**示例** + +``` +输入: s = "abcabcbb" +输出: 3 +解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 +``` + +**解题思路** + +这道题主要用到思路是:滑动窗口 + +**什么是滑动窗口**? + +其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列! + +**如何移动**? + +我们只要把队列的左边的元素移出就行了,直到满足题目要求! + +一直维持这样的队列,找出队列出现最长的长度时候,求出解! + +时间复杂度:O(n) + +**代码实现** + +```java +class Solution { + public int lengthOfLongestSubstring(String s) { + if (s.length()==0) return 0; + HashMap map = new HashMap(); + int max = 0; + int left = 0; + for(int i = 0; i < s.length(); i ++){ + if(map.containsKey(s.charAt(i))){ + left = Math.max(left,map.get(s.charAt(i)) + 1); + } + map.put(s.charAt(i),i); + max = Math.max(max,i-left+1); + } + return max; + + } +} +``` + + + +> 作者:powcai +> 链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/ +> 来源:力扣(LeetCode) \ No newline at end of file diff --git a/docs/leetcode/hot120/31-next-permutation.md b/docs/leetcode/hot120/31-next-permutation.md new file mode 100644 index 0000000..6cef380 --- /dev/null +++ b/docs/leetcode/hot120/31-next-permutation.md @@ -0,0 +1,53 @@ +# 31. 下一个排列 + +[31. 下一个排列](https://leetcode.cn/problems/next-permutation/) + +**题目描述** + +整数数组的一个 **排列** 就是将其所有成员以序列或线性顺序排列。 + +- 例如,`arr = [1,2,3]` ,以下这些都可以视作 `arr` 的排列:`[1,2,3]`、`[1,3,2]`、`[3,1,2]`、`[2,3,1]` 。 + +整数数组的 **下一个排列** 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 **下一个排列** 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。 + +- 例如,`arr = [1,2,3]` 的下一个排列是 `[1,3,2]` 。 +- 类似地,`arr = [2,3,1]` 的下一个排列是 `[3,1,2]` 。 +- 而 `arr = [3,2,1]` 的下一个排列是 `[1,2,3]` ,因为 `[3,2,1]` 不存在一个字典序更大的排列。 + +给你一个整数数组 `nums` ,找出 `nums` 的下一个排列。 + +必须**[ 原地 ](https://baike.baidu.com/item/原地算法)**修改,只允许使用额外常数空间。 + +**示例** + +```java +输入:nums = [1,2,3] +输出:[1,3,2] +``` + +**参考代码** + +```java +class Solution { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + ListNode ans = new ListNode(0); + ListNode tmp = ans; + + while (l1 != null && l2!= null) { + if (l1.val > l2.val) { + tmp.next = l2; //tmp.next = new ListNode(l2.val); 没必要这么做 + l2 = l2.next; + } else { + tmp.next = l1; + l1 = l1.next; + } + tmp = tmp.next; + } + + tmp.next = l1 == null ? l2 : l1; + + return ans.next; + } +} +``` + diff --git a/docs/leetcode/hot120/34-find-first-and-last-position-of-element-in-sorted-array.md b/docs/leetcode/hot120/34-find-first-and-last-position-of-element-in-sorted-array.md new file mode 100644 index 0000000..cebdf3e --- /dev/null +++ b/docs/leetcode/hot120/34-find-first-and-last-position-of-element-in-sorted-array.md @@ -0,0 +1,56 @@ +# 34. 在排序数组中查找元素的第一个和最后一个位置 + +[34. 在排序数组中查找元素的第一个和最后一个位置](https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/) + +**题目描述** + +给你一个按照非递减顺序排列的整数数组 `nums`,和一个目标值 `target`。请你找出给定目标值在数组中的开始位置和结束位置。 + +如果数组中不存在目标值 `target`,返回 `[-1, -1]`。 + +你必须设计并实现时间复杂度为 `O(log n)` 的算法解决此问题。 + +**示例** + +```java +输入:nums = [5,7,7,8,8,10], target = 8 +输出:[3,4] +``` + +**参考代码** + +```java +//输入: nums = [5,7,7,8,8,10], target = 8 +//输出: [3,4] + +class Solution { + public int[] searchRange(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return new int[]{-1, -1}; + } + int left = searchRangeHelper(nums, target); + int right = searchRangeHelper(nums, target + 1);//复用代码 + + if (left == nums.length || nums[left] != target) {//left==nums.length数组元素比target小 + return new int[]{-1, -1}; + } + return new int[]{left, right - 1}; + } + + private int searchRangeHelper(int[] nums, int target) { + int left = 0; + int right = nums.length;//特殊情况[1] 1 + while (left < right) { + int mid = (left + right) >> 1; + if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +} +``` + diff --git a/docs/leetcode/hot120/36-valid-sudoku.md b/docs/leetcode/hot120/36-valid-sudoku.md new file mode 100644 index 0000000..dde67a8 --- /dev/null +++ b/docs/leetcode/hot120/36-valid-sudoku.md @@ -0,0 +1,75 @@ +# 36. 有效的数独 + +[36. 有效的数独](https://leetcode.cn/problems/valid-sudoku/) + +**题目描述** + +请你判断一个 `9 x 9` 的数独是否有效。只需要 **根据以下规则** ,验证已经填入的数字是否有效即可。 + +1. 数字 `1-9` 在每一行只能出现一次。 +2. 数字 `1-9` 在每一列只能出现一次。 +3. 数字 `1-9` 在每一个以粗实线分隔的 `3x3` 宫内只能出现一次。(请参考示例图) + +**注意:** + +- 一个有效的数独(部分已被填充)不一定是可解的。 +- 只需要根据以上规则,验证已经填入的数字是否有效即可。 +- 空白格用 `'.'` 表示。 + +**示例** + +![](http://img.dabin-coder.cn/image/sudoku.png) + +```java +输入:board = +[["5","3",".",".","7",".",".",".","."] +,["6",".",".","1","9","5",".",".","."] +,[".","9","8",".",".",".",".","6","."] +,["8",".",".",".","6",".",".",".","3"] +,["4",".",".","8",".","3",".",".","1"] +,["7",".",".",".","2",".",".",".","6"] +,[".","6",".",".",".",".","2","8","."] +,[".",".",".","4","1","9",".",".","5"] +,[".",".",".",".","8",".",".","7","9"]] +输出:true +``` + +**解题思路** + +关键在于找到子数独的规律:`box_index = (row / 3) * 3 + columns / 3` + +![图片来源于网络,出处不详](http://img.topjavaer.cn/image/1587260486363.png) + +```java +class Solution { + public boolean isValidSudoku(char[][] board) { + int[][] row = new int[9][9]; //二维数组初始化 + int[][] column = new int[9][9]; + int[][] box = new int[9][9]; + + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + if (board[i][j] == '.') { + continue; + } + int num = board[i][j] - '1';//数字1-9对应下标0-8 + int boxIndex = (i/3)*3 + j/3; + + if (row[i][num] > 0 || column[j][num] > 0 || box[boxIndex][num] > 0) { + return false; + } + + row[i][num] = 1; + column[j][num] = 1; + box[boxIndex][num] = 1; + + } + } + + return true; + } +} +``` + + + diff --git a/docs/leetcode/hot120/40-combination-sum-ii.md b/docs/leetcode/hot120/40-combination-sum-ii.md new file mode 100644 index 0000000..c4681cd --- /dev/null +++ b/docs/leetcode/hot120/40-combination-sum-ii.md @@ -0,0 +1,68 @@ +# 40. 组合总和 II + +[40. 组合总和 II](https://leetcode.cn/problems/combination-sum-ii/) + +**题目描述** + +给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 + +candidates 中的每个数字在每个组合中只能使用 一次 。 + +注意:解集不能包含重复的组合。 + +**示例**: + +``` +输入: candidates = [2,5,2,1,2], target = 5, +输出: +[ +[1,2,2], +[5] +] +``` + +**解题思路** + +数组元素可能重复。使用回溯算法。 + +剪枝: + +![](http://img.dabin-coder.cn/image/1587051935261.png) + +去重复组合: + +![](http://img.dabin-coder.cn/image/1587050948930.png) + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> combinationSum2(int[] candidates, int target) { + if (candidates == null || candidates.length == 0) { + return ans; + } + Arrays.sort(candidates);//排序方便回溯剪枝 + Deque path = new ArrayDeque<>();//作为栈来使用,效率高于Stack;也可以作为队列来使用,效率高于LinkedList;线程不安全 + combinationSum2Helper(candidates, target, 0, path); + return ans; + } + + public void combinationSum2Helper(int[] arr, int target, int start, Deque path) { + if (target == 0) { + ans.add(new ArrayList(path)); + } + + for (int i = start; i < arr.length; i++) { + if (target < arr[i]) {//剪枝 + return; + } + if (i > start && arr[i] == arr[i - 1]) {//在一个层级,会产生重复 + continue; + } + path.addLast(arr[i]); + combinationSum2Helper(arr, target - arr[i], i + 1, path); + path.removeLast(); + } + } +} +``` + diff --git a/docs/leetcode/hot120/415-add-strings.md b/docs/leetcode/hot120/415-add-strings.md new file mode 100644 index 0000000..ccd374f --- /dev/null +++ b/docs/leetcode/hot120/415-add-strings.md @@ -0,0 +1,48 @@ +# 415. 字符串相加 + +[415. 字符串相加](https://leetcode.cn/problems/add-strings/) + +**题目描述** + +给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。 + +你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。 + +**示例** + +```java +输入:num1 = "11", num2 = "123" +输出:"134" +``` + +**解题思路** + +![image-20221029095055775](http://img.dabin-coder.cn/image/image-20221029095055775.png) + +**参考代码**: + +```java +class Solution { + public String addStrings(String num1, String num2) { + StringBuilder res = new StringBuilder(""); + int i = num1.length() - 1, j = num2.length() - 1, carry = 0; + while(i >= 0 || j >= 0){ + int n1 = i >= 0 ? num1.charAt(i) - '0' : 0; + int n2 = j >= 0 ? num2.charAt(j) - '0' : 0; + int tmp = n1 + n2 + carry; + carry = tmp / 10; + res.append(tmp % 10); + i--; j--; + } + if(carry == 1) res.append(1); + return res.reverse().toString(); + } +} + +作者:jyd +链接:https://leetcode.cn/problems/add-strings/solution/add-strings-shuang-zhi-zhen-fa-by-jyd/ +来源:力扣(LeetCode) +著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 +``` + + diff --git a/docs/leetcode/hot120/43-multiply-strings.md b/docs/leetcode/hot120/43-multiply-strings.md new file mode 100644 index 0000000..22e1e05 --- /dev/null +++ b/docs/leetcode/hot120/43-multiply-strings.md @@ -0,0 +1,53 @@ +# 43. 字符串相乘 + +[43. 字符串相乘](https://leetcode.cn/problems/multiply-strings/) + +**题目描述** + +给定两个以字符串形式表示的非负整数 `num1` 和 `num2`,返回 `num1` 和 `num2` 的乘积,它们的乘积也表示为字符串形式。 + +**注意:**不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 + +**示例** + +```java +输入: num1 = "2", num2 = "3" +输出: "6" +``` + +**解题思路** + +参考自:https://leetcode-cn.com/problems/multiply-strings/solution/you-hua-ban-shu-shi-da-bai-994-by-breezean/ + +![](http://img.dabin-coder.cn/image/1587226241610.png) + +```java +class Solution { + public String multiply(String num1, String num2) { + if (num1.equals("0") || num2.equals("0")) { //乘0 + return "0"; + } + int[] arr = new int[num1.length() + num2.length()]; + for (int i = num1.length() - 1; i >= 0; i--) { + int m = num1.charAt(i) - '0'; + for (int j = num2.length() - 1; j >= 0; j--) { + int n = num2.charAt(j) - '0'; + int sum = arr[i + j + 1] + m * n; + arr[i + j + 1] = sum % 10; + arr[i + j] += sum / 10; //+=,不能忘了原先的数 + } + } + + StringBuilder ans = new StringBuilder(""); + if (arr[0] != 0) { + ans.append(arr[0]); + } + for (int i = 1; i < arr.length; i++) { + ans.append(arr[i]); + } + + return ans.toString(); + } +} +``` + diff --git a/docs/leetcode/hot120/46-permutations.md b/docs/leetcode/hot120/46-permutations.md new file mode 100644 index 0000000..0186dd7 --- /dev/null +++ b/docs/leetcode/hot120/46-permutations.md @@ -0,0 +1,49 @@ +# 46. 全排列 + +[题目链接](https://leetcode.cn/problems/permutations/) + +**题目描述** + +给定一个不含重复数字的数组 `nums` ,返回其 *所有可能的全排列* 。你可以 **按任意顺序** 返回答案。 + +示例: + +``` +输入:nums = [1,2,3] +输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] +``` + +**解题思路** + +使用回溯。注意与组合总和的区别(数字有无顺序)。 + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> permute(int[] nums) { + boolean[] flag = new boolean[nums.length]; + ArrayDeque path = new ArrayDeque<>(); + permuteHelper(nums, flag, path); + + return ans; + } + + private void permuteHelper(int[] nums, boolean[] flag, ArrayDeque path) { + if (path.size() == nums.length) { + ans.add(new ArrayList<>(path)); + return; + } + for (int i = 0; i < nums.length; i++) { + if (flag[i]) { + continue;//继续循环 + } + path.addLast(nums[i]); + flag[i] = true; + permuteHelper(nums, flag, path); + path.removeLast(); + flag[i] = false; + } + } +} +``` + diff --git a/docs/leetcode/hot120/47-permutations-ii.md b/docs/leetcode/hot120/47-permutations-ii.md new file mode 100644 index 0000000..542356c --- /dev/null +++ b/docs/leetcode/hot120/47-permutations-ii.md @@ -0,0 +1,63 @@ +# 47. 全排列 II + +[题目链接](https://leetcode.cn/problems/permutations-ii/) + +**题目描述** + +给定一个可包含重复数字的序列,返回所有不重复的全排列。注意与组合总和的区别。 + +示例: + +```java +输入:nums = [1,2,3] +输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] +``` + +**解题思路** + +1、排序; + +2、同一层级相同元素剪枝。 + +> 参考自:https://leetcode-cn.com/problems/permutations-ii/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liwe-2/ + +![](http://img.dabin-coder.cn/image/permutations-ii.png) + +```java +class Solution { + private List> ans = new ArrayList<>(); + public List> permuteUnique(int[] nums) { + if (nums == null || nums.length == 0) { + return ans; + } + ArrayDeque path = new ArrayDeque<>(); + boolean[] used = new boolean[nums.length]; + Arrays.sort(nums);//切记 + dps(nums, used, path); + + return ans; + } + + private void dps(int[] nums, boolean[] used, ArrayDeque path) { + if (path.size() == nums.length) { + ans.add(new ArrayList<>(path)); + return; + } + for (int i = 0; i < nums.length; i++) { + if (used[i]) { + continue; + } + if ((i > 0 && nums[i] == nums[i - 1]) && !used[i - 1]) {//同一层相同的元素,剪枝 + continue;//继续循环,不是return退出循环 + } + path.addLast(nums[i]); + used[i] = true; + dps(nums, used, path); + path.removeLast(); + used[i] = false; + } + } +} +``` + + diff --git a/docs/leetcode/hot120/48-rotate-image.md b/docs/leetcode/hot120/48-rotate-image.md new file mode 100644 index 0000000..1829e75 --- /dev/null +++ b/docs/leetcode/hot120/48-rotate-image.md @@ -0,0 +1,49 @@ +# 48. 旋转图像 + +[48. 旋转图像](https://leetcode.cn/problems/rotate-image/) + +**题目描述** + +给定一个 *n* × *n* 的二维矩阵 `matrix` 表示一个图像。请你将图像顺时针旋转 90 度。 + +你必须在**[ 原地](https://baike.baidu.com/item/原地算法)** 旋转图像,这意味着你需要直接修改输入的二维矩阵。**请不要** 使用另一个矩阵来旋转图像。 + +**示例** + +![](http://img.dabin-coder.cn/image/mat1.jpg) + +```java +输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] +输出:[[7,4,1],[8,5,2],[9,6,3]] +``` + +**解题思路** + +先转置,然后翻转每一行。 + +```java +class Solution { + public void rotate(int[][] matrix) { + if (matrix == null || matrix.length <= 1) { + return; + } + //转置 + for (int i = 0; i < matrix.length; i++) { + for (int j = i + 1; j < matrix.length; j++) { + int tmp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = tmp; + } + } + //翻转每一行 + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix.length / 2; j++) { + int tmp = matrix[i][j]; + matrix[i][j] = matrix[i][matrix.length - j - 1]; + matrix[i][matrix.length - j - 1] = tmp; + } + } + } +} +``` + diff --git a/docs/leetcode/hot120/49-group-anagrams.md b/docs/leetcode/hot120/49-group-anagrams.md new file mode 100644 index 0000000..13ac24b --- /dev/null +++ b/docs/leetcode/hot120/49-group-anagrams.md @@ -0,0 +1,44 @@ +# 49. 字母异位词分组 + +[49. 字母异位词分组](https://leetcode.cn/problems/group-anagrams/description/) + +**题目描述** + +给你一个字符串数组,请你将 **字母异位词** 组合在一起。可以按任意顺序返回结果列表。 + +**字母异位词** 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。 + +**示例** + +```java +输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"] +输出: [["bat"],["nat","tan"],["ate","eat","tea"]] +``` + +**解题思路** + +由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。 + +```java +class Solution { + public List> groupAnagrams(String[] strs) { + if (strs == null || strs.length == 0) { + return new ArrayList(); + } + + Map ans = new HashMap<>(); + for (String s : strs) { + char[] arr = s.toCharArray(); + Arrays.sort(arr); + String key = String.valueOf(arr); + if (!ans.containsKey(key)) { + ans.put(key, new ArrayList()); + } + ans.get(key).add(s); + } + + return new ArrayList(ans.values());//没有<> + } +} +``` + diff --git a/docs/leetcode/hot120/5-longest-palindromic-substring.md b/docs/leetcode/hot120/5-longest-palindromic-substring.md new file mode 100644 index 0000000..7921703 --- /dev/null +++ b/docs/leetcode/hot120/5-longest-palindromic-substring.md @@ -0,0 +1,68 @@ +# 5. 最长回文子串 + +[原题链接](https://leetcode.cn/problems/longest-palindromic-substring/) + +## 题目描述 + +从给定的字符串 `s` 中找到最长的回文子串的长度。 + +例如 `s = "babbad"` 的最长回文子串是 `"abba"` ,长度是 `4` 。 + +## 解题思路 + +1. 定义状态。`dp[i][j]` 表示子串 `s[i..j]` 是否为回文子串 + +2. 状态转移方程:`dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]` +3. 初始化的时候,单个字符一定是回文串,因此把对角线先初始化为 `true`,即 `dp[i][i] = true` 。 +4. 只要一得到 `dp[i][j] = true`,就记录子串的长度和起始位置 + +注意事项:总是先得到小子串的回文判定,然后大子串才能参考小子串的判断结果,即填表顺序很重要。 + +![](http://img.dabin-coder.cn/image/image-20201115230411764.png) + +时间复杂度O(N2),空间复杂度O(N2),因为使用了二维数组。 + +```java +public class Solution { + + public String longestPalindrome(String s) { + // 特判 + int len = s.length(); + if (len < 2) { + return s; + } + + int maxLen = 1; + int begin = 0; + + // dp[i][j] 表示 s[i, j] 是否是回文串 + boolean[][] dp = new boolean[len][len]; + char[] charArray = s.toCharArray(); + + for (int i = 0; i < len; i++) { + dp[i][i] = true; + } + for (int j = 1; j < len; j++) { + for (int i = 0; i < j; i++) { + if (charArray[i] != charArray[j]) { + dp[i][j] = false; + } else { + if (j - i < 3) { + dp[i][j] = true; + } else { + dp[i][j] = dp[i + 1][j - 1]; + } + } + + // 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置 + if (dp[i][j] && j - i + 1 > maxLen) { + maxLen = j - i + 1; + begin = i; + } + } + } + return s.substring(begin, begin + maxLen); //substring(i, j)截取i到j(不包含j)的字符串 + } +} +``` + diff --git a/docs/leetcode/hot120/50-powx-n.md b/docs/leetcode/hot120/50-powx-n.md new file mode 100644 index 0000000..84e0d92 --- /dev/null +++ b/docs/leetcode/hot120/50-powx-n.md @@ -0,0 +1,41 @@ +# 50. Pow(x, n) + +[50. Pow(x, n)](https://leetcode.cn/problems/powx-n/) + +**题目描述** + +实现 pow(*x*, *n*) ,即计算 `x` 的整数 `n` 次幂函数(即,`x^n` )。 + +**示例** + +```java +输入:x = 2.00000, n = 10 +输出:1024.00000 +``` + +**解题思路** + +快速幂算法。 + +```java +class Solution { + public double myPow(double x, int n) { + if (n == 0) { + return 1.0; + } + if (n == -1) {//负数边界 + return 1 / x; + } + double res = myPow(x, n / 2); + double ans = 0; + if (n % 2 == 0) { + ans = res * res; + } else { + ans = n > 0 ? res * res * x : res * res / x; + } + + return ans; + } +} +``` + diff --git a/docs/leetcode/hot120/53-maximum-subarray.md b/docs/leetcode/hot120/53-maximum-subarray.md new file mode 100644 index 0000000..4fc330f --- /dev/null +++ b/docs/leetcode/hot120/53-maximum-subarray.md @@ -0,0 +1,37 @@ +# 53. 最大子数组和 + +[原题链接](https://leetcode.cn/problems/maximum-subarray/) + +## 题目描述 + +给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 + +子数组 是数组中的一个连续部分。 + + ```java +示例 1: + +输入:nums = [-2,1,-3,4,-1,2,1,-5,4] +输出:6 +解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。 + ``` + +## 解题 + +```java +class Solution { + public int maxSubArray(int[] nums) { + int res = nums[0]; + int sum = 0; + for (int num : nums) { + if (sum > 0) + sum += num; + else + sum = num; + res = Math.max(res, sum); + } + return res; + } +} +``` + diff --git a/docs/leetcode/hot120/54-spiral-matrix.md b/docs/leetcode/hot120/54-spiral-matrix.md new file mode 100644 index 0000000..d495d3c --- /dev/null +++ b/docs/leetcode/hot120/54-spiral-matrix.md @@ -0,0 +1,71 @@ +# 54. 螺旋矩阵 + +[54. 螺旋矩阵](https://leetcode.cn/problems/spiral-matrix/) + +**题目描述** + +给你一个 `m` 行 `n` 列的矩阵 `matrix` ,请按照 **顺时针螺旋顺序** ,返回矩阵中的所有元素。 + +**示例** + +```java +输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] +输出:[1,2,3,6,9,8,7,4,5] +``` + +**解题思路** + +- 首先设定上下左右边界 +- 其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界 +- 判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案 +- 若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理 +- 不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案 + +> 作者:YouLookDeliciousC +> 链接:https://leetcode.cn/problems/spiral-matrix/solutions/7155/cxiang-xi-ti-jie-by-youlookdeliciousc-3/ +> 来源:力扣(LeetCode) +> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +```java +class Solution { + public List spiralOrder(int[][] matrix) { + List ans = new ArrayList<>(); + if (matrix == null || matrix.length == 0) { + return ans; + } + int top = 0; + int bottom = matrix.length - 1; + int left = 0; + int right = matrix[0].length - 1; + while (true) { + for (int i = left; i <= right; i++) { + ans.add(matrix[top][i]); + } + if (++top > bottom) { + break; + } + for (int j = top; j <= bottom; j++) { + ans.add(matrix[j][right]); + } + if (--right < left) { + break; + } + for (int m = right; m >= left; m--) { + ans.add(matrix[bottom][m]); + } + if (--bottom < top) { + break; + } + for (int n = bottom; n >= top; n--) { + ans.add(matrix[n][left]); + } + if (++left > right) { + break; + } + } + + return ans; + } +} +``` + diff --git a/docs/leetcode/hot120/543-diameter-of-binary-tree.md b/docs/leetcode/hot120/543-diameter-of-binary-tree.md new file mode 100644 index 0000000..32ecbaf --- /dev/null +++ b/docs/leetcode/hot120/543-diameter-of-binary-tree.md @@ -0,0 +1,47 @@ +# 543. 二叉树的直径 + +[题目链接](https://leetcode.cn/problems/diameter-of-binary-tree/) + +**题目描述** + +给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。 + +**示例** + +```java + 1 + / \ + 2 3 + / \ + 4 5 + +返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。 +``` + +**解题思路** + +**深度优先搜索** + +```java +class Solution { + private int max = 0; + + public int diameterOfBinaryTree(TreeNode root) { + depth(root); + return max; + } + + private int depth(TreeNode node) { + if (node == null) { + return 0; + } + + int left = depth(node.left); + int right = depth(node.right); + + max = Math.max(max, left + right); + return Math.max(left, right) + 1; + } +} +``` + diff --git a/docs/leetcode/hot120/55-jump-game.md b/docs/leetcode/hot120/55-jump-game.md new file mode 100644 index 0000000..d060cc9 --- /dev/null +++ b/docs/leetcode/hot120/55-jump-game.md @@ -0,0 +1,47 @@ +# 55. 跳跃游戏 + +[题目链接](https://leetcode.cn/problems/jump-game/) + +**题目描述** + +给定一个非负整数数组 `nums` ,你最初位于数组的 **第一个下标** 。 + +数组中的每个元素代表你在该位置可以跳跃的最大长度。 + +判断你是否能够到达最后一个下标。 + +**示例**: + +```java +输入:nums = [2,3,1,1,4] +输出:true +解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。 +``` + +**解题思路**: + +1. 如果某一个作为 起跳点 的格子可以跳跃的距离是 3,那么表示后面 3 个格子都可以作为 起跳点 +2. 可以对每一个能作为 起跳点 的格子都尝试跳一次,把 能跳到最远的距离 不断更新 +3. 如果可以一直跳到最后,就成功了 + +```java +class Solution { + public boolean canJump(int[] nums) { + if (nums == null || nums.length == 0) { + return true; + } + + int maxIndex = nums[0]; + for (int i = 1; i < nums.length; i++) { + if (maxIndex >= i) { + maxIndex = Math.max(maxIndex, i + nums[i]); + } else { + return false; + } + } + + return true; + } +} +``` + diff --git a/docs/leetcode/hot120/56-merge-intervals.md b/docs/leetcode/hot120/56-merge-intervals.md new file mode 100644 index 0000000..e9c6892 --- /dev/null +++ b/docs/leetcode/hot120/56-merge-intervals.md @@ -0,0 +1,43 @@ +# 56. 合并区间 + +[56. 合并区间](https://leetcode.cn/problems/merge-intervals/) + +**题目描述** + +以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 + +**示例** + +```java +输入:intervals = [[1,3],[2,6],[8,10],[15,18]] +输出:[[1,6],[8,10],[15,18]] +解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. +``` + +**解题思路** + +先对区间左边界排序 `Array.sort(arr, (i1, i2) -> i1[0] - i2[0])`,然后新建数组进行合并。 + +```java +class Solution { + public int[][] merge(int[][] intervals) { + if (intervals == null || intervals.length == 0) { + throw new IllegalArgumentException("array is null or array is empty"); + } + + Arrays.sort(intervals, (a, b) -> a[0] - b[0]); //lambda表达式写法,返回值是int + + int index = 0; + for (int i = 1; i < intervals.length; i++) { + if (intervals[index][1] < intervals[i][0]) { + intervals[++index] = intervals[i]; //++index,先自增,再取值 + } else { + intervals[index][1] = Math.max(intervals[i][1], intervals[index][1]); + } + } + + return Arrays.copyOf(intervals, index + 1); //第二个参数是数组长度 + } +} +``` + diff --git a/docs/leetcode/hot120/59-spiral-matrix-ii.md b/docs/leetcode/hot120/59-spiral-matrix-ii.md new file mode 100644 index 0000000..245bf86 --- /dev/null +++ b/docs/leetcode/hot120/59-spiral-matrix-ii.md @@ -0,0 +1,60 @@ +# 59. 螺旋矩阵II + +[题目链接](https://leetcode.cn/problems/spiral-matrix-ii/) + +**题目描述** + +给你一个正整数 `n` ,生成一个包含 `1` 到 `n2` 所有元素,且元素按顺时针顺序螺旋排列的 `n x n` 正方形矩阵 `matrix` 。 + +**示例** + +```java +输入:n = 3 +输出:[[1,2,3],[8,9,4],[7,6,5]] +``` + +**解题思路** + +tips:定义上下左右边界。 + +```java +class Solution { + public int[][] generateMatrix(int n) { + int left = 0; + int right = n - 1; + int top = 0; + int bottom = n - 1; + + int[][] ans = new int[n][n]; + int num = 1; + while (true) { + for (int i = left; i <= right; i++) { + ans[top][i] = num++;//注意下标顺序 + } + if (++top > bottom) { + break; + } + for (int j = top; j <= bottom; j++) { + ans[j][right] = num++; + } + if (--right < left) { + break; + } + for (int m = right; m >= left; m--) { + ans[bottom][m] = num++; + } + if (--bottom < top) { + break; + } + for (int k = bottom; k >= top; k--) { + ans[k][left] = num++; + } + if (++left > right) { + break; + } + } + return ans; + } +} +``` + diff --git a/docs/leetcode/hot120/62-unique-paths.md b/docs/leetcode/hot120/62-unique-paths.md new file mode 100644 index 0000000..529cd97 --- /dev/null +++ b/docs/leetcode/hot120/62-unique-paths.md @@ -0,0 +1,120 @@ +# 62. 不同路径 + +[题目链接](https://leetcode.cn/problems/unique-paths/) + +**题目描述** + +一个机器人位于一个 m x n 网格的左上角 。机器人每次只能**向下或者向右移动一步**。机器人试图达到网格的右下角。 + +问总共有多少条不同的路径? + +![](http://img.dabin-coder.cn/image/uniquePaths1.png) + +**示例**: + +```java +输入:m = 3, n = 7 +输出:28 + +从左上角开始,总共有 3 条路径可以到达右下角。 +1. 向右 -> 向下 -> 向下 +2. 向下 -> 向下 -> 向右 +3. 向下 -> 向右 -> 向下 +``` + +**解题思路** + +首先了解下**动态规划**的思想。 + +动态规划用于处理有重叠子问题的问题。其基本思想:假如要解一个问题,需要先将问题分解成子问题,求出子问题的解,**再根据子问题的解得出原问题的解**。 + +动态规划算法会将计算出来的**子问题的解存储起来**,以便下次遇到同一个子问题的时候直接可以得到该子问题的解,减少重复计算。 + +**动态规划的解题思路:1、状态定义;2、状态转移方程;3、初始状态;4、确定遍历顺序。** + +接下来分步骤讲解本题目的思路。 + +1、首先是**状态定义**。假设 `dp[i][j]` 是到达 `(i, j)` 的路径数量,`dp[2][2]`就是到达`(2, 2)`的路径数量。 + +2、然后是**状态转移方程**。根据题意,只能向右和向下运动,当前位置`(i, j)`只能从`(i-1, j)`和`(i, j-1)`两个方向走过来,由此可以确定状态方程为`dp[i][j] = dp[i-1][j] + dp[i][j-1]`。 + +![](http://img.dabin-coder.cn/image/uniquePaths2.png) + +3、**初始状态**。对于第一行 `dp[0][j]`和第一列 `dp[i][0]`,由于都在边界,只有一个方向可以走,所以只能为 1。 + +4、**确定遍历顺序**。`dp[i][j]`是从其上边和左边推导而来,所以按照从左到右,从上到下的顺序来遍历。 + +**代码实现** + +使用二维数组`dp[][]`保存中间状态,时间复杂度和空间复杂度都是`O(m*n)`。 + +```java +public int uniquePaths(int m, int n) { + int[][] dp = new int[m][n]; + //初始化 + for (int i = 0; i < n; i++) { + dp[0][i] = 1; + } + //初始化 + for (int i = 0; i < m; i++) { + dp[i][0] = 1; + } + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + //状态方程 + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + } + } + return dp[m - 1][n - 1]; +} +``` + +**优化1**:根据状态转移方程`dp[i][j] = dp[i-1][j] + dp[i][j-1]`可知,只需要保存当前行与上一行的数据即可,空间复杂度可以优化为`O(2n)`,具体代码如下: + +```java +public int uniquePaths(int m, int n) { + int[] preRow = new int[n]; + int[] curRow = new int[n]; + //初始化 + for (int i = 0; i < n; i++) { + preRow[i] = 1; + curRow[i] = 1; + } + for (int i = 1; i < m; i++){ + for (int j = 1; j < n; j++){ + curRow[j] = curRow[j-1] + preRow[j]; + } + preRow = curRow.clone(); + } + return curRow[n-1]; +} +``` + +**优化2**:上述代码还可以继续优化,对于`curRow[j] = curRow[j-1] + preRow[j]`,在未赋值之前`curRow[j]`就是**当前行第`i`行的上一行第`j`列的值**(这里可能不太好理解,小伙伴们好好思考一下),也就是说未赋值之前`curRow[j]`与`preRow[j]`相等,因此`curRow[j] = curRow[j-1] + preRow[j]`可以写成`curRow[j] += curRow[j-1]`,优化1代码中的`preRow`数组可以不用,只需要`curRow`数组即可,代码如下: + +```java +public int uniquePaths(int m, int n) { + int[] curRow = new int[n]; + //初始化 + for (int i = 0; i < n; i++) { + curRow[i] = 1; + } + for (int i = 1; i < m; i++){ + for (int j = 1; j < n; j++){ + curRow[j] += curRow[j-1]; + } + } + return curRow[n-1]; +} +``` + + + +这道腾讯面试题,算是动态规划里面比较简单的题目,虽然不难,但是在面试时氛围比较紧张的情况下,想要一次性bug free做出来,并且做到最优解,还是有点难度的。 + + + + + + + diff --git a/docs/leetcode/hot120/7-reverse-integer.md b/docs/leetcode/hot120/7-reverse-integer.md new file mode 100644 index 0000000..43f8753 --- /dev/null +++ b/docs/leetcode/hot120/7-reverse-integer.md @@ -0,0 +1,58 @@ +# 7. 整数反转 + +[题目链接](https://leetcode.cn/problems/reverse-integer/) + +**题目描述** + +给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 + +如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 + +假设环境不允许存储 64 位整数(有符号或无符号)。 + +**示例** + +```java +输入:x = 123 +输出:321 + +输入:x = 120 +输出:21 +``` + +**解题思路** + +- 本题如果不考虑溢出问题,是非常简单的。解决溢出问题有两个思路,第一个思路是通过字符串转换加`try catch`的方式来解决,第二个思路就是通过数学计算来解决。 +- 由于字符串转换的效率较低且使用较多库函数,所以解题方案不考虑该方法,而是通过数学计算来解决。 +- 通过循环将数字`x`的每一位拆开,在计算新值时每一步都判断是否溢出。 +- 溢出条件有两个,一个是大于整数最大值`MAX_VALUE`,另一个是小于整数最小值`MIN_VALUE`,设当前计算结果为`ans`,下一位为`pop`。 +- 从`ans * 10 + pop > MAX_VALUE`这个溢出条件来看 + - 当出现 `ans > MAX_VALUE / 10` 且 `还有pop需要添加` 时,则一定溢出 + - 当出现 `ans == MAX_VALUE / 10` 且 `pop > 7` 时,则一定溢出,`7`是`2^31 - 1`的个位数 +- 从`ans * 10 + pop < MIN_VALUE`这个溢出条件来看 + - 当出现 `ans < MIN_VALUE / 10` 且 `还有pop需要添加` 时,则一定溢出 + - 当出现 `ans == MIN_VALUE / 10` 且 `pop < -8` 时,则一定溢出,`8`是`-2^31`的个位数 + +> 作者:guanpengchn +> 链接:https://leetcode.cn/problems/reverse-integer/solution/hua-jie-suan-fa-7-zheng-shu-fan-zhuan-by-guanpengc/ +> 来源:力扣(LeetCode) +> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +```java +class Solution { + public int reverse(int x) { + int ans = 0; + while (x != 0) { + int pop = x % 10; + if (ans > Integer.MAX_VALUE / 10 || (ans == Integer.MAX_VALUE / 10 && pop > 7)) + return 0; + if (ans < Integer.MIN_VALUE / 10 || (ans == Integer.MIN_VALUE / 10 && pop < -8)) + return 0; + ans = ans * 10 + pop; + x /= 10; + } + return ans; + } +} +``` + diff --git a/docs/leetcode/hot120/71-simplify-path.md b/docs/leetcode/hot120/71-simplify-path.md new file mode 100644 index 0000000..d031608 --- /dev/null +++ b/docs/leetcode/hot120/71-simplify-path.md @@ -0,0 +1,73 @@ +# 71. 简化路径 + +[题目链接](https://leetcode.cn/problems/simplify-path/) + +**题目描述** + +给你一个字符串 `path` ,表示指向某一文件或目录的 Unix 风格 **绝对路径** (以 `'/'` 开头),请你将其转化为更加简洁的规范路径。 + +在 Unix 风格的文件系统中,一个点(`.`)表示当前目录本身;此外,两个点 (`..`) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,`'//'`)都被视为单个斜杠 `'/'` 。 对于此问题,任何其他格式的点(例如,`'...'`)均被视为文件/目录名称。 + +请注意,返回的 **规范路径** 必须遵循下述格式: + +- 始终以斜杠 `'/'` 开头。 +- 两个目录名之间必须只有一个斜杠 `'/'` 。 +- 最后一个目录名(如果存在)**不能** 以 `'/'` 结尾。 +- 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 `'.'` 或 `'..'`)。 + +返回简化后得到的 **规范路径** 。 + +**示例**: + +```java +输入:path = "/home/" +输出:"/home" +解释:注意,最后一个目录名后面没有斜杠。 + +输入:path = "/../" +输出:"/" +解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。 +``` + +**解题思路** + +使用栈实现。 + +```java +//输入:"/a/./b/../../c/" +//输出:"/c" +class Solution { + public String simplifyPath(String path) { + Stack stack = new Stack<>(); + String[] strs = path.split("/"); + + for (String s : strs) { + if ("..".equals(s)) { + if (!stack.isEmpty()) { + stack.pop(); + } + continue;//只要是"..",就执行下一个循环,不能放入栈 + } + if (!"".equals(s) && !".".equals(s)) { + stack.push(s); + } + } + + if (stack.isEmpty()) { + return "/"; + } + + StringBuilder sb = new StringBuilder(); + int size = stack.size(); + for (int i = 0; i < size; i++) { + sb.append("/").append(stack.get(i));//tips + } + return sb.toString(); + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/73-set-matrix-zeroes.md b/docs/leetcode/hot120/73-set-matrix-zeroes.md new file mode 100644 index 0000000..8c6e254 --- /dev/null +++ b/docs/leetcode/hot120/73-set-matrix-zeroes.md @@ -0,0 +1,76 @@ +# 73. 矩阵置零 + +[题目链接](https://leetcode.cn/problems/set-matrix-zeroes/) + +**题目描述** + +给定一个 `*m* x *n*` 的矩阵,如果一个元素为 **0** ,则将其所在行和列的所有元素都设为 **0** 。请使用 **[原地](http://baike.baidu.com/item/原地算法)** 算法**。** + +![](http://img.dabin-coder.cn/image/image-20221121020953873.png) + +**示例**: + +```java +输入:matrix = [[1,1,1],[1,0,1],[1,1,1]] +输出:[[1,0,1],[0,0,0],[1,0,1]] +``` + +**解题思路** + +[参考解法](https://leetcode-cn.com/problems/set-matrix-zeroes/solution/ju-zhen-zhi-ling-by-leetcode/) + +1. 遍历整个矩阵,如果 cell[i][j] == 0 就将第 i 行和第 j 列的第一个元素标记。 +2. 第一行和第一列的标记是相同的,都是 cell[0][0],所以需要一个额外的变量告知第一列是否被标记,同时用 cell[0][0] 继续表示第一行的标记。 +3. 然后,从第二行第二列的元素开始遍历,如果第 r 行或者第 c 列被标记了,那么就将 cell[r][c] 设为 0。这里第一行和第一列的作用就相当于方法一中的 row_set 和 column_set 。 +4. 然后我们检查是否 cell[0][0] == 0 ,如果是则赋值第一行的元素为零。 +5. 然后检查第一列是否被标记,如果是则赋值第一列的元素为零。 + +```java +class Solution { + public void setZeroes(int[][] matrix) { + if (matrix == null || matrix.length == 0) { + return; + } + boolean isCol = false; + int rows = matrix.length; + int cols = matrix[0].length; + + for (int i = 0; i < rows; i++) { + if (matrix[i][0] == 0) { + isCol = true; + } + for (int j = 1; j < cols; j++) { + if (matrix[i][j] == 0) { + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + + for (int i = 1; i < rows; i++) { + for (int j = 1; j < cols;j++) { + if (matrix[i][0] == 0 || matrix[0][j] == 0) { + matrix[i][j] = 0; + } + } + } + + if (matrix[0][0] == 0) {//顺序 + for (int j = 0; j < cols; j++) { + matrix[0][j] = 0; + } + } + + if (isCol) {//顺序 + for (int i = 0; i < rows; i++) { + matrix[i][0] = 0; + } + } + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/74-search-a-2d-matrix.md b/docs/leetcode/hot120/74-search-a-2d-matrix.md new file mode 100644 index 0000000..ecab9d9 --- /dev/null +++ b/docs/leetcode/hot120/74-search-a-2d-matrix.md @@ -0,0 +1,54 @@ +# 74. 搜索二维矩阵 + +[题目链接](https://leetcode.cn/problems/search-a-2d-matrix/) + +**题目描述** + +编写一个高效的算法来判断 `m x n` 矩阵中,是否存在一个目标值。该矩阵具有如下特性: + +- 每行中的整数从左到右按升序排列。 +- 每行的第一个整数大于前一行的最后一个整数。 + +**示例**: + +![](http://img.dabin-coder.cn/image/image-20221121021212085.png) + +```java +输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 +输出:true +``` + +**参考代码** + +```java +class Solution { + public boolean searchMatrix(int[][] matrix, int target) { + if (null == matrix || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + int rows = matrix.length; + int cols = matrix[0].length; + int left = 0; + int right = rows * cols - 1; + + while (left <= right) { + int mid = (left + right) >> 1; //! + int val = matrix[mid / cols][mid % cols]; //cols!不是rows + if (target == val) { + return true; + } else if (target > val) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return false; + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/75-sort-colors.md b/docs/leetcode/hot120/75-sort-colors.md new file mode 100644 index 0000000..ee507a7 --- /dev/null +++ b/docs/leetcode/hot120/75-sort-colors.md @@ -0,0 +1,51 @@ +# 75. 颜色分类 + +[题目链接](https://leetcode.cn/problems/sort-colors/) + +**题目描述** + +给定一个包含红色、白色和蓝色、共 `n` 个元素的数组 `nums` ,**[原地](https://baike.baidu.com/item/原地算法)**对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 + +我们使用整数 `0`、 `1` 和 `2` 分别表示红色、白色和蓝色。 + +> 必须在不使用库的sort函数的情况下解决这个问题。 + +**示例**: + +```java +输入:nums = [2,0,2,1,1,0] +输出:[0,0,1,1,2,2] +``` + +**解题思路** + +三指针。 + +```java +class Solution { + public void sortColors(int[] nums) { + if (nums == null || nums.length == 0) { + return; + } + int p1 = 0, cur = 0, p2 = nums.length - 1; + while (cur <= p2) { //边界,nums全为1的情况 + if (nums[cur] == 0) { + int tmp = nums[p1]; + nums[p1++] = 0; + nums[cur++] = tmp; //cur++ + } else if (nums[cur] == 2) { + int tmp = nums[p2]; + nums[p2--] = 2; + nums[cur] = tmp; //nums[cur]可能为2,不自增 + } else { + cur++; + } + } + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/77-combinations.md b/docs/leetcode/hot120/77-combinations.md new file mode 100644 index 0000000..12806e7 --- /dev/null +++ b/docs/leetcode/hot120/77-combinations.md @@ -0,0 +1,67 @@ +# 77. 组合 + +[题目链接](https://leetcode.cn/problems/combinations/) + +**题目描述** + +给定两个整数 `n` 和 `k`,返回范围 `[1, n]` 中所有可能的 `k` 个数的组合。 + +你可以按 **任何顺序** 返回答案。 + +**示例**: + +```java +输入:n = 4, k = 2 +输出: +[ + [2,4], + [3,4], + [2,3], + [1,2], + [1,3], + [1,4], +] + +输入:n = 1, k = 1 +输出:[[1]] +``` + +**解题思路** + +回溯。剪枝优化。 + +![](http://img.dabin-coder.cn/image/image-20200526090917688.png) + +```java +class Solution { + public List> combine(int n, int k) { + List> res = new ArrayList<>(); + if (n <= 0 || k <= 0 || n < k) { + return res; + } + Stack stack = new Stack<>(); + combineHelper(res, stack, 1, n, k); + return res; + } + + public void combineHelper(List> res, Stack stack, int index,int n, int k) { + if (stack.size() == k) { + res.add(new ArrayList<>(stack)); + return; + } + // i 的极限值满足: n - i + 1 = (k - pre.size())。 + // 【关键】n - i + 1 是闭区间 [i,n] 的长度。 + // k - pre.size() 是剩下还要寻找的数的个数。 + for (int i = index; i <= n - (k - stack.size()) + 1; i++) { + stack.push(i); + combineHelper(res, stack, i + 1, n, k); + stack.pop(); + } + } +} +``` + + + + + diff --git a/docs/leetcode/hot120/83-remove-duplicates-from-sorted-list.md b/docs/leetcode/hot120/83-remove-duplicates-from-sorted-list.md new file mode 100644 index 0000000..091726c --- /dev/null +++ b/docs/leetcode/hot120/83-remove-duplicates-from-sorted-list.md @@ -0,0 +1,39 @@ +# 83. 删除排序链表中的重复元素 + +[83. 删除排序链表中的重复元素](https://leetcode.cn/problems/remove-duplicates-from-sorted-list/) + +**题目描述** + +给定一个已排序的链表的头 `head` , *删除所有重复的元素,使每个元素只出现一次* 。返回 *已排序的链表* 。 + +**示例** + +```java +输入:head = [1,1,2] +输出:[1,2] +``` + +**解题思路** + +使用快慢指针。 + +```java +class Solution { + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length <= 0) { + return 0; + } + + int slow = 0; + for (int fast = 1; fast < nums.length; fast++) { + if (nums[slow] != nums[fast]) { + slow++; + nums[slow] = nums[fast]; + } + } + + return slow + 1; + } +} +``` + diff --git a/docs/leetcode/hot120/9-palindrome-number.md b/docs/leetcode/hot120/9-palindrome-number.md new file mode 100644 index 0000000..db1ec32 --- /dev/null +++ b/docs/leetcode/hot120/9-palindrome-number.md @@ -0,0 +1,51 @@ +# 9. 回文数 + +[9. 回文数](https://leetcode.cn/problems/palindrome-number/) + +**题目描述** + +给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 + +回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 + +例如,121 是回文,而 123 不是。 + +**示例** + +```java +输入:x = 121 +输出:true + +输入:x = -121 +输出:false +解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 +``` + +**解题思路** + +将数字后半段反转,跟数字前半段相比即可。 + +```java +class Solution { + public boolean isPalindrome(int x) { + //排除负数和整十的数 + if (x < 0 || (x % 10 == 0 && x != 0)) { + return false; + } + + int reverseNum = 0; + //反转x的后半段数字,再做比较即可 + while(x > reverseNum) { + reverseNum = reverseNum * 10 + x % 10; + x /= 10; + } + + //x为奇数位时,转换后reverseNum会比x多一位 + //如x为1234321,转换后reverseNum为1234,x为123 + return x == reverseNum || x == reverseNum / 10; + } +} +``` + + + diff --git a/docs/leetcode/hot120/92-reverse-linked-list-ii.md b/docs/leetcode/hot120/92-reverse-linked-list-ii.md new file mode 100644 index 0000000..a582d16 --- /dev/null +++ b/docs/leetcode/hot120/92-reverse-linked-list-ii.md @@ -0,0 +1,41 @@ +# 92. 反转链表 II + +[原题链接](https://leetcode.cn/problems/reverse-linked-list-ii/) + +**题目描述** + +给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 + +**示例** + +```java +输入:head = [1,2,3,4,5], left = 2, right = 4 +输出:[1,4,3,2,5] +``` + +**解题思路** + +双指针+头插法。 + +```java +class Solution { + public ListNode reverseBetween(ListNode head, int m, int n) { + ListNode dummy = new ListNode(0); + dummy.next = head; + ListNode pre = dummy; + for (int i = 1; i < m; i++) { + pre = pre.next; + } + head = pre.next; + for (int i = m; i < n; i++) { + ListNode cur = head.next; + head.next = cur.next; + cur.next = pre.next; + pre.next = cur; + } + + return dummy.next; + } +} +``` + diff --git a/docs/leetcode/hot120/958-check-completeness-of-a-binary-tree.md b/docs/leetcode/hot120/958-check-completeness-of-a-binary-tree.md new file mode 100644 index 0000000..0a303e6 --- /dev/null +++ b/docs/leetcode/hot120/958-check-completeness-of-a-binary-tree.md @@ -0,0 +1,57 @@ +# 28. 对称的二叉树 + +[28. 对称的二叉树](https://leetcode.cn/problems/dui-cheng-de-er-cha-shu-lcof/) + +**题目描述** + +给定一个二叉树的 root ,确定它是否是一个 完全二叉树 。 + +在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的,并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 1 到 2^h 节点之间的最后一级 h 。 + +**示例** + +```java +输入:root = [1,2,3,4,5,6] +输出:true +解释:最后一层前的每一层都是满的(即,结点值为 {1} 和 {2,3} 的两层),且最后一层中的所有结点({4,5,6})都尽可能地向左。 +``` + +**解题思路** + +层序遍历,当且仅当存在两个相邻节点:前一个为null,后一个不为null时,则不是完全二叉树。 + +``` + 1 + / \ + 2 3 + / \ \ + 4 5 6 +层序遍历序列为:[1, 2, 3, 4, 5, null, 6],其中 null 出现在了6前面,所以不是完全二叉树 +``` + +代码实现: + +```java +class Solution { + public boolean isCompleteTree(TreeNode root) { + LinkedList list = new LinkedList<>(); + TreeNode pre = root; + TreeNode cur = root; + list.addLast(root); + + while (!list.isEmpty()) { + cur = list.removeFirst(); + if (cur != null) { + if (pre == null) { + return false; + } + list.addLast(cur.left); + list.addLast(cur.right); + } + pre = cur; + } + return true; + } +} +``` + diff --git a/docs/leetcode/hot120/98-validate-binary-search-tree.md b/docs/leetcode/hot120/98-validate-binary-search-tree.md new file mode 100644 index 0000000..a932e48 --- /dev/null +++ b/docs/leetcode/hot120/98-validate-binary-search-tree.md @@ -0,0 +1,56 @@ +# 98. 验证二叉搜索树 + +[题目链接](https://leetcode.cn/problems/validate-binary-search-tree/) + +**题目描述** + +给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 + +有效 二叉搜索树定义如下: + +- 节点的左子树只包含 小于 当前节点的数。 +- 节点的右子树只包含 大于 当前节点的数。 +- 所有左子树和右子树自身必须也是二叉搜索树。 + +**示例** + +```java +输入:root = [2,1,3] +输出:true + +输入:root = [5,1,4,null,null,3,6] +输出:false +解释:根节点的值是 5 ,但是右子节点的值是 4 。 +``` + +**解题思路** + +中序遍历时,判断当前节点是否大于中序遍历的前一个节点,如果大于,说明满足 BST,继续遍历;否则直接返回 false。 + +> 作者:sweetiee +> 链接:https://leetcode.cn/problems/validate-binary-search-tree/solution/zhong-xu-bian-li-qing-song-na-xia-bi-xu-miao-dong-/ +> 来源:力扣(LeetCode) +> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +```java +class Solution { + long pre = Long.MIN_VALUE; + public boolean isValidBST(TreeNode root) { + if (root == null) { + return true; + } + // 访问左子树 + if (!isValidBST(root.left)) { + return false; + } + // 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。 + if (root.val <= pre) { + return false; + } + pre = root.val; + // 访问右子树 + return isValidBST(root.right); + } +} +``` + diff --git a/docs/leetcode/hot120/README.md b/docs/leetcode/hot120/README.md new file mode 100644 index 0000000..5cc5691 --- /dev/null +++ b/docs/leetcode/hot120/README.md @@ -0,0 +1,41 @@ +## 目录 + +- [1.两数之和-梦开始的地方!!](./1-two-sum.md) +- [3.无重复字符的最长子串](./3-longest-substring-without-repeating-characters.md) +- [5.最长回文子串](./5-longest-palindromic-substring.md) +- [7.整数反转](./7-reverse-integer.md) +- [15.三数之和](./15-3sum.md) +- [19.删除链表的倒数第N个结点](./19-remove-nth-node-from-end-of-list.md) +- [22.括号生成](./22-generate-parentheses.md) +- [28.对称的二叉树](./28-mirror-binary-tree.md) +- [40.组合总和II](./40-combination-sum-ii.md) +- [46.全排列](./46-permutations.md) +- [47.全排列II](./47-permutations-ii.md) +- [53.最大子数组和](./53-maximum-subarray.md) +- [55.跳跃游戏](./55-jump-game.md) +- [56.合并区间](./56-merge-intervals.md) +- [62.不同路径](./62-unique-paths.md) +- [92.反转链表II](./92-reverse-linked-list-ii.md) +- [98.验证二叉搜索树](./98-validate-binary-search-tree.md) +- [103.二叉树的锯齿形层序遍历](./103-binary-tree-zigzag-level-order-traversal.md) +- [104.二叉树的最大深度](./104-maximum-depth-of-binary-tree.md) +- [120.三角形最小路径和](./120-triangle.md) +- [121.买卖股票的最佳时机](./121-best-time-to-buy-and-sell-stock.md) +- [122.买卖股票的最佳时机II](./122-best-time-to-buy-and-sell-stock-ii.md) +- [131.分割回文串](./131-palindrome-partion.md) +- [133.克隆图](./133-clone-graph.md) +- [134.加油站](./134-gas-station.md) +- [141.环形链表II](./141-linked-list-cycle.md) +- [146.LRU缓存](./146-lru-cache.md) +- [152.乘积最大子数组](./152-maximum-product-subarray.md) +- [160.相交链表](./160-intersection-of-two-linked-lists.md) +- [169.多数元素](./169-majority-element.md) +- [199.二叉树的右视图](./199-binary-tree-right-side-view.md) +- [200.岛屿数量](./200-number-of-islands.md) +- [206.反转链表](./206-reverse-linked-list.md) +- [215.数组中的第K个最大元素](./215-kth-largest-element-in-an-array.md) +- [234.回文链表](./234-palindrome-linked-list.md) +- [236.二叉树的最近公共祖先](./236-lowest-common-ancestor-of-a-binary-tree.md) +- [415.字符串相加](./415-add-strings.md) +- [543.二叉树的直径](./543-diameter-of-binary-tree.md) +- [1143.最长公共子序列](./1143-longest-common-subquence.md) diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" b/docs/mass-data/1-count-phone-num.md similarity index 95% rename from "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" rename to docs/mass-data/1-count-phone-num.md index c2ac733..0050098 100644 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\347\273\237\350\256\241\344\270\215\345\220\214\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\344\270\252\346\225\260.md" +++ b/docs/mass-data/1-count-phone-num.md @@ -1,6 +1,10 @@ -大家好,我是大彬~ +--- +sidebar: heading +--- -海量数据题目是面试经常会考的题型,今天给大家分享一道百度二面的题目。 +# 统计不同号码的个数 + +题目来自百度二面。 ## 题目描述 diff --git "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" b/docs/mass-data/2-find-hign-frequency-word.md similarity index 87% rename from "\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" rename to docs/mass-data/2-find-hign-frequency-word.md index 70a08a9..0d549bb 100644 --- "a/\346\265\267\351\207\217\346\225\260\346\215\256\345\234\272\346\231\257\351\242\230/\345\246\202\344\275\225\344\273\216\346\265\267\351\207\217\346\225\260\346\215\256\346\211\276\345\207\272\351\253\230\351\242\221\350\257\215.md" +++ b/docs/mass-data/2-find-hign-frequency-word.md @@ -1,6 +1,8 @@ -大家好,我是大彬~ +--- +sidebar: heading +--- -今天分享一道面试常考的海量数据场景题。 +# 出现频率最高的100个词 ## 题目描述 @@ -71,14 +73,3 @@ 解法2相对解法1,更加严谨,如果某个词词频过高或者整个文件都是同一个词的话,解法1不适用。 - -## 点关注,不迷路 - -大彬,**非科班出身,自学Java**,校招斩获京东、携程、华为等offer。作为一名转码选手,深感这一路的不易。 - -希望我的分享能帮助到更多的小伙伴,**我踩过的坑你们不要再踩**。想与大彬交流的话,可以到公众号后台获取大彬的微信~ - -后台回复『 **笔记**』即可领取大彬斩获大厂offer的**面试笔记**。 - -![](http://img.dabin-coder.cn/image/公众号.jpg) - diff --git a/docs/mass-data/3-find-same-url.md b/docs/mass-data/3-find-same-url.md new file mode 100644 index 0000000..6faedcf --- /dev/null +++ b/docs/mass-data/3-find-same-url.md @@ -0,0 +1,30 @@ +--- +sidebar: heading +--- + +# 查找两个大文件共同的URL + +## 题目 + +给定 a、b 两个文件,各存放 50 亿个 URL,每个 URL 各占 64B,找出 a、b 两个文件共同的 URL。内存限制是 4G。 + +## 分析 + +每个 URL 占 64B,那么 50 亿个 URL占用的空间大小约为 320GB。 + +5,000,000,000 * 64B ≈ 320GB + +由于内存大小只有 4G,因此,不可能一次性把所有 URL 加载到内存中处理。 + +可以采用分治策略,也就是把一个文件中的 URL 按照某个特征划分为多个小文件,使得每个小文件大小不超过 4G,这样就可以把这个小文件读到内存中进行处理了。 + +首先遍历文件a,对遍历到的 URL 进行哈希取余 `hash(URL) % 1000`,根据计算结果把遍历到的 URL 存储到 a0, a1,a2, ..., a999,这样每个大小约为 300MB。使用同样的方法遍历文件 b,把文件 b 中的 URL 分别存储到文件 b0, b1, b2, ..., b999 中。这样处理过后,所有可能相同的 URL 都在对应的小文件中,即 a0 对应 b0, ..., a999 对应 b999,不对应的小文件不可能有相同的 URL。那么接下来,我们只需要求出这 1000 对小文件中相同的 URL 就好了。 + +接着遍历 ai( `i∈[0,999]`),把 URL 存储到一个 HashSet 集合中。然后遍历 bi 中每个 URL,看在 HashSet 集合中是否存在,若存在,说明这就是共同的 URL,可以把这个 URL 保存到一个单独的文件中。 + +## 总结 + +最后总结一下: + +1. 分而治之,进行哈希取余; +2. 对每个子文件进行 HashSet 统计。 diff --git a/docs/mass-data/4-find-mid-num.md b/docs/mass-data/4-find-mid-num.md new file mode 100644 index 0000000..2fdcdff --- /dev/null +++ b/docs/mass-data/4-find-mid-num.md @@ -0,0 +1,36 @@ +--- +sidebar: heading + +--- + +# 如何在100亿数据中找到中位数? + +## 题目描述 + +给定100亿个无符号的乱序的整数序列,如何求出这100亿个数的中位数(中位数指的是排序后最中间那个数),内存只有**512M**。 + +## 分析 + +中位数问题可以看做一个统计问题,而不是排序问题,无符号整数大小为4B,则能表示的数的范围为为0 ~ 2^32 - 1(40亿),如果没有限制内存大小,则可以用一个2^32(4GB)大小的数组(也叫做桶)来保存100亿个数中每个无符号数出现的次数。遍历这100亿个数,当元素值等于桶元素索引时,桶元素的值加1。当统计完100亿个数以后,则从索引为0的值开始累加桶的元素值,当累加值等于50亿时,这个值对应的索引为中位数。时间复杂度为O(n)。 + +因为题目要求内存限制512M,所以上述解法不合适。 + +下面分享另一种解法(**分治法**的思想) + +如果100亿个数字保存在一个大文件中,可以依次读一部分文件到内存(不超过内存限制),将每个数字用二进制表示,比较二进制的最高位(第32位,符号位,0是正,1是负)。 + +如果数字的最高位为0,则将这个数字写入 file_0文件中;如果最高位为 1,则将该数字写入file_1文件中。 从而将100亿个数字分成了两个文件。 + +假设 file_0文件中有 60亿 个数字,file_1文件中有 40亿 个数字。那么中位数就在 file_0 文件中,并且是 file_0 文件中所有数字排序之后的第 10亿 个数字。因为file_1中的数都是负数,file_0中的数都是正数,也即这里一共只有40亿个负数,那么排序之后的第50亿个数一定位于file_0中。 + +现在,我们只需要处理 file_0 文件了,不需要再考虑file_1文件。对于 file_0 文件,同样采取上面的措施处理:将file_0文件依次读一部分到内存(不超过内存限制),将每个数字用二进制表示,比较二进制的 次高位(第31位),如果数字的次高位为0,写入file_0_0文件中;如果次高位为1,写入file_0_1文件 中。 + +现假设 file_0_0文件中有30亿个数字,file_0_1中也有30亿个数字,则中位数就是:file_0_0文件中的数字从小到大排序之后的第10亿个数字。 + +抛弃file_0_1文件,继续对 file_0_0文件 根据 次次高位(第30位) 划分,假设此次划分的两个文件为:file_0_0_0中有5亿个数字,file_0_0_1中有25亿个数字,那么中位数就是 file_0_0_1文件中的所有数字排序之后的 第 5亿 个数。 + +按照上述思路,直到划分的文件可直接加载进内存时,就可以直接对数字进行快速排序,找出中位数了。 + + + +> 参考链接:https://blog.csdn.net/qq_41306849/article/details/119828746 \ No newline at end of file diff --git a/docs/mass-data/5-find-hot-string.md b/docs/mass-data/5-find-hot-string.md new file mode 100644 index 0000000..d6862a4 --- /dev/null +++ b/docs/mass-data/5-find-hot-string.md @@ -0,0 +1,54 @@ +--- +sidebar: heading +--- + +# 如何查询最热门的查询串? + +## 题目描述 + +搜索引擎会通过日志文件把用户每次检索使用的所有查询串都记录下来,每个查询床的长度不超过 255 字节。 + +假设目前有 1000w 个记录(这些查询串的重复度比较高,虽然总数是 1000w,但如果除去重复后,则不超过 300w 个)。请统计最热门的 10 个查询串,要求使用的内存不能超过 1G。(一个查询串的重复度越高,说明查询它的用户越多,也就越热门。) + +## 解答思路 + +每个查询串最长为 255B,1000w 个串需要占用 约 2.55G 内存,因此,我们无法将所有字符串全部读入到内存中处理。 + +### 方法一:分治法 + +分治法依然是一个非常实用的方法。 + +划分为多个小文件,保证单个小文件中的字符串能被直接加载到内存中处理,然后求出每个文件中出现次数最多的 10 个字符串;最后通过一个小顶堆统计出所有文件中出现最多的 10 个字符串。 + +方法可行,但不是最好,下面介绍其他方法。 + +### 方法二:HashMap 法 + +虽然字符串总数比较多,但去重后不超过 300w,因此,可以考虑把所有字符串及出现次数保存在一个 HashMap 中,所占用的空间为 300w*(255+4)≈777M(其中,4表示整数占用的4个字节)。由此可见,1G 的内存空间完全够用。 + +**思路如下**: + +首先,遍历字符串,若不在 map 中,直接存入 map,value 记为 1;若在 map 中,则把对应的 value 加 1,这一步时间复杂度 `O(N)`。 + +接着遍历 map,构建一个 10 个元素的小顶堆,若遍历到的字符串的出现次数大于堆顶字符串的出现次数,则进行替换,并将堆调整为小顶堆。 + +遍历结束后,堆中 10 个字符串就是出现次数最多的字符串。这一步时间复杂度 `O(Nlog10)`。 + +### 方法三:前缀树法 + +方法二使用了 HashMap 来统计次数,当这些字符串有大量相同前缀时,可以考虑使用前缀树来统计字符串出现的次数,树的结点保存字符串出现次数,0 表示没有出现。 + +**思路如下**: + +在遍历字符串时,在前缀树中查找,如果找到,则把结点中保存的字符串次数加 1,否则为这个字符串构建新结点,构建完成后把叶子结点中字符串的出现次数置为 1。 + +最后依然使用小顶堆来对字符串的出现次数进行排序。 + +## 方法总结 + +前缀树经常被用来统计字符串的出现次数。它的另外一个大的用途是字符串查找,判断是否有重复的字符串等。 + + + +> 作者:yanglbme +> 链接:https://juejin.cn/post/6844904003998842887 \ No newline at end of file diff --git a/docs/mass-data/6-top-500-num.md b/docs/mass-data/6-top-500-num.md new file mode 100644 index 0000000..c5c5428 --- /dev/null +++ b/docs/mass-data/6-top-500-num.md @@ -0,0 +1,116 @@ +--- +sidebar: heading +--- + +## 如何找出排名前 500 的数? + +## 题目描述 + +有 1w 个数组,每个数组有 500 个元素,并且有序排列。如何在这 10000*500 个数中找出前 500 的数? + +## 方法1 + +题目中每个数组是排好序的,可以使用**归并**的方法。 + +先将第1个和第2个归并,得到500个数据。然后再将结果和第3个数组归并,得到500个数据,以此类推,直到最后找出前500个的数。 + +## 方法2 + +对于这种topk问题,更常用的方法是使用**堆排序**。 + +对本题而言,假设数组降序排列,可以采用以下方法: + +首先建立大顶堆,堆的大小为数组的个数,即为10000 ,把每个数组最大的值存到堆中。 + +接着删除堆顶元素,保存到另一个大小为 500 的数组中,然后向大顶堆插入删除的元素所在数组的下一个元素。 + +重复上面的步骤,直到删除完第 500 个元素,也即找出了最大的前 500 个数。 + +**示例代码如下**: + +```java +import lombok.Data; + +import java.util.Arrays; +import java.util.PriorityQueue; + +@Data +public class DataWithSource implements Comparable { + /** + * 数值 + */ + private int value; + + /** + * 记录数值来源的数组 + */ + private int source; + + /** + * 记录数值在数组中的索引 + */ + private int index; + + public DataWithSource(int value, int source, int index) { + this.value = value; + this.source = source; + this.index = index; + } + + /** + * + * 由于 PriorityQueue 使用小顶堆来实现,这里通过修改 + * 两个整数的比较逻辑来让 PriorityQueue 变成大顶堆 + */ + @Override + public int compareTo(DataWithSource o) { + return Integer.compare(o.getValue(), this.value); + } +} + + +class Test { + public static int[] getTop(int[][] data) { + int rowSize = data.length; + int columnSize = data[0].length; + + // 创建一个columnSize大小的数组,存放结果 + int[] result = new int[columnSize]; + + PriorityQueue maxHeap = new PriorityQueue<>(); + for (int i = 0; i < rowSize; ++i) { + // 将每个数组的最大一个元素放入堆中 + DataWithSource d = new DataWithSource(data[i][0], i, 0); + maxHeap.add(d); + } + + int num = 0; + while (num < columnSize) { + // 删除堆顶元素 + DataWithSource d = maxHeap.poll(); + result[num++] = d.getValue(); + if (num >= columnSize) { + break; + } + + d.setValue(data[d.getSource()][d.getIndex() + 1]); + d.setIndex(d.getIndex() + 1); + maxHeap.add(d); + } + return result; + + } + + public static void main(String[] args) { + int[][] data = { + {29, 17, 14, 2, 1}, + {19, 17, 16, 15, 6}, + {30, 25, 20, 14, 5}, + }; + + int[] top = getTop(data); + System.out.println(Arrays.toString(top)); // [30, 29, 25, 20, 19] + } +} +``` + diff --git a/docs/mass-data/7-query-frequency-sort.md b/docs/mass-data/7-query-frequency-sort.md new file mode 100644 index 0000000..3001b61 --- /dev/null +++ b/docs/mass-data/7-query-frequency-sort.md @@ -0,0 +1,33 @@ +--- +sidebar: heading +--- + +## 如何按照 query 的频度排序? + +### 题目描述 + +有 10 个文件,每个文件大小为 1G,每个文件的每一行存放的都是用户的 query,每个文件的 query 都可能重复。要求按照 query 的频度排序。 + +### 解答思路 + +如果 query 的重复度比较大,可以考虑一次性把所有 query 读入内存中处理;如果 query 的重复率不高,那么可用内存不足以容纳所有的 query,这时候就需要采用分治法或其他的方法来解决。 + +#### 方法一:HashMap 法 + +如果 query 重复率高,说明不同 query 总数比较小,可以考虑把所有的 query 都加载到内存中的 HashMap 中。接着就可以按照 query 出现的次数进行排序。 + +#### 方法二:分治法 + +分治法需要根据数据量大小以及可用内存的大小来确定问题划分的规模。对于这道题,可以顺序遍历 10 个文件中的 query,通过 Hash 函数 `hash(query) % 10` 把这些 query 划分到 10 个小文件中。之后对每个小文件使用 HashMap 统计 query 出现次数,根据次数排序并写入到零外一个单独文件中。 + +接着对所有文件按照 query 的次数进行排序,这里可以使用归并排序(由于无法把所有 query 都读入内存,因此需要使用外排序)。 + +### 方法总结 + +- 内存若够,直接读入进行排序; +- 内存不够,先划分为小文件,小文件排好序后,整理使用外排序进行归并。 + + + +> 作者:yanglbme +> 链接:https://juejin.cn/post/6844904003998842887 \ No newline at end of file diff --git a/docs/mass-data/8-topk-template.md b/docs/mass-data/8-topk-template.md new file mode 100644 index 0000000..d9bc6e6 --- /dev/null +++ b/docs/mass-data/8-topk-template.md @@ -0,0 +1,166 @@ +## 大数据中 TopK 问题的常用套路 + +今天想跟大家聊一些**常见的 topK 问题**。 + +对于海量数据到处理经常会涉及到 topK 问题。在设计数据结构和算法的时候,主要需要考虑的应该是当前算法(包括数据结构)跟给定情境(比如数据量级、数据类型)的适配程度,和当前问题最核心的瓶颈(如降低时间复杂度,还是降低空间复杂度)是什么。 + +首先,我们来举几个常见的 topK 问题的例子: + +1. 给定 100 个 int 数字,在其中找出最大的 10 个; +1. 给定 10 亿个 int 数字,在其中找出最大的 10 个(这 10 个数字可以无序); +1. 给定 10 亿个 int 数字,在其中找出最大的 10 个(这 10 个数字依次排序); +1. 给定 10 亿个不重复的 int 数字,在其中找出最大的 10 个; +1. 给定 10 个数组,每个数组中有 1 亿个 int 数字,在其中找出最大的 10 个; +1. 给定 10 亿个 string 类型的数字,在其中找出最大的 10 个(仅需要查 1 次); +1. 给定 10 亿个 string 类型的数字,在其中找出最大的 k 个(需要反复多次查询,其中 k 是一个随机数字)。 + +上面这些问题看起来很相似,但是解决的方式却千差万别。稍有不慎,就可能使得 topK 问题成为系统的瓶颈。不过也不用太担心,接下来我会总结几种常见的解决思路,遇到问题的时候,大家把这些基础思路融会贯通并且杂糅组合,即可做到见招拆招。 +
+ +### 1. 堆排序法 + +这里说的是堆排序法,而不是快排或者希尔排序。虽然理论时间复杂度都是 `O(nlogn)`,但是堆排在做 topK 的时候有一个优势,就是可以维护一个仅包含 k 个数字的小顶堆(想清楚,为啥是小顶堆哦),当新加入的数字大于堆顶数字的时候,将堆顶元素剔除,并加入新的数字。 + +用 C++ 来说明,堆在 stl 中是 priority_queue(不是 set)。 + +```cpp +int main() { + const int topK = 3; + vector vec = {4,1,5,8,7,2,3,0,6,9}; + priority_queue, greater<>> pq; // 小顶堆 + for (const auto& x : vec) { + pq.push(x); + if (pq.size() > topK) { + // 如果超出个数,则弹出堆顶(最小的)数据 + pq.pop(); + } + } + + while (!pq.empty()) { + cout << pq.top() << endl; // 输出依次为7,8,9 + pq.pop(); + } + + return 0; +} +``` + +> Java 中同样提供了 PriorityQueue 的数据结构。 + +### 2. 类似快排法 + +快排大家都知道,针对 topK 问题,可以对快排进行改进。仅对部分数据进行递归计算。比如,在 100 个数字中,找最大的 10 个,第一次循环的时候,povit 被移动到了 80 的位置,则接下来仅需要在后面的 20 个数字中找最大的 10 个即可。 + +这样做的优势是,理论最优时间复杂度可以达到 `O(n)`,不过平均时间复杂度还是 `O(nlogn)`。需要说明的是,通过这种方式,找出来的最大的 k 个数字之间,是无序的。 + +```cpp +int partition(vector& arr, int begin, int end) { + int left = begin; + int right = end; + int povit = arr[begin]; + + while (left < right) { + while (left < right && arr[right] >= povit) {right--;} + while (left < right && arr[left] <= povit) {left++;} + if (left < right) {swap(arr[left], arr[right]);} + } + + swap(arr[begin], arr[left]); + return left; +} + +void partSort(vector& arr, int begin, int end, int target) { + if (begin >= end) { + return; + } + + int povit = partition(arr, begin, end); + if (target < povit) { + partSort(arr, begin, povit - 1, target); + } else if (target > povit) { + partSort(arr, povit + 1, end, target); + } +} + +vector getMaxNumbers(vector& arr, int k) { + int size = (int)arr.size(); + // 把求最大的k个数,转换成求最小的size-k个数字 + int target = size - k; + partSort(arr, 0, size - 1, target); + vector ret(arr.end() - k, arr.end()); + return ret; +} + +int main() { + vector vec = {4,1,5,8,7,2,3,0,6,9}; + auto ret = getMaxNumbers(vec, 3); + + for (auto x : ret) { + cout << x << endl; // 输出7,8,9(理论上无序) + } + + return 0; +} +``` + +
+ +### 3. 使用 bitmap + +有时候 topK 问题会遇到数据量过大,内存无法全部加载。这个时候,可以考虑将数据存放至 bitmap 中,方便查询。 + +比如,给出 10 个 int 类型的数据,分别是【13,12,11,1,2,3,4,5,6,7】,int 类型的数据每个占据 4 个字节,那这个数组就占据了 40 个字节。现在,把它们放到一个 16 个长度 bool 的 bitmap 中,结果就是【0,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0】,在将空间占用降低至 4 字节的同时,也可以很方便的看出,最大的 3 个数字,分别是 11,12 和 13。 + +需要说明的是,bitmap 结合跳表一起使用往往有奇效。比如以上数据还可以记录成:从第 1 位开始,有连续 7 个 1;从第 11 位开始,有连续 3 个 1。这样做,空间复杂度又得到了进一步的降低。 + +这种做法的优势,当然是降低了空间复杂度。不过需要注意一点,bitmap 比较适合不重复且有范围(比如,数据均在 0 ~ 10 亿之间)的数据的查询。至于有重复数据的情况,可以考虑与 hash 等结构的混用。 +
+ +### 4. 使用 hash + +如果遇到了查询 string 类型数据的大小,可以考虑 hash 方法。 + +举个例子,10 个 string 数字【"1001","23","1002","3003","2001","1111","65","834","5","987"】找最大的 3 个。我们先通过长度进行 hash,得到长度最大为 4,且有 5 个长度为 4 的 string。接下来再通过最高位值做 hash,发现有 1 个最高位为"3"的,1 个为"2"的,3 个为"1"的。接下来,可以通过再设计 hash 函数,或者是循环的方式,在 3 个最高位为"1"的 string 中找到最大的一个,即可找到 3 个最值大的数据。 + +这种方法比较适合网址或者电话号码的查询。缺点就是如果需要多次查询的话,需要多次计算 hash,并且需要根据实际情况设计多个 hash 函数。 +
+ +### 5. 字典树 + +字典树(trie)的具体结构和查询方式,不在这里赘述了,自行百度一下就有很多。这里主要说一下优缺点。 + +字典树的思想,还是通过前期建立索引信息,后期可以反复多次查询,并且后期增删数据也很方便。比较适合于需要反复多次查询的情况。 + +比如,反复多次查询字符序(例如:z>y>...>b>a)最大的 k 个 url 这种,使用字典树把数据存储一遍,就非常适合。既减少了空间复杂度,也加速了查询效率。 +
+ +### 6. 混合查询 + +以上几种方法,都是比较独立的方法。其实,在实际工作中,遇到更多的问题还是混合问题,这就需要我们对相关的内容,融会贯通并且做到活学活用。 + +我举个例子:我们的分布式服务跑在 10 台不同机器上,每台机器上部署的服务均被请求 10000 次,并且记录了个这 10000 次请求的耗时(耗时值为 int 数据),找出这 10\*10000 次请求中,从高到低的找出耗时最大的 50 个。看看这个问题,很现实吧。我们试着用上面介绍的方法,组合一下来求解。 + +#### 方法一 + +首先,对每台机器上的 10000 个做类似快排,找出每台机器上 top50 的耗时信息。此时,单机上的这 50 条数据是无序的。 + +然后,再将 10 台机器上的 50 条数据(共 500 条)放到一起,再做一次类似快排,找到最大的 50 个(此时应该这 50 个应该是无序的)。 + +最后,对这 50 个数据做快排,从而得到最终结果。 + +#### 方法二 + +首先通过堆排,分别找出 10 台机器上耗时最高的 50 个数据,此时的这 50 个数据,已经是从大到小有序的了。 + +然后,我们依次取出 10 台机器中,耗时最高的 5 条放入小顶堆中。 + +最后,遍历 10 台机器上的数据,每台机器从第 6 个数据开始往下循环,如果这个值比堆顶的数据大,则抛掉堆顶数据并且把它加入,继续用下一个值进行同样比较。如果这个值比堆顶的值小,则结束当前循环,并且在下一台机器上做同样操作。 + +以上我介绍了两种方法,并不是为了说明哪种方法更好,或者时间复杂度更低。而是想说同样的事情有多种不同的解决方法,而且随着数据量的增加,可能会需要更多组合形式。在这个领域,数据决定了数据结构,数据结构决定了算法。 + +**没有最好的方法,只有不断找寻更好的方法的程序员。适合的,才会是最好的。** + + + +> 作者 Chunel Feng,编程爱好者,阿里巴巴搜索引擎开发工程师。 + diff --git a/docs/mass-data/README.md b/docs/mass-data/README.md new file mode 100644 index 0000000..e60cf7e --- /dev/null +++ b/docs/mass-data/README.md @@ -0,0 +1,12 @@ + +## 海量数据面试题(更新中) + +- [如何查询最热门的查询串?](./5-find-hot-string.md) +- [统计不同号码的个数](./1-count-phone-num.md) +- [出现频率最高的100个词](./2-find-hign-frequency-word.md) +- [查找两个大文件共同的URL](./3-find-same-url.md) +- [如何在100亿数据中找到中位数?](./4-find-mid-num) +- [如何查询最热门的查询串?](./5-find-hot-string) +- [如何找出排名前 500 的数?](./6-top-500-num) +- [如何按照 query 的频度排序?](./7-query-frequency-sort) +- [大数据中 TopK 问题的常用套路](./8-topk-template) diff --git "a/\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" b/docs/message-queue/kafka.md similarity index 100% rename from "\346\266\210\346\201\257\351\230\237\345\210\227/kafka.md" rename to docs/message-queue/kafka.md diff --git a/docs/message-queue/mq.md b/docs/message-queue/mq.md new file mode 100644 index 0000000..27423b4 --- /dev/null +++ b/docs/message-queue/mq.md @@ -0,0 +1,181 @@ +--- +sidebar: heading +--- + +## 为什么要使用消息队列? + +总结一下,主要三点原因:**解耦、异步、削峰**。 + +1、解耦。比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单操作失败。订单系统与库存系统耦合,这个时候如果使用消息队列,可以返回给用户成功,先把消息持久化,等库存系统恢复后,就可以正常消费减去库存了。 + +2、异步。将消息写入消息队列,非必要的业务逻辑以异步的方式运行,不影响主流程业务。 + +3、削峰。消费端慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。比如秒杀活动,一般会因为流量过大,从而导致流量暴增,应用挂掉。这个时候加上消息队列,服务器接收到用户的请求后,首先写入消息队列,如果消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。 + +## 使用了消息队列会有什么缺点 + +- 系统可用性降低。引入消息队列之后,如果消息队列挂了,可能会影响到业务系统的可用性。 +- 系统复杂性增加。加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。 + +## 常见的消息队列对比 + +| 对比方向 | 概要 | +| -------- | ------------------------------------------------------------ | +| 吞吐量 | 万级的 ActiveMQ 和 RabbitMQ 的吞吐量(ActiveMQ 的性能最差)要比 十万级甚至是百万级的 RocketMQ 和 Kafka 低一个数量级。 | +| 可用性 | 都可以实现高可用。ActiveMQ 和 RabbitMQ 都是基于主从架构实现高可用性。RocketMQ 基于分布式架构。 kafka 也是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 | +| 时效性 | RabbitMQ 基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。其他三个都是 ms 级。 | +| 功能支持 | 除了 Kafka,其他三个功能都较为完备。 Kafka 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准 | +| 消息丢失 | ActiveMQ 和 RabbitMQ 丢失的可能性非常低, RocketMQ 和 Kafka 理论上不会丢失。 | + +**总结:** + +- ActiveMQ 的社区算是比较成熟,但是较目前来说,ActiveMQ 的性能比较差,而且版本迭代很慢,不推荐使用。 +- RabbitMQ 在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,但是由于它基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。但是也因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做 erlang 源码级别的研究和定制。如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。 +- RocketMQ 阿里出品,Java 系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的 MQ,并且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。RocketMQ 社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准 JMS 规范走的有些系统要迁移需要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用 RocketMQ 挺好的 +- Kafka 的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。同时 kafka 最好是支撑较少的 topic 数量即可,保证其超高吞吐量。kafka 唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集。 + +## 如何保证消息队列的高可用? + +RabbitMQ:**镜像集群模式** + +RabbitMQ 是基于主从做高可用性的,Rabbitmq有三种模式:单机模式、普通集群模式、镜像集群模式。单机模式一般在生产环境中很少用,普通集群模式只是提高了系统的吞吐量,让集群中多个节点来服务某个 Queue 的读写操作。那么真正实现 RabbitMQ 高可用的是镜像集群模式。 + +镜像集群模式跟普通集群模式不一样的是,创建的 Queue,无论元数据还是Queue 里的消息都会存在于多个实例上,然后每次你写消息到 Queue 的时候,都会自动和多个实例的 Queue 进行消息同步。这样设计,好处在于:任何一个机器宕机不影响其他机器的使用。坏处在于:1. 性能开销太大:消息同步所有机器,导致网络带宽压力和消耗很重;2. 扩展性差:如果某个 Queue 负载很重,即便加机器,新增的机器也包含了这个 Queue 的所有数据,并没有办法线性扩展你的 Queue。 + +Kafka:**partition 和 replica 机制** + +Kafka 基本架构是多个 broker 组成,每个 broker 是一个节点。创建一个 topic 可以划分为多个 partition,每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据,这就是天然的分布式消息队列。就是说一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。 + +Kafka 0.8 以前,是没有 HA 机制的,任何一个 broker 宕机了,它的 partition 就没法写也没法读了,没有什么高可用性可言。 + +Kafka 0.8 以后,提供了 HA 机制,就是 replica 副本机制。每个 partition 的数据都会同步到其他机器上,形成自己的多个 replica 副本。然后所有 replica 会选举一个 leader 出来,生产和消费都跟这个 leader 打交道,然后其他 replica 就是 follower。写的时候,leader 会负责把数据同步到所有 follower 上去,读的时候就直接读 leader 上数据即可。Kafka 会均匀的将一个 partition 的所有 replica 分布在不同的机器上,这样才可以提高容错性。 + +## MQ常用协议 + +- **AMQP协议** AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。 + + > 优点:可靠、通用 + +- **MQTT协议** MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。 + + > 优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统 + +- **STOMP协议** STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。 + + > 优点:命令模式(非topic/queue模式) + +- **XMPP协议** XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。 + + > 优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大 + +- **其他基于TCP/IP自定义的协议**:有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。 + +## MQ的通讯模式 + +1. **点对点通讯**:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。 +2. **多点广播**:MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。 +3. **发布/订阅(Publish/Subscribe)模式**:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。 +4. **集群(Cluster)**:为了简化点对点通讯模式中的系统配置,MQ提供 Cluster 的解决方案。集群类似于一个 域(Domain) ,集群内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用 Cluster 通道与其它成员通讯,从而大大简化了系统配置。此外,集群中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性 + +## 如何保证消息的顺序性? + +**RabbitMQ** + +拆分多个 Queue,每个 Queue一个 Consumer;或者就一个 Queue 但是对应一个 Consumer,然后这个 Consumer 内部用内存队列做排队,然后分发给底层不同的 Worker 来处理。 + +**Kafka** + +1. 一个 Topic,一个 Partition,一个 Consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。 + +2. 写 N 个内存 Queue,具有相同 key 的数据都到同一个内存 Queue;然后对于 N 个线程,每个线程分别消费一个内存 Queue 即可,这样就能保证顺序性。 +## 如何避免消息重复消费? + +在消息生产时,MQ内部针对每条生产者发送的消息生成一个唯一id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。 + +在消息消费时,要求消息体中也要有一全局唯一id作为去重和幂等的依据,避免同一条消息被重复消费。 + +## 大量消息在 MQ 里长时间积压,该如何解决? + +一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下: + +1. 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉; +2. 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量; +3. 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue; +4. 接着临时用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据; +5. 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。 + +## MQ 中的消息过期失效了怎么办? + +如果使用的是RabbitMQ的话,RabbtiMQ 是可以设置过期时间的(TTL)。如果消息在 Queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。这时的问题就不是数据会大量积压在 MQ 里,而是大量的数据会直接搞丢。这个情况下,就不是说要增加 Consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。 + +我们可以采取一个方案,就是批量重导。就是大量积压的时候,直接将数据写到数据库,然后等过了高峰期以后将这批数据一点一点的查出来,然后重新灌入 MQ 里面去,把丢的数据给补回来。 + +## 消息中间件如何做到高可用? + +以Kafka为例。 + + Kafka 的基础集群架构,由多个`broker`组成,每个`broker`都是一个节点。当你创建一个`topic`时,它可以划分为多个`partition`,而每个`partition`放一部分数据,分别存在于不同的 broker 上。也就是说,一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。 + +每个`partition`放一部分数据,如果对应的broker挂了,那这部分数据是不是就丢失了?那不是保证不了高可用吗? + +Kafka 0.8 之后,提供了复制多副本机制来保证高可用,即每个 partition 的数据都会同步到其它机器上,形成多个副本。然后所有的副本会选举一个 leader 出来,让leader去跟生产和消费者打交道,其他副本都是follower。写数据时,leader 负责把数据同步给所有的follower,读消息时,直接读 leader 上的数据即可。如何保证高可用的?就是假设某个 broker 宕机,这个broker上的partition 在其他机器上都有副本的。如果挂的是leader的broker呢?其他follower会重新选一个leader出来。 + +## 如何保证数据一致性,事务消息如何实现? + +一条普通的MQ消息,从产生到被消费,大概流程如下: + +![](http://img.dabin-coder.cn/image/消息一致性1.png) + +1. 生产者产生消息,发送带MQ服务器 +2. MQ收到消息后,将消息持久化到存储系统。 +3. MQ服务器返回ACk到生产者。 +4. MQ服务器把消息push给消费者 +5. 消费者消费完消息,响应ACK +6. MQ服务器收到ACK,认为消息消费成功,即在存储中删除消息。 + +举个下订单的例子吧。订单系统创建完订单后,再发送消息给下游系统。如果订单创建成功,然后消息没有成功发送出去,下游系统就无法感知这个事情,出导致数据不一致。 +如何保证数据一致性呢?可以使用**事务消息**。一起来看下事务消息是如何实现的吧。 + +![](http://img.dabin-coder.cn/image/消息一致性2.png) + +1. 生产者产生消息,发送一条半事务消息到MQ服务器 +2. MQ收到消息后,将消息持久化到存储系统,这条消息的状态是待发送状态。 +3. MQ服务器返回ACK确认到生产者,此时MQ不会触发消息推送事件 +4. 生产者执行本地事务 +5. 如果本地事务执行成功,即commit执行结果到MQ服务器;如果执行失败,发送rollback。 +6. 如果是正常的commit,MQ服务器更新消息状态为可发送;如果是rollback,即删除消息。 +7. 如果消息状态更新为可发送,则MQ服务器会push消息给消费者。消费者消费完就回ACK。 +8. 如果MQ服务器长时间没有收到生产者的commit或者rollback,它会反查生产者,然后根据查询到的结果执行最终状态。 + +## 如何设计一个消息队列? + +首先是消息队列的整体流程,producer发送消息给broker,broker存储好,broker再发送给consumer消费,consumer回复消费确认等。 + +producer发送消息给broker,broker发消息给consumer消费,那就需要两次RPC了,RPC如何设计呢?可以参考开源框架Dubbo,你可以说说服务发现、序列化协议等等 + +broker考虑如何持久化呢,是放文件系统还是数据库呢,会不会消息堆积呢,消息堆积如何处理呢。 + +消费关系如何保存呢? 点对点还是广播方式呢?广播关系又是如何维护呢?zk还是config server + +消息可靠性如何保证呢?如果消息重复了,如何幂等处理呢? + +消息队列的高可用如何设计呢? 可以参考Kafka的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。 + +消息事务特性,与本地业务同个事务,本地消息落库;消息投递到服务端,本地才删除;定时任务扫描本地消息库,补偿发送。 + +MQ得伸缩性和可扩展性,如果消息积压或者资源不够时,如何支持快速扩容,提高吞吐?可以参照一下 Kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了吗。 + +[参考链接](https://juejin.cn/post/7088909199475736612#heading-18) + +## 多线程异步和MQ的区别 + +- **CPU消耗**。多线程异步可能存在CPU竞争,而MQ不会消耗本机的CPU。 +- MQ 方式实现异步是完全**解耦**的,适合于大型互联网项目。 +- **削峰或者消息堆积能力**。当业务系统处于高并发,MQ可以将消息堆积在Broker实例中,而多线程会创建大量线程,甚至触发拒绝策略。 +- 使用MQ引入了中间件,增加了项目复杂度和运维难度。 + +总的来说,规模比较小的项目可以使用多线程实现异步,大项目建议使用MQ实现异步。 + + + +![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git "a/\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" b/docs/message-queue/rabbitmq.md similarity index 100% rename from "\346\266\210\346\201\257\351\230\237\345\210\227/RabbitMQ.md" rename to docs/message-queue/rabbitmq.md diff --git a/docs/other/leave-a-message.md b/docs/other/leave-a-message.md new file mode 100644 index 0000000..3013cc1 --- /dev/null +++ b/docs/other/leave-a-message.md @@ -0,0 +1,4 @@ +# 留言区 + +大家有什么建议,或者觉得某个知识点理解有误的,欢迎到评论区留言~ + diff --git a/docs/other/site-diary.md b/docs/other/site-diary.md new file mode 100644 index 0000000..1d40738 --- /dev/null +++ b/docs/other/site-diary.md @@ -0,0 +1,109 @@ +--- +sidebar: heading +--- + +大彬的小破站是22年7月份开始搭建的,收录了我平时梳理的一些文章,网站内容还在不断更新中~ + +在此记录下小破站的迭代更新记录。 + +## 更新记录 + +- 2022.12.18,新增[order by是怎么工作的?](/advance/excellent-article/13-order-by-work.md) + +- 2022.12.17,新增[单点登录(SSO)设计与实现](/advance/system-design/8-sso-design.md) + +- 2022.12.05,新增[ES的分布式架构原理](/database/es/1-es-architect.html) + +- 2022.11.28,新增[系统设计-微信红包系统如何设计](/advance/system-design/6-wechat-redpacket-design.html) + +- 2022.11.20,新增[系统设计-短链系统](/advance/system-design/4-short-url.html) + +- 2022.11.20,新增[校招分享-双非本,非科班的自我救赎之路](/campus-recruit/share/1-23-backend.html),[校招分享-秋招还没offer,该怎么办](/campus-recruit/share/2-no-offer.html) + +- 2022.11.14,[修复Java集合uml图错误](https://topjavaer.cn/java/java-collection.html#%E5%B8%B8%E8%A7%81%E7%9A%84%E9%9B%86%E5%90%88%E6%9C%89%E5%93%AA%E4%BA%9B) + +- 2022.11.12,[120道LeetCode题解(高频)](/leetcode/README.md),已整理**58**道 + +- 2022.10.28,[120道LeetCode题解(高频)](/leetcode/README.md),已整理**40**道 + +- 2022.10.15,增加计算机基础-[120道LeetCode题解(高频)](/leetcode/README.md),已整理**28**道 + +- 2022.10.08,增加校招-[Java和C++怎么选?](/campus-recruit/program-language/java-or-c++.md) + +- 2022.10.05,增加优质文章-[MySQL最大建议行数 2000w,靠谱吗?](/advance/excellent-article/12-mysql-table-max-rows.md) + +- 2022.10.04,增加优质文章-[8种架构模式](/advance/excellent-article/11-8-architect-pattern.md) + +- 2022.09.18,增加海量数据面试题-[如何找出排名前 500 的数?](/mass-data/6-top-500-num.md) + +- 2022.09.16,增加高并发-[限流算法](/advance/concurrent/1-current-limiting.md),[负载均衡](/advance/concurrent/2-load-balance.md) + +- 2022.09.15,增加海量数据面试题-[如何查询最热门的查询串?](/mass-data/5-find-hot-string.md) + +- 2022.09.09,增加框架-[SpringCloud面试题](/framework/springcloud-interview.md) + +- 2022.09.05,增加优质文章-[大文件上传时如何做到秒传?](/advance/excellent-article/10-file-upload.md) + +- 2022.09.04,增加[留言区](/other/leave-a-message.md),[网易面经汇总](/campus-recruit/interview/10-netease.md) + +- 2022.09.03,增加优质文章-[美团面试:熟悉哪些JVM调优参数?](/advance/excellent-article/9-jvm-optimize-param.md) + +- 2022.08.29,增加海量数据面试题-[如何在100亿数据中找到中位数?](/mass-data/4-find-mid-num.md),优质文章-[如何保证接口幂等性?](/advance/excellent-article/8-interface-idempotent.md) + +- 2022.08.22,增加框架中间件-[Kafka面试题](/message-queue/kafka.md)总结 + +- 2022.08.21,完善工具-[linux常用命令](/tools/linux/) + +- 2022.08.19,补充进阶之路-[海量数据场景题](/mass-data/),增加进阶之路-[优质文章汇总](/advance/excellent-article/) + +- 2022.08.18,增加秋招-[面经合集](/campus-recruit/interview/),包括阿里、腾讯、百度、字节跳动、京东等面经 + +- 2022.08.13,调整导航栏结构,将分布式、设计模式、系统设计、海量数据场景题移至进阶之路目录下 + +- 2022.08.08,网站改版,调整UI布局,导航栏增加图标等。 + + 改版后: + + ![](http://img.dabin-coder.cn/image/image-20220809084502495.png) + + 改版前: + + ![](http://img.dabin-coder.cn/image/image-20220801004446607.png) + +- 2022.08.07,完善设计模式、Docker、Git部分内容 + +- 2022.08.02,增加部分场景设计题目 + +- 2022.07.31,应粉丝要求,增加暗黑模式~很贴心有木有! + + ![](http://img.dabin-coder.cn/image/image-20220801004603404.png) + + ![](http://img.dabin-coder.cn/image/image-20220801004446607.png) + +- 2022.07.30,SEO优化,小破站被谷歌、百度等搜索引擎收录啦! + + ![](http://img.dabin-coder.cn/image/image-20220801003633682.png) + +- 2022.07.29,增加工具-[Nginx面试题](https://mp.weixin.qq.com/s/SKKEeYxif0wWJo6n57rd6A) + +- 2022.07.26,完善计算机网络面试题部分 + +- 2022.07.24,增加编程内容-[设计模式](/advance/design-pattern/),工具-Git/Maven详解 + +- 2022.07.23,整理[力扣算法题目](/computer-basic/algorithm.md) + +- 2022.07.20,修复小伙伴通过微信、评论留言等渠道提出的bug + +- 2022.07.18,增加ElasticSearch面试题 + +- 2022.07.16,整理数据库相关面试题 + +- 2022.07.13,增加**分布式**相关内容,包括分布式事务、分布式锁、微服务等 + +- 2022.07.10,增加学习资源,包括面试手册、算法手册 + +- 2022.07.08,整理**计算机基础**内容,包括操作系统、计算机网络、数据结构与算法等 + +- 2022.07.06,7月6号正式上线,**首日上线PV过万**! + +- 2022.07.01-2022.07.06,网站搭建,整理大彬在公众号、知乎等平台发表的文章 diff --git a/docs/practice/service-performance-optimization.md b/docs/practice/service-performance-optimization.md new file mode 100644 index 0000000..68ba334 --- /dev/null +++ b/docs/practice/service-performance-optimization.md @@ -0,0 +1,25 @@ +## 线上接口很慢怎么办? + +首先需要明确一个问题,是只有**一个接口**变慢,还是**多个接口**变慢。 + +如果系统中有多个服务的接口都变慢,那可能是**系统共用的资源不足**导致的。比如数据库连接数太多、数据库有大量慢查询、共同依赖的下游服务性能问题等。 + +可以查看系统中调用量突然增多的服务,它的调用量是否导致数据库的并发达到了瓶颈,是不是共同调用的下游服务出现了性能问题,数据库中是不是有大量这个服务引起的慢查询等。 + +可以有以下针对性优化: + +- 如果数据库并发达到瓶颈,可以考虑用**读写分离、分库分表、加读缓存**等方式来解决 +- 如果下游接口出现性能问题,需要通知下游服务做优化,同时要加**降级开关** +- 如果数据库中有大量慢查询,需要**优化sql**或**加索引**等 + +如果是只有一个服务的接口变慢,那就要针对这个服务做分析,查看它的cpu占用率和gc频率是不是异常,做针对性的优化。 + +1. 比如在循环里获取远程数据,可以改成只调用一次,**批量获取数据** +2. 比如在链路中多次调用同一个远程接口获取相同数据,可以第一次调用之后就把数据**缓存**起来,后续直接从缓存中获取 +3. 比如如果多个比较耗时的操作是串行执行的,但它们又没有依赖关系,就可以把串行改成**并行**,可以用countDownLatch +4. 还有如果实在无法再缩短请求处理耗时的话,也可以考虑从产品逻辑上进行优化,比如把原来的同步请求改为**异步**的,前端再去轮询请求处理结果 +5. 比如为了得到一个复杂的model,需要调多个接口获取信息,但当前接口只需要其中部分比较简单的数据,那么需要根据实际情况,**重新写**一个简单model的获取方法 + + + +> 参考链接:https://juejin.cn/post/7064140627578978334 \ No newline at end of file diff --git "a/Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" b/docs/redis/redis-basic-all.md similarity index 100% rename from "Redis/Redis\345\205\245\351\227\250\346\214\207\345\215\227\346\200\273\347\273\223.md" rename to docs/redis/redis-basic-all.md diff --git a/docs/redis/redis-basic/1-introduce.md b/docs/redis/redis-basic/1-introduce.md new file mode 100644 index 0000000..a1aa20f --- /dev/null +++ b/docs/redis/redis-basic/1-introduce.md @@ -0,0 +1,36 @@ +# 简介 + +Redis是一个高性能的key-value数据库。Redis对数据的操作都是原子性的。 + +## 优缺点 + +优点: + +1. 基于内存操作,内存读写速度快。 +2. Redis是单线程的,避免线程切换开销及多线程的竞争问题。单线程是指在处理网络请求(一个或多个redis客户端连接)的时候只有一个线程来处理,redis运行时不止有一个线程,数据持久化或者向slave同步aof时会另起线程。 +3. 支持多种数据类型,包括String、Hash、List、Set、ZSet等 +4. 支持持久化。Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免数据丢失问题。 +5. redis 采用IO多路复用技术。多路指的是多个socket连接,复用指的是复用一个线程。redis使用单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件。多路复用主要有三种技术:select,poll,epoll。epoll是最新的也是目前最好的多路复用技术。 + +缺点:对join或其他结构化查询的支持就比较差。 + +## io多路复用 + +将用户socket对应的文件描述符(file description)注册进epoll,然后epoll帮你监听哪些socket上有消息到达。当某个socket可读或者可写的时候,它可以给你一个通知。只有当系统通知哪个描述符可读了,才去执行read操作,可以保证每次read都能读到有效数据。这样,多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这就叫I/O多路复用,这里的复用指的是复用同一个线程。 + +## 应用场景 + +1. 缓存热点数据,缓解数据库的压力。 +2. 利用Redis中原子性的自增操作,可以用使用实现计算器的功能,比如统计用户点赞数、用户访问数等,这类操作如果用MySQL,频繁的读写会带来相当大的压力。 +3. 简单消息队列,不要求高可靠的情况下,可以使用Redis自身的发布/订阅模式或者List来实现一个队列,实现异步操作。 +4. 好友关系,利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同爱好之类的功能。 +5. 限速器,比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力。 + +## Memcached和Redis的区别 + +1. Redis只使用单核,而Memcached可以使用多核。 +2. MemCached数据结构单一,仅用来缓存数据,而Redis支持更加丰富的数据类型,也可以在服务器端直接对数据进行丰富的操作,这样可以减少网络IO次数和数据体积。 +3. MemCached不支持数据持久化,断电或重启后数据消失。Redis支持数据持久化和数据恢复,允许单点故障。 + + + diff --git a/docs/redis/redis-basic/10-lua.md b/docs/redis/redis-basic/10-lua.md new file mode 100644 index 0000000..f88539f --- /dev/null +++ b/docs/redis/redis-basic/10-lua.md @@ -0,0 +1,70 @@ +# LUA脚本 + +Redis 通过 LUA 脚本创建具有原子性的命令: 当lua脚本命令正在运行的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。 + +在Redis中执行Lua脚本有两种方法:eval和evalsha。 + +eval 命令使用内置的 Lua 解释器,对 Lua 脚本进行求值。 + +``` +//第一个参数是lua脚本,第二个参数是键名参数个数,剩下的是键名参数和附加参数 +> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second +1) "key1" +2) "key2" +3) "first" +4) "second" +``` + +## evalsha + +Redis还提供了evalsha命令来执行Lua脚本。首先要将Lua脚本加载到Redis服务端,得到该脚本的SHA1校验和。Evalsha 命令根据给定的 sha1 校验和,执行缓存在服务器中的脚本。 + +script load命令可以将脚本内容加载到Redis内存中。 + +``` +redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'" +"232fd51614574cf0867b83d384a5e898cfd24e5a" + +redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 +"hello moto" +``` + +使用evalsha执行Lua脚本过程如下: + +![](http://img.dabin-coder.cn/image/evalsha.png) + +## lua脚本作用 + +1、Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令。 + +2、Lua脚本可以将多条命令一次性打包,有效地减少网络开销。 + +## 应用场景 + +限制接口访问频率。 + +在Redis维护一个接口访问次数的键值对,key是接口名称,value是访问次数。每次访问接口时,会执行以下操作: + +- 通过aop拦截接口的请求,对接口请求进行计数,每次进来一个请求,相应的接口count加1,存入redis。 +- 如果是第一次请求,则会设置count=1,并设置过期时间。因为这里set()和expire()组合操作不是原子操作,所以引入lua脚本,实现原子操作,避免并发访问问题。 +- 如果给定时间范围内超过最大访问次数,则会抛出异常。 + +```java +private String buildLuaScript() { + return "local c" + + "\nc = redis.call('get',KEYS[1])" + + "\nif c and tonumber(c) > tonumber(ARGV[1]) then" + + "\nreturn c;" + + "\nend" + + "\nc = redis.call('incr',KEYS[1])" + + "\nif tonumber(c) == 1 then" + + "\nredis.call('expire',KEYS[1],ARGV[2])" + + "\nend" + + "\nreturn c;"; +} + +String luaScript = buildLuaScript(); +RedisScript redisScript = new DefaultRedisScript<>(luaScript, Number.class); +Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period()); +``` + diff --git a/docs/redis/redis-basic/11-deletion-policy.md b/docs/redis/redis-basic/11-deletion-policy.md new file mode 100644 index 0000000..d479872 --- /dev/null +++ b/docs/redis/redis-basic/11-deletion-policy.md @@ -0,0 +1,26 @@ +# 删除策略 + +1. 被动删除。在访问key时,如果发现key已经过期,那么会将key删除。 +2. 主动删除。定时清理key,每次清理会依次遍历所有DB,从db随机取出20个key,如果过期就删除,如果其中有5个key过期,那么就继续对这个db进行清理,否则开始清理下一个db。 + +3. 内存不够时清理。Redis有最大内存的限制,通过maxmemory参数可以设置最大内存,当使用的内存超过了设置的最大内存,就要进行内存释放, 在进行内存释放的时候,会按照配置的淘汰策略清理内存,淘汰策略一般有6种,Redis4.0版本后又增加了2种,主要由分为三类: + + - 第一类 不处理 noeviction。发现内存不够时,不删除key,执行写入命令时直接返回错误信息。(默认的配置) + + - 第二类 从所有结果集中的key中挑选,进行淘汰 + + - allkeys-random 就是从所有的key中随机挑选key,进行淘汰 + - allkeys-lru 就是从所有的key中挑选最近最少使用的数据淘汰 + - allkeys-lfu 就是从所有的key中挑选使用频率最低的key,进行淘汰。(这是Redis 4.0版本后新增的策略) + + - 第三类 从设置了过期时间的key中挑选,进行淘汰 + + 这种就是从设置了expires过期时间的结果集中选出一部分key淘汰,挑选的算法有: + + - volatile-random 从设置了过期时间的结果集中随机挑选key删除。 + - volatile-lru 从设置了过期时间的结果集中挑选最近最少使用的数据淘汰 + - volatile-ttl 从设置了过期时间的结果集中挑选可存活时间最短的key开始删除(也就是从哪些快要过期的key中先删除) + - volatile-lfu 从过期时间的结果集中选择使用频率最低的key开始删除(这是Redis 4.0版本后新增的策略) + + + diff --git a/docs/redis/redis-basic/12-others.md b/docs/redis/redis-basic/12-others.md new file mode 100644 index 0000000..c0c8069 --- /dev/null +++ b/docs/redis/redis-basic/12-others.md @@ -0,0 +1,81 @@ +# 其他 + +## 客户端 + +Redis 客户端与服务端之间的通信协议是在TCP协议之上构建的。 + +Redis Monitor 命令用于实时打印出 Redis 服务器接收到的命令,调试用。 + +``` +redis 127.0.0.1:6379> MONITOR +OK +1410855382.370791 [0 127.0.0.1:60581] "info" +1410855404.062722 [0 127.0.0.1:60581] "get" "a" +``` + +## 慢查询 + +Redis原生提供慢查询统计功能,执行`slowlog get{n}`命令可以获取最近的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令。慢查询队列长度默认128,可适当调大。 + +Redis客户端执行一条命令分为4个部分:发送命令;命令排队;命令执行;返回结果。慢查询只统计命令执行这一步的时间,所以没有慢查询并不代表客户端没有超时问题。 + +Redis提供了`slowlog-log-slower-than`(设置慢查询阈值,单位为微秒)和`slowlog-max-len`(慢查询队列大小)配置慢查询参数。 + +相关命令: + +``` +showlog get n //获取慢查询日志 +slowlog len //慢查询日志队列当前长度 +slowlog reset //重置,清理列表 +``` + +慢查询解决方案: + +1. 修改为低时间复杂度的命令,如hgetall改为hmget等,禁用keys、sort等命令。 +2. 调整大对象:缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操作过多的数据。 + +## pipeline + +redis客户端执行一条命令分4个过程: 发送命令-〉命令排队-〉命令执行-〉返回结果。使用Pipeline可以批量请求,批量返回结果,执行速度比逐条执行要快。 + +使用pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成。 + +原生批命令(mset, mget)与Pipeline对比: + +1. 原生批命令是原子性,pipeline是非原子性。pipeline命令中途异常退出,之前执行成功的命令不会回滚。 + +2. 原生批命令只有一个命令, 但pipeline支持多命令。 + +## 数据一致性 + +缓存和DB之间怎么保证数据一致性: +读操作:先读缓存,缓存没有的话读DB,然后取出数据放入缓存,最后响应数据 +写操作:先删除缓存,再更新DB +为什么是删除缓存而不是更新缓存呢? + +1. 线程安全问题。同时有请求A和请求B进行更新操作,那么会出现(1)线程A更新了缓存(2)线程B更新了缓存(3)线程B更新了数据库(4)线程A更新了数据库,由于网络等原因,请求B先更新数据库,这就导致缓存和数据库不一致的问题。 +2. 如果业务需求写数据库场景比较多,而读数据场景比较少,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。 +3. 如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。 + +先删除缓存,再更新DB,同样也有问题。假如A先删除了缓存,但还没更新DB,这时B过来请求数据,发现缓存没有,去请求DB拿到旧数据,然后再写到缓存,等A更新完了DB之后就会出现缓存和DB数据不一致的情况了。 + +解决方法:采用延时双删策略。更新完数据库之后,延时一段时间,再次删除缓存,确保可以删除读请求造成的缓存脏数据。评估项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百ms即可。 + +```java +public void write(String key,Object data){ + redis.delKey(key); + db.updateData(data); + Thread.sleep(1000);//确保读请求结束,写请求可以删除读请求造成的缓存脏数据 + redis.delKey(key); +} +``` + +可以将第二次删除作为异步的。自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后了,加大吞吐量。 + +当删缓存失败时,也会就出现数据不一致的情况。 + +解决方法: + +![](http://img.dabin-coder.cn/image/image-20210913235221410.png) + +> 图片来源:https://tech.it168.com diff --git a/docs/redis/redis-basic/2-data-type.md b/docs/redis/redis-basic/2-data-type.md new file mode 100644 index 0000000..1f2c31a --- /dev/null +++ b/docs/redis/redis-basic/2-data-type.md @@ -0,0 +1,318 @@ +# 数据类型 + +Redis支持五种数据类型: + +- string(字符串) +- hash(哈希) +- list(列表) +- set(集合) +- zset(sorted set) + +## 字符串类型 + +字符串类型的值可以是字符串、数字或者二进制,但值最大不能超过512MB。 + +常用命令:set, get, incr, incrby, desr, keys, append, strlen + +- 赋值和取值 + +``` +SET name tyson +GET name +``` + +- 递增数字 + +``` +INCR num //若键值不是整数时,则会提示错误。 +INCRBY num 2 //增加指定整数 +DESR num //递减数字 +INCRBY num 2.7 //增加指定浮点数 +``` + +- 其他 + +`keys list*` 列出匹配的key + +`APPEND name " dai"` 追加值 + +`STRLEN name` 获取字符串长度 + +`MSET name tyson gender male` 同时设置多个值 + +`MGET name gender` 同时获取多个值 + +`GETBIT name 0` 获取0索引处二进制位的值 + +`FLUSHDB` 删除当前数据库所有的key + +`FLUSHALL` 删除所有数据库中的key + +**SETNX和SETEX** + +`SETNX key value`:当key不存在时,将key的值设为value。若给定的key已经存在,则SETNX不做任何操作。 + +`SETEX key seconds value`:比SET多了seconds参数,相当于`SET KEY value` + `EXPIRE KEY seconds`,而且SETEX是原子性操作。 + +**keys和scan** + +redis的单线程的。keys指令会导致线程阻塞一段时间,直到执行完毕,服务才能恢复。scan采用渐进式遍历的方式来解决keys命令可能带来的阻塞问题,每次scan命令的时间复杂度是O(1),但是要真正实现keys的功能,需要执行多次scan。 + +scan的缺点:在scan的过程中如果有键的变化(增加、删除、修改),遍历过程可能会有以下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键。 + +scan命令用于迭代当前数据库中的数据库键:`SCAN cursor [MATCH pattern] [COUNT count]` + +``` +scan 0 match * count 10 //返回10个元素 +``` + +SCAN相关命令包括SSCAN 命令、HSCAN 命令和 ZSCAN 命令,分别用于集合、哈希键及有序集合。 + +**expire** + +``` +SET password 666 +EXPIRE password 5 +TTL password //查看键的剩余生存时间,-1为永不过期 +SETEX password 60 123abc //SETEX可以在设置键的同时设置它的生存时间 +``` + +EXPIRE时间单位是秒,PEXPIRE时间单位是毫秒。在键未过期前可以重新设置过期时间,过期之后则键被销毁。 + +在Redis 2.6和之前版本,如果key不存在或者已过期时返回`-1`。 + +从Redis2.8开始,错误返回值的结果有如下改变: + +- 如果key不存在或者已过期,返回 `-2` +- 如果key存在并且没有设置过期时间(永久有效),返回 `-1` 。 + +**type** + +TYPE 命令用于返回 key 所储存的值的类型。 + +``` +127.0.0.1:6379> type NEWBLOG +list +``` + +## 散列类型 + +常用命令:hset, hget, hmset, hmget, hgetall, hdel, hkeys, hvals + +- 赋值和取值 + +``` +HSET car price 500 //HSET key field value +HGET car price +``` + +同时设置获取多个字段的值 + +``` +HMSET car price 500 name BMW +HMGET car price name +HGETALL car +``` + +使用 HGETALL 命令时,如果哈希元素个数比较多,会存在阻塞Redis的可能。如果只需要获取部分field,可以使用hmget,如果一定要获取全部field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型。 + +`HSETNX car price 400 //当字段不存在时赋值,HSETNX是原子操作,不存在竞态条件` + +- 增加数字 + `HINCRBY person score 60` +- 删除字段 + `HDEL car price` +- 其他 + +``` +HKEYS car //获取key +HVALS car //获取value +HLEN car //长度 +``` + +## 列表类型 + +常用命令:lpush, rpush, lpop, rpop, lrange, lrem + +**添加和删除元素** + +``` +LPUSH numbers 1 +RPUSH numbers 2 3 +LPOP numbers +RPOP numbers +``` + +**获取列表片段** + +``` +LRANGE numbers 0 2 +LRANGE numbers -2 -1 //支持负索引 -1是最右边第一个元素 +LRANGE numbers 0 -1 +``` + +**向列表插入值** + +首先从左到右寻找值为pivot的值,向列表插入value + +``` +LINSERT numbers AFTER 5 8 //往5后面插入8 +LINSERT numbers BEFORE 6 9 //往6前面插入9 +``` + +**删除元素** + +`LTRIM numbers 1 2` 删除索引1到2以外的所有元素 + +LPUSH常和LTRIM一起使用来限制列表的元素个数,如保留最近的100条日志 + +``` +LPUSH logs $newLog +LTRIM logs 0 99 +``` + +**删除列表指定的值** + +`LREM key count value` + + 1. count < 0, 则从右边开始删除前count个值为value的元素 + 2. count > 0, 则从左边开始删除前count个值为value的元素 + 3. count = 0, 则删除所有值为value的元素 `LREM numbers 0 2` + +**其他** + +``` +LLEN numbers //获取列表元素个数 +LINDEX numbers -1 //返回指定索引的元素,index是负数则从右边开始计算 +LSET numbers 1 7 //把索引为1的元素的值赋值成7 +``` + +## 集合类型 + +常用命令:sadd, srem, smembers, scard, sismember, sdiff + +集合中不能有相同的元素。 + +**增加/删除元素** + +``` +SADD letters a b c +SREM letters c d +``` + +**获取元素** + +``` +SMEMBERS letters +SCARD letters //获取集合元素个数 +``` + +**判断元素是否在集合中** +`SISMEMBER letters a` + +**集合间的运算** + +``` +SDIFF setA setB //差集运算 +SINTER setA setB //交集运算 +SUNION setA setB //并集运算 +``` + +三个命令都可以传进多个键 `SDIFF setA setB setC` + +**其他** + +`SDIFFSTORE result setA setB` 进行集合运算并将结果存储 + +`SRANDMEMBER key count` + +>随机获取集合里的一个元素,count大于0,则从集合随机获取count个不重复的元素,count小于0,则随机获取的count个元素有些可能相同。 + +## 有序集合类型 + +常用命令:zadd, zrem, zscore, zrange + +```java +zadd zsetkey 50 e1 60 e2 30 e3 +``` + +Zset(sorted set)是string类型的有序集合。zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是Zset每个元素都会关联一个double(超过17位使用科学计算法表示,可能丢失精度)类型的分数,通过分数来为集合中的成员进行排序。zset的成员是唯一的,但分数(score)可以重复。 + +**有序集合和列表相同点:** + +1. 都是有序的; +2. 都可以获得某个范围内的元素。 + +**有序集合和列表不同点:** + +1. 列表基于链表实现,获取两端元素速度快,访问中间元素速度慢; +2. 有序集合基于散列表和跳跃表实现,访问中间元素时间复杂度是OlogN; +3. 列表不能简单的调整某个元素的位置,有序列表可以(更改元素的分数); +4. 有序集合更耗内存。 + +**增加/删除元素** + +时间复杂度OlogN。 + +``` +ZADD scoreboard 89 Tom 78 Sophia +ZADD scoreboard 85.5 Tyson //支持双精度浮点数 +ZREM scoreboard Tyson +ZREMRANGEBYRANK scoreboard 0 2 //按照排名范围删除元素 +ZREMRANGEBYSCORE scoreboard (80 100 //按照分数范围删除元素,"("代表不包含 +``` + +**获取元素分数** + +时间复杂度O1。 + +`ZSCORE scoreboard Tyson` + +**获取排名在某个范围的元素列表** + +ZRANGE命令时间复杂度是O(log(n)+m), n是有序集合元素个数,m是返回元素个数。 + +``` +ZRANGE scoreboard 0 2 +ZRANGE scoreboard 1 -1 //-1表示最后一个元素 +ZRANGE scoreboard 0 -1 WITHSCORES //同时获得分数 +``` + +**获取指定分数范围的元素** + +ZRANGEBYSCORE命令时间复杂度是O(log(n)+m), n是有序集合元素个数,m是返回元素个数。 + +``` +ZRANGEBYSCORE scoreboard 80 100 +ZRANGEBYSCORE scoreboard 80 (100 //不包含100 +ZRANGEBYSCORE scoreboard (60 +inf LIMIT 1 3 //获取分数高于60的从第二个人开始的3个人 +``` + +**增加某个元素的分数** + +时间复杂度OlogN。 + +`ZINCRBY scoreboard 10 Tyson` + +**其他** + +``` +ZCARD scoreboard //获取集合元素个数,时间复杂度O1 +ZCOUNT scoreboard 80 100 //指定分数范围的元素个数 +ZRANK scoreboard Tyson //按从小到大的顺序获取元素排名 +ZREVRANK scoreboard Tyson //按从大到小的顺序获取元素排名 +``` + +## Bitmaps + +Bitmaps本身不是一种数据结构,实际上它就是字符串,但是它可以对字符串的位进行操作,可以把Bitmaps想象成一个以位为单位的数组,数组的每个单元只能存储0和1。 + +bitmap的长度与集合中元素个数无关,而是与基数的上限有关。假如要计算上限为1亿的基数,则需要12.5M字节的bitmap。就算集合中只有10个元素也需要12.5M。 + +## HyperLogLog + +HyperLogLog 是用来做基数统计的算法,其优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。 + +基数:比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数即不重复元素为5。 + +应用场景:独立访客(unique visitor,uv)统计。 diff --git a/docs/redis/redis-basic/3-data-structure.md b/docs/redis/redis-basic/3-data-structure.md new file mode 100644 index 0000000..3cc6f88 --- /dev/null +++ b/docs/redis/redis-basic/3-data-structure.md @@ -0,0 +1,100 @@ +# 数据结构 + +## 动态字符串 + +SDS(simple dynamic string,SDS),简单动态字符串,其定义如下: + +```c +struct sdshdr { + + // 记录 buf 数组中已使用字节的数量 + // 等于 SDS 所保存字符串的长度 + int len; + + // 记录 buf 数组中未使用字节的数量 + int free; + + // 字节数组,用于保存字符串 + char buf[]; + +}; +``` + +在64位系统下,属性len和属性free各占4个字节,紧接着存放字节数组。 + +下面展示一个SDS示例: + +```c +set name "Redis" +``` + +![](http://img.dabin-coder.cn/image/sds.png) + +free属性的值为0,表示这个SDS没有分配任何未使用空间。 + +len属性的值为5,表示这个SDS保存了一个物字节长的字符串。 + +buf属性是一个char类型的数组,数组的前五个字节分别保存了'R'、'e'、'd'、'i'、's'五个字符,而最后一个字节则保存了空字符'\0'。 + +SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面,并且为空字符分配额外的1字节空间,以及添加空字符到字符串末尾等操作,都是由SDS函数自动完成的,所以这个空字符对于SDS的使用者来说是完全透明的。遵循空字符串结尾这一惯例的好处是,SDS可以直接重用一部分C字符串函数库里面的函数。 + +下面是SDS与C字符串的区别。 + +| C 字符串 | SDS | +| :--------------------------------------------------- | :--------------------------------------------------- | +| 获取字符串长度的复杂度为 O(N) 。 | 获取字符串长度的复杂度为 O(1) 。 | +| API 是不安全的,可能会造成缓冲区溢出。 | API 是安全的,不会造成缓冲区溢出。 | +| 修改字符串长度 `N` 次必然需要执行 `N` 次内存重分配。 | 修改字符串长度 `N` 次最多需要执行 `N` 次内存重分配。 | +| 只能保存文本数据。 | 可以保存文本或者二进制数据。 | +| 可以使用所有 `` 库中的函数。 | 可以使用一部分 `` 库中的函数。 | + +## 字典 + +字典使用hashtable作为底层实现。键值对的值可以是一个指针, 或者是一个 uint64_t 整数, 又或者是一个 int64_t 整数。 + +```c +typedef struct dictEntry { + + // 键 + void *key; + + // 值 + union { + void *val; + uint64_t u64; + int64_t s64; + } v; + + // 指向下个哈希表节点,形成链表 + struct dictEntry *next; + +} dictEntry; +``` + +## 整数集合 + +整数集合(intset)是 Redis 用于保存整数值的集合抽象数据结构, 它可以保存类型为 int16_t 、 int32_t 或者 int64_t 的整数值, 并且保证集合中不会出现重复元素。 + +## 压缩列表 + +ziplist是 Redis 为了节约内存而开发的, 由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结构。每个压缩列表节点都由 previous_entry_length 、 encoding 、 content 三个部分组成。 + +节点的 previous_entry_length 属性以字节为单位, 记录了压缩列表中前一个节点的长度。 +节点的 encoding 属性记录了节点的 content 属性所保存数据的类型以及长度。有两种编码方式,字节数组编码和整数编码。 + +压缩列表的从表尾向表头遍历操作就是使用这一原理实现的: 只要我们拥有了一个指向某个节点起始地址的指针, 那么通过这个指针以及这个节点的 previous_entry_length 属性, 程序就可以一直向前一个节点回溯, 最终到达压缩列表的表头节点。 + +## 跳表 + +跳表可以看成多层链表,它有如下的性质: + +- 多层的结构组成,每层是一个有序的链表 +- 最底层的链表包含所有的元素 +- 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入、删除也为 O(logn) + +![](http://img.dabin-coder.cn/image/redis-skiplist.png) + +## 对象 + +Redis 的对象系统还实现了基于引用计数技术的内存回收机制: 当程序不再使用某个对象的时候, 这个对象所占用的内存就会被自动释放; 另外, Redis 还通过引用计数技术实现了对象共享机制, 这一机制可以在适当的条件下, 通过让多个数据库键共享同一个对象来节约内存。 + diff --git a/docs/redis/redis-basic/4-implement.md b/docs/redis/redis-basic/4-implement.md new file mode 100644 index 0000000..fb53417 --- /dev/null +++ b/docs/redis/redis-basic/4-implement.md @@ -0,0 +1,68 @@ +# 底层实现 + +## string + +字符串对象的编码可以是 int 、 raw 或者 embstr 。 + +1. 如果一个字符串对象保存的是整数值, 并且这个整数值可以用 long 类型来表示, 那么会将编码设置为 int 。 +2. 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39 字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw 。 +3. 如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度小于等于 39 字节, 那么字符串对象将使用 embstr 编码的方式来保存这个字符串值。 + +| 值 | 编码 | +| :----------------------------------------------------------- | :------------------ | +| 可以用 `long` 类型保存的整数。 | `int` | +| 可以用 `long double` 类型保存的浮点数。 | `embstr` 或者 `raw` | +| 字符串值, 或者因为长度太大而没办法用 `long` 类型表示的整数, 又或者因为长度太大而没办法用 `long double` 类型表示的浮点数。 | `embstr` 或者 `raw` | + +## hash + +hash类型内部编码有两种: + +1. ziplist,压缩列表。当哈希类型元素个数小于512个,并且所有值都小于64字节时,Redis会使用ziplist作为哈希的内部实现。ziplist使用更加紧凑的结构实现多个元素的连续存储,更加节省内存。 +2. hashtable。当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。 + +使用 ziplist 作为 hash 的底层实现时,添加元素的时候,同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后。 + +使用场景:记录博客点赞数量。`hset MAP_BLOG_LIKE_COUNT blogId likeCount`,key为MAP_BLOG_LIKE_COUNT,field为博客id,value为点赞数量。 + +## list + +列表list类型内部编码有两种: + +1. ziplist,压缩列表。当列表中的元素个数小于512个,同时列表中每个元素的值都小于64字节时,Redis会选用ziplist来作为列表的内部实现来减少内存的使用。 +2. 当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。 + +Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。 + +![](http://img.dabin-coder.cn/image/list-api.png) + +使用场景: + +1. 消息队列。Redis的lpush+brpop命令组合即可实现阻塞队列。 + +## set + +集合对象的编码可以是 intset 或者 hashtable 。 + +1. intset 编码的集合对象使用整数集合作为底层实现, 集合对象包含的所有元素都被保存在整数集合(数组)里面。 +2. hashtable 编码的集合对象使用字典作为底层实现, 字典的每个键都是一个字符串对象, 而字典的值则全部被设置为 NULL 。 + +## zset + +有序集合的编码可以是 ziplist 或者 skiplist 。当有序集合的元素个数小于128,同时每个元素的值都小于64字节时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。否则,使用skiplist作为有序集合的内部实现。 + +1. ziplist 编码的有序集合对象使用压缩列表作为底层实现, 每个集合元素使用两个紧挨在一起的压缩列表节点来保存, 第一个节点保存元素的成员(member), 而第二个元素则保存元素的分值(score)。压缩列表内的集合元素按分值从小到大进行排序。 +2. skiplist 编码的有序集合对象使用字典和跳跃表实现。使用字典查找给定成员的分值,时间复杂度为O(1) (跳跃表查找时间复杂度为O(logN))。使用跳跃表可以对有序集合进行范围型操作。 + +## 使用场景 + +string:1、常规key-value缓存应用。常规计数如微博数、粉丝数。2、分布式锁。 + +hash:存放结构化数据,如用户信息(昵称、年龄、性别、积分等)。 + +list:热门博客列表、消息队列系统。使用list可以构建队列系统,比如:将Redis用作日志收集器,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。 + +set:1、好友关系,微博粉丝的共同关注、共同喜好、共同好友等;2、利用唯一性,统计访问网站的所有独立ip 。 + +zset:1、排行榜;2、优先级队列。 + diff --git a/docs/redis/redis-basic/5-sort.md b/docs/redis/redis-basic/5-sort.md new file mode 100644 index 0000000..75969b2 --- /dev/null +++ b/docs/redis/redis-basic/5-sort.md @@ -0,0 +1,36 @@ +# 排序 + +``` +LPUSH myList 4 8 2 3 6 +SORT myList DESC +``` + +``` +LPUSH letters f l d n c +SORT letters ALPHA +``` + +**BY参数** + +``` +LPUSH list1 1 2 3 +SET score:1 50 +SET score:2 100 +SET score:3 10 +SORT list1 BY score:* DESC +``` + +**GET参数** + +GET参数命令作用是使SORT命令的返回结果是GET参数指定的键值。 + +`SORT tag:Java:posts BY post:*->time DESC GET post:*->title GET post:*->time GET #` + +GET #返回文章ID。 + +**STORE参数** + +`SORT tag:Java:posts BY post:*->time DESC GET post:*->title STORE resultCache` + +`EXPIRE resultCache 10 //STORE结合EXPIRE可以缓存排序结果` + diff --git a/docs/redis/redis-basic/6-transaction.md b/docs/redis/redis-basic/6-transaction.md new file mode 100644 index 0000000..6f099d4 --- /dev/null +++ b/docs/redis/redis-basic/6-transaction.md @@ -0,0 +1,61 @@ +# 事务 + +事务的原理是将一个事务范围内的若干命令发送给Redis,然后再让Redis依次执行这些命令。 + +事务的生命周期: + +1. 使用MULTI开启一个事务 +2. 在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行 + +3. EXEC命令进行提交事务 + +![](http://img.dabin-coder.cn/image/redis-multi.jpg) + +DISCARD:放弃事务,即该事务内的所有命令都将取消 + +一个事务范围内某个命令出错不会影响其他命令的执行,不保证原子性: + +``` +127.0.0.1:6379> multi +OK +127.0.0.1:6379> set a 1 +QUEUED +127.0.0.1:6379> set b 1 2 +QUEUED +127.0.0.1:6379> set c 3 +QUEUED +127.0.0.1:6379> exec +1) OK +2) (error) ERR syntax error +3) OK +``` + +事务里的命令执行时会读取最新的值: + +![](http://img.dabin-coder.cn/image/redis-transaction.png) + +## WATCH命令 + +WATCH命令可以监控一个或多个键,一旦其中有一个键被修改,之后的事务就不会执行(类似于乐观锁)。执行EXEC命令之后,就会自动取消监控。 + +``` +127.0.0.1:6379> watch name +OK +127.0.0.1:6379> set name 1 +OK +127.0.0.1:6379> multi +OK +127.0.0.1:6379> set name 2 +QUEUED +127.0.0.1:6379> set gender 1 +QUEUED +127.0.0.1:6379> exec +(nil) +127.0.0.1:6379> get gender +(nil) +``` + +UNWATCH:取消WATCH命令对多有key的监控,所有监控锁将会被取消。 + + + diff --git a/docs/redis/redis-basic/7-message-queue.md b/docs/redis/redis-basic/7-message-queue.md new file mode 100644 index 0000000..aa10a6b --- /dev/null +++ b/docs/redis/redis-basic/7-message-queue.md @@ -0,0 +1,31 @@ +# 消息队列 + +使用一个列表,让生产者将任务使用LPUSH命令放进列表,消费者不断用RPOP从列表取出任务。 + +BRPOP和RPOP命令相似,唯一的区别就是当列表没有元素时BRPOP命令会一直阻塞连接,直到有新元素加入。 +`BRPOP queue 0 //0表示不限制等待时间` + +## 优先级队列 + +`BLPOP queue:1 queue:2 queue:3 0` +如果多个键都有元素,则按照从左到右的顺序取元素 + +## 发布/订阅模式 + +``` +PUBLISH channel1 hi +SUBSCRIBE channel1 +UNSUBSCRIBE channel1 //退订通过SUBSCRIBE命令订阅的频道。 +``` + +`PSUBSCRIBE channel?*` 按照规则订阅 +`PUNSUBSCRIBE channel?*` 退订通过PSUBSCRIBE命令按照某种规则订阅的频道。其中订阅规则要进行严格的字符串匹配,`PUNSUBSCRIBE *`无法退订`channel?*`规则。 + +缺点:在消费者下线的情况下,生产的消息会丢失。 + +## 延时队列 + +使用sortedset,拿时间戳作为score,消息内容作为key,调用zadd来生产消息,消费者用`zrangebyscore`指令获取N秒之前的数据轮询进行处理。 + + + diff --git a/docs/redis/redis-basic/8-persistence.md b/docs/redis/redis-basic/8-persistence.md new file mode 100644 index 0000000..f109548 --- /dev/null +++ b/docs/redis/redis-basic/8-persistence.md @@ -0,0 +1,67 @@ +# 持久化 + +Redis支持两种方式的持久化,一种是RDB的方式,一种是AOF的方式。前者会根据指定的规则定时将内存中的数据存储在硬盘上,而后者在每次执行完命令后将命令记录下来。一般将两者结合使用。 + +## RDB方式 + +RDB 是 Redis 默认的持久化方案。RDB持久化时会将内存中的数据写入到磁盘中,在指定目录下生成一个dump.rdb文件。Redis 重启会加载dump.rdb文件恢复数据。 + +RDB持久化的过程(执行SAVE命令除外): + +- 创建一个子进程; +- 父进程继续接收并处理客户端的请求,而子进程开始将内存中的数据写进硬盘的临时文件; +- 当子进程写完所有数据后会用该临时文件替换旧的RDB文件。 + +Redis启动时会读取RDB快照文件,将数据从硬盘载入内存。通过RDB方式的持久化,一旦Redis异常退出,就会丢失最近一次持久化以后更改的数据。 + +触发RDB快照: + +1. 手动触发: + - 用户执行SAVE或BGSAVE命令。SAVE命令执行快照的过程会阻塞所有来自客户端的请求,应避免在生产环境使用这个命令。BGSAVE命令可以在后台异步进行快照操作,快照的同时服务器还可以继续响应客户端的请求,因此需要手动执行快照时推荐使用BGSAVE命令; + +2. 被动触发: + - 根据配置规则进行自动快照,如`SAVE 300 10`,300秒内至少有10个键被修改则进行快照。 + - 如果从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点。 + - 默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave。 + - 执行debug reload命令重新加载Redis时,也会自动触发save操作。 + +优点:Redis加载RDB恢复数据远远快于AOF的方式。 + +缺点: + +1. RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。 +2. 存在老版本Redis服务和新版本RDB格式兼容性问题。RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。 + +## AOF方式 + +AOF(append only file)持久化:以独立日志的方式记录每次写命令,Redis重启时会重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是**解决了数据持久化的实时性**,目前已经是Redis持久化的主流方式。 + +默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数启用`appendonly yes`。开启AOF方式持久化后每执行一条写命令,Redis就会将该命令写进aof_buf缓冲区,AOF缓冲区根据对应的策略向硬盘做同步操作。 + +默认情况下系统每30秒会执行一次同步操作。为了防止缓冲区数据丢失,可以在Redis写入AOF文件后主动要求系统将缓冲区数据同步到硬盘上。可以通过`appendfsync`参数设置同步的时机。 + +``` +appendfsync always //每次写入aof文件都会执行同步,最安全最慢,只能支持几百TPS写入,不建议配置 +appendfsync everysec //保证了性能也保证了安全,建议配置 +appendfsync no //由操作系统决定何时进行同步操作 +``` + +重写机制: + +随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。 + +优点: +(1)AOF可以更好的保护数据不丢失,一般AOF会每秒去执行一次fsync操作,如果redis进程挂掉,最多丢失1秒的数据。 +(2)AOF以appen-only的模式写入,所以没有任何磁盘寻址的开销,写入性能非常高。 +缺点 +(1)对于同一份文件AOF文件比RDB数据快照要大。 +(2)不适合写多读少场景。 +(3)数据恢复比较慢。 + +RDB和AOF如何选择 +(1)仅使用RDB这样会丢失很多数据。 +(2)仅使用AOF,因为这一会有两个问题,第一通过AOF恢复速度慢;第二RDB每次简单粗暴生成数据快照,更加安全健壮。 +(3)综合AOF和RDB两种持久化方式,用AOF来保证数据不丢失,作为恢复数据的第一选择;用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,可以使用RDB进行快速的数据恢复。 + + + diff --git a/docs/redis/redis-basic/9-cluster.md b/docs/redis/redis-basic/9-cluster.md new file mode 100644 index 0000000..1bbf7c7 --- /dev/null +++ b/docs/redis/redis-basic/9-cluster.md @@ -0,0 +1,121 @@ +# 集群 + +## 主从复制 + +redis的复制功能是支持多个数据库之间的数据同步。主数据库可以进行读写操作,当主数据库的数据发生变化时会自动将数据同步到从数据库。从数据库一般是只读的,它会接收主数据库同步过来的数据。一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。 + +``` +redis-server //启动Redis实例作为主数据库 +redis-server --port 6380 --slaveof 127.0.0.1 6379 //启动另一个实例作为从数据库 +slaveof 127.0.0.1 6379 +SLAVEOF NO ONE //停止接收其他数据库的同步并转化为主数据库。 +``` + +### 同步机制 + +1. 保存主节点信息。 +2. 主从建立socket连接。 +3. 从节点发送ping命令进行首次通信,主要用于检测网络状态。 +4. 权限认证。如果主节点设置了requirepass参数,则需要密码认证。从节点必须配置masterauth参数保证与主节点相同的密码才能通过验证。 +5. 同步数据集。第一次同步的时候,从数据库启动后会向主数据库发送SYNC命令。主数据库接收到命令后开始在后台保存快照(RDB持久化过程),并将保存快照过程接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发送到从数据库。从数据库接收到后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。 +6. 复制初始化完成后,主数据库每次收到写命令就会将命令同步给从数据库,从而实现主从数据库数据的一致性。 + +![](http://img.dabin-coder.cn/image/redis-replication.png) + +Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。 + +全量复制:一般用于初次复制场景,Redis早期支持的复制功能只有全量复制,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。 + +部分复制:用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点。因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销。 + +### 读写分离 + +通过redis的复制功能可以实现数据库的读写分离,提高服务器的负载能力。主数据库主要进行写操作,而从数据库负责读操作。很多场景下对数据库的读频率大于写,当单机的Redis无法应付大量的读请求时,可以通过复制功能建立多个从数据库节点,主数据库负责写操作,从数据库负责读操作。这种一主多从的结构很适合读多写少的场景。 + +### 从数据库持久化 + +持久化的操作比较耗时,为了提高性能,可以建立一个从数据库,并在从数据库进行持久化,同时在主数据库禁用持久化。 + +## 哨兵Sentinel + +当master节点奔溃时,可以手动将slave提升为master,继续提供服务。 + +- 首先,从数据库使用`SLAVE NO ONE`将从数据库提升为主数据库继续服务; +- 启动奔溃的主数据库,通过`SLAVEOF`命令将其设置为新的主数据库的从数据库,即可将数据同步过来。 + +通过哨兵机制可以自动切换主从节点。哨兵是一个独立的进程,用于监控redis实例的是否正常运行。 + +### 作用 + +1. 监测redis实例的状态 +2. 如果master实例异常,会自动进行主从节点切换 + +客户端连接redis的时候,先连接哨兵,哨兵会告诉客户端redis主节点的地址,然后客户端连接上redis并进行后续的操作。当主节点宕机的时候,哨兵监测到主节点宕机,会重新推选出某个表现良好的从节点成为新的主节点,然后通过发布订阅模式通知其他的从服务器,让它们切换主机。 + +### 定时任务 + +1. 每隔10s,每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构。 +2. 每隔2s,每个Sentinel节点会去获取其他Sentinel节点对于主节点的判断以及当前Sentinel节点的信息,用于判断主节点是否客观下线和是否有新的Sentinel节点加入。 +3. 每隔1s,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,来确认这些节点是否可达。 + +### 工作原理 + +- 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。 +- 如果一个实例距离最后一次有效回复 PING 命令的时间超过指定的值, 则这个实例会被 Sentinel 标记为主观下线。 +- 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master是否真正进入主观下线状态。 +- 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 。若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。 +- 哨兵节点会选举出哨兵领导者,负责故障转移的工作。 +- 哨兵领导者会推选出某个表现良好的从节点成为新的主节点,然后通知其他从节点更新主节点。 + +```java +/** + * 测试Redis哨兵模式 + * @author liu + */ +public class TestSentinels { + @SuppressWarnings("resource") + @Test + public void testSentinel() { + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + jedisPoolConfig.setMaxTotal(10); + jedisPoolConfig.setMaxIdle(5); + jedisPoolConfig.setMinIdle(5); + // 哨兵信息 + Set sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379", + "192.168.11.129:26379","192.168.11.130:26379")); + // 创建连接池 + JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456"); + // 获取客户端 + Jedis jedis = pool.getResource(); + // 执行两个命令 + jedis.set("mykey", "myvalue"); + String value = jedis.get("mykey"); + System.out.println(value); + } +} +``` + +## cluster + +集群用于分担写入压力,主从用于灾难备份和高可用以及分担读压力。 + +主从复制存在不能自动故障转移、达不到高可用的问题。 +哨兵模式解决了主从复制不能自动故障转移、达不到高可用的问题,但还是存在主节点的写能力、容量受限于单机配置的问题。 +cluster模式实现了Redis的分布式存储,每个节点存储不同的内容,解决主节点的写能力、容量受限于单机配置的问题。 + +### 哈希分区算法 + +节点取余分区。使用特定的数据,如Redis的键或用户ID,对节点数量N取余:hash(key)%N计算出哈希值,用来决定数据映射到哪一个节点上。 +优点是简单性。扩容时通常采用翻倍扩容,避免数据映射全部被打乱导致全量迁移的情况。 + +一致性哈希分区:为系统中每个节点分配一个token,范围一般在0~232,这些token构成一个哈希环。数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点。 +这种方式相比节点取余最大的好处在于加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响。 + +Redis Cluser采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(key)&16383。每一个节点负责维护一部分槽以及槽所映射的键值数据。 + +### 故障转移 + +Redis集群内节点通过ping/pong消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。因此故障发现也是通过消息传播机制实现的,主要环节包括:主观下线(pfail)和客观下线(fail)。 + + + diff --git a/docs/redis/redis-basic/README.md b/docs/redis/redis-basic/README.md new file mode 100644 index 0000000..6a9d345 --- /dev/null +++ b/docs/redis/redis-basic/README.md @@ -0,0 +1,26 @@ +--- +title: Redis基础 +icon: redis +date: 2022-08-06 +category: redis +star: true +--- + +**本专栏是大彬学习MySQL基础知识的学习笔记,如有错误,可以在评论区指出**~ + +![](http://img.dabin-coder.cn/image/Redis知识点.jpg) + +## Redis总结 + +- [简介](./1-introduce.md) +- [数据类型](./2-data-type.md) +- [数据结构](./3-data-structure.md) +- [底层实现](./4-implement.md) +- [排序](./5-sort.md) +- [事务](./6-transaction.md) +- [消息队列](./7-message-queue.md) +- [持久化](./8-persistence.md) +- [集群](./9-cluster.md) +- [LUA脚本](./10-lua.md) +- [删除策略](./11-deletion-policy.md) +- [其他](./12-others.md) diff --git "a/Redis/Redis\351\235\242\350\257\225\351\242\230.md" b/docs/redis/redis.md similarity index 85% rename from "Redis/Redis\351\235\242\350\257\225\351\242\230.md" rename to docs/redis/redis.md index b9a05f4..3e88fb1 100644 --- "a/Redis/Redis\351\235\242\350\257\225\351\242\230.md" +++ b/docs/redis/redis.md @@ -1,3 +1,9 @@ +--- +sidebar: heading +--- + +![](http://img.dabin-coder.cn/image/Redis知识点.jpg) + ## Redis是什么? Redis(`Remote Dictionary Server`)是一个使用 C 语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis 的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。 @@ -38,9 +44,10 @@ Redis基于Reactor模式开发了网络事件处理器,这个处理器被称 1. **缓存热点数据**,缓解数据库的压力。 2. 利用 Redis 原子性的自增操作,可以实现**计数器**的功能,比如统计用户点赞数、用户访问数等。 -3. **简单的消息队列**,可以使用Redis自身的发布/订阅模式或者List来实现简单的消息队列,实现异步操作。 -4. **限速器**,可用于限制某个用户访问某个接口的频率,比如秒杀场景用于防止用户快速点击带来不必要的压力。 -5. **好友关系**,利用集合的一些命令,比如交集、并集、差集等,实现共同好友、共同爱好之类的功能。 +3. **分布式锁**。在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。 +4. **简单的消息队列**,可以使用Redis自身的发布/订阅模式或者List来实现简单的消息队列,实现异步操作。 +5. **限速器**,可用于限制某个用户访问某个接口的频率,比如秒杀场景用于防止用户快速点击带来不必要的压力。 +6. **好友关系**,利用集合的一些命令,比如交集、并集、差集等,实现共同好友、共同爱好之类的功能。 ## Memcached和Redis的区别? @@ -185,7 +192,7 @@ Redis单条命令是原子性执行的,但事务不保证原子性,且没有 Redis支持两种方式的持久化,一种是`RDB`的方式,一种是`AOF`的方式。**前者会根据指定的规则定时将内存中的数据存储在硬盘上**,而**后者在每次执行完命令后将命令记录下来**。一般将两者结合使用。 -### RDB方式 +**RDB方式** `RDB`是 Redis 默认的持久化方案。RDB持久化时会将内存中的数据写入到磁盘中,在指定目录下生成一个`dump.rdb`文件。Redis 重启会加载`dump.rdb`文件恢复数据。 @@ -220,7 +227,7 @@ Redis启动时会读取RDB快照文件,将数据从硬盘载入内存。通过 1. **RDB方式数据无法做到实时持久化**。因为`BGSAVE`每次运行都要执行`fork`操作创建子进程,属于重量级操作,频繁执行成本比较高。 2. RDB 文件使用特定二进制格式保存,Redis 版本升级过程中有多个格式的 RDB 版本,**存在老版本 Redis 无法兼容新版 RDB 格式的问题**。 -### AOF方式 +**AOF方式** AOF(append only file)持久化:以独立日志的方式记录每次写命令,Redis重启时会重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是**解决了数据持久化的实时性**,AOF 是Redis持久化的主流方式。 @@ -253,7 +260,7 @@ appendfsync no //由操作系统决定何时进行同步操作 1. 对于同一份文件AOF文件比RDB数据快照要大。 2. 数据恢复比较慢。 -### RDB和AOF如何选择? +## RDB和AOF如何选择? 通常来说,应该同时使用两种持久化方案,以保证数据安全。 @@ -605,6 +612,65 @@ Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式 5. Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。 6. 为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。 +## 说说为什么Redis过期了为什么内存没释放? + +第一种情况,可能是覆盖之前的key,导致key过期时间发生了改变。 + +当一个key在Redis中已经存在了,但是由于一些误操作使得key过期时间发生了改变,从而导致这个key在应该过期的时间内并没有过期,从而造成内存的占用。 + +第二种情况是,Redis过期key的处理策略导致内存没释放。 + +一般Redis对过期key的处理策略有两种:惰性删除和定时删除。 + +先说惰性删除的情况 + +当一个key已经确定设置了xx秒过期同时中间也没有修改它,xx秒之后它确实已经过期了,但是惰性删除的策略它并不会马上删除这个key,而是当再次读写这个key时它才会去检查是否过期,如果过期了就会删除这个key。也就是说,惰性删除策略下,就算key过期了,也不会立刻释放内容,要等到下一次读写这个key才会删除key。 + +而定时删除会在一定时间内主动淘汰一部分已经过期的数据,默认的时间是每100ms过期一次。因为定时删除策略每次只会淘汰一部分过期key,而不是所有的过期key,如果redis中数据比较多的话要是一次性全量删除对服务器的压力比较大,每一次只挑一批进行删除,所以很可能出现部分已经过期的key并没有及时的被清理掉,从而导致内存没有即时被释放。 + +## Redis突然变慢,有哪些原因? + +1. **存在bigkey**。如果Redis实例中存储了 bigkey,那么在淘汰删除 bigkey 释放内存时,也会耗时比较久。应该避免存储 bigkey,降低释放内存的耗时。 + +2. 如果Redis 实例**设置了内存上限 maxmemory**,有可能导致 Redis 变慢。当 Redis 内存达到 maxmemory 后,每次写入新的数据之前,Redis 必须先从实例中踢出一部分数据,让整个实例的内存维持在 maxmemory 之下,然后才能把新数据写进来。 + +3. **开启了内存大页**。当 Redis 在执行后台 RDB 和 AOF rewrite 时,采用 fork 子进程的方式来处理。但主进程 fork 子进程后,此时的主进程依旧是可以接收写请求的,而进来的写请求,会采用 Copy On Write(写时复制)的方式操作内存数据。 + + 什么是写时复制? + + 这样做的好处是,父进程有任何写操作,并不会影响子进程的数据持久化。 + + 不过,主进程在拷贝内存数据时,会涉及到新内存的申请,如果此时操作系统开启了内存大页,那么在此期间,客户端即便只修改 10B 的数据,Redis 在申请内存时也会以 2MB 为单位向操作系统申请,申请内存的耗时变长,进而导致每个写请求的延迟增加,影响到 Redis 性能。 + + 解决方案就是关闭内存大页机制。 + +4. **使用了Swap**。操作系统为了缓解内存不足对应用程序的影响,允许把一部分内存中的数据换到磁盘上,以达到应用程序对内存使用的缓冲,这些内存数据被换到磁盘上的区域,就是 Swap。当内存中的数据被换到磁盘上后,Redis 再访问这些数据时,就需要从磁盘上读取,访问磁盘的速度要比访问内存慢几百倍。尤其是针对 Redis 这种对性能要求极高、性能极其敏感的数据库来说,这个操作延时是无法接受的。解决方案就是增加机器的内存,让 Redis 有足够的内存可以使用。或者整理内存空间,释放出足够的内存供 Redis 使用 + +5. **网络带宽过载**。网络带宽过载的情况下,服务器在 TCP 层和网络层就会出现数据包发送延迟、丢包等情况。Redis 的高性能,除了操作内存之外,就在于网络 IO 了,如果网络 IO 存在瓶颈,那么也会严重影响 Redis 的性能。解决方案:1、及时确认占满网络带宽 Redis 实例,如果属于正常的业务访问,那就需要及时扩容或迁移实例了,避免因为这个实例流量过大,影响这个机器的其他实例。2、运维层面,需要对 Redis 机器的各项指标增加监控,包括网络流量,在网络流量达到一定阈值时提前报警,及时确认和扩容。 + +6. **频繁短连接**。频繁的短连接会导致 Redis 大量时间耗费在连接的建立和释放上,TCP 的三次握手和四次挥手同样也会增加访问延迟。应用应该使用长连接操作 Redis,避免频繁的短连接。 + +## 为什么 Redis 集群的最大槽数是 16384 个? + +Redis Cluster 采用数据分片机制,定义了 16384个 Slot槽位,集群中的每个Redis 实例负责维护一部分槽以及槽所映射的键值数据。 + +Redis每个节点之间会定期发送ping/pong消息(心跳包包含了其他节点的数据),用于交换数据信息。 + +Redis集群的节点会按照以下规则发ping消息: + +- (1)每秒会随机选取5个节点,找出最久没有通信的节点发送ping消息 +- (2)每100毫秒都会扫描本地节点列表,如果发现节点最近一次接受pong消息的时间大于cluster-node-timeout/2 则立刻发送ping消息 + +心跳包的消息头里面有个myslots的char数组,是一个bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的。 + +接下来,解答为什么 Redis 集群的最大槽数是 16384 个,而不是65536 个。 + +1、如果采用 16384 个插槽,那么心跳包的消息头占用空间 2KB (16384/8);如果采用 65536 个插槽,那么心跳包的消息头占用空间 8KB (65536/8)。可见采用 65536 个插槽,**发送心跳信息的消息头达8k,比较浪费带宽**。 + +2、一般情况下一个Redis集群**不会有超过1000个master节点**,太多可能导致网络拥堵。 + +3、哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩。bitmap的填充率越低,**压缩率**越高。其中bitmap 填充率 = slots / N (N表示节点数)。所以,插槽数越低, 填充率会降低,压缩率会提高。 + ![](http://img.dabin-coder.cn/image/20220612101342.png) diff --git a/docs/resource/1-cs-books.md b/docs/resource/1-cs-books.md new file mode 100644 index 0000000..177692d --- /dev/null +++ b/docs/resource/1-cs-books.md @@ -0,0 +1,329 @@ +--- +sidebar: heading +--- + +

200本计算机经典书籍分享

+

+
+ 微信交流群 +公众号 +知乎 +牛客网 +掘金 +八股文 +

+ +# 简介 + +大彬断断续续花了一个多月的时间,从各个学习网站上收集了**300多本经典的计算机电子书、个人笔记和面试资料**,在这里分享有需要的人,希望可以帮助到曾经像我一样的新手,节省下找资料的时间。 + +书籍也同步到Github仓库了,可以**star**一下,下次找书直接在上面搜索。 + +> Github地址:https://github.com/Tyson0314/java-books + +![](http://img.dabin-coder.cn/image/image-20210902223746952.png) + +![](http://img.dabin-coder.cn/image/image-20221030094126118.png) + +书单持续更新中,小伙伴们也可以帮忙一起完善书单,找不到想要的书籍可以评论区提出~ + +**注意:本网站的书籍来源于网络,版权归原作者所有,不以盈利为目的,仅限学习使用,如有侵权请联系 1713476357@qq.com 删除**。 + +> 👍**推荐一份大厂面试手册 [计算机校招社招高频面试题汇总](https://github.com/Tyson0314/Java-learning)** + +# Java + +- Java编程思想第四版 [百度云下载链接](https://pan.baidu.com/s/1b2-OMKNi9WcaiZDnP3Y2uw) 提取码:wsyh +- Java 8实战(中文版) [百度云下载链接](https://pan.baidu.com/s/1nqEvhapy3Las-U_k1PB7jA) 提取码:opzq +- 阿里巴巴Java开发手册(终极版) [百度云下载链接](https://pan.baidu.com/s/1fxQ5Sv21QYjR6JJYiZBPsQ) 提取码:nazl +- Head First Java [百度云下载链接](https://pan.baidu.com/s/1L2LMXF4ng7CgLfeNZ8e1yg) 提取码:atxr +- Java核心技术 卷1 基础知识 原书第10版 [百度云下载链接](https://pan.baidu.com/s/12iSfpIlLxMjGKrvDE2k9qQ) 提取码:hobd +- Effective Java [百度云下载链接](https://pan.baidu.com/s/1DIlEro6-wJZNJ7qmflqR4g) 提取码:jxqz +- Java核心技术 卷 2 高级特性 原书第10版 [百度云下载链接](https://pan.baidu.com/s/126BEN1e7ab1U6kPEjXWDRQ) 提取码:wmov +- 写给大忙人看的JavaSE8 [百度云下载链接](https://pan.baidu.com/s/1ZXaXyzFBcqK1e4lmoWQjuQ) 提取码:bvqf +- 深入理解Java虚拟机 [百度云下载链接](https://pan.baidu.com/s/1Ya1HjRV14kee-T_UQITVqg) 提取码:atis + +# 数据库 + +- SQL学习指南 [百度云下载链接](https://pan.baidu.com/s/1ZmFdhgEAJPPKFmjCO0gxRg) 提取码:ibwp +- MySQL性能优化的21个最佳实践 [百度云下载链接](https://pan.baidu.com/s/15bVDICpfCEcijNXjyU1Yjw) 提取码:qriw +- SQLite 权威指南 [百度云下载链接](https://pan.baidu.com/s/1-BxMGu0O7Qk1Dzj4I15vzg) 提取码:cibr +- 深入浅出MySQL:数据库开发、优化与管理维护 [百度云下载链接](https://pan.baidu.com/s/1UF3CBjYeXiQH65dsPI7muA) 提取码:euxk +- MySQL必知必会 [百度云下载链接](https://pan.baidu.com/s/14TrWxw2kbcmrC1EqXgEdiw) 提取码:nlgc +- MongoDB权威指南 [百度云下载链接](https://pan.baidu.com/s/16UeSqyw0d_R0ng0q32hjRA) 提取码:ewcl +- SQL必知必会 第4版 [百度云下载链接](https://pan.baidu.com/s/1ti1SRNov6ZVyxNERVNZveA) 提取码:wgin +- 高性能MySQL(第3版) [百度云下载链接](https://pan.baidu.com/s/1wfYewFoqG8bgvGyb50DhAQ) 提取码:jzeq +- 高性能mysql第三版 [百度云下载链接](https://pan.baidu.com/s/1M45u3refIdVVJd0PGzl3rA) 提取码:wako +- MySQL技术内幕 InnoDB存储引擎 第2版 [百度云下载链接](https://pan.baidu.com/s/16hklWAOb55sehRpZOAaDZw) 提取码:raqe +- 数据库系统概念 [百度云下载链接](https://pan.baidu.com/s/1FbRF00lfjjUcb27irHRDfA) 提取码:rtei + +# 缓存 + +- Redis开发与运维 [百度云下载链接](https://pan.baidu.com/s/1FfcllHYv1IM8xU5optlAKQ) 提取码:acmy +- Redis设计与实现 [百度云下载链接](https://pan.baidu.com/s/1bpEzyDiZvOwzIVNJTEvopg) 提取码:islw +- Redis实战 [百度云下载链接](https://pan.baidu.com/s/1elpeXuhAP2CkgPzQc3tgGQ) 提取码:fwdt +- Redis入门指南 第2版 [百度云下载链接](https://pan.baidu.com/s/1J44vHvyt8G2WKxWzldjBRA) 提取码:ieya + +# 消息队列 + +- Kafka权威指南 [百度云下载链接](https://pan.baidu.com/s/1Bib19ABwbtL83MS-EWLoeg) 提取码:ipte +- RabbitMQ实战 高效部署分布式消息队列 [百度云下载链接](https://pan.baidu.com/s/16QZFQ06ugVKCU4fXiTXHVQ) 提取码:lrjn + +# Web架构 + +- 亿级流量网站架构核心技术 [百度云下载链接](https://pan.baidu.com/s/1I7UaRqkn59vAD1domt696g) 提取码:hjsa +- Java EE互联网轻量级框架整合开发 SSM框架(Spring MVC+Spring+MyBatis)和Redis实现 [百度云下载链接](https://pan.baidu.com/s/1g5A15YZfqpwJTTnCsCVFCA) 提取码:ojyb +- 架构探险 从零开始写javaweb框架 [百度云下载链接](https://pan.baidu.com/s/1T2d5fz66qgP9Bg8838nFgQ) 提取码:cwyt +- 大型网站技术架构:核心原理与案例分析 [百度云下载链接](https://pan.baidu.com/s/12rIP_3GasPTJG6Aoix3YUA) 提取码:gkps +- 大型网站系统与JAVA中间件实践 [百度云下载链接](https://pan.baidu.com/s/1ZVNuDaS5dAzVvmpL-feFxw) 提取码:jaxm +- Head First Servlets and JSP 中文版 第2版 [百度云下载链接](https://pan.baidu.com/s/1VGPI1jdwX8SsBOT9ozxcTw) 提取码:dqby + +# 并发 + +- Java并发编程实战 [百度云下载链接](https://pan.baidu.com/s/1vx77KmOXuVyrIJbwRHgORQ) 提取码:hqyk +- 深入浅出 Java 多线程 [百度云下载链接](https://pan.baidu.com/s/1TevopQ6rvoTqY0G8UWEoUw) 提取码:nxcr +- Java多线程编程核心技术 [百度云下载链接](https://pan.baidu.com/s/1VdvJLMMQhnrPdLybMVTQhA) 提取码:tyug +- JAVA并发编程实践 [百度云下载链接](https://pan.baidu.com/s/1r0JzJuks2VdYRlNZrkM8Eg) 提取码:uldo +- JAVA多线程设计模式 [百度云下载链接](https://pan.baidu.com/s/1suHlbw-QLf-WVlmLuYF4IA) 提取码:vphc +- 实战Java高并发程序设计 [百度云下载链接](https://pan.baidu.com/s/1T6abSW0vIAF3inyoQGNB0A) 提取码:qhxd + +# 框架 + +- SPRING技术内幕 [百度云下载链接](https://pan.baidu.com/s/1oTzs-uKh3x4ZJt3PZHu6Ag) 提取码:suqt +- Spring MVC学习指南 [百度云下载链接](https://pan.baidu.com/s/1jsKdItKWYD1y7TVNkDKQcw) 提取码:yubj +- spring揭秘 [百度云下载链接](https://pan.baidu.com/s/1wylIipOQDQNpuk7lWI7EFg) 提取码:ivkt +- Deep into Spring Boot [百度云下载链接](https://pan.baidu.com/s/1Aqk1I7sQoLeuh-he68J4ag) 提取码:jzkg +- 看透springMvc源代码分析与实践 [百度云下载链接](https://pan.baidu.com/s/1ChEWlR9fSTFqtLgd4Mq8Qg) 提取码:saqw +- Hibernate实战 [百度云下载链接](https://pan.baidu.com/s/1ckTFs5q_aBwXX86abaPg8w) 提取码:vifl +- Spring源码深度解析 [百度云下载链接](https://pan.baidu.com/s/1P4e3ua8CiKr7iOlY8ii6NA) 提取码:viyz +- 深入浅出MyBatis技术原理与实战 [百度云下载链接](https://pan.baidu.com/s/1LoqF22KYKQCSE6aZi69ySQ) 提取码:quao +- MyBatis技术内幕 [百度云下载链接](https://pan.baidu.com/s/18S_UBMIVERSXubh2zkk1Jw) 提取码:reqk +- Spring Boot实战 [百度云下载链接](https://pan.baidu.com/s/1wjCZeNi7OahfrrJY4VJzvA) 提取码:buwr +- Spring Cloud与Docker微服务架构实战 [百度云下载链接](https://pan.baidu.com/s/13FBSyWIO24ISVJ20FZosGw) 提取码:gqxs +- Spring in action 中文版(第4版) [百度云下载链接](https://pan.baidu.com/s/1H2plA0SvhBsln8dnneJktQ) 提取码:mzpa +- Spring Cloud微服务实战 [百度云下载链接](https://pan.baidu.com/s/1IHeojC96rV4MsVk1eMWnKw) 提取码:plie + +# 计算机网络 + +- 图解HTTP [百度云下载链接](https://pan.baidu.com/s/1qIAc42Qr6W3uj6tAxWMgOw) 提取码:bghw +- 图解TCP IP [百度云下载链接](https://pan.baidu.com/s/1myv-uGxV3UpEAR2dMpHhlw) 提取码:dplo +- 计算机网络-自顶向下方法(第六版) [百度云下载链接](https://pan.baidu.com/s/19ImHNtMjhBtvQbNoBsi3lA) 提取码:dbat +- TCP IP详解卷1 原书第2版 [百度云下载链接](https://pan.baidu.com/s/1-NBccguGQLu92aYZ4NxdkA) 提取码:caxe +- Wireshark网络分析就这么简单 [百度云下载链接](https://pan.baidu.com/s/1-BBFEi-haLu08LKwWYu9Lg) 提取码:dciw +- 计算机网络(第7版)-谢希仁 [百度云下载链接](https://pan.baidu.com/s/1u3qdDs4oEjyDvKNMBKRQ1w) 提取码:fitz + +# 数据结构与算法 + +- 数据结构与算法分析—C语言描述 [百度云下载链接](https://pan.baidu.com/s/1-KnLmebSD480amniojO2bg) 提取码:yuvz +- 算法图解 [百度云下载链接](https://pan.baidu.com/s/1d-csiFMCaLoqpE_ZZr8dGA) 提取码:vkos +- 数据结构与算法分析 java语言描述(原书第3版) [百度云下载链接](https://pan.baidu.com/s/1TsISSLvJ8PhdTDP5k4GZ7Q) 提取码:suby +- 算法之美:指导工作与生活 [百度云下载链接](https://pan.baidu.com/s/1wfrTES2OwSEVjaPF52BLuw) 提取码:cbgk +- 背包九讲2.0 [百度云下载链接](https://pan.baidu.com/s/1h6NNsstEvZEYftalvfJQtg) 提取码:soxk +- 算法导论 第三版 [百度云下载链接](https://pan.baidu.com/s/1-indIwnhk8-wt7v6KLp3oQ) 提取码:hduz +- labuladong的算法小抄 [百度云下载链接](https://pan.baidu.com/s/1AFabRcS6CYa9LdFYUGokBQ) 提取码:kbci +- LeetCode刷题手册-阿里霜神 [百度云下载链接](https://pan.baidu.com/s/1Oz5w7dQPiS4lHgiRadociQ) 提取码:ekdx +- 谷歌大佬LeetCode刷题笔记 [百度云下载链接](https://pan.baidu.com/s/1NV-wCa9QhA8zEzAdjwiP0g) 提取码:vpui +- 编程珠玑 [百度云下载链接](https://pan.baidu.com/s/100eDgsFCnUN1mL7N_RuIEQ) 提取码:nzxt +- 剑指Offer [百度云下载链接](https://pan.baidu.com/s/1napasMTPIA-yIP8HG093EQ) 提取码:zlmt +- 数据结构(C语言版) [百度云下载链接](https://pan.baidu.com/s/1_NxoY-d3luDCIfnxprFAdA) 提取码:ksyw + +# 操作系统 + +- 深入理解计算机系统.pdf [百度云下载链接](https://pan.baidu.com/s/19Fsk4oQgn16QsqLVo7-OtA) 提取码:wlrf +- 30天自制操作系统 (图灵程序设计丛书)-2-753 [百度云下载链接](https://pan.baidu.com/s/1kh7QTXNmrvAnoMo_N4d_rA) 提取码:dutc +- 现代操作系统(第三版)中文版 [百度云下载链接](https://pan.baidu.com/s/1nCPyrsGXr6porYlsohUmmA) 提取码:gkps +- 操作系统精髓与设计原理(原书第6版) [百度云下载链接](https://pan.baidu.com/s/1V_JBro99aqnLET1FDMP52A) 提取码:fbzt +- 操作系统概念 [百度云下载链接](https://pan.baidu.com/s/16iSiLoqq0mugRnb61QflTA) 提取码:iqvo +- 深入理解计算机系统 [百度云下载链接](https://pan.baidu.com/s/1Vb21cODDySHFxZFr2JvO0w) 提取码:caoi +- 操作系统设计与实现 [百度云下载链接](https://pan.baidu.com/s/1-kAryblScC_X7HZV5XCxgw) 提取码:kbte + +# Linux + +- Linux学习笔记 [百度云下载链接](https://pan.baidu.com/s/1SZ8UrKE9roY5MQ7btXzo-A) 提取码:fzmc +- UNIX环境高级编程 第二版中文 [百度云下载链接](https://pan.baidu.com/s/1B-NM0bJMiPTHOBYV_zpNkA) 提取码:mdao +- 鸟哥的Linux私房菜 服务器篇(第三版) [百度云下载链接](https://pan.baidu.com/s/14cCH0_yvgzNuAMfqbVTbYQ) 提取码:rmjn +- Linux Shell脚本攻略(第2版) [百度云下载链接](https://pan.baidu.com/s/16uYXwvrxVoKYMwFr7FDo5Q) 提取码:thaj +- UNIX网络编程 卷2 进程间通信 [百度云下载链接](https://pan.baidu.com/s/1L3ZVi6sxnmQSPqC8-LxKMw) 提取码:kcae +- UNIX网络编程 卷1 套接字联网API [百度云下载链接](https://pan.baidu.com/s/1SUjwqH3IHbqzjG7wsKGTqQ) 提取码:jbwc +- 鸟哥的Linux私房菜 基础学习篇(第三版)-清晰版 [百度云下载链接](https://pan.baidu.com/s/1pAkMc0RoVmAKVDBqPakAiQ) 提取码:mawv + +# c + +- C程序设计语言(英文第2版)Prentice Hall.-.The C Programming Language(2nd Edition) [百度云下载链接](https://pan.baidu.com/s/1UMkZBeC-UVSUijUHGTAg9A) 提取码:kuec +- C程序设计语言(第2版)中文译版 [百度云下载链接](https://pan.baidu.com/s/1_ZdUbucFt6DniKyUDkJgtg) 提取码:apnu +- C和指针 [百度云下载链接](https://pan.baidu.com/s/1sCq_KW21QBJwop6zBr-S2w) 提取码:pakl +- C语言深度解剖 [百度云下载链接](https://pan.baidu.com/s/1CAMYvuqP52vj5io8joeTwg) 提取码:qzgu +- C语言函数大全 [百度云下载链接](https://pan.baidu.com/s/1mzeoJpWCMy7WMUP4ximEhg) 提取码:dxfw +- Microsoft编写优质无错C程序秘诀 [百度云下载链接](https://pan.baidu.com/s/163oTBX13HD3J--6DVck6yw) 提取码:ftba +- C语言参考手册第五版 [百度云下载链接](https://pan.baidu.com/s/1qUaZNDB1WcnuEsjaAjyz-Q) 提取码:urnh +- C专家编程 [百度云下载链接](https://pan.baidu.com/s/1LiceKF0W6R2HzaPdzw1_Cw) 提取码:geta +- C程序设计(第四版).谭浩强 [百度云下载链接](https://pan.baidu.com/s/1hXzs9vxvriBFfLOkkyV9kQ) 提取码:knox +- C标准库中文版 [百度云下载链接](https://pan.baidu.com/s/1M_PDS6UFL4spe8JvKICx9w) 提取码:pqxe +- C Primer Plus(第五版) [百度云下载链接](https://pan.baidu.com/s/1D7iUmPSiOEVH3ddeld9vbg) 提取码:haxs + +# c# + +- 深入理解C# [百度云下载链接](https://pan.baidu.com/s/1T3IvAWhhdOm0ReZ7lo2_5Q) 提取码:lvbr +- c#图解教程 第4版(Illustrated C# 2012) [百度云下载链接](https://pan.baidu.com/s/1lIIsJDy7Ma8t6FhcaACaeQ) 提取码:eklv + +# c++ + +- More Effective C++中文版 [百度云下载链接](https://pan.baidu.com/s/1kBqKs8kY2HP9dZZvHSVmLA) 提取码:njug +- 深入探索C++对象模型 [百度云下载链接](https://pan.baidu.com/s/1uTksFSLfWuTl6O0axQfDlg) 提取码:eslv +- 深度探索C++对象模型 [百度云下载链接](https://pan.baidu.com/s/1Lf7WhdTd2cDP7Qwkf-5rgA) 提取码:brpa +- STL源码剖析 [百度云下载链接](https://pan.baidu.com/s/1YqwPZgyrHHIi4h8U0ba87g) 提取码:otdz +- STL源码剖析简体中文完整版 [百度云下载链接](https://pan.baidu.com/s/19DW-eq2bp7HhpnYz71lg0g) 提取码:lhno +- 深入理解C++11:C++11新特性解析与应用 [百度云下载链接](https://pan.baidu.com/s/1Y2yIOhb7v8rWsh9do5wiKw) 提取码:rdlx +- 学习OpenCV(中文版) [百度云下载链接](https://pan.baidu.com/s/14ycBk6tMpRKxqbe4CBTP0Q) 提取码:voru +- OpenCV3编程入门 毛星云编著 电子工业出版 [百度云下载链接](https://pan.baidu.com/s/1-Mm3Iwvvt-HRYQhJFn3LeA) 提取码:yvtq +- C++ Template 全览, 中文版 [百度云下载链接](https://pan.baidu.com/s/15PG066--meojYuXW7p-WIg) 提取码:pgim +- Qt Creator快速入门 [百度云下载链接](https://pan.baidu.com/s/1bTFHqT2127b_kHhrdtgfag) 提取码:aesf +- C++ Primer中文版 第6版 [百度云下载链接](https://pan.baidu.com/s/1insd8sVXI4jHpqTrXKWN9Q) 提取码:iud2 +- C++并发编程 [百度云下载链接](https://pan.baidu.com/s/1SRJiDtleXA2rvWOjcxS5dA) 提取码:czlf +- C++编程规范-101条规则准则与最佳实践 [百度云下载链接](https://pan.baidu.com/s/1GQ10rT7z1V-JAdlAJV5dBQ) 提取码:oyvz +- C++primer 5th [百度云下载链接](https://pan.baidu.com/s/1bJUGemBydhPjt-4Eyq0PIQ) 提取码:tvaq +- google C++ 编码规范(完整版) [百度云下载链接](https://pan.baidu.com/s/12X9mE1cYdKwaqyekV8ueCw) 提取码:pmec +- Effective STL 中文版 [百度云下载链接](https://pan.baidu.com/s/18l9CI8_jtD8ilV2Ec2OCHA) 提取码:gban +- Effective C++ 改善程序与设计的55个具体做法 中文第三版 [百度云下载链接](https://pan.baidu.com/s/1thtQHg_6k9dLZbU75OfnVw) 提取码:oxke +- C++沉思录 [百度云下载链接](https://pan.baidu.com/s/1QpglHQWSqB3xMjjJ-iqiow) 提取码:ojgn + +# Go + +- 学习 Go 语言(Golang) [百度云下载链接](https://pan.baidu.com/s/1_pJnZgyAALpehgedVepbGA) 提取码:zadr +- Go web 编程 [百度云下载链接](https://pan.baidu.com/s/1V4t3MfcOFI_5qfoSNNMMJw) 提取码:znwa +- Go语言实战 [百度云下载链接](https://pan.baidu.com/s/1NJbeIJqVZf22Detdn8af7A) 提取码:uate +- Go并发编程实战 [百度云下载链接](https://pan.baidu.com/s/1YSQE_ENBbONjXMCAI9qPng) 提取码:fmst + +# Python + +- Python高级编程第2版 张亮 阿信(译) 人民邮电出版社 2017-10 v2 完整版 [百度云下载链接](https://pan.baidu.com/s/1qt6IYNKJ-T8zuaCZGPEZkg) 提取码:xjfi +- Python开发技术详解 [百度云下载链接](https://pan.baidu.com/s/1qE7mDBDHn8jw0EJf_sEP_Q) 提取码:dywg +- 编程小白的第一本python入门书 [百度云下载链接](https://pan.baidu.com/s/1uP2xRqwJOgsWxwypmcBWJQ) 提取码:dsmi +- Python开发实战 [百度云下载链接](https://pan.baidu.com/s/1ei4XdEWCt_DjqD9t1VEH0w) 提取码:hxjw +- Python学习手册(第4版) [百度云下载链接](https://pan.baidu.com/s/1dJhk1RBZ3LZdMITLDYSZ0A) 提取码:miey +- Python编程入门经典 [百度云下载链接](https://pan.baidu.com/s/1091A_q7XHtC6sKmNdbOELA) 提取码:vyfs + +# 编程之术 + +- 统计推断 statistical inference(英文版) [百度云下载链接](https://pan.baidu.com/s/1al-C2Je6eeS9AnmYU8-ajw) 提取码:azmx +- 重构:改善既有代码的设计(第2版) [百度云下载链接](https://pan.baidu.com/s/1x31IAg4cn30XNbQ6U7ac_w) 提取码:tvyp +- 编写可读代码的艺术 [百度云下载链接](https://pan.baidu.com/s/1AYNaWER4ZjzEf3sjDUS3zA) 提取码:yqxu +- 编程的奥秘 [百度云下载链接](https://pan.baidu.com/s/194oroXguaGLyogGbRWnpqA) 提取码:iycm +- 敏捷软件开发:原则、模式与实践 [百度云下载链接](https://pan.baidu.com/s/1B0tBpmKXMfVU9XIQbq4qHA) 提取码:xsub +- 代码大全2中文版 [百度云下载链接](https://pan.baidu.com/s/1FFTfDuegBTpq_YOsqHpSEg) 提取码:mwid +- 代码之美精选版 [百度云下载链接](https://pan.baidu.com/s/1sw6bOaKADfOJ748I0yUoTA) 提取码:qecg +- 代码整洁之道 [百度云下载链接](https://pan.baidu.com/s/1I00RoSEGKvr3i5GwWgNDPw) 提取码:qbeu +- 程序员的自我修养—链接、装载与库 [百度云下载链接](https://pan.baidu.com/s/1tJv2vJKju78ZmW57ZpewgQ) 提取码:xefk +- 编程之美 [百度云下载链接](https://pan.baidu.com/s/1U4hIi3QlWGhXRmcuOwxXpA) 提取码:fxsd +- 程序视角下的可计算和复杂性理论 Computability and Complexity(英文版) [百度云下载链接](https://pan.baidu.com/s/1byjn9mj8yIB56sdF--6JTA) 提取码:xadr +- 编码:隐匿在计算机软硬件背后的语言 [百度云下载链接](https://pan.baidu.com/s/1bi5u18o7Od8T1_jzMj7_iQ) 提取码:jprb + +# 大数据 + +- Hadoop权威指南 第3版 修订版 [百度云下载链接](https://pan.baidu.com/s/1Vlxty3N0Tiv4cvHauRMVuw) 提取码:dfyu +- Spark快速数据处理完整版 [百度云下载链接](https://pan.baidu.com/s/1b-rYRFU682GCLZeSVhwCHw) 提取码:iawf + +# 分布式 + +- 架构探险:从零开始写分布式服务架构 [百度云下载链接](https://pan.baidu.com/s/1AmKV6G-azET88E6jcmoBAA) 提取码:cvwu +- 深入分布式缓存 从原理到实践 [百度云下载链接](https://pan.baidu.com/s/1g3KehD1HAJqrZd8BgUIhdQ) 提取码:uwim + +# 工具 + +- Maven3实战 [百度云下载链接](https://pan.baidu.com/s/16y03dBloWJSYC3BlXypijg) 提取码:xilj +- IntelliJ IDEA 简体中文专题教程(电子版-2015) [百度云下载链接](https://pan.baidu.com/s/19UwnAgsi_IZBNLBrl-dTxA) 提取码:vfqm +- Maven实战 [百度云下载链接](https://pan.baidu.com/s/1EVCEe2MxyecSAYPZ6eOSYw) 提取码:bwid +- Vim 中文用户手册 [百度云下载链接](https://pan.baidu.com/s/1nGQGlOrTvTm9HoVoAHj7KQ) 提取码:ewvj +- progit [百度云下载链接](https://pan.baidu.com/s/1uzeT4wDruXObe__E6FzMVA) 提取码:mvap + +# 机器学习 + +- 机器学习实战 [百度云下载链接](https://pan.baidu.com/s/12iUnxSAbCXHp6_5i_J_uwQ) 提取码:kwqs +- 深度学习 中文版 [百度云下载链接](https://pan.baidu.com/s/1DSPObptqe4s0TCy-1pQHog) 提取码:oasp +- 贝叶斯思维统计建模的PYTHON学习法 [百度云下载链接](https://pan.baidu.com/s/1_sgg_zMJn3yKd46Yly6CkQ) 提取码:vyzg +- 图解机器学习 [百度云下载链接](https://pan.baidu.com/s/1Fva-HDLAXnCPkLmyKmUubw) 提取码:fqcz +- PYTHON机器学习及实践-从零开始通往KAGGLE竞赛之路 [百度云下载链接](https://pan.baidu.com/s/16oqijoi-v54-TXiqW8qbDw) 提取码:zqhd +- TensorFlow实践与智能系统 [百度云下载链接](https://pan.baidu.com/s/1noqSL35H-vzHYypc1IzqfQ) 提取码:qbli +- TensorFlow技术解析与实战 [百度云下载链接](https://pan.baidu.com/s/1T6KnGXVNHe3Fg2GAC27ZFA) 提取码:gozc +- Tensorflow 实战Google深度学习框架 [百度云下载链接](https://pan.baidu.com/s/1eVW2oHeEmdLRyy4xZPFpcw) 提取码:ecoz + +# 面试 + +- SpringCloud面试专题 [百度云下载链接](https://pan.baidu.com/s/1z6ASwOTOCQbpwQAQjVY4_A) 提取码:jrgi +- Tomcat优化相关问题 [百度云下载链接](https://pan.baidu.com/s/1mNQvAcEQ58BxhFwY-qM2dg) 提取码:cekn +- 面试必备之乐观锁与悲观锁 [百度云下载链接](https://pan.baidu.com/s/1kffc2ar3lHmMDkZvXcY70w) 提取码:mfqw +- 一线互联网企业面试题 [百度云下载链接](https://pan.baidu.com/s/1szgntkHQxHuwaNrhMGEz6w) 提取码:lcrs +- 字节跳动21届秋招全岗位面经集合 [百度云下载链接](https://pan.baidu.com/s/1OS4He8Tbs-_u9ZDwLam61g) 提取码:fydb +- Dubbo面试专题 [百度云下载链接](https://pan.baidu.com/s/1XHVbPR-j-nmww5aVCrKhDg) 提取码:ywpn +- 【笔记】concurrentHashMap [百度云下载链接](https://pan.baidu.com/s/1j9xOojZXdCPu6ScFx2U6NQ) 提取码:yxlf +- JVM性能优化相关问题 [百度云下载链接](https://pan.baidu.com/s/1Sa5zlZBYGPqxOLDd3KWrDQ) 提取码:vuie +- SpringBoot面试专题 [百度云下载链接](https://pan.baidu.com/s/14FGoW7et4D4IkjbVEDSUUA) 提取码:macu +- redis面试专题 [百度云下载链接](https://pan.baidu.com/s/1qQ_iXrrwjscVVl5GaFlN0Q) 提取码:famx +- 程序员面试宝典(第三版) [百度云下载链接](https://pan.baidu.com/s/1zVziyqJzJF99VvE8EH3JZQ) 提取码:kbqa +- JAVA核心面试知识整理 [百度云下载链接](https://pan.baidu.com/s/1sgvCVzNiS-nVEAuDPtmcFA) 提取码:neqb + +# 前端 + +- HTML与CSS入门经典(第7版).(美)奥利弗,(美)莫里森.扫描版 [百度云下载链接](https://pan.baidu.com/s/1qn3aSq2cIopbT7cXhHB87A) 提取码:gjcz +- JavaScript.DOM编程艺术(第2版) [百度云下载链接](https://pan.baidu.com/s/1Mjl4QlAYctlfenO1eX2EKw) 提取码:lcbz +- JavaScript高级程序设计(第3版) [百度云下载链接](https://pan.baidu.com/s/1Vayhr_IkG-VknzV9hI8RQg) 提取码:cmyx +- jQuery高级编程,中文完整扫描版(jb51.net) 2 [百度云下载链接](https://pan.baidu.com/s/15V9ZVJiKI2kU7kNkyD8NTA) 提取码:ckwh +- jQuery权威指南 [百度云下载链接](https://pan.baidu.com/s/1eZKd2R2o7wmum5U2TdrVgA) 提取码:mltc +- Node.js开发指南 [百度云下载链接](https://pan.baidu.com/s/1jzHETr0KCVV9uX6cPAgVRQ) 提取码:mqsc +- jQuery技术内幕 深入解析jQuery架构设计与实现原理 [百度云下载链接](https://pan.baidu.com/s/1QF4CRQvvk9ToZMbZZtwHUA) 提取码:qklc +- 疯狂ajax讲义 [百度云下载链接](https://pan.baidu.com/s/14P8jYleL_nq4rfi8qrKM4g) 提取码:ztdq +- Bootstrap实战 [百度云下载链接](https://pan.baidu.com/s/13PPzbbWAB37Mhny-kidYoA) 提取码:fxpe +- HTML5揭秘 [百度云下载链接](https://pan.baidu.com/s/18dJfVWdE6BRHdy9ZsoQ0gA) 提取码:ksnr +- HTML5与CSS3基础教程(第8版) [百度云下载链接](https://pan.baidu.com/s/1xmd6phEtyePtjmwUpC1riA) 提取码:ldfh +- Head First HTML与CSS 第2版 [百度云下载链接](https://pan.baidu.com/s/1Dyw_2i2Sx7mDLbEG90opIA) 提取码:ldcn + +# 分布式 + +- 架构探险:从零开始写分布式服务架构 [百度云下载链接](https://pan.baidu.com/s/1ROY7qowHOR-q9CnbekJfKA) 提取码:cxap +- 深入分布式缓存 从原理到实践 [百度云下载链接](https://pan.baidu.com/s/15nUR6wmcA2leCQvMpyLOag) 提取码:udhb + +# 设计模式 + +- 大话设计模式 [百度云下载链接](https://pan.baidu.com/s/14dCH7uGVK1t_91aSgHim9A) 提取码:uhln +- 设计模式之禅(第2版) [百度云下载链接](https://pan.baidu.com/s/1FvlKhGUJLWaXyt6KkNpWSQ) 提取码:jhnt +- HeadFirst设计模式 [百度云下载链接](https://pan.baidu.com/s/1jmXMgjCfxTR8PrDGqB09UQ) 提取码:fcsu +- 设计模式 可复用面向对象软件的基础 [百度云下载链接](https://pan.baidu.com/s/1KgYyRxNEYdiaOQGC-R1rLg) 提取码:efny +- 图解设计模式 [百度云下载链接](https://pan.baidu.com/s/1yReilEpnN3emamckAAEJCg) 提取码:yhuv +- 重学Java设计模式·小傅哥 [百度云下载链接](https://pan.baidu.com/s/176Z-SVRHZnhCdMpWft_S4g) 提取码:rsmk + +# 有趣 + +- 游戏开发物理学 [百度云下载链接](https://pan.baidu.com/s/123wSt5Zjrr20dLxqxFSeUg) 提取码:uogs +- 奔跑吧,程序员:从零开始打造产品、技术和团队 [百度云下载链接](https://pan.baidu.com/s/1Jmfxbkw7YDab6OBZUKAyUg) 提取码:uphr +- 正则表达式必知必会 [百度云下载链接](https://pan.baidu.com/s/1dCSDQEqzC5UdS2X6G2UJ1g) 提取码:xebg +- 自己动手写网络爬虫 [百度云下载链接](https://pan.baidu.com/s/1DQuJi4DFd-0cppKQ1_sG9Q) 提取码:xrcw +- 图灵的秘密 [百度云下载链接](https://pan.baidu.com/s/1wa5NItFkOeRkAp6qKREBOA) 提取码:erol +- 编程人生 [百度云下载链接](https://pan.baidu.com/s/1U4AxnlDj8bGLDVWazinhOA) 提取码:gobd +- 人月神话 [百度云下载链接](https://pan.baidu.com/s/1AwswyHcdOURRB3mtbLOs2g) 提取码:hnbm +- 入侵的艺术 凯文.米特尼克 [百度云下载链接](https://pan.baidu.com/s/13EmQTlLY6eSTxRSSgD6-jw) 提取码:jbeg +- 黑客与画家 [百度云下载链接](https://pan.baidu.com/s/1vmQuh8TeWjlA1aCuq8j5nA) 提取码:jcqm +- 浪潮之巅(完整版) [百度云下载链接](https://pan.baidu.com/s/1UoqR9gHV8Ced8kRHBLBVHA) 提取码:cnhr +- 数学之美 [百度云下载链接](https://pan.baidu.com/s/1yAxu3O4StwhCKQ4lMO8K6g) 提取码:euni + +# 免责声明 + +本仓库书籍资源均来源于网络其他人的整理,个人只是做了整理。若有**违规侵权**,请联系1713476357@qq.com ,本人立马删除相应的资源! + +本仓库仅作学习交流分享使用,**不作任何商用**。 + +# 赞赏 + +整理这些资源花了很多时间,如果觉得本仓库有用,可以请大彬**喝一杯咖啡**~ + +| 微信 | 支付宝 | +| ------------------------------------------------- | ----------------------------------------------------- | +| ![](http://img.dabin-coder.cn/image/微信收款.png) | ![](http://img.dabin-coder.cn/image/支付宝赞赏码.png) | + +> 最后给大家分享另一个Github仓库,用于分享**互联网大厂高频面试题、Java核心知识总结**,包括Java基础、并发、MySQL、Springboot、MyBatis、Redis、RabbitMQ等等,面试必备!欢迎大家star! +> +> Github地址:https://github.com/Tyson0314/Java-learning +> +> 如果github访问不了,可以访问gitee仓库。 +> +> gitee地址:https://gitee.com/tysondai/Java-learning + diff --git "a/\345\267\245\345\205\267/docker-overview.md" b/docs/tools/docker-overview.md similarity index 76% rename from "\345\267\245\345\205\267/docker-overview.md" rename to docs/tools/docker-overview.md index 0359ec2..3899f46 100644 --- "a/\345\267\245\345\205\267/docker-overview.md" +++ b/docs/tools/docker-overview.md @@ -1,65 +1,9 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [简介](#%E7%AE%80%E4%BB%8B) - - [基本概念](#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5) -- [docker镜像常用命令](#docker%E9%95%9C%E5%83%8F%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4) - - [添加docker仓库位置](#%E6%B7%BB%E5%8A%A0docker%E4%BB%93%E5%BA%93%E4%BD%8D%E7%BD%AE) - - [安装docker服务](#%E5%AE%89%E8%A3%85docker%E6%9C%8D%E5%8A%A1) - - [启动 docker 服务](#%E5%90%AF%E5%8A%A8-docker-%E6%9C%8D%E5%8A%A1) - - [重启docker服务](#%E9%87%8D%E5%90%AFdocker%E6%9C%8D%E5%8A%A1) - - [搜索镜像](#%E6%90%9C%E7%B4%A2%E9%95%9C%E5%83%8F) - - [下载镜像:](#%E4%B8%8B%E8%BD%BD%E9%95%9C%E5%83%8F) - - [列出镜像](#%E5%88%97%E5%87%BA%E9%95%9C%E5%83%8F) - - [删除镜像](#%E5%88%A0%E9%99%A4%E9%95%9C%E5%83%8F) - - [打包镜像](#%E6%89%93%E5%8C%85%E9%95%9C%E5%83%8F) - - [创建镜像](#%E5%88%9B%E5%BB%BA%E9%95%9C%E5%83%8F) - - [推送镜像:](#%E6%8E%A8%E9%80%81%E9%95%9C%E5%83%8F) - - [docker hub](#docker-hub) - - [修改镜像存放位置](#%E4%BF%AE%E6%94%B9%E9%95%9C%E5%83%8F%E5%AD%98%E6%94%BE%E4%BD%8D%E7%BD%AE) -- [docker容器常用命令](#docker%E5%AE%B9%E5%99%A8%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4) - - [新建容器](#%E6%96%B0%E5%BB%BA%E5%AE%B9%E5%99%A8) - - [查看容器](#%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8) - - [停止容器](#%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8) - - [启动容器](#%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8) - - [重启容器](#%E9%87%8D%E5%90%AF%E5%AE%B9%E5%99%A8) - - [进入容器](#%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8) - - [删除容器](#%E5%88%A0%E9%99%A4%E5%AE%B9%E5%99%A8) - - [容器日志](#%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97) - - [容器ip](#%E5%AE%B9%E5%99%A8ip) - - [容器启动方式](#%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%96%B9%E5%BC%8F) - - [资源占用](#%E8%B5%84%E6%BA%90%E5%8D%A0%E7%94%A8) - - [磁盘使用情况](#%E7%A3%81%E7%9B%98%E4%BD%BF%E7%94%A8%E6%83%85%E5%86%B5) - - [执行容器内部命令](#%E6%89%A7%E8%A1%8C%E5%AE%B9%E5%99%A8%E5%86%85%E9%83%A8%E5%91%BD%E4%BB%A4) - - [网络](#%E7%BD%91%E7%BB%9C) - - [复制文件](#%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6) -- [docker-compose](#docker-compose) - - [安装](#%E5%AE%89%E8%A3%85) - - [常用命令](#%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4) - - [部署多个服务](#%E9%83%A8%E7%BD%B2%E5%A4%9A%E4%B8%AA%E6%9C%8D%E5%8A%A1) - - [定义配置文件](#%E5%AE%9A%E4%B9%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) - - [启动服务](#%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1) -- [maven插件构建docker镜像](#maven%E6%8F%92%E4%BB%B6%E6%9E%84%E5%BB%BAdocker%E9%95%9C%E5%83%8F) - - [docker镜像仓库](#docker%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93) - - [docker开启远程访问](#docker%E5%BC%80%E5%90%AF%E8%BF%9C%E7%A8%8B%E8%AE%BF%E9%97%AE) - - [docker支持http上传镜像](#docker%E6%94%AF%E6%8C%81http%E4%B8%8A%E4%BC%A0%E9%95%9C%E5%83%8F) - - [重启docker](#%E9%87%8D%E5%90%AFdocker) - - [开放端口](#%E5%BC%80%E6%94%BE%E7%AB%AF%E5%8F%A3) - - [构建docker镜像](#%E6%9E%84%E5%BB%BAdocker%E9%95%9C%E5%83%8F) -- [其他](#%E5%85%B6%E4%BB%96) - - [给nginx增加端口映射](#%E7%BB%99nginx%E5%A2%9E%E5%8A%A0%E7%AB%AF%E5%8F%A3%E6%98%A0%E5%B0%84) - - - ## 简介 Docker是一个开源的应用容器引擎,通过容器可以隔离应用程序的运行时环境(程序运行时依赖的各种库和配置),比虚拟机更轻量(虚拟机在操作系统层面进行隔离)。docker的另一个优点就是build once, run everywhere,只编译一次,就可以在各个平台(windows、linux等)运行。 ### 基本概念 -[docker](https://zhuanlan.zhihu.com/p/23599229) - docker的基本概念: 1. 镜像(image),类似于虚拟机中的镜像,可以理解为可执行程序。 @@ -71,12 +15,13 @@ docker的基本概念: docker的基本命令: -- docker build:我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,生成的可执行程序就是image。 +1、docker build:我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,生成的可执行程序就是image。 + +2、docker run:运行image,运行起来后就是docker container。 -- docker run:运行image,运行起来后就是docker container。 -- docker pull:到Docker Hub(docker registry)下载别人写好的image。 +3、docker pull:到Docker Hub(docker registry)下载别人写好的image。 -![](../img/docker/docker.jpg) +![](http://img.dabin-coder.cn/image/docker.jpg) > 图片来源:知乎小灰 @@ -265,36 +210,32 @@ Docker官方维护了一个DockerHub的公共仓库,里边包含有很多平 ### 修改镜像存放位置 -1. 查看镜像存放位置: - - ``` - docker info | grep "Docker Root Dir" - Docker Root Dir: /var/lib/docker - ``` - -2. 关闭docker服务: - - ``` - systemctl stop docker - ``` +1、查看镜像存放位置: -3. 原镜像目录移动到目标目录: - - ``` - mv /var/lib/docker /home/data/docker - ``` +``` +docker info | grep "Docker Root Dir" + Docker Root Dir: /var/lib/docker +``` -4. 建立软连接: +2、关闭docker服务: - ``` - ln -s /home/data/docker /var/lib/docker - ``` +``` +systemctl stop docker +``` -5. 再次查看镜像存放位置,发现已经修改。 +3、原镜像目录移动到目标目录: +``` +mv /var/lib/docker /home/data/docker +``` +4、建立软连接: +``` +ln -s /home/data/docker /var/lib/docker +``` +5、再次查看镜像存放位置,发现已经修改。 ## docker容器常用命令 @@ -312,13 +253,13 @@ docker run -p 33055:33055 --name nginx \ # -d nginx:1.18.0 -d表示容器以后台方式运行 ``` -- -p:将宿主机和容器端口进行映射,格式为:宿主机端口:容器端口; -- --name:指定容器名称,之后可以通过容器名称来操作容器; -- -e:设置容器的环境变量,这里设置的是时区; -- -v:将宿主机上的文件挂载到容器上,格式为:宿主机文件目录:容器文件目录; -- -d:表示容器以后台方式运行。终端不会输出任何运行信息; -- -i: 以交互模式运行容器,通常与 -t 同时使用; -- -t: 为容器分配一个终端,通常与 -i 同时使用。 +> - -p:将宿主机和容器端口进行映射,格式为:宿主机端口:容器端口; +> - --name:指定容器名称,之后可以通过容器名称来操作容器; +> - -e:设置容器的环境变量,这里设置的是时区; +> - -v:将宿主机上的文件挂载到容器上,格式为:宿主机文件目录:容器文件目录; +> - -d:表示容器以后台方式运行。终端不会输出任何运行信息; +> - -i: 以交互模式运行容器,通常与 -t 同时使用; +> - -t: 为容器分配一个终端,通常与 -i 同时使用。 使用-it,此时如果使用exit退出,则容器的状态处于Exit,而不是后台运行。如果想让容器一直运行,而不是停止,可以使用快捷键 ctrl+p ctrl+q 退出,此时容器的状态为Up。 @@ -328,11 +269,11 @@ docker run -p 33055:33055 --name nginx \ docker run --name mysql4blog -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3307 -d mysql:8.0.20 ``` -- `-name`: 给新创建的容器命名,此处命名为`mysql4blog` -- `-e`: 配置信息,此处配置MySQL的 root 用户的登录密码 -- `-p`: 端口映射,此处映射主机的3307端口到容器的3307端口 -- -d: 成功启动同期后输出容器的完整ID -- 最后一个`mysql:8.0.20`指的是`mysql`镜像 +> - `-name`: 给新创建的容器命名,此处命名为`mysql4blog` +> - `-e`: 配置信息,此处配置MySQL的 root 用户的登录密码 +> - `-p`: 端口映射,此处映射主机的3307端口到容器的3307端口 +> - -d: 成功启动同期后输出容器的完整ID +> - 最后一个`mysql:8.0.20`指的是`mysql`镜像 ### 查看容器 @@ -386,17 +327,17 @@ docker attach container_name/container_id 使用exit退出命令行之后,重新进入容器: -1. 先查询容器id:`docker inspect --format "{{.State.Pid}}" nginx` +1、先查询容器id:`docker inspect --format "{{.State.Pid}}" nginx` -2. 根据查到的容器id进入容器:`nsenter --target 28487 --mount --uts --ipc --net --pid` +2、根据查到的容器id进入容器:`nsenter --target 28487 --mount --uts --ipc --net --pid` - ``` - [root@VM_0_7_centos ~]# docker inspect --format "{{.State.Pid}}" nginx - 28487 - [root@VM_0_7_centos ~]# nsenter --target 28487 --mount --uts --ipc --net --pid - mesg: ttyname failed: No such device - root@b217a35fc808:/# ls -l - ``` +``` +[root@VM_0_7_centos ~]# docker inspect --format "{{.State.Pid}}" nginx +28487 +[root@VM_0_7_centos ~]# nsenter --target 28487 --mount --uts --ipc --net --pid +mesg: ttyname failed: No such device +root@b217a35fc808:/# ls -l +``` ### 删除容器 @@ -645,8 +586,6 @@ docker-compose up -d ## maven插件构建docker镜像 - - ### docker镜像仓库 服务器创建docker镜像仓库docker registry: @@ -838,3 +777,6 @@ docker start nginx +## 参考内容 + +[只要一小时,零基础入门Docker](https://zhuanlan.zhihu.com/p/23599229) \ No newline at end of file diff --git a/docs/tools/docker/1-introduce.md b/docs/tools/docker/1-introduce.md new file mode 100644 index 0000000..ca62330 --- /dev/null +++ b/docs/tools/docker/1-introduce.md @@ -0,0 +1,27 @@ +# 简介 + +Docker是一个开源的应用容器引擎,通过容器可以隔离应用程序的运行时环境(程序运行时依赖的各种库和配置),比虚拟机更轻量(虚拟机在操作系统层面进行隔离)。docker的另一个优点就是build once, run everywhere,只编译一次,就可以在各个平台(windows、linux等)运行。 + +## 基本概念 + +docker的基本概念: + +1. 镜像(image),类似于虚拟机中的镜像,可以理解为可执行程序。 + +2. 容器(container),类似于一个轻量级的沙盒,可以将其看作一个极简的Linux系统环境。Docker引擎利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。 + +3. 镜像仓库(repository),是Docker用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用tag进行区分,比如Ubuntu仓库存放有多个版本(12.04、14.04等)的Ubuntu镜像。 +4. dockerfile,image的编译配置文件,docker就是"编译器"。 + +docker的基本命令: + +1、docker build:我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,生成的可执行程序就是image。 + +2、docker run:运行image,运行起来后就是docker container。 + +3、docker pull:到Docker Hub(docker registry)下载别人写好的image。 + +![](http://img.dabin-coder.cn/image/docker.jpg) + +> 图片来源:知乎小灰 + diff --git a/docs/tools/docker/2-image-command.md b/docs/tools/docker/2-image-command.md new file mode 100644 index 0000000..00a69e6 --- /dev/null +++ b/docs/tools/docker/2-image-command.md @@ -0,0 +1,209 @@ +# docker镜像常用命令 + +## 添加docker仓库位置 + +安装yum-utils: + +``` +yum install -y yum-utils device-mapper-persistent-data lvm2 +``` + +添加仓库地址: + +``` +yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo +``` + +## 安装docker服务 + +``` +yum install docker-ce +``` + +## 启动 docker 服务 + +``` +systemctl start docker +``` + +## 重启docker服务 + +```java +systemctl restart docker.service +``` + +## 搜索镜像 + +``` +docker search java +``` + +## 下载镜像: + +不加版本号,则默认下载最新版本。 + +``` +docker pull nginx:1.18.0 +``` + +## 列出镜像 + +``` +docker images + +REPOSITORY TAG IMAGE ID CREATED SIZE +nginx 1.18.0 c2c45d506085 7 days ago 133MB +nginx 1.17.0 719cd2e3ed04 22 months ago 109MB +java 8 d23bdf5b1b1b 4 years ago 643MB +``` + +## 删除镜像 + +删除镜像前必须先删除以此镜像为基础的容器。 + +``` +docker rmi -f imageID # -f 强制删除镜像 +``` + +删除所有没有引用的镜像(找出IMAGE ID为none的镜像): + +``` +docker rmi `docker images | grep none | awk '{print $3}'` +``` + +强制删除所有镜像: + +``` +docker rmi -f $(docker images) +``` + +## 打包镜像 + +``` +# -t 表示指定镜像仓库名称/镜像名称:镜像标签 .表示使用当前目录下的Dockerfile文件 +docker build -t mall/mall-admin:1.0-SNAPSHOT . +``` + +## 创建镜像 + +镜像的创建也有两种: + +- 利用已有的镜像创建容器之后进行修改,之后commit生成镜像 +- 利用Dockerfile创建镜像 + +(1)利用已有的镜像创建容器之后进行修改 + +利用镜像启动容器: + +``` +[root@xxx ~]# docker run -it java:8 /bin/bash # 启动一个容器 +[root@72f1a8a0e394 /]# # 这里命令行形式变了,表示已经进入了一个新环境 +[root@72f1a8a0e394 /]# vim # 此时的容器中没有vim +bash: vim: command not found +[root@72f1a8a0e394 /]# apt-get update # 更新软件包 +[root@72f1a8a0e394 /]# apt-get install vim # 安装vim +``` + +exit退出该容器,然后查看docker中运行的程序(容器): + +``` +[root@VM_0_7_centos ~]# docker ps -a +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +857aa43eeed4 java:8 "/bin/bash" 19 minutes ago Exited (127) 4 seconds ago gifted_blackburn +``` + +将容器转化为一个镜像,此时Docker引擎中就有了我们新建的镜像,此镜像和原有的java镜像区别在于多了个vim工具。 + +``` +[root@VM_0_7_centos ~]# docker commit -m "java with vim" -a "tyson" 857aa43eeed4 tyson/java:vim +sha256:67c4b3658485690c9128e0b6d4c5dfa63ec100c89b417e3148f3c808254d6b9b +[root@VM_0_7_centos ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +tyson/java vim 67c4b3658485 7 seconds ago 684MB +``` + +运行新建的镜像: + +``` +[root@VM_0_7_centos ~]# docker run -it tyson/java:vim /bin/bash +root@88fead8e7db5:/# ls +bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var +root@88fead8e7db5:/# touch demo.txt +root@88fead8e7db5:/# vim demo.txt +``` + +(2)利用Dockerfile创建镜像 + +dockerfile用于告诉docker build执行哪些操作。 + +``` +#该镜像以哪个镜像为基础 +FROM java:8 + +#构建者的信息 +MAINTAINER tyson + +#build镜像执行的操作 +RUN apt-get update +RUN apt-get install vim + +#拷贝本地文件到镜像中 +COPY ./* /usr/tyson/ +``` + +利用build命令构建镜像: + +``` +docker build -t="tyson/java:vim" . +``` + +其中-t用来指定新镜像的用户信息、tag等。最后的点表示在当前目录寻找Dockerfile。 + +构建完成之后,通过`docker images`可以查看生成的镜像。 + +## 推送镜像 + +``` +# 登录Docker Hub +docker login +# 给本地镜像打标签为远程仓库名称 +docker tag mall/mall-admin:1.0-SNAPSHOT macrodocker/mall-admin:1.0-SNAPSHOT +# 推送到远程仓库 +docker push macrodocker/mall-admin:1.0-SNAPSHOT +``` + +**什么是docker hub**? + +Docker官方维护了一个DockerHub的公共仓库,里边包含有很多平时用的较多的镜像。除了从上边下载镜像之外,我们也可以将自己自定义的镜像发布(push)到DockerHub上。 + +1. 登录docker hub:`docker login` +2. 将本地镜像推送到docker hub,镜像的username需要与docker hub的username一致:`docker push tyson14/java:vim` + +## 修改镜像存放位置 + +1、查看镜像存放位置: + +``` +docker info | grep "Docker Root Dir" + Docker Root Dir: /var/lib/docker +``` + +2、关闭docker服务: + +``` +systemctl stop docker +``` + +3、原镜像目录移动到目标目录: + +``` +mv /var/lib/docker /home/data/docker +``` + +4、建立软连接: + +``` +ln -s /home/data/docker /var/lib/docker +``` + +5、再次查看镜像存放位置,发现已经修改。 \ No newline at end of file diff --git a/docs/tools/docker/3-container-command.md b/docs/tools/docker/3-container-command.md new file mode 100644 index 0000000..e949669 --- /dev/null +++ b/docs/tools/docker/3-container-command.md @@ -0,0 +1,242 @@ +# docker容器常用命令 + +## 新建容器 + +新建并启动容器(docker容器运行必须有一个前台进程, 如果没有前台进程执行,容器认为空闲,就会自行退出。所以需要先创建一个前台进程): + +``` +docker run -it --name java java:8 /bin/bash + +docker run -p 33055:33055 --name nginx \ +> -v /home/data:/home/data \ +> nginx:1.18.0 \ +> -e TZ="Asia/Shanghai" +# -d nginx:1.18.0 -d表示容器以后台方式运行 +``` + +> - -p:将宿主机和容器端口进行映射,格式为:宿主机端口:容器端口; +> - --name:指定容器名称,之后可以通过容器名称来操作容器; +> - -e:设置容器的环境变量,这里设置的是时区; +> - -v:将宿主机上的文件挂载到容器上,格式为:宿主机文件目录:容器文件目录; +> - -d:表示容器以后台方式运行。终端不会输出任何运行信息; +> - -i: 以交互模式运行容器,通常与 -t 同时使用; +> - -t: 为容器分配一个终端,通常与 -i 同时使用。 + +使用-it,此时如果使用exit退出,则容器的状态处于Exit,而不是后台运行。如果想让容器一直运行,而不是停止,可以使用快捷键 ctrl+p ctrl+q 退出,此时容器的状态为Up。 + +**创建MySQL容器**: + +```java +docker run --name mysql4blog -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3307 -d mysql:8.0.20 +``` + +> - `-name`: 给新创建的容器命名,此处命名为`mysql4blog` +> - `-e`: 配置信息,此处配置MySQL的 root 用户的登录密码 +> - `-p`: 端口映射,此处映射主机的3307端口到容器的3307端口 +> - -d: 成功启动同期后输出容器的完整ID +> - 最后一个`mysql:8.0.20`指的是`mysql`镜像 + +## 查看容器 + +列出运行中的容器,`-a`参数可以列出所有容器: + +``` +docker ps +``` + +## 停止容器 + +使用容器名称或者容器ID: + +``` +docker stop $ContainerName(or $ContainerId) +``` + +强制停止容器: + +``` +docker kill $ContainerName +``` + +## 启动容器 + +``` +docker start $ContainerName +``` + +## 重启容器 + +``` +docker restart nginx +``` + +## 进入容器 + +进入名字为mysql的容器,同时打开命令行终端。使用exit时,容器不会停止。 + +``` +docker exec -it mysql /bin/bash +``` + +docker attach可以将本机的输入直接输到容器中,容器的输出会直接显示在本机的屏幕上。如果使用exit或者ctrl+c退出,会导致容器的停止。 + +``` +docker attach container_name/container_id +``` + +新建并运行容器时,使用`docker run -it tyson/java:vim /bin/bash`,直接进入容器命令行界面。 + +使用exit退出命令行之后,重新进入容器: + +1、先查询容器id:`docker inspect --format "{{.State.Pid}}" nginx` + +2、根据查到的容器id进入容器:`nsenter --target 28487 --mount --uts --ipc --net --pid` + +``` +[root@VM_0_7_centos ~]# docker inspect --format "{{.State.Pid}}" nginx +28487 +[root@VM_0_7_centos ~]# nsenter --target 28487 --mount --uts --ipc --net --pid +mesg: ttyname failed: No such device +root@b217a35fc808:/# ls -l +``` + +## 删除容器 + +根据ContainerName删除容器: + +``` +docker rm nginx +``` + +按名称通配符删除容器,比如删除以名称`mall-`开头的容器: + +``` +docker rm `docker ps -a | grep mall-* | awk '{print $1}'` +``` + +强制删除所有容器: + +``` +docker rm -f $(docker ps -a -q) +``` + +## 容器日志 + +根据ContainerName查看容器产生的日志: + +``` +docker logs nginx +``` + +动态查看容器产生的日志: + +``` +docker logs -f nginx +``` + +实时查看日志最后200行: + +```bash +docker logs -f --tail 200 mysql +``` + +## 容器ip + +``` +docker inspect --format '{{.NetworkSettings.IPAddress}}' nginx +``` + +## 容器启动方式 + +``` +# 将容器启动方式改为always +docker container update --restart=always $ContainerName +``` + +## 资源占用 + +查看指定容器资源占用状况,比如cpu、内存、网络、io状态: + +``` +docker stats nginx + +CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS +b217a35fc808 nginx 0.00% 3.641MiB / 1.795GiB 0.20% 656B / 0B 11.3MB / 8.19kB 2 +``` + +查看所有容器资源占用情况: + +``` +docker stats -a +``` + +## 磁盘使用情况 + +``` +docker system df + +TYPE TOTAL ACTIVE SIZE RECLAIMABLE +Images 3 1 885.4MB 752.5MB (84%) +Containers 1 1 1.258kB 0B (0%) +Local Volumes 0 0 0B 0B +Build Cache 0 0 0B 0B +``` + +## 执行容器内部命令 + +``` +[root@VM_0_7_centos ~]# docker exec -it nginx /bin/bash +root@b217a35fc808:/# ll +bash: ll: command not found +root@b217a35fc808:/# ls -l +total 80 +drwxr-xr-x 2 root root 4096 Apr 8 00:00 bin +drwxr-xr-x 2 root root 4096 Mar 19 23:44 boot +``` + +指定账号进入容器内部: + +``` +docker exec -it --user root nginx /bin/bash +``` + +## 网络 + +查看网络: + +``` +docker network ls +NETWORK ID NAME DRIVER SCOPE +5f0d326b7082 bridge bridge local +af84aa332f22 host host local +741c1734f3bb none null local +``` + +创建外部网络: + +``` +docker network create -d bridge my-bridge-network +``` + +创建容器时指定网络: + +``` +docker run -p 33056:33056 --name java \ +> --network my-bridge-network \ +> java:8 +``` + +## 复制文件 + +将当前目录tpch文件夹复制到mysql容器相应的位置: + +``` +docker cp tpch mysql56:/var/lib/mysql #mysql56为容器名 +``` + +容器文件拷贝到宿主机: + +```java +docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径 +``` + diff --git a/docs/tools/docker/4-docker-compose.md b/docs/tools/docker/4-docker-compose.md new file mode 100644 index 0000000..1538869 --- /dev/null +++ b/docs/tools/docker/4-docker-compose.md @@ -0,0 +1,102 @@ +# docker-compose + +Docker Compose是一个用于定义和运行多个docker容器应用的工具。使用YAML文件配置多个应用服务,通过这个YAML文件一次性部署配置的所有服务。 + +## 安装 + +``` +curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose +``` + +修改文件的权限为可执行: + +``` +chmod +x /usr/local/bin/docker-compose +``` + +查看是否安装成功: + +``` +docker-compose --version +``` + +## 常用命令 + +创建、启动容器(默认配置文件docker-compose.yml): + +``` +# -d表示在后台运行 +docker-compose up -d +``` + +指定文件启动: + +``` +docker-compose -f docker-compose.yml up -d +``` + +停止所有相关容器: + +``` +docker-compose stop +``` + +列出所有容器信息: + +``` +docker-compose ps +``` + + + +## 部署多个服务 + +1. 使用docker-compose.yml定义需要部署的服务; +2. 使用docker-compose up命令一次性部署配置的所有服务。 + +## 定义配置文件 + +ports:指定主机和容器的端口映射(HOST:CONTAINER) + +volumes:将主机目录挂载到容器(HOST:CONTAINER) + +link:连接其他容器(同一个网络下)的服务(SERVICE:ALIAS) + +```yaml +services: + elasticsearch: + image: elasticsearch:7.6.2 + container_name: elasticsearch + user: root + environment: + - "cluster.name=elasticsearch" #设置集群名称为elasticsearch + - "discovery.type=single-node" #以单一节点模式启动 + - "ES_JAVA_OPTS=-Xms128m -Xmx128m" #设置使用jvm内存大小 + volumes: + - /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载 + - /mydata/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载 + ports: + - 9200:9200 + - 9300:9300 + logstash: + image: logstash:7.6.2 + container_name: logstash + environment: + - TZ=Asia/Shanghai + volumes: + - /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件 + depends_on: + - elasticsearch #kibana在elasticsearch启动之后再启动 + link: + - elasticsearch:es #可以用es这个域名访问elasticsearch服务 +``` + +## 启动服务 + +先将docker-compose.yml上传至Linux服务器,再在当前目录下运行如下命令(默认配置文件docker-compose.yml): + +``` +docker-compose up -d +``` + + diff --git a/docs/tools/docker/5-maven-build.md b/docs/tools/docker/5-maven-build.md new file mode 100644 index 0000000..b734b08 --- /dev/null +++ b/docs/tools/docker/5-maven-build.md @@ -0,0 +1,136 @@ +# maven插件构建docker镜像 + +## docker镜像仓库 + +服务器创建docker镜像仓库docker registry: + +``` +docker run -d -p 5000:5000 --restart=always --name registry2 registry:2 +``` + +## docker开启远程访问 + +docker开启远程访问的端口2375,修改docker.service文件: + +``` +vi /usr/lib/systemd/system/docker.service +``` + +修改内容如下: + +``` +ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock +ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock +``` + +`unix:///var/run/docker.sock`:unix socket,本地客户端将通过这个来连接 Docker Daemon。 +`tcp://0.0.0.0:2375`:tcp socket,表示允许任何远程客户端通过 2375 端口连接 Docker Daemon。 + +## docker支持http上传镜像 + +``` +echo '{ "insecure-registries":["192.168.3.101:5000"] }' > /etc/docker/daemon.json +``` + +## 重启docker + +使配置生效: + +``` +systemctl daemon-reload +``` + +重启docker服务: + +``` +systemctl restart docker +``` + +## 开放端口 + +``` +firewall-cmd --zone=public --add-port=2375/tcp --permanent +firewall-cmd --reload +``` + +## 构建docker镜像 + +在应用的pom.xml文件中添加docker-maven-plugin的依赖: + +```xml + + com.spotify + docker-maven-plugin + 1.1.0 + + + build-image + package + + build + + + + + mall-tiny/${project.artifactId}:${project.version} + http://tysonbin.com:2375 + java:8 + ["java", "-jar","/${project.build.finalName}.jar"] + + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + +``` + +相关配置说明: + +- executions.execution.phase:此处配置了在maven打包应用时构建docker镜像; +- imageName:用于指定镜像名称,mall-tiny是仓库名称,`${project.artifactId}`为镜像名称,`${project.version}`为版本号; +- dockerHost:打包后上传到的docker服务器地址; +- baseImage:该应用所依赖的基础镜像,此处为java; +- entryPoint:docker容器启动时执行的命令; +- resources.resource.targetPath:将打包后的资源文件复制到该目录; +- resources.resource.directory:需要复制的文件所在目录,maven打包的应用jar包保存在target目录下面; +- resources.resource.include:需要复制的文件,打包好的应用jar包。 + +修改application.yml中的域名,将localhost改为db。可以把docker中的容器看作独立的虚拟机,mall-tiny-docker访问localhost自然会访问不到mysql,docker容器之间可以通过指定好的服务名称db进行访问,至于db这个名称可以在运行mall-tiny-docker容器的时候指定。 + +```yaml +spring: + datasource: + url: jdbc:mysql://db:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai + username: root + password: root +``` + +执行maven的package命令,执行成功之后,镜像仓库会生成mall-tiny-docker镜像。 + +启动mysql服务: + +``` +docker run -p 3306:3306 --name mysql \ +-v /mydata/mysql/log:/var/log/mysql \ +-v /mydata/mysql/data:/var/lib/mysql \ +-v /mydata/mysql/conf:/etc/mysql \ +-e MYSQL_ROOT_PASSWORD=root \ +-d mysql:5.7 +``` + +进入运行mysql的docker容器:`docker exec -it mysql /bin/bash` + +启动mall-tiny-docker服务,通过--link表示在同一个网络内(可以在启动容器时通过--network指定),应用可以用db这个域名访问mysql服务: + +``` +docker run -p 8080:8080 --name mall-tiny-docker \ +--link mysql:db \ # 在同一个网络内不同容器之间可以通过--link指定的服务别名互相访问,containName:alias +-v /etc/localtime:/etc/localtime \ +-v /mydata/app/mall-tiny-docker/logs:/var/logs \ +-d mall-tiny/mall-tiny-docker:0.0.1-SNAPSHOT +``` + diff --git a/docs/tools/docker/6-other.md b/docs/tools/docker/6-other.md new file mode 100644 index 0000000..af19572 --- /dev/null +++ b/docs/tools/docker/6-other.md @@ -0,0 +1,53 @@ +# 其他 + +## 给nginx增加端口映射 + +nginx一开始只映射了80端口,后面载部署项目的时候,需要用到其他端口,不想重新部署容器,所以通过修改配置文件的方式给容器添加其他端口。 + +1、执行命令`docker inspect nginx`,找到容器id + +2、停止容器`docker stop nginx`,不然修改了配置会自动还原 + +3、修改hostconfig.json + +```java +cd /var/lib/docker/containers/135254e3429d1e75aa68569137c753b789416256f2ced52b4c5a85ec3849db87 # container id +vim hostconfig.json +``` + +添加端口: + +```java +"PortBindings": { + "80/tcp": [ + { + "HostIp": "", + "HostPort": "80" + } + ], + "8080/tcp": [ + { + "HostIp": "", + "HostPort": "8080" + } + ] +}, +``` + +4、修改同目录下 config.v2.json + +```java +"ExposedPorts": { + "80/tcp": {}, + "8080/tcp": {}, + "8189/tcp": {} +}, +``` + +5、重启容器 + +```java +systemctl restart docker.service # 重启docker服务 +docker start nginx +``` + diff --git a/docs/tools/docker/README.md b/docs/tools/docker/README.md new file mode 100644 index 0000000..5288fd6 --- /dev/null +++ b/docs/tools/docker/README.md @@ -0,0 +1,17 @@ +--- +title: Docker基础 +icon: docker +date: 2022-08-06 +category: docker +star: true +--- + +![](http://img.dabin-coder.cn/image/docker-img.png) +## Docker总结 + +- [简介](./1-introduce.md) +- [docker镜像常用命令](./2-image-command.md) +- [docker容器常用命令](./3-container-command.md) +- [docker-compose](./4-docker-compose.md) +- [maven插件构建docker镜像](./5-maven-build.md) +- [其他](./6-other.md) diff --git "a/\345\267\245\345\205\267/git-overview.md" b/docs/tools/git-overview.md similarity index 81% rename from "\345\267\245\345\205\267/git-overview.md" rename to docs/tools/git-overview.md index a79a027..efa45a8 100644 --- "a/\345\267\245\345\205\267/git-overview.md" +++ b/docs/tools/git-overview.md @@ -1,74 +1,3 @@ - - - - -- [Git 简介](#git-%E7%AE%80%E4%BB%8B) - - [Git工作流程](#git%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B) - - [存储原理](#%E5%AD%98%E5%82%A8%E5%8E%9F%E7%90%86) - - [Git 快照](#git-%E5%BF%AB%E7%85%A7) - - [三种状态](#%E4%B8%89%E7%A7%8D%E7%8A%B6%E6%80%81) - - [配置](#%E9%85%8D%E7%BD%AE) - - [获取帮助](#%E8%8E%B7%E5%8F%96%E5%B8%AE%E5%8A%A9) -- [Git 基础](#git-%E5%9F%BA%E7%A1%80) - - [获取 Git 仓库](#%E8%8E%B7%E5%8F%96-git-%E4%BB%93%E5%BA%93) - - [文件状态](#%E6%96%87%E4%BB%B6%E7%8A%B6%E6%80%81) - - [配置别名](#%E9%85%8D%E7%BD%AE%E5%88%AB%E5%90%8D) - - [工作区](#%E5%B7%A5%E4%BD%9C%E5%8C%BA) - - [暂存区](#%E6%9A%82%E5%AD%98%E5%8C%BA) - - [提交](#%E6%8F%90%E4%BA%A4) - - [修改commit信息](#%E4%BF%AE%E6%94%B9commit%E4%BF%A1%E6%81%AF) - - [查看提交历史](#%E6%9F%A5%E7%9C%8B%E6%8F%90%E4%BA%A4%E5%8E%86%E5%8F%B2) - - [版本回退](#%E7%89%88%E6%9C%AC%E5%9B%9E%E9%80%80) - - [stash](#stash) - - [rm和mv](#rm%E5%92%8Cmv) - - [忽略文件](#%E5%BF%BD%E7%95%A5%E6%96%87%E4%BB%B6) - - [skip-worktree和assume-unchanged](#skip-worktree%E5%92%8Cassume-unchanged) - - [远程仓库](#%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [查看远程仓库](#%E6%9F%A5%E7%9C%8B%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [添加远程仓库](#%E6%B7%BB%E5%8A%A0%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [修改远程仓库](#%E4%BF%AE%E6%94%B9%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [pull 和 fetch](#pull-%E5%92%8C-fetch) - - [本地仓库上传git服务器](#%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E4%B8%8A%E4%BC%A0git%E6%9C%8D%E5%8A%A1%E5%99%A8) - - [推送到远程仓库](#%E6%8E%A8%E9%80%81%E5%88%B0%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [查看远程仓库](#%E6%9F%A5%E7%9C%8B%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93-1) - - [远程仓库移除和命名](#%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E7%A7%BB%E9%99%A4%E5%92%8C%E5%91%BD%E5%90%8D) - - [标签](#%E6%A0%87%E7%AD%BE) - - [创建标签](#%E5%88%9B%E5%BB%BA%E6%A0%87%E7%AD%BE) - - [附注标签](#%E9%99%84%E6%B3%A8%E6%A0%87%E7%AD%BE) - - [轻量标签](#%E8%BD%BB%E9%87%8F%E6%A0%87%E7%AD%BE) - - [推送标签](#%E6%8E%A8%E9%80%81%E6%A0%87%E7%AD%BE) - - [后期打标签](#%E5%90%8E%E6%9C%9F%E6%89%93%E6%A0%87%E7%AD%BE) - - [共享标签](#%E5%85%B1%E4%BA%AB%E6%A0%87%E7%AD%BE) - - [检出标签](#%E6%A3%80%E5%87%BA%E6%A0%87%E7%AD%BE) - - [git 别名](#git-%E5%88%AB%E5%90%8D) -- [git 分支](#git-%E5%88%86%E6%94%AF) - - [分支创建](#%E5%88%86%E6%94%AF%E5%88%9B%E5%BB%BA) - - [分支切换](#%E5%88%86%E6%94%AF%E5%88%87%E6%8D%A2) - - [分支合并](#%E5%88%86%E6%94%AF%E5%90%88%E5%B9%B6) - - [合并冲突](#%E5%90%88%E5%B9%B6%E5%86%B2%E7%AA%81) - - [rebase](#rebase) - - [删除分支](#%E5%88%A0%E9%99%A4%E5%88%86%E6%94%AF) - - [分支管理](#%E5%88%86%E6%94%AF%E7%AE%A1%E7%90%86) - - [远程分支](#%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF) - - [推送](#%E6%8E%A8%E9%80%81) - - [跟踪分支](#%E8%B7%9F%E8%B8%AA%E5%88%86%E6%94%AF) - - [fetch和pull](#fetch%E5%92%8Cpull) - - [删除远程分支](#%E5%88%A0%E9%99%A4%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF) - - [创建远程分支](#%E5%88%9B%E5%BB%BA%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF) - - [cherry-pick](#cherry-pick) - - [cherry-pick与rebase的区别](#cherry-pick%E4%B8%8Erebase%E7%9A%84%E5%8C%BA%E5%88%AB) - - [补丁](#%E8%A1%A5%E4%B8%81) - - - -> 首先给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ -> -> github地址:https://github.com/Tyson0314/java-books -> -> 如果github访问不了,可以访问gitee仓库。 -> -> gitee地址:https://gitee.com/tysondai/java-books - # Git 简介 Git 是一个开源的分布式版本控制系统,可以有效、快速的进行项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 @@ -156,7 +85,7 @@ git clone https://github.com/... 查看文件状态:`git status` -![git生命周期](http://img.dabin-coder.cn/image/git生命周期.png) +![](http://img.dabin-coder.cn/image/git生命周期.png) > 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` @@ -420,11 +349,11 @@ assume-unchanged: git ls-files -v | grep '^h\ ' ``` -## 远程仓库 +# 远程仓库 远程仓库是指托管在网络中的项目版本库。 -### 查看远程仓库 +## 查看远程仓库 查看远程仓库地址: @@ -434,7 +363,7 @@ origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push) ``` -### 添加远程仓库 +## 添加远程仓库 运行 `git remote add ` 添加远程 Git 仓库,同时指定一个简写名称。 @@ -452,7 +381,7 @@ git remote add pb https://github.com/paulboone/ticgit git remote remove origin ``` -### 给origin设置多个远程仓库 +## 给origin设置多个远程仓库 如果想要给origin设置两个远程仓库地址(git add会报错),可以使用`git remote set-url --add origin url`来设置。 @@ -464,7 +393,7 @@ $ git remote set-url --add origin xxx.git #success ``` -### 修改远程仓库 +## 修改远程仓库 修改远程仓库地址: @@ -472,7 +401,7 @@ $ git remote set-url --add origin xxx.git git remote set-url origin git@github.com:Tyson0314/Blog.git ``` -### pull 和 fetch +## pull 和 fetch 从远程仓库获取数据: @@ -489,7 +418,7 @@ git pull = git fetch + git merge FETCH_HEAD git pull --rebase = git fetch + git rebase FETCH_HEAD ``` -### 本地仓库上传git服务器 +## 本地仓库上传git服务器 ```bash git init # 将目录变成本地仓库 @@ -502,7 +431,7 @@ git push -u origin master # 如果当前分支与多个主机存在追踪关系 ``` -### 推送到远程仓库 +## 推送到远程仓库 推送使用命令:`git push [remote-name] [branch-name]` @@ -510,13 +439,13 @@ git push -u origin master # 如果当前分支与多个主机存在追踪关系 git push origin master ``` -### 查看远程仓库 +## 查看远程仓库 ```bash git remote show origin ``` -### 远程仓库移除和命名 +## 远程仓库移除和命名 移除远程仓库: @@ -530,7 +459,7 @@ git remote rm paul git remote rename old-name new-name ``` -## 标签 +# 标签 给历史的某个提交打标签,如标记发布节点(v1.0等)。 @@ -547,13 +476,13 @@ tag标签可以帮助我们回退到某个版本的代码,我们通过tag的 - 回退到某个版本:git reset --hard commitId - 获取远程分支:git fetch origin tag V2.0 -### 创建标签 +## 创建标签 Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。然而,附注标签是存储在 Git 数据库中的一个完整对象。 它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证。 通常建议创建附注标签。 创建的标签都只存储在本地,不会自动推送到远程。 -#### 附注标签 +## 附注标签 添加附注标签: @@ -565,7 +494,7 @@ git tag -a v1.4 -m 'my version 1.4' 使用 `git show v1.4` 命令可以看到标签信息和对应的提交信息。 -#### 轻量标签 +## 轻量标签 添加轻量标签: @@ -575,7 +504,7 @@ git tag v1.4-tyson 此时运行 `git show v1.4-tyson`不会看到额外的标签信息,只显示提交信息。 -### 推送标签 +## 推送标签 推送某个标签到远程,使用命令: @@ -595,7 +524,7 @@ git push origin --tags git push origin :refs/tags/ ``` -### 后期打标签 +## 后期打标签 比如给下面的这个提交( `modified readme.md` )打标签:` git tag -a v1.2 c1285b` @@ -608,7 +537,7 @@ ba8e8a5fb932014b4aaf9ccd3163affb7699d475 renamed d2ffb8c33978295aed189f5854857bc4e7b55358 add readme.md ``` -### 共享标签 +## 共享标签 git push 命令并不会传送标签到远程仓库服务器上。在创建完标签后你必须显式地推送标签到共享服务器上: @@ -622,7 +551,7 @@ git push origin v1.5 git push origin --tags ``` -### 检出标签 +## 检出标签 如果你想要工作目录与仓库中特定的标签版本完全一样,可以使用 `git checkout -b [branchname] [tagname]` 在特定的标签上创建一个新分支: @@ -631,20 +560,6 @@ $ git checkout -b version2 v2.0.0 Switched to a new branch 'version2' ``` -## git 别名 - -取消暂存别名: - -```bash -git config --global alias.unstage 'reset HEAD --' -``` - -最后一次提交: - -```bash -git config --global alias.last 'log -1 HEAD' -``` - # git 分支 Git 鼓励在工作流程中频繁地使用分支与合并。 @@ -748,16 +663,16 @@ merge操作会生成一个新的节点,之前的提交分开显示。 pick c38e7ae rebase content s 595ede1 rebase -# Rebase 8824682..595ede1 onto 8824682 (2 commands) -# -# Commands: -# p, pick = use commit -# r, reword = use commit, but edit the commit message -# e, edit = use commit, but stop for amending -# s, squash = use commit, but meld into previous commit -# f, fixup = like "squash", but discard this commit's log message -# x, exec = run command (the rest of the line) using shell -# d, drop = remove commit +-- Rebase 8824682..595ede1 onto 8824682 (2 commands) + +-- Commands: +-- p, pick = use commit +-- r, reword = use commit, but edit the commit message +-- e, edit = use commit, but stop for amending +-- s, squash = use commit, but meld into previous commit +-- f, fixup = like "squash", but discard this commit's log message +-- x, exec = run command (the rest of the line) using shell +-- d, drop = remove commit ``` `s 595ede1 rebase`会将595ede1合到前一个commit,按下`:wq`之后会弹出对话框,合并commit message。 diff --git a/docs/tools/git/1-introduce.md b/docs/tools/git/1-introduce.md new file mode 100644 index 0000000..5aadec6 --- /dev/null +++ b/docs/tools/git/1-introduce.md @@ -0,0 +1,71 @@ +# Git 简介 + +Git 是一个开源的分布式版本控制系统,可以有效、快速的进行项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 + +## Git工作流程 + +Git工作流程如下: + +- 从远程仓库中克隆资源作为本地仓库; +- 在本地仓库中进行代码修改; +- 在提交本地仓库前先将代码提交到暂存区; +- 提交修改,提交到本地仓库。本地仓库中保存修改的所有历史版本; +- 在需要和团队成员共享代码时,可以将修改的代码push到远程仓库。 + +Git 的工作流程图如下: + +![](http://img.dabin-coder.cn/image/git-work-flow.png) + +> 图片来源:https://blog.csdn.net/ThinkWon/article/details/94346816 + +## 存储原理 + +Git 在保存项目状态时,它主要对全部文件制作一个快照并保存这个快照的索引,如果文件没有被修改,Git 不会重新存储这个文件,而是只保留一个链接指向之前存储的文件。 + +## Git 快照 + +快照就是将旧文件所占的空间保留下来,并且保存一个引用,而新文件中会继续使用与旧文件内容相同部分的磁盘空间,不同部分则写入新的磁盘空间。 + +## 三种状态 + +Git 的三种状态:已修改(modified)、已暂存(staged)和已提交(committed)。已修改表示修改了文件,但还没保存到数据库。已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。已提交表示数据已经安全的保存到本地数据库。 + +基本的 Git 工作流程:在工作目录修改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 + +![](http://img.dabin-coder.cn/image/git工作流程.png) + +> 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png` + +![](http://img.dabin-coder.cn/image/git-status.png) + +## 配置 + +设置用户名和邮箱地址: + +```bash +git config --global user.name "dabin" +git config --global user.email xxx@xxx.com +``` + +如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情,Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。 + +查看配置信息: + +```bash +git config --list +``` + +查看某一项配置: + +```bash +git config user.name +``` + +## 获取帮助 + +获取 config 命令的手册: + +```bash +git help config +``` + diff --git a/docs/tools/git/2-basic.md b/docs/tools/git/2-basic.md new file mode 100644 index 0000000..ed6b7d9 --- /dev/null +++ b/docs/tools/git/2-basic.md @@ -0,0 +1,280 @@ +# Git 基础 + +## 获取 Git 仓库 + +在现有目录中初始化仓库:进入项目目录并输入`git init` + +克隆现有的仓库: + +```bash +git clone https://github.com/... +``` + +## 文件状态 + +查看文件状态:`git status` + +![](http://img.dabin-coder.cn/image/git生命周期.png) + +> 图片来源:`https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png` + +**状态说明:** + +新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记,如下图,`MM Rakefile`出现两个M,其中出现在靠左边的 M 表示该文件被修改了并放入了暂存区,出现在右边的 M 表示该文件被修改了但是还没放入暂存区。 + +```bash +$ git status -s + M README # 右边的 M 表示该文件被修改了但是还没放入暂存区 +MM Rakefile # 左边的 M 表示该文件被修改了并放入了暂存区;右边的 M 表示该文件被修改了但是还没放入暂存区 +A lib/git.rb # A表示新添加到暂存区中的文件 +?? LICENSE.txt # ??表示新添加的未跟踪文件 +``` + +## 配置别名 + +有些人可能经常敲错命令,通过配置别名可以简化命令: + +通过命令 `git config --global alias.st status ` 将 命令`git status` 简化为 `git st`: + +```bash +$ git config --global alias.st status + +$ git st +On branch master +Your branch is up to date with 'origin/master'. + +nothing to commit, working tree clean +``` + + +## 工作区 + +查看工作区修改:`git diff` + +```bash +$ git diff +diff --git a/md/leetcode刷题笔记.md b/md/leetcode刷题笔记.md +deleted file mode 100644 +index 63a7c90..0000000 +--- a/md/leetcode刷题笔记.md ++++ /dev/null +``` + +撤销工作区修改: + +```bash +git checkout -- file_name +``` + +此命令会撤销工作区的修改,不可恢复,不会撤销暂存区修改。 + +撤销修改还可以使用 restore 命令(git2.23版本引入)。 + +```java +git restore --worktree demo.txt //撤销文件工作区的修改 +git restore --staged demo.txt //撤销暂存区的修改,将文件状态恢复到未add之前 +git restore -s HEAD~1 demo.txt //将当前工作区切换到上个 commit 版本,-s相当于--source +git restore -s hadn12 demo.txt //将当前工作区切换到指定 commit id 的版本 +``` + + +## 暂存区 + +通过`git add filename` 将工作区的文件放到暂存区。 + +```bash +git add README.md +``` + +查看暂存区修改: + +```bash +$ git diff --staged +diff --git a/README.md b/README.md +index ecd6c7a..653f001 100644 +--- a/README.md ++++ b/README.md +``` + +可以看到暂存区中有 README.md 文件,说明README.md文件被放到了暂存区。 + +撤销暂存区修改使用unstage: + +```bash +git reset HEAD file_name +``` + +将文件修改移出暂存区,放到工作区。 + +**git reset 加上 --hard 选项会导致工作目录中所有修改丢失。** + +## 提交 + +任何未提交的修改丢失后很可能不可恢复。提交命令: + +```bash +git commit -m "add readme.md" +``` + +`git commit -a -m "xxx"` 相当于`git add`和`git commit -m "xxx"`,将 tracked 的文件直接提交。untracked 的文件无法使用此命令直接提交,需先执行 git add 命令,再执行 git commit。 + +单独执行`git commit`,不带上-m参数,会进入 vim 编辑器界面: + +![](http://img.dabin-coder.cn/image/image-20210830225020753.png) + +此时应该这么操作: + +1. 按下字母键`i`或`a`或`o`,进入到可编辑状态 +2. 输入commit信息之后,按下`Esc`键就可退出编辑状态,回到一般模式 +3. 输入:wq (保存退出)或 :wq!(强行退出,不保存) + +### 修改commit信息 + +如果提交后发现漏掉某些文件或者提交信息写错,使用`git commit --amend`重新提交: + +```bash +git commit -m 'initial commit' +git add forgotten_file +git commit --amend +``` + + +### 查看提交历史 + +`git log`列出所有提交的更新。 + +`git log -p -2`,-p 用来显示每次提交的内容差异,-2表示显示最近两次提交。 + +`git log --stat`每次提交下面都会列出所有被修改的文件、有多少文件被修改和哪些行被修改等。 + +`git log --pretty=oneline`将每个提交放在一行显示。 + +`git log --pretty=format:"%h %s" --graph` format 表示格式化输出,%h 提交对象的简短哈希串,%s 是提交说明,--graph 可以更形象的展示分支、合并历史。 + +```bash +$ git log --pretty=format:"%h %s" --graph +* 75f8b36 update +* cd72e4f 删除查询性能优化 +* 6bddc95 MySQL总结整理 +* f8ace0e java常见关键字总结 +* 0c4efeb 删除android +* 4844de5 mysql执行计划 +* 635c140 redis分布式锁 +* 7b65bc3 update +* e563eec update +* 67e1cf7 update readme +* 218f353 调整目录结构 +* 9428314 整理Java基础内容 +``` + +`git log --since=2.weeks` 按照时间作限制。 + +## 版本回退 + +版本回退使用`git reset`命令。 + +```bash +git reset --hard commit_id +git reset --hard HEAD^ # 回退所有内容到上一个版本 +git reset --hard HEAD^^ # 回退所有内容到上上一个版本 +git reset --hard HEAD~100 # 回退到之前第100个版本 +git reset HEAD readme.txt # 把暂存区的修改撤销掉(unstage), 重新放到工作区 +``` + +## stash + +将未提交的修改保存起来。用于后续恢复当前工作目录。 + +```bash +git stash +git stash pop stash@{id} //恢复后删除 +git stash apply stash@{id} //恢复后不删除,需手动删除 +git stage drop +git stash list //查看stash 列表 +git stash show -p stash@{0} //查看stash具体内容,-p查看diff,stash@{0}可以省略 +``` + +## rm和mv + +`git rm readme.md`:文件未被修改过,从暂存区移除文件,然后提交,相当于 `rm readme.md`和`git add .`。如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit”。 + +`git rm --cached README.md`:让文件保留在工作区,但是不想让 Git 继续跟踪。可以使用 --cached 选项来实现。文件被修改过,还没有放进暂存区,则必须要用强制删除选项 -f ,以防止误删还没有添加到暂存区的数据,这样的数据不能被 Git 恢复。 + +git rm 支持正则表达式: + +```bash +git rm log/\*.log +``` + +对文件改名: + +```bash +git mv README.md README +``` + +相当于运行一下三条命令: + +```bash +mv README.md README +git rm README.md +git add README +``` + +## 忽略文件 + +.gitignore 只能忽略未跟踪状态的文件。 + +如果远程仓库已经有了logs文件夹,使用以下命令可以删除文件的跟踪状态。 + +```bash +git rm --cached logs/xx.log +``` + +此时本地工作区修改还在。然后更新 .gitignore 文件,最后使用下面的命令删除远程仓库对应的文件。 + +```bash +git add . & git commit -m "xx" & git push +``` + +### skip-worktree和assume-unchanged + +skip-worktree: + +- skip-worktree 可以实现修改本地文件不会被提交,但又可以拉取最新更改的需求。适用于一些不经常变动,但是必须本地化设置的文件。 + + ```bash + git update-index --skip-worktree [file] + ``` + +- 取消skip-worktree: + + ```bash + git update-index --no-skip-worktree [file] + ``` + +- 查看 skip-worktree 列表: + + ```bash + git ls-files -v | grep '^S\ ' + ``` + +assume-unchanged: + +- 该命令只是假设文件没有变动,使用reset时,会将文件修改回去。当远程仓库相应的文件被修改时,pull更新之后,--assume-unchanged 会被清除。 + + ```bash + git update-index --assume-unchanged [file] + ``` + +- 取消忽略: + + ```bash + git update-index --no-assume-unchanged file/path + ``` + +- 查看忽略了哪些文件: + + ```bash + git ls-files -v | grep '^h\ ' + ``` + diff --git a/docs/tools/git/3-remote-repo.md b/docs/tools/git/3-remote-repo.md new file mode 100644 index 0000000..2be1371 --- /dev/null +++ b/docs/tools/git/3-remote-repo.md @@ -0,0 +1,110 @@ +# 远程仓库 + +远程仓库是指托管在网络中的项目版本库。 + +## 查看远程仓库 + +查看远程仓库地址: + +```bash +$ git remote -v +origin https://github.com/schacon/ticgit (fetch) +origin https://github.com/schacon/ticgit (push) +``` + +## 添加远程仓库 + +运行 `git remote add ` 添加远程 Git 仓库,同时指定一个简写名称。 + +```bash +git remote add pb https://github.com/paulboone/ticgit +``` + +如上命令,可以在命令行中使用字符串 pb 来代替整个 URL。如`git fetch pb`。 + +如果使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 origin 为默认简写名称。 + +取消关联Git仓库: + +```bash +git remote remove origin +``` + +## 给origin设置多个远程仓库 + +如果想要给origin设置两个远程仓库地址(git add会报错),可以使用`git remote set-url --add origin url`来设置。 + +```bash +$ git remote add origin xxx.git +fatal: remote origin already exists. + +$ git remote set-url --add origin xxx.git +#success +``` + +## 修改远程仓库 + +修改远程仓库地址: + +```bash +git remote set-url origin git@github.com:Tyson0314/Blog.git +``` + +## pull 和 fetch + +从远程仓库获取数据: + +```bash +git fetch [remote-name] +``` + +git fetch 命令将数据拉取到本地仓库,但它并不会自动合并到本地分支,必须手动将其合并本地分支。 + +git pull 通常会从远程仓库拉取数据并自动尝试合并到当前所在的分支。 + +```bash +git pull = git fetch + git merge FETCH_HEAD +git pull --rebase = git fetch + git rebase FETCH_HEAD +``` + +## 本地仓库上传git服务器 + +```bash +git init # 将目录变成本地仓库 +git add . +git commit -m 'xxx' # 提交到本地仓库 +git remote add origin https://github.com/Tyson0314/profile # 关联远程仓库 +git branch --set-upstream-to=origin/master master # 本地分支关联远程分支 +git pull origin master --allow-unrelated-histories # 允许合并不相关的历史 +git push -u origin master # 如果当前分支与多个主机存在追踪关系,则-u会指定一个默认主机,这样后面就可以不加任何参数使用git push。 +``` + + +## 推送到远程仓库 + +推送使用命令:`git push [remote-name] [branch-name]` + +```bash +git push origin master +``` + +## 查看远程仓库 + +```bash +git remote show origin +``` + +## 远程仓库移除和命名 + +移除远程仓库: + +```bash +git remote rm paul +``` + +重命名远程仓库: + +```bash +git remote rename old-name new-name +``` + diff --git a/docs/tools/git/4-label.md b/docs/tools/git/4-label.md new file mode 100644 index 0000000..604a817 --- /dev/null +++ b/docs/tools/git/4-label.md @@ -0,0 +1,101 @@ +# 标签 + +给历史的某个提交打标签,如标记发布节点(v1.0等)。 + +tag标签可以帮助我们回退到某个版本的代码,我们通过tag的名称即可回退,而不需要根据某个提冗长的commit ID来回退: + +- 查看本地tag:git tag +- 新建tag:git tag -a v2.0 -m 'msg' +- 推送指定tag至远程:git push origin v2.0 +- 推送本地所有tag至远程:git push origin --tags +- 删除本地tag:git tag -d v2.0 +- 删除远程tag:git push origin --delete tag 2.0 +- 本地查看不同tag的代码:get checkout v1.0 +- 查看标签详情(包含commitId):git show v1.0 +- 回退到某个版本:git reset --hard commitId +- 获取远程分支:git fetch origin tag V2.0 + +## 创建标签 + +Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。然而,附注标签是存储在 Git 数据库中的一个完整对象。 它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证。 通常建议创建附注标签。 + +创建的标签都只存储在本地,不会自动推送到远程。 + +## 附注标签 + +添加附注标签: + +```bash +git tag -a v1.4 -m 'my version 1.4' +``` + +-m 选项指定标签的信息。 + +使用 `git show v1.4` 命令可以看到标签信息和对应的提交信息。 + +## 轻量标签 + +添加轻量标签: + +```bash +git tag v1.4-tyson +``` + + 此时运行 `git show v1.4-tyson`不会看到额外的标签信息,只显示提交信息。 + +## 推送标签 + +推送某个标签到远程,使用命令: + +```bash +git push origin +``` + +一次性推送全部尚未推送到远程的本地标签: + +````bash +git push origin --tags +```` + +删除远程标签(先删除本地标签) : + +```bash +git push origin :refs/tags/ +``` + +## 后期打标签 + +比如给下面的这个提交( `modified readme.md` )打标签:` git tag -a v1.2 c1285b` + +```bash +$ git log --pretty=oneline +22fb43d9f59b983feb64ee69bd0658f37ea45db6 (HEAD -> master, tag: v1.4-tyson, tag: v1.4) add file note.md +aab2fda0b604dc295fc2bd5bfef14f3b8e3c5a98 add one line +c1285bcff4ef6b2aefdaf94eb9282fd4257621c6 modified readme.md +ba8e8a5fb932014b4aaf9ccd3163affb7699d475 renamed +d2ffb8c33978295aed189f5854857bc4e7b55358 add readme.md +``` + +## 共享标签 + +git push 命令并不会传送标签到远程仓库服务器上。在创建完标签后你必须显式地推送标签到共享服务器上: + +```bash +git push origin v1.5 +``` + +把所有不在远程仓库服务器上的标签全部传送到那里: + +```bash +git push origin --tags +``` + +## 检出标签 + +如果你想要工作目录与仓库中特定的标签版本完全一样,可以使用 `git checkout -b [branchname] [tagname]` 在特定的标签上创建一个新分支: + +```bash +$ git checkout -b version2 v2.0.0 +Switched to a new branch 'version2' +``` + diff --git a/docs/tools/git/5-branch.md b/docs/tools/git/5-branch.md new file mode 100644 index 0000000..5e41e9f --- /dev/null +++ b/docs/tools/git/5-branch.md @@ -0,0 +1,305 @@ +# git 分支 + +Git 鼓励在工作流程中频繁地使用分支与合并。 + +Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。git 提交对象会包含一个指向暂存内容快照的指针。 + +## 分支创建 + +创建 tyson 分支: + +```bash +git branch testing +``` + +查看远程分支: + +```bash +git branch -r +``` + + +## 分支切换 + +使用 `git checkout branch-name` 切换分支: + +```bash +git checkout testing +``` + +查看各个分支当前所指的对象:`git log --oneline --decorate` + +```bash +$ git log --oneline --decorate +22fb43d (HEAD -> master, tag: v1.4-tyson, tag: v1.4, tyson) add file note.md +aab2fda add one line +c1285bc (tag: v1.2) modified readme.md +ba8e8a5 renamed +d2ffb8c add readme.md +``` + +master 和 tyson 分支都指向校验和为 22fb43d 的提交对象。 + +`git checkout -b iss53` = `git branch iss53` + `git checkout iss53` + +## 分支合并 + +合并 iss53 分支到 master 分支: + +```bash +git checkout mastergit merge iss53 +``` + +squash merge:合并多个 commit 为一个,合并完需要重新提交,会修改原 commit 的提交信息,包括 author。 + +### 合并冲突 + +当合并产生冲突时不会自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于 unmerged 状态的文件。 + +```bash +<<<<<<< HEAD:index.html + +======= + +>>>>>>> iss53:index.html +``` + +在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。然后输入 `git commit -m "merge branch iss53"`完成合并提交。 + +## rebase + +现在我们有这样的两个分支,test和master,提交如下: + +```bash + D---E test + / + A---B---C---F--- master +``` + +在master执行git merge test,会生成额外的提交节点G: + +```bash + D--------E + / \ + A---B---C---F----G--- test, master +``` + +在master执行git rebase test,本地提交以补丁形式打在分支的最后面: + +```bash +A---B---D---E---C‘---F‘--- test, master +``` + +merge操作会生成一个新的节点,之前的提交分开显示。 + 而rebase操作不会生成新的节点,是将两个分支融合成一个线性的提交。 + +合并commit:`git rebase -i` + +```bash +pick c38e7ae rebase content +s 595ede1 rebase + +-- Rebase 8824682..595ede1 onto 8824682 (2 commands) + +-- Commands: +-- p, pick = use commit +-- r, reword = use commit, but edit the commit message +-- e, edit = use commit, but stop for amending +-- s, squash = use commit, but meld into previous commit +-- f, fixup = like "squash", but discard this commit's log message +-- x, exec = run command (the rest of the line) using shell +-- d, drop = remove commit +``` + +`s 595ede1 rebase`会将595ede1合到前一个commit,按下`:wq`之后会弹出对话框,合并commit message。 + +## 删除分支 + +删除本地分支: + +```bash +git branch -d tyson +``` + +删除远程分支: + +```bash +git push origin --delete master +``` + + +## 分支管理 + +得到当前所有分支的一个列表: + +``` +$ git branch +* master + tyson +``` + +\*代表当前 HEAD 指针所指向的分支。 + +查看每一个分支的最后一次提交: + +``` +$ git branch -v* master 22fb43d add file note.md tyson 22fb43d add file note.md +``` + +查看哪些分支已经合并到当前分支: + +``` +$git branch --merged iss53 *master +``` + +查看所有包含未合并工作的分支: + +``` +$git branch --no-merged +testing +``` + +如果分支包含未合并的工作,使用 `git branch -d testing` 删除时会出错,可以使用 `git branch -D testing`强制删除。 + +## 远程分支 + +### 推送 + +将本地的 master 分支推送到远程仓库 origin/master 分支: + +```bash +git push origin master +``` + +将本地的 tyson 分支推送到远程仓库的 tyson-branch 分支 : + +```bash +git push origin tyson:tyson-branch +``` + +假如当前本地分支是 tyson,抓取远程仓库数据后,需要进行合并: + +``` +git fetch origin +git merge origin/tyson +``` + +将本地的所有分支都推送到远程主机: + +```bash +git push -all origin +``` + +强制推送(**最好不用**): + +```bash +git push --force origin +``` + + +### 跟踪分支 + +``` +$ git checkout --track origin/tyson +Branch tyson set up to track remote branch tyson from origin. +Switched to a new branch 'tyson' +``` + +本地分支与远程分支设置为不同名字: + +``` +$ git checkout -b tyson-branch origin/tyson +Branch tyson-branch set up to track remote branch tyson from origin. +Switched to a new branch 'tyson-branch' +``` + +设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,使用 -u 或 --set-upstream-to 选项: + +```bash +git branch -u origin master +``` + +查看设置的所有跟踪分支: + +``` +$ git branch -vv +iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets +master 1ae2a45 [origin/master] deploying index fix +* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it +testing 5ea463a trying something new +``` + +这些数据是本地缓存的服务器数据,如果需要最新的数据,可以先运行:`git fetch --all` 然后再运行:`git branch -vv` + +### fetch和pull + +git fetch 会将远程仓库的更新拉取到本地远程仓库的副本,不会自动合并到本地仓库。 + +git fetch 步骤: + +```java +git fetch origin master:tmp //在本地新建一个tmp分支,并将远程origin仓库的master分支代码下载到本地tmp分支 +git diff tmp //来比较本地代码与刚刚从远程下载下来的代码的区别 +git merge tmp//合并tmp分支到本地的master分支 +git branch -d tmp//如果不想保留temp分支 可以用这步删除 +``` + +`git pull` = `git fetch` + `git merge` + +### 删除远程分支 + +Git 服务器会保留数据一段时间,误删的远程分支很容易恢复。 + +```bash +git push origin --delete tyson +``` + +## 创建远程分支 + +基于本地分支创建远程分支: + +```bash +git push origin backup_foreign:backup_foreign +``` + +本地新分支和远程新分支关联: + +```bash +git push --set-upstream origin backup_foreign +``` + +## cherry-pick + +可以用于将在其他分支上的 commit 修改,移植到当前的分支。 + +```bash +git cherry-pick +``` + +当执行完 cherry-pick 之后,将会自动生成一个新的 commit 进行提交,会有一个新的 commit ID,commit 信息与 cherry-pick 的 commit 信息一致。遇到冲突则解决冲突,然后 `git add 产生冲突的文件`,然后使用 `git cherry-pick --continue` 继续。这个过程中可以使用 `git cherry-pick --abort`,恢复分支到 cherry-pick 之前的状态。 + +`git cherry-pick -x ` 增加 -x 参数,表示保留原提交的作者信息进行提交。 + +在 Git 1.7.2 版本开始,新增了支持批量 cherry-pick ,就是可以一次将一个连续的时间序列内的 commit ,设定一个开始和结束的 commit ,进行 cherry-pick 操作。 + +```bash +git cherry-pick +``` + +上述命令将从start-commit-id开始到end-commit-id之间的所有commit-id提交记录都合并过来,需要注意的是,start-commit-id必须比end-commit-id提前提交。 + +### cherry-pick与rebase的区别 + +cherry-pick 操作的是某一个或某几个 commit,rebase 操作的是整个分支。 + +> 参考链接:https://juejin.im/post/5925a2d9a22b9d0058b0fd9b + +## 补丁 + +`git apply xx.patch` 需要自己重新 commit。xx.patch 必须从`git diff`中获得,才能使用 `git apply`。 + +`git am yy.patch` 会保留commit信息,yy.patch是从`git format–patch`获得的。 + + diff --git a/docs/tools/git/README.md b/docs/tools/git/README.md new file mode 100644 index 0000000..69dbb1b --- /dev/null +++ b/docs/tools/git/README.md @@ -0,0 +1,17 @@ +--- +title: Git基础 +icon: git +date: 2022-08-06 +category: git +star: true +--- + +![](http://img.dabin-coder.cn/image/git-status.png) + +## Git总结 + +- [Git简介](./1-introduce.md) +- [Git基础](./2-basic.md) +- [远程仓库](./3-remote-repo.md) +- [标签](./4-label.md) +- [git分支](./5-branch.md) diff --git "a/\345\267\245\345\205\267/linux-overview.md" b/docs/tools/linux-overview.md similarity index 100% rename from "\345\267\245\345\205\267/linux-overview.md" rename to docs/tools/linux-overview.md diff --git a/docs/tools/linux/1-basic.md b/docs/tools/linux/1-basic.md new file mode 100644 index 0000000..3703c5d --- /dev/null +++ b/docs/tools/linux/1-basic.md @@ -0,0 +1,172 @@ +# 基本操作 + +## Linux关机,重启 + +``` +#关机 +shutdown -h now + +#重启 +shutdown -r now +``` + +## 查看系统,CPU信息 + +``` +#查看系统内核信息 +uname -a + +#查看系统内核版本 +cat /proc/version + +#查看当前用户环境变量 +env + +cat /proc/cpuinfo + +#查看有几个逻辑cpu, 包括cpu型号 +cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c + +#查看有几颗cpu,每颗分别是几核 +cat /proc/cpuinfo | grep physical | uniq -c + +#查看当前CPU运行在32bit还是64bit模式下, 如果是运行在32bit下也不代表CPU不支持64bit +getconf LONG_BIT + +#结果大于0, 说明支持64bit计算. lm指long mode, 支持lm则是64bit +cat /proc/cpuinfo | grep flags | grep ' lm ' | wc -l +``` + +## 建立软连接 + +``` +ln -s /usr/local/jdk1.8/ jdk +``` + +## rpm相关 + +``` +#查看是否通过rpm安装了该软件 +rpm -qa | grep 软件名 +``` + +## sshkey + +``` +#创建sshkey +ssh-keygen -t rsa -C your_email@example.com + +#id_rsa.pub 的内容拷贝到要控制的服务器的 home/username/.ssh/authorized_keys 中,如果没有则新建(.ssh权限为700, authorized_keys权限为600) +``` + +## 命令重命名 + +``` +#在各个用户的.bash_profile中添加重命名配置 +alias ll='ls -alF' +``` + +## 同步服务器时间 + +``` +sudo ntpdate -u ntp.api.bz +``` + +## 后台运行命令 + +``` +#后台运行,并且有nohup.out输出 +nohup xxx & + +#后台运行, 不输出任何日志 +nohup xxx > /dev/null & + +#后台运行, 并将错误信息做标准输出到日志中 +nohup xxx >out.log 2>&1 & +``` + +## 强制活动用户退出 + +``` +#命令来完成强制活动用户退出.其中TTY表示终端名称 +pkill -kill -t [TTY] +``` + +## 查看命令路径 + +``` +which <命令> +``` + +## 查看进程所有打开最大fd数 + +``` +ulimit -n +``` + +## 配置dns + +``` +vim /etc/resolv.conf +``` + +## nslookup,查看域名路由表 + +``` +nslookup google.com +``` + +## last, 最近登录信息列表 + +``` +#最近登录的5个账号 +last -n 5 +``` + +## 设置固定ip + +``` +ifconfig em1 192.168.5.177 netmask 255.255.255.0 +``` + +## 查看进程内加载的环境变量 + +``` +#也可以去 cd /proc 目录下, 查看进程内存中加载的东西 +ps eww -p XXXXX(进程号) +``` + +## 查看进程树找到服务器进程 + +``` +ps auwxf +``` + +## 查看进程启动路径 + +``` +cd /proc/xxx(进程号) +ls -all +#cwd对应的是启动路径 +``` + +## 添加用户, 配置sudo权限 + +``` +#新增用户 +useradd 用户名 +passwd 用户名 + +#增加sudo权限 +vim /etc/sudoers +#修改文件里面的 +#root ALL=(ALL) ALL +#用户名 ALL=(ALL) ALL +``` + +## 强制关闭进程名包含xxx的所有进程 + +``` +ps aux|grep xxx | grep -v grep | awk '{print $2}' | xargs kill -9 +``` + diff --git a/docs/tools/linux/2-disk-file.md b/docs/tools/linux/2-disk-file.md new file mode 100644 index 0000000..ea23537 --- /dev/null +++ b/docs/tools/linux/2-disk-file.md @@ -0,0 +1,159 @@ +# 磁盘,文件,目录相关操作 + +## vim操作 + +``` +#normal模式下 g表示全局, x表示查找的内容, y表示替换后的内容 +:%s/x/y/g + +#normal模式下 +0 #光标移到行首(数字0) +$ #光标移至行尾 +shift + g #跳到文件最后 +gg #跳到文件头 + +#显示行号 +:set nu + +#去除行号 +:set nonu + +#检索 +/xxx(检索内容) #从头检索, 按n查找下一个 +?xxx(检索内容) #从尾部检索 +``` + +## 打开只读文件,修改后需要保存时(不用切换用户即可保存的方式) + +``` +#在normal模式下 +:w !sudo tee % +``` + +## 查看磁盘, 文件目录基本信息 + +``` +#查看磁盘挂载情况 +mount + +#查看磁盘分区信息 +df + +#查看目录及子目录大小 +du -H -h + +#查看当前目录下各个文件, 文件夹占了多少空间, 不会递归 +du -sh * +``` + +## wc命令 + +``` +#查看文件里有多少行 +wc -l filename + +#看文件里有多少个word +wc -w filename + +#文件里最长的那一行是多少个字 +wc -L filename + +#统计字节数 +wc -c +``` + +## 常用压缩, 解压缩命令 + +### 压缩命令 + +``` +tar czvf xxx.tar 压缩目录 + +zip -r xxx.zip 压缩目录 +``` + +### 解压缩命令 + +``` +tar zxvf xxx.tar + +#解压到指定文件夹 +tar zxvf xxx.tar -C /xxx/yyy/ + +unzip xxx.zip +``` + +## 变更文件所属用户, 用户组 + +``` +chown eagleye.eagleye xxx.log +``` + +## cp, scp, mkdir + +``` +#复制 +cp xxx.log + +#复制并强制覆盖同名文件 +cp -f xxx.log + +#复制文件夹 +cp -r xxx(源文件夹) yyy(目标文件夹) + +#远程复制 +scp -P ssh端口 username@10.10.10.101:/home/username/xxx /home/xxx + +#级联创建目录 +mkdir -p /xxx/yyy/zzz + +#批量创建文件夹, 会在test,main下都创建java, resources文件夹 +mkdir -p src/{test,main}/{java,resources} +``` + +## 比较两个文件 + +``` +diff -u 1.txt 2.txt +``` + +## 日志输出的字节数,可以用作性能测试 + +``` +#如果做性能测试, 可以每执行一次, 往日志里面输出 “.” , 这样日志中的字节数就是实际的性能测试运行的次数, 还可以看见实时速率. +tail -f xxx.log | pv -bt +``` + +## 查看, 去除特殊字符 + +``` +#查看特殊字符 +cat -v xxx.sh + +#去除特殊字符 +sed -i 's/^M//g’ env.sh 去除文件的特殊字符, 比如^M: 需要这样输入: ctrl+v+enter +``` + +## 处理因系统原因引起的文件中特殊字符的问题 + +``` +#可以转换为该系统下的文件格式 +cat file.sh > file.sh_bak + +#先将file.sh中文件内容复制下来然后运行, 然后粘贴内容, 最后ctrl + d 保存退出 +cat > file1.sh + +#在vim中通过如下设置文件编码和文件格式 +:set fileencodings=utf-8 ,然后 w (存盘)一下即可转化为 utf8 格式, +:set fileformat=unix + +#在mac下使用dos2unix进行文件格式化 +find . -name "*.sh" | xargs dos2unix +``` + +## tee, 重定向的同时输出到屏幕 + +``` +awk ‘{print $0}’ xxx.log | tee test.log +``` + diff --git a/docs/tools/linux/3-search.md b/docs/tools/linux/3-search.md new file mode 100644 index 0000000..e8d4109 --- /dev/null +++ b/docs/tools/linux/3-search.md @@ -0,0 +1,59 @@ +# 检索相关 + +## grep + +``` +#反向匹配, 查找不包含xxx的内容 +grep -v xxx + +#排除所有空行 +grep -v '^/pre> + +#返回结果 2,则说明第二行是空行 +grep -n “^$” 111.txt + +#查询以abc开头的行 +grep -n “^abc” 111.txt + +#同时列出该词语出现在文章的第几行 +grep 'xxx' -n xxx.log + +#计算一下该字串出现的次数 +grep 'xxx' -c xxx.log + +#比对的时候,不计较大小写的不同 +grep 'xxx' -i xxx.log +``` + +## awk + +``` +#以':' 为分隔符,如果第五域有user则输出该行 +awk -F ':' '{if ($5 ~ /user/) print $0}' /etc/passwd + +#统计单个文件中某个字符(串)(中文无效)出现的次数 +awk -v RS='character' 'END {print --NR}' xxx.txt +``` + +## find检索命令 + +``` +#在目录下找后缀是.mysql的文件 +find /home/eagleye -name '*.mysql' -print + +#会从 /usr 目录开始往下找,找最近3天之内存取过的文件。 +find /usr -atime 3 –print + +#会从 /usr 目录开始往下找,找最近5天之内修改过的文件。 +find /usr -ctime 5 –print + +#会从 /doc 目录开始往下找,找jacky 的、文件名开头是 j的文件。 +find /doc -user jacky -name 'j*' –print + +#会从 /doc 目录开始往下找,找寻文件名是 ja 开头或者 ma开头的文件。 +find /doc \( -name 'ja*' -o- -name 'ma*' \) –print + +#会从 /doc 目录开始往下找,找到凡是文件名结尾为 bak的文件,把它删除掉。-exec 选项是执行的意思,rm 是删除命令,{ } 表示文件名,“\;”是规定的命令结尾。 +find /doc -name '*bak' -exec rm {} \; +``` + diff --git a/docs/tools/linux/4-net.md b/docs/tools/linux/4-net.md new file mode 100644 index 0000000..2c7fc27 --- /dev/null +++ b/docs/tools/linux/4-net.md @@ -0,0 +1,125 @@ +# 网络相关 + +## 查看什么进程使用了该端口 + +``` +lsof -i:port +``` + +## 获取本机ip地址 + +``` +/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:" +``` + +## iptables + +``` +#查看iptables状态 +service iptables status + +#要封停一个ip +iptables -I INPUT -s ***.***.***.*** -j DROP + +#要解封一个IP,使用下面这条命令: +iptables -D INPUT -s ***.***.***.*** -j DROP + +备注: 参数-I是表示Insert(添加),-D表示Delete(删除)。后面跟的是规则,INPUT表示入站,***.***.***.***表示要封停的IP,DROP表示放弃连接。 + +#开启9090端口的访问 +/sbin/iptables -I INPUT -p tcp --dport 9090 -j ACCEPT + +#防火墙开启、关闭、重启 +/etc/init.d/iptables status +/etc/init.d/iptables start +/etc/init.d/iptables stop +/etc/init.d/iptables restart +``` + +## nc命令, tcp调试利器 + +``` +#给某一个endpoint发送TCP请求,就将data的内容发送到对端 +nc 192.168.0.11 8000 < data.txt + +#nc可以当做服务器,监听某个端口号,把某一次请求的内容存储到received_data里 +nc -l 8000 > received_data + +#上边只监听一次,如果多次可以加上-k参数 +nc -lk 8000 +``` + +## tcpdump + +``` +#dump出本机12301端口的tcp包 +tcpdump -i em1 tcp port 12301 -s 1500 -w abc.pcap +``` + +## 跟踪网络路由路径 + +``` +#traceroute默认使用udp方式, 如果是-I则改成icmp方式 +traceroute -I www.163.com + +#从ttl第3跳跟踪 +traceroute -M 3 www.163.com + +#加上端口跟踪 +traceroute -p 8080 192.168.10.11 +``` + +## ss + +``` +#显示本地打开的所有端口 +ss -l + +#显示每个进程具体打开的socket +ss -pl + +#显示所有tcp socket +ss -t -a + +#显示所有的UDP Socekt +ss -u -a + +#显示所有已建立的SMTP连接 +ss -o state established '( dport = :smtp or sport = :smtp )' + +#显示所有已建立的HTTP连接 +ss -o state established '( dport = :http or sport = :http )' + +找出所有连接X服务器的进程 +ss -x src /tmp/.X11-unix/* + +列出当前socket统计信息 +ss -s + +解释:netstat是遍历/proc下面每个PID目录,ss直接读/proc/net下面的统计信息。所以ss执行的时候消耗资源以及消耗的时间都比netstat少很多 +``` + +## netstat + +``` +#输出每个ip的连接数,以及总的各个状态的连接数 +netstat -n | awk '/^tcp/ {n=split($(NF-1),array,":");if(n<=2)++S[array[(1)]];else++S[array[(4)]];++s[$NF];++N} END {for(a in S){printf("%-20s %s\n", a, S[a]);++I}printf("%-20s %s\n","TOTAL_IP",I);for(a in s) printf("%-20s %s\n",a, s[a]);printf("%-20s %s\n","TOTAL_LINK",N);}' + +#统计所有连接状态, +#CLOSED:无连接是活动的或正在进行 +#LISTEN:服务器在等待进入呼叫 +#SYN_RECV:一个连接请求已经到达,等待确认 +#SYN_SENT:应用已经开始,打开一个连接 +#ESTABLISHED:正常数据传输状态 +#FIN_WAIT1:应用说它已经完成 +#FIN_WAIT2:另一边已同意释放 +#ITMED_WAIT:等待所有分组死掉 +#CLOSING:两边同时尝试关闭 +#TIME_WAIT:主动关闭连接一端还没有等到另一端反馈期间的状态 +#LAST_ACK:等待所有分组死掉 +netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}' + +#查找较多time_wait连接 +netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20 +``` + diff --git a/docs/tools/linux/5-monitor.md b/docs/tools/linux/5-monitor.md new file mode 100644 index 0000000..59b17e9 --- /dev/null +++ b/docs/tools/linux/5-monitor.md @@ -0,0 +1,131 @@ +# 监控linux性能命令 + +## top + +``` +按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序, 然后回车。而大写的 R 键可以将当前的排序倒转 +``` + +| 列名 | 含义 | +| :------ | :----------------------------------------------------------- | +| PID | 进程id | +| PPID | 父进程id | +| RUSER | Real user name | +| UID | 进程所有者的用户id | +| USER | 进程所有者的用户名 | +| GROUP | 进程所有者的组名 | +| TTY | 启动进程的终端名。不是从终端启动的进程则显示为 ? | +| PR | 优先级 | +| NI | nice值。负值表示高优先级,正值表示低优先级 | +| P | 最后使用的CPU,仅在多CPU环境下有意义 | +| %CPU | 上次更新到现在的CPU时间占用百分比 | +| TIME | 进程使用的CPU时间总计,单位秒 | +| TIME+ | 进程使用的CPU时间总计,单位1/100秒 | +| %MEM | 进程使用的物理内存百分比 | +| VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES | +| SWAP | 进程使用的虚拟内存中,被换出的大小,单位kb。 | +| RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA | +| CODE | 可执行代码占用的物理内存大小,单位kb | +| DATA | 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb | +| SHR | 共享内存大小,单位kb | +| nFLT | 页面错误次数 | +| nDRT | 最后一次写入到现在,被修改过的页面数。 | +| S | 进程状态。D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程 | +| COMMAND | 命令名/命令行 | +| WCHAN | 若该进程在睡眠,则显示睡眠中的系统函数名 | +| Flags | 任务标志,参考 sched.h | + +## dmesg,查看系统日志 + +``` +dmesg +``` + +## iostat,磁盘IO情况监控 + +``` +iostat -xz 1 + +#r/s, w/s, rkB/s, wkB/s:分别表示每秒读写次数和每秒读写数据量(千字节)。读写量过大,可能会引起性能问题。 +#await:IO操作的平均等待时间,单位是毫秒。这是应用程序在和磁盘交互时,需要消耗的时间,包括IO等待和实际操作的耗时。如果这个数值过大,可能是硬件设备遇到了瓶颈或者出现故障。 +#avgqu-sz:向设备发出的请求平均数量。如果这个数值大于1,可能是硬件设备已经饱和(部分前端硬件设备支持并行写入)。 +#%util:设备利用率。这个数值表示设备的繁忙程度,经验值是如果超过60,可能会影响IO性能(可以参照IO操作平均等待时间)。如果到达100%,说明硬件设备已经饱和。 +#如果显示的是逻辑设备的数据,那么设备利用率不代表后端实际的硬件设备已经饱和。值得注意的是,即使IO性能不理想,也不一定意味这应用程序性能会不好,可以利用诸如预读取、写缓存等策略提升应用性能。 +``` + +## free,内存使用情况 + +``` +free -m + +eg: + + total used free shared buffers cached +Mem: 1002 769 232 0 62 421 +-/+ buffers/cache: 286 715 +Swap: 1153 0 1153 + +第一部分Mem行: +total 内存总数: 1002M +used 已经使用的内存数: 769M +free 空闲的内存数: 232M +shared 当前已经废弃不用,总是0 +buffers Buffer 缓存内存数: 62M +cached Page 缓存内存数:421M + +关系:total(1002M) = used(769M) + free(232M) + +第二部分(-/+ buffers/cache): +(-buffers/cache) used内存数:286M (指的第一部分Mem行中的used – buffers – cached) +(+buffers/cache) free内存数: 715M (指的第一部分Mem行中的free + buffers + cached) + +可见-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数. + +第三部分是指交换分区 +``` + +## sar,查看网络吞吐状态 + +``` +#sar命令在这里可以查看网络设备的吞吐率。在排查性能问题时,可以通过网络设备的吞吐量,判断网络设备是否已经饱和 +sar -n DEV 1 + +# +#sar命令在这里用于查看TCP连接状态,其中包括: +#active/s:每秒本地发起的TCP连接数,既通过connect调用创建的TCP连接; +#passive/s:每秒远程发起的TCP连接数,即通过accept调用创建的TCP连接; +#retrans/s:每秒TCP重传数量; +#TCP连接数可以用来判断性能问题是否由于建立了过多的连接,进一步可以判断是主动发起的连接,还是被动接受的连接。TCP重传可能是因为网络环境恶劣,或者服务器压力过大导致丢包 +sar -n TCP,ETCP 1 +``` + +## vmstat, 给定时间监控CPU使用率, 内存使用, 虚拟内存交互, IO读写 + +``` +#2表示每2秒采集一次状态信息, 1表示只采集一次(忽略既是一直采集) +vmstat 2 1 + +eg: +r b swpd free buff cache si so bi bo in cs us sy id wa +1 0 0 3499840 315836 3819660 0 0 0 1 2 0 0 0 100 0 +0 0 0 3499584 315836 3819660 0 0 0 0 88 158 0 0 100 0 +0 0 0 3499708 315836 3819660 0 0 0 2 86 162 0 0 100 0 +0 0 0 3499708 315836 3819660 0 0 0 10 81 151 0 0 100 0 +1 0 0 3499732 315836 3819660 0 0 0 2 83 154 0 0 100 0 +``` + +- r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。 +- b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。 +- swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。 +- free 空闲的物理内存的大小,我的机器内存总共8G,剩余3415M。 +- buff Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M +- cache cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。) +- si 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。 +- so 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。 +- bi 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒 +- bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。 +- in 每秒CPU的中断次数,包括时间中断 +- cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。 +- us 用户CPU时间,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。 +- sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。 +- id 空闲 CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。 diff --git a/docs/tools/linux/README.md b/docs/tools/linux/README.md new file mode 100644 index 0000000..c1f622b --- /dev/null +++ b/docs/tools/linux/README.md @@ -0,0 +1,12 @@ +虽然平时大部分工作都是和Java相关的开发, 但是每天都会接触Linux系统, 尤其是使用了Mac之后, 每天都是工作在黑色背景的命令行环境中. 自己记忆力不好, 很多有用的Linux命令不能很好的记忆, 现在逐渐总结一下, 以便后续查看。 + +> 来源:siye1982.github.io/2016/02/25/linux-list + + +## Linux基础命令 + +- [基本操作](./1-basic.md) +- [磁盘,文件,目录相关操作](./2-disk-file.md) +- [检索相关](./3-search.md) +- [网络相关](./4-net.md) +- [监控linux性能命令](./5-monitor.md) diff --git "a/\345\267\245\345\205\267/maven-overview.md" b/docs/tools/maven-overview.md similarity index 83% rename from "\345\267\245\345\205\267/maven-overview.md" rename to docs/tools/maven-overview.md index a8255db..714c885 100644 --- "a/\345\267\245\345\205\267/maven-overview.md" +++ b/docs/tools/maven-overview.md @@ -1,61 +1,20 @@ - - - -- [简介](#%E7%AE%80%E4%BB%8B) - - [配置](#%E9%85%8D%E7%BD%AE) -- [入门](#%E5%85%A5%E9%97%A8) - - [编写测试代码](#%E7%BC%96%E5%86%99%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81) - - [添加 junit 依赖](#%E6%B7%BB%E5%8A%A0-junit-%E4%BE%9D%E8%B5%96) - - [编译](#%E7%BC%96%E8%AF%91) - - [测试代码](#%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81) - - [执行测试](#%E6%89%A7%E8%A1%8C%E6%B5%8B%E8%AF%95) - - [`mvn clean test`](#mvn-clean-test) - - [打包和安装](#%E6%89%93%E5%8C%85%E5%92%8C%E5%AE%89%E8%A3%85) -- [依赖](#%E4%BE%9D%E8%B5%96) - - [依赖范围 scope](#%E4%BE%9D%E8%B5%96%E8%8C%83%E5%9B%B4-scope) - - [传递性依赖](#%E4%BC%A0%E9%80%92%E6%80%A7%E4%BE%9D%E8%B5%96) - - [排除依赖](#%E6%8E%92%E9%99%A4%E4%BE%9D%E8%B5%96) - - [优化依赖](#%E4%BC%98%E5%8C%96%E4%BE%9D%E8%B5%96) -- [仓库](#%E4%BB%93%E5%BA%93) - - [本地仓库](#%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93) - - [远程仓库](#%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93) - - [认证和部署](#%E8%AE%A4%E8%AF%81%E5%92%8C%E9%83%A8%E7%BD%B2) - - [镜像](#%E9%95%9C%E5%83%8F) -- [生命周期](#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) - - [三套生命周期](#%E4%B8%89%E5%A5%97%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) - - [命令行与生命周期](#%E5%91%BD%E4%BB%A4%E8%A1%8C%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) -- [插件](#%E6%8F%92%E4%BB%B6) - - [内置绑定](#%E5%86%85%E7%BD%AE%E7%BB%91%E5%AE%9A) - - [自定义绑定](#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%91%E5%AE%9A) - - [命令行插件配置](#%E5%91%BD%E4%BB%A4%E8%A1%8C%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE) - - [插件全局配置](#%E6%8F%92%E4%BB%B6%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE) -- [聚合](#%E8%81%9A%E5%90%88) -- [继承](#%E7%BB%A7%E6%89%BF) - - [依赖管理](#%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86) - - [import 导入依赖管理](#import-%E5%AF%BC%E5%85%A5%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86) - - [插件管理](#%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86) -- [测试](#%E6%B5%8B%E8%AF%95) - - [跳过测试](#%E8%B7%B3%E8%BF%87%E6%B5%8B%E8%AF%95) - - - -## 简介 +# 简介 Maven 是强大的构建工具,能够帮我们自动化构建过程--清理、编译、测试、打包和部署。比如测试,我们无需告诉 maven 如何去测试,只需遵循 maven 的约定编写好测试用例,当我们运行构建的时候,这些测试就会自动运行。 Maven 不仅是构建工具,还是一个依赖管理工具和项目信息管理工具。它提供了中央仓库,能帮助我们自动下载构件。 -### 配置 +## 配置 配置用户范围 settings.xml。M2_HOME/conf/settings.xml 是全局范围的,而~/.m2/settings.xml 是用户范围的。配置成用户范围便于 Maven 升级。若直接修改 conf 目录下的 settings.xml,每次 Maven 升级时,都需要直接 settings.xml 文件。 -## 入门 +# 入门 -### 编写测试代码 +## 编写测试代码 -#### 添加 junit 依赖 +## 添加 junit 依赖 ```xml @@ -70,7 +29,7 @@ Maven 不仅是构建工具,还是一个依赖管理工具和项目信息管 maven 会自动访问中央仓库,下载 junit 依赖。scope 为 test 表明依赖只对测试有效,即测试代码中的 import JUnit 代码没有问题,而主代码中使用 import JUnit 代码,则会产生编译错误。 -#### 编译 +## 编译 主类 HelloWorld @@ -89,7 +48,7 @@ public class HelloWorld { clean 清理输出目录/target,compile 编译项目主代码。 -#### 测试代码 +## 测试代码 ```java public class HelloWorldTest { @@ -101,9 +60,9 @@ public class HelloWorldTest { } ``` -#### 执行测试 +## 执行测试 -#### `mvn clean test` +`mvn clean test` 测试结果: @@ -115,7 +74,7 @@ Running com.tyson.test.HelloWorldTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.117 sec ``` -#### 打包和安装 +## 打包和安装 打包:`mvn clean package `将项目代码打包成 jar 包,位于/target 目录。 @@ -155,7 +114,7 @@ Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.117 sec -## 依赖 +# 依赖 ```xml @@ -172,7 +131,7 @@ Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.117 sec - exclusions:用来排除传递性依赖 -### 依赖范围 scope +## 依赖范围 scope maven 在编译、测试和运行项目时会使用不同的 classpath(编译classpath、测试 classpath、运行 classpath)。依赖范围就是用来控制依赖和这三种 classpath 的关系。maven 中有以下几种依赖范围: @@ -184,21 +143,21 @@ maven 在编译、测试和运行项目时会使用不同的 classpath(编译c - import:导入依赖范围 [import 导入依赖管理](#import-导入依赖管理) -### 传递性依赖 +## 传递性依赖 假如项目 account 有一个 compile 范围的 spring-core 依赖,而 spring-core 有一个 compile 范围的 common-logging 依赖,那么 common-logging 就会成为 account 的 compile 范围依赖,common-logging 是 account 的一个传递性依赖。maven 会直接解析各个直接依赖的 POM,将那些必要的间接依赖,以传递性依赖的形式引入到项目中。 spring-core 是 account 的第一直接依赖,common-logging 是 spring-core 的第二直接依赖,common-logging 是 account 的传递性依赖。第一直接依赖的范围和第二直接依赖的范围共同决定了传递性依赖的范围。下表左边是第一直接依赖的范围,上面一行是第二直接依赖的范围,中间部分是传递依赖的范围 -![依赖范围和传递性依赖](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190705222236595-1506009657.png) +![](http://img.dabin-coder.cn/image/传递性依赖.png) -### 排除依赖 +## 排除依赖 传递性依赖可能会带来一些问题,像引入一些类库的 SNAPSHOT 版本,会影响到当前项目的稳定性。此时可以通过 exclusions 元素声明排除传递性依赖,exclusions 元素可以包含一个或多个 exclusion 元素,因此可以排除多个传递性依赖。声明 exclusion 时只需要 groupId 和 artifactId,而不需要 version 元素。 -![排除依赖](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706165424929-1192438533.png) +![](http://img.dabin-coder.cn/image/排查依赖.png) -### 优化依赖 +## 优化依赖 查看当前项目的依赖:`mvn dependency:list` @@ -208,27 +167,27 @@ spring-core 是 account 的第一直接依赖,common-logging 是 spring-core -## 仓库 +# 仓库 仓库分为两类:本地仓库和远程仓库。当 maven 根据坐标去寻找构件时,首先会去本地仓库查找,如果本地仓库不存在这个构件,maven 就会去远程仓库查找,下载到本地仓库。若远程仓库也没有这个构件,则会报错。 私服是一种特殊的远程仓库,是在局域网内架设的私有的仓库服务器,用其代理所有外部的远程仓库,内部的项目还能部署到私服上供其他项目使用。 -### 本地仓库 +## 本地仓库 要想自定义本地仓库地址,可以修改 C:\Users\Tyson\\.m2 下的 settings.xml 文件(默认不存在,需要到 maven 安装目录复制),不建议直接修改 maven 安装目录下的 settings.xml 文件。 通过`mvn clean install`可以将本地项目安装到本地库,以供其他项目使用。 -### 远程仓库 +## 远程仓库 当默认的中央仓库无法满足项目需要,可以通过 repositories 元素在 POM 中配置远程仓库。maven 中央仓库 id 为 central,若其他仓库 id 命名为 central,则会覆盖中央仓库的配置。 -![使用Jboss maven仓库](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706072227846-1642299607.png) +![](http://img.dabin-coder.cn/image/使用Jboss maven仓库.png) maven中的仓库分为两种,snapshot 快照仓库和 release 发布仓库。元素 releases 的 enabled 为 true 表示开启 Jboss 仓库 release 版本下载支持,maven 会从 Jboss 仓库下载 release 版本的构件。 -#### 认证和部署 +## 认证和部署 有些远程仓库需要认证才能访问,可以在 settings.xml 中配置认证信息(更为安全)。 @@ -271,7 +230,7 @@ server元素的id要和pom.xml里需要认证的repository元素的id对应一 配置完 distributionManagement 之后,在命令行运行`mvn clean deploy`,maven 就会将项目构建输出的构件部署到对应的远程仓库,如果项目当前版本是快照版本,则部署到快照版本仓库地址,否则部署到发布版本仓库地址。 -### 镜像 +## 镜像 mirrorsOf 配置为 central,表示其为中央仓库的镜像,任何对中央仓库的请求都会转发到这个镜像。 @@ -296,11 +255,11 @@ mirrorsOf 配置为 central,表示其为中央仓库的镜像,任何对中 -## 生命周期 +# 生命周期 项目构建过程包括:清理项目- 编译-测试-打包-部署 -### 三套生命周期 +## 三套生命周期 clean 生命周期:pre-clean、clean 和 post-clean; @@ -308,7 +267,7 @@ default 生命周期; site 生命周期:pre-site、site、post-site 和 site-deploy -### 命令行与生命周期 +## 命令行与生命周期 `mvn clean`:调用 clean 生命周期的 clean 阶段,实际上执行的是 clean 的 pre-clean 和 clean 阶段; @@ -320,17 +279,17 @@ site 生命周期:pre-site、site、post-site 和 site-deploy -## 插件 +# 插件 maven 的生命周期和插件相互绑定,用以完成具体的构建任务。 -### 内置绑定 +## 内置绑定 -![内置绑定1](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706171830733-661580052.png) +![](http://img.dabin-coder.cn/image/maven内置绑定1.png) -![内置绑定2](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706171854778-608245986.png) +![](http://img.dabin-coder.cn/image/maven内置绑定2.png) -### 自定义绑定 +## 自定义绑定 内置绑定无法完成一些任务,如创建项目的源码 jar 包,此时需要用户自行配置。maven-source-plugin 可以完成这个任务,它的 jar-no-fork 目标能够将项目的主代码打包成 jar 文件,可以将其绑定到 default 生命周期的 verify 阶段,在执行完测试和安装构件之前创建源码 jar 包。 @@ -355,13 +314,13 @@ maven 的生命周期和插件相互绑定,用以完成具体的构建任务 ``` -### 命令行插件配置 +## 命令行插件配置 maven-surefire-plugin 提供了一个 maven.test.skip 参数,当其值为 true 时,就会跳过执行测试。 `mvn install -Dmaven.test.skip=true` -D 是 Java 自带的。 -### 插件全局配置 +## 插件全局配置 有些参数值从项目创建到发布都不会改变,可以在 pom 中一次性配置,避免重新在命令行输入。如配置 maven-compiler-plugin ,生成与 JVM1.5 兼容的字节码文件。 @@ -383,11 +342,11 @@ maven-surefire-plugin 提供了一个 maven.test.skip 参数,当其值为 true -## 聚合 +# 聚合 项目有多个模块时,使用一个聚合体将这些模块聚合起来,通过聚合体就可以一次构建全部模块。 -![maven聚合](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706142605104-1246458390.png) +![](http://img.dabin-coder.cn/image/maven聚合.png) accout-aggregator 的版本号要跟各个模块版本号相同,packaging 的值必须为 pom。module 标签的值是模块根目录名字(为了方便,模块根目录名字常与 artifactId 同名)。这样聚合模块和其他模块的目录结构是父子关系。如果使用平行目录结构,聚合模块的 pom 文件需要做相应的修改。 @@ -400,7 +359,7 @@ accout-aggregator 的版本号要跟各个模块版本号相同,packaging 的 -## 继承 +# 继承 使用聚合体的 pom 文件作为公共 pom 文件,配置子模块的共同依赖,消除配置的重复。其中packaging 的值必须是 pom。 @@ -442,7 +401,7 @@ accout-aggregator 的版本号要跟各个模块版本号相同,packaging 的 ``` -### 依赖管理 +## 依赖管理 使用dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,不用每个模块项目都弄一个版本号,不利于管理,当需要变更版本号的时候只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个特殊的版本号时,只需要在自己的模块dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。 @@ -531,9 +490,9 @@ springframework 依赖的 version 继承自父模块,可以省略,可避免 使用 import 依赖范围可以导入依赖管理配置,将目标 pom 的 dependencyManagement 配置导入合并到当前 pom 的 dependencyManagement 元素中。 -![使用import依赖范围导入依赖管理配置](https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190706155054098-1669414992.png) +![](http://img.dabin-coder.cn/image/使用import依赖范围导入依赖管理配置.png) -### 插件管理 +## 插件管理 maven 提供了 pluginManagement 元素帮助管理插件。当项目中的多个模块有相同的插件配置时,应当将配置移到父 pom 的 pluginManagement 元素中,方便统一项目中的插件版本。 @@ -570,11 +529,3 @@ account-parent 的 pluginManagement 配置: ``` - -## 测试 - -maven 通过插件 maven-surefire-plugin 来执行 JUnit 或者 TestNG 的测试用例。默认情况下,maven-surefire-plugin 的 test 目标会自动执行测试源码路径下(src/test/java/)所有符合命名模式(*/Test\*.java、\*/*Test.java、\*/\*TestCase.java)的测试类。 - -### 跳过测试 - -`mvn package -DskipTests` \ No newline at end of file diff --git a/docs/tools/maven/1-introduce.md b/docs/tools/maven/1-introduce.md new file mode 100644 index 0000000..5ac3852 --- /dev/null +++ b/docs/tools/maven/1-introduce.md @@ -0,0 +1,12 @@ +# 简介 + +Maven 是强大的构建工具,能够帮我们自动化构建过程--清理、编译、测试、打包和部署。比如测试,我们无需告诉 maven 如何去测试,只需遵循 maven 的约定编写好测试用例,当我们运行构建的时候,这些测试就会自动运行。 + +Maven 不仅是构建工具,还是一个依赖管理工具和项目信息管理工具。它提供了中央仓库,能帮助我们自动下载构件。 + +## 配置 + +配置用户范围 settings.xml。M2_HOME/conf/settings.xml 是全局范围的,而~/.m2/settings.xml 是用户范围的。配置成用户范围便于 Maven 升级。若直接修改 conf 目录下的 settings.xml,每次 Maven 升级时,都需要直接 settings.xml 文件。 + + + diff --git a/docs/tools/maven/2-basic.md b/docs/tools/maven/2-basic.md new file mode 100644 index 0000000..2b49fa1 --- /dev/null +++ b/docs/tools/maven/2-basic.md @@ -0,0 +1,104 @@ +# 入门 + +## 编写测试代码 + +## 添加 junit 依赖 + +```xml + + + junit + junit + 4.7 + test + + +``` + +maven 会自动访问中央仓库,下载 junit 依赖。scope 为 test 表明依赖只对测试有效,即测试代码中的 import JUnit 代码没有问题,而主代码中使用 import JUnit 代码,则会产生编译错误。 + +## 编译 + +主类 HelloWorld + +```java +public class HelloWorld { + public String sayHello() { + return "Hello world"; + } + public static void main(String[] args) { + System.out.println(new HelloWorld().sayHello()); + } +} +``` + +编译代码:`mvn clean compile` + +clean 清理输出目录/target,compile 编译项目主代码。 + +## 测试代码 + +```java +public class HelloWorldTest { + @Test + public void testHelloWord() { + HelloWorld hw = new HelloWorld(); + hw.sayHello(); + } +} +``` + +## 执行测试 + +`mvn clean test` + +测试结果: + +```java +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running com.tyson.test.HelloWorldTest +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.117 sec +``` + +## 打包和安装 + +打包:`mvn clean package `将项目代码打包成 jar 包,位于/target 目录。 + +安装:`mvn clean install`,将项目输出的 jar 包安装到 maven 本地库,这样其他 maven 项目就可以直接引用这个 jar 包。 + +默认打包生成的 jar 不能直接运行,为了生成可运行的 jar 包,需要借助 maven-shade-plugin。 + +```xml + + HelloWorld + + + org.apache.maven.plugins + maven-shade-plugin + 1.2.1 + + + package + + shade + + + + + com.tyson.maven.HelloWorld + + + + + + + + +``` + +执行顺序:compile->test->package->install + + + diff --git a/docs/tools/maven/3-dependency.md b/docs/tools/maven/3-dependency.md new file mode 100644 index 0000000..5c5f075 --- /dev/null +++ b/docs/tools/maven/3-dependency.md @@ -0,0 +1,53 @@ +# 依赖 + +```xml + + junit + junit + 4.7 + test + +``` + +- scope:依赖的范围 + +- type:依赖的类型,jar 或者 war + +- exclusions:用来排除传递性依赖 + +## 依赖范围 scope + +maven 在编译、测试和运行项目时会使用不同的 classpath(编译classpath、测试 classpath、运行 classpath)。依赖范围就是用来控制依赖和这三种 classpath 的关系。maven 中有以下几种依赖范围: + +- compile:默认值,使用该依赖范围的 maven 依赖,在编译、测试和运行时都需要使用该依赖 +- test:只对测试 classpath 有效,在编译主代码和运行项目时无法使用此类依赖。如 JUnit 只在编译测试代码和运行测试的时候才需要此类依赖 +- provided:已提供依赖范围。对于编译和测试 classpath 有效,但在运行时无效。如 servlet-api,编译和测试时需要该依赖,但在运行项目时,由于容器已经提供此依赖,故不需要 maven重复引入 +- runtime:运行时依赖范围。对于测试和运行 classpath 有效,但在编译主代码时无效。如 JDBC 驱动实现,项目主代码的编译只需要 JDK 提供的 JDBC接口,只有在测试和运行时才需要实现 JDBC 接口的具体实现 +- system:系统依赖范围 +- import:导入依赖范围 [import 导入依赖管理](#import-导入依赖管理) + + +## 传递性依赖 + +假如项目 account 有一个 compile 范围的 spring-core 依赖,而 spring-core 有一个 compile 范围的 common-logging 依赖,那么 common-logging 就会成为 account 的 compile 范围依赖,common-logging 是 account 的一个传递性依赖。maven 会直接解析各个直接依赖的 POM,将那些必要的间接依赖,以传递性依赖的形式引入到项目中。 + +spring-core 是 account 的第一直接依赖,common-logging 是 spring-core 的第二直接依赖,common-logging 是 account 的传递性依赖。第一直接依赖的范围和第二直接依赖的范围共同决定了传递性依赖的范围。下表左边是第一直接依赖的范围,上面一行是第二直接依赖的范围,中间部分是传递依赖的范围 + +![](http://img.dabin-coder.cn/image/传递性依赖.png) + +## 排除依赖 + +传递性依赖可能会带来一些问题,像引入一些类库的 SNAPSHOT 版本,会影响到当前项目的稳定性。此时可以通过 exclusions 元素声明排除传递性依赖,exclusions 元素可以包含一个或多个 exclusion 元素,因此可以排除多个传递性依赖。声明 exclusion 时只需要 groupId 和 artifactId,而不需要 version 元素。 + +![](http://img.dabin-coder.cn/image/排查依赖.png) + +## 优化依赖 + +查看当前项目的依赖:`mvn dependency:list` + +查看依赖树:`mvn dependency:tree` + +分析依赖:`mvn dependency:analyze` + + + diff --git a/docs/tools/maven/4-repo.md b/docs/tools/maven/4-repo.md new file mode 100644 index 0000000..a92d550 --- /dev/null +++ b/docs/tools/maven/4-repo.md @@ -0,0 +1,88 @@ +# 仓库 + +仓库分为两类:本地仓库和远程仓库。当 maven 根据坐标去寻找构件时,首先会去本地仓库查找,如果本地仓库不存在这个构件,maven 就会去远程仓库查找,下载到本地仓库。若远程仓库也没有这个构件,则会报错。 + +私服是一种特殊的远程仓库,是在局域网内架设的私有的仓库服务器,用其代理所有外部的远程仓库,内部的项目还能部署到私服上供其他项目使用。 + +## 本地仓库 + +要想自定义本地仓库地址,可以修改 C:\Users\Tyson\\.m2 下的 settings.xml 文件(默认不存在,需要到 maven 安装目录复制),不建议直接修改 maven 安装目录下的 settings.xml 文件。 + +通过`mvn clean install`可以将本地项目安装到本地库,以供其他项目使用。 + +## 远程仓库 + +当默认的中央仓库无法满足项目需要,可以通过 repositories 元素在 POM 中配置远程仓库。maven 中央仓库 id 为 central,若其他仓库 id 命名为 central,则会覆盖中央仓库的配置。 + +![](http://img.dabin-coder.cn/image/使用Jboss maven仓库.png) + +maven中的仓库分为两种,snapshot 快照仓库和 release 发布仓库。元素 releases 的 enabled 为 true 表示开启 Jboss 仓库 release 版本下载支持,maven 会从 Jboss 仓库下载 release 版本的构件。 + +## 认证和部署 + +有些远程仓库需要认证才能访问,可以在 settings.xml 中配置认证信息(更为安全)。 + +```xml + + + + releases + admin + admin123 + + + snapshots + admin + admin123 + + +``` + +server元素的id要和pom.xml里需要认证的repository元素的id对应一致。 + +```xml + + + + releases + releases + + http://localhost:8081/nexus/content/repositories/releases + + + + snapshots + + http://localhost:8081/nexus/content/repositories/snapshots/ + + + +``` + +配置完 distributionManagement 之后,在命令行运行`mvn clean deploy`,maven 就会将项目构建输出的构件部署到对应的远程仓库,如果项目当前版本是快照版本,则部署到快照版本仓库地址,否则部署到发布版本仓库地址。 + +## 镜像 + +mirrorsOf 配置为 central,表示其为中央仓库的镜像,任何对中央仓库的请求都会转发到这个镜像。 + +```xml + + + alimaven + aliyun maven + http://maven.aliyun.com/nexus/content/groups/public/ + central + + +``` + +`*`:匹配所有远程仓库。 + +`external:*`:匹配所有不在本机上的所有远程仓库。 + +`repo1, repo2`:匹配仓库repo1 和 repo2。 + +`*, !repo1`:匹配除了repo1以外的所有远程仓库。 + + + diff --git a/docs/tools/maven/5-lifecycle.md b/docs/tools/maven/5-lifecycle.md new file mode 100644 index 0000000..a0408c3 --- /dev/null +++ b/docs/tools/maven/5-lifecycle.md @@ -0,0 +1,24 @@ +# 生命周期 + +项目构建过程包括:清理项目- 编译-测试-打包-部署 + +## 三套生命周期 + +clean 生命周期:pre-clean、clean 和 post-clean; + +default 生命周期; + +site 生命周期:pre-site、site、post-site 和 site-deploy + +## 命令行与生命周期 + +`mvn clean`:调用 clean 生命周期的 clean 阶段,实际上执行的是 clean 的 pre-clean 和 clean 阶段; + +`mvn test`:调用 default 生命周期的 test 阶段; + +`mvn clean install`:调用 clean 生命周期的 clean 阶段和 default 生命周期的 install 阶段; + +`mvn clean deploy site-deploy`:调用 clean 生命周期的 clean 阶段、default 生命周期的 deploy 阶段,以及 site 生命周期的 site-deploy 阶段。 + + + diff --git a/docs/tools/maven/6-plugin.md b/docs/tools/maven/6-plugin.md new file mode 100644 index 0000000..a50ae36 --- /dev/null +++ b/docs/tools/maven/6-plugin.md @@ -0,0 +1,63 @@ +# 插件 + +maven 的生命周期和插件相互绑定,用以完成具体的构建任务。 + +## 内置绑定 + +![](http://img.dabin-coder.cn/image/maven内置绑定1.png) + +![](http://img.dabin-coder.cn/image/maven内置绑定2.png) + +## 自定义绑定 + +内置绑定无法完成一些任务,如创建项目的源码 jar 包,此时需要用户自行配置。maven-source-plugin 可以完成这个任务,它的 jar-no-fork 目标能够将项目的主代码打包成 jar 文件,可以将其绑定到 default 生命周期的 verify 阶段,在执行完测试和安装构件之前创建源码 jar 包。 + +```xml + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.1 + + + attach-sources + verify + + jar-no-fork + + + + + + +``` + +## 命令行插件配置 + +maven-surefire-plugin 提供了一个 maven.test.skip 参数,当其值为 true 时,就会跳过执行测试。 + +`mvn install -Dmaven.test.skip=true` -D 是 Java 自带的。 + +## 插件全局配置 + +有些参数值从项目创建到发布都不会改变,可以在 pom 中一次性配置,避免重新在命令行输入。如配置 maven-compiler-plugin ,生成与 JVM1.5 兼容的字节码文件。 + +```xml + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.1 + + 1.5 + 1.5 + + + + +``` + + + diff --git a/docs/tools/maven/7-aggregator.md b/docs/tools/maven/7-aggregator.md new file mode 100644 index 0000000..b497a63 --- /dev/null +++ b/docs/tools/maven/7-aggregator.md @@ -0,0 +1,17 @@ +# 聚合 + +项目有多个模块时,使用一个聚合体将这些模块聚合起来,通过聚合体就可以一次构建全部模块。 + +![](http://img.dabin-coder.cn/image/maven聚合.png) + +accout-aggregator 的版本号要跟各个模块版本号相同,packaging 的值必须为 pom。module 标签的值是模块根目录名字(为了方便,模块根目录名字常与 artifactId 同名)。这样聚合模块和其他模块的目录结构是父子关系。如果使用平行目录结构,聚合模块的 pom 文件需要做相应的修改。 + +```xml + + ../account-register + ../account-persist + +``` + + + diff --git a/docs/tools/maven/8-inherit.md b/docs/tools/maven/8-inherit.md new file mode 100644 index 0000000..d062834 --- /dev/null +++ b/docs/tools/maven/8-inherit.md @@ -0,0 +1,169 @@ +# 继承 + +使用聚合体的 pom 文件作为公共 pom 文件,配置子模块的共同依赖,消除配置的重复。其中packaging 的值必须是 pom。 + +```xml + + + 4.0.0 + + com.tyson + account-parent + 1.0.0-SNAPSHOT + pom + account-parent + +``` + +子模块 account-email 继承父模块 account-parent,子模块的 groupId 和 version 可以省略,这样子模块就会隐式继承父模块的这两个元素。 + +```xml + + + 4.0.0 + + + com.tyson + account-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + com.tyson + account-email + 1.0.0-SNAPSHOT + account-email + +``` + +## 依赖管理 + +使用dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,不用每个模块项目都弄一个版本号,不利于管理,当需要变更版本号的时候只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个特殊的版本号时,只需要在自己的模块dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。 + +```xml + + + 4.0.0 + + com.tyson + account-parent + 1.0.0-SNAPSHOT + pom + account-parent + + + 2.5.6 + + + + + + org.springframework + spring-core + ${springframework.version} + + + org.springframework + spring-beans + ${springframeword.version} + + + org.springframework + spring-context + ${springframeword.version} + + + org.springframework + spring-context-support + ${springframeword.version} + + + + +``` + +子模块 account-email 会继承父模块 account-parent 的 dependencyManagement 配置。 + +```xml + + + 4.0.0 + + + com.tyson + account-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + com.tyson + account-email + 1.0.0-SNAPSHOT + account-email + + + + org.springframework + spring-core + + + +``` + +springframework 依赖的 version 继承自父模块,可以省略,可避免各个子模块使用依赖版本不一致的情况。 + +与dependencies区别: + +1)Dependencies相对于dependencyManagement,所有生命在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。 +2)dependencyManagement里只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。 + +### import 导入依赖管理 + +使用 import 依赖范围可以导入依赖管理配置,将目标 pom 的 dependencyManagement 配置导入合并到当前 pom 的 dependencyManagement 元素中。 + +![](http://img.dabin-coder.cn/image/使用import依赖范围导入依赖管理配置.png) + +## 插件管理 + +maven 提供了 pluginManagement 元素帮助管理插件。当项目中的多个模块有相同的插件配置时,应当将配置移到父 pom 的 pluginManagement 元素中,方便统一项目中的插件版本。 + +account-parent 的 pluginManagement 配置: + +```xml + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + +``` + +子模块 account-email 继承 account-parent 的 pluginManagement 配置。如果子模块不需要父模块中的 pluginManagement 配置,将其忽略就可以。如果子模块需要不同于父模块 pluginManagement 配置的插件,可以自行覆盖父模块的配置。 + +```xml + + + + org.apache.maven.plugins + maven-compiler-plugin + + + +``` + diff --git a/docs/tools/maven/README.md b/docs/tools/maven/README.md new file mode 100644 index 0000000..411f823 --- /dev/null +++ b/docs/tools/maven/README.md @@ -0,0 +1,20 @@ +--- +title: Maven基础 +icon: build +date: 2022-08-08 +category: maven +star: true +--- + +![](http://img.dabin-coder.cn/image/maven-img.png) + +## Maven总结 + +- [简介](./1-introduce.md) +- [入门](./2-basic.md) +- [依赖](./3-dependency.md) +- [仓库](./4-repo.md) +- [生命周期](./5-lifecycle.md) +- [插件](./6-plugin.md) +- [聚合](./7-aggregator.md) +- [继承](./8-inherit.md) diff --git a/docs/tools/typora-overview.md b/docs/tools/typora-overview.md new file mode 100644 index 0000000..0f2b787 --- /dev/null +++ b/docs/tools/typora-overview.md @@ -0,0 +1,184 @@ +--- +sidebar: heading +--- + +11月23日,Typora 正式发布 1.0 版本,正式版开始收费了,定价14.99美元。不过,Beta版本还是可以继续免费使用的。 + +作为 Typora 的重度用户,今天给大家介绍一下这款 Markdown 神器。 + +## 简介 + +Typora 是一款**支持实时预览的 Markdown 文本编辑器**。 + +## 特点 + +1. **所见即所得**。输入`Markdown`标记后,会即时渲染成相应格式。大部分的`Markdown`编辑器都是一半是编辑窗口,一半是预览窗口,而Typora合二为一,更为简洁。 +2. **支持 LaTeX 语法**。 +3. **支持图床功能**。 +4. **定制化主题**。 + + + +## Markdown + +Markdown是一种**轻量级标记语言**,排版语法简洁,让使用者更多地关注内容本身而非排版。 + +**基础语法**: + +![](http://img.dabin-coder.cn/image/image-20211205134819994.png) + +**代码高亮**:输入 ``` 后并输入语言名,换行,开始写代码,Typora 会自动实现代码高亮的效果(如下图)。 + +![](http://img.dabin-coder.cn/image/image-20211205133939439.png) + +## 图床 + +Typora 里的图片是链接到本地图片的,如果将文档同步到其他平台,图片链接会失效。可以使用图床来保证文档在分享后图片仍能正常显示。 + +我使用的是PicGo图床工具,具体配置方法如下: + +1、下载 PicGo:`https://github.com/Molunerfinn/PicGo/releases` + +2、选择图床,设置相关参数。PicGo 支持多个图床平台,如七牛、阿里云OSS等。 + +![](http://img.dabin-coder.cn/image/图床1.png) + +3、设置 PicGo server。 + +![](http://img.dabin-coder.cn/image/图床2.png) + +4、打开 Typora 中的「文件-偏好设置-图像」选项,配置上传服务为 PicGo 和 PicGo 的路径。 + +![](http://img.dabin-coder.cn/image/图床3.png) + +配置完成之后,当你在 Typora 中插入本地图片时,PicGo 会自动将图片上传图床并使用 Markdown 语法替换图片地址。 + +## LaTeX + +Typora 支持 LaTeX 语法,可以往文档插入数学公式。 + +数学公式有两种形式: inline 和 display。 + +- **inline(行间公式)**:在正文插入数学公式,用`$...$` 将公式括起来 +- **display(块间公式)** :独立排列的公式,用 `$$...$$`将公式括起来,默认显示在行中间 + +**常用语法**: + +![](http://img.dabin-coder.cn/image/latex语法.png) + +下面举几个例子: + +**分段函数**: +``` +$$ +f(n)= + \begin{cases} + n/2, & \text{if $n$ is even}\\ + 3n+1,& \text{if $n$ is odd} + \end{cases} +$$ +``` +![](http://img.dabin-coder.cn/image/image-20211204235551407.png) + +**矩阵**: +``` +$$ +X=\left| + \begin{matrix} + x_{11} & x_{12} & \cdots & x_{1d}\\ + x_{21} & x_{22} & \cdots & x_{2d}\\ + \vdots & \vdots & \ddots & \vdots \\ + x_{11} & x_{12} & \cdots & x_{1d}\\ + \end{matrix} +\right| +$$ +``` +![](http://img.dabin-coder.cn/image/image-20211204235601934.png) + +**偏导数和微分:** +``` +$$ +\frac{\partial z}{\partial x_1} + \frac{\partial z}{\partial x_2} \\ +\frac{\mathrm{d}z}{\mathrm{d}x_1}+\frac{\mathrm{d}z}{\mathrm{d}x_2} +$$ +``` + +![](http://img.dabin-coder.cn/image/image-20211204235614665.png) + +## 目录 + +markdown文档生成目录,我使用过的两种方法: + +1、在文章开始使用`[TOC]` 将自动在文章生成目录。 + +- 某些平台(如掘金)不支持 + +2、使用插件 doctoc 生成目录(页内超链接)。 + +- 需要执行命令`doctoc xxx.md`生成目录。如果修改了标题,需要再次执行命令更新目录 + +使用 doctoc 生成目录的步骤: + +1. 安装 doctoc,`npm install doctoc` +2. 在文档当前目录执行`doctoc xxx.md`命令,即可生成标题 + +## 定制化主题 + +在 Typora 中 CSS 被称为「主题」,但其本质仍是 CSS 文件。可以在 `文件 - 偏好设置 - 主题 - 打开主题文件夹` 看到这些 CSS 文件。 + +可以自定义修改 CSS 文件,生成新的主题。 + + + +## Mermaid + +`Mermaid`是一个用于画流程图、状态图、时序图、甘特图的库,使用 JavaScript 进行本地渲染,广泛集成于许多 Markdown 编辑器中。Typora也支持`Mermaid`语法。 + +下面举几个例子。 + +**流程图**: + +```mermaid +graph TD; +A-->B; +A-->C; +B-->D; +C-->D; +``` + +![](http://img.dabin-coder.cn/image/image-20211204235313626.png) + +**时序图**: + +```mermaid +sequenceDiagram + Alice->>+John: Hello John, how are you? + Alice->>+John: John, can you hear me? + John-->>-Alice: Hi Alice, I can hear you! + John-->>-Alice: I feel great! +``` + +![](http://img.dabin-coder.cn/image/image-20211204235348115.png) + +## 导入导出 + +Typora 支持导入和导出的文件格式:`html`、`pdf`、`docx`、`epub`和`latex`等。其中导出`docx`、`epub`和`latex`需要安装 `Pandoc` 插件。 + +## 其他功能 + +**打字机模式**:使得你所编辑的那一行永远处于屏幕正中。 + +**专注模式**:使你正在编辑的那一行保留颜色,而其他行的字体呈灰色。 + +![](http://img.dabin-coder.cn/image/image-20211204235513676.png) + + + + + +码字不易,如果觉得对你有帮助,可以**点个赞**鼓励一下! + +我是 程序员大彬,专注Java后端硬核知识分享,欢迎大家关注~ + + + diff --git a/img/1588431199776.png b/img/1588431199776.png deleted file mode 100644 index c28de4d9340ff02b1f26c604165de87afc182865..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63521 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

H@$K;pBU&fX$_24I6PiZxpzaRoU*Y6wQxY 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 diff --git a/img/ConcurrentHashMap-segment.jpg b/img/ConcurrentHashMap-segment.jpg deleted file mode 100644 index 4b709a3d983fafe226abab18b3e3630dc12b49dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 230179 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

(dJc*MTV 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

m~*)PN3|A9CN zLw#yKd<*Lzn!A_YR3E|LSe`AZ$dBMPV`$?V69yU*!-+Mar7KcS%qQD2 z{Bc)Z9Wf%w6-w^wyNjiySohsC)=LhEcmTn!5ZK(R9NB~lfu>*5^cm!xvBrCGJmyi_ zbcT9SA5HGK!FFAW{(66`U`QSat ze{peSM+;apnEWKLpGj!QI-nP<*$Dscgk6vAN{uM^Dj7It;vs=BRXlTc^OYcN!KBxR z?*X9Qy?hFo^iN2q1;AAvh*W14`rke|`_fK4>d8!%V_V-(2X+6H3SV99qgOOlJ#Luq zd)~*gweJ7;@na`j@XQgwdFYPBj?*YzY?6^=LI5#>aKceP zAxtG@sRD6*Tfl|co~LfUl{5*sFkDLyL_lDFp^=H)S^P;x!-RO0toPvs3;~oO6|v4( z?lVx%`xJAqKw~mg6{Q8w*KOH+IO&%Q_g=4>yhgC*ZX(zVhFsRX0pL<@?>Znc`~$2~ z1?h2OpAlF%aBRjgJA~09mKxy|#ZM_d5!)~L<_^#gQk3hP2E5tpR}I-;J<(%hu^8Xn zqd*)JpaGaBX#OAn$=U1q%&HD6;L6`f?7n*B%kj9R8moVh`MB40Uv#|P)L#tn-$T9t z!eBCaW#)gS#J^-BD}iX*{ag#pzf^QnM*sBo_~sjKCCPtnj6mj>QecrAo)IznJ97YM zd{f`?!rc+~f4IbWxBTmi$JIlgY!dRX_1S{uFF)lLEL*Vrd+KdXqQCTqTd-`w^6&L) pYbE;c?ZN*;i7i0zC2uPD& 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


3%zov-(#YXyKd*SDBm z8%-4V4&6j^`i_DeF&vi?G&iPrepq*_YdY&5N_j$Fo{zr+nWc$&ie1LXP- z=yiEl1+(R6^Bn}lBgTvsq5=9Bey=JNi4P6T&6-qGg8wK#3u&7xc&L6!w~YrKVo5rh zpK{lk+;giV@#Hjkwg#U4c@sfLD_@X9Zio97%1b$Flhzb;(xm%D!7uWybCz>oncMI( z<#LrE#)3y$9e1(48+8FGNn7$q^!y6k{JrhecDLQD=JY!^i~G7>2j%Uq%an%emA2a+ z4T3gY(9YPb{j6Vc!RM;Af$k?lPQ0WBQx8w(0?ibGtnk0hz&DkT)EqA^2FhuA4`75!)5{|&OKJ~<}oppSHHDZrD82|yI+wiz!R zID43t5`Z&Dyg4BF$JE1@kR~X&39wXwc`8I1^`pD1Gv%Sh^%KB+tX}#A9RmoPw{Z45 z-A-*FT|BltHW^=#U6!DA>B)cYx3ZFEAX#SXh^v#keBe0Oe~%AvEB%}J0JHYnY9ZYc zBj6d)fghl$casfm09G4-m2$)EUzi;4U<2kDpc%Fxe1PWEeO_;Gc}@2=$9g7ciw{hj zdqxK)gJmvB8(WafMZX6` z$sKsG09m$3lRI`!5fZWet5jBBKIXcF+*%DtvNi}2^^$Ihs*<=Sa@cov=u_0{2k;%) zg4S0|eTB!o2A|@^ryJ|y`x`dG-#Jk(*Wm=maW}0D3ho-_8-N+;%2C>8O_v0B5T1@} zTB5+mB$GCBf)cyCS9St<2xEh&{_IbK^i|-50R*yAZcp;1-<=*2%`M``4cih6AKC-6 zEXt+-OqHEuji7~w)0KJ5!Tk@3V5<}L22t+>^s7bWc_k*iV?x&z6V{4BW`HnCh%|H3 z?WY^A%;-&s?$mh*hQ;kH(g|1UDL-G5PZ*`;gY-KM9X1@@D!Fzyn>svuOU7>vn z^-zt<)%!P>@T2$NT*BojW6{64gj?a+PsV^tn0WKQatR54x`h8c+@o$mv;iMUcK%nu zejRa;vx5BZyYBU090~uDR-vCG%#$}aKDt}oz%0y$b@depL34M`!BXDaJ84~S=azW0 zMn5$VAJjBClP#3jCh2h@AKWz=bQjzncj7qPQ`^)gu$_3aS?5N3ICm>rV0%FJka(Er zovvN{Jg-n@l2)xNF=g$2nQJh53f*cjEgx&tD;QwN79ta@^2%M}7C_|Iza89jw$-Zc zbmu|KlI}c2f3|i)APtAd7S)2~B021N?q>!SMZnUHe(T3=!KVduATLgR@h6bS0U&3q z#;G2VHvl5PeDc7bgGY3*X6x$SI6|loJUu`;m8z&Qgn8O93CY<{VLk!@l6O z`qC?O!4Anf{1@Dvi=xf0E~%fBEV;l&ng?q~e}8bF*d4e2qkce}uQ=tWfHv_#K!GbY z+|QS$M&)J!9NMA-?-vK!uy|!KARVton%zyL7o#un4Mrd5poV`Hspb4ercE_I&$oV# z*zrp}Chmp{ws2w3{1r&=;!a0E%|x_>|D>OyySc|uuC5Lf($f%!=4T1d(%S>MT9!?q zi}Dv<(*^hMqRkZYy&O=N7$FeJ91wB1%h-0^OPQ0N)3z=xU^-VNvngB#8z%2{lJ`O$ z+Ul?EUUkf2`nTM8{3o{nozNDpJNexNxqu7})S$R_`KE%nSQ=dg#!D4Ud*>~W&csV8 zd@lgWpBzft?Wc9|AiURgDpYbLj9w=KJ@b8{A#2)BDm!3-+rqB_PZZ^px68q~ z8_h$Plpu*#+rXQhU1p-0w`8^g1vfmu_c?^eEelu>O9245+y0aU;@GB3dbxjS?m1A` z&4N&nL9+o;m@dvIeUv@DA@A%ZGv|q3!WWkT3^_iD@44dj~~eIdgE`;1ER+-4b{#9Ia znR)9ezqR;@KE=(^(PHao14XTr|RTHPMwF7K-~db8V|{Bf9TPOezlnB$n!p$#k=%mzNfk zN>3Dlud5E7-rCh=^!-EAlBZ9>ZPlHKk8QUdqj)ClQvuHOgYt9$NMJqx&tP9h4X`%+QlYG8D)&z{g#dG_T4zwjHe*T{D@_!y zD+dYSQj~RENwO@?CH^j!At|Z4og||CX(ekfMEipJo6Fsg7#J_<3O?WUD~%S%>x@x5 zQ>@c6p@}}rRfUL5VK5ayOCKV6>OsnFfYu>B(QeQ$hEw}LmyKI~&?jF%+yKJw?&;~u zT(-Azj0s%DCV)2J<~RcI5g#F|C8NB7$Wm` zBCKdP5hlQb#>MP%G}BYfn~J~?SiU^luq+U&=)f9MIB(fmD80a zp{J~OWTH=<9p+L+Kh1OW0NR3KWeM->qu&t!pT0HzA4TThb3gsR+tVzKK}vYGDDq6H z3Yagio5~$Gb2B#!xd$#5-~}QkdPPP^^oo#}wEh(tIq+XpLQoX^7Cl=cO8UDB4o>Da zmYDy%g7xxqHBdo|-h-=?rJJXjiv2b*@OA_mYu9 zNlBas-AfBy5fc)-a^Bj_%~?)F#M9GL*oIyU{D4}*PA*motNyZ}sz}!+?SKP z>GZ(e!NSo^PEH#Xb%k8Xq}7Q0Lz&&a<>XW?Y^Q2Mafhvjt>#R3grfR?5YOTK~|FramYIxgvQ*T2w+tOh%$J z#AXH*IsKP*^lZFA2{B;__3PKQn|G$cW7WSrHqeDbEN$#9KnO%Uom}i(oy{Ith`2d8 zi`Y0=dDvKZilJmt;*u7U(y|gV5AK_ZN!&+?nMvQ5wnSZ#xNj_K;xr_a4BCXiRkUvA JU%&VGe*v{!RjB{~ diff --git a/img/Java-Collections.jpeg b/img/Java-Collections.jpeg deleted file mode 100644 index cf9071ff6a26db773f72703f21c3703b88c3e6bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167969 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 z 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%0DV+F>>t{q}Hy(?h4T8QF5U$_)j_ zp*+3gC%mPHNk%Is^|1ZNWdJ$hFxN}ZJO`ymmkQ&}hOh4xlICLEV-c-NYfl?ZXAAm< zqkYa4_AmbYrG>8y^g7RQKfiL;LGq9z_0s4oysErW$}Q~SXRp!|dUQ3d+ehJZH7aYF z)6dI3We%4v__4UI%s23bgnM*zUHGCfk3JbqZwy&^>=n>vXH?B~RhlZ9rbSgLQjW0I z;9VEGv1o5vI@1cmJ)-YIAQV` z?xY}B-_?>TG78zVq}iWe&=Dcqex@G2|JDArSlt7+TREpn&c47hC*LeF8+w=c(Cp@j zb(u1IE9^kE(exP*?l@A~`*e;TTVJ&?t`3)`sdxo|`T`!DvmQnl`g4q%S`!{zbsfkz zF8-XeJK^QQ^9?Y>QChc61Gt5Us#ACNV&9k)Na6g!S*7?p;_X+J10G?^EO3 zIhu0@Aq4NLWgyY^s4!c;b>+b3p|{XQ^JY&}Z=SzX$icQ>imF~rgfZ?mG2@`r-coo|l=( diff --git a/img/all-table-search.jpg b/img/all-table-search.jpg deleted file mode 100644 index 8c0605ae8b75defbbb9fb64bf9b05e2e00206469..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14178 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

U4Kaa8L97}`9!&AIce!lyNd zUty8!e|txUx?Z;IHJQYy4L0V>$dhoEp%3pm(;F;?v!&H34McF6 z;((IhlWs`;UY<_)ZKyAb*PVsbKP4tokT?9z?h-1+h!o7AX#NKScal)f&j;rV*Ecz9 zY!*Y*d8B4faj#xg1X1#j#1sCIqFfFd3gzeeSXhc>pwYPa^0jqcc9a2p+L;-5O~M;G zFWjpteBINYZ@I=(vBP%_^jKw0UjqXadlNTOfbI`&)NVpr(r;SWj1~FY9q}2C1-0_3 ze10w6pJE$%)(MWAhng~=I_iMQFm||VQxVUs`tfD^!UXZlpk=+hoI^-^1&e)DbOL?G z&SL~+FKR|wex8XEbXRBN=^ez0n*Tax-YeRguF0=O;w@d2mJbUOW>=&2vI_m~`K{!( z|3Ip>;Z1Wq_}Ek(aru)9O~2xFr}dp{CZ8ptav9sLg=m>3TS`L_+=q9-FNy7ia?|@T zLSf;=9+JR9t3;(TsT>V4Y$1n4JGO$ha~%E&+Lu>8pO~%ZlSBh;DGO@mn;&CKgtoX= zqzrg%U*Fc*@yHi^zX0J(Cp>Rs-~553<8wF|sI){XHCwZ|=fN?=}IDJ6sB71fb3i4NPm z#Ef?y+8NQSk!Thk32D5uf|F^-j9=so>yBq+1nlQX{p=-YEPRu|=4Z(Mp;}90?#_x+ zr1n?jk>H2JGSKCH#|=!!J(A1MUqRcxV78mGx+2b1hL%0MWMnrMnX1V{_=h&fO?QEA zCHM*3s^i@-^RkWmh05Tj;+2t#s#yIL&fYa`+yw=7qecO!!K|Dc;UWKu8hELuw2JR> zvNEam70SkaFMhq=<*%1k|5lNaot33D%a^e`>hcli;}4n4p#Y*YlHhfF_?eHEl}_E{ z`)^t-C@;Ud$J{Yz2oBl84}8jWUk;TP6p!uXQiADwPrOaF@XCB`L*9V6KS_m%ozsVk z%K}LfxL)mh?bIhvq}`K$4Pk9t~Xds&|Q@YNX0YpPDlPnl!(+|geMWGhozMMMGPx&-dxJs5zTq7LX z{-h(~?ChM1`wZ(}mNAbv)sny&J=R1kY~!^1e&ctGC_k1T<}$^5B^t9*+@i76^k493 zSDaAuNU~{6PlL!M2;(2?jM!B_xkdjbFCNwVXsVk-B#^tKgJ&uzmm5HXPegH&)RF3Q zo!EGcYV)hUe=O9UUg0qzN#)M}oxMx!+^0pNrf#%)a5Ovu&4XiVcRbOj>MRA=?r_Hh zuFrz>J<*m^L*G?6>5N=NJ{QtZzSmeKh0C#5*wq|GJ}*4jw5iu9k^P8&G@Rq9k`dX` zQa3O78YGf%d?MY^=GQ*Jfx|+;Itxfc|Lkqr^kbhY~=Jcz@q^CU=M zKE2QHx#`LiQWIoR#Aq@D6)$ov8mwXP>ska8g2o37(YckErH{l&053rik*VV3Vu^j<@bVuUwSf(?n?5M0{}TkJ4US9a7f z?bw-Eme1^%=DE((#=ie~|0tFZKdHG8?fcQ_(6);rNu+M;N>41o{$je1gGGcTwT+_X z1s^}P;OB4sMI358rN`vxcF_7Lz^=S{HG?)|_V%HYNV;haN`q9eJ>-nxLVcMw)Uv3! zX7H3E-jUlV!RRa0*$^&I0hO6>ENv$eD^tKblHcT6R=IIKdNiPX8>+%Gr6=F`b%7 diff --git a/img/aqs.png b/img/aqs.png deleted file mode 100644 index 08ceae567c03166674036a66fd001b9dc1f04be3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21797 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 F_dmk=*DL@4 diff --git a/img/bean-life-cycle.jpg b/img/bean-life-cycle.jpg deleted file mode 100644 index 628017f3319f30defb6250da9f4ffb7fc21c716a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29410 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%0DfqBI$=A40aJ!J2Lj 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 diff --git a/img/bloom-filter.jpg b/img/bloom-filter.jpg deleted file mode 100644 index 96e3f884c28b9ff98e3efde7086390b5ac77835f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23578 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≻s*&YNVdZKO!d2 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 OCLN$}y8r+H0000H#w4Kt diff --git a/img/cms-collector.png b/img/cms-collector.png deleted file mode 100644 index 3ed3bd82543efb520215b89e8cdad658d98c29f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86817 zcmc$_XH-*L8#Rg|A~gciksL)q=@7axd6ic<(jvV|1O%i>6AcoH3M6!1l`fK(!$G7O zx~P$odZa2H^gxP$6eU{}wvvRK^L_VzcZ~b%j{E(%$;ima*k$Bdd#z{9XU_TT&F-

w%>jwW^yw@+LaA=?UesA%83S#>e_K7R( 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

pnue}?PQtJ+GN6^v@ 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 Kf4F-0@&5s77n(Z& diff --git a/img/condition-signal.png b/img/condition-signal.png deleted file mode 100644 index ea388d9e84b3b9c7de0ce35a4ba5df2e80c04caf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48475 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 ZDZctTp+)dcuoDaZ)K%^)m)*7q`yW)BB%=TT diff --git a/img/condition-wait-queue.png b/img/condition-wait-queue.png deleted file mode 100644 index 9d2f803005fe990d168ed3f214cbaf13d5c94fb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46923 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�|<<|G!@5kl>|h+%p1^m!~o?FR&p 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�Hd_|0KL=`kNI&ZFbZcL+n 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≈rC9sUW)-~Jc~wx?0!z3l5w4TvRF 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 diff --git a/img/docker/docker.jpg b/img/docker/docker.jpg deleted file mode 100644 index a64ca6318beaf8b83b37706ff8477bfc2cc08a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88608 zcmeFYbyQqU(=R#+9zuc>Jiy@YPJ%NGu0a!QV1U70LV`QN88o=Ndmy;G3>G{PAUMGf zdA{#?-n>Wd`OaN;t$Y8td)Dl!p02L?b$3fYV=bNAl>*zz(U8Nj1Q0KlV%58!?Q zAPIQ<==b&e{`mKWjP(1Cf{cuWjEaJa`qvi?1059&0}T}w9TOen$?xlddW!kv>F>mE zA^%bIF$xkA$`dqHw7*#Xk8by0066H6#gPS&9#I1x<2*vbd34_epm+fJ_z}u)ynkQl z7-)|kBcq@qJ$cA?#RdS7Q63>7VPN55Afuq8VgepLMtaCa!$HTurNZMB$0w#%ePfhR zGeOA3$1kX3@9g@qs(SJX!3!F0UI7U;2S+Ctx9G&mj&UM&4K3r?xXiCW-ewIA=@D>&labPvjKz{YsDTz4p%{4C-fUPlUrYIktrE)1nl50)eAlE@pXEFM0uGR;>W)|$tv51

X>y(3!TKb zE+Z@m_0^OViAa%%-KREO2%J>uiHtOuDy6I9;>oQwiQ=;ytE;tWwbqp^*^G(rw-gkS zRntvM}YJMPA;hUeyRS@qJ zQk_-17a;c*shsVeY%6xN<(c3mviG)dc2Pfn0>0(V{()ljlZePc)soM>CD{D~ndPE#&6Eo>9)N{J6ubzaG4s zJxYyiG8`G%8}weKdDSJf<0&j$&3fSm$n}|mw)5Djk;@JrChc>Zx7$dwiFwgeQqx_P(RPz;j{UG!R+eU+L)_EDx|FL zEVay&DR`8MGp?r|dtj)sFTszi-zAX1)vRq~Hbq^2ycQsp)sYN6k9mI-ZR#&Gwdvx>q01-NF6x)XLJfzlGFS!W-Kz;r1gUlbPcL1!yj_CCqJM%N-$hep;4PL2ZLW4)>@>&9Wy>3d`upyCwr0de^tAvKiuoLt^eIN ze|Z|t?bbcO>eq~ zrNuF*xPTUK#=xzw0Um2wy53>`O|t8uXWU##^;RCnB_v`?J>&NgY^@}F($V#wTn1`C zD6=b0^F){76=p@x^V#stACwAr>2Oi&5aAbuJE#oMT`;Lf{6Z+Qd+6@j#~T2%i3DX* zOS@8I-*h@_E#UO7P>*_WoPpQa3*FnigS-)hG?48~E=EKin;q}{T!@ak)@ zWu$M)W<$+k7)+I4ya$*kxpCst2bMB9BH(pj)^WZY0MJx_{Nd35 zCDQbPiv#uRH(B3XI)PYFSDrY_dqpY zQL8y7Y;kJa+LRk_&RKD@cvYzQ=95otU2tmGE|o2Kfmp2*szr0JU*%Mmfg#CX>#f@m z5o~gyt4R1>5|DoxiobiV?U6nA`)(e<}Qj zvHzTvoL?C|HP`!H%&#n{`fIb$lABU*oS3M!cY142!jBF&AE31l#Ac*VD;@_gJH-Zp ztE0AE^@mXH9?6L-{n53WJs@Lj$6QD%?WtdU}N6&5Y8mYMywC_6zEbM&AIu{vZCf zb{^^u6B@}ScFz`pNkM=7WZfHt@g*UWu22c<2% zgE1Olbz*KVUek&<9rhyO_Sz$~)gC?WJigwO#!U9y4&>&@N4A-By<`$C+nhOlw?{oW zG%r8rKT9>0jCh%uL~U^dzD%+ZweE-#-k4K_s$vCNQ$fHHdKR5`kQt8_F&Sdi+$M` zVd|51wwA=@Ig`(Q0%H(tgyXupF_SClh}jTRofPIx-iE8;7g)G}kmcT8gkj-q9C}9|vY=nGC4-tGGt^@hzkZbL#SQ3akNdffawbN< zK;b^Sx@05jUpT?5fSWgEXKMrney$Iz*!pJD8`fcTG_@{Y)uemLTTrHy4NHW$-6Yif zSS3-nnYBDuf;H1!Vt$(6uI*`>$;&3Ij2DfM?R&#y%w-u8-sG|;5uqUZY`zYvC)eZd zwS7(P_$^Gt`{oJlJbgi!c;2u{(dM#lZogFQkix|C;z(`WRfmJFj>5Xbz+oMpy6UZ7 zW0p48I;+<)bIxqq4(53EF|mBBz|(NgvXZ-vU(K zZ8zF$3@W2)j*4Y?XbVpbehrBEh{a6f*GQFl(&p>Ilti&7BN{QWP1nYJdCaySKm&--KzKuJ*+taYNtZRGElSwm5WKkREmAefsmq{^qY=r+ zT~lW$&Y}^PiJvXqcRw4_QC@Z^b@lLdUVxllv5hbZ(%Z^wyatD?+TI!`0om*5ez8VJTu7!iNnp7Lq z8VDHbv)?WGhVu=IxhrN)6{9ToU-ByYy*n^To8{HkgStXuq&e9FI8H z3c{6_pKQ@tjTCv>E&IkhEqP|@beBT!IdrRT4ekxST-Vh46oiQ#_LtnEw;y% z6JCUo-*qRLe^IV!!X5xjTe;@BINFx^C>}9!})B_mNCM&KBkRTs9A)8sO#fSs^be` zJOieCU!v(=W?{F^^i{-yvOV2`>w__ArqX9xxuFU7fY#hl-^8*ay$?;6xX!>lh9c7~ zRqnbhGG`1M0@iXSHBfwMH_ImkwiKidC_6T;XH=3lTUD=HnPZ*16i`x1B~krGw=bE% zOhcTBW0<479&LbFWFk0j>q^U14kj-azDiEH@W$i0jR}6sPTx*=Cw!dz6+6UCEJ(s+ z(8V-x#wJE1OR@+EOaQ4S$PLm-F6++m#n%1QM8kX<<3OW)YMi<;-rfCk7+1z^TZEQ& z4~OVAlFJvx&llVV9z1bf%LBTrueAF!wKlfui=Y}`2I&_|tkv`wh{jBV{h(O1&v4b! zzIISJM$dVTl^15HzE>R(fzo7NrU+MCTMj4GkeBCKT}pX_Kylqg>5`Zfh;>@9gE?W| z09BUgdHuuMk6W04h~u;Ct$EKODwCDrq7i#*6kJ*f=Mz0<* zMZRx<2 zC-y-;d-my6{SVER7&6y-Hg{+4Y9GvlpS8GsmlFG*90C@o^fF%4s{RPH)H^Hs*^f4c zq2aNboN#N|d@SDD=r~vyal_u+HU*~H#Hdk;98X>>H!HFgFzKRrP-7$)1^;q`%nFU z7PYm}Ki)O@{|a=ke_`o2I9y?y$1WZHj9YN_m6!Eu+I1sHN5{gWG9QXjDvnk|uLkx& z)xD7fIqV8OOfzd4f)D2@xFm%UvA4&&Mmq!Y_W=4tOWNd|6Tcqsj}1eWy^&J(^Q=14 z7ntVGWhKRkA~WHX-hKlIAt--@12rA38UB&2zkW&B(n=Oh^=s$%XwQZhS#V1ADTM^<8$4bE5XHC@?s}?`gFEjpHq(Z6EorFm?A`JSe^+EDJC#K*S{f%GE~nU3|Wg{kia*E zcs;Fx(ris!@WsvR)b*SwICJt_Cf1SUevBQlKpa?jrB=dkkkFpp)LtAl4TjM+?J7c~ z{gf$aUiJ%hkBy|%U{&L(PqG5la85m#n2ktrNKr6UdRm_i9*$KaFI0SYpN``iO4B;3 zZ*Fb!6Jw;o8R=OrF0P4^Pj;C%$^!@Se25c&)5HfYT*zgL(AJQDrynoLiYwrHdFLjb z{5~m5>jVaeM{i206Tp)4 zD{1nvj^!4?O;tf+-S4X9)1p)*p`7G}@xD*5jjrt)P!;nHDq72BxjC>zDeV%(pB!$8 zp^^9Gwu=(k?mA)Oq0EecBb*zmtwOSNt{~jg15KfpdF;poSzwhBfq23bPR?<3>tV$N zq9*xorm`av6tL=667H6Z6>-;*ooOC3antRysR<+QYJB6$WjU%b=UO0l{2|OeR+-Lu z`(AQT@+XMQDlt69Rl0O9d$uLkf-T0(RftO>)T1VUO+WuYks>c5w=dtWL2{4Oyc=B$ zql-vFOL`<005a0&QOYVEPP@#sxNXBg-ixoTSipN z9#7o$FP`N1u#gFv^mCy>)7gRTLFjd&`S&2kCy{eQ#-Kt(z6ur-PLkHDLZhsp8Q**^ z6qFOyGmZ;sYhess$1heQE0l zng+p+j;_vZ3{jOMkib#$7uJ!1F4865X;X`lG+e!zFN>ILiX%fLBZPdx5mGf962VK< z)cqons%X6*qfn|*JJ345)M1SBGHWIjb}1qy$Iy-p zWsazO0MEyB0=<LSz$WXo#H-G9N3PV0&7J^7gd-+7NFsd~*D29iyY72du<4 zA*U9PJC9e{VSo1}TbGGar%F8OCsrAfG`D`6TvWXQmUmH~!y(J{-ScOIyjWLXd?+TTy;BGLJ)q_nESKE}g$m+QsUP-r4B;s8pIJTwF+2+?Vla?O2csmSB zzOSG>_WOelO7v7tH&D3vx#K;5o~1K#ojKccFU%1k=E6Js zfmfc!l}#%|=CdqQ{68Mu0~mzwB`#%H(x(2*uOr>r5AFHkWssp?t+G;r zcJuj9dUXR5E9-sWg=?p-yby8TG7Bu%-xy9dPa{?YZBY5U*@BeY$ASP&DN z0t>DvTk}sY5Jb%UY8GpRWVXL~ekuM3ElG;_E6xQUjMn0gxK1u$ot}4_IJdElmgyAO z&LG{X{7KtFPaY-EqGQfM!l?1UJF-BI`*6NM^?=*gJet8q9LCT=R#C%4p@t?L+X$S$lgCm zr)C;}3X3rxkq)*2kaEsalt<7}s`jNybCRcd(!s<2VNrK<^gEZMZrXQ)CO{a?Og0l2 zZJG%U7bpXdW$4#E0RBF@vco$TXZ$Ukglu-gjUu(3hHC~PkQA&Ks~Zv;;0+U4%1L9y zgvrDMuj0Mr29vs-pc`#w14MFh8oSp@-zAIi#KDWj8u0LM>q5n(5kcD<^3p zog;Ob^9xZ0ifP(;y@)4J_2j(bdTx-ZuSQZHT%e)eXew}FlR}qNM#EG`HzsC>i##&A zW|Jz*$<>BcdZDIDN^#TWT${OIGdkv%g)jYrA1oiC8}snyvqc^RCyDW{rXgAPlE6wO z=_;;yUL{0#x$@nkvoL?_LYGe`p9Eq{s5H8*_U3!1rR?L{rfi;4@8sY`ZoUPYS3+?) z5N($<%XVegCqY58=g|yTd_fJ)WITaywZ;;q@(1!EsxoGnSX^c*;Vx|KSZ9(<>d?0` zPs3$E?|UOuXY{y>TB%0&dGJL#XDvgGbak2_+36e(O$jMd4(Y~#*{8?TPbT+Tv14eD zEn${QAlg{+Va7~%(Y3}nUUrxZ<{+!`2%_j2S4+vkz9beUdtzrrmVMVCNur|Gp1ynn zh%Q}C1))$M7kiR}9G?y&o;Ew0lJ+s>bA?i;lx^~*+o@S@HI)^g_0t}VVB|FHm0>*X zlw#f1lOF>+>lH{uy%32`M{Oq6`pj!o{Zm_c*HNOG+m-1sgMW=S(W29fXHd zXQp0+S+H5-%UrP`mD!bjhMOkw53Y*%Guy>IdCklp&^1Z1&?dA$xtL8&Q-TF>cuR zgSZf;GlvSfv&hGf=SCr5Eu&0PfE@SDVci4L4}MC-jPT0L-vg@P1yi|4t~q8g2*=`P zumdYM$>>;3)BJd%$2Vc{Af&Is0xr{M;DDc&Nam?187rp`&Z&#QaKs`e)X3icig(Ly z74vIvVPZL*{)#7UqELI zxf64UqA-K;cu(Elge%8G&tmFy=Q8q>ae;{853BtOuA~@diP|cBSviQkO zYE+Dw2#~&Nrab68-jD6qlBq`aTLK{m7bPy;*1pgk8)`R&rZfxSqNRAwIbQ~OZEW%P zyRo0nXEle*Xq%FM&{8@-JS~D6Jt7`|R4yiRUZpG>%)a@YFE3fODNjgS#0gr&JFet(2@kEelC- z_-LR8lzJ48`URt~XpMANTfnYx(0^A^{$}6y8E_#=9z3^pB1pgGIf`|gMUaxV@7Pov z@Aao4hU7p#WlD@k9R30N)=$M77J|)W`=c8sDlC?1K>32AYg7R1?u+^wMJh(d;^@eh zp~9!7Ng&Tih8YkWvS-8h?Gco;^if4@_`8}`S^Ir?Y-YM6-S25)Z!PmiQw8g$BJI{T zfo8rAk2XmwcG)ion!Hbw62HGE5wtO3Fxoa(V>JYcLRZwGKlr`-q`%!@<5_Gj=|A`7j_qrtouRj$Evv-5%xmo~4oA(Ycmhx>DWK!-=3u z4cL3mw(7|lkEZ&n7t)vT7)5hVso0GLi2l0bc3W*ugD0{{lr68TtOo9Ra+xU}28%l| zWaS*qz{qkx7X*S6xeW$c_w0z`F~Bo%=aSbRKXWHi?i$H;coUdPE7MuAHnvLD$vUFG zqg?XI$8sQis4C`_h=>Mlc-LAk)0?DPqQ*E4g4l&}g9BKlv%_9Hd;U|I$M()@sgPaa z+NvGhnTu>1g);(+T)QQ;qK~t`Oj809Mb@HPeP#D4uv)DKH8sl!7R>k=`BrhMCpuED zFW0hdUo7>?I0$@(NO$$-;{^@v4zLkSscrbWo(s38$+V-Sn7(-f((Dw9l%I7bsjmel zw7W;sdVH$ElTq6>kNTP%7G|$jKL-6tp&E5U%7g_*ka!R%-`u=s^lX&GcDT^W&9D+~ zVE5`Xp1VAG8eRXybnWiP=l0+o6B@$OUk$wtv~-rbmoaY}f~?c|@b9YlHy7^`D|^C^ z5ofb!c#BtUj(X>IHZIj^hG2TTBm2o@OB3Wg*Q<{Kb(Sz6$M|>k3Ri9v!p2=SR5clp zK>r#)`YgKod%*URCZUaDQ4NT3u9rL%-u|$FWeH{I#Fev%kf;7?>b^#^HL{N~Xj>HP z{d1Epxaf6?8Z_i#jjPilm+%>9SB9{ZjOjdOx=3*fal-9CE{&p|qgiYo8$oiGTG-Ld z6VvRer~QlF=v2x7T}2ZO#@b<$=9Ai(B}OGRdwmdJtwTF>W~Y2B=(O9_mR4GR8C~0g z#Cm|3$9lp-=0bzmA+@oaF^lWn&?UFHJqU+FGg^4xdAYW}DpAqO;s8G@C$4bPIuG~F zsT2>Gnudqu6GSTOVFSYvORz9$^$)26Klh%~4q2SsT4G|*_=uFK))xU6BOc7DieWrh zt>MU+|H}$Fkkq^2u+PE%G&}pn#45g=ne2l~ONA^{Tbea&t4%=0Msac1hiYB2Mhr zUgFVsAt(L)+s+U5S(B3O@~pAW*2AECS=;Y1Z-x>Gm)5NU(ti$Cauf-TWF{4gE^LJT zP<;EA$ttdpi=3s~Y~D;nR9?6izn)cC7zWC#EA{{JVg4c$q}g?+O`H6xuHx*KCO$}+ zIQwNRt}dN|4f-W1wZg*Mve1^DT9r(aF&qvs?Uxc|x99VC| zGcwygFcH(Q~ZN02IGw3)pvR}bjB**c{r3CVrYf?Gv(#^!!P89!iXt^kYqg+;thD; zGD4CI*QmM6`R^(TSH)FvKV`E`$Gs#1T8TzLPL$RRcj_AqitEyc?%|Dxv7^$976|wX!N+c zEU#cDkXt5=94suXI`r_@|C?ScOjDNO@{Hl#Vkoq*>Aks%kdiV4SBDw9T!BztEkv2M zCc4Qqx8%6wNHqf#Ok2-%F)>?}o?GXr3ku_ITCOVoY?vw}q0t-#$*1~6M| zx55jAu9Gfc-py>rJd(2zJj?sTzLt;>QM9=#Jt4!@ljOvke@pMIFtDILj>Fw>YBR(H z8Ul6oO5vm{3U7B{a8nPcNy++-D0p%Rl9N$T^X95Mt(O8z%R~38^^$iC>3KT9SWko> z)`S)m7b1WOvjb)!8c)m|8laX0F+o9+Qr=baa_x2-0IWt*-A{k*gn5*iE*NYHksf)m z{s|BsUiF%XhMJq@G~)GNx&Lu{G;Tl%mJdU`Xb*YwQ&!r^o0W;(!uXEXBu+qXT?|S1 zHatB~H0M0vC#e^x%PF|GGIpxBCVi}R-8MuZGTLB^(zbXa(UZ+9Wt>L{=RoEgfI=PO zH6`oUSA-QK)K;6IY=H2aMCmJ_GR@aqB2G2qyrcx1dnuv&;HkJ8Y=s75xC6MWisZ#WoBgkn!%vYx&yf9zATd>27J}zA# zI^>yTP;OXuaIV@8Pi+~!w}L;^hO6yuNT)GF&L%NfeQsvcz*BTHZ(>GiP!$h1Wt=ZG zF-|%$Ei}H5Dsz$jB1N1MbQk>{!gcAiW_XhadpxAUqRwPVM?#gQXH%Ee`6;Ium;)z{ zjy~k#)P8E6?3cim^u$NEKK(87gsai#)!lAf5@iXw;Nala)%Jf3{`4nAjKsMLL_11xUmcNmR%| zwCQE<%%^HCmlcI+;m@Utyuffh$i&(vu7I1lh94InvZy&tHEAuH8n3P6u=zAd7-jQ+4wq@78ThJ zl`hnysuZQhA!r9|U<9IV;9ih-KuyTCJ+r3-6?#)u@|1N6@5Z+^v}Za$KlsANczD=Z+SQD=josN)*Z z5Fa^?D3LQYD+LO1s1L|Hki{O)a;wG zyybYK^HKapz$hOLTK^skzy4#Twl=?wl*UI>Z1>vgOVy76>(W|8K3NW18WOOOR;eIv zqt2Vfk~M(Xk+^PGBQ?<$siY>^r;_lQ;b~ruZg1ZW|?2##oT+R~jg#!8Pe z@dy`l>_000F;%Sn-gE=yF5BJwrMECQLRXcE(^do2#k%5rvlBU&EbMCq1taV$?A_-K zb}?04w7_36jf0=v(_UK=j_-udDU|JRmr$7=yPFCn)V8dF`U0ZupmD^}4Qo-zaYT6B z1k?X?mt!Goj0;tA5n*Y|EMa}4^6P?lG)$e*S)6BnY}TJEtl0P92N|Fj+gPMId8xZg z_BmK$#8`ofr+oW`ilKLt#!3`sKaqn`v!vbXUjQ17)fJ#ZCYK4#6Em*rjxh9 zp7Mep?H7VOPNQ)Wk#H-#R;j4oQR(^m2Er0_#HsRh#c3Hpgcv~SFAs4`(3qSVa5>j( zwa^v2K)Oe0X@ztXw$xVl1@M&Y%in`Ak|g(X2T>I-P5&hR;GL zIzgd2Vj4G!=(VNDyT&1{z}WXA-rC!D$1mGxk7&mGI-Qwipgil442l|YCxkO}@~cv6 zs%gH{%+%D|<5AG_6UinA-yj>3l8MrT#38j*8S#2~34sLt9T20vg<5b_&RFbE>?@xM zhKVRg@8d%;%sV%Tb4BN9`Zlk$Cn_ImEz=k)8V z(@>u5#TBoX=e`fi6wj}uNmLJP+YHe6^24e3v{7H>5k%3tu*>aSlRYfVG3l^=x!6~ zT?x>YUaUQwr@8s8Riyle8LG-3yBxFt#bAp0d(DtrfZsU3R|EcX*di;cU5< zPngRnJ7TPI2IN0=xd*Ji+?BKazW)%$il5MF?t*LY0fDZQIU*aLuda+T{zQ&;OC7;* z!N0WH6W*C@S23hl!aj$e zod3pp8OwA=i?|1T75+ZK<{%n%%Yk2PtCaz)(co>H%nLra(a>*0X<%|lV^Sl;#i^kJ z1}4)OUBn@9rDCYT=3jzTbD3ESNCOI(VhyjleFG9_;#nFSorS^TCByhPwXd#d9na1E z5BuR}knDk>SXz}q#dJL=UCu^*m0BvQda7<5 zsiL)&x^n!BIOtSZfLx*UF0?qWVNx3MrZinsaVrn+jo!X;pYh9K$dD7hBG(UlI~05&BIi+Noq|XOFdX4QqZ;5AVULOt_=J6$ocjw)EkLE%o%fppZ{}z~+yKg8IEbU%M z@q{s?PUkUHhoAG!+ zcv(1^ZkYo^jXxwxTy|4mVpArDXKsXn@F3=04<=-pb9BcB3e~3YxtqZ#QpF zdSr@4PEB^$r#^kp&o>!Qya6=;9%Ji%0{{r3D(?YPH<|4ioJSX3NjMn~XC4YKCEw$k ztp5z*U}d@o7~bw(UZb7szTaE~SjI8R13y=p4@n7H%R!Z?~o*N^SwFP4(|c;%)ih^UQpOSPpYKeV;e}znVf$ zKf~oc`NrKgH@ItpP_{5Qs_#ly#^a`XQOD(xbRLT!YJnZm<2+0vpWg#U{>Nz~%yA^6 zf|=4>HXBRw&MqFU2dMKk-Rbt@n`4!XnCN~bR*`d#FexGTvAz+puj<^?i4V0Z>pq+h{g_-|KJ!t3EKtB-hSmpKW z|31_l>pO{20anhP2Y%*ud4T#y{+r>sha+Nt{ejkFa@Kke_)>iS;z;RLvf`ig>v~NAQ@(w+-BZlF<2E6q(Up7&iCR%yRdR4~ zqXLUPLNZTh%Nm@8mP^04ChLji*7O^Y6s5e+FZw~!M%-8EOsZUW#5pY=1Oo{K&FsYJ zSxY+APFbt!UJaQ{aLoV9sdR6mBwYAqmwg9-tUXnVVh-EWI55JrWVmc?Q&_z`1u_qs;lv8W zH_5+CSHqVI#AKizC37)c9@{U8>9PJ?`Vd8W!#)l$Ef^4U=Km<7);cOhQ|%N}=?^ga zy37UJCNu4qP3yG#RqRTKeEh<o>=%fWG> zGo(sQ%d@*lDwbx43#V)j0c+Ow@QYp94Km`ILJ2+84U4F zam2JX`5&2ub4>NU*v5qWVKpc9>`MFzSF>sem$dv6Gbn**nrw4Jmk?gR=`{r6g&RYo z7Ty>9uzU28*=MSr(Fo8FbHjR)S6YsZG+Hals@S{6^Qx1AOax*@DQnUKVa^b9)XvKV zGh}&H8+f`v8E?N!vZd!+ZHi4TAzK8k>FJs6cal7=^eo!i5@4Gc^i6l?x3usuhK9fq zLM(6xe?Pt3L@qHr`SsU1-8uB<5Wf5+EQvi(`Pn+n$Cv>&UM%pG$|TR=gsR%q$R^aD z?u1b_{Th=eb1G-(n&4ppV-#hmmcPDN1wod7_7k!dW66hN=b#PbtJAU7OHsC*F|ZHJ z%2Q?5jo^TlyU(T=1yszDc z;7mubV$V3GW#lq~gVb7X`-*p}Ql&Iv`617mR5-UbmscdM)T52)jg{ z6|zsUCDvSPzWp`mtfpD2Hc=gJAS^c+$!0<(m6LCu5PVI;y1%|p%Ov(O;Jnwe?$F|^ z6gTFM37v{cJhG_4%fy;fuP4TObktkck}Z0ntFf?d97^#c3L=<67lJeoCOVB6n9wSO z>gp!fPrcPrw16))+F0BmSUKrr)@TT?+>ujk_|irc-S~!1=ItIEE$nU*J)ZA7(9;;2 z(Sk3Al0e`*%Xra|{`7EgtJ1ZM57?b_AymeVA-oCMpjywEwR>{9l{Z_ySYA7MMU&Ty zr-wQ{qej!Ic?_tvlb< zr2uJ_Tc0dM5(686^>J=&AD`5w?A`+`u8*J9A4z>+d1`E6XGJpiolVXpX8iqz~nsYM_H1p=$jZAY#1V|QU(Vm#4<^zg6ucaDodw?YIv(WEXx*CRK-8b^RZk8ZooPyxdr0~mL zX{SXA)-=hsDwe*rzACTnzLGa8h)_eT@6}`0re~b{^fl~m3u{V=8JzeoQd6hX&`fKCrSBf>ypTh1sPGb=8T=}=fm2(QKrelCuJj5a~MA`(+9I8zgkk~c{@ zGs(?GuF8hBo0yi7dOcR;$qD)SZY%xrU?Tmg5@jaEhRbK6V3OreaMeV)(hM<55{K1tg+`iV7#iM(O*Xoe_Mec87b>?oz}GrM}O*0tWuMT{W>WEw@@v|-@G zN+@i)rdl%OTZsT-!fgkX`1&}7d%R$jylk!{EsY|a_xWX~2IY%r(VC+oQp{o|87l+m z?i#1sKu#^bexNzgbM$N4=bQmNv4>lUp8|+KPo=_fa!$SsX+wsa*^PuygDN-gZnI&Gz@|cZP(?V7?*@;#CY{A%J!imX%zQrq0}g+!V=r-i(odQ zIJLA92?@caSrF)iOclc2v1u2;kf*>_(`glO_qFRt%&M$T$^PoIl=@xF__f9DvIGa6 z!8~N1v>Iyy){9=DpZvj|7P1qa{$($IwVVU!j^ClYO*B2XGd;M-?H&=l71WO8IQ=Fj zB&8LUriAJ5U1YM56;T?X2$mNfyY&bO#f(Hjc<6cP#fK^)vImaXO~|qYhms>hP7oH? zZHdyhqBUG;y3X}bxJq?HcFd}Xg?1*B!MMj9cK#IHdyG)!r6D4nMoIR_b55TQ& zt3GSsKRTCB1q%N~Dh@qNIns6bNrUHjMILdM$JA^Gd;ysaYg$rZo?H1dC9&Ta&1TMPdFd&s46^Nod?e>|9lFN)LUm zme463CE`%7^XVEfIc=a8rH?m=F6&grMD|e>i1k0Rl=xfk{YJWdBPdc&mq6`_DY%25 zXh@BZmz%RkW5#>H>@xDHA@R8ptd@7XoJjiMhGcFK^i)(4w0ouebefqRpX42n*8BeLT^bMxq;mr!p-DIz_-t7O@w_mqCnWFxZ zyl}Ah_?f6fqRS6PCA8Q;5Z@waEha0c^!P`!gYFol>d>WXIDabm<)_U^$6Gl>dET)6 zouzpmIQpwVGI!57M9Ij*jY@mf3aVcccwC@aWni#{+Y{fo*Z1ij)xE$iDcPi!=&j1n zc}Kv=wcx#YK{KGE#L=GlKuhaqD<#=F|C1KtUWb6)v**LfE=^&)d51WKN>+BM8T?0X zG|0#m{5+InX!8D;g<4jxa<*0na_wfdf4D{!dP)CrG$cHZKb<0A&gQGOL}Ly?W%-Ee zk`sYBFmnWTl2AGBPLs&0B|JLph<38x1APt%lxC9ZGDusDIeOL~8KG>|CY1-4Y^{XK z9AZpNEU}m@6n=v)CBnY|4{tPy(X26y|B(9y7zfofP1dA-HM*eti)1J%7m=_uum6fE z(sbG7>kj{dpi+_(Kgm|#89p^pY*SQd?;XBZRq@CM9K}fUw$~Yr*4?a5S431^$>i5X zpTxY@QATp7RT7?%GCa%Oti2dh0>`zsy?hag3X)vM!v;r<4{fO$6=rsY-REJy{X19W zhy$*i*D-TvCUfuZMy~k%MTY6gT3{Ed`Qoc%Q_!N#0x@gTaNB(G?S6&@lHR=zVFd{> zV!(7K>1~2X70_4P0gKIEHej@Wr>U=%jcHso zAQ~-^EL~nXMuJ#j`7k6HlN-cXn3*cJ*0}vc6z}-hEiMdkAgo&kZrbZ_{7KBz{opT> zf`5D$7>CgqNvb$2fu0yweJI|n3qF0Hmrv2ybjoNQu26aOqrrNw$Xbz@lWw+?$2$do zB%L?x3CA=k{xvx>CU{*|?YR2upvnHe?RG0U)s1fAht02c`ch(vo7DU6%_!@SDxPkk zGbD)oTh|*WlHd8gpGyg|Bg6{1>|g!$d)G~?Bb4)fv>S5FcW45(3qnXuvk59RJA0Xk zzA>wouMjKys|qirK+~V7nCnu!l>Zq$NhvTr7r}q;L|H4M>^St3MQcg1q}FJ-U7k=o zU+t!3TY2m&n4*${5tN>L5QpJEj7JeT|LJ)2e_(k0fByjfzsq4XL&=j{6=`ybnuwwL zxH^>yrZavWwh*sW3@d`MyTn5$P{1yEhJpr$=YH$MovRv+q3G~4WX#X@ySSi9Px@ju z4j(AGG12w9-DLA`h{IB2dVWUfqqje)Wp3ofA(0*#bdM!9BbXU25 ztvF6RwL`Vc(%)awBYV@VuX(9(B~+!i7jf%=Gk`JF!$CJ}%bz3ZT9G#M7k~{I4!A4v zckIJk*1|o-m6^<%S~+UT*rlVltf-VbTuZ4`CWAfIxi@><4%bE#tU=#WiDSQz zJ=E9*j$A*xOnZa68@$>^gTD$NqvSaopuBU9?m8N}Qe(d#wkHK2V>25}WmZ@Fsr{*> zl$5{<>}m)v-lDN&i+K495M(;?T5qFbWgvv0T~9>Fbs#Gh9w=7{dspnit^L~jMX#mg zBSH=eBK>tRE6Je;Rqqb|wGV#9L&Aq-Uk&tiC5wuLBtvqeqRHO|*R^xur@g6iaJIkZ zLXzxUbZrVT*SU~<8RK{Y*_>f`p2gOjCFNBdZs@0!`BZVgW}q2Zs0t~(RGlDnU*lZ7?$SeZqCw@_#@l6 zm^^T^XJtv){D>HKW4S^tIucd+X`;8FjNze4YIcnHfvl7_I^$zMotpw>WQvFFQ;8Qp z{}@luh&2f9~)|rt|(&wJPa!vrwiQEGL z$LpADNKOzsP1sN)3X?aYachtJsZ#V=at8y!1y#EmzW}4o4<%F(TInhA#dqrr59E(3 z9J(o+0q_PpKf|G^o8*>7hE z2y7Prb7u%=e?LQTz2eA>*8M_pgg*EMxDnjLaKa>ND2@l9oMPnOzTGhJn%N%oLD_tZGz8y}~Wn|+A7=AZ5G zSBps089ET%{B~WSHSuXf2o!?h?I3C>waM{0WYqY;9Y3gjeFl~Y}H z3bXB&E4@s?A=47}gv3QU`HqV8d*ANlrwk`2=VzX@nfF<}e9sv z$H&2rHac=3BdGQD4-Q`=V1*DGm7|$!jO~-9-?kK4;-xxpmUU!cZh^RqGS;iB*QQ}Q zH{k7coI%#J7t>s@UJL7iXBo3lj9VZB*4+B2rsbbS|HcD(0RDD^x$>+|Xl%^KimBT{ z6_L>L&|J+Nu&O9EvCZ&($H&w96PjK;$XY-D$e6Pz_yXP*zzrITJqZ`W48u zUoIadjj3#oh5Rj3P@ps1PC-qI3QL@mawYl5i^lLG%xlnLrkqw~+rB z;lysj2=X(el$4K%+^hW99iK`{j+?^M$Bxq<&3669=jXZCpM-747LZ}8-I#N3q$u)Q z&$zJhXHrR;$w+>)lBKy+6~Qya;d!&_0xirET<%~74Plw*jZY8^4{A`_OTmN`xIPT2 zsz#Wcv{oOoXuAh;)Wl32j!!0GY>MR5lybAI{ozs8g+;7^+A4{OU4Bq_O1BjF>d(Ue zB(PjC&AsR?9bsm6n&t)9%8XQ|3Q++4yWW76Hxs^%O$DVp$O^EeCe({daz*#3Vustk zp71K?M1fk@ZJ@iHxW&QogoLKD<|u_Is-RrDQa#%>rQ=8KuP z89Z63uCk=C$_!|Cy#4vys20Com@Q)ysq7|6e!xaNrbw`jaQt~ogmnzA0J$dF-D&!v zIlOZ;Y8)|^-AQF^SVbtor2>x>;?@p}Y-zF69 zX^zlaqqY3o86FgX0egNHpzfHhVwO&{+6+L>&MF#_MW zs|G%WpqBs!;i5lZOta}*7WNa|umFP}vS#N^!pY+8(GY;Y*=yAzl#SH1MFdDl3zPB1 zhL7Sn>;+Db#e?+N46{r68=D>!kY3|Q!-TK^PZ|xtj4-u_X>@&NwUkU1t#DYtaa^89 z`03U;e8Lp&0RGn0Y!(;TcqAv2xqlcX+1e`2dll#ky2sJgKVnn47jMl7t2US?bJ^G= z&H7|!=1diz$1JCQMrE#CMfoZzei3*m7sS*iSLsOTz$)MYvAMD+iSpVk(j3i_VI7Y| zJ3*RaF>`|-fVYEEkqwGt@=Nq-`RpKat~lvhOX*J8k)bfr!@*>j)-)gU)tccHAgZ&0holZCb#zx_9%`6b1GUO?33QEnsVN6pD2!HHg9BN?PPW-UbLkoyl*Q z-K^$opu_mk79k|^?>~IQz=nBs*c~C=`z=IXm}GgkC@M>lf+EMuxA?B;-m0-I(3*=E!32AViqN+h*hDDxv(qS&c2 zI0#c1us`|yDNobRAHVJRQBJF?6W~m|gNw7BybCbm_~35ISLsrmIo^D&a! zy=9y?Jpu1M?3yxDsA#&8^;o=BdQ2PAnA-2TG@q)lV3ViZg zqPd@@Tg8*1G&JFw6Hb&YQPy+T(1d3_uPPSLJoHo8(n)G36gTKHy!W_|`3@ zN`)&^qaWiHrN}E5D6=@?p-dMmB@f{kPRst zkMpUCjq-k&U^MUaW~fn=LM;-+TcLOg*Bn7s37BD0ZcHXw_SEh{qP}xR6!ecRH+oAZ zMDGwjzB>7jl^hPaFcPo8HroaV|A2+zmLvTJYOgAC1fw>RIu<3mHS@}9VC>25o9&!L z$C8hZ9#<#Ms+6Gu{6SO@xE6ysUIqxiRm2oYmIoxQ3|-V@AuY+GFOuI=Ab^Ugwkl+7 z-96UkPB5O+i6XWx4KbFILCtH{%4BAuxxW7<6TeB_4XhwV{MG9=$8{A%D;v6|C{r!# zv`=(K(F(V2%WcU77+8CQCVHs*^6xlNt3L@eUTvKAhVnS%!0dyEBp*(PgsENQNcGy6 zaZRqjT|Xe2?4kPwh`l@JM6}Y(DzEIG!*QI&CfP}ax%LCTHjn;VbB2e+${zhmetM&T zQWwF$aP&7d_@~sQ+Oy?Ax0Oz?kzwlPuV2fs^{zjGtFZb7!tz~J>r{&=vN-MghKk{& zhcg;P^bA+}>s48Xe1!M&f)H4wlwqR$4u=;#IlR}>l6~teu|m9&ef9C3)ZYGDBvbTS zu7uG<+Otq}R?Gp-orC{EG5_8~X)U6D6R`%mx08zP>#Bs0R9$16t$CwDr&Vh>-e;_w z9wJzaiB?n|9d@0c8NNvkF}~F$)!6p3D@B6xkqryI@*(Qg2FsIVr}DHh4?_E=yoA7N zUU>%s73Hzkt~&4ltJq``CFRz6oS#6QV>lB2>Z3y^0Zc0jGPfLF|JNXKV?tyKvaQzc z{5Cb5;QN|q{*OqD4@45|8?!zkispBCk-cTz_hP(&#qHkGq%&@r5xvl+5F`5MryZ zoy}8=m>Qn?;dtO7bSWib_;-Q+O&_V|`>xf-eSaMOZ8)MZRK64`vGO@9Q_)y>q}s$L zIZnhn$C7(YcW#gXO{1e+LA$G)WX~=o?JWdfbleIXX&ymsOO}U3Rz*i;EV7)NJ-%n@ z=0<0Z%SyzU?Bi0g8W(eD{3veyF_L*@!WUfuuQ{_8Bmb`?`d{QH*1jyuJkN~7H-~AA zx|pKQqNiZd(5#b?+K-eFe~pF0-^T8+#3BviKW3-jv;7+s`M>dQJO9s7`M;bw@U7nQ zoM>oK{W)`xUQ8%XJ+r$7jVNyhE2UM|E)i=H?tx^|A@PUQ+(?ZLuCsric>YLk`tQ@; zzfBXv$rmf)jSWQmObd5z|E3NPew!=*BSZg_Q`x%3*fGdRY|6N$?4`t=Cj}w}CH;1N z7X2)*&4~16U%=09-n1j;L8VFQB3^d0F+kED(?dfv8N@C1MWqUGeDl0|7ok~Ek#3Z3 zTGd~h`VTNX)JsLK;MyvZM1{8sVv2na2;@xck3R>c-~Ge>Xk-Q!p=zR{DJ-pBSF(qhVAa6R&eBRp_;u()9OTKU#!YF_Jc>Z%bMaD(~j zQ>^pxN4~|pGj@V{slb>ZAg1CNoagG_H9(mD1$@LYX%z5$O7t2VtH;{#+R21|e+%!O zG9z%})?E^7?zZp7Ec%hWgt7C?Q7vaahN~)2)W%$>;NmK(DrJo`gw2DosTb}!a{eWEf}%2m2#RgewrmwHff34AJ=bRH69e zkoSzIJ-bOnMK59xuiUbF9HYDgRBT-&;~@%9Bu*9CySgrb%r#D)vr_7J)! z%z?v-=1%ZA;n7`L&ao5X^6_JBg6ER0LhA6ab^*RDEQ-AdYw<{W zY@l1=!Q@Dy+Xf_aBDdgLwC@dQk7jE=b|8YR9CDm!ZjmmYLiN?ucli22no{5LfhFIl z4H99S;5ZeDIh}3tL4=GxXF2cr1z_zy{D%3;n?)f`l0M=_9a-O?0ID%QZE;ASO`MX- z+M%3X`*jjrtuUIU#GAQ5?Uvt}ddD*+U<;2B!Owmx;4j3P|v@O(n`qzaEp zNNhJ#$=5G!31?B+LlyKO3cEbexA@Z$gOOd1)QzA)iFQl^>$rk~{IH52jS6NZE1L$T zdwG~uJuDuo_2?|R(IO&N9ENLTP+SEvESMG1MUEBLcI22mQ)aB}$n6`Y?zsX=0S5!n zU5D;#vS@LjVT(ek{j&=W^1j6=gDRJ<%27;Fk-5|KaTpUiX^=d4B-pjxa8;;RD}#@Z z*#qpFl_$8b619*`)-&M1eezCLhEhi#QT8fd`Oro_{#1dzUhc{RPs+FttTj0! z?6^II?)8C6QHAr!88{T}SUtUn@-d8uC{xNe7_satfTJ`}bW5p|no-Jm1W&WkZOlJ5 zjlqrR??%(2PJ`6~DKeGC%{YP=>6InWsxy`Y1-7k~S;BXlA}dGtlQss<_lIDFzSX-~ z#j3NBEo?!^?DJyz1puu&ZOR+0Rvr6d9Y`b2UtVXd2@%!GM9l);a@}Fc!_9Wk;qIdLL(0 zO=D|E(}M5C1mPHJ>takcRK~WCM@O2i+nO^gO{8-`x=~wIHi_`fRkEb^w7H=r*BJa# zCvVJ<=YxKncYB?;#1~*+aD~^`7@2e|%D2%u*~6U3?5GHpvgp-DFQM6*T>Kwn@Ov_s ztDH0fvlc=|WC2C^hG@qX}E#c!{&N;EO!VVn^^BVt%gvZs*&Of<*sbrjoMynWlAicV7P z;9qIuV5IAdeDrKnUXSI`;m@(V45#vaXekpTS-L|dpZ;g@)nqXa0&w%eIk+XH^D;ZZ z>aEr{O>y~!%~#b%nDqRPJ;iOiy2Ryr^YBh85Pv3WLM4{lIO}R!I7O8;<#XdseO&}J z4H1})iSkezVGKx-1-^z4Wq@*n?t$KvR-H_-Rra)_)D4XnstWU~HCXe8!ImCO;jm}| zB9qMcN))p;aUQfr{Ugt;G6i_PeL$z~zw^qZN&vq5E7(2G)lYM+` zpkKAWFbA-xQ$pg`-8>Alvm6vEsxI2d-Y*o9h>)cdoK8hfK$Vm929tk~e1YqfGJ@Fg`0K~F00RWt3uFJV!fCaTHeCOm3v~S?Q0G#V7++vlT+it%A zA2fEjmKnVZ{ zlHQ2J{7%T>`#gs~tVB3!mOO-unJ!K|!?$Wv*T*hp`*2oj-zhtA-uVC9>s}Y_tBhCw zXdw3%s)633^HjxxfS(?EnSXDBh$FxS_#w9LIJBG{N9EWf`JttB`Lf=E<1p-GPAnP+ zSifh#xo;3#$BUjHwrO%H^}b&IsWs= zkmJDb&#pXlqZ%gdR(=Mg4TafaBsPfWWV)8i$dRirZZtejEH zXk?Qvw~EeOtEMzvo%rJy3JNwxBjX@dyTmy4Y%j!1j_j-p-UuQr9Bb;$O#%PDUjVsq zvmImBqv##;sQOBvU`U z=RX+OOf5B3>E6c%Q^ir*v@<9tmI44+8UF7d>wIBUQlU`zDr@ezy(c)1^0!el$;LR;8n5&H@+0^xKCSDLT{d0jMXP}sM?`W(Nef*{=)d8 z&NXFx$vxiMTCbj{tRfb^k|&HtIyep~c^v75QQ3Kz!UP4n{0LUT!2Aa=lAKR(k`)hQ z6l#lEAwd7W>xi8o+(M@LTfakBJf5i>OC{{b%rZF?HOvPeoId!e1yFnB&n9AQorn*vubPk6|6Fu-dzIlscp7#dV;R41=fLBCAevfLTN`_TnjI zcH?>o4n8ngN*aqiZ&}y$qlC{wIi^mSil*l)l*0kePx$qm94IXAEjO4I+ym)}(Jw?Z z6s~x*;{w9+Z&_afCUtQ z+vc}U#_>^(VVU&%zcD=aU)>9Wp6NaNJ<_5rQdYdaMD|3AT+uV<;mEsav>X8U)BE=T zfPE~h{i=Xv&e(kvw<>-DD;=W_o^Mq8^~cmFHdggHN$RRq6uDO>2J?H3S(7KlxhuhB z8Wi+F#<)6++3M0)($C`sN8?1ZAkW={-6vL82Up{O=lrocW4{16dsZ7hl+XE1%EKNy zDHYhUc>?=u5=p-IyO_{f8jh``BlzQ9Fmm7}2KZ_g*g)o>+RkAFggPs+7QCxduG$g&~jZt=I))s!QG~V4@D_6aVTi#7kISv zr=U1B^d^c(aY%-Y1VsyMD}-IP<-&@O9d3U-~Z%oC~{M~Wp#4df{AwM%!1*QBSXT8}Re zF!w{XqTJ>Cuumtor9AuLip6pMI%cd&4%W(>{!$pRI57H|l%?pj#oo}+qn zA1hEeas|_K|E`7Ubq&GY4qM}t;o#+J#;-^>#d7G&gbMY6n=sL&4yksTx;xu}+&)Ma zMFLh$Gz4Z{_VG&E(I+gnmpe7`hZL%VBQSQ@*2=!B_+EvQUX@Lhqn#2kYc&yf0}3N% z_TalkPFBOc*ffIN^9VDN1M;X3x*Q#X)m3thO(3E2@@(F+>*#EC=W7;*Ghb4Q*caSR zYnR1Ym>&5{>}>}3J72=TVnG(;Ld@LqD+_QpcaKWHYy99)YRu{gZcH@^EVspo)BzUWUy@;I!xUZWFh_hE`Qx< zsKSHq`tn`hta~?uHu&Oc;GwCa9-((NSz$tPDo6Zl+s zU0Kl>r(bDKm<&pQj$9{BO)NG1bPm3Hw|m0kQjn>Bi1;qqTD?-`8#7~cQEuk}bm5`z zwhsk=N@rC6n8nf;t4wzAO{3wicimJ7bre)su9y19xp>%{zEENd>M_qjaPm|TSh)Yx zaP&lSceGRm)K4fVsGYc}oIrr*^QLRW-EKrQJKUixbJl9E+aj>^iaax7RB+6yLq<$B z?^*db1Mc|%f9tftNDHC$FY)ncxJ(AU@QA03E$VzCr6XCIML@+q8$D5@c8dCTibmCm z2fEj*)i|hr_kfDHN!Mrv!WHNXmUA3a7N7>3cPg6EC8fxn2O~2J zCbHrP)YK@Yhw+lqW^yvEVU8O!tnS@)swCYkvnIN+51EM0ND0xZQlY)6_c{!Unbbe( z>n{u4cTcGIPY^#Qh22~h%~yK>RZ#+4us6q{;m)xSs9pRGvL7-GBU!6BZ<=8HT;1wZ(-6-J5do_M(a$$NM#^3!25b*-)0#6%Bj>o6KLRr|++&S1wW}@ea=U58K;--aEZXV#;*Gjl z8AKh$7TG!Gf*q}MDFREWA#ijvQ}x zez?K)yIaHjoMmH!Nztw7DL&Fn#4NmfjlbSQ2^z~#1R`X1ArcClhHI}`k zY0>yqMz?ZQR(5L69CCb#kQ9e(SnLMP*8l}6-t->TXmXrx3fh(_!kZg!#VcY3bd?=Y z7D@U3<@P&)+Q-@?#g7w&+VrzvHondj%OaUeM`#d{O50)l2azNwF-xqn{o9BDX(0x0 z%LgzP@3-MIA_SS?-e}kdeV~-|kQ7*$_zOhYnQiim<@fSa%r)8_iDK3P`#$WiQyWvi zEUMa`cxTEWTneBfYQ|2j=Y5_vE$5`3tu#z;WWSNL^j@q7hgtlm8w@_p^$c2wXQr35 zm0s^i z^3gMn#S{ws{jQ;kB-%~Nh&QFeO0TdNj8Re;29Oix0(d*D4PX6zvgi3?1h|n#8GIfq zi23_}{`K?rZ#YIxPe_N4D|4IDg3hCZJ5hpz?+32_aq{bgJ^6J3d2tiM3`AA81dQ9W z{BuD_FMk$o+ebY*pw+0pbac<54x3qc1&5cqFm4fK-M@qjdm}?WHaPm~kCkxXA1h%# zz>QUYld-_DA;0YGtX}}3dy&g>n(&Ku)Q04!3U>FE2dz@WrLMneWbYoO&1Q-h=^YUkt@oG+Utuk2HD3x8A}zdAmVV2hQXajE{4@4^#K z7?PKxI?}Bm)E4A&+iQ)RX5aqo=Dn)0G}A|9<2E=Pxim4&0YLWwQl-|`c1rvNn~o7A z-=|nF-iR1EKQ%*;lVfs){YuU&wYS9%nyt`y%dEs6x(AeGtelUvrr!>hF^H1OCtXej-^fuv-773}@!viomV-hZ+B zYFy-G<{!sfZ=8MFzrHnt0^oeLR47;@P0jpXk*H3yF{DRyUUBQ_-rxw*RQs~@O!nh> zj`zPU{bZR^_6gtgJ$wBbb12&f!o~e#lLBIu$dZzgdCe^zp)!?Hb)f$7QdL!@bW4(; zv*;X$dm-0J$)kc}?k=LaM;`IuOi|FW&3uY2Td<%?iqCGN&WTMdCtgqW*$B*&`=Lk= z$7MvjlnxNZ;eM~6XFOPagy6~1H|M?lSC$ZP5#KTTbZT(He@HLS$!KM(!TNYO&Kp=RbEb6PSx{uSM4`}29debi( zD#lQ1d(@#wG;8BxM0Adudm+2JAKF&ea2>@K$$rI3xUFy{!N->sPX~|bDD+W{OHs*U zivLWv20@ADNw2FXr4oPjH@a-FFezirccoA9^U7S+QNgd)366!%!@A}e7~lj}x#7;@ zx4pQz2c%ja#%<7Wr1sbx=d35%qBS7Z-;GU;Vg~5T+gDOvb5Hf+L}}z4zRr5wqac)< z89j}*{Ek?zAuAwS>eiVh-9RPAPa{|$V`D!wpeNE(M0jT~h^-pC{cx(OJ7l$kk3G4iF@O0ryJ`q&kQ$oW zCcLs`3nFYR0)LiOsHE9k5wQJZob(`t12T@14%d=>IcVp`>+_@ z#H8G_F^R4#`gtD2zcsHWpjiI?)5fH2x(V^^fa+Je4xj;Z|4tX3priFkTC-E13*wKx8%h8T2eBg0B zbctj%*Sa>AJ4jTnH#68;c7*B|Kv;J1{%I(wAqCt9wXvHfq*8QOdNR8zg8XfD4-|pK zOH=$bsxTh)Rae+Vlijz71%g3VPaiss7rzvuSW1zv)830fcZ)QVKtT5Du}bnT0HaDAqT*AWLd-dNs>vo$OFESX;s?ld zpAv;{^+Y$dus1Zm4-`8Msd=?cUBI%&n|r9a&Mj_BhvpCqX`&36gt1p$id2n}R)=Jh z!D{(Oj9FdD__H+W7;7R)mR{K)dLVW6p6{q~yk5dRT^-n3!L2IEMw<tR5)2?NH2 zle=%Lj+hEKKoR*X@HUlE{+T$1Os+>eS*SPNEPO?{QYP;0DfFJ%@kwfw$`M~7MmAgn z73%WT{EP7_zUVFgk8|Ag;@>hGEAwlq?P+uvw^&Ij%{K+WV9C02rU z_?n!fFw(}r+}~ly0&TFE!sMB-`Q7@>^-l^8rvBg+$9kO_C+_%U>2YFz=SibzUy`_U zL4UP8N9y@K8#%2Xd4S1TUdMaskMk5q0Iw%{$sHJ|MuGHu(} zzAs4PgA#OCRPpIpdwg4HujGzq0ff(mjV&MUIz!WK?ZB_ao24Eq+)R5nKsls{MMos3 z%zUf?roL&R4K^`uR*73jF|Hu}xxEc2?jzF|5Ir1ryK(!=<8vRm3j-LFC?t3q_4dMm z;^SD?x|osjnqk?lixUW@f7>#7m$4aZmc3ENht+}qr@gbW_KcKIe_L5#KM3v|eeOcx zIkUg#)!=uN;p*ZUR$A4MtZ$?Of-2V*E^!J9%`UX z>W$=|9ZD)RBW^FxLYjd~!cvCcy8nh1qKm}}NwUh+aPgboI?kHwO=UV(cz|`vs|DPS znoQIfVAFU>laLVmV}(^Igw7bYPFj%mP(cCq)0UK}BRtYt{U%1zmGkCNu<6!|Rc^DXGEwFRC3k!=Ozv$ba<*K4!w&UmB`DWu& z^kJ!L&t?(il;5WXGpzf;D?i6@qhif7f5i1Ul5+;@nAd;<5GK7f-^DIWRKf;O3i>-4 z_nDa7bP6UxMHLSnIxD$mMPR=G!Owxh%Ttf{lCjIl4q7y@2H_>4(^dJ%bn>-uB#yeI#QrCa^2aNqy$md*3;^>%eL zE=cB@)2ve&Z@yGfiT~KRf(sm`uK#&bMZuzb@VI~WAMHm_wi2wLw;N2!+RV!?4{E47 z-1bmwt+Z4*QDYoQqxSOWV1`dyKw!CpLKH?pf%0MgtN2$ONf>Qo(%!sp+XZQpW2}}? z>qu>wec~zOUa{*N!U>c1tJ(?AL4^&(_+lLbksomBnBfoiA0w((Dz)F2k}=VQq)t*ve5PgB!$y$D5*N0{I{y5`6dJ%9hZ1 zMi~_S_XQWl+C5*aE4JQ2&PwoyEO3Y`v_h4HS7Ecp_9{%L?~yW}n3_7TO`v~}CSk1t zT`O-|xpIo26|HdaU?Mx&!0tU-@raF^zW|pe*!!nZ@jvzM)^>2CwO!GkOG>g*Jo(sz zN|Mxnpcz8u_?avkvkU&o`y+z!a<-m$PqyYKek(S3 zbayD#R;*j$hlg!Zql&Flzg%6R_8ub;M)q}XU>$@%D^RNS`XhEg5P{5j9V z6+cAHOOLKoER1~IJD@=OAIY%-ZTW{XJ^w3-WU)wE%I1{D599^CyhDRM(@dDv4+_6S z$)f2r@fEjs3w_VgR7;;P(c6+PE;S+#@(5G^Ncc}B88@cb(N90;dXH{e z#Bz0fsqVc*n+mB8kLY)!3<+Rsyd}jAlspc1H|- zKZHMvYH}J?F`iI=PI2t~1h&~RhpHZt)kLKKn9UP)m*@FjEX(J3?`ceHx5Hzb42F)w z`=CD00sN-@2WOAFc~5z|?+zqk(s#yN2gR(xRV?b=7Pw#QVp>&+Uz2M`bS*O?1;35c zjijix(Vu&VCaPf!8b~Tbhd{xoV^dKKd8!XN}CxVp=yUr`T0dtb!u5JlO>Xw^e zZLRYz#RTP}S}pEbP+g>>W&f7B1{=bn>orBneFjNUGP#FB-F5_0*z>fZzP_VSoLAfo z?2mDf5ixfL-(yNmj0bcMN`!2l-k*KlV1ln$PQMtHHg%Tue-zbjhcA*6P|CjEC|{ z=cT+!J(o{TtSM&IKaC{HB;hCm23Pz6tiLYI-6tL|o|Hf_hUIMuFDV)WGj_BB^lLMj zzAgE9M$))a8L6^7ZzA{9Rxxsi)LRG0eovBE{?RUp=q5{o7u1H_0`=rjc?u6^mbQ$* zy2a`Jl43Ysc^2jk`~rM5KcIVkQXSZ--MjcIJ-NnybU1L1-am*p;k7Trl_~Wa#HnuZ zQ?R1>y9#n8)x?e9e4PYU%TI?2ol=ML@n=KhoAFK|GCGaHSMqTCc2Z`Pgxu&p`WqvR z;Om!XF+;ist<_HJFirn;3VlQC7g&c_YiSDbmAZN-&?m+C8z<#}^A)@amFO;9^T z9H-^Fc9xYzuwfRMVMN$0M|DZt(ok8ZTAC*@f$QUfdn7iZb&|F@W61+o(;47F6>aQH z9gBm{_~727z;f7u#X(JvyKE+fxyW@F9e@<()&r~Bd zmlpJvOG=D#KN({t^6Tyw$YhgNOhe|0&RchrJ)tq-vQYZMtaZBl?#jefN7rg|ZBry% zH!xouRRbj4^74l4l@Ier!h`mrOk~?S^?nr2C~b?h%+#!e3Ev#@)%oB}qQ+P7EksOy zo~J;$e=K^Q0qIUUfCWw9&1FzD6burW<3%f&pc%f{*%3Zq2As-p<&dNohT*OYM^k6+ z&5dILfsIoL<+;K&r z^p3*w#Cg3FWqy{I)H$W!&Y{MC4%Lf_cn<)!;Rn@dj3tgftU8(}3LtyS#<=BLkzjDz z?6#y#-?#MGgvF;->S@%pKW`D!2-XBg7y`Py)S(@V!TWd}+VTrJmRqA57?~ZIEls2b;Tc*OBu zKQ|oDecRDj3;k~Vpqhiact-V@?{kv;hETE|N!%UE;?&SUTNeM^*M1@3+H$_an2+i( zpmg$>p~%P;lqsQNN(HjnAaP=ZF0HC`57g&wu4*fP!WGWm25wf=WA_P$*75kSS}zC4 zoav*xDcBr&6(1<{PU{;ZucFn5$T$^Z0}sAVe_MZAu$A&{xCz0IZWr)!rJl3txNt&n zu)=_ihSV1{fom4g!vwX%W5mTvMGR}FbF~Ev$ZwF!azKB#yXwo?mjf)(3F^b#+1gAh zURqAhAWio6CO_e>k#Qe;1+kF_6(v4=mX^tRh3mfnJ?!-r@ijL{pCQVM+tQ7Og^hBv zXN@iPil{o=GIdz`-bg>))%$d*wbvpg)eF8}nsNZebTlA@rbCt@FLpJ~VQrGDebjkzVGYy*f98;?M*X;}APW_iI9o{C!_c`%A@-N6bO=Ew=Vz_{X(3#i7q?X=QO}EPH0J5XfdT#4BE%{#v*T z{#Zdwvz+eO6O{HrKi@RY!Hfo_3onOqyATygRFh`}qRBN;Gq2{Eh zBjdq66_Ehz;BQ9BupmK)dUOxbp>h+N1J6kOEW^Svp8fQbIhaLaI?+c%+g1EiY|n(8 za^-MmduNm?4p$D@FrBj$54d?m+o4s0XdFWSe=+yoVNG=X+GuR3ARFCzL*a3`5)3;O}qieKS4%_weQFq1h%ZZrq3 z6--K_700qlq3_De33aqMs!Nf;6=-fS*9FzZ$=6fnY;mb>XIKc^9n=@QoE1=FK7=1G zAF8e(EP@p&4%uEsxT9AeZ5KwwIWTds zhemv`#DiJPtSV457J{L247=v_*6=U!w>-C5Mm&ZajP)*1*piE^mhW7VhR7WS`C1Y= zHQYM~)->l8nsgv$^&rCYwz)-+5SeU=n!Pf{XB8_J^7F?*(AUxwizAu>JhK$&58LOH zjGv=r9&%Q9w;ogFgIBshPx3p>*#7A9H-$RR4i*|eWNKNtRib2nS?^A?&>{9KYvX*4 z>-dMoSw__M28jp*?x*0J2UZg-HFyDu;Gc`M*Xq`#?`vi`Mf~X+g6H*)obgt99E?&c zuN$|21J->+^6ncCD%E^>kaCmXt{}RIq0&7bm0yBB9PceN#~BbYN=9perF5A|K-l6-rAHMI^T(1_D#O(vtW`-JCD)(Ym6$+>X2oJ`hu0L_imR~GKm)kx+>Wa&< zPSLTw!=%;Oo%GgT@Ld2)QIh_-D7L9xXqI)4JFPP$QGl=%eWeM@Z(b5){0-5M-XS z(4hp$Abd!)`U2a*%5DGjXuWTcI4iU^zKUb`0~l|oeKO!XSfTFpQIfWl?g6edQlm5@V=u?8>BZ!9oX4&Z+!B501D_lVezKf%qmxEI zfb+YdJ-T*~y&+Dcu%|MJh3DYtxLOwKxu)tqk+&LK`RSp7t=VFhgL%f61TI1oSVwz} zsyJ32WYe2M9;doc?CTX;_mfm~fAhpqcSpWi!mqHpR&E0hbzF9#$3?mQDiWb^nE_FQ zxL9-9-lH2bo=n)2!Gn_-m1LNV#Q3CN+8yC;*;TE1TAf0iQm5F9)sI%XW-`XLesLq$ za##jYINNypi798Wrah1ljF&b9k^*>M*PUnYJjbQ#?_4xCsJ4*j-=HGy8+FgSe!KkC z=CL49c$!PhWi(w;>jxhUxgR8zOuEJkvlqeO9K&-tlDNpK%8R$&a&VUN+85rZ(uMu_ zgEj9v<)$ZcMv_y64AxDF6me2@@_HxfFoY zsS{*>ipE|N+B*nuPT^Ind8WhU>P3WYe+afZ3$pywl9}=4l`OK(sc+D0(%Fr!JA8$3 zCvo1==gD3^WM2$C1Qppg)IMRyq_;cYXPM)f$5@ad8UmFQD5kN4YxO=!UoL9n$0(`E zug25H+`jyguYozuTp8hij}OY9sXx5Rt7(v{ z+*@L;f%`hVtmk!vVc*z>Hg)w9CDp6n{|2bniblI=_^v&IwSKFt+Cv@BU)KC*GZs7e&t^=2G$HR>UTj`JfuiAq57D)DliVgk z7mTG)t-KIX!uzfw8lz+%Lflc53uHM74@eAX#iLSa%A6}4haJ=L70Igy zENEqXz(-wVp7T#uqbb1a9wXe=q9EiRgD?5Eyn{yKh{rRHbd^-s?L>+*u7KRpAg@SXwxPVXnx z{Qi>F?4!Wxe~5ZhI;SoFJ^aK1?t(Y}S-HDnk7=x=!#-l4;b$C(rPeAg3F>&32|^UT zegmEnWC`;Tb}454v+%!O|Nj$-2Bm`bj@VEhVUxr!27%?B{Tqc|-_e8e!Zvy@>zZF4 zlX~>lYFYeXrfjm~tFHTUWKP^(?OxU34@~-;Xu?J|8Q*{#wMb)-+KfmV^%BG{EKJ6_ zgoy>*_GKQ-$P)8Mu3*Ei$f8#qf>oS8Y)5Mpn_DB z^@*Yn@2&1~i`Uj8@~Y8eFj)lG9zjOQ!>pBW2flk2MG}3Kq?UDxT;Tx>&v`iZRlijL`SEmi1|4Xis%)$qoO1Zx5D#*R0~d3HM+A$-6bRl--^A& z5asiyTeonpw|!R@kTS~Fzq$;Do7?w+Klq0O)>|%=uJbT;7iMEdONH57TlEE-%tfhC zJg-wCJmGy*=m%!0Sf=h&I1=Qi9D05h1C`0P*3Y>~pba0vghld{2_)5<3%fNHq`nWe zick|y$m^{oJ^7?cEKMLs?*4X%-$VM~XD=fw{TpBCY>eL*L8aaY-jTJL{vQ@)j5DrA z0*_*@z||TWNB(aLDYUDqFxDO^l`c65$^W6l2Hugr^ zy3pcH^t9#}=XP4picsOXB#A=nn*+m$esF2Cl<#9cX6oaAf8g`~eqeKblQE@(wBiYU zzZ|K_QiHxvzxvwz4n)joXEl2dlDi-5S<&5PP9K}dTtB0yqP;_;VH!Ojbqo=@{@wq;$HB`mmCNGn#EyKB&X$7edh)cto!sx^(t+K7yXXixL>vs& zP##eyI;?i2AT1L!x4AJBo$&sBM4;C}>1m2Rw~kua@>%9%h7@h3Q8Mc7p~Bcv%p_;p zjy<2N!27rMwM*DhFr!NzSU4_L3n&#vh8x^Ptes5HQw zrddP`Z?<-cTM(Shj6tW(%eI|PsHgk(bsU<vX#Z(Y_LlVF%Qt5pA7ZFN zy-MUijhA=!Bp{7+M7RQhXN zYnqB-$V&SFQ+6+#U(S@hD$>hi@TPreZxuxdv%^qowy7R8s@^}J)44h?iVIv!pr|yY z_}B;}g$gnA(Y0|Jr3cgS*NG8ut*SqU3{7`;m#QkYPvfmhvtR2+4h*Dd+OnNxrYmmx zg6SDw$@DW`l{>b4xOYx^E1j;)Wmd5`+)tIadb`1=-z9@v8Szri%WJS4r-=!e7IAm6 zcy7PbSjB(vdgm64wh%U$Xw@B#R=xX?&$1!YGj8U3Xjig*OE%kDqD-!nS4#sK7LTFs zG7L#n>QC_wL5;*#<<(TBz^w&Yz_A|UJa6P5es)jXZEBvQV_CjcLT_<7+MPLcS&Dld< znjZ#9S;dGS)^@`<3ausPtkB@dkjYtz47nr@?quG)`OHW}SD4gW**;N!^*&FscX9`y zOv!i59j;q<^#Zo0cNW@YUP!b~7&n|;dO5{>B>9h8kREIw?ne9uIlt*Ewb2Yn9Foth`^LkI|2p_zugvnfr_3cuhhL-A zCB72tEt@JS1XBi*n$TK#+@(JYdbwoJ1s?VwKS^B6(RBfhjHmSRa%QlM8`VkRpxNoq zl}Dieh|?-7g}P)VX#7;)N9S948&=wr;XO7pT)dZJss3`(4?p{()-L$}@jn30WsLsp z?-==pW$@h{{{`}$WRxD_ zYsS6E4v$GITkZ=-*s=C$y$e;oCQ;+-?s2DswQmRm_3~sFDBiXU+7_RIgRzgwpmI$_ zBdxiE@4GmV<0|U~Mo-C>ABcR-Bsb@Vf@6_Uc{M?R-djj|`DY&s4^bK4a;?$qm8s$a-Mm zz%Y?;N<>x{2sOB(>5*oLwk07CF*YFKqF=6qHN0#4W*H~N$^NzHEcP(c@x_LRnq#%3 z;ieDG*2E!4->xoyP*}cY<)H_ZdlQrbo)m{e;Qi6;p8kq98oNIQSp)$Vf6kKtZV-r` zUqxW48bKefoMXGhr`JySzrEfeV?6FsdYl$F;=CdItw=cc*GtXZhpTu0%Zo?&FCIPi zW^KY`|3hOQ{4jpw|2&M}Y+@XLWc2(ZO%{Bu17^xm?x{<{{z)O@Ir;;iKOFHqy|-w} zwlet_j)s8rJxykKgg{Dua|I0B_NS+0EFEE)F z!amSa{m35`aOfs?=r1$!t872=*Yfx6c4LFdh<5pw-0$&5+|EUCe4CNDGjSo&^l_oZ zGVj$67E7Fj`A8U3|D8sctJUJ!FbJ9Hx~H$IQ|=W)tn=NUgZyyKL`aiP^hCy+JX1yWm{Y?y}fvvHgM{Upk{4H9~RHSy%^6@#V-K;ZP0$F4fDpgNHDU!wzuG}*a zoD8jssc0*$t-w_ju*3P&)VH))VidYNzu)By#RH%nPuJmpshgBw5C$_MpK#}hm+yla`+32e~>PtVeXRnxL zH@KS^-}QY)&u%(I_rbtR;K}t>z6s*A$CngbODX3OKF_gk(8`fs`Y`qLSi{THDLIno zytB(szxn6z-I=EL=(B%=6~RPVW_;SbN7GE2!(zy~;1$8@>cP*B5!x$3Nhcd8Nb#(# zR??^n8d%UfpH>HK*yM0qdN z22qTS92}t1RE^-_G|Fp6&in?%xH2n1(eSB`$F9_%*3d#vI0SKK1-8~>6hI;^73KQ+ z4wBtPT$6X0L>08SvvjMViJ2PAdAdY?V=aci_ zmoYBEp}iaEgNig_Xa!%uEzvh;1C5-ntC_2Rvdl~0%D&OR`o`WYY=-MzD`b{549EM- zQT&(BT)}_(%>6GKu@M-ekl{YM{`1}#ya`yQ9~jBw_LDTzoKX2BV1$~#_8+lh#NP~| z004US!hhB8mVE2aXMmqMtxrgk88$Av?w%^(9ult41E{Gpl&@loD8(QBtL(ovZv7<> zaW48V#w8q1v0Z)yo|k{4KL6eH`iFAaAxZ7{2DB+rMr}QX{@y8z6M%%XQnWlxr|iA7 zhzS3Ak5(p)Tp#LhIf}rMmXhLKqxH8N-M2_a6IWQ@0Pa7(#j<@k9zV9WoUX7qM8wP& zYfw3?qp6mObf=0C=LxMJP;iUc(YoMnLOpzU6;!Tv6biUO&o+-g4;i`_02;E!H@Q5% z^a~^+=QX-8eGW^mNTia8fo>Q$zrjI+GR}c`fKsCLpjT+f=q+ii{WA^+rC=P8X@A_# z9-rNyIqfXoX6j>!FaMzmip_7!W$QP<#D?ZI3u|J|vNLQz4}3_Sq5~60?vZlzHv?CY zxWKIb-+-P9$7&%MTHu$9%hZh3(0T&()hC0n84*VB=T8#2Dsa(G9qJjq)Mt0Q$OOq` zs7aj!U|+_<`sfknd4-MU7GJw3oh1MG=im1q1JJ1U{}_+*7En9s>0WYQ@j0k9l3y;t zfsY~@|GHPX)@J;0S-q-`-hUean8!Pt0d8A;{|zW0NR^(mV0-|6OMUzsu+fSh_Doi4 zr%NPwy*4utFe9PyYlLT(!KvwO;mAMMCC~*s0D#~H{`)uP0QS9%k7XR*@R()(`atIR zJih0tu3!etWWgkbr{Nd0*PfGaDmj_-fu!yZ#fbg=M|EJlGsZ)F$Cip}cD7W)U4S`S z2D}BHY*P}yZhF<~t8cW{cqhTqJHA#NB2wS%0S zYJxO@dOm^b#-q_dNGdb6!>lo_tVg!0=#*hE-7)6yha{W*7wgMKaB|*d7f8bCyv!gH zwHj>Qd%($d5huA{|Ii!N?itaBEnv`-1G`uGjKmy60}xSs8_kVachgNx-s}zWbF2o> zejm9cky9!k4wZ+zS3iIS87@5~#nW~=mHZ|{%7=Qkx8pW28Obi15w%*iB$PPqcjsfb z6-XZiT+S-Tm_TSBYsvoxB&SZ(-w>!fRg?EYH#)mvVY@|ak2jgCROGD-s~{gwDcYk48+Z2rSBNQIjgNqix-3gq7_ z(_aaKJ&}egXEAL;{E`ngO_^rlbaG+J`XmH#e5~dc1Ev!vs=r1UrapwSB=aoCq~G)2yt>p_+T|cVE>_e%66`t&NdY9~Oh-pG{gVjLE?>*u znf6v6R(JsAd)P-~xL^9po>Ve)g~Ziq{QUx#2x~kB%=>!&&)ezAUk4UXmK-xDTVDEB zDF=S1rc=eJDRk%k2FT@(#_Zowjg(CK3p?pA7S2^M_rCqV$5i?@>NquwXQ{b`@`w3> zg>3qof^~_aGB%ZZrFHibPif3AmCZlD zU-}}q?r<#0R=lGC17kI-`YjG60t6`~Oe>i=bPO%54GQ9z+u)XEQsRV!4Ib$p7v(X? z(PNM_l=r>g7_lVk^Wvim=uRyim{WGuC|7Wivz!alQSjltjd*K;yD!^rsk^)Dj@o(x zUA+>c&MRwd>HU{Q;znJ(lKI>slyi-|fj52a(pqq|7z&kz9bFA#NwF~R%8%ICgSnEB zAiL0BYhhB3X}t^*KcqJwHDBrrE9;D5<1~YTO_?wiM)v6Z%?_YJQyG+Y?qvPfR3A4k zNZq_Y=2#wq_i}CN=>M_CfYxv}7oroR%nf$Bpg(Nc52Pd9;veO4&T`eukWjHSofPDG z0D^OIYmwr)fgua6Sg~p2#E+#ePk2$jKCK$b$CW9=3Sm!#Vl||(s%)3() z5M3OuUl)`F>U-_o<7twisqu)f#{N&gEI38Ra~AyawPQS?s7^!yMp(~En0-$9xvn;S zc{JFO5$r7M6>0f=P=PzaQC1`g$gQJgo^N3zGxvPJ8$3AbKTyf~o~=K7tuFJ6Vdu4} zv||3NmaK+;F`>43E(O1w+-CHspKY8iWX%kuY{Mn0*{G)rNy0N<9ho?x{yR(C342Mg zz9J%|I^g3#B?Ae$;v_Z=sU(SkiF=tE@>0kT&ViaT1SQ$hsC)f%i_EcF+FH5~Uvqk& z#$AR&XJaRZzV%njvt=65M4OI7A1-B>=YRXS>{QllR}$~g*wpkzS!6-7v0%t%mF36! z0DCi?q&B$$atVVgt9Hq0ILHnUR%6$T3{ctBjN;sh-qoF%lJ>05Xe>>I`r-*rHnPBs zZ+{Axbo=CEAGD~TTx51sIKNxw-@D|gy*ai#Qddg}<|*kpRj$hvIDDv+QBC6D&g*Eh zOWc@@oYpm=2W*CB2KnaKk|}+?R2s182&rB@w;8y0bl1(O*>dd~^VQ`W44XOhDcCUbkTcSNx0MT~C0yDKMRqchG4 z;p&6c-bJt?9W@Q?yg#i@5(;DSU}RNEs;7ZF&>z%z=Cat&EW^%;Wyi@y|(|$St2U>WrJh z0h??I!~kq*+o-kge3xSqfR;`wO~#8 z%;PQHz5ZsA8>yfD{*6ntQccp8W8hD&s}L#GuQ8uF0}~I2scF&LR=;~0d9=?{DJ?_!o5~|7twE@{sILYWI@a16zK(vFc|C`HmWMB9S7e zEeMGZ=OOQSvO{@l^hSn+b1cX725HRS#lMYK86E#u17hoDPKxZTS7??p%e=*f#OCRg z$U-dcrv*|BZtf+++@B`J`rq7$VYy(3Vp-F@r!-E-CW#mM=U`#LO_i6Smr}yr!Rcn4DFF6A@g z5LzOx_?h{#K?buF^)?-?VyH_djao}+Yzkmf*X(HY7cUm8`Sbh3#$MUbRk0Q1X$+g? zw5nC2Q{?rhH85#Drwp^tW1jq+4^S{$uVh}3+5?Zz+y_e4huS&`_jnDq&ohr{l%qDI zaSCXY2Z&1y0wO)SLzd3(XGtqoV{Dbb>`gYoUm`6a2(Q)VE@k@8>r8YRXOIaQ@_K`k zIxbw)yg+1pVG!akCfT%1IZb9bTxV2lcqjj99Hr0rLf3$T7ce zNydzdAo{xXQX{lRG`M@KA8r*U%RRk#mMCV_jai5wL~o{8enyE&<$V&T&Lhe{D(rRB zXG8?xC#;k%luQ!*htH!6u|>p@$B-zRVtti@d!-*6-v|ej)rWknmf1caj+?VFX8S~+ zNZVmJ{j&nP=_*6lRqe~7=uy2BGBVbKvRQ($OC)~IfmR%**!L(DHY!jN9R)jW%u1aM z7zT(ZeZ`A&_IP+-{#;BRKQQVZ?=A177&LE2$bu7M zt8e&}ma2g|GVZU3s3)g!k>s7Gur|hAQ)gm;$MN60qTI<)u~yZzDzF^JZXlrWAS7H! zCi>-peEpuovO86|Wk9g|%|zpR2?RRv$*w2brA{V0y!Ytf^J*~n)pnxSOI}Aix^GP} zwPUosM4$8q>rrx)o?J2zvxfyFLsfln*q7=|Ipv95YAA`ul#xtjWPW%~+4gr0J7r-S zu(gizd1OqQjg8co%4{^XKO0R!RS5YJG-mBvrm|%?mvk|)->T%&c%~BhP zcwYP~8TtyJRZFGeYqMY*c&>E6q|;=QDPnhN(E)G+>+=G4icL60ixHRmgN=RO)TCLo zS{QGaAJx~(Y-{dCDaXt4{cUeJ^S+;Ctla3l`{`%Et+$i-)`m3G_&SZo?$kTpPXO;u z{g+_T!pXS)RN&HSL+KDy>E_*bLXZpkbDe|XcmE6kPy=p!ygU41+SMFn$%121C8YzR4iPt*&#Ej(Rc8394q@&ml~Z)m&}bBxah%`@t?6@*T$=!P3geiYpr*Y7j=gL$s427T+JzX6~Ke~8KYzC zQ+BR|Kmlrgd|Gae#b`oSPyd|2`X_1GxeF2ACOv(haP{`+{N|z*@DG!`B1MoMd=zA; z5*+o_PO9SJ6lPr+1APmCvg=l=e=T|#PF%+((22Ba!7 z^T>~-&c|fb#GIT7uFky{mqBg}Q4M+PJ}cr+$(Z<6phpYw>!0r3A3#WYLR$MAuY8kHd>zarQER9quZAl1l4i@7D<+F8L!h&AUfGEmJz zjgETb6A)OvH+UYtXnG7YVq_CuJmmoZdhn0XJ6gZ%&I_X19Qo_Io+Uc_!%M1levdGc zizSw@3GjN|QRcdqkH+=WqLB}-{~Mn;(bxr=|0&z5mTm>tb;lYZxxGIAp#j8*Pok+; zR2pu-SuC9GzP@Y^8iyfO3?ee6HHDsw!bf(+2!D*ayG`4a6t`DfIKt zmM(IL(cjY6)n|%vuolyqrob@XkZ{%g!zjftDHJI051QCz%q>uCBFQ%qfR~ZF;4jsb z-3Ld{)HoFootv8tKM?!qAlxn3hX?3TFv@;#Y4q^ZFLf{bRV%Z29oix;)gpK(7-`n{Zen|Srb(wdrKYKX zJQLrIw-?C^aP6EB4Ob47AJS{hO{!!cZ07(4?ya$MSLpr}=u9){J*pb)vFzi-Y}gJ{ zVKNtDyAsBa$;132oFQx^BE5j9Le}f-$!e!zcnUB>fv;);N>G#9)-o{Qsh%(^Bx|0{C4Rfczq-Ji zVgK;sC9u(!jjvR0K__Ps2~7R4N2y{mXuKh>H@u60~3Y%pF^)@+N|a5^-5Y6LHUyKh$0!?%Hqf)SE5*+#A>Y8 zay=V(KB0&bdc7=99TAeAr67B3KO6fZSFXhcOz%n=#DXSzg8U43s@vmyO>DG2Hf z=D~|=KWcxZvuMO)oy!&Wi43_WN7az|2J3hIGnQ6>pS2A&Ax-aCx;?~3rY9Za!r;`- zEnG>CGnv&Oi#u6WL<$Nm8r^cv&1Bcxr547`cI(%2)%*zV35@SdQF~Fz>99n#YGvJ+ zH?i_V%YAN|zst}IKvJS{PIH2v(7A1k>pr0wY^r;EHu5gV&i?yIwFq>JR^@(xD3n&U zRn~Ac+!-SG(Jot6LSe{SsCOBI9vJB76k<-Po$DTv2(1}G)y$J?Ky&F3o%Of(MK>vN zy}bv;E*Wh?g&Q|+&ag`IF`SNm40_3WIQ+Hlq|-lj-R{uu zx=aE-BP(`C6>-I(%3HJ3vm0mVd+(Z`-Rq0rmRS7-ry?HLs15XJvhdmHt1Ujh<$V0u zXfn>@rafHqerUYdBZa;!Y}p`2P>O6I3<0SO5@MlWjV*H@%&l_0%Q>?1SgmWqDM50* z?2V1}NwTNcSiA(%c@+#6Mv@t2n$_jB?vu3*AlL>cx!=JJ4Xn6AgTjh>?@-<8k8PJn zYS{={+*YVl%KYxHzk+Jo8dewU)9*C!d!WrJS(# z;2PV-R9aleH7z%8ZpYj5QF9}>@uPid(QTo@?B9SBs~CUttupH3+_$lw!G9oPz?8+{ zgXi%moV)L4sseDmr#H99dBvf?onuap420Z{jG)^TSXn%A+gN2Ahm{;Er&V&LVK*{B zMMZC23PZuvWRG%R#)^VP*a;N9Wc=pa(C-k^DkyR*xL^@buitH~GGj%7EvLNo0tWN| zA}w873+vh03Vf?;bTAE&>)DW-Ncst!Km4oaBbylX_AH-DHJ(efROuBm3bOd2@w3$# zYVIvn*z>`)($WBIkUH*f0gIPvRstqJRv3S1Qs`xw9?I7Xk(B`Rv6-5EJCf#f;8dnz z4n+#^CG;mjpMCte(WZ{PLi?>+b>O8QP3tq>*}1i87(>XGH|fP_L`a3YO;&FwR8^JC zFk4j!LOijS<~bS+&Vyg=7qazGk12u&$a4)I6HgZ|ZabdfHHdtjTkk9p!q74v!I zY}_ekQhfuWkcMG)+!v=~Lq@hyPFqpb8Wgv5PAJerCFhgpl|+=Frj;UMrwhHpDDydT z1hdEj@N3CqIgyOaPffCY3rFX-u@7z&A#5zT^%Aw^I~`EJ0eoI8`dB}2RSPOHQKF}~ zRHYYF`h*Xsr+bN<;B}&>@F_~I&6r{Fg{uavpUQCNLvTRT|go_}$kE`*J@q(yhC?zvy-vN~)} z6z@E@n3Cb<@BDNMpEY(XwV-XhBC&crY5omB`Ia5uNB@7S?KTg%m3RDKkvyU)kn*_HR(`sR0CgZovg*-uzdAe{KEWMEt)2e-GuKoCx|Poy6g&zS!@x({51AnVeiS zae89bdaoYKXEQA0V+6cf+jpsrOT5Cho6j?>?Am>GKU0OY=WA+{6fu>#BO&;QOC0iU ziH!9^>thpfhDzH~A@@ z^hjNk!Z#Rkh$FlhD*fHdJFhc09szDj;I;4o+_|fX*KOgNv&^&|X18UruOU^~k=WmW zaRs5vH}6}{@me3BbK*~xL-wDvJ`$l`AJcrjd^EfhL_1KsNqu)zwx)gdqGS8JS6O;R z5%*aNS$z`p+IgcbGYRqvI+OcoM1hC^>CVf~yZ2@wa*!RlMt`Lg$k})CbQ$;V^HG%3 zK#Q6>MU}aoR_UXW5e;;^jr;9Gi;$0%8X0669p`lqe2uSs8!}V2KXhh&=yN>YbUsIY zJu8;C^|vQ=SEW?No$C~Ic9r;Y$>9)`H1^zSuln;{dEQ@GIS|%3_mc0ghdu%OsM|WF ziSSHRDsChfB=tnlXQ%Cyp5uyN^sgLBzWkKx?w1$)kuwqn-SkqNN0UB7TY~j<<`&}> z5gLxX?Tbp?e}s=Nf`=^b<1y(9JI`<_a++DwKwCPKQyP7@CK+Mz(Lt`4$2FLRrtc}x~QXXAym{e`II{{i)UfLr4fQJHO%pgo|==szmn@gmM28*}e!u#a# zZ=V~|S_BpC?D>hEbD6UWbTC;lDeZ&K1qaEq)GV$b5fv}mPC&jjyqWdG86zkhTerZ;!AG!mOD1+HLsw3JfvpKI>g%io z-p3jhYr-KHV>SKzvaakCjUJ`1jOhBN(M4w=TjAH1L+0`C!+H4%2NmLIZt?V^3#NUy)dC@;Q-wj%BwekM7WF6Tq-| zP`;kxz_DEBbM$h`oVd=B&17=+9M};KRB}~>FS;Orn^|>ybo2F%^S!?u5Hqw7 z!43RyE~(hm$!cC-HE89=eOtR7vJfN~VonMI;}eYBA204j5E#_)gbPfyX!mSNf7Ut4 zL3Jf+Dvga8sXCqziqMh2ba->NhX)=d%}o!HmR5s%p$@UC>4vzxjYjlt%H&uj%#XS+;}KiGR}`j0(IzcVAFo@|7Z#N{O5##cOM47e9lb)cX(1#4 zF{`Eeyq&M3Wh>`gjYVNoCPpWZoly>HG*J5N{{)vyp@V;d%P_RUkXe{mN~`jUhGtPj z$JnD1-nAM1&tM4L($asCnXa9gxizUR6~z4{oJisHVIaYN_IMA~y-}o>px7YKZ@~3Z zZ*&I_17WErhSagh@YKSK)AD)x17_@|s=$tL3p~|b+n-$`x+MXKO9hp}1}up47gx;_;`2x#_Z ze3fIIE$CeRoWVzt^K^qns0!vFv!Bxz$m@49f+#_xOh_DY3OUxwL;>nSO(=@E%hv_CX z*Et6sA!`TjK^MgjnLSTx5l!uGqM#t#Ob-hSb(>f!)>whSW5SY?mj^oErY!#SA?6}? zSufI^nRD?OgM&+TS9JA{`Mp)FclDCb4POoDcyh|$T_elCx9RMJ-QMZh;V$qj*N#90 zB2M1A!&FqZ)4wLe%+)C#aAjo}y#%NTn`2rzG7z><#kjUGh;S@5>9WVTe+G`~hWRSF zNEX(eUpj$JwMw}_tuH>T1WKDE@ApXu9c3BGn%U)@5F`UsW9|}V-o)g`qzwu;>BG_^ z-rBq_3KlN>pfdF2V-9-~i)@wjQDH>ZX~l5+Snh@4(L09E$wBye;w~Zd3`3KL&F(J` zzvjbEbO4McJ6X7rC*`$EIwxme!mBP{p0u3p(#{4$+nMnFbja%H^A1B~;LTscesqwj z$dIs?`CaLdNK^vpK9Dpvb}i2t)HMCla(QA&YkLB_ETqylK^EWDkzGPcXJ8{NRmSLM zh>WSp=jf25KszU5`&=P)dXja$TPp^dXXuDEg~Lz!3b|)~_@<}m_D;_U*pJ3`#?YaA z7Njs&%3A?ZTk`g9qId-Fp3%otx10IUD{ZrE_+P7ZVAl9pxr*OhSx|Aeh}b_!RQs5! z8P!olJ#T9=%9{B_t*~j|CV23R*?QBx0rq6;S(*g;723{U^oa{*i)viSB6KmT0$Lo! zaxfSl4A*Gni8nbwC9DJfpCbG;2^OpW$pUf!>oK(#5&Z_RoAtD015*hQJ9j_5ss7>x03cxyqtH4N;VWGmcdwgiGNTutGz}64+1Qf^qX$7sUkAeU z$QO#Fb>AB97AgRy@^At)o}g`-Ii z2fLgbA`>ajQhZYCEzczn3i23KxrdhpA~&=UePn6|P)(Sv>adNh#AlIw4OI}=O(|3} z*q}_lGppBHaE(t&`LatgPYVmv39|GiK+y}fat=K?p)~$tgvu7?%-?}wmTF}tU#4{; z+N>~D@jNcRiVj(rFCHie-_N(W&`AwkVf#Qly7%ClUZArYaDQ%FFGXDePXH5HO2w|s_=MIx* zNc`vrt|d2|U7@-~@5kF%wD_8B_C1tyn4%8TeeN3FRh7-p`>rqnHbW!lsM^gse1)>Q zhwdG4EAXn-F*;gqTq+N*8wVLk1u@gw0^f-mv}QJYcYk@B@a(MbvD+H0NMDNWTzbSF zNs{%oOi+iWXN0anGCO6xLwbqlJ+w6reEaz2lcW#*VNAyLcP_ihY+a3JHuVE;Jllyi z;nr6kXnKE0bsm|G-bs@v8|SQ+Mspc?h29CL zaj6E9NPp4Tr@+pB;g|{oSMbX<4&)8Y@V98hUiIFWQOl;DbHQT81Olshq4PDE&tv?2 z4Ue-wCooFoYuFsR?Qs4;s-DEu?9J=&=8mmq9Sg~xkK5XBFJ}45!om=793C=PD<(Bp zhfHSEG9K~+!uw9Z#Kkim6-6yU415I+mWX%yS;kB7&LBF2c$`cthc%YW#k=qQEPBJo zCOWQC4KDnPyzD0Z?IbTwH!f;KRpL$7?AsuP?MG`wu1p91C<_r2{i<|GY^5Psq$0oD z(R+V4Gf>%{eRNw|h4LX0i5#L!$G50gTF1o)Y3s1!_X0o!IRCRl|2ND32f@&}@6_SR ze`&8g{bwz1G0Qjs0M_2!HwwQ+_74N7w=1S;qR5qyf_O^bze@eHG~j=$Zr%PqT4-LV zQ08ZDMk}RUV)<*Q zgu7j=dhHo*{|(+$%QbF3b%|-VETzAKaO%i4ipH`S*SU_V6K5 zEOw{yUMk{r;<*Wh z+#)d`LlQQ*&kpamY(x`SH3=DYX&imZ^Ol~D-4X~(SB9|BubXqkqnf>6nt(tE7BFwS zpkOc6jk^9Vc(B-gX}i$1NgkNZei1|r`WwJds`hae5BI#@Em&=2+P7vpNWJn&3$XYs z!}V<=Kjq6v=Um9A)KB>dz}j?et=rOUiJ{lNkokp4Hsoj>nW-Qc!6_uYy*w~1rKo5* zDs5b;KCYwMT)tPPXBAhY-FVmnjq}1`@;RnIzE2Z5oc=dr!vu-|-Uk6XHi@4=|QN7`EAMaDz zPtCV`T#w$Z4=c-tkIM+3&Hr!S?+DENI%pJkDzlNHswa~IE+)#qq1Ik{UedP%d$STL zJXHj7cP3f{^SLs!2=c|Xx6@GwB`gR{~!jd(=#AS7E0qR!OBvY)J5`wGS z1Eny2n^87`dYNRbi=p8GUm_dEukg7h8j5{<%lm$*8tJMFWOEv1-5s=eXV4>+CD32quB2l|jT;@(kKoIhk3~-3! z(8{mRNO)RO>DO+w{eh|4lQDE(FDN*k=p4M1SJ@G~$T4u1cylKT<^Cc2eRp3l--Ceg zQw2N-`!H;&!aG9=N)>+5mkHjisTX4}#$%X#XT%!7TekTqtnm~+aPi!<`7?0osN?xG z7<>Fa8lAKI3$1l9afCV>Hem@<7DgHhA=;RQ4m%q#i$>4+-tvMBr(V5ho0-W6-c~H` zl@Xz)k{yEspH$KyYqlK9meu#;=}!s!jca4N=Klk%QS=YIa6(khu4>?!>wg756Iv7N zPlXt3AI1j?L&cQR_}|zF|6|R~e1_-z-iSlQCTHGY6h%Xrtt1|oCxx(x2;F*k5!$>` zheDMffWru-N;hjid+Lv2J?5mY6QqzGt%dt*-im{)0ln0*m+i(WCMyyBw(8MSieO({ zMO9D5=l;qsqFlb5*!P+BV6ijC%*}@-p;=pD(vJ5Du<{u1JSkf{$u&AnRiJs?9>eY( zw65fvqYWe6UCu4$i6z{TZJ#|EqVULd45MP;C;J|d@>E5*T4 z5j#ex7)XdV%a0vuQ^e%7)@<1dbFycQ#72|p)Sy&FD3dl@p%#@J!Gb%4?NpDmcuftY%{LZ2nzs~MpKCx_*Y0Tc zp$Wm{ZBLNa;_IeX`i8iJFnXG9``U?gUXSq z_;#-BHCoH2-eKhv$q>|HuDB*OhR3l-Q2N{m1>t22YW+{yZdtD?KJjc}bQ2 zs9`aTxVn#&;r=V9fd(*vTah<>4fLr^=w2qq^QC1b~lx_1#=os+8CeYfSAEW0THtBL-62B(Xwf9@jkHJfQfRP z_LhCsw0qH|=gaZq+v98I;ZaHFS*cu{cF0*_QDrF)R=<>i{z+0h-&vS(N(B6SjjxxD zd8z}9Ii`ro6QlmEcU#XorojC+$ZFJECU*Y4nsmoPg?F`norR5q>fB0^^F9tw^Y0#c zKwyHho}eO$PED}xbV&Wbn0pJbD7Sro919f*K?G?9h7Rc(Kx$w}VF>B&?gmA=8M-9~ z7)t39q#J=@K)PERBqaQg?tS-m@3YUj`<`>3`}@!H49{9`&3YH_yXyOi6_3eNow@5~ zR-AF|offUuT;?>^A_&}@3r7U!{Y%G>suwxt8Bg>s)54*eoAsx%3;58C&I;CexKyWl z&>RoGb~z*x&pV+pMo%J=RN@=j^7(DZ-5mTHORcHImPT!})1^KdLz$-|TQYe&S#?33 zjJgn)Q<9fxa-k>*x9gZchgNMV_z15>R-bu?RsKqP!iTc(&C~MHW-lRpvlKTZPyO;i zWc{CRdPgrPo0!UXEr0m(U913A$ql$|a6#;@E9%{5wkj(u z1(Xx;g(=#2$Vl9f(?T29#B%>XK+pFK~tlH!m0mwiy(Prd4;y zgN6NE#?0bicd4JCyi)uqS#F9wzxEjnFfyM`OP^{$Lu1$bZ4`!P>er2SLsXGy={Vxq z?_2*@w7Fx-PzEEHsAcGTZ2KqeiMWO`lhTvBup$6$*-=$o6@-qSugMzJH5wILO7fO@ zq~~#P7Ug=`1IR?6EA+?l|wpP5hj~jp%6Vq#f zULD)XJMI-t1Rb}N8Y=_`xm{bwv)WeNSX=}xo43yzIM3gov$pp)KOOvS_nSk)YSX$O z*Je9-PbffMH7{f{Ahavgx6knulWmpNs>`u4W3P$v6w9l_I&sIX;)+n>cJH3nmdB@; zzg@ARBkhO8;3Iuboe8hyqg~Sr)=(TaPvh<=V%LgU!j6A9WB#wpK*8AJh@vyySlt@g zIo$g2fPLrC@QsCW2KwJSoCB>*$l$pD1UNBw&){{x&P2vqs=$KPbFa6zK6aJ3;iOh5 zGz^ws$oAjBJPVuRm_~K-%-_pt;+bK!8&D?lk2S!7s)0erf%LsJi$MnTAj&z~Lpb~I5RE0E#@w+irW$+_o65Ik39 zU*o};{+bqFhr=dLDgqp)TO?DrDGsg)b2cZclg!{G_>sik9XsPTw2T+({ypnc3Cd1W~JH>X+IpN2)% zF<;;J+6%j|WR<9U>e(G;W7s7#!r7N84OI_4%}R`M)R5er0tz*Vl#-Pr!KO^`lBPKL zS-*}8eNqRf`D?Ep;|ZWYk?E@p_u9y&X3fIQu^Dd~1P^v>WSlIl8=f5DAEAfHQ>_ge z^DoK?l?`t&awkF&wJ-XSb*v3QL|~S|;|$R=DRViqv3-Dg51v6*w6r`w<|M~L`(T=$ zbmYq^{faa3<*#X(NT=oNH8Hq7abI=f65Mua-N)_`txd17?ZTq61a#F7>g2E)A9pD! z*qwmqY)arIMYGP_3uF4F#xovIkXcwW^gSh(s&}as@AV`f;Q&X~+^ejeUX18Oz(1{y zNG)-8%B!m`*=^%4*f<3FnO7dwn|3AhaWEb6gGXFSxS=y1p`kT55UCPB8 zRn)-n<7eaX+^APZ{e!mQh?F??ZoR#)DXO+nQA*1i-8+!w5uA|0&DFYq+*EnCMOCo& zLBp0NrhSE@v2n%_GhOnQsQ#uv7zMU@+UQ_eN46@KtSGeHnyb0o$K9>BRv*Bq?1kAN zCZcWB!NEyDo-`#+2_mO9;g7B{>!v6e-X+wX` zLI~SnyZ_G+O9w3?&rC;(8uEXbbKsqPpL0Z`XiJaKt`}AhtZxbh)CRye$)B527pTT5 z)9aVsj~Q(P)j=%oqd&K%oT!t z5hQNh9`NjQn+bCtqJ4~^`puigLX3x&Ts7nfEZaWF3GPkkDoc=5jY7WDDF&-Tr2wwv z17P1REF_>5Y^@M66|?O#@>!T_7Gmf29t#-7nG*4W8s014Yp+S=dM;zoG-|{Cv^O6T zf~nZmy*m8dHdV%I);}0x$;nI;pHI&YL>bx{_Zyjj0Aumh&C_x`Q|8*Rs7iKldxm@$ z;HI5Dqo3PIEC*Ksw6X+*dT?f_IDkn(dW`RD`1%h#t{m?wcB1BuhrSO`0|geRZ}pE~{~sLdNpWn07H7d25@&J`dxMS?IH6 z=vq(YUI>LR*G8u)H3;V>au$X>Q9>dLR7RE$7P0aoU|c=BB&)kZ-_WKUl4l1=mlf@{ zM%2gX^Rc7k)Y$2z6Pp~$BOT!b>L1;KJ8Oaq%zY@{1(7riyn0_{IzE1@MnH4aQhiQ4 zkpNLS2n=6wULS(Rs=BGjd%`uHX_*sT9U4cQBCF$PbHey-ULaSQ;f%cwSZwn6R4Age zoGtlArdQvMkr%1-nihDQ(#%}fSRwm|Qn^|3HY@iBjOrxEyzhuQzmPRyLwf{18wsg%NC@?N!1i_z)5fFbUe1&u_Cg<&Dy@DhCvvnFr( zkfsj$9*V~wr6QPdV<^ZO*n5^<5e7*(sS)PBSW!~6&(5eR^Gswu_Qb6_2w1^k8A^i> z`6Kt0B63J(@-1y()*;rPN*ZM%k{voGi49sO%^&9FOiaImHfQ_TxlpbYYG^A-&@FrXV+E=1IBz-UnRphQ(3l4@O3RlPIU zQDKLMJ%XY=KdOJ+IVW7^<9A{f{SB>@o!vn@ED34hEpUW_1AJY;K~JcrzT{B}@g zcMCi;{h3y(k+Dr5BVKssid@Jn_BA2*3`(g=s)w-zEiq0%saA+7eyI%oP#p6#LGFQa zb1U_PHHNe@3iLCRaCR6&fvx{!c(QUqBRdWH-fdFLGS1(;gm~2M2slkzLhDJheWZ&A zcz);e#k*~#FU3n2LWyVkKcx*IYj(5mJ*8f`hud-pwZFfMf1MvC3n-x6Xo*5<;J~h4 z`2L)6pXPZ>jvzNA=^rd(y)Jw{ha#yU+U6nyeorfG-GR-j{ zajzv=d#Wd79}>t4b*j>QgAk}+5&k&?+#&fCWsbuZv1&S=_=@tSr0zjyPwmCwYEBfxxh}I6iZm*B@?f z+{Zx>w)p>(yZdkc3BQ-q{|`(lW}o#3gG7(&DYv&FK4exIeY^*ABKbnL#ux0mJ{+^1 zsSn&a_j5q&B-_s#@Z!9=^D|NK%!bdz|aLzL@ zdZ_-s;z#6~ykcm0RWCEM%aY}|%wx3st-m=TqM>05zC=S~Mt#2nvH$glyY3%QPfQDg z{65Xa-s$AwTsUW~$`p@cXoug3(9wPTZ4;3Q41cLmHB-?02rA4|g z1%TV}BXi%C3`*}&u{b`g6JQra!KAvr{1OL9{O551&g~+=tFkV2a}4*67yvzoQk)wl z#H8eJ6A3@W!7U9BrBzCvu*tC%UeXBP#vk5k?~tNQ3v}n5cMk}acl?Id&Z_7Cu3XcO z+exPsgue?$*q6@NM^^YLV=rWiG{$r69wgy0td3jKdcb<)wWlQIkVBhHHVV|m;yXvi zG>ftb?*n#rT+s2w;MJgKsZFO+W!h?Rgdjaiv{YcomG z$?27qgj3Gqcy&g5=T&waj}O@ruY;rF-B$sIcTVxz*?+J#RW}!V>|JPb7~U24T!a6VgcS{Z{2dNeh7|!CA~u z?e_F*ZLtcu@zjlVRf2p0Q31}>dD(i4c%Ln)R@s$gySp84tFKR@UO^I_uh6EW&V{O7 zIODD?!AN*5Q_*F759{*c@*b)i=lf*g1doR;S!o^n3Bcu|4WoxIE9C3*H=j+*v2%zMej?mZR#ff3 zQ*p+ml#PVnU*ao(#F{rM7<|C}7|)|o`8Y*aT0lDidHlg8dlYx=-Z*i@g9t>InFXWL z(T_nl>K@L-McX>w6}TlRp_pgT=*s0dlp>qtN1-=Q5f=U59b)J$D2#;SZT&SzZwWF4 z=a}N6Tez@1Gm_=4*nnX43eV4QYzNnAY>_mUpTgpAxxpt=`M#?6FU2U%65-mxwYrH7|))t4P^w^3=8La>nGMdu8T z?(%d^M?(g_#L7fnhEa#)Rf>AIWz8E!-)TvGZmloR_-IyRkU^u?eT68~%cE^!%>%vRRV@3WdUKK@ z3>3hHVXqiE4h6INF>0KKgBU6c$5PXlccxJGotmyz$go#Nfp2b9{-T5W$Fv!~i`&&ISnmY1j*;hzuu zrB@59ND42)5<|%&Bz;HoGHv|m*R<1bS`>5PbVUu{er|Z)9wHRsb3WaG3X;eR_c_7N z6luEmiV4B!sOrlF?z?toqx!ZpfrV;_Lclk)g)(BF=6qg}7NGWXr0g9#$O(`)qv z)TOnyS=$G;XQ3|918~magId10o%px&(MQ?1xL{F4>GR>9Ck&7fD$Y0Yu}d+TLO;$% z4Qj{4c|t&Ud<))!Qc_Ro@_eoC&ln$Ve0)7q6y5mvZAeyRP)cgVr-yZ_2wkNHkV}?E zFpa@m>^OP>7=R{vL18;?Mo#EZ8cfgPAj7r0OWh+;KPiK*#k*{z>0Dze0qIF~8eIt} z+V+}1C)6v_aBhFXunOcIq#s|~jsx$`qabd@@b#3YWd*uTKNfW&))6k?1*Z6e)yX91 zr$d@W@_gZ8fu2j#4TXJy2U;)|V1}fIG$6$yadh(~9L6kU&%u&!HC9y@u>?p?&h!n@ z^I$NpHLt0w2jX)^apWd!)0gI#dEK+Aa=q%BBeIvXTA9hWP{k7HtfQVuiUqq2&?%;P zACR}dlZai%_gtkCiNENTV@sOo*{;o$n2h2ngG^$(e70_R7l>Rc$tqs*7RWQ75iv5h zR8jd%85|HRm>W^>Jf4YZQ|@p~MoK%FX4;40PE7+R9HBV{t1Vd)p?b6kUyY2y1o+gDV zY)GW`bDO^EVBK6z&L}-js9f;XPrT>8<;<#Nn~#1pCOZ;E+mz_)`n_Xj(@hmWmfeaQ zxvURucv$85d0cvWV2{+vLPh*^FjfUFn2lTRi%=Fo%Z;V*G!2b zVFzn#8yomR6(^&a+1^>9`?MXiyPiuO>H0aZ`)NTeoBVJ43>~wR!w;=OBiZd09o5Rm z-?rPZ=%Ep3OZ^jM?@vhHKjL~(rt#{B3#>s7bQ)UNO~+;yT|B&ofB5uLml4UGWxHTvhr{F6NfsJRBwpZDFcxY#&HXCyQgl7EX7rZ^Wtq9zlj^6n$Y zw+yY;fMdi#7xSAq;Zm_?h_8PjTBNSdKSLQjkw*PV4^8!tdTEZh+EnLqLZQ3Huitz_ z(<>Ueq(noL1lOXW-EzD@oM1gbpc?J>!M3>JxHl9tBDlDA6lAZ)pRit;yV7P`JRiI| z_}(mwYlCH$7A(@GyTqH{Pq7hXr0}{X3`4ajm5EU6PPb5s&gdsh=Nyl}f)HI|C3R=+nykXL47K^1|%n6c5e3E&qDE)#(ILWXH}Pcc0IDY1E;+_-u^plw2eDISWQFRWLP~CE=qquJxVFKH(M|J?${fxTDW&_yP+@+Fe!+okWIrfd&q^Ds zKvP6=%x30}`QTu3E<$!#0JA_U=y^b;csepU>!ze13ToMHAj21%zOj6WvI}!oYfi>? ziS{PixV^8D-kRCf>&{P0FSx|pf z%RxscYTm@$R(SxO5;yH~2K1|wXV1@Iu#ZdkTC4RZv`MQ!DYp)&g%zJcHFLc@JAuIJ zjiKuDMXlh_9g7Plpz%~{rF1~xO8N|405Q_vsHQ(Gsa&0dg<1>5-}p&Mx4``(Z)V~v z$fNxMTT~q;^2$n)6)tbH%jirmW0jA!TXc8P#MdG&x7Kv_IeFwfo$-Vb{ys!zeWF2o z6ItSNxg6Egb>tNlXZ4vR*8?Sz!d}Sp)fGHwkH2CreV)`gIg@IuL@m^>QGUICa@)4B zN0WsIhe!bg&uxgHgWF3&r;XQ{t`@}4ndz3^R98%e3Kz*gdCu9dp?b{Ll=C`R z>790Q@=`wO;xU+P7s1JwTNc|sM_33;_&jIq+a9wVci{0tuv2NO6%JOiIk8i+V4l;d zoj{3wSPpdm^(^5kk%x9B)O#O}=YN3GJiF8Qlg#q-6sfb0bmpRk=}>~i8*dvU=@-JI zsl&s9krjv=A*l8U4L22~Wx#KF;uhz{j%V}}(x=nc`271i`(I#tepzS#^=&qh_^5}5 z#Rux&lVLh8|8771+egH^NsIG?2;tS)GHT&5nhj?FPmQyr0dWfpq8gj`MsKnak8CZC zN{BZYh>J^CLw5{uwMo-SK;ddrcJuoM`S)IcdakPZ{1HUgnyYy!Bgzrhr$HKoqS-M9aB8~BVv0j#pYK0mxG zvhej@Ey{MlfBNNbxA4D`xIysjuNPbX&ry|V*Pm{y3^_w8NfhpLCq%q`Z1jLgMI1Rv zb{5AzZG0$(!_`AK+(ESB_+Gr!#)h(NhbE1CXdNL&C_Bn&WZji5S1Qkqo1_E>?7jm@ zPCSv~4UB&AQ8rp4Jo8y2M2JXuk`rKmIJYc_Z?8gU5i;MgGOlGiR+O1BF6X#$TyrQ# z^?`ugR^sC(zhI$;Azv;9k4B)sSt?EN8%iu-#sarrt6INgvr!1OA97}8kYJzU1a@kanHUC)}#IFO_iOPG9yTjj-DkolZ=NP5f zVT_)=jhnQ-Zb+4(F+zn>Q1}H=nN`ebSe+?mr+EKpii2S?R?NbB48TU0A;RAi1C1`= z37!#^VQsn2EqOh3sm9(!X`I+|hMf0*j!cs!vN3Tyy zAWI67s|fNW#@>|aj`10Auj&l0_{Ush%HrUa*gJ_-#9_-d%9XK8wB4=$@dy zIU{f1V4to7JKqtWPNa8bZjT_nsL~5C(Y}x)kU(}%$ceP`x}rVn%}(=2(?Fo$P+G}a zhB|-_EY3<}Vpxzxo$_ju%sEOyLk0>AG5v=2VKdkdA}hw0M&Cu+g&3X$yVy`%XK^6e z;?~X~QVMj`Nl5^d$Tc*oN%u6cx|4L73&#!6!XRQ#UnGmMgukWhuz}3j7@f#@(`)bR z%(hWkO=t8LHlmmV)?CEFt52whOT+~+J=aBJZ|*aevpk|wBycZxBaF!)v$SdS zI!Y$uy3WwUI_e`FHkX~5#xj>|uule>3CT>1xJ5tcJDD*19!U`$fvSC&~SFP_CHs?gT^?Pe3*j$L1bCC-K$n{WML>P!iJ-aA*;%8Mr{~loXvoAlYV+b6HwU!f!-O8MR60Vc&F5R{IiC)2sQF6 zlum2D5;WoT5ZDLwT{$2yhMN~kfvk}p{X z+hfR>_P}Bbt>fjU?9WsrZvkG1Dofwb2IMB*AFiLsFYCp*H9^49E_ofoH9;Y5^*0*Alm0fjm zN((2bnK>|OC;At&Gb=By523X5L`fmRzMijepD>`r0Md-fcrJzl#8{T8HL|MUQMNY| zX^&b%u+JHT?0RUtk4l6+fP(!~F|I{eTo9xH{zWKDNwAi(pv}c1C}@6hVWgoOj+v<+ z4~=rC0f}2@UI*NN=}LScqFhBPd$u84mlQPSxd&CZw2NLB-paa5oj?1eup|}ORIH<^ z<0z*Mx77Hue_-XkJjgl}Y!1RMM{Jb`pr?idB-druH*Hm`GsfpsN(wIVH&6;2lMrN| z9Gf{SW+A&^yRFx1s8iMw?Uv{ z@Ls?@x>g09whS!w`6OVw1Wzd>)~KD$(E^LNHT79YtLE~9MPgz~$U>uaJYQwptYMy| z_P%cD-?31Je5ippBeDMt?UK%FmvW%e@oBuHbxbN z2h*Gp%P`5$p#t)v`3QKg`qtts?9tVmpET|rC4bYt@0bm$U%3=^07J2t=kxg^w2Pr5`Seco;p{F1v_NBDhw91ID=OyZ>?Awx3Ip2F)82s9NX+ zh*3|yqxvLh<%|nY*N0nykTOj7ILsTv+~?p<)SLF$a$Qb|H&cn-&C{ZAvlpZD363GA z%Azru=If5?OHH}dWW?{rKA@HHdZfUL#!*n7{rZ5jluNF$_KPJ2S0Qf+P+hEey`z?Ertr`UebX_XFynV6-VR3GUP|0*#w}=-# zxU(!tPGu&XK^AYUZ$-gK5@oWKq(eg0@v;r)TJSQ1?Sdn^9!AnOhb09E2M0>d%&*sWO*{$f)F?Hw~oYWOR%z#3u)>S%@pPtrX?S%37fuGuh%KNww$W5ShMqEvew<}I4(&_|9<@p2}+QqZEv9cv822zHXI8*0-c-Yat^`c#MX2!Lv z6~C@7f(pILg_d+cs6xZHDu5TI)%}%fNOSwaYw@cL_xRYf~R&!q`nYs;C`H5zE|TfwP#3P63k7S&H`Z^ryVxr;zsp~>$o%+b!iQd5GoQdKD+X7uMsZ+w z-pk~ZhWrUXQO;VW}}yV{-ue z%O+@xgG4$9268rCbe-3Yxrd9A;<82ip;~saZ0<%DgV+Z64TpjnfyGN)h7@|aD&n@u zfZ_d$ThgRz=lljFKBUm5PSsmH3wEgaSE=T*dCsymJuX~p2-1oxMvxw=~5$-pstp&(cDj^>BILF zFWIOpea(;(8BoH!i$eLiYO1GvlF3wT836gsYXk4Oo5KqmNEdSjA40E;ql zfZ>LgL-ukmQb~i8p84@fT>6QUv~>4nxIGCI4bf=c3W@HdWQ8mu5(k&q`E8wLh;FQ{ zx*S3N8(HB3CE_vA>w*GNhCwmpTbA+r{X4 zLig(Nd_}Gs@%t|}lEnK_mJ3|y4#w)lx z1gwF}9guJrjA_X^$3tAMOl%bH64YHKbIGvBiC3Exm@y=1_v(GUldT^YKsB+91X5br z4q&do-WdB@m->mFSAjoRy^o_a;?{Aa0@2Y?g3tnxA16sGREAV4+`|1FrFs>dq8gw1 ze#4Dl?L8~uma*t?CZ|Lp2`iTzRk1gj0ic)$FwWTyUW81kQQ-yQeb9@b_Aa9<&YQE& zP&0-4!Heo(xTHJx;F}?0{$sw_U33$K-k=!P&y2pJTISNZJQ$(z3Xip@0IhN>+wGM` zUYB7Z>igk)T<~%cLsEsC zUh^BOF4GO?*!3B{IJbGYjQfiAnb4>2!iMd)cdo#`XTIVdFQ>+%0-^bDnnBlBO2%rDVM zv71q?#UEhYKgY-nq4Rxz9VB~^_#;S`Di!7gx-8*72(9NwtHn2NuH8a7tm!||IXiiP zkv}xj-%8P|JOm#lh=ZmwZ*YW91lfnmU>v?>heJA_cXQF- z5&!tmQWx7mS_)}8ByIxa3#-0fT69TRw6Mi9$xJo|)f?OB{Gwl?@p*&U;_KU8q>qP5 z<*1mf1pQ3c-8+g<%B=nq*?Js6d*cPRQ^v}`ydAQqvV&XK%Cx@xI37uCN&BqqpRq{)q)hf4;>u2=dHd=oAV7VgX&Gvv<6gfxI9ra zh>C?4JC^E_#>7ZSDU>@aqage4YwM~ExsySn-Q#`}X=|O_;>I9iNb5-aySV90#!rUj zXyJbT?%Gh7>$DJFM|u2)$*AyN$gAY=9FTQgBMiNN)l5GZTjG?G!6u)!y<*nZY*tYS+P6#XVIS8}^j)3fB*W z^{P45To1)vWg_-9u0|GZnFg_#c?;ITRds=587osJC27@D#nW26D9%v)^Z&UJOymmw~L%Q&L)Z$mGmrFmA8Ea{X@MQ(>{)vCT+Rptxy&yPT+SB=aen3q~p!LImH$XGD zFG#ZScF;P@(sMNO2M&L?mq!2h;<&$E{{OyX{~0U;dMb7);lYWVtNS62*ZlXy@fOB# z_YVp)*7}VVcSYOF@`$~y#Kr2(G%e`dsHmjFLMXg~>S8Q1&J@|Az*$9H{V>D;lT0Bu zEH)2wIX(@-3=ub_IU<*@ySSt`KA!W_bnuBmO31azTM&4)O)XKIgR*C>U>T0`mDrvhQD*XV z+JTjDwN@UADFRyI8#RO&(n2F830DHE69oJcJ}*Ku@?-js&hAmdP3|+74k_=H+_$&1 zX3)Se$fZL_1`sQYXZMg}27g7D8}TWzxomwsvQk%96gT=*jU3NIMPT%18BYBgM7%y> z;C2hOC!9J%$;e2%iK+|Oa1UaYQMt|8gro8eZL{Y=ae8f>5eLBh2yNuy zjONq8S%-XXWhFQRzC;kdCFP11Q>K9t7@YV(@%TF4$nmNpM~NXTV6&LA2xHS?q2Xz! z?57Vs1y`eSnK!BH!fw7`xd~>uQBr}Itd&q#cd#K|75u`@GM3ALEZ9ZKpA$i$_~b4n z6P}XRov>H;cUWNK`P=vbDSo+r5%x)mas8~2w&d7S>R=>PaeOn=2 z?&T}OMTM}&Et#~s4t%TnVvV=Q)l`_Nr6NUKM5cz|#mL7*SJ`AJ8qll2hULg*kZ%y5Ti*KPQR(YcJ@@rX}` zxG-eZ93-XMKW{IQXW&m|UY8^lif?5)V`n)8&DmBnQm6`GarNX$hz}a!TiDzZ>Pd;^ z%$c%Z8}i$5c|ckyTQ}&G0A&%FKE1>~q`>R(3*qhJu`;ut6i8UIW&XITRW>?S&E7h^ zOFyX+&4nYdX8v{}qX}-8sHxL-V2!0RiY&HRam0Tg-&Skpfz4F`sLq}@XBX7(qYELcj-q3sZ~^VzWXQeqrmV(#G7hM-T`;}E9PAZ^IK zV}bWK@_7i{*}1rGW(Sy^;_`HWbO!ex$ai{uylN^1C{N#-iUXHiWUE3^((76nLvue%N-Z*uu?wG+jcKJ1HK}x(Z=Rc95Mvje*KZ zw3P$zZ#J9d>4(Ozk@c=5u2-jG0S-oTk|oGG2`q{;w-8lL?Bh*XAM|DUl_%s%X7rno zh?iBkN_AA5REG*Gc=K=KGU6YP#cHn1nKLdjeFkT8#N-Lc)_No=Ia6zQq*R-$_kkJx z5;(J$UW*d;0@cr}@MLR=+0w?}0|o96z>-Xq{HcSXarrmJwb~_ygmT3*sAN>Zm&917{#GVK%va(G#CDL2p%l4f2;c%vC&Cl0*2p^>U1_LCe(j zYIg!384Kp3w4}5vwli_3b1OzN-E3MeKb>9MTa?(^$9n{OXru~B+Z^bX-`=*>^f|Ub zyFr6`AO6U_;_dobcJvN`}HA;xERdfq(9yK6W3}r@;44vM6MesQ0u{<)%`DA z^a?ilI>G1bimW+Sh|GZ2g!#gJ&RQfD%YFF06qQDJ30Z&vWXG@HS8>BlCeiJiNPQ_(GED1j7w zdn~VNROkn0nSuwgLb7c6&`Ub2N&y!$q<3vUg-EVyen*YP{f-**=-H00cM^v{k_V{p zF3KUf@U#?mS7rs}<~T>YC}aPo+2=5)7~K7Ja`~Xa!6_{e2&AEt8548lTiz83<{bTo zmL4P>r=^|#4K2Z{B2(w+aEC|5>u&Vg#_i#ZXy1p0UgrDFf4zM#itw=8p{U$vZHA*Q zZwFBwx}fFOTZ&xN;K)J0YDDVRH42vS{m$>9!$Q1Nh zT0hx1<<2Ivua-92(u6fOyk8n*mh_LIjxz@nD8m?ul%zb(XJY-|*HA7tOMV=^+1|9R zK z+&putucyM->CBSTsv*?jvR+Mje__eHEqJ_t?Jw{+DK8pN5YKWKoNmP%rUh+7_`{8WgZIP=MwfwK*XlRkK zc0bAhOh=S+yPR}?lGi@he*)J_NOO1q*HpZj@m0>8L*%5pyIZtT%u3?#~}Om#KUMdhH1yD`dGV8##GDtgDH=9%N{cb2pc3JH%1AP z!pH0)!DWE~fK?tm&z3~J?X?w5kHcu8>}wQn$~g~{BLf#S8q8gCW%5|!uK@~HK2rDC zanud3z&}6zNLJTC%kiH}F0`pW|4{66mxYu%5CnL-x1bDSd`HZyes>u|&n`{j1)wi9nBA9x^x9e3e z`0iXWg6yA$9V#{M*61KlM>B~c=otcKz@J=0J)ifd_`eRU=ZFWM_qI^iXZhxyqim0? z%c?aMr<6)96Pmi7wM)^_(MlEam$St?F!Q7xzhGY>Fpe0*a~E#>IH+{ZiKlTGt1P+%H!mm=AGs@Qde2KKbM*LeB)6 z+XUb#OG0V6BcYZ`<TlV&&F^=B7 z_sYO_C^~09dNx%jdY(CD%PS%}e~}tm7Y(*>eG-%bA{rXse}abkn^P6T<0VAYYKY1D zVZas^2qpO*FhR&;W!V%}&x&BgL#ZDi(NovYvoD|g*n(~o@yz^3isbvo$1MM6*mJV~#s9#Rfs=!sz3b_QW&PLSs-s+MNBhD$r$_}BqnXI$0fV77%r{{) z78?D*fh3bC+e}N-4nMi23`Ip}Ol7B0ydGdF@e?LkH>`Te-=@~cGXkoqm<(0+>WJiH z=&L#wFyo#H9d1bW+VNB_dFvm}5f~Vth%aCi+melUC-ME~q#lP|3e3aIbh63~n}kjI z?t{^G8}dblgJt&B((3i;&ok;7Db>1~XT>{?Pwk)g6osnV3N0KGzgg&yat5>ytVsn2 zSJX>PU|KUxP*o?)isYS5U4nK-E8pr{TSZfy zc4wTM-V9LJV+*Og&g$6hw&B+yfylAU>`iwqzMZ?qqNCI;8(z~nF3huD_65lT_i%CE2Or+g ztINSW2$0t`45lp%5*^qUnR~Q8>Lop@5E|ydt%Xs{#)Qw|Jix(680c$@m6TBD)=mZ^ zvbSRrc}oRG4!Jy3ijZ60vGwtSg!gkeEXe8UQ$(x1Z-UjUcLWnL&zDeW`yi{*NL^*0 z*e^8OBCL7?W{JHF&aJjF_C2j2ipQq2vmEP8;qLY9^L@pG8SP>LBpJ;J3LQ> z`WMof#m}d^CDW%dnvP7AgPr=mp#@~@E$)3$t$e$~CrK#Lz+<|Ne33;R7KwJC)y`%d zIo5#iC;uJ*A?z+kzcu)WkT_+Zm3ai>Yy{TYG^y4$WKK4 z)1$7XIKDtmg`V4*DWzXpcGm(!&YsXTGu06)?QxiUAU-Ev2KS7u7B$*=o-JhiNd0ui zUG8hf-SvqtD;v$7`>xuJK0B(+)(T$i4GU9~*;q7uy8R)8n0DDe6|H<(Tc%kOVm<%om3_T0#+miTuSE?-t@sW-^pbtILteJ~Q06W}s#w4NO2yZh zf+R=pc-tqSfO6vuhaSB>Q`8*%TIvj7zM60{1W_Soh_m^{I%(|ON*wTtv$G7G=q^c z#WW3Op9`myg4Oer!;)Dckn4WI*4XTeV<7nju)QEOP2oYyJ`-jM%@kI_IXKu_Z|kh^ z@gv*UqqnZ%hs3e)tMs7cYeqWyW1Q}A+1-hBcD{3-m`l!jQ&5n{tMvaX?>fMm%C&b=`}!*B3%U>ofq%i zd80GVefQqizIWgGz6AC;d!OvRv(Cynd#(Tf-&dz9QG&*CXLbBkkbLoecj@L>?E^1zZ+VtdGt5vV8Doxk zyShBmD@tM5J4AVnZ6IhWM){mIf`=~?T%zD;TH@_P&UuC=gTTE&q*^dcau)`tFh3v@ zLc;=_BdV8EO^aHTM(D#N9Fpt?_`@UweLvz;VQ#iM_n2mM>*SdoM&R32t#i}LLK@vT z+^oWUTAJhP8)cUF<`kV6kBuGuHcXP)dWQ05si$b!j;m;*B>FlYZThe@$+{ssKhCCf z#BHkPS;sY6?_}&UZhM)c|0q1tg1%vtVN5B2|51^9Xtr3?VWA_}k)JD^GKWr9=&=;I zm>hmPDVT=`l9p3>>4Ul-gwrSvW zHJ9UjN}zCRQ`GCGj@1Tx0W)EdJ!PX^fpn-SZ#(mC&*7-nKE$kNVXUrh1TiUrBE;|A zRYU9pDKWd~)wM))afR7rS+7u|B2yN>k&yO86U~A6Hh*-W2%q5YMBY(f?>f%o;?%Z! zM&2Y=?5Ve~Fxyj4Pq^0#ptD%SDC2q|x$xck4|;}Y`=0AI?`rCv#Jz-=>hum~r*#>v zr&N^$dO{4Y%5igFwO)ZIFsIOFwg&LuxDxwzP)<6vXq(0VR?>|6!FVsfQLb5r;8ebM zji%=V+i~b^ZzbdX`{b_gF9>IVClZxtC6c?iuTs+#>eAP=wYoTuxdEW{nD5v_VmX&AR>*wY+VYdgXK@dsri-7JAbd0tP2ZNPR@<*pEgM(Y zvj-3#@E5#K6qtARWl@5(gNg>LU-Dp~WTRgp4{9@%Rzwc2?|ld<&{MLyKXMQL(k&8w z=jGXY7PXU7;(;C$ju`BN#bAQe!f&9t6TgLl2iSz;hc_SoB|4njPQ-uwM_$tMs4%bO zAm#SkzYom&eJB4jr4tc6{|M1$EG3b!;J-{S?N=YEItnL>13ZYw5yb)YsZ+0gI=5!X z`96*kZ}M1doos4c>YPWG_)G!XTQRlh-QA!RHiA8#n>o@mq5VP;xYl(ONfevj@damI zo`WG8sX95qHqnY{9#b!@(1tILKi*T7nWT=mLXDc=7+u;I3)-~^UEg)F!>^T#U`6yW zq&)9_CaJnYS@l~8*icrB>-mFbO3eH-I$~56+%RVe1E*Xk5)wu>^z7V8jdY(%QKUzgFysQP`L~_*{cEqoE9IRHX6*f@*cM&CFs3R9GmumbX_4TKRor4N`#%4 z(zQs|L5Yz0ub|LM6O84J+ON2yWN+$ZueDS%9A^fb6xZ80@nNj@i+WH0RP>49r|NHS z)ZEidJTkyi3qFZeHjpuXY`*rLAB%QDOl)QE~1-(SQmf*6pb-fG$HfWOGty4srXIaEm{sW5D-Bbq+xPvXX2w=)ZES%(#>>;q4s=F@{A&I) znd+OMif3`ygE~L~8V$L?zm$CcMzW<&>djdHoG3dvugBP()dgUH*a=RN5_eRi%gF<2 zJr;)|nggJQQ%G%2NDNj;pfje~QE1jEWn)YxB(=f%?YN2l5Cb-KB2+$!w~FG<79FBX zdeu$X=IpUfD09U<+G-8GDthp};(`~_G_zM|#S{`O4ZUs&(-TIg`>Uiv!BA94Q4GdX zMXNheHbkptVi@lQ?4Zg(BG(_N2(C>2iTKI%Rm-=A)kQAn%52T)E1u>FrKBgCh=;2e zjI?{m6g?>oSpKZ~-0n(IB(6W5L!sLU=Y%H2)^wwtEE<~&N>kWd6{ck_u4klUa>4}b z*zYB(=0=8Deb{PpO&wH&)rN6FmC4K8_ef)4)e(m;98e+I~@p4tYg-m z0z>UL2ea;_#}m-NG^nq@oC-UFW67^KMxO6hPW3I}Ts`SxbwHQL&3ss6&1}s^-3u2g z)ZLHZU8^XL?1*BD8UtOECgWKd)^&?nWn1xa<_%e+pFXxeu;Lwu%s}=9*S*r?yX0ik zQQU}dFL_H_byO>KyBrGU*^EIf1>v_p`a&JwNxMY%uL+N}*|2hgrGyjI8TL!}hq{48 zTIf$6Sp4i4(3(*t?LnJRYt{;X#uZ8ETGX^+}h}jK^+rs!iThoFcK0D zshj^{Dr>fi7Z2eVGMJtrxxH7ahocCMM(egaS53C}nUnmTh5`{A z{3q-LWTHP}y83-@zAxW+`vX#zZ>#*b1^RWKy8J-|7x+~K_m@q+$^}&LK*HM;n5faM zu97jHoim{qRgWG)<^TX6v;|3M<&38pY6I38lcJ-l3?O&3_gqtrH}qRw9RVIvDUGhxeYSFjBpSv2G5f}Xb}4o?8?Qec^l-Cn>Akz z2jwlepLM(M3b=vw;VtJTQ?0)8_w@yrmPf$)fa@zG*axSk^<|N5w6uZoL|i*j8`3A# zdcnbp!1c7I#KI?DDy-e4y?a=VIbqJKmn!9!>aIK!|l}!RR;@|!5A$fhtQ(%R}P`K&eyY>GmO$rBatak3 zxA%<}SuCyRLY$RizN1OvxSi}Xvsw)!$s{t4xLAYhx%oRdCx<>10$hufsrM75i?XBh zpI88JUe$0WlN>8Z4XnHl49XkC^xMl;3xN4ikg3F`Rtw$gYs!6?G8r4I6nQMRrntpI z&(*#?a9g0375gsy^f+Ydl>fA_Q)U^H>LtZ>TQ$GNH&RAp6r8cr^Ov3Mb2jXG;{%x) z+zewQ#PbHX8c zxo>h}GSonIgVV{LOzGPz_KD|Yru$Y)eRYk=oJhb0{Q-C#8BE^8oStU7#63A!9XDC) zq}#S!)sdF`B>IADYTg&lY>U@EA)h}l5U=m*@6G=QB}!_tioQ9P(6dK9C#vgrhU6rp z*>$w;9{8mYb7#M1o6mUmERLeX9Eoy8J_}6CnIjF||9cr{f94jx&qVv@e~QRLp*f4g z{u;a$ryTq#B2Q#P-=Ol`+CZ#@=<_Ub4qx+F|E`UaB629^vVeTs0m*L*HotHA<5lig zf;-XwoT%%MLZws%nPo0hCH&XPFD0|7=f{;ii3Y%2bUC=OSwy7{>qOtJlsGE(;nMkR zL4^c^(V@~nbapA7M4mW2)!+uD( zVeY*GJBwX9N>DR;n^e?WSwV8I3c&hYDgpPAtf+-nib?*+*2I$zhUJ>pjUvb)fH`Lq zCW@hc+)GXKB+%Ed0%2lL3=hoOLVFqpUg^AWiJ>kOP7E+J-o>2{b>6fc7?teLew7ff z=j?ONs1hV!^Cqm)84*}h{BHAngL5N}ZAtW^RyMh}HUd}$8(K+yK2;X^u!z+M zWMUD>keXjSc4=kT-0nP{%Lbd@CFG(`T*OPy=e6G<*fR%&V^A1=ckA{0vT&AN4Qzgh zpo^g<&{vef7~W{jBPBk`s2F}?+u1D%G*iHhe~Z97QM~M81L_T6@WzI;@N*C(2-8h1 zg!L5X8Kz1lO1t!~6+tw4NO}A|AUEwA?NArofi7bBUI@}8@oZIe(99#!!7(3;ndwdL z>aqpCEg>cB_0^tP6K^c0H?ryQ<=gFq_97Q6W_Q*r*>%D;iGqtTU^eXX8h79G^P(K! za{yK7elRzH-9Pmy=EF&|Sq;0vOEan6EnnUk4_!0_b+rcij<{m;>h}eL7>G;OFF9JH z8mdpXhuIm>TeRtebNYI&Zw+AH6`u*=Z6avAU?+`trIM|7$`n{+L)VdbmgU#(t#b{4 zqCW45pOXTJ!lV5n!%jXazUEa~?0(=npoi=N9I!rJH51i%@Yd*|ClpWqNyx}hjidhF z8)YM|Tb&I!GQ|cd!1b5Q6QXcYw2=-@pw`ryzxm~3Yr|T!$aU?xu2b2 z4zY3#)ubuR!cPlu&Dx6G9F1R_wWf=h=Vl^Q-CwsMhnri}Xf7S?EkSlrOFC6g%}=Pi^rp8gO(@cGhD%AjRo{|nZd4ckNITtFU8zW^c$qu&6txX zTq3hL5$X&!*lf5sZSF2sQfGPUQ#4n;lDaydma}!%Axjg~k#E>bu^_$BM6`5+&nOqU zKHBg!%aqCuj0P(qq`2E|uafvU{N5k^u*~!;W%FN;{*yXMlo#_dspc<_66q-GFo4-v zqS&h|F<;Y8E#?6)^mGWVpesnT|BoG@luy|KI=E^he-w;^NAr_VQVT@kNC6hqY-CS- z#m_B}%no&iCQC^TU3Q2e`*YVz@^?RK{hsUC=;QgHNu&=F?Bl;;r1?3sIsOz&#jflk zTg+Si3CE%yYqqC+-iS+Fkg(XGUxd)|P-v4E&6HeaTH_$YkJD?XOxf_~RGyJUg9aOX z{g@47^ZMpooDwtTpJYuhwMN2EX%Q&)0F|8w8CbMki~0Zz6^S*3j2>hy=8mDoK;6at zE5hOmqRey=M>Wh)lp5t58S8tlO4fGV3pOaz+XEveVP`QJRZNA6HC&+?4~lnl0~raCqLslmR<*LMuBL*f*t&1_)TP(DH6aldk3-5_k6CK znzS&eH4*&=yyD#@b%^L}H;`~T&xMet!>q6{CavKt@vgvq(M`Gc7GW_3%CfBc0@= z3%Dq!*2IL?>oD9gyod+wUQ}>#>LUXI;uMd!qkt}uT`J#DxZ~}K2ziN#XY$U1->$^0 zk>h}hH3E0y?xtVa&GG&Uyk|>O?`YtM65WWNoBkIbt22JlJqc4v+9?$wp8@GtYC$*4F`wgW3UeA&7Iod;e|Fw(2(;lvJ&8u4DH z7^7QX&cRXBbx^4R3w`-MutUrYR~?RB|gMGm3z0iL~IcsjPqHHCb=ff6Gt#9N|d5G61)LQ5+1ao!Z!Wn zlILZIK^e=6t2i3pHWo|;@V@qgTjigX-Gyph?!yxDQDTOQ8|(AlTyOkV?JTDSkBug{ ziJ8)*?6XPH%j;yZHJ6{Ra6t{(j(s(Qbq&~U$s1yBLqjc|8vcNxP95$Io%~ z>?D^`7!%0V&$`e|Dj(I^DAO`-4HE`6iJ#Z>3X5@$o;C`-Vhv7FE0;7B`)KC7*cj~*&od_)NAZrNW2e$ULzSUE zq;?8YH^a>*54DovI2$1_M5I25rU14SgWh=>_r0?8c(3953TLMa=3V2Q-Qq=Pj-c}T z22(hlL%2GT!x(^yBM+8|^p|wvKl<~3-}8gqXX3G`oW*$6J^BubNzZE6iJ6EX6PHgG z(ridQTgyAbkqb`JQ~0ayCgQ0GVaT*4oz@yNBSl;U=MdHDxH{m&M;{!XA4ZbK=Zud` z-$f7kmGtlVGu&blRez{iTQ)US_JMx);Jkax)?#hz>7<^pVWC>prqHQFhHKoSg7Pum zhj+xyC$)0@QUrLLZaz~VMo;W5*euqfhmv!SxSoAmTO{0*a))47iV58Z7=pbg?O&)B zOnlj5bz89Z4-Yt*=J=`J{aFxfkGs7-jAot+*4rd_ONw_n$vt7?&pPlga7x_U3)Aca z2e+rM!TU}8V=G&^I^{Z2yefKG`>_gq)3E!Wf14SuZ{{K5Jf2O%Um;0&GrPGz9(lFa z^4rPg{AOw^EB?=)l1GDRS4*qol+`wKh%d6g7@x*pZO8t~JelMF55xKwyP{&!ErMk`H9Hi}U8o>;EttJI zjM=|P{Ap_YndEIqm?sriD_dWJxAB}k7%M(~nSbE3z?=IbBTwRu-sGE}P)zP~%)NGB z#cE`@_sBP-5d^~UEavR=t@QegI#daJAA0I^!%N zA$l`WT^)~zj9^*+?uLK+NAdn(f=6v3w@Wgj-~R%wX5*)kapZJ~wys>1z+)B1ZfZ8E zK^2BCGb6I?XpiKa71+7+A*ti>GGcGgfSRJiqM_5#t^Zcup0(j3=Yz~-*w?O|7&pTR-cQwFG}6@U(x_pkDoFh40s&XV zBMK81ca(TN%_ADSAvREwU9O)GdCISw3~hvZN)&6=hTdBNBZ7 z%CM;wqXR$9@`j-R=E`zI3@?7j+fI2+;PUk#;oz>% diff --git a/img/explain-all.png b/img/explain-all.png deleted file mode 100644 index 7b49bf4481939788d53b0fd0d443b1e8e3ccff74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8446 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 wk;Qcv5?IrbY9w*#zr*(KKAc^w8%VwN(5n%4 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 diff --git a/img/g1-region.jpg b/img/g1-region.jpg deleted file mode 100644 index 99f595a864c3c64664fa3aa25e14bf8fb2053bab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19644 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 TwYrn^SI^)6zw)0+A7}m#ZhKi^ diff --git a/img/git-status.png b/img/git-status.png deleted file mode 100644 index f93b1c3d6746181fc7b54b680d58c40c5b555bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109277 zcmZs?WmH_j(ltzg06~I<;O-vW-914EcL?ro!6C@t1PBm31b24=3`5Z1?(Xj2A@|}$hJk@WlarNHg@J(+240^aAppO-x~c+!Kd)R= zWyE31hlzH9H}IBXN@6fDRbZ3{(ZPXjX4><24oj@wp8q%2KZMf?ll;FCE+lw*dh&mR_h2;=9R7c! z-xyuRSMX(Ap|~H;nWqLkKQ`#YF1|+zc)U#2wx%F^+8rCYdt{qh*z*8e`C-#;(`HMO>J-)MU{lRGnkM3f-) zN3X8OgxzAZMmm=b&F%SiYQ5e3+~KnCdCYget6AqEw*G;YuHemS!+^*BTcMYA#S(e0 zt*-*3%J2tO4>jXgk>>}s6jnnPo2k8T^~C{g2ka*FAs6r z=)@*P2L|}@>xa`oS5ZCh%ROp`*3&RlVt(}{uWjPpg{GR;t2vvq$LnP%X~2UqShvN! z43&uY<59=6e;Suf3bnY=)5GmqCmi~~yh8`GoSfXJwL~EwcdNzbI-#qQiuSKq*{|Rb zB*CwP-G{gCgicNHKQRX7u)+=Y|6|-DHEH7fJOi+`2(TNX4;>w zXwb~qFK-zx?BP#JNH8fAOQcas09FMF#WkSI_C1TF=K7Pt)6iR_l)-%^2%KD9-A!X} zKQ_tBHd5mL=SzALVf@?-r#5wwPogt^gEltvuA<|qS-o6O`)m_Rn;r1fgrhf&qyxhz zub@!Vix{P{+8w$%uE1Jn<(O$Ro*zlAgh2*l)$JW3^=9q-{EpHVo$_x$&`;9#dW z?IsG9QW{svry3j#6=dT+J$sd7!vlhjA0LmfYvYr`mvUi00 zXUvr7|2>5RkC4cb6lUFgP?br_29ev}PtJe1ra>lZRVGsOI<-I1?EW+o_njN>-mF1>MMv* zC0p2!DW_>Qj4-#{K9k?A+RJ@+{5MH|$j{5Y$wX{rUNHb@NZg#x%k5v#O@`*bxHjVu zA;nE5Cg~R3E9#r&wS}*sxAiB3HZn5Ood}FY&BO!GVWfyr?ugW14FHcD_h3e$xjmV< zk;7v1WCBg!g^{+2!1;p_j;dqp3oQ1>zy2R05|UBJWqmm9T9Z((7Y{|Ag~-1$d!3uN zzq+nRH~XrzpMpI-^&gTV{+|PjMJjkkYJ^AFY-f68`QEICv%#U$Ij!PRbC>oLWUph9 zuV9g%Imvx2UH=DeZv+14i_1SGWpdy{Md3(&PXb%dhXvR@j`UiTu76X~v+R!5TH}wq z;o5qPkUky$gDJEB+2u35BL5&SQH1ihIM1N9m;aqQ{Ld$z;X!uYEY|;t1@|cbHGvn% z0YK;KziVC>365=X`u%cvJ*ENwMZXuL0i3soD&PEJZS&H>$m6#0UVDVeuhnlsV(VtM$;C2d z>uz?@>k6R-n&@{VkmDF&lMdRghQ0nK1feY1j!q6+KB`}Qyn2Z-?^a%-SU)+6o$qg( zFKme-G0km(ThP-MXt-;Bj?+=$gy2G}x@!gsPv+KU;Tuxy;gQfMn(Q*&hQTm2LNfqY zt3QuX++NK)Y@UyZq^5CL4%S*tm;pG;?zAR}FXG=Cjn5%19ZN*t6ONvmBN09rM=oKu z(iwQR8csThNa{;=+q~wAsF@ zFA)SRboEW}Y=H7?B^X_PBui*B%jYOw;J8)IzT?ro37Dopx50kAKmqr~;TK#dl*a4r zbgd?TCD(o)6Mu=70K%pgDrF2_P8+hu5b~tZD5cNX0bi%yYQDk20Zg4eZ{MPH)V$Bq z1O$b{rk7acV?QYBmF2xhuiJ-f=sT8jUpH+~Gkx}Sf2{EQ^k_c%LyX;a=7Z0nX@6|; z8*G|^BziToyNlg3Ahts-v;AmXwua&>+VAAs?~ep-fe+2Qf?ijfL9n#jeVa=4n#Pxw z-S(&Cbac`mfNgyCr161`4LvzEIAqBN-E#wE(UWz|$+2)Dqlnh@>+Vd!fDZUi!#FA^jVENuPe75uA&SAmVdE^PcNDNkT5Zxm-~ zyHITcAhE!p&0Dp>UjGGxHlsO)<0g~^l$3>U&G=SBus0glV-tZHbgcjWBnM0*aWI)t z;rCaZ0w4&hHoIEUf65JcN3SZ0{GN&KHS)W-gV`E|dfQnla&lvEi0PUfZ|1!Klh@fs z)g~PPp-D{Is)I@NlsF9PalbT5sJm&A;Pr zujJ|pokVa(7+v+HUWog{C~%$bk%= zie%s0GwreEBkth})keqF0Hj{o*W$3+L7d5~h6W58zs%lDev%=k?kDjn{ada-pOB!Y zBE%)%NyZTOejo~~eC>DC{6qJ4E-D6Th}+<OXpdw}spD zPq~raswofpZ>3r41bJOfYU%E40#TKj{x^Fl7c$Db5fYmPz+=dxa9Qhnam9OEY5*76 z@#(n(QWooFj*aW(fQDm|W6CMvC5Y#7ReMW*q?Fl3TkIusuYAR*?|SC+OC;?0Pb3Uy zsug?xUaE1dpMPF`!S5?*zIz4Kz>{VA*>z1>npGH0lc1c_$O*;gsA;>D8U_lZ3Cn~C z!enV&f#rL=nArSg8e27$SZxl~fx^RwxkZTOh==CJxZ9OZV0aMDmA0Tc;}AT@!JYMc z2UD*PGFH@TMk#0VYwx3%TQ-IZopi$0M>qalEf1Sq1Jbq1a$69qqg@YIsbPnIO7tp0 zn10RAPTo(AU}=GJV^Be*@+v{S>#nNJVyAbV_ocPXCJ0D$?Pe(d zWrScLrJB8m@V{q$RMNp2uMYXJW-YyRzCDt9-0{4WmCD|j@mr=-`b2)r|OwxQ>IWbNn>y^nJjojBq@X> z!8eUWEXOfX8^_5oSqKWq5+B2f`^V`rIeae>3r2A6LE`~oq2d>|#;pS-!=f-@dGhwj zAD(4U6xKE7I6VF!YKzbF^;O180mO^<-7A0XVV$Gcl!O)6U!z8*(9vXa@k^VP}UIfqh;u7V6U|sMg z=y|m~GsGL>5uk*cn1ga@_`yAOWEc#oqGAJ$xN)x+kgMuN3mXli_g9zv9xtb_gvA-! zAI=nPa@LpF-y@y%gXkkz*Yn9hg4jrA%k6&5V#d+frWtd!R;J7zjRfNIUVVZ#rQ)DY zGSN8NYvNC9#l8Rv(f!(=4;%Uy2Yc z&=O`j_`Z`vGb$eCnlB_9vqR(NB~x*#{FkVJd$8tCaxn|h%sSl(b~zWUZpK#%;uZ4V zGrnrui0=RLVU(;F>kA=Pj8tFm_kgEc_fixzwbWj+IUjInA&{z0S@+=KEi{mcHQKM% zyIsv%$`Iyb;FpSk0(aW_4>Eqrkh*!=dW*6_t3bWQE z{9ZL)r9}OHCQG|#O2}X$tbrVGM7`d55|sSO>ZX}RKKJmU*y(Eq-%RAiawFnt&Il^_ z#8aU-IwV9*jx07!F4zwjM~ed1Zr%Jcqlip`F$7!*Q7p{^u{}XEqLo#!r~ao|V*ZtQ zXHTajCURfR&BZ+f$QA3XC##RSj>*?MJeSF>`{eQ|wBTRnVP<4hMgZe#WKi-K&> zmI+^St>^!S#j{cA_h_Gpb%Q@FiS_>_!+v=_VV9y0}RA@6hT9+?Nzhl`)<&Qj}`j6qkw!u7YR zk=wRF{f+nCSkkSBWJ~V9kFLVwXPflm!p@H03LZQ9`{)#YsMhHd5-WXJ%cPugKMGw! zzhd+X`hsEnmc6t*8ARbUO*tB*lkC|5z<|RdLlv3$fE#L3?BrV8TU{~@&whNhP-<)_ z<}LeDbd_ZsmmYFetXN3p&s`8Vu}8k?64}=2lJ?8@g?sgqX2%+h!hC`tn-sVOgikLb z5ITZA2%T5gyRAeUyEb%qK7)*#x|9&LDEo3gl!wXch6wg0M@SR0NJ?Ji@(^_auSr8_ z41z1n{GJ0m3UHk4le~t()RuPnM8s_6ZjjAb{#=JU<)-YDaFQsdQ z#bo-@N1*v$?+YHSSOqs`7a0@h(9W2K;+s``7n+pL*vI77mfTin+#cfMb;){g>UDy*Xug8X};zhl33v#5kDX zyihge3j|@{qg@kw=i#4==0$m_;i31eIP^{T+SrO&A5nTUqjWns5D-x zqzp`XuH^5Y%tR+yU#)1dHNxNKNyqOR`1^>B%{N>AenBl?VUeeOZJLaCE)9dgPZm)c zzMmys6dZ?X25WQt_zd34N-LOA9plp zur;n6Q9`HdK)!F%4D~_R+wsD<_QV1Brohs6!}~Lm=Hm_&BrIa2Xrb<);0!|3*k+Go z`wkUYj#2WiM&1F8_u6im>+^2|&VBbKd3w_oPSBAsH4XcASC_tS;-57THkO+$a&mZ_Ri9q@o*SNaHGT>* z8IX1r$*B;)=ABPnqCqi@SJO6d+E#QT$;5V$Twj;}!l3AO=fGrY4n&HU?59)|*hVod z($#ERawG_C5vg$nDv9v-FBAZ8P<%47{zPNU>ri_*kkjYCqS8noL@St%%oJngRG8ti ztcE^3Axz`)46&dQ^dYYtIqw#v&c!uLO8K1s;W-qf3z?t};XorGP^71)PZ@1AwOw!y zJUIrTk@#DNfp$$d*H=#sJN*z%A?*}3zBdRa@ji>O!Vzwz{sLd9HzJ0SyG=Q=->vWL zkfrgv{hB0?u2YM`Jl9&44ku(h$F-t;;~io|?V5|BAAeget8l?L@Q!>HzXB0rLWC`; zD2BhlPCo-sk4`uLspwG{{IyIp9ymYmbW!ua3(h%hDvEz8N#|{%xWdGsH@6emy19~( zJG?{$v=>wC@w8);cs{`jgrD+}XctSgSobGJhMq%qHwC}5E|86#g<{&bIx=CEe9DV( zi#Z)XdP^kZe{{RB3{+x>Sa(aiEfG5nt4CnO>qbY6SGeg8ysSbEQA5K;juWD}WYUW7 zp!t;`_iwcg+BFuM(?)#maLkRGribdr-$~7ov_O5-t3ilOCTrSycI5hd{J8Eemw>JL z{`By{ro)Hp?GmqcHyw~COnZ7Ms#@;_251U?GHV(Po=T9-@H+J-+9uj=N^+H$CIop4H&2O||L|1C+R&LPN zOs%rRaY2wmu6I%?UffbTEcI@R=f#>x{#g_JkK}fFJWlo`-b#@LGVt_I#3SL@ylz@o z4tpB-H#;wU95bqHSm%l%`j}YKMrA(ct2g7)y&NNgrj#OLjuBIRH-zxZJ_AX|8o*}E zX#MCP^^3#a`j8upAQY@Y06hgN3u9XC-})1y4*tO zlpEXGifPN~37VMSn2M`b0?7gVzy_dEG??O4nMp+a9Yka6=I@=M=tC0%h?ptySgD9p@x~>)rB*&Q z!2Cl5aq}&+kBVA%prBiTAUnYSXATjV6(-YP*-*zR4tnOqe=FcwSx8tK5atqP0tFkl zVyTW3#-)d)G7$|)Z(DE`ulg416E!+D!*^ZidWu2=Wm4BmDJW{HauK(uNrhU^mc}ND zpvA`|2nr(;-%+`shL_d%)5g+%%PtA?`hwX7pKX_s3h^;Assf7z_q#%5tZs_u=Gh$( z@QznELKPhf1R7J9QDJD{d zaq0wcV{OuM1XsVNorN&khH^8#D^1MSwRlOu9?@J?K1NVwyDiz-RSBKD@W`TNs2uM(5L z*>k`IDZ7jU4m0IC;b zHtN;vM7d2|rh4qF#(U1U!tDOSSy=In0r+=Eg&R5F~ zZ0rx6=86egCzFWIF&qDDzt}um6|Xp?NX4hOfhSVj-0ZwLs9K~TT0rBq)H8H})HF${Ed)ER&3S z&&)vk-7!ed)?;$>fL*4%I)Rz>GtSa3-$ynnpdKXCOc8Wz`K zRt#G&(vBYuQ5GvpOqeK-r-l*X{ja{b8yR=aHag`|(a`Al#l+Hn=Vlq$@pOwZh4hZN zTCf$s7}vky?EwwFh(5QG-AL17Iu#)eyACP#i*O74P@&%D(2cRX~4&dBqOn==3FL}cpx<+!Ztmh0`7K;xFxy9 z!n?OmcvXLl2=$$BbIoU(VW$7pKPoxkFfnhYU0bapUESNL^bbR2OXHx5XbPFvfncIx#|d8HG}UjpwgHvu9JxmQNv?)6TCzDEB0MsKgW^y_c6## zrqm7yN^mbIGyt!Ty!w@bF+wY?lDHvs6PgMI=nlL7y%)ZDyxLqrH)r)plv?Jq`a@TV zW*Nha_^>$gT_8^eT#rND7QT_4raQNkG{24k2cAh561^F9WsAwfGokYhqsEFWYfGKk zMvp2)VHFa5OWgYlyL%oKj>;B`4Sieg44V7^#t6j1 zLy;FsOy=*L#wL*=cvDC^@zOAg6QH3H$MvA<#lV5pt2$3KYK=q~m_zH(u zcnO2@p{LIIZ&pibCo{O;7@4GskqtxnOy!NNqVz3?g2~c=U&74xFr9ICa=fRPCsC`T z8`s^p<%sfq_V=!+G@ZE>2N_(S+mQ& z;nm7}s%<$NmA)08Q{T5Vk-V|R)6}&Xs}lp2XEh6X zCZj;!0ubhTQNLtOd5ceL{Nw;xy!I9pCl>-P+H_!SsNzJ=)wm*7P31%O?ulzl!=&wX=%}ZjQK@mF|S*UB|ror6_$31cZ4x z$z7+3ui+;X>e53if4=j>A)rmeD7TO+Nu+hk%MeVNsoS}vO&5bXc~Lv%gMB2;a3H{o-nk{jYO6D zUYR!32)usJ9L+Kv?P^Z9J#`;cd#84ZKkKqzUc|>VGR@bbn_uQ%*?$IkMD+F9E^^sS zMZe|$y$Az+yMc(++sZF#G(p0BHYrbo%D~>h?gCx8>TOC^FLn0zljbXL2 zIPYibPV~g+EDob)txLz_alms8u_yd+plFjhP^^4ki5ww;kqR<#!inqeiaDvtbsn|T zDeh(8w|SlGKWa}cdOQPwEQ6MTSAm-`Wp%8;bN84GDf5dO(E4~aKlQ6;fq!UO)Zl6H zbVfIXkXsYC>fO0=26YONKhVFiWJy^nvw2+k?UCt^aH36;%t5haj>sA_AC6=FIsHju zP05MwZ+i~LEBT@E#qb%s;p^V!rztm&j_E}b8H%4Cj*;_~#=&Sw=YZa$o5~Bj^Ajf` zw)vm zp46xsE?&9L@@*j@xrbX?t06oI?7R2uA@yh4Ib9VLe2cn9Z@I#-<0yf|!@UJHF3$wW zQI!`By`R|Qd)YfO!MMzqj+yd~CvN}(d=6$vm;~&zSRMpcsw!59-IiIGXjAhaF0ZpS z54a_;Fls34A8u10Zs#k`&ad9dDb3Om@=!t2^Kq(8HdVEoZF7b)o`WAw)_KnUG#Cz~ z8vaS(bFqLN%x3GRaqV;59@MC8tb+k%vpCUwa3hl4YRxn4gMTT`)NEfn*g`o~MdVi2 z!tbegh`WFH49aQ&M%&iEJ^tnI4272IO=VKSW zX9A779|+y71W%P^hzkC7BcLGc-TN^%jBuTST6B7H!wTSZKW3<-)Q=Fv&{AY?K>1_0 z8mA(pQHQ)0GFFFI{2;FasxWA?1*ehZMO@D>7M>)3=|5U&7daB>^&WM6Bda3Kb|15{ zCceHtBJ$?@Y3jq%z4C0kUwEl*gBb95Dnq}^WO9Z)^U+TKvonPe2qjpUtYKkJL#Mv^ z6QC4goo8iJ(`LE`5gFd|7CWgc6@!`*l9=@6k#Xn&eQz__w#ixk>N_75xn&TQ8ApPU zUmCNFyWBwXpHj<2A}<&DuI|wM&&4LH^}c+?>TT6Teg|x-`yuO_wH(UHcbBY5G)m>E zEc*PAN1@~7?W{w_M`2GHX)pmzwjZay|J{*|c87Q9Lp7Jw(}P>f!{z*lraQj)#dLN+ zudOS6?dj`otA%?Y;xq5Dge#Z@= zV?^>$1ay8nqO0C;@OZM2)XhyBg!28c5 z8g;&Cl}SRw$4`*tjyQ5IFDh~m1Ik;}cs2$9?EzvYmn!>q%)W-I4Ic=keZV2*Vd`+z z{AeLTC_oINRvEFus;YH@`eSTD!JzD{Gfuwm?N`+*6Z2w&y7cd!zRbk|{`yw) z)uDn{qrqo$P*zC(8|=*thxRJW;)@Iuh@Vq{1Z>Z;uVAIh@1FIKG8V_xEt$u`$03~v zN8f&Q1tTf|f?!_e7bM~@@KQ!kWP&8$C}ndp(KeK_jyw==GPT=)qNih(S-9mD>CXxn zbp2i*e>zJhfr%oOR6v~`zhiGn?8MAOtDY!Uqb1D$qFuTBMs2jDPGIwozs6Zopn2<= zrzgx3nwH+l@E-RPrG<-O_2;UgZ`}G%*Mm0WHQR7ujms2=a~?@0MVGJYuodRYFqA&n{L}>@+W#!WK;XIlFGrC@kc5b z$wzHj3FYAH6c+GRiZb{j;Yx@!zW!Q>uI#AUP-nrbg0tn2#L9a=)7h_Ke)Eo{VL-!< zA5x&CBbUiY0JXYgO~oEAW0lGDu2<)6u21@@r;nV(M9YVQ!?VfV%a}o~IP0Pim`k0n zT9@u@dziSfaK1N(aXO?TzJ74ja-3qB}Glqx21^I|@Mc5jSIok7j891xZ zd*$$b@>!rsk_K2{NedRlYnjNe8+xTu^7b_b zzWP3=1Q7@FbCT^O+u3v3tOqGnF*@eojOxkbld%cN{aJKe%0dd(lV!A)X&1OWcGRg2 zhjcLxO&EUs zMu1;q6dHZQ_9-l&K^DP}&u}U2G*nQ;x>@jPRkrCl=4pIA?OARf@m_X9fFv%A=Q1uz zXNk(va8X^kc?Y@J>*}@YYA;7V=#P$SqpBOdUT*CMD~Qao37SI2=dzvPj57%Ja@!w> z`I7-j^z(+UtK{>mJ{9-(SGCUSOWZBCHYvLi3nJ?42S>2NBzSLBWs*1Pg0XmW6nki!j z9;_=qsV`ki{Kvw(z|$@YPUYQKlAn>zKRrF&S2(4jIzL}d6W6cCr>EPN!9yS!hrUb) zDC6XTk-SXb;cm~tE8hbSAJp6*tqA%f9#3KtB9nwbsu!iK!3vY+WZL4TA@(%xBHK=z zqi|n!ecaPNCq>xYu;i7J3lRK9=)UTsQpQ zMOgIqGFXH%#^Hztm%CNxSGMEV zcT8$x0Q9`u4+{4&Sb7MA>c=jqwz}dM>sGWc`1k9d9o-+#{*2nOy!epQVRz$@I|7t% z(gUUKZ>CMF#;pks|H7rmQmY9F0(}kKH?MN4@Zmxl;4k-HIEKX);oA-Dd4t@?ynbr~ z5|ZcFS7|pV1eP~?uECV3<*y$&v%&HDXW{XNPfu!3Gv-KgX4x!OeKI~9L#(;)URQH4 zgcwru5YBFoEC(0hxUf(LJXA|?ml`rgy&q0x?f7o$bAyOVKs^=Db+q3u?PnyUY3JQ;d)7iLrHswW)-w^)$b>d~!J%HB>#R_4U^bk7>>W zm#tKB^I!61DCKc?%q_C12CRc>kNpD~*dod37QXb4B9EE~Lw9mvzHJ`?r0LbM?ZaF9 z;1AJJa7{XhjvVa!DeA5+O;C;f9_eH0p%3Lz(*ip@R#J>}tl|5(+_9*sffFxA^AmKa z*=U1;*~&rF_;ccM!SYbW#$s{JW&vj6X4dv{oQ=RTjirH8SrY#pyxf4=KwOVt0*4_v zy-sOT5{tg3wWf$X!QT#9lHFOg_J;@TTQ}WbO@}*J=e|$fT*D0Fgo0wzhsKYEbZ)16)3TIHX?D1&)>#l?8 z^iBFTO$=tj^J&qnDZxUz;SbQv{t^+viU2jAc^;E)^T+lqj`;+nfnEhxVOI2u*5xpg zzJP%1TPJHJWE>qvh)X&&hi@44i_!wjdK3uu@+Ys#FUKObQsB z|FX$IBg5!2-G*nKjoYH~yUbGulc)8mm2^0huZRU?8+0AwTYQ#i{jz=Jg^3mnX;d<) zT-v`gD`2M%)Mq!O?<+rl2yVG8x<$NQjYUXu-ZtENViyTt;;}Cz7p}KdbErjj43KfC zxeey+4R>kUp6u3jAr@mEHH%F&oG`AAv!sgW;jL6 zkTv;@0ym^K*^1rV{FkCm7SnpFL!^#csd--<3KNfY8-BfK=3-V_F9qXsVK09XBc&of zrcw!&+_j29n-Wdg97Cd3KE7Ohq{VXOaq6Hh$JW3(B@M){qLn(6)Jrwptxcb$=}5ZR zudhj!2>LN-Z1N3Xfpp!T>T&mZfoXWg22e?I@OykM)$bS(7He)#J5y?C4cGjKqBD zz2MSMAaiag3RRx{M*1133f!465}fb1)=kfO1r{o%nd~ou%rtVYe=imq z>9$(7(hkfNI)(bBDZHz4_lBf@^T`x5DS#+mVIlsVWcK_NjAG{Qq`xgSVK;WTmHX4I zzNioq#${u^y5My-dBAtJdjU2-I2k+ZgH}LH(S;f8=H23?r#Vv+M|gGRlelnnt`?*f z3oHg?>S04s)99J_qLSiT3!rjcXUX}Fq1LLc)@bxTigv}0-SnzYArtxC5KGxjwc!MY zqHM}ZWf84k*%~sj!rQQXg~~#F?MG6o``ro~8&NE&YOHotMO>e$ia0;h(N1; zU6X1RwG+7Ke8bG;VKY^qo~N!w`>5?+*z0gp%k1I=^X&8j z|Lic;5Hfy?Vt)85`3zcLHYU#(>}Z(jV;hjs!65i1dFOterjqcI7l-yR0QFtAZr2Yg zpcNB$Urlj?%R3cGAZC`h0NN^Gndz1S^e^|tF1~50d8O6Wr&K9CW9=5pnov(k|mx|z&&wTMVMLz z4WAya<3W>#mIl(luV$vYMw8a)S`%$(i_|49VfMbXPGO<1k7eFWDiU^s+))cf7JV%t zF8EW@P2+~ln^8QMLvNu0*&4fpvk0p4M5ib%XunP3=0v^{`&Rhv+1w2MStry%wq*V| zv3Z&^d9Ua@JvD@$J=?4ny1V%L`?&vi6H)K!30OfmWWb+(z;u-(`B^f&H&EJAKqnSRTZ zutcbC#XdU|;@bsNt&wnnLt5e1gk3CE0(VLUO5Y*(3@^wtH(GFqe}job zkX!?^T?vz6y?7WJJ_}grtWj_Fgn;kYos%k=112OTjyBHrmg*Jh^+G5d#FQ$44Wd^6 zHA(2`orKA7A_q&0&TvP0n%-=A2~cDS?>?*~I!|*{$W}B6Cs`uIBwZJc#9xa%=^*^M z6ASa@Q<3(s`6%tzAxSf&&w`Cxnot~-U^ckM#qI~uNvn6w9MY>_V!0JEmrJ-z%&v9} zmFrON^X(WV5>W~Bzs*Fwdtlssh7fs~uDNYQsk~>EyzO#^@g$hsDyid0C29t-$$ zkD%#)B@zEQ{Zu(601hB6e~KxJ8k^-T-|aLJSJF!kESY}gomqP-`h;Y~nQ8Bm(^2f> z|8OcJfS6)aHTvk?4(i|M)<-YOA%R;xywimc-`dPQ6X;c>fW7DH#CO|__yV4M_x-vW zNf%aj;;1O}fbR6oC7!fvvLh9;0%z_{~s=8A@Hdq4lUfI`^C-a)aw1?jj{I#8` z@a%^%OJj!>aZueF*wB1pZj#+@jn`{!Oy;2Ro6ATUrA7%c^(KR6BA}Ba;$TtH%803n zB`1w*fK%6pe>uo1F*f~Lw;R75E7~065l+$yQ%Ulm37~ki@Fjml%eg(tt1#=dTpo<$ z6VW!|cqqALUx>>X6JbgoJJ%eH$kv2b-pbV%B_Raci894-(xliWL`Lc=uA9^-g6e0V zNIG2AE*kXH!w{d&OqD`^v3rkM<8v)<2zjJM(*(t9zrFR3M}2Z{PYyI3N%nVXPrVj- z)IkV%3P!!zA>8FLk8S06QuFc}ko3Bkye>F@Y%8$Z7T8$Z*BOv=V@Ux@_o^e7n=8uM zbKC^jPzBjE)lECeB7Vy(M&@+R)S|2%M(jSNS{&|IIOAo)U3fv60go2`Y$XY5_=cS_wyy-CiTmQE9+Wq|u@p5BHQZ+BZ&y?<0 z`o#Bi(LDY%jJWap6=lJ5^hm*Tks)N%VVfY+l;99LJ@{e5v&dM)%qam?uXd0noJBTa z6=mvy(h;U3oK@!@ox-URa#COuLk0OzQ+sW(OMu@>MbGd+VkJAe5?W$A=fqe)5P}0- zkum>D%=q^inw`JAy*wC|Mu^(q}643o`cbJ!uKveY7VM6 zk{^+3k}(PYop4pA04_i#zjOfc1-l>27=z)`RZ4wukNuxoR)~;Bc$g5^9sm~qKJ*42 zcK3~0Dsioi0T#k6_D-iSdO-eB9I0ghrNq*+C`s!zi`Co>f3ZhbsPlqTUA}DOcmi{S z)r#c^W$2)03J|&M^s&pEn!;;a*U5M9ZfcyD8IK{R$8X~;!XNCAC!rCpI#d1ZwP5p#DDQShbwmV+edlit$N_;Y zr)>JmKFO6~(Aj?5TZxLE*YFYhFV|P>w#|S`t4z0Du)S^O%58vj_&c@(P2w2Gar&Co z6XCRX-LNarI|=h3oK5&n{G_`GTHfJ4IQ5rPyU8`w_jES(?8@d?J~dW|X$+FW*idZb zEdR7dT_9OtB;J-cQch`U=#|OYbji|m*rc_wc{*Ws$;g60<(XL_Qz3A-SqMM~NfEg@io5_ls*%|5WFD<2BJ)PSJoH_PoxF+ZeTE`cYvq+7`nlh!Hhwz@ zr4p&#Q#DnYGkP7yOm70$rBZMdQU|X7GD|}V*a@5#KL+jj5446yaPP$Jv_O#MxW@cL zN)~?Zd<+}HbbPrVBo*16k40hh%HIC*{<;Bhb~5xb(S-+BT|qNVFE3A+NBE%OEZ4}r zF4>^vfF~syrEd(D-@UR9^9NEIDi24CCrUFH9;d?DosZbln!OVhWjXnooMP;T(6wt- zrD+PmhEsYSkifN1AV(S9)HUlA)LS3&GfbvP)U@ReajEgG zH%V;eSv75{+Shj;N^_$&gq*oAe2#S9+}OpjIy!{id_?>}N_Yv!qNb=9wXgdPPn7#xMB=SEo^BBB7w)0D)nPAu zmmo&MZK`I9Ta(#U&p}bwj|BV2t>>{qn#}ld6ywcaKnLbr${QOrE7^TmEuje1U6_6& zVscrS?XB-2K^B6j)7k~{I0|^YBVDL_nhpM&PrHxiZ)U*#(!iaS0-(D`waM9B!31*) zE(j)uRAfn*V>Y6ViBAy}94|g(Y?Phg~Y-nFjqqNe#+7*zq z$`uCj;LMHJVNQqrfF-hF;EX_{3hoOmXKXU&Tdt;_f(I?KqGj|R17NS)UE~} za>vYCFiuEqwMt*`NQMt4ZAM6iQAtsei3WZofv4a^7MEP777q)fvQH3;B+Tn}7{Cxp z=|MZiukTggfKF*sNQMpzb=JiqjKjM)e495J?ABnvYWaP(w?jW(H$CC}>AYTbcZ1`P zAG0-5TvI<^@E7y~Xi}n0MZ5G;z&){clUd}!-TL$j{w(r$>VzkDsX5!KNHF6)J{>PZ z#ET*g)bytPhd+qY9BY9a>{A}Rn%@-Pl``mtGAx1Q)f%dz>y~>c-+QW=B#?w;TCiDM z!1EC>s+7Yf)X35oPn__3on@k%FFb6r+w+-fM;owt+wY7|PMPGe=(>i$r({Ktu!UH5 zCzz$Rx|T$9@9zj)ylD=lQ+KK4iIz zNHX5^k5DiXf#%WO2O#9xu4rJUE)?Hueb;_woM&e?fr0L#Adf zUM>BmeJV}6-62IP*AP25P`=^2yL4pHp>_Q6 z$IF>#o+-E9daETRq*vm@VEJ>;Jy(Vf9cnE!Pv25qvU7n)~(jc(4s{Psa30% z9rsD(*YCgoKAMJdKtP^+@<}=Ew9{^UJLcoh(#j1D+R%3E)}Wr-J^ zah!wth4MpaC~v)b_2lTIkCrR1yiz{=@IzU@e!bn#d1>?$>iNM3AB++L^0@7`+w8fi z*M2jLWOK6AJ(SuJ^L@9^(1A9RcC4$-F@yh-3}ofK76=!BXq~;7A{;^ z+P7~npMCb3z1ROKD5@(S`w6@sS(UxRJ`*2({?^wu@;@L@Uq z?DM2(*$R@4#yI0t3YCeQF(Zofw!e1D+4{n0G>0N1zg7Raati85y4O4Gn!V=6LJ zAwhUdWrk~mR(iHKFN;Fs!A`mt5^JF``^i`H-?Jr^FC-@*H1Q>rZ-AAgYlUiV)aFL1}YNiBF)Yf;7SSq0HebJXg`h zQi!ap^4INDMEEu16RZjmmo_4_q5SE!V;%u@WpJVA@bK7QNPovNMygEzE%MUKugVFh zo@q!=K1nE0+(s4qVCp9_?#IP4ZqX|H9jjgmI(61tH!Uk6eKl&)CZikE#afk(PKYP5 z^vB^Ms!zu*OqZ~J%_w2L9CT0x9alkJz;mF^8Ec*k&t?qcG)R+Ee|QO8-R6-wRQKyW!)pJ*2Orp;f5vVyLFQFgU1jHmp)P>b(B{A@ zz&tVe^XHfI&O1-Kbm?MA3j^pOHxL#uY0@N1h)4@Lf~YXX0cnW>%5x)F!8O-hW5lLd=!z-_l zr=RI9KmPEYbw^af$}{{sGDBbFkw%1V5wX_1-Gd5BU)p#|M-`4LA6yFPX~PGY-Zkw3 z!pE5&IVu(^8S>UVS%yCj50Cu{UcFsZv{)Ad*C!=FJ9qvrv*&y%7hm4UG??>Bz6w?3 z##`@}4`zNYlb0Huw+w4VlC@H(r9$W;%$(2tpuoj`(p z=01}yvJCbq2_ipqa8d>tzhZ-ZPQ$)lAa}p`rc^ui97)JqNRF>{l05g!vr!iuR|mOE zkIWIP!wTSzh6M$^-?nXA+u)r(eY$P@5+3>Ek3Y5zWr7+&Oe$2UV67)ugL?JqCFRPM zvm^sIGrUb0_eoyl$+5UlQMa%S^0IE-I{D<2Pb}Hs*!%9g&stuXj|S@zWQ8=it3j|J zF<2)cQ;;AmH0%R3-f6g#H}w@H1>%Kg0$vJOoUl%D?JZljwDlU+9c|E0o;=xlHssBl z*Oryezuvuj+x#F|l!;K$hYP|4jyiqu;>Fg|)u~gbs0$nfkswA)M$Q;twbTI!O*kLg z0@@y6$^JEK*4T;4u>b}LA~c4fpD)d!SV9xYHj_*`zIDIcn`Kzo?n*E|58<~9eug&f z5%!(?xopo#0%Y<>0rDKP#QWlps)4mOz6s&z7L zU9xSgk6oE6qY{Il0_wJgD;W`ZYz0RJ9}%}QORoSkl83O+i<-VP4FX+8j<-vb_g*cH z{3G8C%giO{T}&5k1VtrWK`$~59wX{TH^REQ&}$hXLFT^Md%A3cwU|MGX01L7xd?wC`x6K9 zTpkB0%qtLd5U4PoF$l}QeaAL=q}LNts!CN!C{kP+v~Dj0XMH78mamgB%jnp_qMiP& z2OS|1onk~gY+PX2UfbEm#sw81bQ~;UH=MAgUcgxxQ$i! zo>3Q-C{e*T!}+M6AWyi&VG*K3j``s@4q`=mEINY*4YKDZJ#`dT zDe5iU;i#|3YtyDpmbh>%pWgFN5YaRCrs~69ksCtl1Hwqm0Mc*m%b>AsEDIiS!`t`F`z5wYR zRl$0k@0Q|)#e(!YRKPFyY#C43k5G^5dT>lYhDft-_*cgG=!^IJ?>ptGr=OR~)sB{I zxeH1{&O(x}bQQU#eRp|v#3Y$GZ@G+Lyjn&rTp?qYudzPuR8sg|51qfx%IL+LZNq-V zLQ@f`3xX?7rRP>`dnf;_IQLvk9){rTjZlVv5+4<945bsFjQ1i!e9XO5AyUy$Q-Kdz zXzryAWxG~}Em$Grh<5bTQW<5VMQxDjh77$jcB)*{{Wd93sfrDPkdQs66fIds-hSsj zS-W<<{jmSWg2#s)dD)2l79~GfwDu@aNb!^kN{>p69yUz=D14MW6&mhsxG$*hv_chS zynNa3rvEoV-YOnPHZ18Oa+`e>cn{6DVM8A8lFi9mq)z?%lA}lwsa3b09lOYw#ZgOE z$)JU+0!yvc0YM`?kaXP^kG!PogpBE8N%+{qNw_}OBBoZcs9v_|Tz#L>niCKo$6{pk zE~E(J1L+yOY`qMiBWY!dA*mZ=?7Wrou^~Z?TC}$vdS%O1Fpc85(MG7-(DJ$=>)@Vo zzubFABP@CVl*a7M+h#6KTh#M9kz_bjcgJePc4kx(vH20hP<$`CAmFC44UzC$hI>|ma zb%BEbK?->n$VcBLg}bifv9PW&rYb<7vk@%zq$eMix=xw2oq@0|NE2B3iID4MFNOQ( zN_5|ER(AdUyB$l(wsZ@SeQ^7PeYf~T*fQo_dN)g8MaYpy3Rb8tSGDgZFAtj_LuUP8 z2aHa@70XoixU-F0y~WN!G1fHR8LT_r5T0>{@Qhos*=`%XaDyd3+R)dEOhw&6VpWK- zB)wsgE^H4f$-vKh&m~eWLt+TFu&1KrCtlf9!q*;1P{CV5v}l7}j#;+FibkFrm1xSy zITC}w2xClT9z;M|ZO2f(_sLiC!tl{{qQnZvpJbmKb0$6BtBa&ada%-_Y|Mh;w-yA~3H4 zuA| zC@3$#@;|Ge6si-ve#kn)x}5t4Sz($2>H>P`6_5&Cy&x1cWFZg`4936&jnTg?*}>w2 zMF#5+QQ^9E>t-9vxSM_c`R8_QC`-~3K@Hb2BByaaNRnCvu-4F6W*?-7$ZZ5GP%91N zPYJwm>Zzw%f(9Tfj3c5hBk~(T7$_U>NwsR#EZKr6QKw;bqJxj|OWNSak^#Y?15k+% z*G<_N-=pU_9Kf@WRhNgsb0v};!6jaL=_P9s<9;BF$%4#`9z8nx&AH@>dk^TK$4#EG zU65B?7j+-U1;^5sO_Hy_{!(Vo`Bc98dbZ5@;xoHG=ZjC}i!VQm$R~FB)fZnI`PR$c z%AD^qN^~Fh^=tWJ_Sf>|oNwgoFTOYXe~>R{|0rM1nk!#?{*%o5>VU&+O=R#?9&qLDhXPyZnlbK3s@wy<)s%e{FQbNp=qnO z$h5?D^4|2%<>m)^N%>l*n&($osvdQm+>#7G-PbukfC9q;-)Eh^V1oujb zPDTl*OHZFs(3gnb<8<PIWtRY^bmwQSSG{_1|EHVQI46s3MAT|7^A&aXRL;_bR1@2*LF@YfA7N>4( zgr}Z*%GObMDPV zcgc_;gQR7v8>P{em&z3lFOr6hE|!K@)|V?9U0|i*l`PMf%Nw3A4X?Pw$YoykRxZCH zU836?M5R%~%jK#o8_E@zT`re3xZI?>N*Z2vwOn!OHFD(@jU&%&&#~{s=kJ};w@)vr zTAdllb4vN+YRfHso|VaqP2<{BAT+QUct6BcEQF69x!hDDreb1T3M4360hu&}ZMGp< zmoSe-=Al+CX<^+|TH#6$(F!etMA8SxYh{-)zr9^%CiePtY0jIzj3+_b;5cpIKwg3h zIqIrmWb{HqD2*_2p-x_Ck2Qn`R~nXsnd1VY8M&vBC5{;}FUihcK5OF+8T-Q$x%Y)P zrQGqSnCF;R%2li;k3RaiY)ji}o-xnah`RI``3qgddKLlELHV%6Z;F~+Jq+3zaRy@lrUZ{_E4ctJhg(qT6I{g-T9zroJ8k-u;; z>lSr>qZ?$}+!dDipnHZa*(}4Br~aeSt~vv~64ovDyIz`ZF-F|9uDHh?Ns@jK0&BQ- z2IwZ1n=+_xbR?GEWZjtP!ft-*dLF$}e*Sg`- zICJ%b*A;sP?w2+~0pn>1002o~tPd_u5FT9Lnl^1JpMLtOz2}6B#y#!&>#w)JsW-6J z5O@FrgT;runcD|z3DyC6`yne;t5&tv8qNb~P`7T~+8&3si4f999d(o?8xR>RH&~Ad zKh1VRQv*mC`H|L(Y$Q6$PDD2ZQiWFo(ch@!AW67s(RhdCke>5nQPQ;P z;teS~_Sj>s`yP?zh-i8^L7#uT?}mMDAQ9RTSmSsGJZlYrz`FpM#VST11NWUGWH!%K zUFEp%bnZsmH%747KlbQ@QmSMT(>B4~K0yi>$tJ~1h_2tVAG%izb-oeaUske04_jP!o*Lzy^# ziHwWPy91FK8tK^#WRv}^6Nb__$09**=g8&3+%;70G}42He|lvWbxAOyp-Y1b?4ROR zaIqw)6gBUE_NHcC(#sc1qLp&!{3_{XR@XU|e-fX7@B~Zltr8!sW#gA_iO$|0-1Bwz zzH)ydKDfPEqPd6=*nu12xWr@`yWBLu<`ZGc+|Tb9%ad<@DAi6p(>B&BR;ngz)~&Ub z33_3dG94C5d?K6TL3?YoQliI<9xW8R_SDdehXO;9xgW4rl#XA0wmyq7HL?*gF{hHHtuj+Usk$^Cx7H!EOBNuN8>Z1tx433Yu z654uZql{RvK}IgzXgv@{%v~-smnO-%S6^p4`SKPlAU8B^V%=|mtCJ3temY#>-Y?bj zjENzz0S#Lsp+PwAzWeTIk3Oz$^xD&5hV=&U9kL&yf)$7;Z-5Ro>KzF zAC{4dJH4Tw-T<(bSfpapicHCl3T_8XT$h1d9LkcRB9A9p!D}PO+!tp~58D_p!adXm zlG{5RxW}mkdE$0B+K?Zjz)e`VN+$oXM4EQKO$wE+B>9UJmx05F%9d>@@`s^4$Y1nm z)5T3k3PNMgC?ZuxE;(Rbe=k|G#D@5!!coP8zcc>2M9rZ$M->!^rSSF#^gK$?0KG&g zOnM8clptl45yUDN*Qh;9?taaaZF(Qvb)aeJO~mDbL9B%Gbjt%c&dnRYbmn)!t;4NI z=?RMkdb?-@Q1OyKAir?A^|zK$ms%dT2hF_>;Fghex}Wv%dBVpYlHd}!94?J@``i35 z*Z6yCnv5GdLP``aZaanYmMJfFn>3eU-~1@!maH=5$9#W_SKDvVPE2fFf7i&M1uL!P zd(4V0wxc4jjGM-{`L1;g9}^!36EqvK-*qq`Kd=b148HZ?dynXjh;GP02=-AlZ})tA zDp@XHl)MC@`i?w^z~<^WOCTf1L0kx!Gj4H;sV`E^alvxzf)umQ+*?y04K~lf9oDhFl2|&HCag%dQ8L><)>}#)TifWboKhrTA?ehi<6-G`bg%%uh<;-}9>|9~ zg#o&R-w+S@zi z6y-oS(x}G5z&_Q%Z09$5;Sxt!YOW`&`#2UtMY%{%8p@#Mr+l2BZHbAAHZQLCu+X9V z2z?K@PelBK7;7|Gtagx5+zbKFT*r+eSbZ+Nq=9_*&G#lBRC#benckyZ*%DH;aDqJl z{8jSR*F9wMqHeNqQG1y`|7KaZu(Qlt(8&tFz3i)Wl(`Z4X@OZTxY z{n$a~&TB0{&Fdgbmp>ubH7;j~PtF|K?DN_i>@)Fc)ZiNPGS!sor<^TM^cyS_P31df z&1O@1tdudP;hjDRH>i}908!znn}=3d`r#mFUE#!7_DSA7J zcKEjvpJ7tEXi3S*#HBfNNkZwea#_dD^6p2U%g3vNj)t*Ia8F%h$3KoW-=B5&U9!f0 zlSF1@X$g>Nh-1yAL9XNZu-pcEH6T3c7U3A*c|7yW){vXK}yiU?ms@6Ts5ez?B}CHY{WWsKBLA zi4T%LZ$8^TVazgj6Y2ZZ6H=*SSt(f}K}L;iB^x*0A;0~8i~Ra)d)e`GC)x2!H~D!- zSK0ncSG)AG_wviny53#3@8}`he(7$+{Qjk*+16S9*m0Nq{>vTm`){4(m)~xc-~N0~ zZo0X$AwA~VCgilweQ&VO#HT{3Qj#x!L8*0qed#~z8&lyV$#7F?^qWfn0|FET)9hA?=6Nxx`~ zOg0TMBJnk7+``T@U+cKqGJV<Y{wD=VPeAO=`q zaBCpSj82lqc0CVi^}6*q&WTHdhFnEKyZ1)#i%UG-fB$_OHHe5uO0YD)a2Yucixut} znm>q@p7ZK?!uf!B=Wxpl_^sFMt}DX74_TPY=F+(u#C#!U(=OSuHBCkjA0~wh7O`RC z3zw^4zo&%a<)m@fJLLWGAIYTemRZZS9h--h!FV&1M(uMjXYPm`mYt@O!(1?WxeMdf) z$Sg9;h-A12O9NubB-tYtn>uOP8Y3);u4j&)zd^>#Hza2s*JbX->MhcL#aelvvaDQh z$?5RVe~`PLd_iiSVn`2>FH4n?;w4K+o?N+YIAu?K4lK|oVSNM8NwIVm$V`{Hh?Oru zU&Tuw-mcqX?F(af`$4=iW#!nz9d12By`}f$v(G-WF7=GhqRu0L1VNOjGa*9=+p{NR zv-RQ^UwmboGJpNOOL{%=h?Fl^$`YT!gPO?dq;9fxTPIVWx0ICRwvv*1vz0BWH%W4e zmwl1cly;Hz4zk6_=2XP|PHknjwUd;Moh4;+CzHsJpKJ-)?X%t+ z>@)GnWnP|yYzb29f(xbJXJ6S~%E3#w$dF~JreaFA6>C6zR#~xQQ%r?4W+8sohWywH zG-#x2<6Yer0#TQ^j6%Lv?D0pYa3AbFiZlq6_*g&nh=t6RprMiRc;@_Je9@>C$+mGd zDRG1JdT+3teaTfuG31f_IrGYd;Umzp=4sQ@^`~vvVHQSFxQ%fICVAY$u$HKTAv`sc z%|Up=pke=CkRG6l(p8{LW_R}4XIrAid=lydP8nIptd6Sz>ul4C2}==CW$0C6#%`=X z?)@PhBnO{lB`f>}5EHCo+$#pZGTsRxo$IavaMxh=YN8eqVwH1{H=@VjE}`226Yvq4 zi2U(GcR?BSICVMH`@->*m!;k#%ELD90mlK-YZ*w#cHBYq9)bVr8Sii4`N@^>B!4%= z$9yHSb$gn1TP#|%xKuy-I63Y7`ckph$&!$>pd=J3FXvs_RGxo-w2b{}l}uWmEEAS7 z)-K5qpd|Ah2I1$2E>8cZ5gQrP2>LV#OTWf^*8zzLFO^t?zxlAZI(1KlO@J%o=>tDDk2T8xmGT? z=wiuVuz)8%2MFjF^or^wMOde(z5}jKSKSm#Vu9^?&RA)5zplG!+;ZwZej{!=1>3j| zw=My((vx?*G99UKpR>D8$0ODs#zax?Y2;Xh00(xNExVK|RZ1Ru=#glf28&OH@}=!y z`auJ4u*4^At7&wnwTKcQ8tb0;?7IZS2Ql|EOng$?$hPFJl9t@X5+C+MeA=`vFS&9i zNY3oJf(N}9*k|IClNZUbukyzqFSkGcstlRC!c;J+GAi+B8Da;JD!Bx@ZM{q>A1rDtJpMBP53q;p!F`Gz21zfJpD@(8N`dp3{xy zInlFh8Vre>WZH_&a`S_|rA)P2k}V;x6wOmmrj8zCG>TE=e?xk3cH3p`Kd2ZK14`qU?y*T$M3o4 z9vi`j?F^>Grx?F$8u*Ysq7HE!b4#$FaY9sRnBZ|`V{j@F?63+EkqEzTK>kD~!pa0e zVc;zTH0iNw-n_Yu{-Yq&Yy0-?ZDb*Q!U2shNEc+2vJpnLM~@!SMi~Qsn>1-+$5$~C z9H3l~7u@BTSPvIOW)^2sJ;JRjh%AI_;_0WKZlmro0GF~6Wr&6!zVLv1$oL_ylR>1A zU9R_;XP%Lyq$Hb$XX_HHLmuV>FqfTy_%IeOb^A6MI&y@RC{tF-R;?}_Z@*h!A2d>` zoN%_$mjw1GE~RUnE~j17TJC;(kc>Cq=0|Hy1Kg0FF$-7Q$&4o?n(ueX8X393G};%e zwia2wW5^N0x+M>g4@)945}l|HH4^Pe;+u~U2bOM{Jr>RrIse{DSf8r|9s%w$3lh2R zDB&?>#C0$zueoQ-*4QNzXAfPx!V)6%DFJ3L<*KCmK8#c@TCQp?cdfYBG zPdrO<uOTX=tF2p@OY=)nIN+)KT;+*3O8^xhJ-oDk+jd(%1{(Q(GvBEPS=qLKVGZ?0|6 z^y%A6Dpx8OB|fWGo5pv9_#|&>6K%9_PH8V&3=#6O_X3d&*4x|rxd}-%zf)QoX)S4+ zJ4@=8j)ugxmeg%#x#LM`-L}lZVe!e8JDVirDpCgl&r^(>NMzu=w^OU8r=6KuFstUZ{; zAuj}AfC%6sMq?gw!T1`Y_0Yg40uRK39)8FG*U#j0xXCf!fKIx`Tn&&OjwQS)=69k7 zL5di#+PHCJdrqPWL4F`YgkLROxUh8Y+}RQ@0J*&O+G{Pr)PcN^3rG^=h5Jq!A)k;G z#`jPL2oz-_U;`kes?Jlv_$$W$aBj{?1R~1L{o#C&9?C}aA<70(qFjV)g*cH8D-cAe zQl&~ZAIb;`gP<`}cGz+i?yWuK!0XBDV}w<%MlC){d~)V1DCKG#B|RQ|L}vcDQ2M?# zKpM5|CWXt@l7w8PO=G%(R5G|4w(*M(MWaf$u^6}~|GI8k|ON7P~?7)1R z2;Z=d{b78b>Omzu>BJ|{3EJp)Nl%#gsP5SFrFKT`t)P3TAO0x;;Yka04YixVj~+=^k};!$Ogo)*-O^q~Y?`-pf8nT68_QpIeZv z=670aBW)#lLkCITbh9Cytt|1`{%ap;+rFF~pmJeLXu#OOwM@bFuI??IqNqY0mH?7jds==5WBJ*I0;XYu|89#o!B?C;x z3UT1xU@_u;VI5-L24)<`+Jn^yLP37`B4eV5tU!2l8{`NuZi*lXEV-Y|LqQoZ-$Oo` zOM>v85Fqj=nj6QqZQItC0arSRDBB6?$@8MzSmn4TNDCwf;zju(K)C*KEWKyUlR;XD z9ow*a5uAbRg4jX0ur`s7ee|~BZooJu*ZuC02bV#;ii4nL5TD_O_!KEwMoLw! zE?pjcR6bq0Qs%7LBJWL`E$w^uk?Ln$B!$aXw=Pr(xr<1xvoDl3cl4CU-|Q!^PnaS7 zXMHCFznO2o=hZTPLY}V6BkLttN`qL#WuDEGbKkV6(e8NOyPsEnX zLvl1STe@#Hm8n*&=|W{5mUI`c z*cIN9AVK3{m1zhe>EuVF<+(kl=>#Zp56%6z?lgw{Og8fFM~3v=`=}%oE@LYF0!CpN zrI9VK)T~lNrcIq}8*}tz|6!YUM&X!0fBd%7hKkfiF+Q|dHJJB62llHncNMm)xK(kv zl>uq>xB~$Qn4TLegpTo{!A?*Ez;$wsSbT^OgS#2g(Qx^~>OsH;%B*92m?({Vz_qdu z>j;(<$Pr*4(b%xqa8AbHVEy47SVwe>4g?5G4i+K^66M703?ihne`8g{LWQp~1PVZG zAZ+9V7z;%HkSNFvu4h=VAWK+|Aaa2G@4WL)n+_`wl?mgV2ucA#!urGb9S9;Mi{o+2 zV=yV?uTY^v(Rn7AMDC3@-mrub%MT<{17IA;=eys)E5oadsV8`S%>84-F4?|yn<2}i zY)JSL)v8PT`yZ4~Rwl`~MayNJAu^Mhuk5RN(z)lOa`Y)@*g^Bwor*C)`HM-7GwaF? z-S3i@MogB0vwxKFivm}yp$iNNPuwUYR&0_%4BB_}L0E4F-}~-G)9uYNARU2@-}7Z) z{YO-nrwjXnH0j4=6f9Z6zKnV?nx{FQdCtb0ZFH=SUXUbX7p$=XC5C*vRNngdOKJUB zFFEy^t0ZUXvgY3BHP66^Aw5MZ)|7@VZ?-`wCj79}THnT*I&AdP)$;h@F>=n;EhV8q zNl$zZ5Zw9!u#WEA-L_cR-TqhzpGU!ZI6r=e^;^6;Eqts(x5vs~5pVmE2JQnc-?TgE z5Tq{DF+2!F$Nf#+7TsrrPCkfFz5@AWz@UM0+wI-0#ivxstc>x|F)Cj6Mp9D@kxY${ zNpn9L-?KT*>`QHF$N8jg?jR{!ZZ@RT{7$<$-PP^CCO!$-7%-Mgs?O zoxiZuz3eJ^WzYzjv1o!^|$T8wEN9{FvMr{;zV<= zR>-Jjt8E0RAR5$08Or@56ssXUBbFq~@P+1Bvp#OIx!2}CPfy$;pRd>;&-NcGb(^%1 z1YA3E7Leo5I8RPHyN+ZxjWNu`lc!FyBYOhkV+f4V-z&{|@4oFGIp(OqwF{DfD;1I4 z7%OwAK`SPdD8vT~4GNS9Zvd+e*NKG$Qbg1?qOg$;>&^==ykL)ow9wPUKE}@gtUQoH zT)-eau8WseUOL7HrQD}aAG@7Ooby5&AQRkMh={t%F)svQOby2|(>J7q;}n_?a~$CI z#x+1j7+Zujh6(|z62Env7T1E+2C_yta)=M(o**?$+6Sm;ATm@cjDcci@z-B}-KJrj z6RvPfz=zu)WyeMC)mLA&Br{$k;E)54j?4JVtVG%%_IaBBJJNoZk;6wxp<*Qs@u?{{ zKlGSPTfSOG8$C!z#qee8?DsnGyYJ-HNfV{JA+Kj&bG;O(Si^QaBxEZnIr5c}66KDO zTBlzm4O?}SZoOZUXGczwLEkTw@ktwH^2Rh7waVzu)yZbLCHmcuT(;SEe4tDD-h=SX zTTFvLS;j5cB4g)omhtnFWxV-KcxUu3bKS5c#PbM9jX4gTtlRl*J5eJ0SrS&8klF-X z2=ucdXGTXuSlsPFP=?^QyB)GK-sC|C*!cNIpR+W-#~Zz6iHgaOwB*ZpoKc2+j5PI! zb=_NHNZ^t+k%_J&?z&4i%NTS0)Gd?Da{BU3@`)jcU#v-$=?hoNI}<*V`(J!pTHJb{ zoZjFXDO%$=Nhn!L67oSfP2(qjAvxOUy|(v0B+m^SXWf1$E}(_~7d1iO;_;{~$hw^lVOJTR?o$wiv>h(os@Unn~)mn`PTCPe`ja zB@YJTV=9d7dF7moFO#QUdq--YbAcq}G8K1@d~(W#mq?4-?vy?Q2g`8tVoqDXNhYr) z#PwPkGvCMpQ&F4BdCiPPOW#DBor0k zPx{!N@#7~-+ZOGmggJ%*W{iWOho6SI!d18jGs5LW;j6_53kQ}A(hyt#%ML*ch^VHn zZn(WMP6pR6hy(6t5GLjk(2Dw@haR$I2#btHwS&MAiW-uEWrpooWKhDmq5-TUxC`QT z$DBe~pBOI%*}~;a2^7Q!LWVU8%MQTOgGGw*JP;%rXFA5`wbx#Y5*I25%8GRcP-ff~ zDF^uxnU49EAU<3d^9ONW#uafq?tnz=qg>>Hn;%v%NELG*aW2Rp{?_c*2zlU8s$AoO zOW0)^Dv?!tP3HeEhWLygHb#mREhVL@2E=E|iq$gGke|VcNiul3(QnJw$(W=yGR{2z z0pI-~PYoL_w?F-oH0yS^oZH|!seJTlMvoRV&#bU%WS5ch$DSsqHn>_YXx>h)yY+5q z+v_R0|AV3O)P$MR|CL%2Yeva=alhV~u`QQ6j`TB*xAW z6lWP&jE&BTEG-E#dc=|>wwpAN7_2|xWk7;5{to6L3YJ)75ZeLfh+3r~8tH_Iu+*!K zFz3-)JLeHH-jJI~tCD4k5#}MAl4!OqSSjz#_(J-8I8yF->LqD=*8|pibMEEWNR5-v zmi(nE*bW}7YE4LXheG_@A@O@Q~#+5?> zTnn9y^XJdE9hDO&PP9Ran4gDs2_6iDwx;uqdY$@|PCX?)0SPh$DO-Z%&YMSS)jmd! zs#(>#x_RQWf9236KG}1c26JAyqE$PYvm!}ud+J3wwc&M=P@;S=Z-r?Xoq5IOa_>ve z%WD%R$e=I2weD|I7bnZq#H})ZMVbsZmC7K~5FfI{RFcb6WW@3X`!>O0vWQEu_2A)Oao^8l4KdPB(Rb(+q>=YHR+fPas0}S zGSM`$AV`D1nk#Qi`bh44@ijTSQDaHSQ`EY4Bor+vCtP}&-2KwaGW7G$r1Smvo5n#- zsZgb=RVIJ^wNsWaUuG(Y!E)h+^(6(@s0XRse*sMp4F7z6UG9%ANA#&V`i% zD-GjR*hcUIEErg}a4jRGG>VqN{3ux5)*vd79IPIY6B_!2xF$b{3)Yohy?WWPHB_)f zhvPilUjiIp@j(eI@qtJ|Udom&YhBx@tf_d(>y}$?v1vg6{{1caY6mf++>96En#dFA@=yhD4p$J&a20sGnWmTB0r43#bd0Gy zOG)V}M@xqXAD3y%(OKpjj1V8jJEG6V8p1Me#Ri$UYLk3qh|7c}tF2|H&4W+K8K!|< z>EyE{Z<)%Hqflw{t>zD0ip@7$ymS?*eNH`T(6o(of26ncdHX|oe((r+arii+YiGzi zGiOQvFMl+oYMu;Pu*{x&)arFIeAQYbMxU(SB%@bukcq>O%soIq%-WF$!Oh?4soJvDUcMj2wx$CxD*J9((711J}k|M6xW!NNb5 zaifdZ%CMgdS^RRob2n}N) zAr*l|myql=Cm zI(+E3qOnY87~AQ@!W9_(NqY323a-6G)x_$J#hV~6ty{O2E?v6VP9-{ms6)_+)C0It zquZ$$xDIqFomJE^TqjoiSR{mPt`5~SEcKqc$A$9<@5{=wI2fU24_}{NOKNJW?O3F4 zV`6e9@@7mc0esFq`y5*bA9d6*Ql(l|8=}5qrLuM&pK@hA@!8+9J6E@K;?u$gH`w+| z?}KBEPeRTdwt;+plN;rW^_ygpsT|&(IY(}KxQ~=R{uD_lWE$4F3^^)VSdOWCo^*M< zk9;tFj*Rh4C5?C2$FGHiab44t>hTFs&j3)48Tp>XFflgYTleLqj$nL5)D)90jiy^9SoEoq*c zX$)j9Ak}N1A+2t|Pu`j`O=hfEDH9jWmlk*4X&MT7q{6^qNx7=gwT29>jM;mHLJljUgBfl`K}AHRMI}cMA)tqj=xuC6h=g|Hi3EX2klSv% z%~n)Y%J>;WI3NU6fc&N+>)pGz-3IwlH!{WoaV$N6xSA0V0)J!1-ars23q4o#P!R|L z>k~u^g$;SpN{`+yDt8^oNrg-qsjR7J2|Pdp0gI1oQDS@%1d4zJ90vi?u%9#v2v)$e zrAL(efmI1h7x#+$K|Z(=bn4W}ju|39)@c}!mMC#F3}`&Co%?e*fw!9{@Vi+fo)ALZ zLx8Ir79WUDnX1P`iO*<5KCJ#)X1-U`=pV6w05DiZ%)0%)*9I1i#5FQ**=m_+zTFQ# z{!AWv?QOZS>n(D|g$<-k#p;q9t9n8%^9?HzGLk!=o;GRK`Dr(Sx6T-x?#Y4^~h za@Q-b$qVBqShu>-OBS1REH*mU$fBh()aVCmIbURSh0)!*wAN%?%gk?rp*ZR9nB`DI$Z!oFxhTaD zA0rXs!+n{MxWW*hAyTj5mFB(n^Z1|(&_k*}W5KNlSl9Hi>Id`_MXYC_?#m$FJ&%VyNqeY4-@~n`Y4-aa zXY}LqFTNo6+;^{>apozKCwF!!QrHup{VkUG*!4q>_++=l=YnR>@t=uRR zOl6DEXs3c@5Gz&-Ci8;~F{3#H_*o97l8z9B!&P)_4?=^%HWp|&7#U(34?`2T$>3$% zWXQ6urU8*6<5#50{s!-89FWeJzN`;!o zNw<4@$t#1$$w*vf7A==Ci=tjag6ln+*@a(By%#e{+TxNy+}rxh>+gC066C3^8_%rmbI)*3(_ zkQgc~tV5XBvHIX{LC+no6!iSj+eknFTqbaH161ntPSPVu6gA34C5H%Kam(QRkQa_2e+Ud#rLJAO+MZCZ3z7!m(|f{s zaT(xxbfj0>J1+5I+xD%D@d;er zN>_vUJR#G~H;GOoC<)dM#?4G#lqwVEGUjHpOfZe@ak%@MZ#|g2)HL+55-mxTLEp`l z_dfkx-km0>PNx=%0 zrR*`sOHK3bo>u=7x#+qZq+#p!)@82Q{f|lKr(Tx3Uwc;``*66tFlMr~qzwM@2N^$q zxlCHLLZ+E=&se_JhT8sU<$C!vX^VWeHbp*KlPoihe3X=GtyLedNsInw`N`U?^6|P< zyW}^aqoCY-jUm%enC2#GPS<_J{wW3LF1Nk z&P7+siD%Z68poX>Wh)*lg^O2~f<-Gxp8UmvYql=e5W&2Xt#C=Hc;cyY&Q*=2`JMO4 zy|2DyEnx3``h~nd>suN4?K~N|Fwx%IA*QYwmKby-VNJpnIIx^=F{IFJU$n&%Q^pRB zUbIpsE?W_Vvo^#hcm4v>p_8A$Gz`9Ltp`}@I*9kpvz@vG{fTZvr(iWkk1?JS3kn@T zbfjQyq0@*?qF7P85UkUTHKY>?3pV74dCahSqsP#rjJ-scqVMQzLYJef(1%3vBzO$E z5$ta3H_*|AwH+5Z+?6ZW$>rp%R{feBiDB9CdbsdKoUxo zHx+aNQz;jb0#%Nd6YF0tjc)29J)U@4o_uehygg~AjQ(zct!QVi+$2*C8Je_WqiGN@ z#wW0L&}cw#$52vmxXQ4F0lCBKqr`{x39C|MLee%nE^5M>pJn2ztuo}tMET#;+497P zBc$6C&q$MQx5?=Zu8=|%tJvOP+dwE-M2<3zpX=LqkcVG*P5Mv!QYM*mOj)tT_V5z5 zX!QK0(zfTL=9t1#zCu;0Rf!3r&} zdmZ$w(U>710B#0A_d^u$6{m70Y&4aP5+eoH8wd|BW~A31%+%CWdn}bH!3;ES_OlLY zfOJ8y018>lf~y+mqQ{eRv98bxiaa1JoSXA#K3pUFAX$`|JYA3%6(??exLoL@s0xT1 zWgrdDl=D$G-1yi=xixwmAb%!3rNIDk}u2aHtC7jIAYmq8&zz^x-IhY z`V?!$9rD%p^4hpb()<1Xa%WwDZK*Y>zwuIqM(T-l|EH0sb@8no{y7q_}u>NRg87dLGob+5iwPQAE+Dew7~ zm{qEEqLi$DloTmnS#lOBVTfETodsJPT+^-F;uNR2ySqCS_u}sEF2UX1-L<$Bm*Vae zx8NQKUZf|_cV2!#;JV1(GkeXNdx@zzsu@xa$RvbBJgXf`YW@$yds-CIK`kcY>}cB|?6a`AY5m=#Xf`GBbGpi24#WxOeOojW?+$G5obe zm|VN>G$lq&-k57}@6rK>Q+&K6e+%rS`o9;EDrw&}o$k@cKjbxwkCV!xQR?Sp>wc0) zb6oWyL1Vm265YCU7PovueER%-7CZGe5iM_dapQYu8( ztvD6f@^;Y>h4Rl=i!;w7dLLq3ahk|`Zf(NMBF-D831$<1DJ!V<7S@^3M_{O{!4EZ~ zVN^`6jHI-CgaHKb)A1m?R_V~EID;gYm zE?EaomihbNs{^bi8DDN%NX(y6r!2Ngkl7t4ED6%%ti|~&BxMJIv}PEJ2jfW?9&i$C z!h2&!;Ok40!|g=NDZ2xj%~8})H-g;J2|AqRO!6aoiE9T#anBg}>YQJU6Fn812H<($ zP>UO_JM+KiMUj9@h+;H5DJ7+ATCm+NUv}hxngy#WR{f(m;v19x_sL8qni)rXawGrn zi%b=6DKTga&K?cmd`Gz|ZyJzZ%|Oc)NWXF;{JZVO)2lzkFO9YH^_Qwf(yUPBSE0m$ zRKG!+q0MKa8bQPvOzW3Hz`5t%wb}NSta`_pSdSkn-w!`#w@Mw8e96O{HiuW8h(ufp zn3&9Tj6aE~xk$I!meIh$(TMhO~1@ zQ}FUdF)?^1wmAoQ>!=Rd_MQl(<}lRlogyUuV{%gT|rWwxaxsLF-ZQh z$bnN9agbSKk#Y9G`IqRTP`DaTUR~;_$`jg_^C@lPe#6Xe;;*-lXD;0W#Ne`5I#eQ= zID-&Mm-sD~QD`>dXdAe!+;}!R?O4cIW3zQuD^xyzM|vxkEFq3-1nLtD3_Q9RUZbH{ zSmTZxGk>2xk9nOk3YRmlc0!ETP7NUDXIZaJV}`A!BVFLP**Eh=Vd0~|u2=~^z zs+-Lk7?12bX}qe9A%Ph~6|CHwLY@EBOgR&eGG(;@qp3)6AP-B%=ViuUH_iOIu-YD{ zw(&nE2_8>ic+bDH)y2E3&x<7|X0D^@TJmRRiS5PO4xvNby4LDh79WG$G3d+`%7MIt zvjprOFlM2e6MHbS?2DX8_Gk!8RrvM=tE>XtE?#R(A^A=4ha6D9Rz#;Ux@vyyG<}-2@ zkU~lpLUt{Mh}B>jiY-60pMlOT$~jO(1^ zsft}eNa#NUsurRp6bPL9td8qVcJPn?Wp`LZNKNt2Hd2*w|7@}$C{qG}!<#$6WZW9C z9|#(U@-NI}eiF21qK?n`mE5JJPeJpinuSZ5PkxeELtai@NEcD7iuy%PD{YHvQudKt z%IJiLlCC|Wn5`@KHl!(|6HLIKZq$6lLe3ZaE%l9R62DnPMNXrhtQ@(zTK|HR?|S;~ zs8+r{CDzHBZgp!}V`B@@zXd+zSiC!0E%*9203NJr`ajS64G02Y>`)(N(PKWqj2G5# zQys-GvFiOqzH&qQ35t@2!bIW*ZO==TIKCjZ)@pu8eib^{EhEb(u1QM%%j$6P6wf4S zi~lm%W6|n{SKKehci*gt|Faz&HcaihHfxl7v>u)rlughQtJhc?DgQ^f$Ecub?{CR0 zDSm7;@=~#!#^EsFIoS#%9#yD(-u?D59NjLL+)&sz#CyytgNI1I1Iw&a%hVmz`=r}$ z%4h*?6~ue~?g8rDv1|ngIvC*nm;GTT8wLnOhztQPH=!wlV?$d=`uO(STvOQ=28m6@{m-^;hM7`hF2z- zNzGJtE@jsA+fG-h_Xt;w*xd3Nho^};<$m(szsQ+9G=bEmeFl^y4GI}LcI^|=kdeaQ z$!`=k>>hv^1to=a*(p_f@73rj)l!vt`;iXDDpH3zqr>(q1Fn7tcZw6Qi1)TH$Ua8W zXb)qTW;P5u*J2V`Mqj4nNNb%k5ExP{7JsT|XQa_Dt(L7BPAadIZ}{?pUnRkRhqFD~ zZZ->i3^yQsmi|U_e4gvAh3fk~NBK0{n9Kkei&7e4OB6|V8u^TE3Zj94t50O|N14hD z<_y8Za6?B|)rF7_sXrAc!Wf&78>4ycsf092AR3`yHZ4d{un+~pk=I*#Hr{hTn$)n^ z%4!0S6$%{98B};gS~kWDd{cardIQ3KV@Url2y^jenV$ zLFM0Ee@JMDXa7ENfMA#G^C9^+7;TpA>RdE8ojXB5vsa@^6}-n>Wsp7^R- z;yQB&WDOB;rvYf=sOIA-^rd$I$GlAEl@lI&zaO1loxA3mMQ0BL9{o@mj&SkaO8m9_ z9Wi1GS$Wwm(Q&243-Rf&cJbVO+pz5^1X~@BeJ_>**eOkHNIO=e{)`fFw*y4XTwH&2 zU3d#K6sNq(LVco?*bAV{VPcW7xodek&`oCsW^lFmzkv5X{sS)Q*5GN9%T!^I)=CPp z9A^nY=s8#3^hAL%v4moFrXJcV5#A7DQf`8SBXNxP92di!-d&-&Jx}U1gFq^BPDNn3(fTOlzv6WFWRLkC@Hl?%z zephXlR|9S(?9=ESz+eK>NPnu}Ph>_;Ocl!71mndb8XO}VPuU)wNEkYyzNt|WYE&_?l zk#K+U^M5~&&8$q~LskrWieX;@F#7C9VVfn^q(Th^OyO}9t)_?5>Dt6C!RMR|ODm3v zbZV>iE$mb_HHve$X2^V^TM0ypILg#`{?Q7YT`?}P2U^t92EOP_EEcO^yY=ngEWQk% z2cpqP1Y{Y)RNKY<6!=RC&gM%}zkacaRxYgx-Glwdc3Z51AD|5IvUxl6y$re9V1>SJ z0(uqf#u=CpBE=iSf;fx|U1*USt&kAwZ3m{GJ`a%n#COz2+Ow)>({FA3nEyo6fvAZ% zD$TwkH3r*t6s-Xp5ZQ1m1NTJrM!4-e>^q=MHEOrNIJ%}>f&JSpR1{^}VW`JNP<&M3 zj6=dZ0y_M6$a1X?$Lm`o~R^JXY5pMvO^c^M|g>J;S?EzRQG zSdH3YEb^wsaWllYFslq1O~Icnyz+JSI9Tyji&0d&th}f`hN+c1$D2_Fj{HpN)(%74 zI}S(X>&26D%}Q){K9W;SUVA$}5bhO&>b&_o>MD7mxmf0_wS;y?*M5J^gxUwL5d8bM zd+~KU80_9Z0Ji@J1i$?Tf=jBm42k)54e{AWnT_zcl|Fb(^Lm7BQ+l{vdvpqo+v1b8 zq!UszBNN%qq&E%<2w10&mtMC&z|Xm$DX4}X=Jp4F&5Z{?nR*b!j&HlVfPydllEQG9 z<#sNoA-*-KQBMaGgKrx72e!})_ICd|voh(BL1(8c>sy_BTAIKkWwqxypX)i~iNbZo zFW)X*m{uuFNDn3Qsw=G9CS^%r`uLKgF5e|JW5h&pOtt>1U`A$5OQ{q5c4OcC-7l&P zGxj-4#PVUBRM-S2AqAPiwq;W(BEB~>=aAOy*rnh(NTE8ZJ16kf?aB5 z$mSn1-*R*!c?(GADSX#yt3qA6k>qQvE((0npdW7%mVULfSZQ$W0Bj>R>mKn})Z%v+ zo6=+jUFyGKd-H3SN&N}0ZUcZJix>^16%9dl=~^p7(2fa{sr|QLk}Uk-Qvg189zqqF zND`Sx`avhAbBHkpbn@?f^csu|{@TDK?Qt{<(Pg=?Zr={#*eAyI`mr$vFUH{-nx>de zkj}K=jPmxV(J*Eq6ip=4?SM4?K4#o2+a}I;&nktG39dS>@u>VED-+g4XlCRUA~VAh z1qgZ@u{gVu*?{RFP?sDu`>amv9~iXtclzt%^=$VMxI*zL?CxBq8lQ_Y7!ME~6cRFP zmT_->I9b39Kw?v!Kvo$f*@j=CG+-CyX_%-KHMv+SXixzB7XtUKTKx}N627NSm7fOP zkNOhxA&en?$rnUe$gGj$a3F^0-Y%nSw}Q(L|OL&eS1Hjd@I`7UqoWa-zI>b9E7osOd3tD!Nvn`_A;^tgIn~-u|&Gc$d-tSR~3 z_#@uvRD#n_;obPbuu+p03&dF0?I2j&Vz$e33?}KG=1}iVG0RsJ>ESMAotLW}x2Km# zgEi7BG~7`e6D;yeo`pN-@PqZpaIcW2@7j;o{r>_8Boh$K(?4~>XF@p#FeOgzh~9bJ z%|EeVv*%4Qy65*tK{lL}Q1tdgJq9oc>2X>Tt?kQ-Ls~P6j;6PI$=J1qw%*WG_R83~CG z=_^md)=W&9t+q5LhW@>I>ixm$A_s(YF88;pMSfTl8m(oAwCclXWFhppCEr+lRBFo& zq>-v!!ewFHas}^j((Peli8Y&1o-_CArFZM@nD z1dc3)N>5Hzyfr93kN;ggz<>I<>;wbbQqJCAVUr z8)v!Gx5d&M8M>itsyI&-OEa-aoWg$mnSey`|4NDL8a#B-8hN zpGmRXB9d`PY+{hQB!gTcVp~^ol+HMAC$Mfyw4KgWngQ2sjl*&W$Ca-dt%UT~E=`M_ zn~zc`9{ZR9(i)&)-v-&au+f9D#CEd8&0lsjI0o*?9u6V%tlW{XOy+PVD0uk&aT5b6 zp;H9FY%)2d=2aKoLlP8A%#}c3bHr2?Y5sYg_uiWK7|Hd#oiuy5vQOZBz-Y*EDJju) zJapP`a*5xFUleZoSb5OvV>^DMH+}(^9^zh*n6z^tk|ZBy4I#&psj*T@S7?sY)3)f< zPZzB=tcJvrWJqOn3FQ@5NLpQZevlVD6Y}zrk3x)lQb*tM8Bx&+#bQ?`jMYA4Xu4Oe z!`|XK(&NyR)QXm7=8k?h{UHk@h7r|)c{tT0oVsfNE8uwL$?rikyA_g-!1)rdXFdD! zu1auxpP%ij#cDJ6B3J8!y~8er{f!*At#!Iu4b8= z-)1Mf`?V=vw|lyR&M%dUdPTNXvwFKLZUL=1T1FoEtR)J`2u7uh;IG^hL6Q@XJW!7R zG2cO0Pw}6SARKX_tO>;#x5m^wRTt?nK6)t@eJk-$wP>sGXN6q;mnbS>b!e3l>kJnx zYr^^1(NF4iqBqH-$YJyK;t@zqcf5N7icWax!;s)*TLxTws%fVIN)J?#x5g`#q4+RE zP5N)gbw$z%vYOEaWtewOiJWCtuEJna5!f2`b)wK{K2R2$*`*)G{j~}k+Zc>cJEtwK zxxyStXxv$EskF8)97m{cpr@A+iqxfIw(S3XaqWrxZqP_F35Uti%*e^W>C2~{RMVF+z~=S!7|$YDX@H*p-ZNv=nel2AIL1s=6% z!}$Btlxy1XBCnSm@;LzIW#p8*8^^Qm{R}RS4p4?6>TtYQMw9GBgtLvI;|A?C^Y+~T zuZ_}3w*!CT{X6(XP3_Iemv9?Z{wR!u+~mqwm(fVnP^&==Je}=V-==E46TBa%{VJ~ zXo7tpi31kOYyrPNrAg@+pL}6OoBav8-g*e9mix&~eEB=aKoW_0ZD-_x0@Vyx)9oQJ19GW@(5w})cKeTgq`UlF(0F|THFr3}xrCFqp;`MW~9C)%MR%i}&j2 zR`K#+`Ohkzr$S2wob(u4YxS>a?^iL`YCvA<9z3g!Kea}dWTYW6EX zC#isY&W%H<9fXzP@g*!Wg6?m=6a!`?yJsjYlbKse{zM`c5F{SV9JgK-N17*HE2v{D zoHMHERc7k-^t;!|2c$nt&hD7w{oRb(lL?~{=xWsv$Qc^qvHLuLUB9^5E!-g|W0ykl zBdqdh!`|Wy{?3I|+Zb)Icw+*rFeFU{pKM#7?kWjJpnoBK{se8kJV+@(GsfHEKmDe` z?z1CDKC|7?Yrz;lzcIV7q5b8#!>0w-mykr03YVe5dMMwph~=~lKu z|5LoLPinksm5E*wz{NAf!x2JjIC>^7+yfo1U3>~|?xdeENzD$&lUL}&B%}Cc z$D%ty6hr~g8ovdCqcs*fbDT7RDI`LUmupQcikQv2-Cj-?f2H`hNoIB#OE$^(qvwKC zhxj`_r$;$#Nz-QrokC*;y7xp=3<#$OeXFJgs*o9lP^`I~0_-I-nEB~wi)+xg_R#X* zIIV*&^R0L2&t4bjK$@*U@Mg4O9q(qz83jP)vz`uCI-9)aMtN^PwF6@`L}F9a#R8X` z?qcqnX%O?z(tlO6Au`?%4T+(zMKg8qO82rHi@@R`Wjcf{^o&AovGTfHQ^Du9x2~gt zFhgspNYT*0F=pUXAuw0}j)79C(rPH6LhLAEdxFXMw)!5o!;;2DCVf^%Rf3VaypS7# zCS-NJ)w#0qT|5?V0o|uXy>YNHp0g}6D;W-G=3-~IgFHKOx!v&_=o91-32`eF`)LPe zt)bYV4I>sh_*}P=9ck*qXHXuW>=7p=h%KOrMB#=Sc3S0yA|Rv_R&OF(ADY9pM}UF29~ca>e?F{rXCd<2Y>Na~fza3CYb}xq|4BB?=knr4b(| z!&Y7x@=k;@(Ha#{bpK#)f&Q8|h8-Xbh$-T_>(%hgGvjv0X=fcW%zt^in{$XV$*24# z&rC#tpMm=>UW$6b?$$B?X=EfLntlQElp73u1A-w@zjT8j9uO9@l{Oif*s{U&YFIbb z1JXmKULk9n!U;ynj`v}*wE1upx+ZG(F!hcXdO+lDTanrigKN^i+Tx$bBolw-ci3}4 z+u}IjC-*4}K^z#LF_isG(Ma_8lC@;q_l4_9F+i*t1)Sd12l%nlaaBQkPY}V0TkU~SxyqwGC|LUkUq&P; zNVj4`zr?Y~5F-$>lM16_iW0R_r>BRZ-R@|hr$fi* z>idvJDE2`r0YNnWB*KmDCSgX0kf0-phM)%^c8IOeA{E%lFoOJxkKbG)U7Gbv{`I%N zo4ULEb5Ku?g^GaV5Bq)aRr8&RpLi0jZM37u>kR_sHddI}ZKs`;{X8j}Cf!M?s#w1C z_OJ}o?D*mZth(#f-UGd~mlpJ9+9#fZ1ymqW-3}+vyJ-Z5Icx&jrY~*IE@nNX%s<@& zZt5Z@1YSVbzBf1Hh=ZV(bKN3{?hVi5xaWSqfH$hG!N2MJ&a7G{(|S!h51Sz?BXFPr z$i&kdZkO_}hA+%?Bkh=XsZB7UxcPFBOlpiMUzInc6aFUncP&)4^Sce5#@2t{JZZ{X z6Qdt5a3%4siX_VRpTfrZ$I3Ai;*kIS{=?wRMPNAzu{2ZT^|;HcKRayClb=26e*lor zR+9}A?!o5zQXpw0gw!JK6RU12*W*07j>YIqy$tuJrxiI-Y*eg$%$njx0c**Ibb%O% z60D(Fr)x2`Z;Un2HTcQ!3mj`P0p%FcP3*jxL?V3#!4@QA*Kx5d`bu&z4yDsX82TH( zkUCn9_mM}tU3e0fv%Vz;YSW{IC*dY7&XWQIGtBE6tj-Wi?j%gf7ahOjY%6v&a%$Ev zG%-ZHA&C(vw*8$517hn|u>|K`GtXNHXjm6K&P(CC|H36Zv zTU%}0EfVM$+x{QPk74}MAi6RXAPv~Pwf_AzI0!#e-!-}}w3_9HdY=D_s)T3)v5=28 zLr<5+QnXBdJvz)U!npQu*5pVZBhqD+WxW`Ye`_|0>z#KjF9*skj%`A(`bP48F*vuw zR)JIK@_wdVlP(6KTbD}XsS$l$wKk<9y45-eQHfMSQ(yKutaZZPSdT~3ct|mP+n3!& zu&yO7r>4U=(Gg}dRo1RCNVGha{gT9&_Cp6HerPjd0e2CRjIytRk3us1JoO;ZBPcErmh#k$FT&}es5768egr6BU+@jt){}t%Jxj{<+DW%5&;{; zdm5@gAIkWY@w~NFoce2@e(Q+=dyPb1`ty$2_=7x4uepHcDLj1O*PcjiEd=dPWF;+B ze>mU1HSvG>*0XurhZ5Y?y@<`B4es*jPprPb3glQv8-dDBPMAzS@&tN!X5{45^(B8*PN{uTS zwmfZicbQO9Cr@7zq2g`eW;Equ{%DG42c0cO^%k6Rji7Dgn8^wcWz?kE7X>RSZX zly%>{FU7OGV4R1WujXg`6BsfB4JDO+N){Oj2*lnC&vkao%=;R{XhXCOCikfw+? z)-mO8m>S5|h37uEevkE!B84WDg-;PTRk4`xnKb&aNjlkLy#9=r%&3o%N4sHqQs9-7 z0ndO7cI-7cS;~FApEh|eBrar2FJ#uNi}R(KIX63TI=@GfT*R~tJkmW%4*=+8Vue^( zxaP7H%eMjhmQmf%Wig^(J5EgMOtvtwF0QYm4HN4xUSS6YNDO=-S(Tz0O^zkqC73OCZm|2wEMBOc%s*jU6Z2S3U0=s-Jol&8$HMwtBHCr zv^Wyl-(K?4DjvJ-Q?)W)myT4+NnQ(Uv(5_Or8`gd>~9ow~8 z9KA;z^HtywE}zIx!1Ir;e}Okx1$6EibO_(}%$xp0BJHrFx9U;|@

eOp@9&sb;dMZi27}xc4fupS67XO`! zqfunzfJA(t=8JSI5Xj9w=)45^-+g+4o)pS23%gt0tvA;^*51SI)eL)J-9P$TJuDd+ zgR%-2BCxllNF_xIA0p3cg&rnTC#i1B9DSs-M4;p@Kn`P4M{!Pw9!ffZlrbV1QiK`@ za2`V)`QnI6IL1?SvS+Z*BNQL@l&~`}?uBl@WFLQK_REt!NqnvI(pb zyJy(A#r+EAcATMFT6K*+R&Do*M)?dk4^h;w_+6j_v-`j6#Vh13ziqoU9BV^hGdOpW zzGpj}cx;g=(eb2jH1xRUEG0Fy?t(C#BrNO%CAb_X$!dDfF}|_VO`23a<{o38U&3Ow z)6HtrS7{!>=NER+eTt>6can%OW27_u z{Iljv;m3B}ZoVg{zRUViTPP&lIiST~vqH1E-qAu1JGr@B5VE-AI*wU*mwPR68_oSe zB)glb)1)=4gSadM>E zBj>P`Kp(UAg*#R_Xy1H>n${jbyStiU_ptkY}=jV#z-oPjsp)V2L8+>-ts+D%}@9$`|*2R+sd}Q25|Jn z)7ndvm@=aLmDwfn_wr6`ykyOQD-rkEvcdYB&>b%{Q|Q*YE81~K`sRPhG`L$FDJ^(Y zAGVA0l0-zs+SKAO9>enapG7 zRJ9qmO+@Z3@2Fpho$KL^!zqT#C|H5Ku4*XhLTh+6RD1}9_qK<~;Z=g6*|@*r$c(dp z>~wT4{5GG)IS5t~yp*IMj|e`UjiZ-e1*SV>Jmq%hR$)~LXR{Iq<$0Ncm?Y_sPiYiCmiXe?M% zX`}Sw;V-U9PDttL%;&SxThCZgX{*5h(m0aG@?t5wZQEA)D`SSvVFs|7>(RpbQl8!H z(#MqBEiWh6PP$vi0}W7{g`b#jrlKJz7F-!L4Rdud#M0ZjXRoZlWjCcVty598SW3;r z;O>>83j2)y^;+K9DdaB4jEtAA;_`T7kvsR*VqD4DDC9LcZ)1c}Pkv)%w%Ke9bFoVi z;cnVH0uJFeyR9%fF*8uF<6kx=3H`;{Qib-S*~Hwe0r<)2zS+F>dHx0olO$8W5fx+K zQB76CEM1nbX%>=b^Z6PH5+sRovKrh6AFqI4iUd3QC;G+6T7q>BQ4Ey={{>R5GQe$Gxr!H;m3cpj=E9Z8fFMwC$Y9 zW1g6#ZiPC)X0t0_fly?E_T;Mh0wiJz%X2e)vX|mdC7fxrK#M;}^fiII&0G1D)6|e? zv_i}i7KPB7hB*9^c3~j_564gh;B8J+uaP#(vVqo$zU7o`!Ps=AMZxEKm~zf#H~!y( zltH&gTIo-%ltn7Y+*pBPn~?*9#9>dIxoacBPt;EVe_S+;FbVE(j7m5{&_4JXn$mQ0 zC70FJNHSy4mS-?X1rd`+5t~xwxFs4v9_c_fu15U-9$TXih0!H3IXKvd_O!R z%(KABg>;2fOi9G`WU2wa0rGxnza`)iSCfOElXe)*&`BP%FJdr$p86wD%3z|EwjOdf z&!pMpLLlbtDmycJdXvZMsU%^j`>87<%XNux!!!bOOjd{0AU?rcz7mTkh-bzaR*UD{ zj6$OR?-b{?wRZ$Tp-Bnw%Sc*Ijx9sr=-IrU98w@`EJsENJd-9_b_5l&0waGC2|4k? zZ{r`V!SJVlKL5Pm=fZC8nmM?U&@ALS81=@9h94Vl(T=F^`)f;pL~%)6X<8?|-g?4X znSALAe0eaRFZ$ff=%O+W@Pqsr9p*;Sb99vj%;AVw%^)ZfFFft|`oR%oExjE&#w0{7 zo`?r?L84@?^qKh2#?KI9uXZ54QI|R0<}s~WMV@+%ih*vMBNZ}% z0loBURbKcWYz44B-hVS_6>`F^)1Teju#sg#uTkMcQlQ%;+j8F+$=LeIaBU){?YZIu z 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

O&}YnKOj))X3%2ir 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

YB)w)mV`cOy%8=ELQ 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 C1SGit diff --git a/img/image-20200520234137916.png b/img/image-20200520234137916.png deleted file mode 100644 index 8ea464eb8078cff6140a0c0caae36d2420e7b3bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13219 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 Vy_|i(Ki|NJ2}ubSf7AB-{{ZSNbHM-r diff --git a/img/image-20200520234200868.png b/img/image-20200520234200868.png deleted file mode 100644 index 54d8b425047b742c9adafb19e28141ba5555e40c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26483 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 TmgB+0bWlEjk`*f#`R4aO^9uK> diff --git a/img/image-20200520234231001.png b/img/image-20200520234231001.png deleted file mode 100644 index 5867656935e0d57f4e66d13a2be913b16122fc35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25332 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 diff --git a/img/image-20200608232749393.png b/img/image-20200608232749393.png deleted file mode 100644 index 55e28ff14144098cf20dd73ed7c99090c0b5fd8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4492 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 B>^%Sg diff --git a/img/image-20200608233400458.png b/img/image-20200608233400458.png deleted file mode 100644 index 980e3228a6a2d037b78b45d8cad3577b1a6d1d07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2946 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 diff --git a/img/image-20200614165333479.png b/img/image-20200614165333479.png deleted file mode 100644 index aba7127d4ec49e32b83b571260e1563df08fcbd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 208621 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%0DGeM-y)v(L+VqWL-tgM{I*yry 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 WS;LXi9WJT>0000K&I~uzLyLKN-B)7z2n|9 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 LNkvXXu0mjfd|1MI diff --git a/img/index-search-range.jpg b/img/index-search-range.jpg deleted file mode 100644 index f4ab778a4ad0f5b34f66ef3af822de91e9954612..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14490 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 diff --git a/img/index-search.jpg b/img/index-search.jpg deleted file mode 100644 index 3273df7f1d7880373642cfc155155ce2221057d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12920 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 E1NSba@Bjb+ diff --git a/img/java-basic/field-method.png b/img/java-basic/field-method.png deleted file mode 100644 index cb566fcf82efba31a5d1a1bed9f08482ca4d5142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118178 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 Fr8Mqwl*zBlR)n!pD79=AT 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 z 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%0Amb<-lm7bOdXvS(jrH}_bn<8Xc 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 QPv&3JME?)}1pXTPKmJwmLI3~& diff --git a/img/java-ram-region.png b/img/java-ram-region.png deleted file mode 100644 index c5088be551b9cae1960b24aa2bb71570b782b5c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110051 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

VJyuxk{ z{gjn#ZTAeFSL%mO6x%*11k7kYYhV2j9-cVli+*>$JtXHGo5B~_Nyj*p5yR$aGSr^fEEYS2ljsHvX?~4 zft4^Wb#@VAX%=oq3(6C)QuKp03r}XwFfp1xHwDQxyxKM}g+XsKu;%7J*(5KP)$OTf zB)UWVV6Y0=b|Nrp#Nv85fvMxto38aVAcYehQRUCp;Tei*o~?(N8haE^Pp04whI|2h ze(4miDkQoUJ~Ftak)YG(-QCp0#{I)Y`>CITY|Ekq`*I2Y_M!E5_*M7Tb{Ho$a2aai zkI91FzI=H^L}GB!%H+yEkZ0DF;L77d802DeJl6pVAVA% zKEGiwwu+U{_fFZ|{!xREQH|snm~Un_SB{6l7?8VSf?NJv??SUA`4T;OVwTA=4J%ui z%ErE%Am?wyu$O&*@eHn{f=}>54Qw-|t%7emdIFcN|Jv?oj0P>r3v~@2GfUifJbzA- zF)sZttr`_nk42dscI z_e1*v*RK8HYtNCz0 zQBZqsWbgk6BLmMLBNGrR?qaEX;NB+ov>a73{CzN&CgM+!ru}`lvfE5$&*eGt?w#lR zpPQS_5GwnmaEzmBsrrCGrxXn%aJMYV}0cfTkYEB>t}o=juU>8^_TRiPGE{f!n`7$K7V;;sl$5Mrvi%W%ZhU`O8eBY|fJ>57C9evVFkJ#Y56k-9Ztj2VUtlye|3c#bb_f2efPX}|(A7wl UKyEV#Ck|ajL0!K5@$)zT1!|Op^#A|> diff --git a/img/jmeter/jmeter-aggregate-report.png b/img/jmeter/jmeter-aggregate-report.png deleted file mode 100644 index 5a2668e8ceeae4c9a00c73ac0a95a17f8ee3cf95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49256 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�y}jPF?91zpJ~Me;?Bks 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 diff --git a/img/jmeter/jmeter-default-request.png b/img/jmeter/jmeter-default-request.png deleted file mode 100644 index ed4ad06b240f841d01958b84b963f473f8e5a213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79751 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

?|b`b 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 diff --git a/img/jvm/string-equal.png b/img/jvm/string-equal.png deleted file mode 100644 index 1dc11f32eff09a8acea8e01bf26a28753ac4b0a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33445 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 H83z0hs3`nX diff --git a/img/jvm/string-intern.png b/img/jvm/string-intern.png deleted file mode 100644 index 935adc7da357f3b2d8b0cadab7700663c7138d38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36462 zcmb?@by!tzw=L48q|)62($ZbhDIL-s0@5Mf-HkLNjna*DhjdDJcieaXzVF<7Zv1iX zbMND`WwZ8X?X}*RbIdWu+@Xr{k}r|*k)fcVUP^rsQ-*?i5dj`di16TuTGbWg1z0m- zIbkTMs%Vr4132(IsnG{zIVdQ1YAC3$0Z>qP;Lz6{D5x*YP*8iHprCkCprCNjLrM311>-rSdA9pI7lF zoTdE5WxwYSV&VN#l%tP5brSf$)PvLLWAqjquUjNV_KQJwQ= zZQly4Y~Ookjc&VTjrIzcPFrFi!b1Dzzz`nlLiq}jqNAb)w4*}~$sziZL7t?eLyMAv zC-2E%gTU*E)*^_gkT=c-pyNV=CzVKK%;4=ppRhzeLH@3t`oDYvM+M5Wrj^H$<EZEP6D#l>~% z?S0SA90mpll}e}C-@kXbJu|7XT3TGRcXaF;AIBgeA!%-DK|(|%B_)MYP*Cs?3=@L7 zVDpX5q@-b)JfTmX(%>$shGm`j8=InwCsj=jw-IVQkPo}ivYdJ%vWft22%vp{NKOhEFGBH1XEB0a})oNpJwLm={5><1%nGY2)r&wlze;{scdHJ zJ6upj6mT$6-qg&h`8FfgUt~o*8~t3hWYwy7Xvr90oxyHVR#olxc{(S-$H!0Mv?Eq7 zsU799#=*f65fw#x`Ev7Ock*DRE&K8Qy2kJ~a!(YI)$tyN&e{c&@3#TNWTp5%sxLC{ zPx~2z3UfZ;#h_rJ%4Dq4Wb}rTP}5Ek(jA+$ z^z^x3HUw^NZi^nrEdhanm+4V%XB+)|C+#o^$;t6qSy2*sRW7lx>a>q}zthP?sV5&v zuqY@T9q}!sLR0X*8zULhV$-r>#*o#b2p>bPuGNb-FfefOb1xAp5l<~aNv6TRKZ@(_ zLKfrS9ASTrDnmG}GBw1P!WH9SB`8*+YIfr1Ubgw;NKgze!Ii$Im4$_EkVfvKrc*15 z-8dQ$F*)u;Dc5*K%=bZ9_=U^jXUR6biM^ejzG2Q4StBC~eV@mlE#VaP(7Wo;qL|G= z9H+vJ2!88Q>M0CmiLexKr14@6^7}DV#yRFS3ZkStczgT%b4@NxTx>ivC}u~@PlJ~)>_DUnsIpQC^OTF%AOnWr@sF3+lj;T#vaUg|G+@C%Oz4d^IdYg zInGjk9p4`(WgQ87^x|sgSQ+Zj&WeN_94?=p zYU&K3`u!S@KW7+yGoSC@v_6vX7FcPR)Y~0MFVEkjo?8$935cbTRMyd1+}s|KkHa!^ zLdleiD|u5PT~j>0-};gMd3{253tzjyA}hw8VP0WZ|DKrvJvBo_)|5P-mf5!dgIbJ8 z_zIn7r^K44;uwALv}HzS(@AOu7_)2J_blI}H77?3jQsKyq0B}epke0{JSDk!dGn?% zn>>9$)QH>YE-;B9wsRooMRGF~K*A$HQWoCt@4}rto{F%JTTfsV{3y&I+ef36MY(u~ zN_zLL-F$AYj3UlBFn9Q4Y(Fw~|JA$FRq5W*(dhMc!yq&g+j}{)UuUZ=9vU~xddv7I zCyY#tAFQs=YT#}^`1de7Tbs%0AF8OS1yxkoZQBjKKb?dZVmMP>(oa20`dd;}l|P{- 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 diff --git a/img/jvm/string-new.png b/img/jvm/string-new.png deleted file mode 100644 index 2c0a3200e3b88c31a4a6eec7b811a2fd6e19be22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28718 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 diff --git a/img/left-match.jpg b/img/left-match.jpg deleted file mode 100644 index 66ca509490fac5d8e9211ec79a82d2ee3bd3a71e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31737 zcmd421z4QTvOhRD!3ha6z~I3lxVw9Bhu{u_Yj6z~+}+*Xf&_PWcemhyCHd~T=R0@z z{GWSw_rK4+Kr`=DwN?GPy1KjiW&ULyfF>y_Aqs$i001Cfe*iB_03iS*#P8>K3iA}snV+glj7)s}H_k6! zYs2~@sDCu%&wmI=s8<33`fmyV>d)_AbO>|?NFri^w}SGvFN*-AR}v&T6gq$pu+}5Y zFDwlG|DQz55W^oYn;4Rqkocd;RwCUebQF(H+XSze=UTjMNI93TKlF7_TR(@emc2(X zhcFz4cW~oS$G{6f14Z7`b?lz+NNeZy%N;ayEa(k5iloFHZ)db~a^_4xn#TtvxLYIMNSc01b zg!UxUgyJdTb@Gg^Yl}{NrV^o)sL@ZZ_h*Um=t5cbGCL=L+qdKVyaqGy0oPk@o@grB z69if|$V(qW2JpIW$+~UZHJBLhui~CS;sf-l@q%f}J z4{i}R>q)uO^-u?4PEBEY9KPddn9oME@rq3UywAA_X_MurHz5$2+*nM5`ywK*P3-<~2 zy>_(MlYZ6xwX!Q(dkHHGhU+t$O8TcS&(0`Zpt_q4)MW?6s4Mh`y}@ldn`nmV9k*nY zc3pUSg`HhvIAlaoU$S)E0Xx+dn*FA$N;ob;T815*K}^3@v{_AEZV_(66ySEaRY!mk zs8kO&!+FBoI+Ero?4F(hH`VolZiA~u7oJga`pdM7+rhGq1cAfj3ha@4e%iLZlU~vh z#>i0mbCL$52I>o-%MRrQz?X+?jQq3X1pxoyM_m302&?|5!5XDJo>0~-0siCy;8FzU zWZO&UwC#ucYb$MDTe&{mYlHMC>33?v(%L}gdf7`S>fw!dYDvq8jC?9M?zT0u8d$Sz zE!Tz2;{^_kdjTx5m3uiP_~RcExth>B6c*1C~UJKLI8mIShTJ(h*gvy1oE*qtIqO=AU%gcMreBNlb?`Za7OfQm_ob$|@XA zH}$n6nabkBe;_2h4<`CDD2KrZ4=VW-Acse~WAvzMP@kM)PgJvG-=gSUb_P4nt)9$t zn*;YSSYwFfOjPq^5LeRs0tjo{YCI?_m}Iw>e*u^%-J9C8NHVJ@ZY?uja7dB#h77Cq zqV0aOpW_*H_iMI+XJyggp}vJM%W;SQxappE>mYzY&f&6S(RzxPCYF-a9(V1uO0E5Hg^wZKq*>xhtl5aPUTg6w6=C}w-G z+FqVylhcJbJ#TM|)6F`S`50TPzg@wp_G2u~n`3$Ys*D)`{hbWiq^98&tFY0m_<2DE z;MTPn$03Z6HJq==qD9iPyr{~}Vd4yn1MstLI=Fi5D4%b!gkAUG26jmBf0*gNPDHaF zTwg2RK6yxK1l>_rcSs)8c~WYb5g7L*WP)wWtJiNkci)*M#~>BP?{R0=RiNzcd?#lg zm9v}5hS*od%e?hxiCJZ)hsW$wEGt0pfoC?+a&R~H8m-zuMljw>M`_a(0b_?svq4HMFYyvW;k>_T$ zHiFJ(!Gt-gYyR+$&mOEIbT0S{&?uYl!Ywbvx0F#7JuSNqMQS%4x>~RS~lgU~k{Eyxc6UZig;i@5C%j(ng)`P#O zcUSS0T*^f1^Ec+7u+PL-ZekXXJ)h26f-p$M#Tmb)vkwMu9p5}IyD zy7h2t;A&Be{o0BRMzr7FsIcYe8*E?ud$9t3LhcC^7QEc%ty0gMqgn1wst0nwinlL- z#+pK%mAD5Lzii-`L^<`7Bxzo@tPEIZ8dK1>>n@UIz!KIc+Ku3&wxUSm{u!68lku08s3wLlfRhn} zt01BZsos*Fj#HXLtOg^`xX#Vj7krmLZ|!keaD`n@iB>!az(Nm3_Bito4~|SK4h>2- zdmQ;c%NP>#gi>;q$d^F8CO99Z^zE+A%o50VU9PD;YQ_Rod-K{}06RyzmyTpv!M^`8 zcmH!1|6hD6#1o)RWYf92X_JjqOpQgWNILL&EBU$GJ&c2`l{sp4Dhz#DfJpPFEPJSe zXC=kT~a# zGqWMUD0Yt7mzpKa_oLXYhqBApoM)8n9TxcTT(Ew7@SIcK;=>(NNyeR5f+?KA<9=KAQV zpk`l)U7oNES*qOf9W(O)eB9 z*M`dYt8TFS{G=$NRMj`hw-(M!KG9wU!%g^tcbqW>gNMfHv)7kSb@KV0Ws^DmKMEDd zky@u4gS)!lBB}fgLT?(<;`H+^lAUf)FMHHpJ>N)Zu_)Kyv2qe*5tBR{nBAm#s)0&7 zr5J@mC$0+bV{`45b3@$E0+F#_d^zIv+McYr&lO=q*?FC6$3oB4UjQkReY;WUCfZVd zHb0Vb*4)s%N=sPX;|$lAE{siYSN#c&s77K%J+1n^4iHa~_Fe!E@waj>0O|Lc7JRH* z8P!CO_XxPZ&=W}F*t&t#rLXM;-5H?%K`&uq?CQ|__K zP(>@WgvW@!U(sBgdlB{c5jDZvVrz)5Q{y9o!TRhG8I0rm8GzE8bqs~{62axzpOUs0 zTOGQG8yEU5bc8%3ID8-By)?#ig@ym=(R#G(JxP|l0LX?tWd_6U*uAi7+Mg{5QaN-i z{te;1XB0Ymx(8J|3(wgLfL`MT5K}~pq`ucxvZc8C0=WEHanBh&-lIWGOc)#tAME|# zPZ0UoN1yLy@?HSkmuu6QKE*gc4rd#!PsUFK)2tK>WX1eSzU}IF`7&z4VsLEo?OF(s zZ^PG=?5=KH(dAUEonW~AI+*ri32rgvfg8?lQ=JVbYiE7|C^D~(OuMltwAm~&jh0Os zQlV}3MWG~o#a*n*jdz50yvi1_J$K}#Dj~oB}4PtH;`o8b6RWG}Sd>wm@o-%ym1RBFPM3V>2JJ$`K0(^Na<{rA9M) zAz<*SkQ=!LRPkU;25V|8wYMz2=b&Y3NCGthWlK;<$T9(1_l*}RH(Akmdm!sHy8>kP z=@s6YB^{Wve5^FqHt|IJCCD7fWJ^&iqisgo@meEwWNNJ+ zik)_v_>?S{M>sRkm<5AyPA-L|k(x47G5qD^V){@8ZpWIenkJa-jiy81+_6ZmJ6;iS z$r~0Xe+wGC5jepUK(_Bhfht0zbV-uC0OeR)Sk|j#o<#qcI!azD8XP>(CSERmlcaXB z!~$21?wTruy9jGC72T2ZmN5%|#1hKJy<$cRO1(}Ygyn5V{!F4HwVk<&Y4=WWe|Ye0 zE2{sh6Y~b9mUCLOl4Ep9Hs8$92vathC2HQ4H|hS~j05cOxA@t7S6pVPM2b-*nw-&1bG3!nzZ^zGP6 z6C^j$m(J~so7{$$7r=g}26U+K-;4@6H8;Dehk47=<8A)4$dS8J$qgcOjNOs%s;{j-At~MxWT+vG z?cfD%3Cp9S{pZGnz~x!S1y#jU0>eEU71R30lg{YleW@pS$F<`B^80P&2Vr4R*Yo1L z>D!K{Hj8K3+*$^c41|hsIrkU9&}_%{p_CB1Y4HEpRiP?q>safk=WAaq*hPO|N)E-Y z-r1Lb-Fr%BAH*xYy2IGCm04B!-F7?7D#g2_C=8l zZ9%rAnUwAFM{>yfNNb=_vc|^TId$Y#(uVD_bCuCE3&u4%y^7U)!;2Ac!_WEZ4q(W` zo2}#xo1-ct&)-B$%coH9WxO2~UA#F&FYQq3i^7b|bdGY&=N3%WEqOixm=qCpZhI}- zUrsa?z1g0=F1wAI569}d;ljV5G5>wRXzF#Z6Z%p2nfk>G;6q&G2r*sW-|BrQ(P2%q z%~+ zCq$K(CbT;o{ZIvN&CeX|SfE$II6qmF?-S3Yil{yPO*DIbEM04J`h!pAuSA+fs)4_C z7~^j=!Wz>O@(7E7j`AOIchhp?a(@%O??`s(-^KrT(Ic|@uN$fSox9N)CjyJCjjiI3 zrqKjasoPm(PBNYw{xS>#=lh#{Rc(x$OfA|n9SyWrllxd{OGHc-GsZcsf<=OcY(c!} z$cGT@ROfepQ>*4ovJ;1_T#~#jLZ!p5&f#(^EoDkLD41n6(`Zx7Ao!X&(J7_wNnxj2pFFZ+~|J>l%yqZ{R~Wp7@vk{#`Qvw}Dx!9P>A2 zkVlvVbe^vMNcgP@0lj}??LMsH8M1$t)rgbe&^}O)BK}d(YskuK{y}RC$(t80Pl*ot zN#cgGp)EQEPQ#haaw#rj!BN&^^)Sr2p4{jyhdseWK^DHe#`M=}mtA(Phoc3raFJio z7sKa`1bsR~e*i;x`d$~9e)|GQDDxVajt``nTCXW~`%HeqzW@l zDVnq^(S%Igp7|RiV{O&Hc({Mxy8X9{KB7~8o+08VVq}AumAEDI^B+sJoM}#nUqlNK zcyyu-AwpylJc!;$S`MA}%hGg5pmq}JjuPYEO}67N*%n*O=Gn=L_ysddB5~ArMJgrP zcI$m?d64M*4ws$9i$XVT^LV(~+L(0Yk$YuQVKzS*pBm>TGnVK_IJr8?OmTLocloPO zFDI8b4PGSUaKQ@E&$`zEm!EbCp`(7ttw_~~6Ul9P$4)sWYK8O8iXq5!<6P(xfDeF> zNT=2IyRVNkaEHYj&p!v8BF3^#6Kqb;ixq2!AH(Yky3{$L9wr#LLt>2=Knt0pUYH+~ z%+U4TK+|V&YqY@sl&Wg;LEKmLC8~qFt8+sC57yUG{oV5BSHA~bQ+A>)`aS)VRSvVf zi$~$u=Ck0#yY*lzf#-j+l8375fr^~iDv7=zfQ4BzUjUfpoxgtb3Ot~l&&-RZn5oeJ zMU)ZP3M}se^qs!e?}xZA)UEmX?$^OTs5pqdOWsBV@)XrvvGcNt@w4e&q87o*n& zd=wM>$9Hc&`nhUjk-+47Z(MGCc}8MOKusqCDl1R^(p@--5}e^8D~oF`Vq(SyuQ7KA zzR8ae4R#F~?nWgWp@q8>Fdr5TLQw?>oWbZ95NP{aw68eIKS|bGDSQE;M^afIYB$h) z#u zVEbqP5wpSBo2uEZg0*iYt%qB7Nmg#Q{ol9`MymMFGgan8L22VvzQspA8^uFm8ehLw zDRsmVTKwOwoIfJ|5A6sOY`!YwpCI{%=Klc_g0b2X+e#@|!P!of!9%*FOdD=5NKPqGSEP06c+i)z4dZd1`-w5*^KT zqo~sUwIS9ofM*EA{olA`dYpU(Ti0)35}{(&zhci)_qCZ=AX+QGhur!0zu+wPKvego z&8ptIh9gTuMzn4XEbRNx(e~EL_XE<0rpkNo7XT^8{0kuW3l;zW_#g`AaK?Okk&KsC zrRq}vH8n)uL{48Yb}y;~={n2_O~ZLiqwflkDd*ivy4C4cY;wCJq^aZ_#U*$J(-Vf{ z*w!Mk*Uu0AWT*dVUnKpoeOVdzu?w`RhtQW^C&MIk9q;*BR%%4HDYB3u%ALFiF9;?0 z768l1Qc!eQzdBZDipf$XTSIGZ$-!wwCHgMczx2aKWoEaj1(2729I`Z((CNMDv5hHf zUHhUl%bZ$nXQ8(JgaIc>8V7!uhjC>i982o_rR{itMI{fs&foV4{$W938QaY3h!eEF zg-DeuX39v3V29E(!1F|cd{G2+1_^)2Qa!$zIenkpdrGOrcZ!oNgEyP^XOri3;L()Z@zI2((4pp8taHM_vEtM zeC?NYU=?vS(Bj`m^kyfZLml?zTe03QwaPbD_R@BQw1XlwjSghf!?dc@{%FS?_!dPw z>>Ge|tI4PWI;~JU<#5Gn>qn3Sy`Nn_XB7i^0bOA;wE@2ecBW7m5r5CH|A zcQfxV$JMJXjvpw~^Ty$vCF+w>jOJSAB$T9r-Uq!r&&Lt-qlE46KI(N@qynXuFpx>0 zkDr50e*`p?QDm9+Cd&H(6Ys0w-yw%(U4wYI#o+%9dtSFlf2x zqk`CS64%}8MtI<_-k&%4)yj~s)jJZY5n7e(nYMy zDA@-D&eSP}@xB1emt`Fv;Enu5TF8kfin?4x?2R?C>ivi{&L#YitAf@6&d}!4htKDz z^Ge#8$D5LO(;O}s3A0(!xV~jdiQkU*jMj%cy@gX%Q=66}4c6ACdw3w*EczgIkZNJ2 zh6F9y!Hd9tOKadbEC6a4D+;Ime|7lJGsw6SG38+6+Dxr9z5=c%oGxO)78Y_(0Eg^V!ij~aJ6DhD~g_s|Q zAbXtO8OmU`3?}jcDpHMDAEeAC~)&WhSRwz_z?ei9sZcMD1fu z1&0FTMP*^5Dl8Lkc0Aw!u#E0(4x$zHi;xIZF-^QIxVVd}>sHz=YYkg_RL;_@!ncEw z15A{%7Ms}MN9Vd#345P?i0_>|@G65U=FrEr90O`T=bM$hxPA7?q5{wUM%(|nFY({U z7&$_zE$^n8)W(Fx!bH)7hMT#tIuCSav$BAp=C?+9>wKNIqaEk*1GJi0URT5PE%A;0 zM(xl&KfpfXnCL?t2d3TKwu|4do-~D3Ka#mey8}jZWYfAH|;XD>yjT$C|-NqcL z`<{EFa37B@v%}kSqaCF>3LdHWROS9A>#T5~NNW4vYy1C}N(8cg1I#;- ze`vmQ3-7aVeGoI6X2Df(VLcQ91xb1vD4E;GdCx1HU&3)kHa(!U?HkBMiKg%^E7c#@ zFPWYa%PxEYzMqpYyrPUU7B-OzG8v#pHgz5gAj|&ChxkggrgE59uUywsVmB4O-XC45hPS z_zKhesTfAZ%6#0@!g5>J!1eVvXIFY&x=$R=iejq~!=>8Y3Y6!hE9$u{F_&*IhE)cK zyLe*Nw0a=HyBR6$haE{$YyLK9l66abic{gi=2`);`bHC!jLJZZ95FvYYF$O}Y%RCX z6g!TFN!Of{hZMVu6;(>zQjot>_6lvz^zJShRkbZr1vC2vm%?1tc-jsemLpsX{9L@s z)NiZw+d}-GtBsbl#We88k=}!wdN2EX z*+Wj0LIV|a;}i05)@KWc0kDJ8P!mjo>5=N6Y+l;E;?lv;j+I@9;8Q{DmtZ< zJ`WCj_b^KwEe>M{$FXHkxP}a5j>7z;_(aOnHDk0jB7Pn{?ecA>iOU%ww2#8wPjiiW zj}(UJ`xbrATYW^5uJwdsS%XEqsk6dE`2H8btHF=>ud{*F>uezYIvX_nbYRF4uVH-H z%4#cP$>cp~Yh*BY@b_mg3%n1G78{|Qv#rsNT7uy}Xm*3pe}8=YR#L^x~p^LD4>a@jIf0qMwG=){Yd!I5b1CX^mT6Z={z)vWHuq zn6GDHmk<4$2@+vPCA~7J*LmLWK0z$)Jgk9Cu7R|CU=-ag3MEZG9P?f5Kp|f|^~P2z z>Z#WCF35%xdnQ(0{k6iB)M-s${0d`m;B?Z#-H3gblu%(K7ObyaR~+bbd%!{8o^!Ih zZgf382*oXdgh#%wF>iA^gu(7qeudU&2FV;qGt%a=d*&=#NZ)kEi^Q2mLWDeGu}iFU z3Bd#S9zW)GKw#KXu4`u_-$4-aP>ekrt4@C-)x354p$_-rE~B^{e}mrQ+Y7+g;x7gq zjmc0-3lMt#HU;C`_nZ~*BjSFLMRW%J!j2+6B7t}s;yo3)WYk?8%PbnQ`en3TQVP~F)Q?-doi~d9Uy~J8I zClNaU=5)`pBVVq;%KtplpgG$@>E-gmC9_C||JAf{P4cu)EsW`68}RD|z(w}#y7B67 zBG4QOsljpvJbb@~#^2l15)MJZklO6A(BK-1cs;)J*?;4+58uWyI72L$LoJzF%z9FTGIDxnC@jDSW7Sr`9e{rom%S5L{#CEtm)5BM*d2e!;e(E6)-a0;=h$ic=MoYhN304R!42>N5@+0)Kss_!z`tf`l*W_B6YUy`NAvH}hNfASHsz*@ z2aLFO@20a;VWdBu(Bc>|kV;<%;E<;891W@zPF;K%BTj4BN@aC z1}0i^m?;c-~gWBu7tgW9Cj^~Nv!?))kjfRvHB~>R`HqJ+ogm>YwOp3z`ZfGcQG7D?rVi| zM>LVAdT>oqjgeh-l~ZUwL-tVB7$yr7iai9$W71c72XB2d%x5_n9xmR z$Q%|#&lItk--vIE=;!mNBO2xp+hasB=C0h>D2I!EK+S?XgBr(lbm9NF(d=cJI=*OM zp)_vCy*#{Mt8Aj{5AjS;&$oA(^edluv{v#RDsf#Bzt)t3pjW5o3j*#K?cuUYC z*<;jNa4dqdTETMDs=Aj^0UM>&LhJiS$46n9ENb4nLJt#Ms>ky(PeDkU!xsS1BQ!#n z96r@KQO_PlR1)KULsG~h$kqZtJs2E;h`kZSjJ{9g66PP8NYpHgZs7_4u@~}+81)?o z4h0=*0OgxpXUs~-rVwgcoX!iQ`OP(7t#NTJnKAMHkHYDx0WjrG!2K#H0bZZDZHwe} zyh(VT9>Pshc!rb#AfncqP|CMfotvrF%a2|Y0eiwARQH393ktsdF83uFzK1Y^Ydyjl z$`~g4nE1l)AwZD3xb#=Vlt^(nBG=R#hP*Q{04Z7yEU@Je7W3UAj|gpI+qZMV^BzT44UM008?=cv+S2huBjE+0hx>>kAov8VuLa+hhIySiZ9e6a zWtQ+h0mnjD>z>ZEbYuN%(J`-ug$4dZo|^<=>#ki@>+Yo!++>!as&DkZ^Xn*!_IUx& zypE>2H<*rD1^JTMElqRyrmG*$v(G1%!d+{*oML3+3N7%DNX1$XDs^so@p9|+kvIuI zo4J_T+o$iiRdW_2)>8Y9O?fgdg;rM_smY&m4QeFF*IB%WUx_N|7xKow`-FWO1w{X?0LKodA`- zwCAa$SYpc@q#E@V?Yp6r9BMRZH+X1PJ6mOG#uq74y*-H};~~cu4glf?YV0;T5c-R$ zE~lp`vA7GKeqqluhtZ!+ES}8n3ee3IK}v~XALC|2n-;^)P{owkpo9*{UM6GH>4yb>3yqjO+#mUQ~n{4 zphRU`LyO{*;ZM&ZppIG1`6efy>8r`Ly37i^48xdMI9QhV!h&*JVz0U_%axs?uHPyB zWW1BF$tKcBfnkia!fVt4OM+?(ivK1c4~KNJbmW<(n;cbxJl!whInOD?0f}++ZjZgI zOd$vEjd}yhCtS2Zy%o0>atO`2Z*UCY?+C$`YwAUdOTAKH{nkuktx`tel#s%R3mlylr*8C;x!-nMQYAEo7lGE+YQn}n;xqLGEE5(6xYflVMm_U}t4MAO>!f_8-V zOLb7GyrrUSDG8Eu@CtMCIkYa8CqZ!RG@3a%8dMegiiBK^x!lE{X3t~H z7N5+VY4Jvc<8OPTSm($6)vRgV-`LnffA$wP>!Frx;3|8x&zSsDs>A%~)}Wp0N2^dS zD<|ypRv~@wOWQbJFW*UP5&#WO=V!F$`o=&>E1}H@+1v{BTHc;YC|H+K$vh3Xp31wQ zc%om~Qia4Fg^fFmH;1x`;-+V{TW-FaW@?>2!y=_@-6Tni5J|Ov_4CbqR;htl$_{xW z#B^K|kfb!3t4G&i!X@Z5NXyjeG}5eRsl%L_u1O`PQ&V?} z-+1>k(?-9a~Qj&hlagggc)}3+r6G3-&K7(*Eio$R0Dh4%4o%F%o=tAwBw5= z%qPQ=^OeX5MiBI&UVV`aF7d-6y8Q}C*#g_l@o>Cqic5?-3(QdYiWS9^1CXc+GnQZg zd`sii>s61nW%sYdcc@}nCaZ&PUSZXD_#aa3B5c z&8^og2~{BX+X}6E?A9n&B$Y_<*T$cQlG{v~$*=a$eGyfl*bT+IeiYJK^9#c>s8Fa_ zSrH2bFV0Xww=N`v@DKr^J^(qp>Ge#(_cd{%+#rkCDJKKfr8;Z%bBksZ&zb!hAr=hu z{IOC%sILyrI5~?1+r0C2L?+?xpW0978YQD!L}<_l9-D zGa=`O+-6!+xJHhK%1X%Tf;MYqNnD85Kn-3Lm3%)K94y90jpzpHmI@gPbd?DKGRMN# zAnye4)7tkk?4ZxME;D{?rk!gF?@&`@JTbZLD4B` zgM)K~qxed+0j1eIAUq#FR{>OR;wm0ub>ze|t#$Y44nirs?K31={LyDRj*E6}cH|Ss z01hrzI`Uw?wysdm2xnnoGWzb}niQOO7QDH)-PBjaM|I?3XEB@B($%15VngkqY(%W7 zkHjInRP*S*C1gqN_iQkv8_7rYsD)=B5Ymk(l7>L71rtN}24xi9{(<ZK z>49$lM$zSQq6Fx2E3J5N#ejdx^;M3*s-Vx>)gvoIBJQ&k6IUYS?hZ#KDd+GZA;dG_jiWGEel#`v;-@|>_0UEyl`T(MRbXC6 z*>Kqv?}HpL<{p^{c%x*}d6E|HV6~_4lT%d1@Y89VUYRoOKvOW?=akqGEZVQ*rN#qXdN^^Y-aek z1}>Bj8!mBh=5YRpVkVpV^--Dd>RN;VYP78DQ*dr|BJ zb{(5c+WK6TS57b3J=X>5%Mqo(e*`>626>!z3djLB9 z_Or9j2VBPG-g}vx9H4W>X(jV2Nq&ww-VPzbm;BWU)aA;&Q4S%dMXc@DDCF_-U)_H4 z%#VuoZ24@w$x4KM`JUa|dEfm|W2!s9cJC28Le9i(UC~a$n zL+ELGdv@I`H-Q?vwL#t}_OPoc zEi$3ogZ&J{w!LT~A?%4*Hq$H_KagVc8o)nAdVQ&2%~bmJ82iLvtgj1)6wVPH<;_?| zo5m4#8 zK!Jm{@>KFNRUE>4erHCWY$p$KXYlvkRA)cGX;9|&d%;#h)bn3euQvf>$4(ezxiPKW zqenL!bC{{?qZmlIhXmh=4ao@6xEQS7c9VkE)pi>_{3*D)051U4C4#Ga>E|i59n%zE zc;$wW(HlDCc+&u0cUhVVopzh#Yh2^*{GKGVtmYz?c>ds9j&d^t9Std2jv(oXpN2{2 zg4s`>MG}lHSQl7Ilh*H3Kz=A=|2=n}9~WA^w238hGMS2BN{Ypy?KzeF%W-%yHg~SzWVbn|>4z zg0YGLqnhoUHA zAzDj?@r|g+^;XQN^x&G}mGwF8&4wb4;qe9Y)yt?E_ldmwE5_Z;U9M=)3BE{B_Q_c_4J7 zCR20PjgkbbBJe?*MwRsx6^20RH@wz}fcb6c#6%jBvA_X$PTae za%3lIeDp^-+i^60sN&2gFkK69J!#wuHad&7>5B?WeJG!e;*PObv*G9O?r98c3#dV; zHM{;2`$(TW`lCDrpbcprH?uBMElbY2>h9qY`R6}=M;IHWBEab#Y=5HG{pS7ZtP2ZM zd@cKd;hG%KfXKKwN!!#e$y;WwY>ZDg5STh*hjvW}bb!RgADPSQ+*c~A)rM(x zdJVYwNUJS2Q(SjsFWcwvvs<@Vlnyi`O5jWm8~vFqk0mj1z*|8R*<4P_7zw71scv8Q|Ll9%e zws)*hH{oYDwPda$*$T+b(}}{6{nH|&1Q~jOmdK4zb2>`HP1v>MKUvWGW6>|NfSESm3@Ojw1ZOi1i+_T?)d*^O^5D~sDaT3(x?ICEo5 zL!|n2(_xd~3r?r-9@g7v>Ik0J6klFVC&%V;Bs*-E+-HgU-UP9n@H%}HfUgs(H!0Wn zRjs|t707%1^G(7R%r?1jl}YN$EJoq$=}K3W=p-{}j^jh9n&mZKFnw7cCCF(lJtp3S zS*_X@2f68tEEi(;s`Px*Ogl^0L!&+`??&wQ%ZNakoN`HZHP|&9xj?pHusqp?EE-joz@2)H*~-qy z%zi$9v+cl6_!Hs2nCm;|FTY~kPaQu$z;H}jRUFMMe6q~RwofEx9%fJVzrPp>d-{4o zy!wyGD^L!CpRLoEXtsbFQ%7v3z;?$)=_ybj1VC!1tb)m?ztYgx?YzQY zdW)&Y#~ecH##{U0-|UCn^`NWSEC%*=`h!wEf@?|=fm^;_2<1z+8wW-2X31)`%uIzTZC`1E`ncB&t2FMtcX;5$xD@%DY7qe!;7;|Q%rBN^p* zmh$0bbelg%{pV#WZ zRNm%DHpfT{oXsm(MEO?3_L~7GZW{6lEf~cNrU0%LuTarUi`gl!nk(P)Y-uEeLoB6O z0>?bjQGr>_-mquyM5mA44}*uJ4Z%|wt^V%1!mfEG?_+I(HD?rw$&YdwY%KgS2I!th zGC~d4U&G^KOR3^JPT*zNxwe|N#QpaE>!M`!?CZpD8=?`$CGREr^GRo9ZM#om(9_*l zw_^5j_TSZNW^isJArT^N6_2HzKDj?iJWe!wk$frHi3&)8a-K|c|#7p=^XA37RZ+~tauhaBUFhf@*lkR?u& zk^|MwYO9&Wu;4J3CH9r=*QF}kH0DnOb>21?NG4{o9=B{MnL0^JX0+f6M?=NqYGd8W zYcULajetB#W<@;?hIR*mLC#Ipv_xy85%|cn_sOlCBn2BIJyyU>qimkzQQ#iHZnbT& zxudgx1AMpwEF1x41kp>xf6SgDnj;Bu^C3iWIT?#RP3rGcP(Bf6nL4E=-l(mWHSSuv z$d@-)T11bn<5{9zlpO3akV?$q`N@6=9qmcda${QBeT`;$lo^KZ|bQ zaLE+acqzj1Yrude+JM|#c02Th1)}YHKZy01Vb4#zMxIfyCbs<>kM5_dCll1T{LFTB zEUMYF8-fAgq2XZWulOtxW?vV4*3wlXv>Xq7Qp@OkC+Dr8Z($y`@wdzQI|qRw&M`H# z#B02<`0wV(XNZ@oJ|r=r84#&?ugPt$@D!|5^4>Wgao zSPN9p(zW&>O}UT)Fa|7w=$$<76i?$1l>M@2@!6znyXIqaJ{`Or@gb6n4jSy2hJxDT zjagOI7lv4VJ?7E<=P?gulOVTbJAIqUvlTT#vam>+BOP)Frg7w#eSzod(#6tLTu+)2 z(Brt@FC+EZzjn8kP`ESR>y&tr3O?1m@A&)Lv`2k<<8Q0WT(>$#**fXOTqQ#I>Z?!M z2;6MW91+myzhK00$$#y08r_CVKP`Nf6IRyF0dEyq+JIHbOl&yQPI*2wd#9#N4TiOB zHD`RfY|5a-ZaD#`irbn&$4s$9e32zwrn;HvDVrT%HgxyzsuLb-tE8B5mSX7TGa26V zhPTB}?7T8sjWddZdA}6oH`2Xjx!Cr9wDy%zku6J?&^V2|H}255J2dX@E`_^GL(^E} zZUx=A6zLMjGKVw`r)7K-(Y6v$Q zz#<{=h*+fu#<(c5C+Et=D64oh8+dAR46n@FvsYSw*<(JN{t!nNl2<;Ufvb zsW%Puok0XTdf^OLN&XAtWQ*kbt)`+2@`vbUd=p`=!>jCv*7R}LwRM>rPg)v19v>US zJ8n5T-}Cp=JcT2TM9l|{|M;Bts|nlY0Zi&2??moRa(MvC(`T-~dZ1W{0r)FPHTo-j;`jfMaCDSXcJ_(F_RQT`h06Zg4xX^VYG>s6&AJp-vE`#f2oj)nRKV zg_4uML+ReHA-5ccOt`X*_J{zJ7=K75U%K+D=5#(a}*aTrHLrewSkar?NCs zqv2g6GB^ztUK2Tn=I_E-5!S81t5o22(qYi4qg!;$RY7==Uy4NNreTQHlKkrA ze6uAVXl&x7i-`2NiC?`Yu^f))|z7F!G-kN5)BY>DPen^PDbJ;l>%^W^>Ox)=foCqk%Ah>6q-EUn|w2f=gJnMdObBj7+1OY zya-;g`{s3Z+z0XHaH&F00>kqLYfQReI!K!2dr#^V6x7En?hjbKt(*PEt|Z-meRCUs z3ug7h)qC!6I*U~=(>V}*faxfmsfwD02`b_GeH^arP4C@X=^@JFf^4 zj|*X-qG_Vf$JYTc?U~csN8)jolNdul_>D-ZIR3js*XeX8M`ve%!mzGY)IHH=!LWFG zYeagczCpHx-%YUjp+ON&daM&V?tH3(hvH?!S@%=aL-B^|i_}X0HOJ+V!_Muv^ zs8q-Y$Mniz^dhoRUujp=w9TlPuv~OP_Q(O`8e#vl>;NM_F_O;$+@hUpYd_D>Z)qP+ z{di=&?~7>8A|}d>92Pe9y8EZ{H4f|ii>3@<8>y*^3^-Xy*q1w9?;8boyFH&qNneXQ zm?w6;x0)y4Peue#_t2V&48fF-iVJYZBp~G4t@2wVl0R`QKP$kVc{Tj_J9SUm!%}P( z1P9Os{@lsr*ryTyD0^@2!0%H9Cgx4G)jn4NIk{x`K}Q0JYbwFT30fZVn(R08vsc^Y z>ZkteiTiNzzJt(%OwW|Bbz;X{3y{CDx$}ODt!pI-(o%saNPvA zjtDQ42{;OHv&XJ^TfImyC!z)lBf@KRIn~-=b+J&lIw6ah_Z;l+KN1%)v%eCVjdp0k zL7ZcyGI>~Tmz+taP+R8VRZFysSz@v5yvyOEapvtp!8=B_#C#^=nh5yIG2gFRFIVo` zYTt5k6xE ze4Z6j{S>_sx>3IO^9-$c{)Q*UuC%`Yvz_jW_$mxyz(OMc7dp$Onuc{*EIyK@p9?Kq z63v?}=W*UE*s0|)~e|HSbq zRSJ?B%hSDw*LAMpr<~pFt>>2*Dw;y$9uz?(hQB-r0dq4Eywxr3d8Vkeg85T7^f6zU zumib6?=Q3*Ub)^J|B5)0e=hQ$_UB>oznzZRf6?PO|7S3%94tOw#^0$Y-uE8N7yZM| zxsH4Nd({8Hh2?!OBtYq}LHXyBOa5UO`{mO(du=tqUHrK=Y>Z_oOs2TyS3o0jDd(Gi z-mqS(LZy6ij^>>=4xr zie{kctlB46hoc6)nfqO~FqzNshK}~d_trD}c0#xC`CDrT-b``-ldMky(5$8)RkV5%zgP0oP`fQe)TVtw@>FLMw`h2?Fgc(2h+Dc2E*>&nYirrUCun*1UPAg*CJ82I zni~1v5bQ0T%t@}^?ws!hUn#?`R1-hlfjyk_n-2AF-z)u%-~Tj?|4b?J{~m?^M1=(Z z^LBF2`yUWXT%aYKfFpa|5KU0gosOMDemX1nb72zG?uCJ}S5^4^4l>NG;58b?huqKCH1zE}Yp5 zLJCI6gUn+%&jahKfc0XER=tU1uzf0&obttmA4auc+{+E8k$D!Pc}kC%%a*6_GJP89 zEsoWfetA=f3pr#-jq`oSrmzI+K6*|!6ci=dtRLB@BMdQ!Ng6sRdN|fb!ZPwOnPu$9 z$BDwoWdEHze}SI%PM;941g;JL1l{N#pws+aG4dv=ueKCGJV^)qJ*wB* zqy6)`&ifRiz(0rlr~S_|6b62z{3{jzw@^l0C(#k9Kl(1@7ae1@FDzY=&QSGwFT5O1 zEmbvf3;I6CueRe{d2cm+jsCN+<=sCDwNYtLFZyaF0i1e*ZP^3Suixqe0tN>D6XO4z zLUAnNIk_IoT+S~}Vzz~6WDnx%vII`u%|dyPisYnFT?4E@_MmTnX4~KSo^$EPBTe#F zBJ(L5oXy1@bkltszsKrHR>RzuR^sX`^G%!T9C1c zbT0R)^7x1>efMXE_krl~H?;S9fu9j|q{Wa57q`SMUGPy_`QUEhL7jg}`+&!|#e?x-scPi7~ocei5 zKbOk9n7W>*{lixNf55VJRPg!?g|lYmH_ndTjgnhs3-mxoT$Ra=z~cUdOW^xIX5~u} z$c^X>wc2AB*D7FE`*81xcWYKJ@g#Gvg~b$PLmWU{4R9!($jtsRz#AucXXZk{rf3kf zT3m@O_-2pV&rok$qhtV3tHI&i&~RU1SIR_RQMA)mCK!;|9fu^ndqS+4en%ZZXqL_u zsF*LvY4a2!wsAs#l+bvJ-h6gSiAC#+t+$qH1Evbq@_-e6+Qp2p+O@Xzsu8i%sfsxb zrgbh$IN`go@)v%e3Y?P-5dGS9vuzzn_s~_mxzEun6ame6q5^tT)4wmqnIi6@k503p zd`u4b8hqF7LD_0yRNw3=W<5fdF?$3MisRSV59?$IF{g%iYM4SU2lVJJ-(Es|Efk;D znkAvqL!Vy$j%aYvA}6FMFv>iQ#I9xblnJyNq8a~)Tp8G$b3W^E-p4Oio5>`pUQ2DSX1%RWQaP4KheQ=ja=9&vr&3NF;F>x)s+3LU5?fAk9{ z_iB+w5kVbz4&$cew3U}kmt2)5zJ%1_e=x+%?f=?QrNkgIB>Zs_+oQlsSb*WkF`dE@ zC5oEb0KYuiNzorfiXyp9do3yOBEN0fpd}-(C{cOtPn{!_fEX zF-TBj5hTA6*7J(MclDXNR=yoy4_`uTeIcJ-Vyf)?PJH>DZ}r6WW}BW6hvLED%yk}i z>i+c8w0LWK1?mnI;Kc*=i2i9CdCTB}%>(a_qWWP4FX1*?8mFVNijh7hVkFtslj=8C<=g02lEbLhV*c<2 zeh&&u`^Xi;(wl}knV2JPh%dg)JxVIm6sShBQx-&L!8UxDwOK3!;<}d#IP#O^^nW|b#+Wn$-E++J`U7dC|J$g%R*#mEIjDFhX>Ocs0;{z z%K?+IjUUjM9-L8Dg#LiAUJ+b*e><1k&V)^*VRxTP7fnt}E9mzFLo z6iwZq7}v+^=T^36Z7SjcVR+FB8BNw0hIk3LRF?UG8d}fI^f(o(J?H2MiZlwlK$?Z}(iI^HTfb1*rNq3YMEA9(&XG*K zd7w&YW1RltsakT5wU=KzQ?AXuHJ%d_6iLjysL5>gCzcy%$bN0vo;#Lk4vKPc8nkzn zhU*|rKy^6-Qg~&bP?y=<4fQno)&)c9*s&7zf#kaOLUfY9Zz7q+1TDHMN6?SNL9t%p2k`iHCq*+^Dyk8!y+*~u*{WM4xmOH(&zqTZdN z1Qp7;?LRr_j>=*K3Z>5C+eWp~e?Uw&ko9(FemF>OD@EI*#bpG7w9n@mf^~4PBtsh* ziEf!FNI|x}t?rpi3BOAS#kNigW76AC;&KK+hV^)mv(HF*y^?#cV*|XTJp2{B{4pvn z6)najm({7JMA}|4XCvWMP$mLOlsbGP;}y&9IE@4z^J#H+}(w`%S$MbRm z{6;KwU01&rd}Ialo54b(j9C==gx0*E2X2hsy@#8}2+jZK z{OB)RAmw9H?2s)Mx23(VsyQ6B6Q8Pv??i!P;>8ZluCxFhG}hpJ_ zT=|IF4J#3808d_uW?|ZGWyX}*QR6I{36~4otOa^o)4>c3_(^i>^Seccn%{3bALPH! z2!x?0rdE%`p}fL3A6enTEq1 zU%Ogb_2D%Fhh{;Wg;Hm#($9HfX>Rb&c?0Q8c5PA~4ipdvq;YKQP;2@wcaf4!>BkOR z6~rtR{?dMaW5HHncz6J$mNTjj za4JQL#mPi}>g5S(9~h!3{>aJzJ_WdY6iWq5e-=Er8w#?Eojs~hS#$gVSs1BhrG$dd zNbE#Y?wu(xh<08{!kUrn3RFRIIcj;D49WQ3yfOew%HG*o&7LrXKzCQ*Hk8P1LR-?( z6Jp(W`YbjVq|v%wRt!T^Xpwsf6MPigFfsUZGIL>k!FPuj<$GMi8iRT~k7%|%kVu|_ zKE^|Dxd>-JH^r~(ZpblbS2>vp@i;A)DTU!H)|K;_vi58M$#_2bdL5ySO49P)oX_y6 z_|NY|2H2zDz}(oN_^51={eyO-as_bu9*xceuIu4BN-}_Lyv4iW7!y&Gk4^Xj<>QKQ zhCj%g9;93V9wVPxh=-4o?&wP-8uf%d^wim?w@3P*xhPD~M7$=F_--9XYld&OVe*$F z`xMo}6@M)~2iaL0{?wk_o}$)s9IMi@GJt+kk$R|t2-lu=g0~HDV`~^@*b;LT(5laC zW#;*K4?)AD-PfNPvATbDACj-RKAz7U4kpJs+c-x7>m=28cXzi#al@UiPjSt|poYa| zt6hj}xUy=_P;2evD&(}zhkX2^5dF>;^y>5Ougrib-r@1VP}v7OJE@~AXv0$i|LSXC zn`}OMC@+z3Jwp0HWi$K8o=_f(RJ~2430KEkRLtWvDA=cN$hiVsHypk1KN~ueEfHb6 z#Sd-REz&Hu1oVcWca{HG2y3iGrl|~YLB|D`PF%=eL|f+LQ=Z&gs23EDSnWe#kH$!= zFesb$7s|~YPLU17^keV_i--4wAI-_F67meM>%F&M5VxJi2yebB+oH!l;Zi2O++CEaohv%_+xbL~@n|gJRn9~iT-(~Y<{Qz;x zgeayay&uj^C1q}~=}t!?HIp4nJ4&9NZ5Q276hTFA`3Qvz%_hy`d%ix`K-R4>id4$m zVP=iae>GKQzd~}usQ$k9{IIuB-le$U(3*W)JR&X94BBS&ivISl*&R5LZ3i2*X#o%! z=gS4x_waD=tAY5eiMwy5YOzNtgqtDYsFJY)N(YR0WLSY; zX<_3WzK7yc!+y%VjjP)s#uSYK!ez#wL7k8XXW#gt51P+c=wBC8xm=&r)?J5LXDc^^ z$Zk@81_RAXk8mtpRUIwobG6Fj?Nh>?if_dDElrWa;J;Vx0lRuGcR!$hHfqI*G>pun zt=E3iD6$q>Ybb6bNT3a6sz9X@$x3eI|7dPhZTVL)o>oWRCcuLyQjEpu{ z?799%O_~;kYZb~47rJH+F4yYwSZt(W(Cp7uVcOR_eXtL3=&+Sn&q){Q-d?m1;ba=T znL*k2!s{|U!4_1X1z@;x@{UP06j&HX-1i2_H|$$liUZf@MOd#Ws-wReF9=cS55NhY zAu|C+zFB;MwI5JpSPs&d&79tuEuGahPwt{n%#~3$xA@hWltU^Y`oL2L#;;}qW@`0bcH-eowo%u6*#slwa zR45(+Bx!RO2lPH$=mc2yyTWT@@|1TjJtaF8in zAT`Y!9~yh^;%#u1V_*TaY|V<1$FE$_qBxMRC>tgxuQbw|ZP%;C!5ixe*SxZZ{;TdA zEAZD(70t{dmzK(+!n?N&8wErM?09>*Q4IsJnefpF35N5=d{0_xau5jzZ;2~XXrCjy@9P^p#i%H}Q1{<2#~=O|i*bJ2Rj*v~G;7;v7!$&})qSwW zLPz{~IkO0RO%&E#uq5QpbEPzQMzx^u+hF-~ef!2CZ4J#)6)~B~xL&-)f#4hx2PUEe z;c};6N=hpG>r5P^k!vtFj$oOl#}br+rxk_y(VVSZZ#zyfKgUCRJzap5B?nEfEl{BF zNrE2^XhQH_LfBOX3K--nFP__?AkkWD>CuUyveX&Dz~%30CJ`9N?;=Ug!(@4}_Uszx zUDgA7T38tcJ8Kp#aCMcqmrATq3@h3)*>Kc(eTAhUM&qscLl{O;f0%L zZx9JOF=`@VTwRlA;(FUEVkDXsM&DO^YodOn#q=h%gy4(fdov(=r*LX{Kig|ESMt#T&j|%0 zCLRB<5C!X%wd|d!g_Bb@qnxk9-@y6%+m(wH?}PeE%>f&p;3y2Zvnk&v$-o^k^*eia zMXd8c13lrlXcPxc_vz}MVl|@j@P!ogY<*)i9}swxR&P!hx_ysKIVFOOopPxdbE_wQ zl4#wsjR(AslN6kcHtS`3N>ZsBt6ggUQE6vPe!vZIgKl38GeypG!@GO^kRbC)pXR(g z`%bCqChIZTfZqW6<}p#cau(*i%5|D(kgf$M#)cO0eiw@Roi8ei+{bS?I*YY$A#$&y z>>leDberm+vV@4;L$7Fyt$IE+nInwnN^l>QeL;E0s~gLCVZc<2U6S(w!j9QGy*SMQ zZ&FeJLInRpd!*4|<0^7$gkXAwdeKXI=;)5zFo%i$I7?BJ!^;%i3*B_UHG8$ahuKZc z_jTB4XRcIV*?~VGwLUt>{(P%c@2*9kXQ6M(PL%3~6euK%IW$TQB+9;qCjq7mEI4G; z{@})0F>|gvaX|8?oaA<$a^U(f@s%O!D?dMX;K!}59|Y%NsTm}E-^8W|?f0}d8U+up z@@ttQp=_2hySMd}Xs7285RE$Sh5$FplzRr~Wf26dpRLcS&b^251aSt%p^^AIh@GO= zz|z%_qAO1gO#YISOXVC*jRu_gamQ*b8|+T1$1E0wxg$LSQx=PdVN9rwVtNb2!_LZ< z_hn27e7@{pxt@9&n*uQ)A>vQ*_*^y*2X>$nl=w3TDu1k#XtcgE<)hzGNUY5~kNOOK z+{GAQsc7*$C*rroeN~P+DGq`0iC(8OB2yfGC_#NG(J3E&^g9L#Zt!`~gXgP)JBntt zvrZN19MjWF_Gai1f>$1+vw2>NKy^8awPV7nJ9M1HLa!Advv#&TYvFGHF4+2TEfIik z6J7sH^@A>aiOBcM2ZX^>rh^}Pqg(LiC}OP1sI#9V0%(^-&Fy!>8j**IQw^H-a(ZS3 z#khd9s&0e!FZ!aeCZlARs|Zv*BPakU=siOF{uR%NhW4eQIZLjy(xlcDWJHrH`hW*v zp##_2q4=Q5>sGjl5Y@)uGQy;7;S%%)rK*+Y`?+-br4oPL*`Z-pSF-y2Zg(N&UOeAb zxtjf`7{l-GYK}+_c+U(y;*tsxg_pTw3m`OOiB{XI9iEmvRwRCCmTXPVwsQywK9Xil zzF5a8rbovh@q9U%o(Qzw@F4(M&;$+D0P*fmKK4H#@W1qGNu9rAwc4$$FY7XFpCF{r-cWg`NnGAIzZrcb|*9iUgG7PllVbN`(ug;6K$L#O<tC6cd1cft3>GRjua z%)MpFepxSU=4Ia$IbE#nGkjMeBZ3D9Qcns~1RZW-YT71`arRBJ_FceiorAyLoaAE4 z{ZEyAYmP#pEcrt9qC(@821*u*;O(~GjQSWd5%GaLf#v%T^`9i~1|qT$kEXL!!z`@* zR&5jlK#CyUc=9RxmXp0Dq#7S+HnN*OJFez)Xg@aoE>)B@uFNvsjXqrM+Z!ovs(h!S z{o8#_yLI(UW+Yu#3rl{;Au5Qb1}u?<>r@i6sDqMWj;R0=J{pk~ZUi0K(0=<8-GU{f zx)4b$9qV8$#d%W^2#pwSmD8}vnTu-l^uZ?H8Zz^NVpE8y1uu&7!8 zP@y}(4|-9_x5;Y$s7^n9nW;6GIz=w?#m-@p4G9WAnrY-Iazs(4vmeF$t=0P0I)*oc zQ)=oBBDP4q`J?q5ee?&CoR(G;MrOd)jTmeA<+^1kcP-o_#FigZ#A%9^7w&trev)9_ zQS=pJ7O0+!tI=~KarSYm(#a_V1uL(UWuO}!{yK6HZb(%zX!+WgaL3wm+?F{_+s9fg zX$HTuaaKw%I^+$$fBFJBq6MjR&(BE+3~C)B^E&{45pRB=}+}6#f<4Dw?%HsQJj}BU^iMOi)E|g zWDm-9OJni1Z*t8JGKj#rd=>A`R*fU(u4t8mAi0c~Oru}`owWah4WS}xJ{p)gSL_+^ z%uTGanff9vwI~VR#*5~`dIE(~3Bk3O#oIC0w&%bxowk*^KwTe{QpSY!R7}iOkYu74 zIy)>75OVUym3tFtMB8_!?YhH$JB&SpcTEo!uA||BYug2au=`rwmIYhKQ9NQgtjlf_ zEgUkp*CJ4qc|78%^;l*|^on7|Lr?2A-TQriWIWm|w@~Ii!f1YAag%E_AGQ%fb#K5!cy+lnm1LFw`+nu-9}sO-z8x>c^vf%^52^q* z^`>~Js5&4mRi`n3a-h|xAk}e!WI>bG1}P`|fiGM~9!46G*UEA|X^jQCj~rVl9Nejr zl;7A0L?H39G}l7c_00f&RBrdolXWYy`z6;61A-l_!osW=1+36tB1VZ}wyJ_}#$p*p z`Db-Dr{>FiU=Q6Z)bx6Hk$dK>sCP!EZECtv0sK;uX?qY53uzN0p%4&JZfaquZ)c8h z079(V`zwPjcMzxCkI8}-Ny1;U-F66-bQ88uku|H$ixebwm8spBVf)t(*<=ru*u=Yw zj8zBcUYIBax>e%dSu3GEWM})#VS|H=7suPK2a@&6+-5C?T*+BgHh$3uRs1OF4*hk< z*U5B)o@yJcu-Q-2W07q0_i4`NYzDE4e6%~EI7dAFx`dQ7dRAihxBz_*{c-{#K7|0E zJ(j#Nx%-$=anw4ZqK-m=5lzk)`MeX!?}izI3~J^{dKELpQ(KA>q56v`=_wJ=5=?NE z934DQxGIY=%k=z0%l63)#|0CJwX8O(5nZ&K?qxdw2g= z#Np@$S5BT+pzpD4zO9g~_fvPL&Y zJKB43J`qaFJ91ZBmZxkptp3o0s#|XWiXg1IZ5@A@g-@nzkv?JH4C1X^ zrZcXA#w3_geH=jxsC}y-8;;Oc9H8@)%mxH4qCVk-+aU96@+9b|2o2G;cq;!oDk~7m z)L3Y3f#F}RVo=HH3PDo|oZ!;;79aG`J34Gh>E)rG^q6b%*RMR;|Di&|SZd&;>E=?x zuHhOjL_vsEUlwX8)1$w7lbF!y8aIobGz%hi~24qtPqmVr{(c=*R{kqNo0sNC6wAm9HTDbXx>9TVXVS%sTAY+;!*A@_eD}|%rCj= zMVe9hyJa9NGKB>O1(>K1Si<05YX0#D9&Vm_s0esx=)Ssz`J)Cvm1czp~e~iw@SGtT2E{)*&;Fwc8V#g zpXig%b#T`_Q7Q50&Cq_4+mmPZhHZB!YqPfJiqUdOdE%KYB`#B@66vr4WJqCcG2-7K zkD}Z!M8|V%#;6TJh{<#~TXEp-W!=YWV?A_BlYZktH-RV=EhzBCU&&XtxN9Z0$HY50 zSvqA6Al)Lh;NF5(9Ajyh&aV`)bk`B+?7<`7W;W(z?~Z#3J(3A3xtZ8Wh+uE{i1MK@ z$Uad>sXgL~O<6a$=BYR;h=)mJB^GH2UIdfcV2lT2d^SO(Fg%xXhhoMXM(HSMEQly_ zJu8@|K0&jdiEEXu8}rG;LFL$V;P+@A9ohau6vc8ATVERoH8yrvkE*>(vu87DSMtyo zDcfkdGs=3clG8%eb=u3wdj`2K8s)@(DS8w_Gb%GOcI{he5YNvI$DZ};y2%qge)1JG zpjt3AN4YJd)M=-!La^UlK@3j;?bnN$gg%#Lr+G%(FqUYqkd6pl&NN5Rb~5N&WY)fB zf-8_PDF?jv$AiK%2)J%?uqLKyDs)G*>jY_>!;P%4#Rz)incOpl!umcDy*^#bzB~YJ z5r49hF%%QnYiC5rTwB+w);Lq+?MIoFQOvp#lL&vf ziK~f(tv<`-Lyt2GG@1wnjO6Tay)LopX#;tG$((WKa(r5$L5v@Kt+GI~@uC92jI`%8 z0}>x;mzkNeX*46!fAcSC&$rj2CT21|Q8#v=z4{0&sMdpbko43of@WY&8mU zTvO9zYI>ZbZ|@*uSB%f_U}Rs$srA zrD3|v9d0wiYw(n1XP#z`?)Ugw$~`#=#If*Uw9JCZvf~`9a}EU->+XZ-QNTtD8+V+D z!n7V4!g##q4~v!@=kLlQ3ngm;-Fjq- z!%`&tWKubPQ+&dpNSo(i7l^*rosa!lIv-LA+uz}KB1-i5Iafwnr>dw(_bE+1tU-}O zItE?FO-i5#7)s6$ia2y}X*E~ir~zcZ>NhxSFx<+NWOgIZaPuQXg<4q=5G>$^I~;g1 zxrq;-J}J^n%rs1Mz=qhbj86F?{^X|+$x199pSMX=StGIZaB$7crqr&anxepMYij~V zaeRP)faVO4F>*)do^Sn;UUa|52V&RED43)yI+JEc2eDA*$n~9BeypMJh=-n)mUrT{ zllFoD5f@ck7Je=Tj;`*udG`LAUO$|!lIL-xs+M7b8SkW_L;`+*)3}l272V$PgBCfu*$&9&(sdQbj0L~wk z9egu_KF8)B@?w!pFT$;6<28_B3G?;QyCx1YgHH6rN9(Ca_X*3>9+DY4x5rfEVxO$& zlnRF%uxJ&=ouH(~e?OC&fNz@7%U#lpIzO*B)vC9sXaA&l?x9tFqnLdv)sh+I5e%1= zEq(1n=k$Sp;yINz5ERW&6!c#gsd@LI9oA1hhMi?uU)G|t&3-tMlNc7ZPE+z zDq!vs<<}sHCemWk!*0H;ly}F3(pX0x&n{Z-($X|sChRU*++NTt5sgEw|L|d3bVB~N zyK=4r_9jfe?}pcZ@$C2M;Y?g6@^wnV28QlOUDnAD3;fVg@j$C)qq;B4As%K`W2lSm zmFf+3E~Xt^&$B%g8a7%~4wR>(BWXnVqX(NP%G-R9@f$!S_j3I$ojL{g1%^l`-8_3u z8;z3;RYhI@s&j-00CL!8crjyJ(&qLvD1oI{#DQG${1qZp9{VNcm=k_+v+1ar;6eqV zovh&HCQn?KFGL$5KK1X=`mD??i6CyFb^j}%FBDk)!w?vW)`-{Tn!6hXA!JXpULw|OevQ2FDQ!psUh8MjQ}!!hdY~= z(i86m-f;nk=%L>H9Qi_lSl*NcJ}eTgy;Z{G$0uC^qHX?hh#><^*B6y(!L_4@GsiME z4fq7c@W+}fYj^3I_+MY#xY_G$x0>7`2OxH>M)UJUG3;tBo&~GU&{HRwP&viLQnI2s zk>+Xqr-*ugoLgbMBHcY$&`ehX>9k_@QxSj@Ya}b0|1) zLq==^d>ZQ#&a-=RTfvLsn*1z5Cn}0DwzbOI69l|2Zi~FN%K{6V|)zUX6Dwl=g^fO>-+MWnoNCRO4k} zR5EnEpUle``?2zt0B3@(jM1@H0hV>`WbKT|VkC?+7bC%i+K4)=b38#Kj)E)CV27OleOZR&h>w69(hbf~a+ zPMjz51jfrCG;NC);r%}Si!phQezH+pX& z>fq=&KR`&_D5LoK`s#Dt>T;EBxM(eZe@E{pUVcno3`Ko=-WZqht74|Jc5&}G08sCh z?k4OgvnRo|RZ>izMPyv^a|xW>j7;??EQLoYFE8K;Y^b(00^Y#-FeAt?7b({J!*R}9 z7&S<}ALuPtO})22vYWJAYaetY;(%bBi@4L59&pnr#ARZvC_8h zJSo+z{Z3us;|Q68f}Ds>2`YPb!q$(PqJd!2CF4dsNnZaD!|zhNA$+6sJaD(<<{eoH zhnvIbK zmI#q6HO1xMHsFrM>lqUEOXBwV1Ki#Pi~z?qA-UgGgT58BPJNhwHSa2(#&P>sg;fAh zs62jJa3-eid31$RY5-z%5dErqn-BN$p|vca3&IuY^+T9mbuUu{JE2B%c~4J5Z=0U> zU{Gr169q*_{rqy1|K4Lp01!CM$J9%Q1f}CS zJlla?gKw#3Z}=5}CYDdF^miFP`#WD{3O|F;hKLR0)v~aJ4W{r7m5jb)VOl9y_;ZCQ zKnp;t+C-;)rs=lg6dk|>kB6?as$YBVle>fAU(2I{-EZkH-g&wHAsppw_FB)Lo(9CkvMvplIJPlL0aR{M6l8^{$Q^47iQt7N=fqWCz{<$*#HP_(ie5D0Q$ojm z91x>z^oeIvIS`w%6dX4QV}1#E@P0%tF(^kS#LWy{#YJw;B@aY*eQkyI`a-Lzc15*I zZ2ajtNhFKc+@_nsxSZrdTZzrcr$#@r4V4Q(x}PLZy-WqF%iInae$xz1TPCy=8R; z<+$#>__qWiD>ndy$%eD%UL|PmY5r@>1sGXR@Y#;^Cj1=iGxD8wdP}nF z`kuc`o|t!12&o5vel=17Du(Yu@`R(!QjA=`L!ekqFmXNJ3xPx9(%v7Ko-8)#{%zqk z+ZDwOH2J(c0V<(XIqx1fGQDDFE~c-An|5|c^C;|@TAacY23T2e#|lbAyJ14TMDHsiIapaU6oYZ$UDXPNfYN)d?IIAcZR_S)!$wBEz zRe{AwH%;Of%SVE5&JUsIvyAOKMf7B?p#uf%^g!%00S&>3Seed`BEgZR)b7N~g!hHP zJWW0Se#lN3DOdL63s19ScTsaf#&~80!L=CNXY6z#vLc?*a?T z78k0ID(ddPpKRowJ#1Dj*jJO&yWEv7f5{y3b(TlQU@dgI*(N&954E*LYVBOj8ZGED zk2bdr0SmFJL;~Ut(WD)(pshLgNNGB!q)jPuBXfCIp5xHyEL_*1qJd5~qw5k2=@-lhmGHWJx=de4-2a(yzl-1`l zmc<3UIO_&d$4uP8%+sAomkyYsI?g;*o{1dx*zCJ|hZ9E~Yg`VFJHw!qC{uvHk>J5C z)FW%eB&ll&Asl?F$4*TLGB4Sui@G{v*Xk!(X&Y-7Kk&I^n?d|`%~$OTEc87k&QCwc zJ&x7Q9{|{1tTb7C2=u)1<;kAveZQIFTYj^A!}VoGawQE1#83=^5eT#G-=X=9O#hAM zAtFG2Y}z_`_NOB2%jf~c@_P=9>YsKm?-Vhb2^OzJMU_yuw+TTmMd*d0YEU%k zw9tl9(h~JqOOR+AQBao zX;YT91wUGAklo5p*e7aw)E^9x;bV}S3Jgjs)098&HetIQk`8r&o*~n-(zF)>wn9n}Wzaua^($&yQWnn2k&$b(XL0<5}~{&}Z>C8l781us;i# zv1fSWrFX_R%a*^1l@zdRuB2L8xBNU)PyhJd)}>wM*cAGJUBP;?&+y;^OLcRKq?HtZ zRgwh)ok|R;&^8!Pf7|u7-B;8ET#~z13GW*aDLf#`W^GmvcGZ@b1zYdAjxkO@sCKPu zTrrqC1jKpY$UqC6=86&X`NYZ3Gb#Or{9g_<;DX45EZ3(!f;HV7^<~dVm(Ejb+~v#> zXlJi6r$KJPX%G31d(2_HnnB6q5gIxvc^6dFy~hi36455jLm{Xv<6zY62WIr72Cm0g ziw7;#9Yj>!GpI(=0W-WK5ssaw^z`itbCe6C?A&7Q3T=p=WvVY^5fYq;JOD6#(pD@d z@&OmR8linh-k{>f8kI%8L^miqW5aa80|0gm4V(vI!7Age*w%tF@WaA>*NWNxi264k zo!4iNkA9BQf|HU&CI^DOY>_w(900U7t@O=`d=Y^(UccrJ;U1&6-0K?**&%*)S|AmG;sDrAYFW%Q!;kzmtKRdf6dNNZ2F#GGFGt0s;uGO2BRmvN%XKUTfud( zAaB1qQc%b+dP=+pq#TEXWcogYb|XnE}YcB8q-&&E>{q1Oiwd+s%l+*1L;RUpZ?FBlN)5k{j8>WwAP5;{=!8^WISfXxUb0nO6F{~v$yIU zKLm0~1yf`mU&GQI(C^ zRw2KC4(c}0WcXb@^Vat0Yq?v}SOgVN?ET+{8o5tpOGnq(ISLN^)zD#eP=6Ghe-Xa6OUqKO8L%oq>Z9Cr{gN;d*mACxz$Wia79^RvT z@4@VB$2iXHNB8# zBgYTFQwkD$-O#>>lR((eCoydJ^PKUqkX0ff`1dYhe`Wo3{VAniD{dtnwl2tAKq6JdaK5{|YXf+2#m)cN(;P|H<*v9SP?&gkl4VjzLe;lMx@kiZC^%0V-i&gz z&vlf`JrcnL$eXuAC%_v8MzBf8qWofWU8>4bamQr!hH3P z|FsVSuKnf2HnUhAn)fW)dh$F^t6b|svVqGk*XFJM(WRL#q_svFn^pfy<@}{2EPYOM*GWC_s_=l+JIZOW|86T4(M@bzl1FEet6Gc9CVQ6r ziODLB_+2_c(VGDb{RcMS*~j>vTCHI|GXmLr(1S_65&%?G8}gII;&n9xCk-2&|G4O1 zxS44iBZiY9EFp#+$1bJ#mEF{<)+h^BA%oXEOuc4k27+|=EYxDVV07aVbo2Br>4vpk zmCjrJE`_nmH6Uw{6f2_KxT1?Rg|KiJptItYU(_poLiak|W7&5rrM-)-2|KPU# z#wjTl-v>9_c(StTC@@avsx^OYYs{qw4?Y+mW4uUnI8 z#yKG<93{{u3(-Bj8YEs^V+;Ru)HTBEzL^vq=q-#5-kk~eXpTMY{VC?5fV6i6G%|BlHfKSlZ=PKO=9X|f$~ZWlB|xJvyuaa*GrJv#Xc z_AU74Em~ICyy6CK1~l$Mv)DeST?Cp&)&qz)sVh3vW<97T==BO^;}5ZK%^9t(pBuP(QM)CDl5n z3fNIC^nmz9w}%^cnwz)3=eI?i=RL;;qSfSpeJG#@t|!Y*H%FaSq=?gKKT)%eLD77X zuE~JJl;HYoLpZDYzTHJs%>SWo5h6dx``$k%UjwPE_3%Tm1Ax=R3#SrXEleww(c`~a zf<>lllH`w1Mt=d5=DQO36{<=)POm8lhE@w-tHqa{j*S~Q&^SEq6i*9nz%6fz`Oei` z^0!{>x(Vi!yD_T;ATLP$cUo*OBDC0J!b z2xfY2W)Zj2*^e-%57f!=4!a+1HP&d?-ycdxuGm`OQ4lEqxNmIu>My^|;j!w2HB=1p zqx0+6dQ`fZVz+EoS!oEP6@HAFd@Zg>to-!fYv+Me30)wy z>ps$4F7Rsym*ut8X622biPlLw+YcuKC%v5QS~zciQfZ}H1q>1$vphb0d{LDKXU3}e7Ju`$O;UfM=hGuj9xGF* z-XGXH-NSsjC<7~_ZRnraaq?8}%$Ke8SR;Ssc;{Z`4!)veiErFyUn5JxAN5JOcf4GG zXC(^&{!gnPxyf}x!_KCq0l)*r)BtYU*)Ok_ct2|7vLf{~Z5$><%T(!fO^YwPrUu~J zToEBzu9zID!AZm60b!`W@Xum#m$J#!(akauI+gs6?@zBvZ3$7ppeD>_=F(ceYl-`! zz!fnWe*J_@cg;b&94Ps=N}k=`lTV6v-=E{he7?GQJXeKI zvn~WjekC@Rh8*7!f&nDO#^|Eb8Xd4;b;!O<1f8wb!=J@~xR}kB5RsOR_Q+e`${PC@ zUii;_DC@0(m`z8Zo!uqN^GCqDR7mI=HXRto7 zZt#LZ(3@{vvt{${Tkqn%{bl@A5kEgYxfYhP%%vBomz5Z7+&}-iG4re0e_X<-l&EWD z&C1}c=e02^RO_pSa zSJUeNpeXOABQwD5N7|;Yb&4=jo@LS^vs43|b-G|kNXmEag-avryiAhP6{GY%tPMXd zy@Uyb2VDZ?7l6F#@uX?gGrs@L z1DCtbj2#Q}e6^V>-Jtw-Y;ay>)$z;M)~tQ%6Dji8_IPFDpS(Tu+3dADg4eEjaB+2T zMrx3kCO&xuRrn>A1_NSdwLU3$eY;hiql^$z2%po$g}(Jjl;kY59AH!uh2XiNiUy*^u+LVTQq!hWY4T+@#RK^olIp zUh`_-)bvZZfNy6>Y0@S2Kp;X*)3C2h!|&*sYajh|Kvp>gC=)%~=QmnzUE7#0l_OKf zBAqc|9WTxNm2F?ZL#A9{yf#NrO>6&qPOrLe4dR0P$L~Mh{9;!D1zq8m-@Gz$`*yP6 z1mS8gas*nC$YA6j&$&Bb@QAv|XZ5LhY*fMJhVz#Roh1F$A%yi@o0L>r^fzS zTsa()S<73OP4|Y#71Z(`MxfaV&ogV`*sE5SAes^yuwC=fe>pyQ_2J%ZC9_+*y4u=N z!2|oX_^7D;pI?*qR~9r?FBH<39h}$DyyO`UWN^H?5G>sCJ5k!!~KY(`p_!b z6k3n2;jI8cnl-->#D)$;eiKFh$Q1a?>FU8}hBrsI=oGJDqp|&d7lRndataLsq13Np z0ZTuq?|#<9~lV!Kr^Is8AW~w9@;pA5(t?~40nTWd{`kz z{JxMp6^;Ll779($$R=j9>2Zf@pvSGn^QR)HNR$k$i3V_m5g12q)v!&e)?$WC9} z7`b?MI&G2J7;s7s!fsgaMSibS1w;Rf$J6IOK&O_rhD$4d83)qRS0LDiI$Q7cyZds0 z*X+;LTqrUT_{Js`fId_N1uX~qocnZ&8PW&+9NXm7I}4)wv(weGH)F4G&{+1C4iNi& Y=@Q*j)e&fB=92AOsMbn7KKNC@agqvHy9#;s0K@ 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 PO%Q1KEAUVN00000!cL># diff --git a/img/mysql-architecture.png b/img/mysql-architecture.png deleted file mode 100644 index 16597c91d7e3397ebf57a9d43afe6c2abb0e3c20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1229182 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∈`(Vqbs^*^SpyFS`W8m9$=;0kDPw4%9 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 iarz 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�X97VPqh_V)%-?5^U=g0SI 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℞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

-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%0Aq37zJEThkG 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%0D?&;930Js%L=ua3$#m7r63e z)@PrU&sVJqT2Q<$*a+dEIV4V2yz@Pns`abeX1`qNxa;~+!~A}Ges4WF%=tgXNYH_N z&95f)oz%yqkdJHX`NF04lh)qbRtNt_|6q*8EZ;f1IptWKAey@fd~WO} z&0p#34mnOOV2Q+f@=#1oS&JqB$$^4|G8`75HXF+Z5T9)z67n?I44+Q2Jlg1R;}Q_C zFXf=whr7CH{`YS5X^z8!en z1@81`*ek;s&xq=5x|CW|i!@-uWW1^>FFy`RVU<#(QEl!P@0+v-t70w2r_U_;OCoDEQt}XxU`q-keDsVKEmT__6u+E8{YOfVk zbIX1CI~E#$$231Lzd4OQ9p2;~zday-zQgN5)YqMH{B^=8j4R@p7r$?EyPH2G36dgZ ztlfaPLF)o<#dkmE;h!|W!^m`AviU2{{n|L?MCzyKP-9v$b#D0Nqpkmr>>b{7gUjiB z`|!zE;Fejd`-$t>#RZn}#6e7cATaw_$k8Bq>O1C%h*U<}Gu6*f z?2#11=%O%R7O*e#scgtv9W=a$p+3&9lzGiwp@ix*VuOcAPACi%+j_#qi;YW|s4pGm zi&nMevWq|_Npk@#bXOJq_Plsr;p^=Dx|3;*bUiyamlT=s)UH?#HNERETd*q{TeSA` zFa5>82$FPzVc;5evZJ>?QCnehFn8ETA3oAYjZuzW@0)(vP+QBUF+Sj<5eWsGvT35~ zkn5Tr{KTZi6XdYI-ImJ*J{h-Xcb@B+;^0ISzX?JcAcx5cm@3BEy#7WBAU%LYBz&b| zTtjOggFb3whsN%2#*))%_TeG@Ljd1=SZDk3U~M5=qRb|Jr1pfkS86oapaDmx$?4A75XIJz!p5F?@&SwfA=yFGPU> z)`p)`lQB~IRs0vy*9R$H^)xD1b+2&mctU-bkIUQI|075Ge=SJ{agcyO?^mTGYI{H1 zKUB9F)jH!cNf(Y3wUW*S#ByT!yH}^h}tQ%67d+&_N=JrNt& zSyVK4aH^vgO>=q{k%7p_OI_w#+AYns{2_XDpho&kh?l1_N>g?t@jZ~md$)al3Sc3t zi+^C0zrAX?X?P1Q0w68-}*~v4!AY(L94`M_tw8F`=1b=lbd5LOrAnb&BMb3 z&d=e>x(Sz9^Snhx19F!JtRws~??mHP#qDq>bk9<$-cfzQ>nsv|8ACzAm7moZMR-di zSxHH|XsxWy2VOd5RDX^Fcc1pNvk9u(z<#HeHaq5nyOP@2q{_b9#pw?I=T4ysZ@388 z=sg6{WAm`U+*UK%E3ys_;Wwq18Vw8kj$n6QN)APT%adu?JO4zIiUa4s-ZXcQ<0fBP^x4J{kv^rb2OuDotzpR{uUCTP! z@m{Sf_mGst*LtfDKRX%DHTNV|sY~T1R|rSsf<)d30bkq_h(F_4Zs}T2ca4e%R17%< ztx57n=XV|IU@XM$y(h+Abw*9U%eKdZ%R?7^5EoZek?60RTdTQLN$)U;kg)ACH4Vaw zBIIwCmz;xv(7#yW^=%|XlgEP$q$#y+|1u8%U;3wx7Y)nXv z*=dbhmcbdf__SC%pZ}qi|F%1=+%47WIE8QLXs?DW>J2%g&ee@z!k033Dwta*DCTcF z1M?uCP?Gz(DUU3LDn`PhXSs}v^m`B@1#We$BEi?#8nDcQe|(bVv~L0pzz(FA3{4uZ z{uU;TjCw8V&JXbPE^+L9{;uD5L-o2x5ZFjD@})(JWeNgrr;kx_3L%Ej$wHAeA{!tNNSc;HGQ)W(iywM~R^<)g>?I%?Q-JbDLeECzju=Z=h1_cUfIEU3JYn8=# zr0WGO>bwsM*xx488uFSeaW#|;4nux&IC^ckL@?s@2M6E(5XgoBHdK-5GU>FGEW$|K zrSvEZ*aQ{wNTX)I^%seAWlh)+m0gBLBf(x&UtHy1K0oyPKd$?4cZ_7`5J)ZykXc|L zflI%%uVBe>X~dr~NEAI+S1yj0QFbRVkb;0%3yS>8!fT_RWfO;V93sv5(tdJc3uj$H z5>Hh7iLqJ2TgbFe4vrD_E+=c7+tNO6d@7HE@S(P^JVVDcCFaL-D zR>|s#fa2~h#TrIPBd?1!%k?&=wtsF%Fn5&6HaEy?u-2&xubmJ?BUIE5Y$>Wa65NV)%V%!{|H`${TrRe z7GSQ@z~yHM3$C=PALN;S)mXaAy2bO6qn?0{91havEpHCO9m2wAWApB30r-%4kqCIJ zyv16L)e)qV-e3$&;t=AND&b5phmxNRdmqCrz+8{P9C&!X>9x(c*`^jN z;bUf@3F_P3l>0C}4f103NGPql_UWN+hFUA=bDrC|!Ix%zOfCB$-rZa!Fu9N>@wey_ zewhWoL_Z&+CT{8i>oDIS@*zslUA?6J-9 zdH-tsj2tF5dYv@ha=F~)Ekor2V~IUrsOKk2cZwvAI5~2S?EHx~QeNU;p6#{yV#1E- zB{E`MG|CsaJwXP7NyDa)fM2^k#bkydW%Z1TjDUHLhyAd=zxE&3}j{TTO^EJ-2~<1X6VS7ScnXWEJv#vSaLvJ>m;}EPTM)r zvB7yL3?;JjE>h$Y^Cp-Q#>B_A#5Q#+rI-_QB zHIV|Dz^}Jn-BHD=);r6aMEa(S)iLjJUj?-jG7`VGGlrqsJF}A|Qs15VfOxL?<42UA zK5JDe_y2SO_V@4K!;aXN@-4Oe+leh)Xs`CeBv*-b;ZPU`M0Ud(uKLL)64x2i7C*iy z<8@DG~d?JDjvR`ZJ40z@hDh#?*8Et|jS4~x8F4~^OI}mS$y=?U&6IR1q zv>8)tpkRozd}*4I#?-Zqio~V!_hSE|6aII7eu%oId8e5c7UG|;6h{;^BZDn#OV05D z3?l;H_zS7V75gb@^(bc0F82}w%I!Y}43MsNQ+(eRZaYCt4+DgY5^}t$Za&I8PMVhd zulkp?sfas4%kH6_H@wTN%eqsJpae*Ox)n@6ojzS&OiYcqTOgM9No_XEggnvF zJ`rtfIF6v~_V?>ai*R@CD^$z1n7u-2b>H?f+CX7^g3*#-tk5v#0S1xc3q|V1zkl?8 zd^7i!K`aAx-4C#Mmv+c95fVIqb3-ba!ssH_GpszSY@&6~f-=Dp++(=}VpzC@cVBJ4O@XFFc{!L*m#P6fvgL ze?n{b41$7Td6~rf)TqY~{OS52TQj>6J};dDzjHgbi>jXQAE`jHm;~^mz@HHz1i0H( zZ^u?uRmp;pdi?_z@VRMo;Qf6PKqZ3n)cX>P34f5i1C<=LfCAur@ptJMtgdY@Mv60xx30>;A9#=P~}@>LUcfuBKs(EiJ?xFF%8 zEU6+#D@%J&JYa8DqjQR;o2CEySKa3vlW}LIkV+qFSrV2^5*DYMCPy=(9m-zHBTK^E z`n=XY3G#{b*qng-*4B1|y3fJQ80~tif0y9rI!;;uv_FmAk5js<`(m*S3_~=EF14+Z z&y4g>NY&b#lox|Dh<4dK%wYxr2fma+@;@b-fA*H<=Sy$zXy4E`If29Q@Ug6j91@R2 zQp8tM0T_jZ!EKYQ-rxL(-@%T(<_KaR88RREGvCYe#9^EyrjZe9hlz_e+5rfoA~=gJ zE7=1NVRwt!$d_c9PPdFTzLEAi2VsF9!cRn3$`xwqC0Dvu7Tm{#xec+CU+d$7$WpgK*|bw`aBov%z&Z@)UWrqw1hFD7>RqW)rQQhO-s3aAq(5r_`OHNWMn&pvwrkPz zs@u^y*iD)z$Zdbs+h$1Cbk*)44=v{_Kj;gw#Hz*P=RTW!B8B&lCfRB`h+MZnM8>MW zGq~Z~oXp->>X5nY1dOiX>(8If;{5nIqZbZbbxnf+xs$$G?5Ewo$kv0o6c+&SRrH3z z9NGjcyNS3T%0o~Tlj7=EQWBcvC@DGJyR@95z@n-2=v^%B9P2^2QMD61d8!ne41As; zL;H=^Q|U}rmqgj|sdZCC?`xsMmU|PUey7gUm#x{KCH-cuqrL_6Quk#6U4#l<-huD! zY%mJwt$b5>m`u-;RTHQY-?YydDp{#ceg9Vr)9rWtGouNddWYgk zgdJyku8X+_Owo_ou@`p9Md5=>(bf1g$6UlXEmV;ZBl_xR$6qwe6e*>(;pi3p3Dk)P zq?VchLk&{8XpOWerucUO)dc_>^?lQ^s!cQdgLdXixGS1qlQBJkv3HGTF)Aw^%QyqV zw4mF6wVQgey3XLPh+Ymoc42F}*2MRUJYH$JZ@8RS-&uEpT*T~z`l3QQueGhVwxRFO zuB!h(h|Mqc{+jmNAzEPQf&7A2e90e>BJ~$vP~gIhlT>=A&wJn7Uq3X&^HM|n9{Uj` z!VHC&5vpjac-JZ#XXFD?gvnux7^lS;kq|Ug52U{$*pmN*IXLcUJ5YJipwuy8M{CXz zQ7v!IyEr^oAI{gEz_|U`kARPEVC(n4a{BY@72QFjS*l)!;*9N-YLzkxIJ!I3=$;?D zFzaofg{cFO$>b)`Ls9!H7C+IKFoUqeFhE>#X=)`<@~P9kWe*};N6K<3&|8scPuO8= z3KawwZ`bv)YSJT2h;L;E`TsU)LScQto2kVR@~J>#qMC`v-xI|T{!M*$%2Y5Eyqzm; zCVp~4y{QA8RmO6_vLVr;nRhm=0}S5$joh*3I3)!c)nTKs>s;X43~rQwLWH!mh7hei zPiZ^Ca3v_fMY*UqpP05AUrot3hzE1*?e?*2g!8_b>Gz(gXV(XQfSrMj0N)esqFu7B}4J=Azn=%dRJPYIzA-dU)`{gvY^08XZj#mT#zFa`h% zEG(p9K)g=Q4p2I%vx4~&ifv7DxPWt>$VSQqv{1#Kz%40#Hu&{WS}WQ8el7EZ3D`8$ zGjU!O5n!!9y=|H?B7Jc;YeUc>U|$iTq*t5T!Z5Dzb;QQ56gPY;RTTKsw|j@U{-Aqk zo;8O~LC2HLN<9Rlwa~6e5Y)ey9wc-i5jGOZU0Jh?4DBa6Z?Isl$@h$l;0)1MNql4Z((1JaHpw0I!1eG#UW`#I=@_|_r+Ph{uT~N}lFsZ%RBg@8{qtkj<{Z%GHS&*J5;fsgks1aCZv17~*Pe~Fw96jDTldS=q-;VQYpuMc;(_eK6EaVQWYkz+oBz1$WgG*aW z=wT9GsF~N*L8_r^6(4&kDO&MZjCt;y-#WPkJ^}F+x5xl%qUa^0uZ7;}&W(#GJD33j zey)1#UjO!7=m(68E58IW^LqwZ_XS+SKokM`PQs~bj;14U4Ty^%3mY}ao9jd5_JNj) zL}1XmL^{D%p-B1938cswIKsqa!o5y6Gszx6BwRRFrI|s>R3|C`4S9}r zlDR2bo5}JTHgnpla>1?7|MwRZk~zZc{7Gv@s@%`T(aN6N%P!FLcfX2MeQvoNG>FVa z*^A$mB|52SqLr{0Fal;f7>AlK@-Gn{Fwde}zSWvSmw&e<$B&}TL1^rh{75$ePf z@|u-oFxeQI=cmHR4LPu7G;nVN*O#jMerM<33W#$)#3Wy5qJz`!sd&tSRnuX zl&=*m>M=f`=9pHpvbT+{K*^< zdZ2IJ9ouef+qN4wwwk2Lj&0j^(x7Q<+qP{qwsH3N-uwI9bI!Z<53DuU9CM6kaIpr2 zap|88d1;5NrsY%R^N7-z3`vyQ=yGk+U4Mb1Rw`O9hp~$6PY8*mirIWt<;ztn_d#kU zirQ@82&LozM!pAKyS7=K^-Oi?+^7NG=87^>%roSNkh~=8&x6r@4Vsh(CMI|MP5bbx zgRRBP*%`B8rR+M3uQ%rNtFO;1tg7_0FJZ5%-RxtRVvk&A@+1IQJW09}Hf7`(FP}^u zWBUd2JimUuF6Y;b22c|SoV@>`)ZSdOo(f#G)zzp=p;Se8q7p@=2+s~+w)@C+Vg{%t zOSEHkZjXa^-*<6mdtHI5sE;985gy5K6vh4}@0;q2{6zAeSq6VuOuDsfR9$pb8JaX7 zT))S!qgz)ZGgnhfy0hlF3|r7OR@Cj28m3Oh4uQpac;H=cG%ZPga?bgQQ~=YyyP2$~qN5`3NA1T*P(wyPmz^Fn zMB4j#MX@*qWpw#2wL6Qr?i4|`%SKB=lKDlM%Fc8i_?IytU6S$73-5d+lmQ(kaJowW zKkVUpwciJRsb8e=O?~Y=wxjt?ktx4S<|a%;4P{z+63D5zy_sR(SYR% z#uEjd`FfX6c^~wq-`58p0m%rl`;#E$DcHy&DGHSq)7sF3HPC7t{Yek@yV3<+3dJ)H z0#Tb>Y8VSK@9GT&Ta*Un4kgX zvP<(8h@F9DPDJ<)xywA(=&wa1%|hS;B{+t<0ZF$sw_!8R#~-b1rW!A!$b?`d;P@V# z!w2dSryPr{MG#b#<2X9C(Y7w{fctd*R@ibqlSHkUqhe6bwi1A;iu=0_9KM*>Md`bO z+$4pz5n&lrM+$Wc1W%R>u2#J5il4w2&>aqL;t z4=lI0JYIPcJOy_eatI3s_^?6_Jd|<$HGyXUQd`_nGRsz#U*6CYsjs) zQ0T|4MU4zzQUw-(Ba94ur$K&>2IK5;TWiy4udKAnNGUU4ueY9(OW|#2a~_2rg1)#9 zQCo6q9sYU8erxmF)`4D3o*swh75nq(H!-2t4Wdi}b z`Lg_ts2{iEVs9z;f(Ut@$I0^l>;7Gu7fw(K~`eIB+|KO`Jy5-Z2ohj{vMW)UK z`XtgNzf_jqvF0*Fo5$0b*6*gj#*hg?Gp2C=7mV}2_Bm#h6_C0o?GX$2Z>&oc*79-5 zk=Hnj8(2e~>)vPJej|D4RD@DNe+1=C5RZf++C$|#Pozqx)v6Vbh68+DK;q%8iA4oV zWXtXk5BfkFhE0BP7ZI}-s2|1G-kv!iJ!WNyvKljcPpY}RBMq{ z6#0I#B=6%h=O>!9yzSk8?TE<}1%uxgj+&P|IdOD|C*Nh%Sg1O8wfbZ3b}%wJ1JG$Q zqWc<)_6;~k$NZXUl)d@|M*JJ%cVUJ_?S%tyGH%wz?pe@~#@#^mqSc)X;=Wy)h_oCG zy0r!88s*m?Ro+n?fD5j5Z#itjq&JD&-eH%ohev_kVIOn0pG2sPg`>vEv|KJe5ng>2 z7NG{z4~r*c5>z8LoPBJOYk zt{l8QgObu@+VDq$-FBT<+#y1}>(M!_hvS`K+ATW_1V)d{5o>F01f3ckDWgR7S~S4u z$Zb54>fbbHY+lW=3JBJ#A_O;$G~Lr9`m_FCJ@;b^`3T(!*H^@Hcm9}pZMSe3xS81) zRS?7nG|6+vs@yST-F5sah$ zF4nYRBV42=p+r9`(KcZqaKH{`m>9hQFUUbTKwT~?VGzO}_(de?=_k9S=--bx913+(s(m!S=?I*t6G=AY2 zz?bl6PNPbD*B0h83Pewy;Zx2_kCE06!RtKUp5~ALF2qgC2B1D+X=zNUKnP4kod_ZD z{k1M&)~3_4ejRo&D=B6of5?i_cRhwwnyhW39vV5e)(Qjy8yivB{3?(VvoZ1_eu;AF zbM+DQc-d|zKO+(!8IAs@$?wZoo3hvPue67qsudwT?6Nphu)Jn<3#uC3I9+^`OQn`A zJ{K_ADK-eFDn= z<{-dtqz{4sWnW|QQwmpVYx6v*3=sEtc4WJ%K0m=UC#Xk9b!!RW@5E$VtyJW?{SF}L zV~-d^)cuqf94;f49%^6z#z*A+>rOuG9bpImHgZfe;N|spe!3{?!TftbtaeO*V%wA| zLG_biis}Fon!#lTK3m8g;&;CIV^`I-s4#gk^D)>V>AuaM__mF6c)fti;IM-U*6Izc zj=oJUO`4U}EdzenqvRMR1v+P1qO5;K#}bMqBW-jssZ)e=_H)^)gQ8(3y?nasHvMZZ z@E>i?vPqQlLYKimC~;^_<@o8`zrpr8h-*y7$&AEx3_0j2=ldR{RuAG-k;D#D<8eUL z6-xBKF$Q}bdL5ci}PY}$VwR_G|8n*sp zUlCU-YdB+k*7z$`{t(h^_EWEF3w<$=vaCgxQ%hg1kdfJWeQrsEoWZV($D(8^w;`ew zE(HAO`;|c`&9pX=JN03Oi6kk!dB1M*%Rd7*qXE^ms4;}fWxgu#tU-^K>vfzL zshqTB7TW%NVv*nXQsBVs%B5pR@Uxi<gy=l9O6 zflHWjDF@)5`i53hTu~!bFa=lK?H&uLN_Mm>>-wcG_sM=dr9-93d<|30{CE7Fq>d>4 z0_gR$GOq-pWj_w488#M5D@IJY0c@k@c)?vwc&>YQ#o5018$p}mT0*xdtB)8F zh!Knw5l(&0h`)9mrF>*<=OdZQjA*P45Jzes2_NpVPT6gYf7|gIVyi+S7RW1%f>yO_ zh3V(+DdT~T1mKDR`vvcdUQe(s){<@rCXazX*TnzK8JsQ?gxd8pj!PIi_rNfV=c;9i zubb+++jdoo`o?VUcFGF^CiU(K#qlgB+3!3DBqSYC?ov8tSBIq9K@dpb<|*gnSUK}* zX}yI2M?JtsNlm)t=I~wX-bKuT+Np4ZHkAItX2| z;`)etgfWDJYt6D0gXHqKpr*81CD^QGXPDOsx_CxP_0&(0A5}$P(y8~;!mWB5)foQ6 zNg!sWm?wZ)7%pu4f&MoPhu+D3{*QtqgPa+5w8J%E$h1KRXbAAH&RV+jrgi?d>be{Y zbOmkapk?hY(A|jXjI`2<_@dYj%3s%`M}r}!ygnnN>bWm{i5o3edU8tWb+16j&ksU&%PWN&4>0ROl+BV9Gsi*rDVgo+~ z0L!*@c2LLr6h8C)8yAW>FT3zznu7^8KDChjVTIOAYJa6~7 zc}Q=pl+4DlH3MHNFXNGUh2$(*z6zIwp80l4f|Ax73C)NLC{v!A0JX351OE1&jp!!v zS-DEfOSk;-j+)r(hoX%U>(@VKKQmA!Hcae%zcFVNHFY!391&1;hM(1FLBQ+#-8nFi zf?bv#CsIz{A48WwX()h3wL~$uwt34#a~6Mv9Z$_sx!*L;dyh2+=`h^3_P1fiatn#~ z@n>Bo)Q9!*avr#$F<>QPTp|jeP@|i`Bm6><2nV3JS`KB+g)B!<#Y1A^vAo$R2G0H+ zDFiwiM)X^#2rN}9x)|G59}8HO7S0v1@3rsSrCaXokkY0=9E;yh=M!ZEg$!LtF&dVp z!tX!az!e&K!Z8=B!>vY}x&!X#Pn52bnc1<7xfQaw-N`KOwJJfc!I977xUW&BNBzVC z37{AidmrV(dJxKn#eY4@4AGX1Y;8BzJ_t+H!1M6ry)w)NW|9@Ks zO?5*o_#a5cETr}-^0GZC6ONS?7&>nW%n2UY$ykOdLYvO~WwIc=S)CJ(*WqR+RkTis zx9-8hZII9{xty{9mr4g&A=$F*4gFOy{yf!Kj7$;@^=)zBZcN{xg_u0Xbb8&I&U$54 z*K8FcqK=(i91<9Z(&PvPtUfA<^bh~*$UsRs>?tY(qnUy&Wo0C!Xl92AcZIc)=N3YK zADxd9!EAlKR-Ht2$K!X7i*DAy}A5 z@Thv_(W$&Em0VNIK0x~hJ{Cvt+_^!kY7eai6;xRiksa+5^c*f^hTtPpmzbZWq+iX@ z@!ShNUW$G%D!2O^SsOipJDnB#0RsVHW7l|EOvelcdp(yf)9Je?J{U9nVc^`6C5PIj zPyFm^e}B#qoA%k|X&tBjW>ZDuWahWC;s(?FgTt7mJSWnfYBFIDnmzZeqFf~*eimQD zX={gW?AookHUQMGk75K|mV~gHAC#Zjw z55PI2d^}Q?SB>`tyEg+p75-fWv$TS`!;Ni}Pq*7O2&mKDyHsId&G;a%!l=UqrYzo` zz0KMUn7qDkXGOVx+jD1Az4<=Y;`EREImquvck#k<_05F*h;mO%VsTxScseZ(CRM8P zO`&Namu@B+3kNT&Esp2(>dA9_Of-`2C}3EgOEa5YEU7R^YqnJk8pg*bE#)+Vz43(P zBPcIJTl0c&Jcv8$4z3QKxvOJx*|+)miTU*7p@&%{BWsMI0_AmBAm31@8!S4;8m|la z`3)P9T35t=%DEI_NAQOvdnah&YtSz4zm| zn-gMz053~fXae*vuG&`6{q@$JcAIy+=dLt4A)8ibKL7KE;>az#x&Y5Q*n@6o!R5Qd zC%t+4QTH_QT8srdG~BN^lag2Vit3?I5E$P4L@eFKaKDzA_$^arbS3h^=Y0S!z`VNq z@y}BET-+#1qRUABo9Swp%T;$Ke7=o4T1De?c|SweuF!>-tX{7Jlv@3jB`uEge(WEHM5< zG!e&OzNh%#Y#z#NJwAKI3Gc35dT`mV3c6xg%~N~vCCT}?y1%X`#6GRZjyqiC@O2w=Kr zACSOo;>pMC{!w6?8fZ_|+jP)lF(HM5aY~Tkz{NxD(sU9*L-Wp+O$AAAATH@+jGYi^ zF3*ggB%k+e2OV;?UVkzcxz0(we$LclA+_nz21-u>2$L819u<)IM^OUnW1D&*DMDObbl;NPI5 z$o_C#JFAS$@~(ziutzAdJCpv6$rRc-bw%?Jxz`u!JWw8oK;W;y2yUivgBT?8kg=zy zsz3_Wc*Xa#+2xKYp=Ge{1Oo)?#TN>v2uxD7`T9NrkRC)Sx!3bdb=kN;O(fxa+LrCu z_I1MSOLFD;$P%AnQfgBvuWNIayXhFo?*Ko2t38U13s<2vODo-;np*6-yC=!-cpw9N zrDuYmyzOKxoN%tJxHbSv@PR6<9yg}_jFaZ;`L=7D*(`Qlc(%|y+pP~BW9aXrJGdU3 zA3YhN8ic@woG+Lgl?-9vy$`{RG(X)>&~T-H{HUotW9J&<({iU_#l+`tvaMgYTenak zjYi2LNaToSq|>74$cL9JZopGcg>1D<(d5)^_e^PQwH+!)u1c^ zfUBVfj>rcz9=Exi4Jc~b2eI!3gZBBHCZ99x!$}dEGo4x5Uf!h2dUhO7N~0qL zt-`i^hV|dSv@b}6#q{}#SyTWWI^OqkOI}@gN{X@c6B6=jg^e7`2#^*Kub1pfR}%#sp>NhiMZ9Jbh);cX1@R4iSo^SK%j>%G_A=$K$EQ-)jB5Eb%q+i`bf3d$SFj-oI-BQ zE)=Wf2N|FJzTtkDJq%w59Ki_T&i%H~UFe4jl%tGdE6w06A@4U{A0h6%@nUz~0%uXU zo`7tx8GilqPLpHiM{THSyw3!bq`%zZzBGx-fZr24?R8K}s>!j)6IAZVl&Z?OYD_po z!GLC5nSu_9KSJAHqja>G*}-pz9w?j&zS{^mUN){j$JVhronZ+zIOUW2nWV-@qxI$M z8xxM84(pslki90N+O{B9$;sv&QI5k_?99~hY<2n+bA|1K3QfVeRd7fz*&wb>w7Q$t zm#TFOYvPg%n`q)uQa{bj{RrsUZ>t=!w8Zc1fI9Ve~-;-ICf+4XnNSnr6s)} zUFFuzt(i-@4*_uOmoM~emnj2zGoYLoc;&Bd`ZqWh2cDsv_*tOlWa;V)IDhzVy+xkqNr z9Gw_f*e9DKWp`kDZ}E~`n3>&%&{lqi6oOw>tH}6bEg9PEOm+`(_H|(L^lB@>PX!|u z;Yo`b9n(Xdon6(=3tF5XykNMRpVVQ|JJ~bRhY{GQl2Ms5NlhDPGGP=f3AVhyA34tn zsAvDsjGjYI_Hoz0$z>-d8Qb~i>-BZMu8~(>-$=i_9=eEskqUH!hdkn++;<*JG#7#G zE?dSYdlrKifT{_1>N=JzCVUqk9({A4g?`3%N_iLyF;=YAt1&6Cbed=9ViyF8@Arc^ zEsLH^h7Gx&2IKT*1=C)yNcQ0gU~({8rf6G5ad7nCu`X(diRwN%KOSFo?ING(QCtAf z>=Fp&MK+Sd@Uu{MZX7rc6?+amO{<3F{jHDd%x4%I$_SQdBA5XtI&^$z(N%zRaQUx1 zzh`3jjHqGtbgaO{-^2-c*BWxk<*wU;ZYxv3tO}+yjTTdPUgJ3J<~44$pPE(3YpZuS z$wX0tBCr0Aqg=LH)XX$Wj|}h)jB^$L8-91% zBEZDE``mWus@ry8z4~Ymj)_x%C)i=XOFQ{CtCp(VJVAaU(asSE3EjS&xs*rN+*%^! zOln4t1N1%a3<`DXTc|kxsS&GxZ_(QytG5FV)Yb(@qX+*s;|8}No7j)0ErP8+29Y;e z#F!%%r(W#}H=^(da!HgJ_&mnU^bj`&mb}M3*E@QqD-iq-d$}Tr=pKehaq}$Vv!-CP zO0V@7WzV2QpH61h`TF+fA3^u8&ZUh5Ug?C!6_hkLXPrUc!9{YJ#fSX55^!C;oZ#17hZ4zDz5Isj1A)d+OO-$ts}@4pPcGZ;saI5I%Qc zroZtvfQc(*^N<>0F<-5=#;e+)5prx>y2Y!<&jJ>$Fih8GHj2Cpp0?f6x`Oa`vJ*!S z0^g6VBfT3IRR^#8U?j|@u;EDu0e!y()+cjZ=&*D_P&>if5pvgK{WtR>hrMUox0^UW z8+IqCLu#q%h>iXZC>kn9xu-HFFnfMi+xo6g`p6?yR6EzLX}+ppkEvWET*2M|bafD3 zq_fFmUx&Q0=9W9`FQolJq(F%FM;`N)i)m&^t;^P!MVe+oGWv^khtsYQHwmfX^Y;4# z$^~=K6QvX>?prM!o9zr(A^M}yk`S7(jHLZezc~2Bb@I_%_9Ff7RsGoEs6<}HtRHq6 zJ=j9W_)h;74`qEU8h*&+j+FkA_4wIrvubjHLX9rgc+Q)5)wb_iUOiq$V`*8N`G z3DS)+ohZ3Pz}}+crEy56`OO)sUD^6MzbGg|cfWphSekV${26GKAtw`lR>l8O{;u?= zN0SJEorEx<7R~w3!z&9Pf6>a98V462A`A?23kiRD_4bf(ExE?*t0;<%a-_Jhr0N(M zjE2gJ2md?fj#L%$*lk=qpXwgXKyX<6r9o@oW!IhJ*@+evDa@|=5{u|dPXVbJm96fA}-@C@($bYD0k!|Xlt@7*|S7!ucLo<u3A?C&AqiaLL}cS%D#TbHQIMH zKusB+?`yOe-tUf%tE%=vW#NdUD8It*ubFiXSYQrG2NJjZMlQ>?Ur~AY5Qeqs&8mMa zWyL}U`-ybX?nJ`?e_Kx43{+}PO4ioDLH)w~tCBAj@c%ySMCFSV>(!~^DN_QF^Js21 z^jhYb3pQ(!NAv$~p}~R)#P=!_$e^JodyJUg@=4y{2#O?u@}9penC?gVmB)hO(}i$jy6nXTK-{xU^|JUbs3g1QT5RIC>BzR_#KG@NoWVuTSfk&mLG@1STO1o?OBLX}_;a>kNsW%%I>dFsU@%Iks{=OgRGc3Y|Z2>}Gi) zZJ_6IpHSWX(-4+`QrdD+oN5n>pG(k&dMdj?)8H#d;b<5*1+M{)O!~xZz!Dr95<8)f zir9y$0|x9&L5C{;qsKay5ih(+&FrlC$zE=Dj@}X5l6M7v^t9X-?D0vdQBqF!sW^Ux4@Y+sKdR$2yEwD@@99)^hFCGl(uQ(Cc=oV%nFmceoQ+%dyKF z`qhVAJD0kSbI!}#-L~<^0x0TeC$8l!u>D(-iyx(&Y zoqg8*(SxKR+wm{R8V~pda|p=2j!eGg!tLv!R=!RWer#s$G7F0(!T>}jgf10QVj_We zk$r*zvShSOeS(ZvL|<@~z=UM4Ahwk(4kMPfx0zA$%wYM6mR)t%RS&U>e4@kpPMP3k zr+p4q22GLUad$H4Z*{kZJqX4ZT7pr#=aSO3#q~EkreJ-PsIn3*&`9V!c+8iu$ckd( zl<4*(&Jv3=L6T;IMwzMc&SGlZTO22%kD#G-`cuW0N<@Ar*@_H>-kGBp0d)tru&gwK_1}!y8|ot;7lMda57ouZEo$+ENdB3?!hOY1 zs||e{-v!LHuc3ke1otifw$pZJC=P`|?%K-HVPtSex2CJhYN?aO;Qkmma8o<@`Ztaj zleXWsIgDSB0}izQYFop{^4CYV*72>Y?rNi)KU^&K`Q`|Q4IgeJ7(VD1M0I=kBc%4H zVf0;Otus0L3CNSqgX3X-+?r7;`r-~qG{ji@Ge?V3&EUOQ7=$`|Mf`P>2bm5A=r6RC z7WLrV?2*f-;S;e$bFPWz)sb6*gvJ<=Iyl_w_R9lqHOSUQfRckpg*S%h^t3 z%*;f10oQv-DnG@TWQ%P!LtP%v>$e+o)8-~(bSahm=D-bulU_9PgOr_wlJ5Ku{K z){Mxuxq>F%F-+{U^0@7r^;}jk{zHxpz2*3lpL5&ckBI`rlJLhuGiG3p2U#w|7&_W!b1BNT3xV&Pi+?IDK0y~cc{=X-r;O9)B|5c zwBjPSdDclZUkim@$?>)$p-udgzl=KGimB*Cf2F%K4&&p>)xF+lrEQEXM-04QQUIxA zNb+yEDq@`5&O$P)iIj{Wi3%A+Z4Zo5n)37sHI~d_w6dw0jerAt+Cj8}raq4Y0kIp` zA1|=-hWRtN{`B)kizA$&_%}GMqH_ZjJc0v%u+dxMdz0pjjgcT!+ZBZVl$BItiokKt zqb;!vi_K}s6L?bNt-BF)g6kT>TBbdtPXlEsdqn;+9l!K6N{3jOd1Gyfn~J<>rHXmc z2gXfnMh7@%JAmiF3M#<c0+E;N{dBBHwb>369!#JQ&I*!_ErI-Ixu3Di=NCEtg7x5Z{p9ku@-a9t6>*>J13 z%7-=imsU*!rq4<~Iu^g{c{;;us#`-;fH_$W;jNWDJ`s|&MrA6h=hLQ}?pKdL2n0N~ zCHP#0)&xTu?;1ZIT$hpr`x9?i5UEIKfJ;>u(u)<#3Y#d|5Xv28MvR?2PyWfq>=#0`+g z>=?%HivJoRkgj0fG88L&;}Y@NGu_M!#$yp6LX~*2kg6#uO>6yD1>Nz*A3taNxfF6$ zF?kv!<@5*n)iA91Ex;|=)0T+3HYn7eosf@LkAee(J zWV8|2-@uLjVuCg51w_-tSTL3qd9NZ#@jAt)#Y8<_w*HgKIc-mF_gBViHy>uwZT{6r z4;56BL4@dou~f}00D}tz2#BZzi%qRlr_@4RQzp0gSFvXQ!S7RrZ0LosV=}BE2Zi5O z4jM!Re-Hj9TN{4W@&-$0ks=&l1D>TSNJ;!1dd&_x@SmbNU@52Z;*kaG5eSz!%Jqr*D)# z%poveR-+_He8Mm!{k!^qtnHVCyCwb&(=g@^Ykhh?n~yc7Grg@pj45>_Zf~S=SMH@#5S(XgX#R&lz(F1Gnue!$T*-jRql$Me{?B(I- zW@P!{-7L}a91PrSQ_l@@@RP(NVqP17;t98n@OoDKfCG@^J?PJb*mo1jQ#IIK>q4rY zaOV{(l>NZOL;jc?S!sC`J%We7*_}lT&_>z%^1m0EI&_v=O`9eW-97{NqXuB5%N21d|qt({*sO(e&R%7rqJ{p z6X#Xq+SgAX*H!ZgI)UnhD;)zjzNp8M)Y**)lQw`>sv#pXn)(8}1bf(Yr{Q6v@QDlL zy8D1ll79$oWflIYhVXqr{ej}m56)N&sPCe?e^ca$9?0gJCDfdY#dJRSXvZRNW27UN3<3qp#j+7{k-7dH7K$Z2X;d3p> z*U-c34zlv|-c#z2(nmxbcOLtu;l~VK^dxNNzb3#>{=EEN^1k((I2QDJTuCscu1K4? zd*O|tK8v!1msmUb*Gc1xeP&@u(hm6%8kXRP@kw;-!YW+OrNU+OPw;8O^ggO);=FYP zO;LAypO!n8xH9JKY^=w>^L}jnjxb+o0gWfuQVdylZVfDR8VjC_N5Dq-)9)({(JEa$ z8u5@FIf6ofv)n<1n4Wo0LVb#TJhkyuyBI^Zh~w!x_(=Qo$0jM{J*aU0pjIve7eJ2PIiDWFrc!H-_nJ(E`pV+MwgI@>D4wpQ@SO0+H#Fj%-6DXt8|xS0|JH z9M#p2=h|sEe)^CxOO_6v&I^GzO<2Ht0m*u#fu~LBW_cMyDzU>YeN{ zTSH&=vB8lrxw!H1KIA|7<3X=C!kVn-lk@EHRZ}uztibZP@isQzz5MpRk-fwdsu~Rg zEr(lk4Y!)_wMf@~T-6RT!Ps6{%Tdzd^}KXJUr>Dpg)Y3U8sF-Zmk|fasMBwSC2&!IHPC9Gsjd01;hUgd-^Sowz4hR9Jl*WD^sx zY|0I2j}Ydk2Wy7Vmms2FjxVPsC5N!7%{oNz_5{N9@!aFB|EyZRh0F|DqYkxJ$C3U@3-ey= zCP-aV(wLfVX?fWKN_&a}X4j6i{fGCZR5dI@H0x5Sp3N(byU<4;GXLBPltl!BR(AgZ zZ^gE<@AH28Ye{pVtMvbU0T@;hsWXblNP=bX2Uq1QTmeUYIUS?_#UJRbY)8`m8lpGE zFXWY(!X}c0$&Yt9Pd-c^CwD0ofl{MQvvymR!X?1PC>aJ=Cy^(gzol;dhKK`&S?9<3 zZ#Nz!7e>&~Qc;&2YD@CW{A=x)#Jo+N*r5&F&4*~d$)BR%GHBq)#ZlJ!J#wHkw{h|^ z!&Ol~dB!!;Mg+$mJNquabz}V*C#TdG1@8Z|PCG}zlgXgrGoT!v74EtMHB$s{u}loN z`s6%*4iOByEnbIG3N>+<1)kzo;15RV9+Nujc#$}=gw@&1ErpA1{`V=Uk+b0BVg*2t z9!Mz*!{Mn}|Ol^{Tu0ZMwxCr?vF_B!QCq4O z6D+<)Qj{Hcgt$?y$JZ1`@8w3B$x#+CacqylcEkNF2LT#{)ox}BXV2xhg;8GPqUE}82q1D#9+ZL1Ig&I-o=s&n} zz&(0(hV2+h*duQ>8fqZ59IR3}7zgx{vcK}|t%13Z`VNtOXLQG;yc6Z|ztP}DPL364 z-ytdKFnx~+9feGMa!ia=d5)FNH{zP3S8VoZqw9R^=L2W3_XoV!hxFKJxMMGO&b#mJ z){P_o;|1`8t54_^eOsOO{aM}hn(1B#&|9*A1<{8Y{rwkhR?+y@LdhP@b#j-hGL(xR$T(GI9Ty;}&Qe zyo=y~`I|7QPoxLVnKS-;tQUWa4otwO3VSr5Pz+g4S{#0@zbAc^XjWH1|} z#k>`2>Q#^J5>IP2F*XR8_7xLOM>*%LI21lIVQ|l_l_Z8m?aSWTYq#_d=!)=xL0OQi zE$EEwO1_nZHZ+yvbx#rP=27zKN}kp|jy!x^;O?f($vScefCHqzF8$t=9+z~lRu;=O zlcVmY_-&gnFKs6oFN?RYTW@Y08W;P`q+h6h``|0nK0+b)c&*)7bpWn-qv=7(2Vg|E z+=|~9@t5WNamk@G+LPlcGe%P`FU6Z+PiefH7g7AfBdQ5+jw~o4Xl?UwYU_1BD_z-c z-74a8Kxsmrzd!H{?I~&Xr}1 zwcK(aUjO2wTm%DG8)Q`sBIhjX^4tX_9pyiF&rJxiV>-X~(d><@_4%&S&x)}r2K|15Ie z+4EqItJ^zPI@<)d4@W~VmEkS@K6G^J!S7eQ?0XmZ6x7OSn#2-Y(M?%dnTYjQIF`Jc z4x%s};9Bl;2mB7-Q1ro;uiSeYnA@+0y#?(q?<{w^KuPLl+{ku3fQNBzn41}BnditO zPa)xT#N)&#--a-HesE{o)crnAyawuqAvGm_rmdU&dhz?%&P|kpwt|yy(H)$X?doH+hTf%sgI=fThBc!zHL#4cSZuJw*b1F;2_D^rn*aquy`0eXj6oCOWR;dlo;q}TzO()-K ztx;vLa*rD%Sc=smA1km$E7aZKf&~2Xr=4|W#jRKvw0xclILz?woqBj&iThgaruz=} z8zLMOc##A9FWcARTj_Wq$CHA^jy6t*vb?Z#$)x zx6;S45cbO~UAcoGq`WGG-+w?N2surzrc~s8%P=jXN56nAIHZ`a@dMN2mm_05Q;RpEfIci-3Vxg^1w$cqVS`l2j4&^t;U{ALRW;RNQ(*!4Lv^@ z#ZbN1xVZ;AKk9NETuWt2adhxJssI?#9;wn`sxoOp^O2fj)2nBt6Eyekl4gy1!6)5} z$_50|JOTXYR--2!uBXxJ5dB9w^Yn@d1c;UCFm9DS`UH;k#C?Jqn;7a}+xTet+BKbJ zmo#A|XhT88=^qiY43(2vy91fA^PPgFb@beS9!1pQ2bZ0(bA)vm)D=f6nR zZ!Zp}2umyLL5K*Xm2XYa-;mUfQ=!SNdc`vbf-~bzNg!8=71owohMAtYEzydhLLWXec~=GQWqwuW-*6^78IZ3pO{bm{a$k{lY(4xngos z{(!UrxG&Y;mMf6Xmq*i}yLif`T|RDRoYTl1qr)9HPH}3@zhtoX0lc=Z+wpyt-&0PIh)oJLydU0sqllT5~#kH1ib@o66Y=Ou~&x6cq>*oskwL| z#^c&LOoa?y_O5&t$pD3xwLnCeBg>zJz;A@2L+FFagnSMYsT@sf3+KrSQ_(t|PB#tn~cCF7jLJ8eiI6aUYWkrmn{u>Nwm1^NX#6;#V|14q4 zA8d%|5~FBOfh|+|A zm^b;nP8IV5J3PTN=&tU(N$qfLg~(SXZAEYbhx(SrwXS^K6g+eyKEuqSbOi5lCg?k= zm?u=qN>z!K8%DD=ZFsIi!5QL^d`qw&Q0M#&EbMmn3_3PSKoyW_&HO$M38~)92Cs z9QnZbdAYy!*7-?))p}3p#7!f<(-`G9PZIprlJ~kBhcorG5`uuk!9+)UfU8(11)F1# zuIBr?NZ)>uAWd8sM(nxZ$^10x6xRu(WQ-`Or3@}gXO5?tEjVewVtWA`2h|r$f)D)0 z0nQN%;X?%h3-?Pe#;8^G3?-p4EibW zRVcRc^r9YI56OK#Aui&z+(&u)@`~Tfw4cSgn@viu0@cM1?>&aT*43`>8lKf*$6O5Z ziYD{p{YpE`7Q5}tvNPe*ET0d^Gap& z)-U~W{(c@7MaAm>0I+rD<2LsjQ1TW|W70Yd$x!(b#F~N>u5Qb6F~tzx?sfb=n;BHN zGoxB#9;?!&es|jg>R0^m(~@0RDNNp1=5yEwq^c3_mYMEfF=xT4Gcm$ULZEXFAblu2 z@#_T`_4fg?W0U^rA)ZePv(KQX~*JSQkZ0X9xrz5*d!Ww!G8 z%_%1nuLE;Krq^#0Od7lsZg#*T@$amtZ>VpBpJ2j2^UQO1NAB%}KQeNJeAeJax$-MV zSSo=)*SCx2@xtuC=!0_woIuYuI~pbAkD#` zE~3=RLw)k-?(vk^pn36ZY3$|V#qfO$nMmNT{TJJ-Jmv8`H4FDlt+*6oIg4EJRq%ux z3z zCbcMxGyA>9<^~#@UQkn$x=KFaGZp@q`10*x-D7(O*Flt1U5z-vU$j@Ru{QyN$FK%P z=zYfbrrc0&M3RKYx)83F3YF*dn>iH5nV6+B^kE?4b`)F)i{QQSt{cO1;^QYw*!jY$ z6J4Me)C5%`A1ufjFTRF|+I1JA4K_$j@H(Sfn$1PnH)yXQeDzjxVaCR z*wH0m3xXHa$?;r}V5VixzQGsm^C?q^g!A9iUr0ePOgLx9#cO(toM z83)zv&LQZHweDJ-*lf7cHSMsYQVoN(wKCzh$hP_6C_UiE!700kl7VvM8hSi>W+TieCfve3Dx0ViSUP^6H1RqCT( zHCeLwy@m_Bg7wYR1BG_gI{Hlt#Ezz-1&hb0hr$RgeX*UY$Ci*-tRhylK_nGvwXl__Cx znY7-(ahW!=38<&j#o6V#K$kzdfEj8VQ3IJ?bf9F~XP@jf_z>#%O+X$}rZdBm-Zm)S z#<0{@C{N;C9vY^g&ajwR_Y~i0T3||+F1u%cXpp}U0pTRt)=Sv&gf>obx)IVU6*(#% zOCi^Nh9uuLRD@~A$Y%r0E0C5f&{DbA(U`_0f9W1(?K5q=oa;Os@`15 z0FIB|97d4KtowP8=^Vrg&nL+v2RWj(!36oSy^*e)Wg?d`U8>0`xVb68JgiajT5qaI zU-5jvWsKLthreyfpQN|s6I!sK#D2`WEJh89DoPlA#WOo_@ z6)3mH`6oOs6Q*zR*y4Ve0dN8ZE5N+q6Ctp2VFCwfL6@8wZ(AN+ptbDSAcvetR$ZqS zj`>b~LbtThAU34k{k%F2Qs{1LCPVXm5_%nw_#E*nYTKTv(A;X9((AR!uJ00^E7tNE zv_4NgF_h%wPm702dHCK7j;RJ<3=Uuhq{8e|5BWLH?<%CW`I1iA09OjL9d>HPx`I2 zmV_rULBtPiZ`N#RRvh+gAbJx(6#+ATilS@DqMWaEdcW?c?D>?;Y2B z=s^+J_XtHOPIe#1j9y@vg`$w}hppXTjL7JcuYrSm-+SaS&^B~2lT_e-vnS3i1xo2C z80TO~2#i2(41dofWSeCmh^Xu3Xq|(TjiNubiNn)n?DP!pa3U-Zus>aY!##N{ME0lmV@CMJjC~t> zijt3NKdvWpaJy=C>|gz~F`~oXOQ;d-!t#FxK#j^LKnL&#%DfK#{K{n)lVZ9u!~6~y7`w4=@xaO&-E({u$% z+P54O{q~)9rAA7fI(j))y1z~1@;}pj4ZfKQ3LHLGZ%zkPeY~zA4Op)1Ok)Cy^_|ds zHSA+2I2F1^CPqK*4?w2(yY5$y%q);dg&49;K9ghZa+A05@2XJMZfneU3OQxMjtBTB z@JQJGApS%leV9?3MFa1D6k$lxmd%w`#D>y%JD&2SQruPfRaNkn#B^)M=^HLO+svE;FgX>mh4? z;uxjuBs8UiFeLwm>l=dJ(B$BlNQ9-*7rS1F-_rnf^E6?=_A6k!-F9U&JnT^o#5@53 zp{l?^9evw(`{^y+b5OTmBO9H$5zQC>0UJ6v(KWDhhTxA4#LNBg5yG|6^c~T|(A#P7 zabx#_z~cXZ{}zCP4f`W)Zm&RSSoPkHJ4!(d7vgx5v4n<_chSU2nxXuQ*8`Ml1t&h=s-Vj<}VQ+%umWN5sWY)8DK;MUMttB?b>>} zj_o+Q7jbeuVu-{8)5zk+m6L;hX^kfU)leFxfADvx51l7W@dgHBLf+IPG9Dp8qsi!@ z-CC#3pp5QfMD;>Q)0tUTd7gSz$oXV<@Dq>6=y_=(zlF)ixS+ez}DQq(c+m`G

0H@^r*~_H1GjOLgM8mo^|p~EQ+7i?70TN4O70;BML`_(iQi|zf{QpiVY6?^ zd%Nd+{)v1aXCFu`_t*J+PWbkjA#_UYu=)Wxpv-%VHybY`Bl1>qUmjm5$d2?th*2H# zd}*0oN1xU*+nx@}H80oB&aQ6hsOXl_q0F&?0!j8qce!=_@6*(e&rR%$)5UU~oQ7l< z&M_JBZrT#N#oNZETGuf1WKTJkVeR<|@gZi!RA@$pA+Bh{E!+E%HUUjC{P1xwyJy2b zFC|uM(8Rs$LB9?B2X}R2u5fL>M=v#8-{k@ zmpUOXE6>Bzz|Pw@K`ozSXPS?f_?yR<#D=Cv_rp7KwT9b{<2!G{57ejpAIEQItW=KF zfhN!B2154;s928DjE`*H=p5|q*3)07nz!-!ALl4noln46BUsKDgYXZ@_w5Od3az}) zIYyM<3fM8MkvRDH4e{XO!*M9%dy*G%(ff8)53(R>)uv+q6y>@*8JqwrtXN>49HjeQ zVhc9!5671=K1Pew+JUAQ#g*F4ON3s}V8ak*oJV=&iB#8WDVL0%8>R9jkUx6j?!c~O zabgp?AR$VhA^f0YXBJ>{ky%B+nfdHq^AX;BcqmZJ=O*+!7N~TD!M3fzQHvAnuyhv} z%|R;38rR5MGcxh)M@mmrZxO`t$nQJA;h7(ET5V#t=g^5}wJ^*+xEI2b!+wFYuN99x zU-MkU$o>;_(?1P;zfDWV62Z3X(H~Ss5;5%BrO@cs6%M8|+NYGf9xTM_pL9}h(oTc# z7(ov6th6{4#Qtr7$l#X=83!O3=ctloxUf%fs|5U2#F-^W=V0SC9aaF&aP1@INVO*s zeH@4!!zqdftQvN*c7I-D4#_4)VFbB%aNVG8fI@emqaPLGW=+q-7&!4TPd>_jsCE$B zXB}R3ey{ouMAU&VwX0Q}FdQ)nFgF&d4lLU2Bs34l7PgDZE2Q@WMc*kP-uG~S+!UXg z$ApiCR^=l{#UpFosY(f26XZ9X=c_>9+w=mJF1D;en#KkfF>qow1af#xF$2%GR8s^P02rN;v-FY9K&F!(J@;l3FaHBsr5P=8P`ryUzLj@X} zO*KVld-kNT$h`DovwpnmT|9xr7vcoj53%9| z9m~Iw5aqKkuFKri3!ybsD24?4G)owp`>XG|ugzOT#yWj$)Xgs%+V z9?mwKh0K))8ig-nL)c7hXl=arcIqh@6cd`l_r0ofQ!(Os*%`(2-y49tF?)@kHOte( z>^`};sK+RohBfopIxSIN3k(7!#VJ_#aviLo>|MbT_@X+q{C@`UNseJ;f0U}!f<_DL zHwD9Xb|xFwCX~Uww}<*1EG!lwAr78ydlS~YAOO6){B$&vQ6fy0h|M^cK)we!L|vV8 z^LE|SH=pa?h{GC*XM0bmj%=2lgia6tfY=bXl`5{!a1L(v8$rn9!I_wi!gQZgRD9#mKz zqlGCNW@tWd9M5<)>lOP@{uz(hB#>DT!u$;bUzeIIJ3IXhlrnlyMT(@9V0R_0hWDI3 z6$Rt*1uY^H@M{||<$%~j{bpw5S{w^W!^>&pu#&J;10PJr;!yphX5w(NsvMbhm>gb* z2sa@Sj+cypIcS#S-1EKW6()m55}4o{JoEZl6Re23b71>r%_gr0ZNTizOeB4Dv85#i z{nb{hJ~!K3CM7xqO2~?yVPw6f|vc<*FEI%v*E?=XJ)@Ux5dkf{}YP; zU+H)O1bE_hP{jq867WsgA&LH8TkX~>O<7*cuSwzMU?%1mA=EeX&i9v;Av{7xO)%*M z=7q|aIf)CIXHf-q{n4KS|B1K$&`w%%o6Bw zjJt?`wlD4kVTfr>CMXdWDPhZ~&~FxHQSdRj&}7v0<{5)x;uZQGzJnH{E+yCPm$=aC zkxLNFAZNB&^W~Q5nWhKAdEzhvyn@%>fRsdxk4wlCoN6Tht$2KV{Msm+<;6x=3}uLR zP!pWj4$W!36^s)2eMp^@j`}QAR7Y#qmP7Xg$DsuUD2RE7ji0MczW+v6RUyo+H>kxC z>x2I$Hs*q=F=8t9=MN+>5DV}3uLd$nMIC}2J=qwnV~aR^`Xm=jp`q)M2>i4pJe?*;aVz-p2#(xURw2V8ED2kV)HKlkBZ zx}q!-*~0>c+GAG=LHHWGtGXe%6b45_2ZBlhc+0K1hJn*Mq$cN8T3b6i_r#KOW3!th z`MiG&6j)^#zEOYmt~$TE4)0u|wT@^dnQ|1CO8%UG@)Fh^wNc6@8gk=!J)?01LQvBO zLwnVdzLfJx4&MEO99uNNlKOc%!JYa0H-hQuv3t+OeNcOFAsDF~GQHmEP~;h&dRw^10uDF4l+@UJ%6HQX~{E_F(X;EPb-* zkZWc|%Mr@C6JE%z0OKK~RYFt5hjOSSbv^AbOqHdy42$2%49WWPQv37&WC1X;Q1dy! zxBfG&;kL=C7gy?7Y|uwDO5PEY#0f&;Dz zh;gBnPx`47P)n)f^9>@SV(JJ4;Os}R;VMBD>KA_S;Rz0hHEN>+-RR3*$>O^{fCqv zyvs?JpJe7rl%^;ICNC`aoboWhpKUG8w18_+2{Frmtn!}(o)e*4)k(vZ-?8<2n|X?} z1Nh^9nxq=|;a9A(xRv-yzg2{5Xm4i1je1V705iwR@vnaQ8(gL#OU&)f39PG_>QJ6a zK2NUNNxaX3^P2fJEzI!zg(Hup_vUbn~CkNvOrTD}Br+Zn`TtE0KGG`iG~_6qzd zf$#TlZAuBv1RsUn9`P|?$lVYNX;>Cn*W(*8pRA8@-ZL)X93IuD$>%*fMM!M`+TY6~ zC>5e%ND3=me$8w3+kO&W0f+bKe9vkEKB@OLG(o|v?y&JZvwI2d!%Yy05IPLDj*GsD zXs|AtPtUJUuxMz=_r-o_U-Lw>oQa~4AED9KY?|k~9auard5XuJ2V`ls=I!QBgyM<5 zS3AOZgoJ4jn5OMEX%RyP%@%Qh!-yr6h0&37SE{G74@v z`;F%yzFM%o45q7^Mq3T(;R!DQFs~7<@5*~!P+N0c;Fp}m55;Y-tH6)(?#}_}@NkCT zLq-Uq#GGweIXP+3C9q1V-khvOj)$y2sA>HsWXZ@_zxf{hF4@49gJ!r3ZaIOx5Mvs> z_r2XtGT(XFW0$dqc&3Z;`{YIwh?O=p%<&Yw5XHRv`=i(jE0jJ0dev?UUaTB;Rwz-^ z>4zvIkJD-4JYGmik7x^07T|mT6L&+$I_}Fzx_!h;bNtB93;Rt&S2876_rHxX*mYWxNt0Rm#c9g!b8v# zPaB9lUv1THK5lwv25!6AE|qQK{Ij}0dP%=}Lb!-6Q1__>#p4seb8rFY6Kiny+Dt&L zrm;a2Y2*s^FpRgOl!SHAS3oHtxnk1y)RRaK=_|9smzF7pqhlHH)*N68DpfSkCOK(S zySdUg=e(bDvuK9G;6Nc(=+SD2^lZ1Ew@>rgXJ>0=rs+Q;Wr}R*Ep9Pe{*9S_ce>G` zJ{U};DlTcTz9z_L_Tk9A2d!QRRrf>eT^IL@73=>3_MHz?KIk=W&qB-=^>8p4r+X+v zr^Xg~fXIj2vM$?o_+&`%(#INV?E#+}lLd@hDJz@5%}2!!ht}&JX9i*GdzyvrW1-sf z$W}dPlX@Vhho}wHbm-)x1tBsFg+0)YoW(a}=)3?bmrEBm&&}oH&5EYc@&78ff%b91 zIPekv1Aejz8ym)=nj&gDeQhkWluWhz4{L_!`JChl3%K%XTXbTP*R*85vTKe>E$-bd zQfhZ))(8E6%_zv7j%51<$Svd{jh?NfGcN1tl}oc*m$Pm?f&kvWFuf>~AkEV>=P+h# zd3ktStsw|4AO}EkB$;|TgwqmMP{xX_&q-u4{YYZH)1^H1gPJl?8;&Xp9I9xn!y_G$ ziGNd8O>{R(Zv4Ka_QnZ(A|IcIE!bCHcR!4Zh?Q}Sc&?#=$+pq2`8;V4-<;HsU_J;R&KI1N(fRXjTSWRbd>y3b#OA&!(Ot%2=$dcD-;xU%}I%=t`u6(iLrap7(E z7y>gZ+rBcL!jjpq=xYYq@eH6&fM7aZAtT z8&WX)OD)EH%!c`rwaay)#PLO1q?F5KZPOG~%hK*!x-9d;J-%d~MwaRwRo7s>?|r7V zW}!Ndv9#_XPR!^^S;%!Uq#A}=Lyd(?^-=?8_IFJ#&*+LsfHc7x;GeovrKB42A7j^k zvuUu&VTHVCVb2R^IC&W_=p!cJ>vr3)I;%JUA>#;pZJw3y@6>nDcwDPn4PdoY=Y9tA zQyzzJ!slg3K+Ncp6;1Vd z8r$B?W@IXd$ChfEps_wfVSVPH2CIz1aQSv+kZnGQlSGtx>C#Iy!^}HvXJ}fuQwZ$&&Jw2bw@0rm1~}VHr<ndmQPwQl^3vMTkjehXi3n0^Qz0i z&&IHi^lVp=No~V7Jm_(bgoEwFS?&*g8TW|#9mbacKx()j-d5+vl^dZ6HxkncrAtG0h69n4B_48(p!-ubw z%E^d}XBt@g>^5dDLW4}}r=(D4E$6QEMH^G!7$@hC7> z9v#}%Wy?NtIRbEN&+P4&&(0P{p||Wjv9+;a?)R z_23G$as780{|(RXA;W?}1>Gis^=9}6%4m2atR87ozm#h1Q9j&uo}YsWA)qKmW@$-8qw!AY`M~CX0-wh9_@@oq1-QA}^wo^ODj)(MYo~RI( zsReUP3Mf!OHqgm3UWnBbR+;y@tcuL0=hN@8)3VF7ysaIQ(r3DVgS63*(*7ev6a?&b z^0_(GG^>%o4gIyKMGvoz#1F`}+J?}7(hl-MVnQzc*xM?8!39(dx^{p1WtIDOKl^ng zycDyXG@@5 zi~vo+cOX=ay4IeYhHVlli)-LFz101BF%8yJ>|65I-uczgNt&!{X|Zly zm7!%OM@5PU6>*Ma=>3WC$y%o#VyQ211R`r@JjmcW@-s--=b~}>JZ-z%g3NS(Z`k|i z?C+qa+hM-&Dia^!bgF3v;?kjrr^T{PQ1J1w2jWTFr~K+^4?DkyO`JjYH3GO(ejddLp;Mt8)mtA6ix)KYtsM3m+L$M#HO9Ihjjk8%Zc6k~>cSTYNg{PTj0OEciVSW_63EAG=WCOL< z=oC>R9E}75Dwtpuz`uNiH8atNNq{wzWRuu2@z;bSl_p@Y+Nk7C`!UIPl| zv5E{}9o=&9bCRrP>c!*8%G8QqZa6PemK2}&_Yd1ynN6U-$4f?;Nd*p-VS1ctRM&;K zdDC29ej&@C0H6;XfYi&hDdLZ{uxsj+Q zjGdjC*hMB;#!uP;Hl;cpbky3m`uQ}?a?Mq)R#TrhJ6GSn+b|Vab!mTz9=q1dlh_Co zAWut<|Iea1fExwfes;9*@qq?Zh<|eHPOR+Ut0uR?eX3nNJ@P zm2*>}|8MqXrh2`yQI&Kzlm(kH=fzZ?2h^^t8)X4|O-yhKvBc=@Z?QI}!+mT#^DGJS zt?n$}h^r~#H_H1nF5;dH>-R0=R|YnIVU@dRNbhN9DYXc!jjrmQ6{$4RbJJ3+K z{fhv(mv5KSEy^ALsw&Lo?HX5t1sYy@hhmTCJzmzN=9y!f{{F-P!zhIPG3<&RUn&346H zrloB=4--5lo9Pp6yc(;U&6}2!s}f$w5OR?@CvsQE>ajxKQfFdt5~tdUJeJ~2Zw@>A zIDIRVh){_I%uqs_=IkoVJm@WL{7r8 z=NwxcW3nqyzNtj^P>i@`tGCEF%P>xnNwtDnj((?ElD)Z(ILJr|@m^B4L;P39EbIZ` zxwp~<#|>^^{Nl~2t^N@HUNw0P|N-CX;|!SUF=8u#JGX|f%IJ8AWUZB8mxOeP;q{7M*g zE97UWb?$7{MrGVI=kz~D4n&gZP^nS}NjLS)wx?fwUbk79+dr=1BieO)a*)BN}Wa^P6ZY91A0S8 zIPo9(7jOgi2}08GxT#}Auh3Pyx>Px=$p-EMnWW`eIU{yu%8L0n?+?twyemghL;PeH zz2Dj@l?Le6j~mA(iHGqAqTQSf0CcSMX-y#!$g6iu9ae8oR~Zgi)5`fcW1gfVR+|v~ z$>E?;6NnJ3B;|gD-fDK|HG~{UQ>j;Uu7BBn?C`c^x~(LZAyahzkL`qQin>>6r!%|# z{GTPTF}vM;eeed3vl!vNKw&Xc!S=E)jEso|xP5JHDVZ6Y3mIH*jg(}bOT^^))xJUpt3$f- zG8}9{zU$IX0gcZ@*WwMm&#b?sV&0l`0kT@JN9^D#;+S#ea%GmHY1?g? zA0AiUMtCgZ`;5pCVX`f-9#`kkMSQ*9v77&8-0(kXCaK;7uuY>7Xp%n z{6qQJ=XH4)H54dnK-L3!3erYbK$kpmh5{t39e-cAB zXr2Dv#vZ1-%+!Pk7F+szNORaojYUmGCOZNGs?_<5lu>hqoZd`4Dx*HAomOjEFiM0sh!iSGZRC=z&j0zK#{Fk zF2@?&=>GbAYjhI+Rc8!C-2KV&<*{uwwTW@U<< z^hy3_huqTS&G^F>+=WC3gO}KZ7utaC4$|*GX9Ms4gXKC`4Db!qGx;Q#MK&t#Dh z&!`TExW543_Z67dx{%HoLHcP&l(!#n+j`o=;P%(xG5KNO z6c>i1BVmR}G4Dlkg%jcyfGn1virH8v2XkG9P@iN%LmjUi>NR3aWEd-_o&X@+hKYgc zgT`gj6^ej2uHKExt-*vfr!30yA+mt#QIM0TgE577#Kp9t))sBq+`%mDs&lMDt>UF- zR_?n-{6^Hjp^K}isj0TB9aU1-$FwJ%G`jMFaBROF)c@E!stT?Ts9pV%4T6;~RI=4_ z^B#kK^|pW6Q>H;wCY5Q0ISH(@brzYX2}JbFk&90lFGm!jlD53}h1Lce&S20cz51cD zbudSRr_KC#xlTOhqVJiaoy&jK!2bhDa}I1N(StjsNv4zZP?6_2kia#pI<*=-0PL6g zZXt#jCdT*gfR%(|?&Abem(V}c-*PgqrgDUtmKJC+lc~py&SKM?^_R3y>L2yG&69&! z^~VsVatYpX`uN6sGGJ``3ifD_yUEk-TawuYrrFiWl?;J5fF=NRYlC_+Zf1qT+7v(U z`BQbLQ3;j8s+zgVi{Y*hau4LQQpfsVYAU?C#D$5XCggTLZU?o@sj(u-Ep41{725S< zAel0WQZ)DBU|x;5cBIM-zu%#Gs59D@JAYHp%Bk95_-ll{>(A1n)D(Ti;yol09#QPD zY>DaI8m)=RvRLLs%LX)kFk&#)Fe|Y6(b$WvuP%LHn_Za7Y}#vYfx_6%pVhX*GrQG% z^YltnzI|yxr(@Ee8L0Thf;xq>2b2`*7BaGvmc9ABQD1bNP2y`7%&-HG5a+`bI|Nh#@v z=ky`7jnu)zQ{^xrM%;BDI3L9^=~MZ6AxSnKfP|!uyM?H2hUrz9U$6SMS^<61-ruBy zrD5ie3{)SDUs{3Ok{e8>s{3Uhl+Vpz#s%jzpQ+_k7M9}(0{6Y-5BZ`6=u?=EwHAxk ze2I~}-)-pic3pov_w~{sglZl!Yf+5`wCR5B~U2yMt_HiDNF7fV$)N8Ld7>D@1$fB%F`#-Yb zwYzHHYjv5llJX}jK7O`eDP7vdA=T*(f#bk>2`sQ#POqeNzlU|cJo$M0l0B0Y8`1s0Xgb+3Qi3ifAw3EXTZWlMg1QBf6Bysh!_ zHn=3|(dRb(`=#*f4wad2k5Mfk?^4Fcmru8yY?R%MwwO&mM#;+ta2HLIJL0{#h4 z>NmoK$OM`^=BRIrIukK1394YC#{*fwh%ND7kW9m^tokMnd|P!??|-FG8K_8YH*c@f zBrLRFb!;wGYFF}Ir;0Y9Or|IizU^uncn$hL+*cp2B2kyuu*w|~C;UTsCl;LMd7Bk; z%fEYqCBU)w?9QX`)s!?rRS5821G&|x_<8LuQ}w?H&C{lHTzLW~qkoZMB(L&KI-u?y zBGe4ba01?9$@o@QH%&MFKGJ!e=Keu2(RMe6l>$Jy@=X8%T0Sy$Kl@ ztnB=$>5`rmXxV&BxPeB9Q-3!Ho;n#Bpxnz1!91 z8qbDU#6D1A;M`NeyC37iq&cd6Dm8alg177Udf*^T)RC@#i+?8UYTDAlv{KF$5Bdi6 zzaKJ1z+g;4N&F(PAS`%<>d2NWQLvLY%x5gznAMVuK>|?Tn>3R5QMj0+8%k z;qjm~wnNn8V#|?AA=}MSPN-Q;1LcdFm}hO>ZZbM;Y&|?*LWV)xvAu5lDKzhkmCLm! z-CLRV;M(NEs=2Dk-EVsAWVXUCs*}H~e_dQnBb9-qg8l^w8yPA18!V0tMb$GX!{Z}` zS$)pCnzF|tVRg6)(P6#yO>-D$^_MpfpR07~yngu}=2pby}D~acM zl&7}GjewGv+BcJw;c|0LN`#ljGY)0=7e!!cO0ahK8t#|{-D=!Tn`GJgw}b)-F#Bac zZR1$SpZ~Cz)49#1-?An0xEuC!uZV|NcSo{^A(nVxTTi!%JaeU26y}_>+h>eX&Y-3+ zQLFeDoPmgdCfG1+^#mD3byvKA__2+nV>5&#%G$w!d3kTi?SR|#LHuL#Ezgx_K#9Bo z&>0Zjir8HcSOxa8u(G6jcx{dM{3I%+*Ock8(HPVbt{ZdJ=2lVl6eM#Y5BP_*H5Ynv zD?nG#*r$TN#Xr6{(LmcB1#%#ag_KQd#Ax+&AQ#uRCTL;nk$%FzaQ&2uZf8JA< zF?Q(+nv*XPUbDT6Z1(rDi^#m5=}=Zzx?@+vSUS3{2kzKI&Y*tOOcknfu<6$Ze2gmE ze{K0S8SnF~H+jWme_m(xDMB#sQ6L8ldFK=MO?v@t$1to0I;1U;Q1+U){WO8?I(Ohd zgOhVmrw^nCjfHF>+Td=CArY0{-=YJNqh7fwi;Ghc(0l$g4RCCZaM}7(M5Vq{zkc|8 zPJk(n4Y&V!eU`rnE+{1uO(=FhVLKCnm5r@P?-d&ZbMcRm2<06vxY$YRm$?dTu)H|P zMdl2=z6$i7vAD@M_BqeoR$^3Eks#J1ovG$9p9Aj$Tym2l{Z07*TPB47b-Q|PHS*|O zk50c#aFZnT#NYm5r^4)1mcW&GFZkc@6VVmY@-*6QA)x{&vJ9#UOzaEjmoWRp1bz=1rz+rN+ZuA{cyS`+Ia zV5s@%R|=KlnCwqav#4i)Xj0WVY=p+clCRz@IdxF(|u)ElW`q?UwfI&oJ>E{}!(*&AP5*w=Gl0b#TWI zAMaPY^(F@AJ?(~{D^HYh-2OWPo}6<6=^kk|jwh*zABh2>{!_;nbI+mtAOOu;{j>mG zCuFZVSOP_hiR6*^~e%#m2@k~t(X)+FaD24qn+5fy&66&33rCHLpQRBR@ zSYQ_AVw}0Je2LzWc5PrGwi6^l`x6qn`&k|E)ZAq8Aak*8O>~#|IQPci{R1C1jOW8i>Z@b)LU+O=ArBtUn~CrtpBW7^u0*r{IRtp7AJKRdw`Z~QHHh1 zL?~yI3_)Oj5go2lTJt&3xP46DK&;6QlcTM>`gQqpF&QM*tgzI#rR6 zNeQ_S<|@e3Y87=es^wWiR*D!Ryq;5YeDH)Hq-JN^^ia9RXU}&fJ(kb_QJ!Cs((l^% zc7Lq?%#ax(eFD(H=qTW_=k1;pLO;Jv_Pkub@zXk1}4 zn!E@9RvLE7kWBkdOW^cH^GU4^*B!e_@>;_zC{MK~4`6u;@tsJ_m1gmYv8`4R@Ox^( zqv&T&ao6Zo>(UrD`EoQN2yd&x@bvp2oPqwoibEb5a5caQz%36!K<{231e{vU!hjvF z$CSYY96(k>11SMBsx)DeTOOdG{`+-ohkITiU)(%yP`3?&*I@D=A7OI#vwxR$_IR9Y zC&`20JFsLEIC+R0tv<~cg6?u-ggvb{rPi5MON9V%v!Mc5CiSoY^#+Q17woC^l@%|V z^s5%POr$5K>tlXd+_BEzqcpAL=4{;MsJGg{u1gA7)Fc}35lfgM<)L;Fc8nf`=Ng^T zNP}z0-GRfQ%^!@D8`oZ6_%9R^>Ly*V-|T-Ks(9JbHRx{1T(VGApaBuH4~@Si7<$?H zoH%a$q)D0C_Xi}0D~^@o()3*gR$a2oc5Qo8*6PD-)f@7^v9&Y1EG654yj#vJ`8E42 zgf%p#|Hw`Gi~M!leim)EnYRN|?uufwxm*?uybdXFvCNoxc3Z2Bmu5BUfK$k6N%H20 zzqKgPgL?Q^z#xM1D|Kr7II0Y*QFn-dtwwAQWw*8%8aRV2;GTBx`On3H*o0d}e0yXW zaLe?H3jk+?8AKAHhmKJ%#s1K>Mqt^xn)#Ufx%c`IV@|zV_-_RVQ_MxTMy!w=d0UQk zq3N1uJ&OsF23oHQZHyzrLjGgxAIQN6fUBg(q*Kl}e&^ovHB3C_aUx+$fF@d3yAIah zI;&aIu+@t26MLLr#0ig=n~s?r_O&Lu5r_&qx`^PcB;@`+rG-jcPg`!yePCaLUsnOm zY$ek+=a_pKWQ9gb@$Ue+fr68{u)D`G+v@MFM_{ofbmnB6*!w{&Dp^!2Trh!9UJ?g@ zgFKaQkU#HcddVI)T)I^i-H?D?)=vtX4b~|P`faY?Hi$jUF$wfy(1Ew7X@B}o#xW{R zU838(yt-Z!PN(v_=#n|RY#GBpNyi&4WUMcrc$tkjq9iL*pSv7X61w_#Y>e1W@Btbf zi4^5G`EI%K0yPdI{lEX!bp(`9TGFR@4Dw1Ky!cL?9Mgl}@gRpJAIDW;I3lNDzmbV;=Fwh=39GSpRSQ%m8xx=(=E5 zP$2n68s(DD`yAr!ru#$8xK{lLro{fMH{@~MGN-vZ;DHV#D|piJksP(bT85f8^rWM2 z&1pDoeFIFEcYXSKK6ZS}C-~brc74Rh83M06_4}WiaCnV!>wo?nVNQn}5nJYE*Vnkm zwxaT0_zu1uncix$`j`KH=i_nrpX%-3q4MvEXr|(33WeM|1+m;agL(?LhbOZIe{{<= z7_m3a2ehBKeIMWdn5tRPaI1=j7a=9M_xK*%m9g7al$T3B zTnT#iYK3GlTMF{?&4*+r+o z_(ep5WEV{jWy2$9iSuY9_!F%Cs*2a%VqIghS5Kh8M@`X4X>G(CY`ZL}K^D05fVv2H zx$5yLNLt+LuCJdjp3dfc{4<*vd2>9&XDM~6PIsgaB=cd?@36ylu2n^urTRq{mkNZi zhJbMmb!1VYq{Vdcc6VCBstiyHY@O%%WChV`z6zc%J0XI= z`tSN;f^HjjmqVmU=}1ggU22xi^71A`wp`GBH&o|U}Q8BJbJ$uw^A;wF^85spnA!MYqpXRjGF__sUVZPLY?6*1JiD^Btp1P_Bu^LDj!q`cOd?f!Yla@1op18^ z63zscN<~GlBm7fQf!|H9JCwy<4`(m0K*bybQO)sdrjJ};AH?rg_iylEwzOX3=NviO zkluzWLgFpLgTo^H37=cTeGq;pKe#_gaaPsm| zD|-5mSlCT}LNr-!3$*j`A70eQ%6ETt4Y?ggo7cm)w`fWvjR+fZQ4zxwnY7G3Py`Zv zzV~$H*zWgAu5q%n=TTui_TZ#$xvgJ>tDL>BA}npL+mppeUfeD;TnM@%reN*ITrhjpQSzdjFR0o^QB1Mo!N)Iqid1)w`(OyEcBOfq#IKn-rT z)2$y`m#0k(z>W=0S#U!7W8+`_v0d?bYv|~z#OL@&1oHS>&|@MSGE}0KnERUV(iqmM z0v_Pzvp=G;x?FNh?{Cx`%pre7YOL_@p!^b4%zi%7T)pwbIu$_iow(Oj-j1mr+zkT3 zHRG77hRswz``l;DJ>g3XN5AEJFXt;giWA^wM_FM-8CunsqXbf=O0G}&78_WC>yBAG zl|tAU$U_=2)UNyoT!)o0qj+k){i@r(WICsgTr=ecV(g$zM4+THm1foG3LHeW4YAjA ziFt6p*VWDR5d(Jp>;u(C?Sty0)G0hp-Cp}V&5_73kA4sne_&|gA-2y#0F3N5T6){s zc`$+K#DJ>+9YhAP61laZp`pUqsbfIXu@zPhwK|NKe@O5*GJ?wpi&GyZ3yqX$g3q16 z&d04YjqxSK0c_OOoNcyrHH`H(|ME)1*3q@ZuLE>sZv-=d5i=nVt?qPvgODEMV`hqQ zPJn|MUoIZZ*s@7eF06$Qh&V5sQ35qFnM(J^HX?!0DWN_Q0tXj462TL~4=g=dXHh2G zzR7Lg;;sGb-SGV1_WRnF{~g1q&%rn7cXn|h)A;{~tFwxVE84bg;V!|Q5P~}dFWdqI zcXxMp50D_iA-D$!?pC-J5Zv9}3-?#2y>?%_@BGz&wY}F~bN11Po6*Rhl2KjUO)7M~ z5iX5;=D+c73wXY%K5qlX!29j*1W_tNHi>`2W-$>+ONw`LFk)%k!0+^BfP?gqyrxo* zcjf8!@?!d4O6?0ULq@Kgl!0ttUR{1g5xC-br|123|02KR zJ7eSfs6m3h17~k7b^BA7U{9k0G z%;)F&C3zCIT^?hg1Cm5eW`S6E0rJ1pe2;Zl*ZLe(5V3)VU zOS<1S|EKlMZ2!|R+?+N^SGo_*zlLr^-e%&^<2Lo096xN1=X_X(>Q4ttK5a^NP{I^0;vc|(tSOyh&U{Ne zTh`=6LrAOm>v}{CO=A?gia?uyl*m4fuZQT0sa|`PpvQg%)PCy*F&;A)k_;pxUGCMN zT}6&y4vvrQe+;%l>Xq!1y=tRp1GMI2)WzMYpLqD4-8P?DDGA$926{WD#x&uFE|lD3yOz=bm>VYECT?C$H!%GNPnOxonUl~)OE+}tWj>7)tm z+vLEwzZ`f5l~*dX{^*f^LPR`!f2Mpl;4jYq5YTUo5@rsZ{i(RCI<$v%{WWJ%|3vL6 zNikQX{Fx|o{whr>gbfIYY4kDI7dD$3@-jqLB%Uxb`?mC*;htm!DKRREQZC<-4B4{2 z8}++rIf7Wia50O7{ZkFcAM4}1igNOoh>yiWE`8X%FxpeG=xlY+EJiy{9kQS6{r2!^ zSOtY|uXJ|PfWU3MVoT+h`R{*4H@W3vTc!qjp&e?Co@3e3E1j)eTJP>2Ti7-tbh6cf zYxov}4Pq`j}Qc~E|I*mhNs*En@yto&-4rZQHga|yZf-SZ4ab*cF znk9yQEeZ;HE$!YUcW;oS9!c)21e(=vbKJ5fkW`1pA}{dM(gCK zv*L$x3=;74Ez>B?SXBeA6g4-CS39u5jrS=jya2oj7=~~`2^c&HtHOSmA4T7MzNi`r zI7p!FgT5a)iQ@ku#fgYzc-|NuhNc9MV}RNi?4o{m$qE{OJr55#^g7+slW|u2b8`@s z_aW&DT(lkfP!{4`J|Vw+nvc2! zrpv+jGFKBe6eoM-K2!@A$`TnM0RRL71Z88-*qcr6ER80Yt z#Uy_fy#dtBUrQ%yYso~$xE0$|-xuR)y=CD=tikwY%fYUP8FmOs2O1z{ip>Crj_tkm_fGTdCILJ5uPwxJUQ0)v`7MpJv``7L0-nI13}JTrXkm znFuUET^6GR3qA4ehNv3mX=-V9C2Ts(rsH+V?P&t#NO#rV0v*i*K+0*&jX?pDlTT`v~a(5TCvJ{%56U zB(6%RF|e=6@8H=MmqzUu@FN#7RAW+<4GciF?==j()p+i~3j8>s18lcY|FVD=ka2vqjM&bQeBnv1Jrk>wi*k#9zVpxoELgWBgyTjc z5#!FtrEvzGAClDbuKUhllJOZwLPuv%jaZ}JmUBXoiG$es^NWj<+joWto$X?EIcZI3 z@lV6OXJ@(P6vY#C6O9QQ#xte+fjHooE8EU^4zU3n(gM=m?CLg!C@&ATH;c$+H{4yc zkr0j2*YgQ0dC!AvFUGh_rJy@EV*NTp6-eKZvK7ymAYX>!W+TtPcUZYJ*3+2 zHdsgvo122UM@-UG-(kiXK)hzTDdNP1%y%i(9d{Y7D`qYIx^vc?=E^2Pvm(4-d=Ik8 z@9OD-Y@V?waPo$;63No0GiyLnq~zp{`CH-B2}}av!C#*wv|Zy&afc$_YQ1QX1QG-e z1E6G^VRS^7nb(>}n$Yd6+THlCY*a#4(VX~BA__!`1M*EA0S=1UbVPbg&c2gR;>wy6 zM5hV-L$?)#&|b0H=kwMT=yKa)my3>#V^2lqZ^B|e9MYML$Q$9xD79Oq_FD52tu`uo}<@WaO_(_`F zC$X+J`oQ6In#M`6F6;JFg#&b)klOLKPnyUPyhLO$&9l#XBT4Y_#Aze2J>Yp|Lp77V zNwi6}GyDg>zI=|Qr$iKyx|NViA@P%FW_nzac1R%Sa#-XI`mSG@Eq6l5xmG8{f;9Jc zyuZoVJkf84{x5aj-riuxHP7g$Xp@b6YMDylSf{ehu~ZOcNyI%95s_G0^zcU?96zkrradgspye$&&%Xaz-GMX)Uvk5!PoxA%jA5%jn zX6+UjXmAZxegw(17M!UTP1CVVN$BHoB8(PArGBBE^OOtQpV|hs-s}%;=oS`4I+TP* z_V@ZaIci%QVZV%pHwZWXZ-xwdZw~r|n#YW=J8H3p)}mXj-3Opkwye32X1x7_=vw82 zJ9{%T_5uz}wnQ#cH{(KeYjRs~6!h8(h2!|XCY4{>QN46nVAAd}N?^y7${edIy!$e+ zoQdQ<^6vl@au|>F4LJ<#b2r(_+{@-L(}$l}_A^fy^W?x4cp#XX`~m|>B`>qrnGORwJ#TW*<7Jwq=byFp z0HI~yq2$ixa`V+XX7b}m?+G@z}=@0XBbE8xpJf?A- z<1DPL*p*Tq{LApTD2>Xh3i+;aba6WI`Biqebp}~2#upcU6UW|)R=6RWl77~k=vn3tGZ_xh zQ`vVk@m+{YkN*4*>zBN0NWR%@K`U#c1#Z2HQ?hIVQ)b{BS%BoAOUo&0o;jlh8sc*b z+QZ9Y=5cvgBgU|5Z&1NuEK)wG9)L=P?wo9N32^VuWKME1BNG4T%NW`Q;!i+YrL*m$uKJnF8txVwLIXkuwk~Bb-T~6lzpU!dg<+0A1Dy}s0Nt1A z^e7!dLOg-naHAGKOcN5VfNJWmj09&1Y$E1yLT?JhL@=dXRtXpUmG_v;@=hsZB!-a( z6S-+K74z;JfHKEH6yrrKBs}_yox?&`*x-Qkm*3)3oWG#UquSA=B+c?L?-C(qMl&Vd z2w#m4)KLG7iO9qH{Xo(#2aQvu^>;#Yis#^c9Fy;)m82BzY#ld=YqhVMqXg00{8edb z&Bk~omDLPHtMEFE!Y-RhC+QrVSz=b!m<7{LgFU0y6Cp$k0Xt9LP9TvS2?3^?s$&;A z0(VC+1(_*PNfD1(iDLE#d0oKy$ouUZpp5y zr|+&r^DX)K!Jj^AQKi+sK6@^qCzxI?D-~C2|3mR++lOdY{woC*P%Bfo)26^ZV|2m^ zsO4_EBT>u=!?YGYsojk^`HwAbY?h(ZBi0}xqf`q$zqomBO}ET*9ZLEcj2r*fseu+s zt(|v1JCYt=)5j-7B>V{h6N9-KVl^l{z)1y)v<>{<#zInt#LN)O&q zwa%bA>VF5xOY+qqMx`Az!l9a!Bw#V-GR!MvsiAjYCQ6(8 z8Y#)23C0DF>2Uq^A3v_UUaQ~7);Bsv10j?m&0&#o)=dNt%KyUx{MxfDeEWhIU~w{E z2|Nd^LW6blLu$>9(J!|*|{ZKAx?}PLs5y+i5Q+s2{jSz2p zr8<(G;txq)vaZFZ&W;W}UH5PHdv9jJYJST+cLJacLZNmU z=ekfLaaZ1c9fqp;i*>&a7q0eg%&?i4y=&I`SCw+h3QqXW@z^is-R90> z5D~h2c-VB}29lBB&;)nj1%ztB+{_tGu~#?FW9S-q+MdGE_SVBeGv0qQ(Tmi(jV`;C zSmobBf8JS5-cFDKJgGd-3{GQ(zZsphStEEh)?%v}wcD;GeqmU=$z#9o=e65A3uR&c zIKsPyhSK|BmS!AIb`=@_xFF!LxHyT2RUIB)q#5o*9)&x*!siu>)=&y`D>m_F%+=~G zdDg%L**l7tm_Az)jxzmyK4c@|trQDB$6&(uWwElVO#N2&n0!F6hPSKv6?kgHr@=ph zMA0&;$=k~}=Fo5{Ck8IOah4*Fb;oY;>E0CzkP_6R`)|5zA`$jncIK=1jZ|5DJz{>9 z<-Iy_NcUB{YeHZV|7qEa$vbt4(>5VwApe`Fjz{2WK}VNYSAh3cBKI^!oil-`-De1* zL6>Ltt>-IGL-t}J_ho4|7i(Uh$#!%p;t9?GO3u)d_@JsjRA|82p9nf;Ww(*D!LJ4BfuA2 ze)*&3`E(j-%jF=|`pXf0j~(^6^DSpHB*qHQ*i5;B=^wdVYHJ5@f^SmoBWY)<_GqE9 z%@=!DOWoVTQ>`wT7*ZRC*QFCV{$jzaeHi;nMtGVV2R4EVb@0l=-e@WtUgfv(5o}eQ z@U!*4NQaFC>Z%${RI(Z&ptTgPb+Hw>x`5kY<7sP0hb8$yfrppZ@_z~&9;a2bK9017 zaPHsjHyDgCS6mf~4&o{eAO!So^*%X({*~1R$V7e=*u+uz?FV9Qo zm}P_;^5Vt$i$Nx3$+vgzOKl!@#ShTid2Rvg6+GR#gio>@N(`|9sQ<~=m%PVHStPOk zN=a~IU&+Cn78X^^p1y=+LfW=1d6!!YH8H3zr_Qvh&sR=D^WUwuOy|l}z!m23+>4D} z6UA6koNzmbmG_|Q)b-RxRlJOEC#{0g+$CA&=ToEgiil4lQr?C!e{lt`wq$+Yvqk*I z$NjxW#`XDZxNeE}Hd9omv*Gv1Q)CY+*Xg50d zfH(r(C{CgaA-EVRo}#s9k(AxaWJL4{9quySc?c|Ox(K#~q7onv&cm{-asm>+k1MKO zXz6#?WreF|#<>aeGFed^D?8pMzt-f?=Sg}_TC1L7rA=r$IhR{vus>;h1owqV(dt;* zGJfLu+WDhFwP*i+YlCZg53v3>Q{7ZewJ@aSY_V0wu!!F6#2df(-{2q{ze1=9;$EN2 zDwcPY6=N=p@8z%6MyuwXhohLiurz0Z+|+F%3*LpiuhKbu;4Q1mVzZ?{WDx->)#TmWvhmqnY`U zsPLOq6+@PX-m|{riq0O8-@4Ed%;3x|fUBubVNjObn}$12sf>=rRw`|9bA59()9DzI zRR`guHO=XU?MA)dR#O=BWhqwg4<5Z$Gya&NH20TV!um)T>hfdrT9pJv=ART6RW!ojPcTc zRDASad0kO@>&t;^W{qgB0A}2yd_Q2`VK8+o9SyRxVO?M}Q<-%NfQe9jM4Hg`>UCSB z2l3;G09JsG-QsZV4u1foXhP>O<<3LN@M7+-t5!Y1l;gRX5iF7zTW8wx3e9Lb*C{1V zmLd+8RP;Sp`aNl$;*Ud0?f zmPu4LquzN#vaX_S_)y#qF<|HmZSH>7wXA+7$6{WEdK5HanL>~AwKG}k;r=4v!Y>NU zDa3E{?Ac)j#khZMVTWBI_;@)%bq0XU{x0pjF^a04EG{|M41e>rpPv{)b!_Sdo1N;< zn(Z~)VG{DF4I4=poN5S-0;OCt+!yPmMNBZ2#=b>kl0rL<{Cnp1Zpi6y_XaQrRaCIn zfCOLCg;1}<}}uu z;=?|>PPX`v;1*nhT_WS}>uux#r+jf=UCl)INvCj9S@cZUKo12%?=RP$`~QfEkHrXk z2ZGKLs-rC3<)vAPaMkUaoUKCwUK1kiZC?_5t#_=DjZ|#`b*mPoWe(!W*Nm*))%n;%QA9AsNHKpbQT3gFYR4 zURu?6@7veEF@tSB0v3H>9u2`(71hl%({j7waR+xer+C=)5@CIiKO0_~dHY>45|3i_ zX|L$7_s{)i1(}gz8%;h*(7^NthbzbROTk88#wTLz7`_BcH<`t*A~n<%jI(^wfB`1m z0wYnMb+J`!#jNM-`JcDyuwMFKV-^f3L4aL!f8-pQH?b6Y)R_fi>H{5{VGYtruB& z^A9H1skK>qq^l<=;QqdXegw`hy`wj-#Zx~HmYSah?qxGq+N%E-#{D0j z`=O8_uOli;*)?^PfJJX~I5a&pAPAqbA~VJKMF2X}UrScf2gp(PdIdN?H6&=EO{fC> zJiczt)HL}IJGNV7V%%c2K#(uUdr3yG|2h(b6udl_fGlIu0$YNUGWx+a0#-3Co%n=Z_yONSo~ff9+tRiaS}~Ya3pqQ} zjU<2ZQ&tJj!0tYc*WYHeV%A9Dhb7+fvE*U8^$sk9v$Ow@Pq%jSQ1XkW>g%T=M{qiw zMKg5XH;j_(r8^muSj3D*NN*c+A2I=;TX!lEkW0BvqjK&n&6J{wU3o<0R) zS|R*m`36HHB9aW^R~_Ewl3S*6lp?l%cV}s?x`vrHpgd%T^u$OAxURU#_tsXctu2S4 z;qCf)|0BEWwp{v0VX9Mh)K0`!MK{e6FFn2diKr!3d76JS-NE$+S?>XNk$tFZ7L_|h*;h>80Dsb)@kE&bV9I>&|D1}NYzPO zIHg%SMY&!_k8jrLWTCSD{EjE&<)0F$^CzeC_6|ohA z2&bCDinJ8%EA5PNSUew!BmXArbl-WN z>NV5y)QTqcSdR7&x)X`lX!kI05**`X(REl->>vMa4@5h-yVn}D0jsblwo}yQa>RC3 z;6MKu@ss|EXXGv8VqK9WX=v;XQA1jARmO^-j}v(-74CY0jCw+?is63|b~9MDI)ngB z#0AwphWg!m*@9jSTGWQ2-ea(G#>|lIXf{%+9hjh#QI(mzBZcRyt!}VC%j!$Y`zV55T>K96 zkr3W2-8v%^{?bi;nwI2&`PNiZwS5~N5p8mVZ4sOIIBr~+=PVHf9*y=W#-vt7;49{MPWL0zgMuB{#$CPQDBQx3UMD_M;m z@(kR6G*#B8T(NI@yCb{(Qc`&aj$6)pS&$+DDDV|q`%IWDCCT;)82<#eawm#h47^{-Q6Vu8?>tR ztDIMGchVdlA$v^$&z>;nv-z#vn9_z>6rTe6+B|q(f?h5>Pajaun$y@wJ;Eqs05tEg z+>2({6)JW_!S^CBm$_$)NJEWAspz5wPk100AfqjOdd*d^Ei?6RyKA8Zm%?%KB|rp=OEB0c|yj8k~!YH!2rWzuL^~$Ng+rb zU1jVwr-e$;HB2?ty=mryLPJ6K($fn?%$X&l1(TA}(<(UO!mH|==$4#?<$UlrQn|s8 z$%O~i`y+a}dUy|L1>FiT!SA7mkAy38EkFEKVLxu_e5@+yYjI4NB{jMdXCb(fKk4}I zBTQdKG(%Kq)lzjA=Dg^Y>wN9r>w+6d zJKYLmYT1iTuQSd6s1!Yb7FkTcMMY+TFphgV*I zV!L%FIDB>&RY*@S>ZNwAsAml>2Y*<&D*2U-X;$l7?CjurZh}>)AyvQ+$kCCulBu`n z2I9y-Odm7`_$;O$`ZmY;pnL~ClM zph4|j2`7e+YBn%_^pPkZTCJ_~U14(gz2?`~YSp^2*Bv>Ln^7{NzM{L~OD}oemV<$Rii_U(^t}B%tu7|Et`_dkmZC_wrEB$nr0jrUY0Y|HPm6(c=V~5^5SYtUcc|#PFMaqgH0dVVow>k!Mt9GE4vL zVBnD56!=Qp{(R?Gf%aBL?L>BHos+9r0fxVs+Jikvg2!U>=C|W#THNe5Wil76(1)pU zr4Ezkwy@K3sPVgaNrX5uQ92_RA6dLVzNMX_Lhy^(*pipy0*#ym4uVwT8IW76G zWOS0Adr#sjzm=*ZhiChe&^;kSru4pgpC$Ly;7NoYG)BLC@e>c=TUOuaw#x&fkfH((cWk31E|zmmlR8U+3BD$o-| zQS*@Yth2#I2=mjF%YXoW*Va(;Bkoa55oe+Mt8HU4?^;@?)t0HZr=LR@@#K>f%4hOe zt87l7U%zTAVdFM@10S%&rE7i&}k3tfe5A@sK*kct<-B)^f5CEyyYf7q>{k_ z`cNTL?dDg`!C&G=;8Wc8*@PppVB56yS#ajn4AMy=ZE{hB71;gI!?96V0zJguZKf-B zkPv=T*N2aMdSUV1r@rU#W?)h(C#@nEcKsK4ooV%j@;6}$NjLt2djE;71RxDCEO`Rp zvzSHOz^xfH`?eXusWZ_-J}tiM<|B1RL`;#Ik0h<}efG@SPV2YsAvFoD$H}Q}b7U7J zeunx~1f-fHdM2t5xkc5gB0FcM6qY*Zv0{ zhVoYVJho0z3$%X1l{K?ar3@vSwT#h>4KQHI&fMI3&>OeyZH#wgHjp>P#Ie^!SY#>4 z$8htw!m7z{O5l=Ui2m-(_d=iafE*ac%h@gBQzJXP)$Ij;_st}^>oL}8F$`;+O#;X! zC@F_>t#ZwnnX@NJLCYbQEOzzX|43wpxU?Ai4iQ)Kqe0E-^T2}N3cX8~N zamP0)w~_zlf+9b>NsyAws8hWTpIRsU`QQ<4k`F9%r$yEnK`LOs;aUDVwh=fHfrKc8 z?$vtw^jP!jr+th(d)@5V^_v*iFg<$Vk4+QD8zz#vXVfIA9Z9+>SIN$f5ha0vj#KLR zjicx^eZy!())PLgNZZBSt-)*&g8WS=7mN^>oCf-M*9#E5Vq8ZsfwKk z#rVVN&~x(WN0H5RDi@gd!38vjB;b5{8bg4>BGa*;T$8UsR1&f4x#`j`nJCxWxys58 zYx3+f)#HM0t1dnvE*epebHRY>!yfJ7pT!pp74Je{a{N@U_`egPJ&){^D6K3OkESMB z6-F8nJlHWX2tGggif7i2=c;w8v3d->a-rsxlkcVf1qJndXh94nECj5jDK3Ra6P|T% zNz98(S{;e21Um|6e*nn)9BNC8_2$C@%8KFcWdkj z9y8)mJ-yBqxA#BSsj7#McI@kvbM2*nyox#H#9f;_lG{$lSI(QT6e*g8BJWY$OL^Em zsQ{f{qA5bv?6>6vM32oQ;xlzl=o^*_5ajI#4srAveam$Inx-5l?-RNyQrytrt1_&# znIv_`+2KVp zMGqa~@Q;Z~x}aBuSxSqmYHV*3v35H1USd^<)$yaUg6oh#eFZM^+Lv)gAOsO(mB4-r z4ZWx4WRu-J3$Gn|dqtv|`6QJm5@m|=mNz^2jM5s}n;qu5;ddbvFfWkjrok|%^4sg) zeS45aC*t5T;C{8(&IaxX@b+l*rtvsdP8F)1Jn%8vJ7x}U61gRV1`>*Q;t0Z7sqvor zv;wjT6J;NM-5d^g&4kk37Al-yXu4b@JZZT@zC%yeWGmi5Ssh^JiAIR~ z_r<&T)4<$M-~D3{Mdp7FttTd!2>QN!cXgOXyd&BDL~(dh&lYebza2*tP59VG){S?!X`$S%|g;FLUMoWh#=@I_-6mAz&mA#1T`;hwnC+xQCwU&vvz$w zkT{}JyXl)BJj7>vuiEqbAyZ0Jq{N*kzqX=5tzzJib2&rMQOM6o;A6E*ewQ)w_$0@&I!A zPj=L2eSRKd@4?V_^BZ0JPSY8y)z1RB(&djuZVGmc*W9`H9s4)#OSUOd^RC1eJS3Xk zHFcU=a!8FBN|!YUkjB{sIUcpyQ6i2v(9HN(x^?1TU?dmj*3^?PSiQcYU|Vs98O>eY zUAihk*PE8t9g(-BGZBBuM@yS9kTJ?|<*V(OK)b+M$n$w49Yv6OPSYuVOPW8V*6^v< zY8hk!WzFxJY0r)}fQ3Tb9;}BKje<^Hedj@&h6tKJ?lng7_1fIaUX_Bb;Z80t8nujq zX2!GI^W1rMg^-HO?OSrFn*!>1pn>$qh#2@5OLKGWR+pb3(Jw!tFlQ7!dxLX`HR8vA z>*3E^{L^SP6EYDvnj}m2`9gE*Kh{*(tGDZT$&@S;hp6pSyCE!3dzt&4 z>giYaRr+SGaqu2D`5)n&oS!C6;YYJrTowq=TZi;0xUo)u?Bq@JYn<?g1bf2A9B6 z)*@1Gl(8AgwAP+wbxrwJX?mULN5dMqqc#9G*`AQ!h#M)XULz@1XK=QI=;w47{y$2l zJ2w^f4LRFpmpO@1dk_`YGBFw26n9A#fu!l!EUjz&G3t0<--)-2()-==>;{PrLrEPk z4H6|<3rnw8wS0J}s@GxKdf-vHP&Anq`q4XtpNRTYax9l2ZErZbpr?*P6%(~~LW1gp zMDVd`V0?M}JF7!r#~)ypcV7V?BI(J|X(DViCvt2Ap~{~O`qNw{c;&D8f4#an8S5U7 z{igH20079E7v5VjN(#$8eUT~kI8KaJDO&Lm#7uFMeY_bSMsg4ZgD3!0#vY7y9M|pg z-tVnOaVDWdgf$LB;kL;jCCnxc_4hOEqt%b3dkaO;0Ckl|SPVdt-l!wvXl7<3{E^cM zp5RZ0io^|5N8P0BsrIAt;RSg5^3nt=lf7aLmC9dWuqEue*}9D=nVy(lW=B!qsViY5 zlz(#!s-T3`VdNYgS~nxW!A(D93k2wzz~GZ4)y&13Yof>^tX^-W|A#7~fI>u;4DC@4 zG%(Egxtax(0q`&JuwO1(%X&P@e=@CI_G5ofn>~ZFG|7=w)$OCpD{^AbeC5+ozl6tY zNFqe5<8E&D1M)4%C^agcTEPu*kMoZos5pS;Jwa$!-wISh-53ss z<}lO7!qZ^f{pZinX&)M0<@9e)Hkst4;DEWm7Q0JE%^u}ivcn2QW4;)hybg1&Yfo)R z4qKC@_|s?5A_EdqLw3_}^kDCiY1jc5MTqn47%g8<`b^*4Nc1p%25fV8>Q$!R#gG4Ei=C#BL5tw+K~Ou#*p(PPx>U2|9CwOLxf*Q9w~wG7qIW``9^ z^0Q){%k0`1QKSG`^_$Df8do@6f-G(=JK+fX+x`(0VB>s~{n}?`L~yio(=OQ?)B-GJGWreEJGPEOVM&63{zb3UJ*V!;5&krS4j~}U@j+o@j)?9u}73B0H|Yo^-kt?nnCima;c{+^w5 z&snS3%i|_vvE1AH8?>U0wp#+dTGMnET|VZ{Fi&q}CRC{#M=TIhoLXuN6Day!;^}9r z;X~FF`2Im^Q0Zzk9QBY$xgqa&h#N6X&1Nm@p*1qvtC5{Dk0f6)T z(YbZHeuiGoXI?Bu9*o<)H+!DxR)&we*%WK!#V#-GZ5|-k7}&*z@vd2;`amD@-*%82 zI=Pr}$uO*qYnLctej{oLpp~FUJ=QNs&dF~*qLr^a5mpE}F#Xr3^2gkIlN)qPms&>e ze`6wlCr$nipt_fzN8r~k|L`HWZS1`DfP$2mSY=6Hq|Q2jIx_yecaPU>kb=sh(N+gh zHcsSDf%paZdNU*4UvzCoSgD_`X=I)BNe2vYWSs*@TkNFKok2QZr74V_h<#w3@!=S| zjbij&`IT(Cy_Vsf|0OWtRTh?P_!6Qoe=buu56%ShA?v!bAn})7eUo`J1z-2`QeG>s zx>WIm{MjDXk*!*(evoOo??Ad+xiIpU^>aRF&>E3OzJQjJY423H_6o?r_#foOU0vfN z@MZ^NEy{?xc@z7pkv%Jpa|I?3a4@l1#9uNv1!gYKJ}nk>6NbR@VgPbP5_Z17e8Mi9 z8!T5de*10s`j=EtUI*EA-KUlDXy?MgG3*?TQwXxq*hE2T^UND>m z@WN8nXH<6zV&f`=UpZguU*URPZ#_k+`bQlxRuZr`yBlK>?NdHyV57;TwaZ-}xJGhv z-g{EYTCIQo=i9KJl253_AqU88sVikvgTdv;-moUCXw(x1!Uq$a#sfQ8MFW>K4v@o& zB4NtRcnZ=v3dq@-oxaeZHP|)PIdZi`$n3CTqJkvhR|HBOQp%}I*VW)}u#Uqk zR%NBp1mjm!R$8AGC*sYaAw|N2hIa_z0=oeKeISjk2h5au4xoET$Uo2QGzlEZlT*vcp9hyfeDO)bs!MVBj*L zAWVhTFTD&|@;tF6t-14$D`qCl%23gj!9Sr~U_T^)QQb%G8Auno0_cZp7k`^-s#vom zhYt7dHy!<~?#n#`UqA_@L|8$;a#$y-7ZwDK&guPN1k;CDBQYCGUqE(hMajcu;p@QRe6Byw$x}^=`_2znux}Bvm~0}))E4! ztkLx2CXn_K)TUjZj3bw~*KfWLN#I8E$x$;DcW zE>6Dz-J6db@p--#coVY|vW;4dN?Ux~F$UyBbtZmnw#MM6&h_4Qc|J<&O0>eO;|`4i zNKC14f;B--*GpIh%qspB zJ4alSd2h)P7N-uLIiaKw&jpU4s%2k4m;KwTVVX{hiTS!T?z;~>abtnpHy&?#U38@l z9qeCxiR0ASK!Kp-^@)*Rt!odZ+>6h|%==YoA{0d@Z^G z3y!_EXg-@|S1=d_9*XHTSSNJ50&se9cCJQyNSN9p8>8K7DTLLuw5-~NZi*0vCvuo=0iqg#4odI z<<3Mn%wx%q?dc0XF{i64h2d8$x&$;3+=DF#KA#V=+Bh^$puCa zXxwvQ*TZLse5F$T-^7(C^9{+x-^}>al(xt?r=kH|C8677^bhe`-p15UUsz$gu^G5e zF3wc=ZtpO=LB`lPyJBSJcItwD0(U96$6D;$o1nq8SJUE(wq|>6yWMRX=6dho_`UC> zO2zi3t|Ni3D^@X{x%_^HgP*-tT_U@`El+RUQzQirZ^l0@4d{&wqkg2l}^XB zZ(Em{-#vNFfsy~P=f#TCUYSiwf=WLe@3$hyW7tz9vVAT@IU+h^_$c@;Xt2Uyxz$cH z!qga^#Z=D*?)t|nbV@#opF((q?~}DbpG)}q>3HBg`(j0?d83T%eyZi?$}ez zc<7KCt5Q~CP+JLj*TSODZY}eRvR)2~A-`^Cdf5F$-P`$7m(gt$6=Oyj)pbnz%1m&L zid039e(9yAZ7X^uPE`^h6!2rP{&b@BTKc%fcEIQ|DX8rAEfi~|Wc?)*5isH8gC}}D z(cJlNq4tp#o>vZ`%Id>p0Ofs!dtrD}mEHem(j!0+wnGIc@mjQgTbB!`$ShOPDdr>> zzd(%U>7n~2GnV~WLF#F?x1*!ZyyqZ2f6p)f7k`h*u+<%^gKG;TgaP~%nH_CMkn$Ll z5UcmXO{E320L%G)u6y}vmeOfvGpyX~Ces*@!z!wI>vHQq_HjqcNGD(84seKa=5Wy` z%E%Cm_QCWchr6w^NlT>!ivXpRkuMK^=~a=%!$!pxGob;1Y)XntQ-v}P7wa8$|0Z@( z)N~f2^^G567TUeN6Cwwx+1&s*hYWHW%UeTpGHL;X)D@aZu1FRsAZz6|_yL5<IMOf5qc(tMJ}eZfYv(QE8fc1MTX3n)CUNk)ZqaI6Mh>@Hlr@% z@Xx?Qo-lIpYx1B;D_1_j;GYLh@Nyl<;l7b2>>!Dw+rt$=_&^o-5 zib_DxV?7x~7CjZx6T#wT_a}KeoAR`+AW)ba?BuQk>jeo2l78X?XPhEkXM##4N8jz+ zXi1JBPHkE$svN?@w71Nxp`iD7KmQ&dPas9x;?JiG#TNMl^ibIO5C=X-#f_r`BL6^G zUm9;Lqyg@0E_p|(UWuK#tW9z(w%!L?EHQKAWS=1Hp6Zsx6>hJmV~F|redfEYD+37# zUKv66N}S`@_N(8<^RL%Ftalv>MP|Go=)_Ln_dglI%G+*?)lO$8}enb z2YXGT!ECKc(~4T#dHeu+HL>rCZMfB7uKg+1H6^(!EK8NOw-8q?PU=NOwz)ZWxRh3^s0lcRbhidj8t}K40heIFEQApO2I8Jri`o zx6j(bLbk;Q;=l9qIOGMf_1{SE!z#9;`C#72*D5jh(R`<|z&rVNRYOZ>vekfFv)j`n z|FdTKF*~DGLUCXQwZE~)PouBG;H#29<0Dq6Zo>)19c#gfpO|uXo;o4k?&iL6XX|Dt z#nt-IJiWZ?!*FO>LPEm1)l}~v!rs2oZ&LoYj|rHrrKDt%Ltbv=&BDmsz!=M){`q5; zNNwb=47N80PT?^OU=`vhb2uO}Yj z+L10M@^;_r&_eFk_#@T<(NBFbdL+-xk@}bN;$RF zY#l!*yR&Ihzni#_4UwHAj>w_PJDj$=LM_CZ2mOj6Uc7|6p%?%Ef-F|2Tj{XuSYW0@KT6Dv6IRu}(G~5`8N(j-*%OXIdr7l^>gBHNh)d|c_uM4I-6iLlf z-}~+zl0c*^h)(x}U9Y;W9USU^jGfI?9v> z&HI_Z7nRMKMB?Q^T7dNxXIjtVNqB`k&M3My%_ZLA6@Pv*#1;K@qa;Lo@|>D&w%ps> z>unQV=CiMssUzPAhA0jc9>4caFd^p~Sl6JC_NWZ55-{(qX~$F~1Lz&*HV#Nvj;F37Fr>EiJ7SCq@LXNF%PL zK5zY8SI6UvvJ<0^v>S&srIczK6>IC63q6vs5B(#LwW!O9-5wPcRasGY9{DJ9VGKPe zqrkp4G&>-#Eh{?Uo>BLyb7}Fbbh>5}XJu`lZoWBV`#QsdkAV*k?)YG>p*0=bYTf?Y zb1S2Y@tLa938yBP)@j#;+)v#x;AiZzT^1{k_A8U;Bwv2R8!HIMd;M2cG^0^v1wx&K z^D7()=F#O4z-H90FnDsB zs?}yU5y>$a+)I+~4jE_JwIbMmG`<+Prw9OR%+VYd*rCXmiNw^wxaSSE> zu!)rdOUXh&F>d#56qY1UoC#%PbKN2QS2cGd2HV3xjQea?&k>tLWlh}HF6IE3#M^!* zo;9n}0=kSe?TFOu&6?49Fb%}|rs~jcar6-wPA2dMc!Nkd^t-%AW8lNcReyt1toS)v z+qj0~1z9a?mF)J5jdO$`;9L+fqzciJ*Hf2nE89^>{m6>>nQ`ystQJl_UXOXQ*l{7! zcJ(_>jKfrOpTehJlE3@n_SWnH!|&{I4lYLK5G_TyG_N)F?jN#`x`!v|8`micid`IbUowrx6|CgzS)X{+w&Y4 zDt%VmQnQ1xf{z%z0*5leZdQ@S)%Rh~!mRu1|0c^W{!8zK2F14Ym!zX-jId4~>^Ms0 zj0Q^cK`NkqH;j4}Y{?B;1&UzwTL|~w9itSWsbc>VyKi_mzS?qLpPa!fWoKMVrjC-) z7&YKdVOeFHCkw9^AaP*|+uXY>IJ(ns|<`PPpb|Md+xM@Fl3dq4;dU`4iCgkaBsZ;BBx3J2kjo60n%ZfDGb#Ej=dvEo!&( zDn;RrBGS(J>w1tFhqnv1!~N1d0$5>_weH7U(}~KyL%>iuh)v*KsH0RE`PoH982kQy zNpTLUuu<0y=gk)H?2lt9%?+gRe49|!IC(q*u}O!0(Yu?UHZFA^+K$*DJ{a2a1tWcD z85&Ar=6DnBTc&)&C`#h$%k_^pEeZ z4F3`@rc`;$^Z}W5Ns$-r8h_Ul0^87w&2KyochsK{k!!3-yNv?U!aVPf(?r$@6WBpq zQhTT>K)i0ls+|-ooz1$**!XH25AV2Od`Op#{MyXpwO;CWaB$X_gjO2tdH`_%exQuX z-P!2oB5PV3*y1{xugjD9DU4KIQ2od^;Z+qGAue`^?Cbyi(`EF!i=>xoZ2~9k6W8XM z_sfSHFCawwFBc!{)j7@Vr?k5TAxWb2grJ%$j z+weeX#MY`DUQtx>IOr#JH($L5*|!5z4eEUkG#@zEpOvt7(%gbE;gJ^lcq1?=Lc06H zmX+4Y>7Z>kns%umo)0D@GPO)5z@HVw4F5}G)M~>Bzdyw(%V7}wLwr7HI)l6F3px$< z-|g_-?(hX9DkX^MaXybDuzoFp{0rOq{!yJs$df!fQKTE6noG+!Z>gJT;h0L7Y3gWd z=hqKV@Yzc2{)Z9icN(WX&I~jpgb81TzMB_a*MQfy4iy2Su2-wxv^d9 zu~2~Ch(;YoVkIX@(jHq}G>f`bPT)9k#B2AnwsQGe=E{PpqPWu-pD?kH_u+))+8fsj zZT{%;Q@8I6W-V3dC_V8anM}zX%0xL>*z;6RW~{7c_swa zCpN^3w4^%~a|oO!3- zxx$}Wp}lyu?w)r+te$PhyEXH>$UyqncE48thd*1MCCsOQYX(f<%{=rLK67^)$k6`a z1K&`p}E-LWkQ162VaN^X!+tu$oz_l+9kuWS7*n4b@nAer@q|YSH;~X zmQ1+fW>P?-e8=j7#nWG{>;7FY5A&->HnFIh_a4`cl z+V!uZ2Fst;a>9+OKTN1g4w~iA?h4~#fKH1IwFN$`M%|R&AI)z!fp&q}CG3l_;i?KT zrGd9sE@?^jFLmy;%_uCGP81 zHX~Z{NX_i|s9m&|R9s%X#MmSoAzw!0B|t<_%lSL9{&HzXbpr0W)pVU3xahP0vcPqv zl?95bfN}tDqwYUqHkM%gpZ)f`aT161?T3fr|x$BCVKS#`5p$C$psG*?;*t7Tqaza<1UinHMdhw$Sfz)r)_Q*$TP)k!(5X-9lT!CxJ)sw>LT_DBN}S;LYnCsw+m9$FtoWM52< zdG@zM6rnNApCc6DYEx_Dsr}8Bm zTIq#1@1N#jV|7t7|JcBvh4j1p;*O3=ao`tH3E6gk0RX}aeYV}w39YHvs4t|eBx|jS zOS@t!esMi-)BuUM-~7&Af1|4_9O#2+Kh zw529A$GfrIl0ILoFR5n2?}@te93L#KipgfYJ3TSuz8$XVd|Ly)(rXDmFCmJUohc(S zXbrzQVzPJf$8fwmM5Rx9L}pzHcAxp3i5V1nVMQfM3ya(@Jr$ zVGYU9b5A?TIwk&Q_Ljh1B2n%)qv#xbU~#V`J0$X%h$X$%;Mwe>&_?B8<%n#v5$!&; z|HlGQFSAfmJ{rHQYnk}=g!!)+HluY;comNPQwym&rYn>dKcMxxkiiH3t{N>^Lmq{r zaFEd9A( zu!`3{C+OG-I4zDlL}VWpAC>4}f_n0Ud!e^W5L7S9lrmDdZ+ODh?-Y zOZ%<)=oe#2xg(3unb}Yu{&rXBr*Q(#&2uxOf`8zyf``y~Ci#UFogur02F zOe8P(v@kGvSMj?X*?x&6+jfp({)3QF9(a^hu^X5Ts-9AE|G9cLx& zh^b+0E%Y2D$gC56>^3Y4y`)BrNy0PJa!Jl7>{sjps$kH@Dv1iBRN$?-fZg$N49ja& zyHoEJbze`2)a8s|=yuL{@QEj)FQ=w#yU0Ye#tC>PK3}`YfLcu!U$mUocEU5LafI}} zCp{E!@x5yVwv{l8%&(Tj<2|?#6PnuMj^#eO$`CN`JD+{hu@YZ6vv}3fi?p1QiWhpC z;`aCPe==CvwKc+KLuLozm;pY9p}y-9sr;Zf(}VhNq9~Osvuy`SbwKS3V}FKScNY1K zqAX0SoXRBV-!Rl?Nh~C$FmR9>4}75Bde1W*P{NuDK8h19rhB?I4#UI~DKm=m^P`vR zAlk=o>-|eFb=5Z-ocvM**|VlsRsTL+DC1*3HdNw!y6^?am(x$v8;)PK6`@9(1h`A7 z8E)!4Z=5^)6LyR6bNUgArv^((cNJ0a3ln+TEk%B5avdSMnz-JTu2=PiDny+VQ#-`l zV@aQ`ATs*{+d`-ka9LJrvOe0k*jgEUIjk>24?Fz_-yj_ zajhlaOdYEK8oP zx!H;zxF_FJGaz7dWmFUN+~uJhUDX=RDa~&$l<9RfgBJhg#cgpk*W20s);jOaWAF1# z95?XggQ$C9kYr zAzK_&7-s|ljhT$&MI(x}GOawcn@ESlP1{RpA(A$LY2>oH;=v&#VNa`}>~`Nmp(;K{ zp6o-FZF8_m=Q$BEpo!Vi9MZh|tNC`4P-o1rjHbpMc~cF2SLV~Q;@AhLVC{&c`f=ZR zD#6h3sBO1xe!3CJ^{i)P&gZu;M`^Gbdh{eh(=$#kYY>Q;G7;eNyxG0qXxhqw-K7U1 zPD9j0f4~03dUg|OY5O3p@Ie%1P>dNkEZ2s$U3Zp1P`UC@EsL6)5i7^yUqofZU+Y`q z{fPj=e~b;v9lk|8 z#>QoCE8FjT+73!-ffbARVIhsN1)q$*^T*_nK5}GKVZftZav9RFKPLrpKE~VcYu0*7 zG`q8%>&B3i_1X%&opGOjH=`N+KGjc$lOTxk>iP!B($Mn>^Y@BB%)L&yc#Kt%@MK?~ zM)Re=+IfbA!@}#%Vl8OZbuzjac=ulKB^r7U0hiN0J3Whq+8(Eri;q@z_w8^RRF~mP z`5!Piv|dSD|H8@OXcjwhskzMmVE7E4@R*uV?m+&f{UH`Do{pVeb*}leh-CNvc!)D( z1md-Awt7!p$P3z)2BlXTy`5@@8UB7rx?Mcp{`x}cZU?hh*mjV;7RG@7(D|SjKdkid zN9KA>$x)@9Eiz&4DL0^f@}i1uk#GXD0lUd~aoUGdctHDNv!n<*8_ zz-jdn(>_Bk@Ft}8|6yuEU$1E~^|8pWjXbvK&whHyzyYQ19}f9Ks!xZm5xqSM>9QLD zjZE z;c|Hs$)_~xnEm~We>>50_AUBt>s3X+c$^X1A87y0*1LbZtGZJec7y`e)m0T_*ngNk zrADaUoMsNo4ktY`G<}qct6o&Ia}m&Gw$%LQ4!ws#&(#Y!B*Xd>=zo4szdP#?=?UW8 z$@v43(Bi3Q;^WshKx`c^A$AUH1}U4|lw%Z^yh^eiP683XMmMlwahwLa=ivdm!kzex zd4h6baSWk~pj4z7Sc9&qKhLja?tBO0C-`x zt>(r-@I=DjNgwsi_kbsq%VVWZM<0l0Rht3{g3MaCR+!qeL5ohgb=eeVeSBx*f4N-J6q#0iVCQv3LZgpntlDtwlakvYG(ci^PtjruM5VPmGv zy1+?yM}wM|4a6<|)E30wnZ8ngDpj2tN=@fb1DVCEGNzPzmf-)77d zN!u3xd1>P%&1$5Y@CUKA={G`n>Hs>7g=FkLJQ$$ECXf=Q*A1P%+;RK6^;cInATFjcqQ8SZ`WuK4Bd90)_#GAU37K6>SnIVvR-ZbUUV4T;N-i?cKft~_DP=>t*bXS z!Q*X8wE<=Nd@lg3jg^fO+qsb*kggewa=3|ku$#I;%|i=1v;H)FPA1g(-H@aV0bRY! zgB3^<<$pcq*(8ORCkHq=A&PlBSfDpK&?=e8%Z^b6?)Y}hg6LKS5M6$^r5R*2H>Wf= z7MG+KbQq6d0;3)&ajVvj_1G$Pl(=|H@l&?uo?8X2D=jeo`}#+g`+P0qg(xo+83<)d z5MfL(spu}h8TR`sOeG?{=9boeuL-GP)z1l-5E4R7`*T*4oAl4lw>Z*TS{ znOfY>(_JY7cCzfaMk(&MYkn#sJt3HSSC02MAS?7&RC@{Rw&amZE7f<`M$c%Ke8Xq9 z=7o$@d3`AE5n?S-Uh4tL#y`OoA8tDxEmQ9Ri*4SY(j-20W5!X$a4^o4jcO#?2uoVPa$!wRvI`?0USmSm90QwHhB$ z#rNf)$VUEd(t%YurN0%hS;cHeR$l07d(g?HXlgUhS$j%oN^GGtw zrX-)^b8&S&wamz#aNKQPp*CxC5ipb>)RoCajaXsOpUY=ljqC$Se%srDd6B=D?WoJs z^IjjsZ7FzU7S~S@2dP$Fy^^|Q0AO+Ip`99$E%+F!c8gy`+B_59;9i;re^t9yjo0}? zT5^r%$z6wPa(W|ygI`Y(2_N40VRVTnAc046TKLL*FZlbC*oat<{ZcdMzf=!iCN-O; z=K|_MY-zi_-@_5Pi-Z!O@d%x%2cALYxJc`t>UO4vG)$(oKlOs2ISik5(Wl+lF{FUS zIPQh*^1Dp4(HA;57#4Y)I0!xrZVsqZ`(;?9-{W~E*E)wZi?Qy*QXNK-U>&_$A3>{c zFzMDXnmvX-a&iNIiIj{74@3cm@c0XvhwYi&I&VtaPrHc`XomK}oD@ZtoTO`3Tf{?h zH3+-m1?!myVenXp**P43F6no=x3aU%u8R@1DABy)A^vhq=5~T!U>s3il{vWGKik*( zM&|siE%-3<4#A85aW^u4mwI;#z9&E&LeFSJIkD@(j6wB+>;?Kx5MWy^Bk*P@V|y5U zqbkvNUIoh@^3ZGXBOB|0aM}SOm?^PbS6+P5X5tCyV)k!`pto+51%E!5V`1^;d#A1IZ8)yjovLt&?hv z)EG=jwUAdKd4u(NW|pAss&OjLirC=d{@{}4fE^J1O^q$h+11rC&mMRzSTDS|943cI z=*k}H3qbtY=vuUQK4f2PDYL1)G;H{kMZMmi1?nDO#T*y@9&e&L+!r=>e%`5kXY9mT zT~_5wdQX~Z*+Nja0Ju!68G!%K_|8vE7ux6cu&0Y&tB4VccOwfN7HlFDa2G#PtJJ8Y zr&C9&v~6a}GBhXO-2t$W|mUW|T1mg(@;tGrIM*HgWt=x6^u)F>dc zr-8A!Vav`9j)Y9MTWDOYhrx%GNLSOiTX>DkIk86Wh#8_Q_zgrpsh2e~3w;mDH1J%{ z!rDBq@_%p_pdkGuI6hmHI|tCT2D->|2-z4OF_HcGJ71J-f9+$wSCPr={~0^wLT`Ye zASc{}P(wK3M=EmlUKVsudjD}1y`GTzWk5x+G)B*AsE|fLdCkt|{R2QKox!=86tvS~ zw;eZcp5#PppeM+z^H|bl54Z4!_Ht~JBFfxcfy;9zRcB!JyqymgPZ;%+xLa;qDWYre zE+?Jyv74@mKw8die1GE|HH)zM#IvZ=zbpIEA2g>gZu}47GmEsj{?$d*MCL?QZYepx zeh-Y0ln@yeQ!Hjlc(}0gt4bq%>P3V;H}`A8%Xl3q56K|NA^Pln2jt6~w1{*9;8M1& zBb%nul4-=*D@NZX@Z`_LudCj8X5oq*0A z?V*pZH2_ZE>Q1hR%3}UhOe#v7!r!MRB5qj5aX$@ez^&zMDdi^V!+rs8Dp?a$Gx5E- z>N(oYm3dH~mFr>Px-1Oe3Eu8+v$Lv9n}xwKo?~gaRiojOtWMs}=Vx{hJa=_x6jk?G zHd;8wo`sY*Dqi)m6Zq+sA>A+c{_V%NBiD(4+B?c5H{V##Sc~W!*MJe4n3y1B8!W9< z=JH$ngK-(+?tFa6b6lED6L48X@kpP6sS@QaX|46fm^1{_Jkhq2Kjpd_Re8S^^Es=` zEl}vH^DNG70D{?v42CHs=+a(3ERv_NL4s69vFom&`<4QQGi(&^ir_cB* zBaEsbSUAoEjqJS@?+3y5U~ohx;GFN=cYI$jf4CzMxpjZNc+Um;e){Y7D$?<(ZO|xJ;ySXDL!;lgCTP^&C#Y4i6PxSS!q)d+noB;E+Pc0 zcMxPa?t+llh=>FP#D?d%6?t{n-Hw@%z`>^6S1%XG;pZd62S{{Qd{d0St~1(0#}!teV{*g_uE&D?Eh1J1eYZ0;2F zDd=c>QCyBQVN}&CKUs=dhc)^De1Nw#eQ)04_rPxB-UqW zTJ-1AsIC|iK0*h zx`t=R*^c`*7?Zc*Lz-RPXH@---8QuKlROr6>WOB_N3PC95nH1K2hgCHsT2j zdVQgJs2Z1jqn}_eX#Y3l@xW^^1y(OP(uJWP%ay0gCP@- z!=Y)9U^M$6=KxH5=+k%ON06c)1=#Bfv_Z{6b9v#aa~WvwnpfwmqGUwfUL4S=2RZh zn&?zmx|Ky+GyHLG>Fm#ZEYAnu4Ta$eRmvINJ<@cU&U))=2cR}DlDx|1K(CpWC_WNA zFN$0urBHZoq_JR+52V>cnf4n8q^=7It@! z-M~Q1BmmQoV7T7|Co7vREEfzESC=409>$K~8^}GI|N4y`mO$1~qyP35a_QjR(rLVa z?M;GHf6lETlU(fNE@QLkf{N{*wwsOyplH641WKxAepXp4m7TgwXFx*&l z=1Pv*oqqP1ri5ns*d_9R`Gmo=X0y6q`(A8F2*+9NK5lOBBHVkVzttV&>;Bd$!d5k$Dzo>Dv;=%X zQsT-kf0v!`12o-wOZ{T(r}2OKI+c9bBY|FW)r%!+AJw{6bQ51ieCs!`xxW6IT9-6p zxW`t7d#TeJ*Di_v%3+xv&OFn*dy@Ev75iVCTKS}I=C9}ge~G`9uMa5{N6z`S^;jUK zE!nkd*w0zx_Gdh;JELCXtY;I^O}YB9W)>CGJkn!wYsa)cY&Q))@EABN(w*W9+E}sK zbiMaRT0a>qj!a-6MEnEc05Le9v=9HuZp8dSSO&}wnIkkVsV{S#M0V3%WF8c5hi^II z$qPP5iJ6pVzHPC4`4J`qlC){tiI=OR!g*|o!12DNpzN| zRHo#O$;L*6ORu!n4cNqHJ7+~|XTJn4o@zM1?&>DB6^QEh?D;7m-ziJ!YC&^Q^uW!s zcUm=5`mCU(wT?o^^2ptwZvCczBZ$4gQQAX>bCL5lE?zxC;JT!20fPbvPrwYOqEF9r zzP&Uv(tP5?@WWjyPnFIk`B~>Xtol(ir*}(zCu!Rs@V5=ED|*~r2~Rt-9Sdk3lPv=D zHH*tjrc$q;neTP+bj@6!A3GVC`Gxt&jDY0Mg{z1akhJh05z}r!O~1#jR~k!!&DT7L zk-nJfS6$W*4aZPQ|7S7LSBQ)Ayu+}vN~v8@;McINR_L#-p6mA-sbPqHQPCuv%!c;b z#=b8L8;UQ~1}Wl6vxa1(PAn!I$-=CVS4TBcL%kyLR8S6TGq&Zea z>Q%&xlp^WhcUFCDR;hn_?sL|7=5u)w-GlmyoPoGoFE@#;L@HIE3-ukDZp;SAOFLNY zT!g|-u=I<5J@3h-2J)^1g^G)U%3^we4;jL6e3y#jBP1=0`HT#Wo$pxG7BlGRS&cR8 z<>xo>plj|MYec+Sc~s-Tq<;*r)^e&~PqWK>p@RJvXA<~8X*F0w@kZD^4(9V?+T`Wp zrzLecN)tdBn^x5a!T*M>q{&XjpZ@vvJ_e>NG?IBfvNgGt-+sH^wB_z?P?W2zr`a29 z;Gi~Ft6^F%?w_sk@tXWk>*MF2FexAK>nRax=(-N{F?_%mcGF3uPA?r$q!iR3{jhuL zalYv7j~Ju$*j&7vYocnF%$k;GV9Ov3Iq9fH#+2W-^|wg7341?#d192Qq2sgbWr$OU z*&xN@2fQ^^lcFANU2aFzo0>tnHxaF=FF{DPpHY<%?~llHVNKuu;d!WM>n>09QgHCX z5SAAX396m)X73N_7Wx*<=-tUKp1u4eTSh+sSd+}rWXjZ(C|^zDI$Y}7&at@>Y5knh zXZ+Ud>>tpToBo!#Q}t~>IOFx%+lNC*fAi~_9@ShY^m*A-9QPk&>!+RUR>r52_EJh?9+G?bx@CL_2WB(_z{p=TYmOWxuM9}1_5yZ#bkzM#Im z7<3BNB~|{?$ydZ6Gluh@t{9o&6Wq+JO!j$UBU;lmAD+XWw#nJ$MDm~jOOt?G?q0Yk+|CAu z#dE>g#f}FoLh5oWMS?)#*0_iDedY^rLVR!$86n-PkmFd`up);3RnLd@+Bd%txSxaU zc|r5_B7M3;vM%Cf4$%7MQNv|8HkPqK=6QKejF5kE{u!ZbO3TV83dgoYuZ+qKt^Yh; zxY+&SvJjF_GRZ9W;rp4h0$h19oU=z2 z&uJ1Y_&yYLe7)fd544Hg=bLV~?S9-6=(6d!)aSVI6l~^T{#6;UK@+l!ADc29{RIU( zN0L5jtl?Bs4Z8K9WtzF;Y6SYz3?aVWI4Iz}nD%MWtuqx3`G!Al?c$|3hkqEVY%OH&{uiOJP%H;CWA^nifdGpfePO)`jgcR|YKeBM#X3joSBR%pj zZ+k7t3?t7hr^KyuUDA1(Cl{Z0f69-x>eG1L0Zaw6~pdY!OGjnoUqg zvxP-P0^mZ4xW}JmdBN40$gtnpUOw(0z}-{GG=%N3sU{C z4b9zY)f3*xHj?>jvq4izicBY;#LWkClHo5erf6CI$-grtG0elzp6&$}mGnL-<%HtX zI+6YK%_ppD(~A0(8lsETIVGu4d&k}}JC`8ajr@xMB;fPA)(RUZT%qK5`G7K6@B z_33CYi4frAHaEd@VC@{=1Q%T$h9sf2)8TKgE=O(chm$dvQu zL@(4qg7vdDZw=;Lhh`fj1vo^lO)K~DlPcwU01m84x{E(8Zl!AH2wah?x7ho4)e-ih zZjwTXOX(G*&B?Jlo8v_fh9v#B(MX+&9-}6h);SX7hxj)09Ke7*#rh`X^dA@(p?RT?q34t zu6EOh`~dEvVusr7H*P9&fjMjXC@NB0Ig0EfYekwF4IaXUsq298 zZ$=vtZD5xQ&+TosjC&yK_k;!kJ4hz+Z*+5|LYuVYZy$60#AfRM)0+HMOURYnf;rv; zvo%L4@>vFBq7Db>+==o+C*_h&Es^E^wPUUfx{WqdXzP5T{g+C z-#N6C-G1r%xO>iKf3!cY;=d11gB~krl*WJfNI^Pm&Yp#&sEm_6C+XX{llHbwnKi4r z$l-^Tx%#@^nl#g)8JOF2;9ORo^vzwIcI6eB{-=m(A zqH-1+aRx14wHnRH_7*)eWTOK9-eyFvSdST{WSO|0+WKzQ7zrH+SV1_Q(nvaB9?S;# zqFV=hjg@HzHWS};X*1_dQk=<-vVB^w9OCTIt*U2t`9_lB%Hx5H>xxwqn3Y2%nwI#G zo%{C5q|3W3cclAJe^JLl$Kp8BwJC2HGIv_f4jZ19IWhg^NAYm#yN|FKRDsL^MA(!J^3$L zADezE4*cyC8~MX=lapX=6=Y^xr=%^NJ!E?+YpY^G5!bBoZRYLMCWYELzQN(M=R7o^Na{G0|UY%14SAh@I}ITWoj@pgaC%IlRqi6vHtKWhrOmqhpnvfLnUt8H(n5 zSjR>OzlOUr__$%*Ou0s>Xy#r(w%>3RK`3)XSLJ*)h)Mh+=KU-FB5_b1^+Km8al zlJ4}Uz4^)YZu$eu^;+V7(95D9X{`;>)H@#{dal3P?qee3e_D_&qfp~J4otFI_-K2n zE5b%l*l=M)kakpn>-TFGe58@`0_~YeZ-)Xw3NgLB)n3J{$j`021u=@N3X5XgnLpzE}|mk-rxl8{|i1aaqu_W&eV>?Ai;|Z=wm(bwM#};@$6H1#+B_Jn~;|J&0YYbNC^G%w3dB%n3Js{kBx^ zv}Il{!OrY{IO$$vbHa6Vep{B+(f=9l7&lf>s*2L`3i&^WUklQ6mXJBymdA1`Ny|t*@BI2DI@67WlZ+bJwM{93TMUi5wtDNc%g)?)3=>fI}u zubM?#G@vqgP~iN{Z4h-D`3=FTy@oW2>{!k{+M@c)u4ez{BV)tZ>`6Gttd&E;XIU#W zDC8fWs!LS8v6pk(vz>7vsS7`W%lzRRL9CUUq)n?A7ZB4%&-+OF3qlPZ1;EIe81#Ea z)##7T|C=W%DXo2nb@ZMp@yb0Uzz^YsIK)%)Q9rgl^6BpN(X(>s=Vi_#4F|e$v|4Rz zVu)jtX^Ik3CRIW(E?vUpBL00m>)yvWs^?xa97nlxf@RhmVYY9NirkX@6@VoR6bYQb zqgR^yOlkjpzn?}u@}z*2jf`t~xu&yp$b9(W%++hb>@WP0a?(cs;4Eb{!J4Dt86NA` zQe%?n6fWK(xw?<&aQ)=Nbn)thgh!S<%HlVNdMoJtKx2?O`g$y9+TvI zH7N%)a*I!)3Vj<+bFe32d4oFVkp~HxC27^zd&Chl1X| zG`?%aVb(c6k=!b8qI|MUTih1A22?Y@={IuEV!GsFvxhDrKk$EQ2vKazQzY!L199p$V!poN|4KEn-?@%#se zX>FK2BQa>BC%D0{^ilueRT0_M!uI9WN3e3x#uk$ImYnQw|2(8nV@qIo>xDxz-T>As>Kt(9#FgZHS z;o!LAoGACE=abp4n~iwt`e!bG^P#XR(qc#YrFO!;nES(*iZ=BTU4I+Wx zo)_l2zVWST+2yyTRmQ_+3+>uijBe;#MYo7zBaTw6wgLP&0bykJ%0U_qgo1EL@`_QGXt$b=Y&?* z|Gh!4$fJJ;DcNuQ;eY+vl5owcYeSwjWX&=STva3aJaT4g=1rK#&j($t&+Hw<5@dm| z+pX~u2r0)5UactWWWFvgFD2j$ZdCBA9kO`8@Sj6llYgBkxNaF)7l-qk){u|C11QoW zXYnuSX$V7XkEuXIwzg0U$xuk@Jbp4*AW@SZ^KtiMoLX@?o4m8Bc{lUR`(ka9vd2F;NIjj;n z`s#hYsuqcLDljANkIPF^*TIi-vq)aX%lS zK&NbS#m>VooPK{5M~QxVKJ3$O^Mmxp7*n61RHb~eQ26G>+5fKg#b|NkJux1sG`Uy4 zS>};2e9Upra4@(gK4d2b^ zS?KIWiS4jrwQb({kJNoHj>7fGhxdksws1*+Lxj14K*iqsg5Qqkb6sIps1My;7En;+ z^Emh~oKihEFq__1IH6Of!Tnc7SdEiQWm&z5J`OE)#%$l_=}7<2ym!2+>p?4?M`H$M zq{fRN0P=iV%ExVAPL+NgCuCE;tG|EvY>a{0F-ha~=T-7kw^t9C%d}J<65bs6@!NWT zoPALfB{p^ZqpPnd)fwQ$P2I4U7oC2~n6aYS()qglm*_?nMu8<@SykLV$z4!}lc!fx8}%|pg$?ebaA zc9tpWNAl=C&W-hXzSJVhuw)c>91{Ti?GZvZ;p6iwKYAhV|5%3tx47o-nv;cA}>~xa-Ve)6Vbs z@4?@m14ZBVJMIuhh_z#XqP3W7Y6Q~xM-*-2ciTu$AjOsu%aQ9iW5z_mLB$c}y2>~W zosmUrB9~i!0)G}rQv*rVIPcAvW2nK6{R`#gsV^1PA$9AfW}Fqgm)dly(A7NK zjVm%e$q}~jJqS^6G`3_x)q3`FO2hJl`{Kd-ZIuX%#$KK}!Tr>V%; z&A&!fiZHVG*gf<8C;s|Htb|fj!qnK}f|%0SL_ihVWOphR695jg z#fdNt+5);C%4mx#OrJux54KAr_kWR+02u-@CxRV&-ID}GZj_dR?FxB4jw61;3>Nq} zAE$DJ7Y<)!OZCwNe3Cw`WAMyhxHAdR&YCjT41 z(X8gv=lZePC4;&@A88pQOqVnJevN@}Yl7`Q5-#RK3`zgea>^`^7q6U)Ztx;o9?7bt znx(BI;_~MT^D!ipPsb7Osu+&(x2efQa)t(U>Y4MTiZDq5ylX~b2RTf z^{bP&rjjPY2bD_pz%v?nZV#b&6kZcvuw|7n`oZ z?NLn(P^f&{%inyfF`o<14Rf}h9A7`wlakbQ!mStMiVa+31i^ZQylDJ3Kbz}D`=5~K zU#whH4$|fXd@Tu@E@zdesZnh-$=CibJR*ZK(E;sff@Ier562Cz?Hv2^@;$Uyagk#c zjM%zLj9;Bj^Q6mZH`rOGX-qNG*OPz776XTmGPD!+d;RdHf;s^WCMD=&8$ zfwU;smMM5jR4nDh-#bdkmOTf6q`xo4-8 zf0Qqa?*;qO_|8Djb*dQeN6*Hzq2z82--(4-a8;+Q0QUP8=(-n3|^C@F7HlY~P%spqC|$MN9J6B4YwLYiL?eTb5DwHes5pXH_z-B8NU^w(e6%NLF4jZN1R+S<6;kUPycr*pfOFq479k{mRF~! zxY=vRhfeR7f$R0zb-Yan_Ma$G*3YyDr}u6ve0nq&-qkkm_;F?@pe*$AmGozqKsqi^ z2~QYSsLz5D8ExbS1bn z(w7h&=!ehVu-(4BEg_vQ9B$}da$Dp6iT!}@8cw_@oGP2#b&zOgzh&iqZ!0y5-wY-` z{V%}ei89w16uEbP2?AS+s6FKG_Ag7?*yU+-6L!nwu%f%uhmv;~J)>za#s8%J{zH~d zAw9C`yysEqQRCV&qGoP{0j4C4mg=U8`$^3G8dpJ_3FRw__0uk_302F*++UsbSex-a z&ZJBLX(dBtJweoz$>Nv<{gupo2bQc~T!_pd48W-vZ)-~$tMA28?57k*kg2< zusJr%UjpMTk!(F|_ooY$P!1&a=(>UkJB(-)@2|d0?03Q{%FV@$Q7uwq#(0oe;Bdx8 zpRw$(sCJ(pUop`K93F}xolU*EFW2IS{L;R^xZN$hL0ue#bXULLrvi7wx*}ESupmXU zIz`*5?-ZDw0v+TIn??%Fr~UDV_1WVETFFR-?V`#|nV@*^sw6bvO_ZZ20_*wV591e# zhOO~Tm9X^zZg8sonkc)32md0EqKwtlhNn21ImZ0p(JpR7t^V&c14Ke-~b zVA+s(_v13Pf81`60ofd-<)@uI-1qRT%oNvUkF^an^(>`Z&$XPCQ&*w6J8Z`D>~!wy zny)tWu4{jKCUub68^5@xFn%xK??Gv40Dh+5p`y3-%son(nR-oQGyJ3Oe`n~xrE|GJ z0&nk(wMYgbfDtCP8@7*1foXn{YX5KgmE;Fe8}>v54MSYMn za;SQ1qZW2H(ny#4;1v7pOeH5R<=pl^yHPdkoz&(8=h)H9sVb?VrLx}8BczwPt!hKJ zO^#U-`$mB#RhU|0^YlksDMT4@BTd-VQv?_kH@jqXN-525ZzDL&GEL_^SSq9^;!oXa zR3xTS_-(&mXcsYm>bp*X*QAGT`M%Vd;(-|CW{-06w^a!3$o8&V znt1Qjy$82vH3}1Qi#6yoFSu4nofJq%3n@*U83L;WkL}S-M`P%9|GJS!Ec|a(rQkra zX+`|jWy|@w2K!wS@v;brh20qxYN_03AkdYlIAz(&sGgwUrnFe1MYJqEYCtK&lmruV zG1f1ZGrV{cH~x!qO&_8y{-anZj`ZzG`j3&$YT9uUhM(yS){@U5MwENr#QD`$EN-1e}qXSQxenW}?LmA1B=V%Kc6VNA@v%a!t0$=9c! zH_#i_6r7tk>U8SYPo|UB0{JX5f;2N(#aA{KRX8V60XId60=AkN%9c71{U^M^^VSs0 z5mv?|2+mmYy&7p*_3ozNr6XDR$?!N;n$&A4D!}-$nRv*!us~PgEk(2* zu6)!#iT8gi%?~adg3M7P^9p7;m^aHp$qn`n(k|HcylcME;vj1 zRpx?nIgQQH#)f7WOl7k8W4j|lX(|~fY%Ot;C+_(qD~pS}dnwK5FT17_nHGi=1O~$Fj{%T#? zxR`SxEVMaupohj$WRwMdiI$CGCz>bvbv>_?8c#VyQ_4dSy9;;nO+f2Y+8zDHgRSs> zeh?&U$HP~)lr_?>9|+x2@KVY=U}jOpgX}8tWJ2^HaerFGyC0G9p_NXQMd-&yDFXRTlaRgdl|BKLi!FA;Kf$Jd*x<)WjOyJwzECd^H3 zUDMa_{U>|(H+M}FP4CH*SX>28>1LM>W}@gcxw=Hnl2BAcHTg^X;m)<23knjA5jbQt z?k%@Hso0EK)$wk`m#0hW$Q9X|f@9&RJqu65cy>JTLs~IK415ZR;}>nhm-$sC%iT2*yljQbkp^-2E>Xvucyd= z=E)~aE+fD0AA9nS^%oq$(ES)p6#*ry zPvkP1P2~%4$KehK+$oIsBLu6l+sFtvewLRf_4$bcy(}hD+vwyCfl6-Z)JwxnxH7TU zhmE;a8z_yxnx3+!gI^4~R@*wnSZTg6i=4mq`F|nG)4h@MTDk2%`<&X7*0ns}_~crB zqUn4M0*4tDr%CeM0LixdUYT7QOHuK^)oEfgWoXPJGVUJkUUnu0P-^ad9@U+u8;Csr zvZ!aVoukn+i1rMlu^A7h?h zS^Ra$uQp0)X2tusJ;^Q>3)3ke$Cc|3Dr%)hmOo7I`4_YDiK~!qDhbRx(*;tU#hCy; znrUn=abT`1%d<(w?g%Z-&K5V_)a6-jqn3?JSx^moT`z;@=AO%s8kTyy6P}yar&&H7 zxLI_0IE{*HA((J?kUYSO@^fVt!CG~mwZz14D+f)RyvLAZ zOAq`be>X1F!6%~}&x^i+v|9sv`*CZdK%)K@zfXRaM03l5(3^-@0dR|OE0=(Tbs|z# zxT8xELJYDQT6QvO0dVW<=-GfpYdFu@P`Pyu2J%4Xhg1W7Ze(r=-J3DdZRo(Sm^QSl;c zN&saE74aWuV`SnAjr>vcCZsmKWyC^lZe3`Li-Bw3s6k7G8qzciAA;FMG-}7B>`IbL zUJmS11r_jjjGC|v6I+mt_Uw-1$b16p%_s>OHe0=eSQ!i1Z1&T;*O`cOqpT;3%BXE3 zXdVq0t|-}bsjJ`tZc+R!N}C<#AxM{)JlZKU<~pDIwPlJ$A=uIkbr1=B2){<{6}`~H zY@|Lq46mW$ce@d4AjIhvx1~u|FC>JT$24bEEr8CLqpRpMyz7?YukO4h`qMdGyU)2b zoX_!&HN+%WibKz9ZAGWwQmUkh$qF_>Eb4ILL*AW-5pe_0@qf7CR9E~qD zmXvK$**UNQtlk>f*G3aFvr#|(;!0~VUxCbvV>d3_ZzIcV95l9ON-M)G$m%A*r|TRQ zI@mVq_+bWn4bWM{pqcs}T5{xB$ZFWp*Y~pMjvA)*a}e z22z-YS0PNpd%is6S=-o9jxb@zn0R#*FUzsg(hd(9#*P_3sgIB_M^le0Etz++N?OOK zr$;W-3F!+Vk`rl3$TVc2rDbL~7!+ly?EV;6ZU&Jt4N3+#sq4qL{e&kVZ$h5^9)=ce z-u|Td{lZDctE$5kfN7)kvQds-f1TShnH))ENwh(LH7#X5w%#1yMPKK7ItQ1Kv#eq8-3O(lJ_Hg7^#Fmk2x}PimQ&Z7f^btl8Wc(^W z_>R~IW*>cj|2l8GM5RQ=B>=)J00Hcm#qc#e}|)aVoRAQrbLxJu0W0l`6K4?y#&Uyj+MhQ+QxMTM0 ziyglN#<@4dS47F`!>nz2>x5#H%%{TEWf`3o?UOB-v>VmZkQv^&%E>Ln01> z*sRFd@|?Y5l0A1pS4O=IX*Z=-TnZ!A5F=KkvAjI5=f@1bU0m?Y%jV*)r1*;1O7mIE zwCTa17TIVUhW$t?XP%0}kMpx18d2)xdq|mUPF_d9?lvW-wFu|onVVbTNw}nR%t#eS zny8v{P-1?^#cs1klV654VF@xN4q3>nNArz!v8LiL;EFqkeU?2J)Fb15MLN?{ynD0p zvQP6bUB9+pJk-knns=J9Y<@bFigjS-ozfYj6?pcD9CAMp?RHu*y*uFW5pZ+udR9fk zo!7JeyJP(b%`{niU6NiZ(!*L>0l%jx8j=et;&~{bNBjAcTzs75U#jN;J{+ukxqbQM zvA|wGSFrWPG$=X}T*oWm>n01X%)SohNA7vHuHDrf{?1=3*F&uSKO3eeoXB@sN7+8= z!>RMh%SyNnNpu2BEE`XiYSCR}ixSfePj`bYBeu?bo1%&yDIXlOUy%Z>{8z!`&8Vky zo5B&RkMP)KFqGZOtP3B|<4^&$;@^qhY{xXy4QT6c)8dCd3rUh;s)}B@Fnvc}lpM}C z2m*Zq>gMge@5?itO;cLp^3-x zWPPRde#2N%j+*j1FNiw6*j8>jZUMQ4D8Mi7IvnukTOkS^yYnuhfPH=|%fiEiW!q_C zcEQZDdIhB0M`4zcW=j7#)?_tfrKZJgVnNPH3i(djw%}~-R%D{+6~MZQhs0E zy_7y$5^P;(EKtZK5+VQK0|-D|;8UXo;yMzd1$>9}jn4hwlM#7nk1SWpvwxOwp(Q0Z zw_v_^>LXDbMs_?s=uInWRG6D;!Sv0XNnLpSp3FZt_(nM&<$6-IQgD=Nsr)-BFgs2l zHY`;~l`)#A6iJg^_L{}|n18YDn>IChdg0z_`uAVa$o-P>#YS9aAur4eaz#-saxRgT z&ITXn3BN{~?2%O-63#GUU5>nCQ`1g8uz?ay!~ra^7^!qBFH1^eYrTT!Fj-709o4Xfx3m+~3qLOOY+i?fb~h|;^9h2l)Is6UY>_#aZzVPVuP zNC;uFS2mOAb?^|SuyY6S+c^|FBX3&*a6GHdT4CVEy`F@$CKKJ&h(0$`j~Y4<_&>Tp z9coCD-f|r|x}$t)x4*um3BI@TFck(fFL==XU0u$=^)FZJ75mqgYlEHlz>W(IKItQi z-=(w9OX6Y< zd2VxPB3%PMVNS8}~Hmz5Fw*wh47 zy_(CB)(g)QU(t~Zs& z^t@sv($x}JnNUy3aN~xQK!a;UMvN0-=zvq`s`&b5Rd^@$06x7g(i(6l*tn}mcs+Gff z_{$0ses8#!C11=G&nowHQfj?2H;+3Pmr6wjC{bWTEGI|q4nmDQ?G7^BVbb3cUmSbG zdM!8W7_JSUpDkc|%6cwDrAiCGT*Yr=66%!x5Z)I~S$lWK1w>b+-N8G*PmTAt`b zup4)h7NPmo`dguCezu!;E7}L`717Y}|JKU%kc#O$@G|pho%CGVd+=Ns{?Ne8cGL41 zC`1%gpP)xWHLM{9@}TD+wUw7xtUt}|@vG9)?hib+ra?FTviIVYna@?tY2ua?MWst4 zS$w2SVGWs|w%M|@oy(8IITNDKTpW@S@EC~rE*_6}>3Gop-8{0gszr^Tg3U5J{mDFw zusBb_g%RFDYgwD)kg~kFG4YZA6_ZQA7Ap4z*?eTFF2mne>iDdDVrFCA+wgledbi#Z zUDwbIBRLj21*xy{l4ihovjV1%#`Bl&aVS%tzL{ONS?wQpf)=A+P9tD^;?p+lnkBac zx_R;JA8XHIR`I^vrusDeZaCc4nWxsun~50*K$!NGQNP7=U@u!W%ALG&az13tZXbKC zEQMpNZcsopWP;@4+E`D`(0 znM^C`(u*=J;$!6)t>yZ{S@_3DVPokT`enL+}Zd>G|!TOU#hq9^or}i&8Q@Ca` zj4%IxU<_Pw!u%YE*ZZ1ZC!g8c zF(CwltlIn9P=_QaAYirGltyCB3HQVG{>ME5XRaJU&SdtK>9Sf2xYa1lYZc{^SDJ;x zG9r%k8;L^`MrkHV6y)FC}%CnK~?RcPxir6lyN!&uNQKS=yqz|(2i7_rKh>wL-qlo&dcX;EUHUwoTKp+aWo z0V)$S+x#-A8uC$@;It#EUv6jwxVV#sXUbwj>djfL<~WvfU{eG80vCCCsrz??%xv&(Jbxd!D3`y|~C=HI-=57LjhnLx^|^ z!+-yoUk{Wp|6y^N?pf3KmDEbn8oziy^STw%H`6M%}eLzynp0AOjsXL^Q}9qfOi6 zd&Q9FgJSJ&SKMobSMKrpI=tS<9<_L43U$}0|0<}Ixn)sEj|}lTevKLIyL?e zE&lwlO93s*YR=%xf_(H2+IaGlpH)=HDpN;?CUhR(LN=4_x_*mY-HG`SBJE|*lWO)6 zX@RFewX(%+n^UL_Efr#M)0(KRynKw>xpAs%ZfD|Sy0ibYI4DR`NUis&ig~0l5xLsG z50YJ0|3 zT_Ghf^7PEcVjhQAuc~MgyR1&~T#hfC{+~7F*FUjN(#i!ujl}(-^ppemC-$gv#ex1YmTiZxsS9%A#9WxKU?_ z-A^wXBo;;o1u_KG%TNTz;F&6f_RA~y2vm)KDUw6fmqX-FV`;dr6bzl!YrzJ!FTan$ z;k&D^Uqv2-h>4a4JPNqFJ6lp+7Wtrm8Iy P%s@Wi#Hk@R5-qz@6n()|?u?Ttw^ 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

77a#bU36>-x(0>vWQ|E8u+ao^J$wR0^ttY)EX4 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ΝxXM0UHa-#PymPO81nGMb9}#szJ(#S+_^ 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

RqAWsT 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 Q`~UwJ{vZ1b5Pwho7Y!VDZvX%Q diff --git a/img/concurrent/executors-ali.png b/img/concurrent/executors-ali.png deleted file mode 100644 index a1a3858cd98389b292ba3e4c9af7d4eb0fcddc50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114331 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%0AGQw(g(|9)XoF^pP>{lEENb-w3G1GI09{A!6 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 P(QWU%ZHGO}*7xkMY|s)2 diff --git a/img/concurrent/synchronized-block.png b/img/concurrent/synchronized-block.png deleted file mode 100644 index 9c905bb9a6de18af73555a7176ae478466c8bf5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188866 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