diff --git a/README.md b/README.md index 6d043746..7a73df4f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ 本仓库是对 Java 的一些基础知识、数据库知识、以及框架知识进行收集、整理(持续更新中)。
-仓库对应 WebSite:https://duhouan.github.io/Java/#/ +仓库对应 WebSite:https://duhouan.github.io/Java/#
+如何流畅访问 Github -
+

- -| ☕️ Java | 👫 面向对象 | 📝 编程题 | 💾 数据库 | ☎️ 常用框架 | 📖 系统设计 | 💪 工具 | 📚 参考资料 | + +| ☕️ Java | 👫 面向对象 | 📝 编程题 | 💾 数据库 | 🎓 系统设计 | ☎️ 常用框架 | 📖 工具 | 📚 参考资料 | | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | -| Java | 面向对象 | 编程题 | 数据库 | 常用框架 | 系统设计 | 工具 | 参考资料 | +| Java | 面向对象 | 编程题 | 数据库 | 系统设计 | 常用框架 | 工具 | 参考资料 | diff --git "a/docs/1_\345\237\272\347\241\200.md" "b/docs/1_\345\237\272\347\241\200.md" new file mode 100644 index 00000000..406b2d57 --- /dev/null +++ "b/docs/1_\345\237\272\347\241\200.md" @@ -0,0 +1,99 @@ +# 系统设计基础 + +## 安全性 + +要求系统在应对各种攻击手段时能够有可靠的应对措施。 + +## 性能 + +### 性能指标 + +#### 响应时间 + +指某个请求从发出到接收到响应消耗的时间。 + +在对响应时间进行测试时,通常采用重复请求的方式,然后计算平均响应时间。 + +#### 吞吐量 + +指系统在单位时间内可以处理的请求数量,通常使用每秒的请求数来衡量。 + +#### 并发量 + +指系统能同时处理的并发用户请求数量。 + +在没有并发存在的系统中,请求被顺序执行,此时响应时间为吞吐量的倒数。例如系统支持的吞吐量为 100 req/s,那么平均响应时间应该为 0.01s。 + +目前的大型系统都支持多线程来处理并发请求,多线程能够提高吞吐量以及缩短响应时间,主要有两个原因: + +- 多 CPU +- IO 等待时间 + +使用 IO 多路复用等方式,系统在等待一个 IO 操作完成的这段时间内不需要被阻塞,可以去处理其它请求。通过将这个等待时间利用起来,使得 CPU 利用率大大提高。 + +并发用户数不是越高越好,因为如果并发用户数太高,系统来不及处理这么多的请求,会使得过多的请求需要等待,那么响应时间就会大大提高。 + +### 性能优化 + +#### 集群 + +将多台服务器组成集群,使用负载均衡将请求转发到集群中,避免单一服务器的负载压力过大导致性能降低。 + +#### 缓存 + +缓存能够提高性能的原因如下: + +- 缓存数据通常位于内存等介质中,这种介质对于读操作特别快; +- 缓存数据可以位于靠近用户的地理位置上; +- 可以将计算结果进行缓存,从而避免重复计算。 + +#### 异步 + +某些流程可以将操作转换为消息,将消息发送到**消息队列**之后立即返回,之后这个操作会被异步处理。 + + + +## 伸缩性 + +指不断向集群中添加服务器来缓解不断上升的用户并发访问压力和不断增长的数据存储需求。 + +### 伸缩性与性能 + +如果系统存在性能问题,那么单个用户的请求总是很慢的; + +如果系统存在伸缩性问题,那么单个用户的请求可能会很快,但是在并发数很高的情况下系统会很慢。 + +### 实现伸缩性 + +应用服务器只要不具有状态,那么就可以很容易地通过负载均衡器向集群中添加新的服务器。 + +关系型数据库的伸缩性通过 Sharding 来实现,将数据按一定的规则分布到不同的节点上,从而解决单台存储服务器的存储空间限制。 + +对于非关系型数据库,它们天生就是为海量数据而诞生,对伸缩性的支持特别好。 + +## 扩展性 + +指的是添加新功能时对现有系统的其它应用无影响,这就要求不同应用具备低耦合的特点。 + +实现可扩展主要有两种方式: + +- 使用消息队列进行解耦,应用之间通过消息传递进行通信; +- 使用分布式服务将业务和可复用的服务分离开来,业务使用分布式服务框架调用可复用的服务。新增的产品可以通过调用可复用的服务来实现业务逻辑,对其它产品没有影响。 + +## 可用性 + +### 冗余 + +保证高可用的主要手段是使用冗余,当某个服务器故障时就请求其它服务器。 + +应用服务器的冗余比较容易实现,只要保证应用服务器不具有状态,那么某个应用服务器故障时,负载均衡器将该应用服务器原先的用户请求转发到另一个应用服务器上,不会对用户有任何影响。 + +存储服务器的冗余需要使用主从复制来实现,当主服务器故障时,需要提升从服务器为主服务器,这个过程称为切换。 + +### 监控 + +对 CPU、内存、磁盘、网络等系统负载信息进行监控,当某个信息达到一定阈值时通知运维人员,从而在系统发生故障之前及时发现问题。 + +### 服务降级 + +服务降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。 \ No newline at end of file diff --git "a/docs/Kafka/1_\346\266\210\346\201\257\351\230\237\345\210\227.md" "b/docs/1_\346\266\210\346\201\257\351\230\237\345\210\227.md" similarity index 100% rename from "docs/Kafka/1_\346\266\210\346\201\257\351\230\237\345\210\227.md" rename to "docs/1_\346\266\210\346\201\257\351\230\237\345\210\227.md" diff --git "a/docs/AimForOffer/\346\225\260\346\215\256\347\273\223\346\236\204\347\233\270\345\205\263/2_\345\255\227\347\254\246\344\270\262.md" "b/docs/AimForOffer/\346\225\260\346\215\256\347\273\223\346\236\204\347\233\270\345\205\263/2_\345\255\227\347\254\246\344\270\262.md" index 97aef1ca..619b66af 100644 --- "a/docs/AimForOffer/\346\225\260\346\215\256\347\273\223\346\236\204\347\233\270\345\205\263/2_\345\255\227\347\254\246\344\270\262.md" +++ "b/docs/AimForOffer/\346\225\260\346\215\256\347\273\223\346\236\204\347\233\270\345\205\263/2_\345\255\227\347\254\246\344\270\262.md" @@ -384,4 +384,111 @@ private void reverse(char[] chs,int start,int end){ } ``` +## *10、实现 strStr() + +[实现 strStr()](https://leetcode-cn.com/problems/implement-strstr/) + +思路一:朴素模式匹配算法 + +最朴素的方法就是依次从待匹配串的每一个位置开始,逐一与模版串匹配, +因为最多检查 (n - m)个位置,所以方法的复杂度为 O(m*(n-1))。 + +
+ +```java +//haystack 是待匹配串 +//needle 是模板串 +public int strStr(String haystack, String needle) { + if(needle==null || needle.length()==0){ + return 0; + } + int i=0,j=0; + //k存储的是模板串在待匹配串的位置 + int k=i; + while(i +
-
+
- 思路: -
+
-
+
在第 i 行放上皇后,判断是否其他地方能够放皇后的情况: @@ -250,7 +250,7 @@ dia1[1] =true 就表示 [0,1]和[1,0] 位置不能放皇后。 对角线1总共有 (2*n-1) 条;m 与 i 、 j 的关系:m=i+j。 -
+
(3)对角线2:dai2[m]表示第 m 条对角线被2占用,如 dai2[0]=true 表示[0,3] 位置不能放皇后, @@ -258,7 +258,7 @@ dai2[2]=true 则表示 [0,2] 和 [1,3] 不能放皇后, 对角线2总共有(2*n-1)条;m 与 i、j 关系:m=i-j+n-1。 -
+
```java private List> res; @@ -416,7 +416,70 @@ private boolean putNum(char[][] board, int pos, [单词接龙](https://leetcode-cn.com/problems/word-ladder/description/) ```java +public int ladderLength(String beginWord, String endWord, List wordList) { + wordList.add(beginWord); + int N = wordList.size(); + int start = N - 1; + int end = 0; + while (end < N && !wordList.get(end).equals(endWord)) { + end++; + } + if (end == N) { + return 0; + } + List[] graphic = buildGraphic(wordList); + return getShortestPath(graphic, start, end); +} + +private List[] buildGraphic(List wordList) { + int N = wordList.size(); + List[] graphic = new List[N]; + for (int i = 0; i < N; i++) { + graphic[i] = new ArrayList<>(); + for (int j = 0; j < N; j++) { + if (isConnect(wordList.get(i), wordList.get(j))) { + graphic[i].add(j); + } + } + } + return graphic; +} +private boolean isConnect(String s1, String s2) { + int diffCnt = 0; + for (int i = 0; i < s1.length() && diffCnt <= 1; i++) { + if (s1.charAt(i) != s2.charAt(i)) { + diffCnt++; + } + } + return diffCnt == 1; +} + +private int getShortestPath(List[] graphic, int start, int end) { + Queue queue = new LinkedList<>(); + boolean[] marked = new boolean[graphic.length]; + queue.add(start); + marked[start] = true; + int path = 1; + while (!queue.isEmpty()) { + int size = queue.size(); + path++; + while (size-- > 0) { + int cur = queue.poll(); + for (int next : graphic[cur]) { + if (next == end) { + return path; + } + if (marked[next]) { + continue; + } + marked[next] = true; + queue.add(next); + } + } + } + return 0; +} ``` diff --git "a/docs/AimForOffer/\347\256\227\346\263\225\346\200\235\346\203\263\347\233\270\345\205\263/5_\346\216\222\345\210\227\347\273\204\345\220\210.md" "b/docs/AimForOffer/\347\256\227\346\263\225\346\200\235\346\203\263\347\233\270\345\205\263/5_\346\216\222\345\210\227\347\273\204\345\220\210.md" index f33b3989..f5fac2e4 100644 --- "a/docs/AimForOffer/\347\256\227\346\263\225\346\200\235\346\203\263\347\233\270\345\205\263/5_\346\216\222\345\210\227\347\273\204\345\220\210.md" +++ "b/docs/AimForOffer/\347\256\227\346\263\225\346\200\235\346\203\263\347\233\270\345\205\263/5_\346\216\222\345\210\227\347\273\204\345\220\210.md" @@ -4,7 +4,7 @@ [全排列](https://leetcode-cn.com/problems/permutations/) -
+
```java private List> res; diff --git "a/docs/DataBase/1_\346\225\260\346\215\256\345\272\223\347\263\273\347\273\237\345\216\237\347\220\206.md" "b/docs/DataBase/1_\346\225\260\346\215\256\345\272\223\347\263\273\347\273\237\345\216\237\347\220\206.md" index d34f747b..885bf913 100644 --- "a/docs/DataBase/1_\346\225\260\346\215\256\345\272\223\347\263\273\347\273\237\345\216\237\347\220\206.md" +++ "b/docs/DataBase/1_\346\225\260\346\215\256\345\272\223\347\263\273\347\273\237\345\216\237\347\220\206.md" @@ -38,25 +38,25 @@ T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。 -
+
### 脏读 T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。 -
+
### 不可重复读 T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。 -
+
### 幻影读 T1 读取某个**范围**的数据,T2 在这个**范围**内插入新的数据,T1 再次读取这个**范围**的数据,此时读取的结果和和第一次读取的结果不同。 -
+
## 事务隔离级别 diff --git "a/docs/DataBase/2_\345\205\263\347\263\273\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\220\206\350\256\272.md" "b/docs/DataBase/2_\345\205\263\347\263\273\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\220\206\350\256\272.md" index 3846303a..244398b2 100644 --- "a/docs/DataBase/2_\345\205\263\347\263\273\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\220\206\350\256\272.md" +++ "b/docs/DataBase/2_\345\205\263\347\263\273\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\220\206\350\256\272.md" @@ -34,7 +34,7 @@ 高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。 -
+
diff --git "a/docs/DataBase/3_\350\256\276\350\256\241\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223.md" "b/docs/DataBase/3_\350\256\276\350\256\241\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223.md" index c76e11ec..0309567f 100644 --- "a/docs/DataBase/3_\350\256\276\350\256\241\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223.md" +++ "b/docs/DataBase/3_\350\256\276\350\256\241\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223.md" @@ -2,7 +2,7 @@ 关系数据库管理系统(RDBMS)架构图如下: -
+
## 存储 diff --git "a/docs/DataBase/5_LeetCode_Database\351\242\230\350\247\243.md" "b/docs/DataBase/5_LeetCode_Database\351\242\230\350\247\243.md" index c3d52b50..0f3123f8 100644 --- "a/docs/DataBase/5_LeetCode_Database\351\242\230\350\247\243.md" +++ "b/docs/DataBase/5_LeetCode_Database\351\242\230\350\247\243.md" @@ -422,15 +422,15 @@ ON p.PersonId=a.PersonId; * 内连接:返回两张表的交集部分。 -
+
* 左连接: -
+
* 右连接: -
+
# *8、超过经理收入的员工(181) diff --git "a/docs/JVM/1_Java\345\206\205\345\255\230\345\214\272\345\237\237.md" "b/docs/JVM/1_Java\345\206\205\345\255\230\345\214\272\345\237\237.md" index ac756ed2..ae76568a 100644 --- "a/docs/JVM/1_Java\345\206\205\345\255\230\345\214\272\345\237\237.md" +++ "b/docs/JVM/1_Java\345\206\205\345\255\230\345\214\272\345\237\237.md" @@ -8,7 +8,7 @@ JDK 1.8 和之前的版本略有不同: - JDK 1.7 字符串常量池被从方法区中拿到了堆,运行时常量池剩下的内容还在方法区 - JDK1.8 HotSpot 虚拟机**移除了永久代**,采用**元空间(Metaspace)** 代替方法区,这时候**字符串常量池还在堆**,运行时常量池还在方法区,只不过方法区的实现从永久代变成了元空间。 -
+
## 程序计数器 @@ -28,7 +28,7 @@ JDK 1.8 和之前的版本略有不同: 每个 Java 方法在执行的同时会创建一个栈帧用于存储**局部变量表**、**操作数栈**、动态链接、方法出口信息等。 -
+
从方法调用直至执行完成的过程,就对应着**一个栈帧在 Java 虚拟机栈中入栈和出栈的过程**。Java 方法有两种返回方式: @@ -121,7 +121,7 @@ javap -verbose JVMTest - 执行 iload_2,将 2 位置元素(数值 3)push 进操作数栈 - 执行 ireturn,返回操作数栈栈顶元素 -
+
## 本地方法栈 @@ -157,11 +157,11 @@ JDK 7 版本及 JDK 7 版本之前,Hotspot 虚拟机的堆结构如下: - 老年代 (Old Generation) - 永久代 (Permanent Generation) -
+
JDK 8 版本之后 HotSpot 虚拟机的永久代被彻底移除了,取而代之是元空间,元空间使用的是直接内存。 -
+
## 堆和栈的关系 @@ -333,7 +333,7 @@ str1、str2 是从字符串常量池中获取的对象。 对于 str5,字符串常量池已有 "helloworld" 对象,str5 直接引用该对象。 -
+
所以,尽量避免多个字符串拼接,因为这样会重新创建新的对象。如果需要改变字符串的话,可以使用 StringBuilder 或者 StringBuffer。 @@ -353,7 +353,7 @@ str1、str2 是从字符串常量池中获取的对象。 - 实例数据 - 对齐填充 -
+
### 对象头 @@ -444,13 +444,13 @@ Java 对象的创建过程分为以下5步: 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是**对象的句柄地址**,而句柄中包含了对象实例数据与类型数据各自的具体地址信息 。 -
+
### 直接指针 如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是**对象的地址**。 -
+
这两种对象访问方式各有优势: diff --git "a/docs/JVM/2_\345\236\203\345\234\276\346\224\266\351\233\206.md" "b/docs/JVM/2_\345\236\203\345\234\276\346\224\266\351\233\206.md" index da881ac3..020c1779 100644 --- "a/docs/JVM/2_\345\236\203\345\234\276\346\224\266\351\233\206.md" +++ "b/docs/JVM/2_\345\236\203\345\234\276\346\224\266\351\233\206.md" @@ -40,7 +40,7 @@ public class Test { 以 GC Roots 为起始点进行搜索,可达的对象都是存活的,不可达的对象可被回收。 -
+
**Java 虚拟机使用可达性分析算法来判断对象是否可被回收**,GC Roots 一般包含以下几种: @@ -165,7 +165,7 @@ obj = null; ### “标记-清除” 算法 -
+
在标记阶段,从根集合进行扫描,会检查每个对象是否为活动对象,如果是活动对象,则程序会在对象头部打上标记。 @@ -180,7 +180,7 @@ obj = null; ### ”标记-整理“ 算法 -
+
标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。 @@ -190,7 +190,7 @@ obj = null; ### ”复制“ 算法 -
+
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。 @@ -275,7 +275,7 @@ SafePoint 的选择很重要,如果太少可能导致 GC 等待的时间太长 **现在标准:在最大吞吐量优先的情况下,降低停顿时间**。 -
+
@@ -285,7 +285,7 @@ SafePoint 的选择很重要,如果太少可能导致 GC 等待的时间太长 虽然我们对各个收集器进行比较,但并非要挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,我们能做的就是**根据具体应用场景选择适合自己的垃圾收集器**。 -
+
以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。 JDK 9 取消了对 Serial+CMS、 ParNew+Serial Old 这两个组合的支持。 @@ -295,7 +295,7 @@ ParNew+Serial Old 这两个组合的支持。 #### 1. Serial 收集器 -
+
Serial 翻译为串行,也就是说它以串行的方式执行。 @@ -307,7 +307,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 #### 2. ParNew 收集器 -
+
它是 Serial 收集器的多线程版本。 @@ -327,7 +327,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 #### 4. Serial Old 收集器 -
+
是 Serial 收集器的老年代版本,也是给 Client 场景下的虚拟机使用。如果用在 Server 场景下,它有两大用途: @@ -336,7 +336,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 #### 5. Parallel Old 收集器 -
+
是 Parallel Scavenge 收集器的老年代版本。 @@ -344,7 +344,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 #### 6. CMS 收集器 -
+
CMS(Concurrent Mark Sweep),Mark Sweep 指的是标记 - 清除算法。 @@ -371,7 +371,7 @@ G1(Garbage-First),它是一款面向服务端应用的垃圾收集器, 堆被分为新生代和老年代,其它收集器进行收集的范围都是整个新生代或者老年代,而 G1 可以直接对新生代和老年代一起回收。 -
+
G1 把堆划分成多个大小相等的独立区域(Region),新生代和老年代不再物理隔离。 @@ -379,7 +379,7 @@ G1 把堆划分成多个大小相等的独立区域(Region),新生代和 每个 Region 都有一个 Remembered Set,用来记录该 Region 对象的引用对象所在的 Region。通过使用 Remembered Set,在做可达性分析的时候就可以避免全堆扫描。 -
+
如果不计算维护 Remembered Set 的操作,G1 收集器的运作大致可划分为以下几个步骤: diff --git "a/docs/JVM/5_\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md" "b/docs/JVM/5_\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md" index a9fc6ad3..33dbf928 100644 --- "a/docs/JVM/5_\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md" +++ "b/docs/JVM/5_\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md" @@ -36,7 +36,7 @@ ClassFile { 通过分析 ClassFilee,得到 class 文件的组成:
- +
diff --git "a/docs/JVM/6_\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" "b/docs/JVM/6_\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" index 9b348480..210636ca 100644 --- "a/docs/JVM/6_\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" +++ "b/docs/JVM/6_\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" @@ -1,46 +1,3 @@ -# Java 文件执行过程 - -Java 文件经过编译后变成 .class 字节码文件,字节码文件通过**类加载器**被搬运到 JVM 中。 - -
- -
- -举例说明 Java 文件执行过程: - -```java -public class Person { - private String name; - - public Person(String name){ - this.name=name; - } - - public void sayHello(){ - System.out.println("Hello! My Name is: " + name); - } -} -``` - -```java -public class JVMTest { - public static void main(String[] args) { - Person p=new Person("Li Ming"); - p.sayHello(); - } -} -``` - -执行过程如下: - -- 首先编译 JVMTest.java 文件得到 JVMTest.class 文件,系统启动一个 JVM 进程,从 classpath 路径中找到 JVMTest.class 文件,将 JVMTest 的类信息加载到方法区中,这个过程称为 JVMTest 类的加载 -- 然后 JVM 执行 JVMTest 的 main 方法 -- main 方法中 `Person p=new Person("Li Ming")` JVM 需要创建一个 Person 对象,但是此时方法区中是没有 Person 类信息的,所以 JVM 需要加载 Person 类,将 Person 类的信息加载到方法区中 -- 加载完 Person 类,JVM 会在对堆中为该 Person 示例分配内存,然后调用构造函数初始化 Person 示例,并且该实例**持有指向方法区中的 Person 类的类型信息的引用** -- 接着执行 p.sayHello(),JVM 根据 p 的引用找到 Person 对象,然后根据该对象持有的引用定位到方法区中 Person 类类信息的**方法表**,获得 sayHello 方法的字节码地址。 - - - # 类的生命周期 从类被加载到虚拟机内存中开始,到释放内存总共有 7 个阶段:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using),卸载(Unloading)。 @@ -325,7 +282,7 @@ JDK 自带的 BootstrapClassLoader, ExtClassLoader 和 AppClassLoader 负责加 每一个类都有一个对应它的类加载器。系统中的 ClassLoader 在协同工作的时候会默认使用双亲委派模型(Parents Delegation Model)。该模型要求除了顶层的启动类加载器外,其它的类加载器都要有自己的父类加载器。这里的父子关系一般通过组合关系(Composition)来实现,而不是继承关系(Inheritance)。 -
+
### 1. 工作过程 diff --git "a/docs/JVM/7_Java\347\250\213\345\272\217\347\274\226\350\257\221\345\222\214\350\277\220\350\241\214\350\277\207\347\250\213.md" "b/docs/JVM/7_Java\347\250\213\345\272\217\347\274\226\350\257\221\345\222\214\350\277\220\350\241\214\350\277\207\347\250\213.md" new file mode 100644 index 00000000..6e207c69 --- /dev/null +++ "b/docs/JVM/7_Java\347\250\213\345\272\217\347\274\226\350\257\221\345\222\214\350\277\220\350\241\214\350\277\207\347\250\213.md" @@ -0,0 +1,84 @@ +# Java 程序编译和运行过程 + +Java程序从 \.java 文件创建到程序运行要经过两大过程: + +- \.java 文件由编译器编译成 \.class文件 +- 字节码由 JVM 解释运行 + +## 编译过程 + +.java 源文件会被 Java编译器进行编译为.class文件: + +- Java 编译一个类时,如果这个类所依赖的类还没有被编译,编译器会自动的先编译这个所依赖的类,然后引用。如果 Java 编译器在指定的目录下找不到该类所依赖的类的 \.class文件或者 \.java源文件,则会报 + "Cant found sysbol" 的异常错误。 +- 编译后的 \.class 文件主要分为两部分:常量池和方法表集合。 + 常量池记录的是代码出现过的(常量、类名、成员变量等)以及符号引用(类引用、方法引用,成员变量引用等); + 方法表集合则记录各个方法的字节码。 + + + +## 运行过程 + +JVM 并不是在运行时就会把所有使用到的类都加载到内存中,而是用到的时候,才加载进方法区,并且只加载一次。 +Java类运行的过程大概分为两个步骤: + +- 类加载 +- 执行类 + +举例说明 Java 程序运行过程: + +```java +public class Person { + private String name; + + public Person(String name){ + this.name=name; + } + + public void sayHello(){ + System.out.println("Hello! My Name is: " + name); + } +} +``` + +```java +public class JVMTest { + public static void main(String[] args) { + Person p=new Person("Li Ming"); + p.sayHello(); + } +} +``` + +### 1. 类加载 + +首先编译 JVMTest.java 文件得到 JVMTest.class 文件,系统启动一个 JVM 进程,从 classpath 路径中找到 JVMTest.class 文件,将 JVMTest 的类信息加载到方法区中,这个过程称为 JVMTest 类的加载。 + +(只有类信息在方法区中,才能创建对象,使用类中的成员变量) + +### 2. JVM 找 main() 方法入口 + +在 main() 方法 入口持有一个指向当前类 (JVMTest) 常量池的指针,常量池中的第一项是一个对 Person 对象的符号引用。 + +main 方法中 `Person p=new Person("Li Ming"),JVM 需要创建一个 Person 对象,但是此时方法区中是没有 Person 类信息的,所以 JVM 需要加载 Person 类,将 Person 类的信息加载到方法区中。 + +JVM 以一个直接指向方法区 Person 类的指针替换了常量池中第一项的符号引用。 + +### 3. 实例化对象 + +加载完 Person 类的信息以后,JVM 就会在堆中为一个 Person 实例分配内存,然后调用构造方法初始化 Person 实例,并且该实例**持有指向方法区中的 Person 类的类型信息(其中包括方法表)的引用**。 + +(p 为指向该 Person 实例的引用,会被放到栈中) + +### 4. 运行方法 + +执行 p.sayHello(),JVM 根据栈中 p 的引用找到 Person 对象,然后根据 Person 对象持有的引用定位到方法区中 Person 类类信息的**方法表**,获得 sayHello 方法的字节码地址,然后开始运行方法。 + +
+ +
+ + +# 补充 + +- [main() 方法详解](https://www.cnblogs.com/bingyimeiling/p/10409728.html) \ No newline at end of file diff --git "a/docs/JavaBasics/6_\345\217\215\345\260\204.md" "b/docs/JavaBasics/6_\345\217\215\345\260\204.md" index 19ee9863..ba3e78a5 100644 --- "a/docs/JavaBasics/6_\345\217\215\345\260\204.md" +++ "b/docs/JavaBasics/6_\345\217\215\345\260\204.md" @@ -6,7 +6,7 @@ Java 异常是一个描述在代码段中**发生异常的对象**,当发生 ## 异常继承体系 -
+
Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**。 @@ -18,7 +18,7 @@ Java 异常分为两种: - 受检异常:**除了 RuntimeException 及其子类以外,其他的 Exception 类及其子类都属于这种异常**。 - 非受检异常:包括 RuntimeException 及其子类和 Error。 -
+
注意:非受检查异常为编译器不要求强制处理的异常,受检异常则是编译器要求必须处置的异常。 @@ -109,7 +109,7 @@ Java规定:一个方法必须捕捉,或者声明抛出方法之外。 ## try-catch-finally语句块的执行 -

+

(1) try 块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。 diff --git "a/docs/JavaContainer/1_\345\256\271\345\231\250\346\246\202\350\247\210.md" "b/docs/JavaContainer/1_\345\256\271\345\231\250\346\246\202\350\247\210.md" index 9ea4babc..26515fb0 100644 --- "a/docs/JavaContainer/1_\345\256\271\345\231\250\346\246\202\350\247\210.md" +++ "b/docs/JavaContainer/1_\345\256\271\345\231\250\346\246\202\350\247\210.md" @@ -6,7 +6,7 @@ Collection 集合体系图: -
+
### 1. Set @@ -37,7 +37,7 @@ Collection 集合体系图: Map 集合体系图: -
+
- TreeMap:基于红黑树实现。 diff --git "a/docs/JavaContainer/2_\345\256\271\345\231\250\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/docs/JavaContainer/2_\345\256\271\345\231\250\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" index dd0797c5..f795cada 100644 --- "a/docs/JavaContainer/2_\345\256\271\345\231\250\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/docs/JavaContainer/2_\345\256\271\345\231\250\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -2,7 +2,7 @@ ## 迭代器模式 -

+

Collection 继承了 Iterable 接口,其中的 iterator() 方法能够产生一个 Iterator 对象,通过这个对象就可以迭代遍历 Collection 中的元素。 diff --git "a/docs/JavaContainer/3_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - List.md" "b/docs/JavaContainer/3_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - List.md" index 807c4aa1..161d764e 100644 --- "a/docs/JavaContainer/3_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - List.md" +++ "b/docs/JavaContainer/3_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - List.md" @@ -248,7 +248,7 @@ transient Node first; transient Node last; ``` -
+
### 2. 添加元素 将元素添加到链表尾部: diff --git "a/docs/JavaContainer/4_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - Map.md" "b/docs/JavaContainer/4_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - Map.md" index 33ae11e2..595262cc 100644 --- "a/docs/JavaContainer/4_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - Map.md" +++ "b/docs/JavaContainer/4_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - Map.md" @@ -18,7 +18,7 @@ Entry 存储着键值对。它包含了四个字段,从 next 字段我们可 即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用**拉链法**来解决冲突, 同一个链表中存放哈希值相同的 Entry。 -

+

```java static class Entry implements Map.Entry { @@ -98,7 +98,7 @@ map.put("K3", "V3"); - 计算键值对所在的桶; - 在链表上顺序查找,时间复杂度显然和链表的长度成正比。 -

+

### 3. put 操作 diff --git "a/docs/JavaContainer/5_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - \345\271\266\345\217\221\345\256\271\345\231\250.md" "b/docs/JavaContainer/5_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - \345\271\266\345\217\221\345\256\271\345\231\250.md" index 95408bf7..98396c27 100644 --- "a/docs/JavaContainer/5_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - \345\271\266\345\217\221\345\256\271\345\231\250.md" +++ "b/docs/JavaContainer/5_\345\256\271\345\231\250\346\272\220\347\240\201\345\210\206\346\236\220 - \345\271\266\345\217\221\345\256\271\345\231\250.md" @@ -103,7 +103,7 @@ final Segment[] segments; static final int DEFAULT_CONCURRENCY_LEVEL = 16; ``` -
+
### 2. size 操作 diff --git "a/docs/JavaIO/3_\345\255\227\350\212\202\346\223\215\344\275\234.md" "b/docs/JavaIO/3_\345\255\227\350\212\202\346\223\215\344\275\234.md" index 9ca0b8b5..c0c9cc63 100644 --- "a/docs/JavaIO/3_\345\255\227\350\212\202\346\223\215\344\275\234.md" +++ "b/docs/JavaIO/3_\345\255\227\350\212\202\346\223\215\344\275\234.md" @@ -309,7 +309,7 @@ Java I/O 使用了装饰者模式来实现。以 InputStream 为例, - FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作; - FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。 -

+

实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。 diff --git "a/docs/JavaIO/6_\347\275\221\347\273\234\346\223\215\344\275\234.md" "b/docs/JavaIO/6_\347\275\221\347\273\234\346\223\215\344\275\234.md" index e9edb409..eaa5928e 100644 --- "a/docs/JavaIO/6_\347\275\221\347\273\234\346\223\215\344\275\234.md" +++ "b/docs/JavaIO/6_\347\275\221\347\273\234\346\223\215\344\275\234.md" @@ -67,7 +67,7 @@ public static void main(String[] args) throws IOException { - Socket:客户端类 - 服务器和客户端通过 InputStream 和 OutputStream 进行输入输出。 -
+
## Datagram diff --git a/docs/JavaIO/7_NIO.md b/docs/JavaIO/7_NIO.md index a265619a..537fe3a5 100644 --- a/docs/JavaIO/7_NIO.md +++ b/docs/JavaIO/7_NIO.md @@ -65,23 +65,23 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重 ① 新建一个大小为 8 个字节的缓冲区,此时 position 为 0,而 limit = capacity = 8。capacity 变量不会改变,下面的讨论会忽略它。 -

+

② 从输入通道中读取 5 个字节数据写入缓冲区中,此时 position 为 5,limit 保持不变。 -

+

③ 在将缓冲区的数据写到输出通道之前,需要先调用 flip() 方法,这个方法将 limit 设置为当前 position,并将 position 设置为 0。 -

+

④ 从缓冲区中取 4 个字节到输出缓冲中,此时 position 设为 4。 -

+

⑤ 最后需要调用 clear() 方法来清空缓冲区,此时 position 和 limit 都被设置为最初位置。 -

+

## 文件 NIO 实例 ### FileChannel的使用 @@ -427,7 +427,7 @@ NIO 实现了 IO 多路复用中的 **Reactor 模型**,一个线程 Thread 使 应该注意的是,只有套接字 Channel 才能配置为非阻塞,而 FileChannel 不能, 为 FileChannel 配置非阻塞也没有意义。 -

+

使用Selector的优点: diff --git "a/docs/Java_Concurrency/1_\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/Java_Concurrency/1_\345\237\272\347\241\200\347\237\245\350\257\206.md" index 4b612ec2..4850e65d 100644 --- "a/docs/Java_Concurrency/1_\345\237\272\347\241\200\347\237\245\350\257\206.md" +++ "b/docs/Java_Concurrency/1_\345\237\272\347\241\200\347\237\245\350\257\206.md" @@ -77,7 +77,7 @@ Java 程序是多线程程序,这是因为 JVM 启动至少了主线程和垃 单就一个 CPU 而言两个线程可以解决线程阻塞造成的不流畅问题,其本身运行效率并没有提高, 多 CPU 的并行运算才真正解决了运行效率问题,这也正是并发和并行的区别。 -
+
@@ -513,7 +513,7 @@ yield() 和 wait() 的区别: 线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换: -
+
diff --git "a/docs/Java_Concurrency/2_\345\271\266\345\217\221\347\220\206\350\256\272.md" "b/docs/Java_Concurrency/2_\345\271\266\345\217\221\347\220\206\350\256\272.md" index dca44b13..e354e7ad 100644 --- "a/docs/Java_Concurrency/2_\345\271\266\345\217\221\347\220\206\350\256\272.md" +++ "b/docs/Java_Concurrency/2_\345\271\266\345\217\221\347\220\206\350\256\272.md" @@ -14,7 +14,7 @@ Java 内存模型(即 Java Memory Model,简称 JMM)试图屏蔽各种硬 当 CPU 需要将结果写回到主存中去时,它会将内部寄存器的值刷新到缓存中,然后在某个时间点将值刷新回主存。 -
+
加入 CPU 缓存带来了一些新的问题: @@ -27,13 +27,13 @@ JMM 规定线程之间的共享变量存放在主内存(主内存就是硬件 **线程只能直接操作工作内存中的变量,不同线程之间的变量值传递需要通过主内存来完成**。 -
+
### 主内存和工作内存的交互 JMM 定义了 8 个操作来完成主内存和工作内存的交互操作。 -
+
- lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。 - unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。 diff --git "a/docs/Java_Concurrency/3_\345\271\266\345\217\221\345\205\263\351\224\256\345\255\227.md" "b/docs/Java_Concurrency/3_\345\271\266\345\217\221\345\205\263\351\224\256\345\255\227.md" index b2535bd6..b5f51931 100644 --- "a/docs/Java_Concurrency/3_\345\271\266\345\217\221\345\205\263\351\224\256\345\255\227.md" +++ "b/docs/Java_Concurrency/3_\345\271\266\345\217\221\345\205\263\351\224\256\345\255\227.md" @@ -139,7 +139,7 @@ public class SynchronizedDemo { } ``` -
+
任意一个对象都拥有自己的 Monitor,当这个对象由同步块或者同步方法调用时, 执行方法的线程必须先获取该对象的 Monitor 才能进入同步块和同步方法, 如果没有获取到 Monitor 的线程将会被阻塞在同步块和同步方法的入口处,进入到 BLOCKED 状态。 diff --git "a/docs/Java_Concurrency/6_\345\271\266\345\217\221\345\256\271\345\231\250.md" "b/docs/Java_Concurrency/6_\345\271\266\345\217\221\345\256\271\345\231\250.md" index 8372a11d..910c97a6 100644 --- "a/docs/Java_Concurrency/6_\345\271\266\345\217\221\345\256\271\345\231\250.md" +++ "b/docs/Java_Concurrency/6_\345\271\266\345\217\221\345\256\271\345\231\250.md" @@ -113,7 +113,7 @@ final Segment[] segments; static final int DEFAULT_CONCURRENCY_LEVEL = 16; ``` -
+
### 2. size 操作 diff --git "a/docs/Java_Concurrency/7_\345\271\266\345\217\221\345\267\245\345\205\267.md" "b/docs/Java_Concurrency/7_\345\271\266\345\217\221\345\267\245\345\205\267.md" index 9ff22a05..35812b70 100644 --- "a/docs/Java_Concurrency/7_\345\271\266\345\217\221\345\267\245\345\205\267.md" +++ "b/docs/Java_Concurrency/7_\345\271\266\345\217\221\345\267\245\345\205\267.md" @@ -113,7 +113,7 @@ final Segment[] segments; static final int DEFAULT_CONCURRENCY_LEVEL = 16; ``` -
+
### 2. size 操作 @@ -258,7 +258,7 @@ java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J. 维护了一个计数器 cnt,每次调用 countDown() 方法会让计数器的值减 1,减到 0 的时候,那些因为调用 await() 方法而在等待的线程就会被唤醒。 -
+
```java public class CountdownLatchExample { @@ -307,7 +307,7 @@ public CyclicBarrier(int parties) { } ``` -
+
```java public class CyclicBarrierExample { diff --git "a/docs/Java_Concurrency/8_\347\272\277\347\250\213\346\261\240.md" "b/docs/Java_Concurrency/8_\347\272\277\347\250\213\346\261\240.md" index ecdbd567..3dc260da 100644 --- "a/docs/Java_Concurrency/8_\347\272\277\347\250\213\346\261\240.md" +++ "b/docs/Java_Concurrency/8_\347\272\277\347\250\213\346\261\240.md" @@ -6,7 +6,7 @@ Executor 框架是在 Java5 中引入的,**通过该框架来控制线程的 Executor 基于**生产者-消费者模式**,**提交任务的线程相当于生产者,执行任务的线程相当于消费者**。同时,Executor 的实现还提供了对任务执行的生命周期管理的支持。 -
+
- Executor @@ -48,7 +48,7 @@ Eexcutor 框架由 3 大部分组成: 异步任务需要返回结果,提交任务后需要返回 Future, FutureTask 实现。 -
+
运行过程: @@ -190,7 +190,7 @@ private static ExecutorService executor = 状态转换图: -![img](https://gitee.com/duhouan/ImagePro/raw/master/pics/concurrent/c_22.png) +![img](https://github.com/DuHouAn/ImagePro/raw/master/pics/concurrent/c_22.png) shutdown() 和 shutdownNow() 这两个方法的原理都是**遍历线程池中所有的线程,然后依次中断线程**。 shutdown() 和 shutdownNow() 还是有不一样的地方: diff --git "a/docs/Java_Concurrency/9_\345\271\266\345\217\221\345\256\236\350\267\265.md" "b/docs/Java_Concurrency/9_\345\271\266\345\217\221\345\256\236\350\267\265.md" index 24738af6..3707d113 100644 --- "a/docs/Java_Concurrency/9_\345\271\266\345\217\221\345\256\236\350\267\265.md" +++ "b/docs/Java_Concurrency/9_\345\271\266\345\217\221\345\256\236\350\267\265.md" @@ -6,7 +6,7 @@ 假设线程 A 持有资源 1,线程 B 持有资源 2,它们同时都想申请对方的资源,那么这两个线程就会互相等待而进入死锁状态。 -
+
使用 Java 代码模拟上述死锁场景: @@ -533,7 +533,7 @@ public class ThreadLocalExample1 { 其对应的底层结构图为: -
+
由上图可以看出,ThreadLocal 从理论上讲并不是用来解决多线程并发问题的,因为根本不存在多线程竞争。 diff --git a/docs/Kafka&RabbitMQ/Kafka.md b/docs/Kafka&RabbitMQ/Kafka.md new file mode 100644 index 00000000..9d38cbb8 --- /dev/null +++ b/docs/Kafka&RabbitMQ/Kafka.md @@ -0,0 +1,331 @@ +# 一、Kafka 的相关概念 + +Kafka 是一种高吞吐、分布式、基于**发布订阅模型**的消息系统。Kafka 用于离线和在线消息的消费。主要有以下 3 个功能: + +- 消息队列:发布和订阅消息流 +- 容错的持久化方式存储记录消息流:Kafka 将消息数据按顺序保存在磁盘上,并在集群内以副本的形式存储以防止数据丢失 +- 流式处理平台:在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。 + +此外,Kafka 依赖 Zookeeper 进行集群的管理。 + +## Message + +消息(Message)是 Kafka 中**最基本的数据单元**。Kafka 消息由一个**定长的 Header 和变长的字节数组**组成。 + +## Broker + +Kafka 集群包含一个或多个服务器,这些服务器就被称为 Broker。 + +## Topic + +Kafka 根据主题(Topic)对消息进行归类,**发布到 Kafka 集群的每条消息(Message)都需要指定一个 Topic**。 + +## Partition + +Partition 即分区,每个 Topic 包含一个或多个分区。 + +消息发送时都被发送到一个 Topic 中,其本质就是一个目录,而 Topic 由是由一些 Partition Logs(分区日志)组成,其组织结构如下: + +
+ +**每个 Partition 中的消息都是有序的**,生产的消息被不断追加到 Partition Log 上,其中的每一个消息都被赋予了一个唯一的 offset 值,Kafka 通过 **offset 保证消息在分区内的顺序**,offset 的顺序性不跨分区,即 Kafka 只保证在同一个分区内的消息是有序的;同一 Topic 的多个分区内的消息,Kafka 并不保证其顺序性。 + +**Kafka 集群会保存所有的消息,不管消息有没有被消费**;可以设定消息的过期时间,只有过期的数据才会被自动清除以释放磁盘空间。比如设置消息过期时间为 2 天,那么这 2 天内的所有消息都会被保存到集群中,数据只有超过了 2 天才会被清除。 + +Kafka 需要维持的元数据只有一个,即消费消息在 Partition 中的 offset 值,Consumer 每消费一个消息,offset就会 +1。其实消息的状态完全是由 Consumer 控制的,**Consumer 可以跟踪和重设这个 offset 值,Consumer 就可以读取任意位置的消息**。 + +把消息日志以 Partition 的形式存放有多重考虑: + +- 第一,方便在集群中扩展,每个 Partition 可以通过调整以适应它所在的机器,而一个 Topic 又可以由多个Partition 组成,因此整个集群就可以适应任意大小的数据了; +- 第二,可以提高并发,因为是**以 Partition 为单位进行读写**,Partition 的个数对应了消费者个生产者的并发度,比如 Partition 的个数为 3,则集群中最多同时有 3 个线程的消费者并发处理数据。 + +注意:Partition 并不是越多越好的(Partition 的个数不能超过 Broker 结点),原因如下: + +- 分区越多,服务端和客户端需要使用的**内存**就越多。 +- 会降低一定的可用性。某个 Leader 挂了,相比较较少分区的情况,重新选出 Leader,花的时间就会更长。 + +## Replication + +Kafka 中每个 Partition 可以有多个副本(Replication),每个副本中包含的消息是一样的。 + +每个分区的副本集合中,都会选举出一个副本作为 Leader 副本,Kafka 在不同的场景下会采用不同的选举策略。**所有的读写请求都由选举出的 Leader 副本处理**,**Follower 副本仅仅是从 Leader 副本处把数据拉取(pull)到本地之后,同步更新到自己的 Log 中**。 + +一般情况下,同一分区的多个副本会被分配到不同的 Broker上。当 Leader 所在的 Broker 宕机之后,可以重新选举新的 Leader,继续对外提供服务。 + +
+ +## Producer + +消息生产者(Producer),向 Broker 发送消息的客户端。 + +**Producer 直接发送消息到 Broker上的 Leader Partition**,不需要经过任何中介或其他路由转发。 + +**Producer 客户端自己控制着消息被推送(push)到哪些 Partition**。Kafka 提供了接口供用户实现自定义的 Partition,用户可以为每个消息指定一个 Partition Key,通过这个 Key 来实现一些 Hash 分区算法。比如,把 userid 作为 Partition Key 的话,相同 userid 的消息将会被推送到同一个 Partition。**Producer 可以通过随机或者 Hash 等方式将消息平均发送到多个 Partition 上以实现负载均衡**。 + +### 批量发送消息 + +批量发送消息是提高吞吐量的重要方式。Kafka Producer 可以将消息在内存中累计到一定数量后作为一个**批量发送请求**。批量发送的数量大小可以通过Producer 的参数控制,参数值可以设置为累计的消息的数量(如 500 条)、累计的时间间隔(如 100ms )或者累计的数据大小(64 KB)。通过增加 Batch 的大小,可以减少网络请求和磁盘 I / O 的次数,当然具体参数设置需要在**效率**和**时效性**方面做一个权衡。 + +### 压缩消息 + +Producer 端可通过 gzip 或者 snappy 格式对消息集合进行压缩。消息在 Producer 端进行压缩,在 Consumer 端进行解压。压缩的好处是减少网络传输的数据量,减轻对网络带宽传输的压力。 + +### 异步并行发送消息 + +Producer 可以**异步地并行地**向 Kafka发送消息,但是通常 Producer 在发送完消息之后会得到一个 future 响应,返回的是 offset 值或者发送过程中遇到的错误。通过 request.required.acks 参数来设置 Leader Partition 收到确认的副本个数。ack 参数的具体说明如下: + +| ack | 说明 | +| :--: | :----------------------------------------------------------: | +| 0 | Producer **不会等待 Broker 的响应**
Producer 无法知道消息是否发送成功, 这样**可能会导致数据丢失**,但会得到最大的系统吞吐量。 | +| 1 | Producer 会在 **Leader Partition** 收到消息时得到 Broker 的一个确认
这样会有更好的可靠性,因为客户端会等待直到 Broker 确认收到消息。 | +| -1 | Producer 会在**所有备份的 Partition** 收到消息时得到 Broker 的确认
这个设置可以得到最高的可靠性保证。 | + +发布消息时,Kafka Client 先构造一条消息,将消息加入到消息集 set 中(Kafka支持批量发布,可以往消息集合中添加多条消息,一次行发布),send 消息时,Producer Client 需指定消息所属的 Topic。 + +## Consumer + +消息消费者(Consumer),从 Broker 读取消息的客户端。 + +消费者(Consumer)的主要工作是从 Topic 中拉取消息,并对消息进行消费。某个消费者消费到 Partition 的哪个位置(offset)的相关信息,是 Consumer 自己维护的。Consumer 可以自己决定如何读取 Kafka 中的数据。比如,Consumer 可以通过重设 offset 值来重新消费已消费过的数据。不管有没有被消费,Kafka 会保存数据一段时间,这个时间周期是可配置的,只有到了过期时间,Kafka 才会删除这些数据。 + +这样设计非常巧妙,**避免了 Kafka Server 端维护消费者消费位置的开销**,尤其是在消费数量较多的情况下。另一方面,如果是由 Kafka Server 端管理每个 Consumer 消费状态,一旦 Kafka Server 端出现延时或是消费状态丢失,将会影响大量的 Consumer。另一方面,这一设计也提高了 Consumer 的灵活性,Consumer 可以按照自己需要的顺序和模式拉取消息进行消费。例如:Consumer 可以通过修改其消费的位置实现针对某些特殊 key 的消息进行反复消费,或是跳过某些消息的需求。 + +Kafka 提供了两套 Consumer Api,分为 Simple Api 和 High-Level Api。 + +- Simple Api 是一个底层的 API,它维持了一个和单一 Broker 的连接,并且这个 API 是完全无状态的,每次请求都需要指定 offset 值,因此,这套 API 也是最灵活的。 + +- High-Level API 封装了对集群中一系列 Broker 的访问,可以透明的消费一个 Topic。它自己维持了已消费消息的状态,即每次消费的都是下一个消息。 + + High-Level API 还支持以组的形式消费 Topic,如果 Consumers 有同一个组名,那么 Kafka 就相当于一个队列消息服务,而各个 Consumer 均衡地消费相应 Partition 中的数据。若 Consumers 有不同的组名,那么此时 Kafka 就相当于一个广播服务,会把 Topic 中的所有消息广播到每个 Consumer。 + +
+ +## Consumer Group + +Consumer Group 即消费者组,多个 Consumer 可以组成一个 Consumer Group,一个 Consumer 只能属于一个 Consumer Group。**同一 Consumer Group 中的多个 Consumer 不能同时消费同一个 Partition 上的数据。**如果不同 Consumer Group 订阅了同一 Topic,Consumer Group 彼此之间不会干扰。这样,如果要实现一个消息可以被多个消费者同时消费(“广播”)的效果,则将每个消费者放入单独的一个 Consumer Group;如果要实现一个消息只被一个消费者消费(“独占”)的效果,则将所有的 Consumer 放入一个 Consumer Group 中。 + +注意:Consumer Group 中消费者的数量并不是越多越好,当其中消费者数量超过分区的数量时,会导致有消费者分配不到分区,从而造成消费者的浪费。 + +Producer、Consumer 和 Consumer Group 之间的关系如下图: + +
+ + + +# 二、Kafka 与 Zookeeper 关系 + +Zookeeper 为 Kafka 提供集群的管理。不仅保存着集群的 Broker、Topic、Partition 等元数据,还负责 Broker 故障发现、Leader 选举、负载均衡等。 + +- Broker 元数据管理 + + 在 Zookeeper 上会有一个专门**用来进行 Broker 服务器列表记录**的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到 `/brokers/ids` 下创建属于自己的节点,每个 Broker 会将自己的 IP 地址和端口等信息记录到该节点中去。 + +- Topic 元数据管理 + + 在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上,这些分区信息及与 Broker 的对应关系由 Zookeeper 维护。比如 my-topic 的 Topic 有 2 个分区,对应到 Zookeeper 中会创建这些文件夹:`/brokers/topics/my-topic/Partitions/0`、`/brokers/topics/my-topic/Partitions/1` + +- 负载均衡 + + 对于同一个 Topic 的不同 Partition,Kafka 会将这些 Partition 分布到不同的 Broker 服务器上,生产者产生消息后也会尽量投递到不同 Broker 的 Partition 中,当 Consumer 消费的时候,Zookeeper 可以根据当前的 Partition 数量以及 Consumer 数量来实现动态负载均衡。 + +# 三、Kafka 集群 + +## 典型拓扑结构 + +
+ +Kafka 集群包含若干个 Producer,若干个 Broker (Kafka 集群支持水平扩展,一般 Broker 数量越多,整个 Kafka 集群的吞吐量也就越高),若干个 Consumer Group,以及一个 Zookeeper 集群。 + +Kafka 通过 Zookeeper 管理集群配置。 + +Producer 使用 Push 模式将消息发布到 Broker 上,Consumer 使用 Pull 模式从 Broker 上订阅并消费消息。 + +## Kafka 数据流 + +
+ +Producers 往 Brokers 中指定的 Topic Push 消息,Consumers 从 Brokers 里面 Pull 指定 Topic 的消息,然后进行业务处理。 + +图中有两个 Topic,并且每个 Partition 上色数据在其他 Broker 服务器上都有一份副本: + +- Topic-0 有两个 Partition,Partition-0 和 Partition-1; +- Topic-1 有一个 Partition。 + +可以看到 Consumer-Group-1 中的 Consumer-2 没有分到 Partition 处理,这是有可能出现的。 + +# 四、Kafka 的数据存储设计 + +## Segment 数据文件 + +Partition 在物理上由多个 Segment 数据文件组成,每个 Segment 数据文件大小相等、按顺序读写。每个 Segment 数据文件的第一个文件名从 0 开始,后续每个 Segment 文件名为上一个全局 Partition 的最大offset,文件扩展名为 .log。在查找指定 Offset 的 Message 中,用二分查找就可以定位到该 Message 在哪个 Segment 数据文件中。 + +Segment 数据文件会首先被存储在内存中,当 Segment 上的消息条数达到配置值或消息发布时间超过阈值时,Segment 上的消息会被 flush 到磁盘,只有 flush 到磁盘上的消息才能被 Consumer 消费,Segment 达到一定的大小(默认是 1 GB,可配置)后将不会再往该 Segment写数据,Broker 会创建新的 Segment。 + +## Segment 索引文件 + +Kafka 为每个 Segment 数据文件都建立了索引文件,索引文件的文件名与数据文件的文件名一致,不同的是索引文件的扩展名为 .index。比如: + +
+ +Segment 索引文件索引文件并不会为数据文件中的每条 Message 都建立索引,而是采用系数索引的方式,每个一定字节建立一条索引。这样可有效降低索引文件大小,方便将索引文件加载到内存中,提高集群的吞吐量。 + +如下图所示,000000000000036869.index 文件中记录了 (3,497) ,在数据文件中表示第 3 个 Message(在全局Partition 表示第 368772 个 Message),该 Message 的物理偏移地址为 497。 + +
+ +## Partition 中通过 Offset 查找 Message + +比如读取 Offset=368776 的 Message,需要通过下面 2 个步骤进行查找: + +- 查找 Segment 文件 + + 其中00000000000000000000.index 表示最开始的文件,起始 Offset=0。第二个文件 00000000000000368769.index 文件的起始偏移量为 368770 (368769 + 1)。同样,第三个文件00000000000000737337.index 文件的起始偏移量为 737338 (737337 + 1) ,其他后续文件依次类推,以起始偏移量命名并排序这些文件,根据 Offset **二分查找**文件列表,快速定位到 00000000000000368769.index 文件。 + +- 通过 Segment 文件查找 Message + + 当 Offset=368776 时,依次定位到 00000000000000368769.index 的元数据物理位置和 00000000000000368769.log 的物理偏移地址,然后再通过 00000000000000368769.log 顺序查找直到 Offset=368776为止。 + +# 五、Kafka 的高可用原理 + +Kafka 集群由若干个 Broker 组成,Topic 由若干个 Partition 组成,每个 Partition 可存在不同的 Broker 上。可以这样说,一个 Topic 的数据,分散在多个机器上,即每个机器上都存放一部分数据。 + +## Kafka 0.8 以前 + +Kafka 0.8 以前是没有高可用机制的。 + +假设一个 Topic,由 3 个 Partiton 组成。3 个 Partition 在不同机器上,如果其中某一台机器宕掉了,则 Topic 的部分数据就丢失了。 + +## Kafka 0.8 以后 + +Kafka 0.8 以后,通过**副本机制**来实现高可用。 + +每个 Partition 的数据都会同步到其他机器上,形成多个 Partition 副本。从每个 Partition 的副本集合中,选举出 Leader,其他的都是 Follower。Producer 和 Consumer 就和 Leader 打交道: + +- 写数据时,Leader 会将所用数据都同步到 Follower 上 +- 读数据时,直接读取 Leader 上的数据 + +这样,若某个 Broker 宕机了,Broker 上的 Partition 在其他机器上是有副本的;若宕机的 Broker 上面有某个 Partition 的 Leader,则此时会从 Follower 中重新选择一个新的 Leader 出来。 + +注意:Leader 的读写细节 + +- 写数据时,Producer 向 Leader 写入,接着其他 Follower 主动从 Leader 中 pull 数据,当所有 Follower 同步好数据,就发送确认信息给 Leader,Leader 收到 Follower 的确认后,就返回写成功消息给 Producer。 +- 读数据时,只会从 Leader 中读取,但当只有一个消息已被所有 Follower 都同步成功,返回确认后时,这个消息才被消费者读到。 + +# 六、Kafka 中一些常见的问题 + +## 消息消费的顺序问题 + +消息在被追加到 Partition 的时候都会分配一个特定的偏移量(offset),Kafka 通过偏移量(offset)来保证消息在分区内的顺序性。为了保证 Kafka 中消息消费的顺序,可以采用以下 2 种方法: + +- 设置 1 个 Topic 只对应一个 Partition + + 破坏了 Kafka 的设计初衷,不推荐使用。 + +- 发送消息的时候指定 key + + 同一个 key 的消息可以保证只发送到同一个 Partition。 + +**提升:[如何保证消息的顺序性?](https://doocs.github.io/advanced-java/#/./docs/high-concurrency/how-to-ensure-the-order-of-messages)** + +## 消息丢失问题 + +### Producer 丢失数据 + +如果 Producer 端设置了 `acks=all`,则不会丢失数据。 + +Leader 在所有的 Follower 都同步到了消息之后,才认为本次写成功。如果没满足这个条件,生产者会进行无限次重试。 + +### Consumer 丢失数据 + +默认情况下,Kafka 会自动提交 Offset,Kafka 认为 Consumer 已经处理消息了,但是 Consumer 可能在处理消息的过程中挂掉了。重启系统后,Consumer 会根据提交的 Offset 进行消费,也就丢失了一部分数据。 + +解决:关闭自动提交 Offset,在处理完之后自己手动提交 Offset,就可以保证数据不会丢失。但可能会存在消息重复消费问题。 + +### Broker 丢失数据 + +比较常见的一个场景:Kafka 某个Leader 所在的 Broker 宕机,需要重新选举新的 Leader ,但此时其他的 Follower 部分数据尚未同步完成,选举某个 Follower 成 Leader 后就丢失一部分数据。 + +所以此时一般设置如下 4 个参数: + +- Topic 设置 `replication.factor` 参数 + + 参数值必须大于 1,要求每个 Partition 必须有至少 2 个副本。 + +- Kafka 服务端设置 `min.insync.replicas` 参数 + + 参数值必须大于 1,要求每个 Partition 必须有至少 2 个副本。 + +- Producer 设置 `acks=all` + + 要求每条数据,必须是**写入所有副本,才认为写成功**。 + +- Producer 端设置 `retries=MAX` + + MAX 即是一个超级大的数字,表示无限次重试。`retries=MAX `要求一旦写入数据失败,就无限重试。 + +## 消息重复消费问题 + +Consumer 消费了数据后,每个一段时间,会将已消费过的消息的 Offset 进行提交,这样,重启后,可以继续从上次消费过的 Offset 来继续消费。测试时,直接 kill 进程,然后再重启后,会导致 Consumer 将有些消息处理了,但是还未来得及提交 Offset,重启后,少数消息会再消费一次。 + +解决:需要结合具体业务来思考,可从以下几个思路来考虑: + +- 如果要将数据写入数据库中,先根据主键查查询,如果这数据已存在,就不用插入数据了。 +- 向 Redis 中写入数据,可以使用 set,这样数据不会重复 +- 基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。 + +# 七、Kafka 特性总结 + +Kafka 特性可总结如下: + +## 1. 高可用 + +Kafka 0.8 以前是没有高可用机制的。 + +Kafka 0.8 以后,通过**副本机制**来实现高可用,基于**副本机制**实现 Kafka 的高可用。 + +## 2. 持久性 + +Kafka 集群接收到 Producer 发过来的消息后,将其持久化到磁盘。此外,还支持数据备份。 + +## 3. 数据不易丢失 + +通过合理的配置,Kafka 消息不易丢失。 + +## 4. 高吞吐量 + +Kafka 高吞吐量的原因:分区、批量发送和压缩消息、顺序读写、零拷贝 + +### 分区 + +当生产者向对应 Topic 传递消息,消息通过**负载均衡机制**传递到不同的 Partition 以减轻单个服务器实例的压力; + +一个 Consumer Group 中可以有多个 Consumer,多个 Consumer 可以同时消费不同 Partition 的消息,大大的提高了消费者的并行消费能力。 + +### 批量发送和压缩消息 + +- 批量发送:在发送消息的时候,Kafka 不会直接将少量数据发送出去,否则每次发送少量的数据会增加网络传输频率,降低网络传输效率。Kafka 会先将消息缓存在内存中,当超过一个的大小或者超过一定的时间,那么会将这些消息进行批量发送。 +- 端到端压缩消息: Kfaka会将这些批量的数据进行压缩,将一批消息打包后进行压缩,发送给 Broker 服务器后,最终这些数据还是提供给消费者用,所以数据在服务器上还是保持压缩状态,不会进行解压,而且频繁的压缩和解压也会降低性能,最终还是以压缩的方式传递到消费者的手上,在 Consumer 端进行解压。 + +### 顺序读写 + +Kafka 是个可持久化的日志服务,它将数据以数据日志的形式进行追加,最后持久化在磁盘中。 + +Kafka 消息存储时依赖于**文件系统**。为了利用数据的**局部相关性**:操作系统从磁盘中**以数据块为单位**读取数据,将一个数据块读入内存中,如果有相邻的数据,就不用再去磁盘中读取。所以,在某些情况下,**顺序磁盘访问能比随机内存访问还要快**。同时在写数据的时候也是将一整块数据块写入磁盘中,大大提升 I / O 效率。 + +### 零拷贝 + +普通的数据拷贝 read & write: + +
+ +零拷贝主要的任务是**避免 CPU 做大量的数据拷贝任务,减少不必要的拷贝**。 + +**内存映射文件(Memory Mapped Files,mmap)**在 64 位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的页缓存来实现文件到物理内存的直接映射。 + +
+ +显然,使用 mmap 替代 read 很明显减少了 1 次拷贝,当拷贝数据量很大时,无疑提升了效率。 + +# 补充 + +- [Kafka史上最详细原理总结](https://blog.csdn.net/lingbo229/article/details/80761778?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242) \ No newline at end of file diff --git a/docs/Kafka&RabbitMQ/Kafka_RabbitMQ.md b/docs/Kafka&RabbitMQ/Kafka_RabbitMQ.md new file mode 100644 index 00000000..a9ebb4a9 --- /dev/null +++ b/docs/Kafka&RabbitMQ/Kafka_RabbitMQ.md @@ -0,0 +1,47 @@ +## Kafka 和 RabbitMQ 比较 + +从以下几个方面比较 Kafka 和 RabbitMQ: + +- 吞吐量 + + Kafka:十万数量级,高吞吐量 + + RabbitMQ:万数量级 + +- Topic 数量对吞吐量影响 + + Kafka 的 Topic 可达百/千级,吞吐量下降幅度小,在同等机器下,可以支撑大量的 Topic。 + + RabbitMQ 无 Topic 概念。 + +- 时效性 + + Kafka 毫秒级;RabbitMQ 微秒级 + +- 可用性 + + Kafka 基于分布式架构,可用性非常高 + + RabbitMQ 基于主从架构实现高可用 + +- 可靠性 + + Kafka 优化参数配置,可以做到零丢失 + + RabbitMQ 基本不会丢失数据 + +- 功能 + + Kafka 功能较为简单,主要支持简单的消息队列功能,在大数据领域的实时计算以及日志采集被大规模使用 + + RabbitMQ 基于 ErLang 开发,并发能力很强,性能极好,延时很低 + +总结: + +- Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8 版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,**适合产生大量数据的互联网服务的数据收集业务**。 +- RabbitMQ 是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP 协议更多用在企业系统内,**对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次**。 + + + + + diff --git a/docs/Kafka&RabbitMQ/RabbitMQ.md b/docs/Kafka&RabbitMQ/RabbitMQ.md new file mode 100644 index 00000000..45ae2732 --- /dev/null +++ b/docs/Kafka&RabbitMQ/RabbitMQ.md @@ -0,0 +1,1930 @@ +# 一、Rabbit 概述 + +RabbitMQ 是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用中间共享数据,RabbitMQ 是使用 **Erlang 语言**来编写的,并且 RabbitMQ 是基于 AMQP 协议的。 + +特点: + +- 开源、性能优秀 + + **Erlang 语言**最初用在交换机的架构模式,这样使得 RabbitMQ 在 Broker 之间进行数据交互的性能时非常优秀的。Erlang 的优点:Erlang 有着和原生 Socket 一样的延迟。 + +- 可靠性 + + 提供可靠性消息投递模式(confirm)、返回模式(return)。 + +- 扩展性 + + 多个RabbitMQ 节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点。 + +- 与 SpringAOP 完美的整合、API 丰富 +- 保证数据不丢失的前提做到高可靠性、可用性 + +# 二、AMQP 协议 + +AMQP (Advanced Message Queuing Protocol) 即高级消息队列协议,是一个进程间传递**异步消息**的**网络协议**。 + +## AMQP 模型 + +
+ +工作过程如下:首先发布者(Publisher)发布消息(Message),经由交换机 Exchange。交换机根据**路由规则**将收到的消息分发给与该交换机绑定的 Queue。最后 AMQP 代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。 + +关于 AMQP 模型的几点说明: + +- 发布者、交换机、队列、消费者都可以有多个。AMQP 是一个网络协议,所以这个过程中的发布者,消费者,消息代理可以分别存在于不同的设备上。 +- 布者发布消息时可以给消息指定各种消息属性(Message Meta-data)。有些属性有可能会被消息代理(Brokers)使用,然而其他的属性则是完全不透明的,它们只能被接收消息的应用所使用。 +- 从安全角度考虑,网络是不可靠的,又或是消费者在处理消息的过程中意外挂掉,这样没有处理成功的消息就会丢失。基于此原因,AMQP 模块包含了一个消息确认机制:当一个消息从队列中投递给消费者后,不会立即从队列中删除,直到它收到来自消费者的确认回执(Acknowledgement)后,才完全从队列中删除。 +- 在某些情况下,例如当一个消息无法被成功路由时(无法从交换机分发到队列),消息或许会被返回给发布者并被丢弃。或者,如果消息代理执行了**延期操作**,消息会被放入一个**死信队列**中。此时,消息发布者可以选择某些参数来处理这些特殊情况。 + +## Producer & Consumer + +消息生产者(Producer),向 Broker 发送消息的客户端。 + +消息消费者(Consumer),从 Broker 消费消息的客户端。 + +## Broker + +一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务节点,或者 RabbitMQ 服务实例。大多数情况下可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。 + +## Exchange + +Exchange 即交换器,是用来发送消息的 AMQP 实体。Exchange 拿到一个消息之后将它**路由**给一个或零个队列。Exchange 使用哪种路由算法是由**交换机类型**和**绑定(Bindings)规则**所决定的。 + +### Binding + +**Producer 将消息发给 Exchange 时,一般会指定一个 RoutingKey (路由键),用来指定这个消息的路由规则,而这个 RoutingKey 需要与交换器类型和 BindingKey (绑定键) 联合使用才能最终生效**。 + +RabbitMQ 中通过 **Binding (绑定)** 将 Exchange 与 Queue(消息队列) 关联起来,在绑定时一般会指定一个 BindingKey,这样 RabbitMQ 就知道如何正确将消息路由到 Queue 中。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则。 + +生产者将消息发送给交换器,当 BindingKey 和 RoutingKey 相匹配时,消息会被路由到对应的队列中。注意BindingKey 并不是在所有的情况下都生效,它依赖于交换器类型,比如 fanout 类型的交换器就会无视,而是将消息路由到所有绑定到该交换器的队列中。 + +### Exchange 类型 + +Exchange 有以下 4 种类型,不同的类型对应着不同的路由策略: + +#### direct + +Exchange 默认类型。**路由规则是把消息路由到 Bindingkey 与 RoutingKey 完全匹配的 Queue 中**。direct 类型常用在**处理有优先级的任务**,根据任务的优先级把消息发送到对应的队列,这样可以指派更多的资源去处理高优先级的队列。 + +
+ +以上图为例,如果发送消息的时候 RoutingKey="booking",那么消息会路由到 Queue1 和 Queue2。如果在发送消息的时候设置 RoutingKey="create" 或 "confirm",消息只会路由到Queue2。如果以其他的 RoutingKey 发送消息,则消息不会路由到这两个队列中。 + +#### fanout + +路由规则是把所有发送到该 Exchange 的消息路由到所有与它绑定的 Queue 中,不需要做任何判断操作,所以 fanout 类型是所有的交换机类型里面速度最快的。**fanout 类型常用来广播消息**。 + +#### topic + +direct 类型的 Exchange 路由规则是完全匹配 BindingKey 和 RoutingKey ,但是这种严格的匹配方式在很多情况下不能满足实际业务的需求。 + +topic 类型的 Exchange 在匹配规则上进行了扩展,它与 direct 类型的 Exchange 相似,也是将消息路由到 BindingKey 和 RoutingKey 相匹配的队列中,但这里的匹配规则有些不同,它约定: + +- RoutingKey 为一个点号`.`分隔的字符串,其中**被 `.`分隔开的每一段独立的字符串称为一个单词**; +- BindingKey 和 RoutingKey 一样也是点号 `.` 分隔的字符串; +- BindingKey 中可以存在两种特殊字符串 `*` 和 `#`,用于做模糊匹配,其中 `*` 用于匹配一个单词, `#` 用于匹配零个或多个单词。 + +
+ +以上图为例,如果发送消息的时候 RoutingKey 为 + +- "com.rabbitmq.client",那么消息会路由到 Queue1 和 Queue2 +- "com.hidden.client",那么消息只会路由到 Queue2 中 +- "com.hidden.demo",那么消息只会路由到 Queue2 中 +- "java.rabbitmq.demo",那么消息只会路由到 Queue1 中 +- "java.util.concurrent",那么消息将会被丢弃或者返回给生产者,因为它没有匹配任何路由键。 + +#### headers + +headers 类型的 Exchange 不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的 headers 属性进行匹配。在绑定队列和交换器时指定一组键值对,当发送消息到交换器时,RabbitMQ 会获取到该消息的 headers(也是一个键值对的形式),对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers 类型的 Exchange 性能会很差,不推荐使用。 + +## Queue + +Queue 其实是 Message Queue 即消息队列,保存消息并将它们转发给消费者。Queue 是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其消费。 + +**RabbitMQ 中消息只能存储在队列中**,而 Kafka 将消息存储在 **Topic** 中,即该 Topic 对应的 Partition 中。RabbitMQ 的生产者生产消息并最终投递到队列中,消费者可以从队列中获取消息并消费。 + +当多个消费者订阅同一个队列时,队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,这样避免消息被重复消费。 + +### 队列属性 + +Queue 跟 Exchange 共享某些属性,但是队列也有一些另外的属性: + +- Name +- Durable:消息代理重启后,队列依旧存在 +- Exclusive:只被一个连接使用,而且当连接关闭后队列即被删除 +- Auto-delete:当最后一个消费者退订后即被删除 +- Arguments:一些消息代理用他来完成类似与 TTL 的某些额外功能 + +### 队列创建 + +队列在声明(declare)后才能被使用。 + +如果一个队列尚不存在,声明一个队列会创建它。如果声明的队列已经存在,并且属性完全相同,那么此次声明不会对原有队列产生任何影响。如果声明中的属性与已存在队列的属性有差异,那么一个错误代码为 406 的通道级异常就会被抛出。 + +### 队列持久化 + +持久化队列(Durable Queues)会被存储在磁盘上,当消息代理(Broker)重启的时候,它依旧存在。没有被持久化的队列称作暂存队列(Transient Queues)。并不是所有的场景和案例都需要将队列持久化。 + +持久化的队列并不会使得路由到它的消息也具有持久性。倘若消息代理挂掉了,重新启动,那么在重启的过程中持久化队列会被重新声明,无论怎样,**只有经过持久化的消息才能被重新恢复**。 + +## 消息机制 + +### 消息确认 + +AMQP 代理在什么时候删除消息才是正确的?AMQP 0-9-1 规范给我们两种建议: + +- **自动确认模式**:当消息代理(Broker)将消息发送给应用后立即删除。(使用 AMQP 方法:basic.deliver 或 basic.get-ok) + +- **显示确认模式**:待 Consumer 发送一个确认回执(acknowledgement)后再删除消息。(使用 AMQP 方法:basic.ack) + + 如果一个消费者在尚未发送确认回执的情况下挂掉了,那 AMQP 代理会将消息重新投递给另一个消费者。如果当时没有可用的消费者了,消息代理会死等下一个注册到此队列的消费者,然后再次尝试投递。 + +### 拒绝消息 + +当拒绝某条消息时,应用可以告诉消息代理销毁该条消息或者重新将该条消息放入队列。 + +当此队列只有一个消费者时,有可能存在拒绝消息并将消息重新放入队列的行为而引起消息在同一个消费者身上无限循环的情况。 + +### 预取消息 + +在多个消费者共享一个队列时,明确指定在收到下一个确认回执前每个消费者一次可以接受多少条消息是非常有用的。这可以在试图批量发布消息的时候起到**简单的负载均衡和提高消息吞吐量**的作用。 + +### 消息属性 + +AMQP 模型中的消息(Message)对象是带有属性(Attributes)的: + +| 属性 | 说明 | +| --------------------------------- | ------------------------------ | +| Content type | 内容类型 | +| Content encoding | 内容编码 | +| **Routing key** | 路由键 | +| Delivery mode (persistent or not) | 投递模式(持久化 或 非持久化) | +| Message priority | 消息优先权 | +| Message publishing timestamp | 消息发布的时间戳 | +| Expiration period | 消息有效期 | +| Publisher application id | 发布应用的 ID | + +有些属性是被 AMQP 代理所使用的,但是大多数是开放给接收它们的应用解释器用的。有些属性是可选的也被称作消息头(headers)。和 HTTP 协议的 X-Headers 很相似,消息属性需要在消息被发布的时候定义。 + +### 消息主体 + +AMQP 的消息除属性外,也含有一个有效载荷 Payload(消息实际携带的数据),它被 AMQP 代理当作不透明的字节数组来对待。 + +消息代理不会检查或者修改 Payload,消息可以只包含属性而不携带有效载荷,它通常会使用类似 JSON 这种序列化的格式数据。 + +### 消息持久化 + +消息能够以持久化的方式发布,AMQP 代理会将此消息存储在磁盘上。如果服务器重启,系统会确认收到的持久化消息未丢失。 + +简单地将消息发送给一个持久化的交换机或者路由给一个持久化的队列,并不会使得此消息具有持久化性质:它完全取决与消息本身的持久模式(persistence mode)。将消息以持久化方式发布时,会对性能造成一定的影响(就像数据库操作一样,健壮性的存在必定造成一些性能损失)。 + +# 三、RabbitMQ 命令行操作 + +
+ +## 启动 & 停止服务器 + +- 启动服务器 + + ```html + rabbitmq-server start & + ``` + +- 停止服务器 + + ```html + rabbitmqctl stop_app + ``` + +## 查看管控台 + +```html +http://localhost:15672/ + +# 用户名 guest +# 密码 guest +``` + + + +## 命令行基础操作 + +### 1. 应用 + +- 关闭应用 + + ```html + rabbitmqctl stop_app + ``` + +- 启动应用 + + ```html + rabbitmqctl start_app + ``` + +- 查看节点状态 + + ```html + rabbitmqctl status + ``` + +### 2. 用户 + +- 添加用户 + + ```html + rabbitmqctl add_user username password + ``` + +- 删除用户 + + ```html + rabbitmqctl delete_user username + ``` + +- 列出所有用户 + + ```html + rabbitmqctl list_users + ``` + +- 清除用户权限 + + ```html + rabbitmqctl clear_permissions -p vhostpath username + ``` + +- 列出用户权限 + + ```html + rabbitmqctl list_user_permissions username + ``` + +- 修改密码 + + ```html + rabbitmqctl change_password username newpassword + ``` + +- 设置用户权限 + + ```html + rabbitmqctl set_permissions -p vhostpath username ".*" ".*" ".*" + ``` + +### 3. 虚拟主机 + +- 创建虚拟主机 + + ```html + rabbitmqctl add_vhost vhostpath + ``` + +- 删除虚拟主机 + + ```html + rabbitmqctl delete_vhost vhostpath + ``` + +- 列出所有虚拟主机 + + ```html + rabbitmqctl list_vhosts + ``` + +- 列出虚拟主机上所有权限 + + ```html + rabbitmqctl list_permissions -p vhostpath + ``` + +### 4. 队列 + +- 查看所有队列信息 + + ```html + rabbitmqctl list_queues + ``` + +- 清除队列里的消息 + + ```html + rabbitmqctl -p vhostpath purge_queue blue + ``` + + + +## 命令行高级操作 + +- 移除所有数据 + + ```html + rabbitmqctl reset + # 要在 rabbitmqctl stop_app 之后使用 + ``` + +- 组成集群命令 + + ```html + rabbitmqctl join_cluster [--ram] + ``` + +- 查看集群状态 + + ```html + rabbitmq cluster_status + ``` + +- 修改集群节点的存储形式 + + ```html + rabbitmqctl change_cluser_node_type disc | ram + ``` + +- 摘除节点(忘记节点) + + ```html + rabbitmqctl forget_cluster_node [--offline] + ``` + +- 修改节点名称 + + ```html + rabbitmqctl rename_cluster_node oldnode1 newnode1 [oldnode2] [newnode2] + ``` + +# 四、Rabbit MQ 入门 + +## 简单案例:消息生产与消费 + +pom.xml 配置 + +```html + + com.rabbitmq + amqp-client + + 3.6.5 + +``` + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

简单案例:消息生产与消费

+ * 消息生产者 + * Created by DHA on 2019/11/18. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 通过 chanel 发送数据 + for(int i=0;i<10;i++){ + String data="Hello!"; + channel.basicPublish("","test001",null,data.getBytes()); + } + + //5 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

简单案例:消息生产与消费

+ * 消息生产者 + * Created by DHA on 2019/11/18. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 通过 chanel 发送数据 + for(int i=0;i<10;i++){ + String data="Hello!"; + channel.basicPublish("","test001",null,data.getBytes()); + } + + //5 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + +## Direct Exchange + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Direct Exchange

+ * 所有发送到 Direct Exchange 的消息被转发到 routing key 中指定的 Queue。 + * 消息生产者 + * Created by DHA on 2019/11/19. + */ +public class Producer4DirectExchange { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_direct_exchange"; + String routingKey = "test.direct"; + + //5 通过 chanel 发送数据 + String msg = "Hello World RabbitMQ 4 Direct Exchange Message ... "; + channel.basicPublish(exchangeName, routingKey , null , msg.getBytes()); + + //6 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Direct Exchange

+ * 所有发送到 Direct Exchange 的消息被转发到 routing key 中指定的 Queue。 + * 消息消费者 + * Created by DHA on 2019/11/19. + */ +public class Consumer4DirectExchange { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName="test_direct_exchange"; + String exchangeType="direct"; + String queueName="test_direct_queue"; + String routingKey="test.direct"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,true,queueingConsumer); + + //7 获取数据 + while(true){ + QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + } +} +``` + + + +## Topic Exchange + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Topic Exchange

+ * Topic Exchange 将 routing key 与某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。 + * 消息生产者 + * Created by DHA on 2019/11/19. + */ +public class Producer4TopicExchange { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_topic_exchange"; + String routingKey1 = "user.save"; + String routingKey2 = "user.update"; + String routingKey3 = "user.delete.abc"; + + //5 通过 chanel 发送数据 + String msg = "Hello World RabbitMQ 4 Topic Exchange Message ... "; + channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes()); + channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes()); + channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes()); + + //6 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Topic Exchange

+ * Topic Exchange 将 routing key 与某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。 + * 消息消费者 + * Created by DHA on 2019/11/19. + */ +public class Consumer4TopicExchange { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName="test_topic_exchange"; + String exchangeType="topic"; + String queueName="test_topic_queue"; + String routingKey="user.*"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,true,queueingConsumer); + + //7 获取数据 + while(true){ + QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + } +} +``` + + + +## Fanout Exchange + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Fanout Exchange

+ * Fanout Exchange 不处理 routing key,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到交换机绑定的所有队列上。 + * 消息生产者 + * Created by DHA on 2019/11/19. + */ +public class Producer4FanoutExchange { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_fanout_exchange"; + + //5 通过 chanel 发送数据 + for(int i = 0; i < 10; i ++) { + String msg = "Hello World RabbitMQ 4 Fanout Exchange Message ..."; + channel.basicPublish(exchangeName, "", null , msg.getBytes()); + } + + //6 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Fanout Exchange

+ * Fanout Exchange 不处理 routing key,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到交换机绑定的所有队列上。 + * 消息消费者 + * Created by DHA on 2019/11/19. + */ +public class Consumer4FanoutExchange { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName="test_fanout_exchange"; + String exchangeType="fanout"; + String queueName="test_fanout_queue"; + String routingKey=""; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,true,queueingConsumer); + + //7 获取数据 + while(true){ + QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + } +} +``` + + + +## 设置消息属性 + +### 生产者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +/** + *

消息属性设置

+ * 消息生产者 + * Created by DHA on 2019/11/18. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + // 设置自定义属性 + Map headers = new HashMap<>(); + headers.put("attr1", "111"); + headers.put("attr2", "222"); + + //4 设置消息属性 + AMQP.BasicProperties properties=new AMQP.BasicProperties.Builder() + .deliveryMode(2) // 2 表示持久化的投递 + .contentEncoding("UTF-8") // 设置内容编码 + .expiration("10000") // 设置过期时间为 10 秒 + .headers(headers) // 自定义属性 + .build(); + + //5 通过 chanel 发送数据 + for(int i=0;i<5;i++){ + String data="Hello!"; + channel.basicPublish("","test001",properties,data.getBytes()); + } + + //6 关闭相关连接 + channel.close(); + connection.close(); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; +import com.rabbitmq.client.QueueingConsumer.Delivery; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +/** + *

消息属性设置

+ * 消息消费者 + * Created by DHA on 2019/11/18. + */ +public class Consumer { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明一个队列 + String queueName="test001"; + channel.queueDeclare(queueName,true,false,false,null); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,true,queueingConsumer); + + //7 获取数据 + while(true){ + Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + // 获取自定义属性数据 + Map headers=delivery.getProperties().getHeaders(); + System.err.println("headers get attribute attr1 value: " + headers.get("attr1")); + } + } +} +``` + + + +# 五、RabbitMQ 高级特性 + +## 消息100%可靠性投递的解决方案 + +### 生产端可靠性投递 + +- 保障消息成功发出 +- 保障 MQ 节点的成功接收 +- 发送端收到 MQ 节点(Broker)确认应答 +- **完善的消息补偿机制** + +### 解决方案1:消息落库 + +消息落库,对消息状态进行打标。 + +
+ + + +### 解决方案2:二次确认,回调检查 + +消息的延迟投递,做二次确认,回调检查。 + +
+ + + +## 消费端幂等性操作 + +- 唯一 ID + 指纹码 机制,利用数据库主键去重 + + 优点:实现简单 + + 缺点:高并罚下有数据库写入的性能瓶颈 + + 解决方案:根据 ID 进行分库分表进行算法路由 + +- 利用 Redis 原子特性实现 + +## Confirm 消息机制 + +消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 + +
+ +实现机制: + +- 第一步:在 channel 上开启确认模式 + + ```java + channel.confirmSelect() + ``` + +- 第二步:在 channel 上添加监听 + + ```java + channel.addConfirmListener() + ``` + + 监听成功和失败的返回结果,根据具体的结果对消息进行重新发送或记录日志等后续处理。 + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.ConfirmListener; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Confirm 消息机制

+ * 消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 + * 消息生产者 + * Created by DHA on 2019/11/18. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 指定消息投递模式:confirm 模式 + channel.confirmSelect(); + + String exchangeName = "test_confirm_exchange"; + String routingKey = "confirm.save"; + + //5 通过 chanel 发送数据 + String msg="Hello!"; + channel.basicPublish(exchangeName,routingKey,null,msg.getBytes()); + + //6 添加一个确认监听 + channel.addConfirmListener(new ConfirmListener() { + @Override + public void handleAck(long l, boolean b) throws IOException { + System.out.println("------ack!-------"); + } + + @Override + public void handleNack(long l, boolean b) throws IOException { + System.out.println("------Nack!-------"); + } + }); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; +import com.rabbitmq.client.QueueingConsumer.Delivery; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Confirm 消息机制

+ * 消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 + * 消息消费者 + * Created by DHA on 2019/11/18. + */ +public class Consumer { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName="test_confirm_exchange"; + String exchangeType="topic"; + String queueName="test_confirm_queue"; + String routingKey="confirm.#"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,queueingConsumer); + + //7 获取数据 + while(true){ + Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + } +} +``` + + + +## Return 消息机制 + +消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 + +在某些情况下,如果我们在发送消息的时候,当前的 **Exchange 不存在**或者指定的 **routing key路由不到**,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 + +基础 API 有一个配置项 mandatory + +- 如果为 true,那么监听器会接收到路由不可达的消息,然后进行后续处理 +- 如果为 false, 那么 Broker 端自动删除该消息 + + + +
+ + + +### 生产者 + +```java +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Return 消息机制

+ * 消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 + * 在某些情况下,如果我们在发送消息的时候,当前的 Exchange 不存在或者指定的 routing key路由不到,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 + * + * 消息生产者 + * Created by DHA on 2019/11/18. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 指定消息投递模式:confirmListener 模式 + channel.confirmSelect(); + + String exchangeName = "test_return_exchange"; + String routingKey = "returnListener.save"; + String routingKeyError = "return.save"; + + //5 通过 chanel 发送数据 + String msg="Hello!"; + // mandatory 如果为 true,那么监听器会接收到路由不可达的消息,然后进行后续处理 + // mandatory 如果为 false, 那么 Broker 端自动删除该消息 + channel.basicPublish(exchangeName,routingKeyError,true,null,msg.getBytes()); + + //6 添加一个监听 + channel.addReturnListener(new ReturnListener() { + @Override + public void handleReturn(int replyCode, String replyText, String exchange, + String routingKey, AMQP.BasicProperties properties, byte[] body) + throws IOException { + System.err.println("---------handle return----------"); + System.err.println("replyCode: " + replyCode); + System.err.println("replyText: " + replyText); + System.err.println("exchange: " + exchange); + System.err.println("routingKey: " + routingKey); + System.err.println("properties: " + properties); + System.err.println("body: " + new String(body)); + } + }); + + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; +import com.rabbitmq.client.QueueingConsumer.Delivery; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

Return 消息机制

+ * 消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 + * 在某些情况下,如果我们在发送消息的时候,当前的 Exchange 不存在或者指定的 routing key路由不到,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 + * + * 消息消费者 + * Created by DHA on 2019/11/18. + */ +public class Consumer { + public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName="test_return_exchange"; + String exchangeType="topic"; + String queueName="test_return_queue"; + String routingKey="returnListener.#"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,queueingConsumer); + + //7 获取数据 + while(true){ + Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + } +} +``` + + + +## 消费端自定义监听 + +我们一般在代码中编写 while 循环,进行 consumer.nextDelivery 方法获取下一条消息,然后进行消费处理! + +但是,我们使用自定义的 Counsumer 更加方便,解耦性更强,在实际工作中广泛使用。 + +### 自定义消费者 + +实现步骤: + +- 先继承 `com.rabbitmq.client.DefaultConsumer` +- 再重写 `handleDelivery()` 方法 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.DefaultConsumer; +import com.rabbitmq.client.Envelope; + +import java.io.IOException; + +/** + *

自定义消费者

+ * 1 先继承 DefaultConsumer + * 2 然后重写 handleDelivery() 方法 + * + * Created by DHA on 2019/11/20. + */ +public class MyConsumer extends DefaultConsumer{ + public MyConsumer(Channel channel) { + super(channel); + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, + AMQP.BasicProperties properties, byte[] body) + throws IOException { + System.err.println("----------consumer message-----------"); + System.err.println("consumerTag:"+consumerTag); + System.err.println("envelope:"+envelope); + System.err.println("properties:"+properties); + System.err.println("body:"+new String(body)); + } +} +``` + + + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

消费端自定义监听

+ * 消息生产者 + * Created by DHA on 2019/11/19. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_consumer_exchange"; + String routingKey = "consumer.save"; + + //5 通过 chanel 发送数据 + String msg = "Hello World RabbitMQ 4 Consumer Exchange Message ... "; + channel.basicPublish(exchangeName, routingKey , true,null , msg.getBytes()); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.QueueingConsumer; +import com.rabbitmq.client.QueueingConsumer.Delivery; + +public class Consumer { + + public static void main(String[] args) throws Exception { + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName = "test_consumer_exchange"; + String exchangeType= "topic"; + String routingKey = "consumer.#"; + String queueName = "test_consumer_queue"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + /* + //5 创建消费者 + QueueingConsumer queueingConsumer=new QueueingConsumer(channel); + + //6 设置 channel + channel.basicConsume(queueName,true,queueingConsumer); + + //7 获取数据 + while(true){ + QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); + String msg=new String(delivery.getBody()); + System.out.println("消费端:"+msg); + } + */ + + //5 消费端自定义监听 使用 MyConsumer 相应实例 + channel.basicConsume(queueName, true, new MyConsumer(channel)); + } +} +``` + + + +## 消费端限流 + +RabbitMQ 提供了一种 QoS(服务质量保证) 功能,**在非自动确认消息的前提下**,如果一定数目的消息(通过基于 Consume 或者 Channel 设置 QoS 值)未被确认前,不进行消费新的消息。 + +涉及到的方法: + +```erlang +void BasicQoS(unit prefetchSize,ushort prefetchCount,bool global) +``` + +- prefetchSize:0 +- prefetchCount:告知 RabbitMQ 不要同时给一个消费者推送多个 N 个消息,即一旦有 N 个消息还没有 ACK,则该 Consumer 将 block 掉,一直到有消息 ack +- golbal:true 表示将上面设置应用于 Channel;true 表示将上面设置应用于 Consumer。 + +注意: + +- prefetchSize 和 global 这两项,RabbitMQ 没有实现,暂且不研究 +- prefetchCount 在 no_ask-false 的情况下生效,即在自动应答的情况下是不生效的 + +### 生产者 + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + *

消费端限流

+ * 消息生产者 + * Created by DHA on 2019/11/19. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_qos_exchange"; + String routingKey = "qos.save"; + + //5 通过 chanel 发送数据 + for(int i=0;i<5;i++){ + String msg = "Hello World RabbitMQ 4 Qos Message ... "; + channel.basicPublish(exchangeName, routingKey , true,null , msg.getBytes()); + } + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.DefaultConsumer; +import com.rabbitmq.client.Envelope; + +import java.io.IOException; + +/** + *

自定义消费者

+ * 1 先继承 DefaultConsumer + * 2 然后重写 handleDelivery() 方法 + * + * Created by DHA on 2019/11/20. + */ +public class MyConsumer extends DefaultConsumer{ + + // channel 进行签收 + private Channel channel; + + public MyConsumer(Channel channel) { + super(channel); + this.channel=channel; + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, + AMQP.BasicProperties properties, byte[] body) + throws IOException { + System.err.println("----------consumer message-----------"); + System.err.println("consumerTag:"+consumerTag); + System.err.println("envelope:"+envelope); + System.err.println("properties:"+properties); + System.err.println("body:"+new String(body)); + + // false 表示不支持批量签收 + channel.basicAck(envelope.getDeliveryTag(),false); + } +} +``` + + + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + *

消费端限流

+ * 消息消费者 + * + * basicQoS(prefetchSize,refetchCount,global) + * - prefetchSize:0 + * - prefetchCount:告知 RabbitMQ 不要同时给一个消费者推送多个 N 个消息,即一旦有 N 个消息还没有 ACK, + * 则该 Consumer 将 block 掉,一直到有消息 ack + * - golbal:true 表示将上面设置应用于 Channel;true 表示将上面设置应用于 Consumer。 + * + * Created by DHA on 2019/11/19. + */ +public class Consumer { + + public static void main(String[] args) throws Exception { + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName = "test_qos_exchange"; + String exchangeType= "topic"; + String routingKey = "qos.#"; + String queueName = "test_qos_queue"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + // 第二个参数为 1,表示一次处理一条消息 + // 第三个参数为 false,表示应用到 Consumer 级别 + channel.basicQos(0,1,false); + + //5 消费端自定义监听 + // 首先将第二个参数设置为 false,进行手动签收 + channel.basicConsume(queueName, false, new MyConsumer(channel)); + } +} +``` + + + +## 消费端 ACK 与重回队列 + +- **消费端的手工 ACK 和 NACK** + + 消费端进行消费时: + + 如果由于业务异常,我们可以进行日志的记录,然后进行补偿; + + 如果由于服务器宕机等严重问题,那么需要手工进行 ACK 保障消费端消费成功 + +- **消费端的重回队列** + + 消费端重回队列是为了对没有成功的消息, 消息会被重新投递给 Broker。一般在使用应用中,都会关闭重回队列,即设置为 false。 + +### 生产者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +/** + *

消费端的手工 ACK 和 NACK

+ * 消息生产者 + * + * Created by DHA on 2019/11/19. + */ +public class Producer { + public static void main(String[] args) throws IOException, TimeoutException { + + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + //声明 exchange 名称 + String exchangeName="test_ack_exchange"; + String routingKey = "ack.save"; + + //5 通过 chanel 发送数据 + for(int i =0; i<5; i ++){ + + Map headers = new HashMap(); + headers.put("num", i); + + AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() + .deliveryMode(2) + .contentEncoding("UTF-8") + .headers(headers) + .build(); + String msg = "Hello RabbitMQ ACK Message " + i; + channel.basicPublish(exchangeName, routingKey, true, properties, msg.getBytes()); + } + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.DefaultConsumer; +import com.rabbitmq.client.Envelope; + +import java.io.IOException; + +/** + *

消费端的重回队列

+ * 消费端重回队列是为了对没有成功的消息, 消息会被重新投递给 Broker。 + * 一般在使用应用中,都会关闭重回队列,即设置为 false。 + * + * Created by DHA on 2019/11/20. + */ +public class MyConsumer extends DefaultConsumer{ + + // channel 进行签收 + private Channel channel; + + public MyConsumer(Channel channel) { + super(channel); + this.channel=channel; + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, + AMQP.BasicProperties properties, byte[] body) + throws IOException { + System.err.println("-----------consume message----------"); + System.err.println("body: " + new String(body)); + + // 为了实验效果明显 + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Integer num=(Integer) properties.getHeaders().get("num"); + if(num==0){ + // 第二个参数表示是否支持批量签收,如果为 false,表示不支持批量签收 + // 第三个参数表示是否重回队列,如果为 true,表示支持重回队列,则会重回到队列的尾端 + channel.basicNack(envelope.getDeliveryTag(),false,true); + }else{ + // false 表示不支持批量签收 + channel.basicAck(envelope.getDeliveryTag(),false); + } + //channel.basicAck(envelope.getDeliveryTag(),false); + } +} +``` + + + +```java +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + *

消费端的手工 ACK 和 NACK

+ * 消息消费者 + * + * Created by DHA on 2019/11/19. + */ +public class Consumer { + + public static void main(String[] args) throws Exception { + //1 创建一个 Connectionfactory,并进行设置 + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + //2 通过连接工厂创建连接 + Connection connection = connectionFactory.newConnection(); + + //3 通过 connecion 创建一个 Channel + Channel channel = connection.createChannel(); + + //4 声明 + String exchangeName = "test_ack_exchange"; + String exchangeType= "topic"; + String routingKey = "ack.#"; + String queueName = "test_ack_queue"; + + // 声明一个交换机 + channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); + // 声明一个队列 + channel.queueDeclare(queueName,false,false,false,null); + // 绑定:将一个队列绑定到一个交换机上 + channel.queueBind(queueName,exchangeName,routingKey); + + //5 消费端自定义监听 + // 首先将第二个参数 autoACK 设置为 false,进行手动签收 + channel.basicConsume(queueName, false, new MyConsumer(channel)); + } +} +``` + + + +## TTL + +TTL(Time To Live)即生存时间。 + +- RabbitMQ 支持**消息**的过期时间,在消息发送时可以进行指定 +- RabbitMQ 支持**队列**的过期时间,从消息如队列开始计算,只要超过了队列的超时时间配置,那么会自动清除消息 + +## 死信队列(DLX,Dead-Letter-Exchange ) + +利用 DLX,当消息在一个队列中变成死信(dead message)之后,其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 + +消息变成死信的几种情况: + +- 消息被拒绝(basic.reject / basic.nack),并且 requeue=false +- 消息 TTL 过期 +- 队列达到最大长度 + +注意: + +- DLX 也是一个正常的 Exchange,和一般的 Exchange 没有区别,它能在任何队列上被指定,实际上就是设置某个队列的属性。 + +- 当这个队列中有死信时,RabbitMQ 就会自动的将这个消息重新发布到设置的 Exchange 上去,进而被路由到另一个队列。 + +- 死信队列设置需要设置 Exchange 和 队列,然后绑定 + + ```java + channel.exchangeDeclare("dlx.exchange", "topic", true, false, null); + channel.queueDeclare("dlx.queue", true, false, false, null); + channel.queueBind("dlx.queue", "dlx.exchange", "#"); + ``` + + 然后我们进行正常声明 Exchange、队列和绑定,此时需要在队列上加上参数 arguments + + ```java + Map agruments = new HashMap(); + agruments.put("x-dead-letter-exchange", "dlx.exchange"); + //这个agruments属性,要设置到声明队列上 + channel.queueDeclare(queueName, true, false, false, agruments); + ``` + +### 生产者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + *

死信队列

+ * 利用 DLX,当消息在一个队列中变成死信(dead message)之后, + * 其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 + * + * 消息生产者 + * Created by DHA on 2019/11/20. + */ +public class Producer { + + public static void main(String[] args) throws Exception { + + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + Connection connection = connectionFactory.newConnection(); + Channel channel = connection.createChannel(); + + String exchange = "test_dlx_exchange"; + String routingKey = "dlx.save"; + + String msg = "Hello RabbitMQ DLX Message"; + + AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() + .deliveryMode(2) + .contentEncoding("UTF-8") + .expiration("10000") + .build(); + channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes()); + } +} +``` + + + +### 消费者 + +```java +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.DefaultConsumer; +import com.rabbitmq.client.Envelope; + +import java.io.IOException; + +/** + *

自定义消费者

+ * 1 先继承 DefaultConsumer + * 2 然后重写 handleDelivery() 方法 + * + * Created by DHA on 2019/11/20. + */ +public class MyConsumer extends DefaultConsumer{ + public MyConsumer(Channel channel) { + super(channel); + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, + AMQP.BasicProperties properties, byte[] body) + throws IOException { + System.err.println("----------consumer message-----------"); + System.err.println("consumerTag:"+consumerTag); + System.err.println("envelope:"+envelope); + System.err.println("properties:"+properties); + System.err.println("body:"+new String(body)); + } +} +``` + + + +```java +import java.util.HashMap; +import java.util.Map; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + *

死信队列

+ * 利用 DLX,当消息在一个队列中变成死信(dead message)之后, + * 其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 + * + * 消息消费者 + * Created by DHA on 2019/11/20. + */ +public class Consumer { + + public static void main(String[] args) throws Exception { + + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setHost("localhost"); + connectionFactory.setPort(5672); + connectionFactory.setVirtualHost("/"); + + Connection connection = connectionFactory.newConnection(); + Channel channel = connection.createChannel(); + + // 这就是一个普通的交换机 和 队列 以及路由 + String exchangeName = "test_dlx_exchange"; + String routingKey = "dlx.#"; + String queueName = "test_dlx_queue"; + + channel.exchangeDeclare(exchangeName, "topic", true, false, null); + Map agruments = new HashMap(); + agruments.put("x-dead-letter-exchange", "dlx.exchange"); + //这个agruments属性,要设置到声明队列上 + channel.queueDeclare(queueName, true, false,false,agruments); + channel.queueBind(queueName, exchangeName, routingKey); + + //要进行死信队列的声明: + channel.exchangeDeclare("dlx.exchange", "topic", true, false, null); + channel.queueDeclare("dlx.queue", true, false, false, null); + channel.queueBind("dlx.queue", "dlx.exchange", "#"); + + channel.basicConsume(queueName, true, new MyConsumer(channel)); + } +} +``` + diff --git "a/docs/Kafka/2_Kafka\347\232\204\346\236\266\346\236\204.md" "b/docs/Kafka/2_Kafka\347\232\204\346\236\266\346\236\204.md" deleted file mode 100644 index 87998f60..00000000 --- "a/docs/Kafka/2_Kafka\347\232\204\346\236\266\346\236\204.md" +++ /dev/null @@ -1,164 +0,0 @@ -# Kafka的架构 - -## Kafka 的基本组成 - -Kafka 集群由若干个 Broker 组成,Topic 由若干个 Partition 组成,每个 Partition 里面的消息通过 Offset 来获取。 - -### 1. Message - -消息(Message)是 Kafka 中**最基本的数据单元**。 - -Kafka 消息由一个**定长的 Header 和变长的字节数组**组成,其中主要由 key 和 value 构成,key 和 value 也都是字节数组。 - - - -### 2. Broker - -Kafka 集群包含一个或多个服务器,这种服务器被称为 Broker。 - - - -### 3. Topic - -Kafka 根据主题(Topic)对消息进行归类,**发布到 Kafka 集群的每条消息(Message)都需要指定一个 Topic**。 - - - -### 4. Partition - -**物理概念**,每个 Topic 包含一个或多个分区(Partition)。 - -消息发送时都被发送到一个 Topic,其本质就是一个目录,而 Topic 由是由一些 Partition Logs(分区日志)组成,其组织结构如下: - -
- -**每个 Partition 中的消息都是有序的**,生产的消息被不断追加到 Partition Log 上,其中的每一个消息都被赋予了一个唯一的 offset 值,Kafka 通过 **offset 保证消息在分区内的顺序**,offset 的顺序性不跨分区,即 Kafka 只保证在同一个分区内的消息是有序的;同一 Topic 的多个分区内的消息,Kafka 并不保证其顺序性。 - -**Kafka 集群会保存所有的消息,不管消息有没有被消费**; - -我们可以设定消息的过期时间,只有过期的数据才会被自动清除以释放磁盘空间。比如我们设置消息过期时间为 2 天,那么这 2天内的所有消息都会被保存到集群中,数据只有超过了两天才会被清除。 - -Kafka 需要维持的元数据只有一个,即消费消息在 Partition 中的 offset 值,Consumer 每消费一个消息,offset就会 +1。其实消息的状态完全是由 Consumer 控制的,**Consumer 可以跟踪和重设这个 offset 值,Consumer 就可以读取任意位置的消息**。 - -把消息日志以 Partition 的形式存放有多重考虑: - -- 第一,方便在集群中扩展,每个 Partition 可以通过调整以适应它所在的机器,而一个 Topic 又可以由多个Partition 组成,因此整个集群就可以适应任意大小的数据了; -- 第二,就是可以提高并发,因为是以 Partition 为单位进行读写。 - -注意:Partition 并不是越多越好的 - -原因: - -- 分区越多,服务端和客户端需要使用的内存就越多 -- 会降低一定的可用性。某个 Leader 挂了,相比较较少分区的情况,重新选出 Leader,花的时间就会更长。 - - - -### 5. Replication - -Kafka 中每个 Partition 可以有多个副本(Replication),每个副本中包含的消息是一样的。 - -每个分区的副本集合中,都会选举出一个副本作为 Leader 副本,Kafka 在不同的场景下会采用不同的选举策略。所有的读写请求都由选举出的 Leader 副本处理,其他都作为 Follower 副本,**Follower 副本仅仅是从 Leader 副本处把数据拉取(pull)到本地之后,同步更新到自己的 Log 中**。 - -一般情况下,同一分区的多个副本会被分配到不同的 Broker上。当 Leader 所在的 Broker 宕机之后,可以重新选举新的 Leader,继续对外提供服务。 - -
- - - -### 6. Producer - -消息生产者(Producer),向 Broker 发送消息的客户端。 - -Producer 直接发送消息到 Broker上的 Leader Partition,不需要经过任何中介或其他路由转发。 - -**Producer 客户端自己控制着消息被推送(push)到哪些 Partition**。实现方式可以是随机分配、实现一类随机负载均衡算法,或者指定一些分区算法。Kafka 提供了接口供用户实现自定义的 Partition,用户可以为每个消息指定一个 Partition Key,通过这个 key 来实现一些 Hash 分区算法。比如,把 userid 作为 Partition Key 的话,相同 userid 的消息将会被推送到同一个 Partition。 - -Kafka Producer 可以将消息在内存中累计到一定数量后作为一个**批量发送请求**。批量发送的数量大小可以通过Producer 的参数控制,参数值可以设置为累计的消息的数量(如 500 条)、累计的时间间隔(如 100ms )或者累计的数据大小(64 KB)。通过增加 Batch的大小,可以减少网络请求和磁盘 I / O 的次数,当然具体参数设置需要在**效率**和**时效性**方面做一个权衡。 - -Producer 可以**异步地并行地**向 Kafka发送消息,但是通常 Producer 在发送完消息之后会得到一个 future响应,返回的是 offset 值或者发送过程中遇到的错误。通过 request.required.acks 参数来设置 Leader Partition 收到确认的副本个数: - -| ack | 说明 | -| :--: | :----------------------------------------------------------: | -| 0 | Producer **不会等待 Broker 的响应**
Producer 无法知道消息是否发送成功, 这样**可能会导致数据丢失**,但会得到最大的系统吞吐量。 | -| 1 | Producer 会在 **Leader Partition** 收到消息时得到 Broker 的一个确认
这样会有更好的可靠性,因为客户端会等待直到 Broker 确认收到消息。 | -| -1 | Producer 会在**所有备份的 Partition** 收到消息时得到 Broker 的确认
这个设置可以得到最高的可靠性保证。 | - -发布消息时,Kafka Client 先构造一条消息,将消息加入到消息集 set 中(Kafka支持批量发布,可以往消息集合中添加多条消息,一次行发布),send 消息时,Producer Client 需指定消息所属的 Topic。 - - - -### 7. Consumer - -消息消费者(Consumer),从 Broker 读取消息的客户端。 - -消费者(Consumer)的主要工作是从 Topic 中拉取消息,并对消息进行消费。某个消费者消费到 Partition 的哪个位置(offset)的相关信息,是 Consumer 自己维护的。Consumer 可以自己决定如何读取 Kafka 中的数据。比如,Consumer 可以通过重设 offset 值来重新消费已消费过的数据。不管有没有被消费,Kafka 会保存数据一段时间,这个时间周期是可配置的,只有到了过期时间,Kafka 才会删除这些数据。 - -这样设计非常巧妙,**避免了 Kafka Server 端维护消费者消费位置的开销**,尤其是在消费数量较多的情况下。另一方面,如果是由 Kafka Server 端管理每个 Consumer 消费状态,一旦 Kafka Server 端出现延时或是消费状态丢失,将会影响大量的 Consumer。另一方面,这一设计也提高了 Consumer 的灵活性,Consumer 可以按照自己需要的顺序和模式拉取消息进行消费。例如:Consumer 可以通过修改其消费的位置实现针对某些特殊 key 的消息进行反复消费,或是跳过某些消息的需求。 - -Kafka 提供了两套 Consumer Api,分为 Simple Api 和 High-Level Api。 - -- Simple Api 是一个底层的 API,它维持了一个和单一 Broker 的连接,并且这个 API 是完全无状态的,每次请求都需要指定 offset 值,因此,这套 API 也是最灵活的。 - -- High-Level API 封装了对集群中一系列 Broker 的访问,可以透明的消费一个 Topic。它自己维持了已消费消息的状态,即每次消费的都是下一个消息。 - - High-Level API 还支持以组的形式消费 Topic,如果 Consumers 有同一个组名,那么 Kafka 就相当于一个队列消息服务,而各个 Consumer 均衡地消费相应 Partition 中的数据。若 Consumers 有不同的组名,那么此时 Kafka 就相当于一个广播服务,会把 Topic 中的所有消息广播到每个 Consumer。 - -
- - - -### 8. Consumer Group - -在 Kafka 中,多个 Consumer 可以组成一个 Consumer Group,一个 Consumer 只能属于一个 Consumer Group。**Consumer Group 保证其订阅的 Topic 的每个 Partition 只会被此 Consumer Group 中的一个 Consumer 处理**。如果不同 Consumer Group 订阅了同一 Topic,Consumer Group 彼此之间不会干扰。这样,如果要实现一个消息可以被多个消费者同时消费(“广播”)的效果,则将每个消费者放入单独的一个 Consumer Group;如果要实现一个消息只被一个消费者消费(“独占”)的效果,则将所有的 Consumer 放入一个 Consumer Group 中。 - -注意:Consumer Group 中消费者的数量并不是越多越好,当其中消费者数量超过分区的数量时,会导致有消费者分配不到分区,从而造成消费者的浪费。 - -Producer、Consumer 和 Consumer Group 之间的关系: - -
- - - -### 9. Zookeeper - -存放 Kafka 集群相关元数据的组件。在 Zookeeper 集群中会 - -- **保存 Topic 的状态信息**,例如分区的个数、分区的组成、分区的分布情况等; -- **保存 Broker 的状态信息**; -- **保存 Consumer 的消费信息** - -通过这些信息,Kafka 很好地将消息生产、消息存储、消息消费的过程结合起来。 - - - -## Kafka 的拓扑结构 - -### 典型的 Kafka 集群的拓扑结构 - - - -
- - - -Kafka 集群包含若干个 Producer,若干个 Broker (Kafka 集群支持水平扩展,一般 Broker 数量越多,整个 Kafka 集群的吞吐率也就越高),若干个 Consumer Group,以及一个 Zookeeper 集群。 - -Kafka 通过 Zookeeper 管理集群配置。 - -Producer 使用 Push 模式将消息发布到 Broker 上,Consumer 使用 Pull 模式从 Broker 上订阅并消费消息。 - - - -### Kafka 数据流 - -
- -Producers 往 Brokers 中指定的 Topic Push 消息,Consumers 从 Brokers 里面 Pull 指定 Topic 的消息,然后进行业务处理。 - -图中有两个 Topic: - -- Topic-0 有两个 Partition,Partition-0 和 Partition-1; -- Topic-1 有一个 Partition。 - -可以看到 Consumer-Group-1 中的 Consumer-2 没有分到 Partition 处理,这是有可能出现的。 \ No newline at end of file diff --git "a/docs/Kafka/3_Kafka\347\232\204\351\253\230\345\217\257\347\224\250\345\216\237\347\220\206.md" "b/docs/Kafka/3_Kafka\347\232\204\351\253\230\345\217\257\347\224\250\345\216\237\347\220\206.md" deleted file mode 100644 index 4b45a705..00000000 --- "a/docs/Kafka/3_Kafka\347\232\204\351\253\230\345\217\257\347\224\250\345\216\237\347\220\206.md" +++ /dev/null @@ -1,25 +0,0 @@ -# Kafka 的高可用原理 - -Kafka 集群由若干个 Broker 组成,Topic 由若干个 Partition 组成,每个 Partition 可存在不同的 Broker 上。可以这样说,一个 Topic 的数据,分散在多个机器上,即每个机器上都存放一部分数据。 - -## Kafka 0.8 以前 - -Kafka 0.8 以前是没有高可用机制的。 - -假设一个 Topic,由 3 个 Partiton 组成。3 个 Partition 在不同机器上,如果其中某一台机器宕掉了,则 Topic 的部分数据就丢失了。 - -## Kafka 0.8 以后 - -Kafka 0.8 以后,通过**副本机制**来实现高可用。 - -每个 Partition 的数据都会同步到其他机器上,形成多个 Partition 副本。从每个 Partition 的副本集合中,选举出 Leader,其他的都是 Follower。Producer 和 Consumer 就和 Leader 打交道: - -- 写数据时,Leader 会将所用数据都同步到 Follower 上 -- 读数据时,直接读取 Leader 上的数据 - -这样,若某个 Broker 宕机了,Broker 上的 Partition 在其他机器上是有副本的;若宕机的 Broker 上面有某个 Partition 的 Leader,则此时会从 Follower 中重新选择一个新的 Leader 出来。 - -注意:Leader 的读写细节 - -- 写数据时,Producer 向 Leader 写入,接着其他 Follower 主动从 Leader 中 pull 数据,当所有 Follower 同步好数据,就发送确认信息给 Leader,Leader 收到 Follower 的确认后,就返回写成功消息给 Producer。 -- 读数据时,只会从 Leader 中读取,但当只有一个消息已被所有 Follower 都同步成功,返回确认后时,这个消息才被消费者读到。 \ No newline at end of file diff --git "a/docs/Kafka/4_Kafka\344\270\255\344\270\200\344\272\233\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/docs/Kafka/4_Kafka\344\270\255\344\270\200\344\272\233\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index e4ffec07..00000000 --- "a/docs/Kafka/4_Kafka\344\270\255\344\270\200\344\272\233\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,57 +0,0 @@ -# Kafka 中一些常见的问题 - -## 消息丢失问题 - -### 1. 消费端丢失数据 - -默认情况下,Kafka 会自动提交 Offset,Kafka 认为 Consumer 已经处理消息了,但是 Consumer 可能在处理消息的过程中挂掉了。重启系统后,Consumer 会根据提交的 Offset 进行消费,也就丢失了一部分数据。 - -解决:关闭自动提交 Offset,在处理完之后自己手动提交 Offset,就可以保证数据不会丢失。但可能会存在消息重复消费问题。 - - - -### 2. Kafka 丢失数据 - -比较常见的一个场景:Kafka 某个 Broker 宕机,然后重新选举新的 Leader ,但此时其他的 Follower 部分数据尚未同步,结果此时 Leader 挂了,然后选举某个 Follower 成 Leader ,丢失一部分数据。 - -所以此时一般设置如下 4 个参数: - -- Topic 设置 `replication.factor` 参数 - - 参数值必须大于 1,要去每个 Partition 必须有至少 2 个副本。 - -- Kafka 服务端设置 `min.insync.replicas` 参数 - - 参数值必须大于 1,要去每个 Partiton 必须有至少 2 个副本。 - -- Producer 设置 `acks=all` - - 要求每条数据,必须是**写入所有副本,才认为写成功**。 - -- Producer 端设置 `retries=MAX` - - MAX 即是一个超级大的数字,表示无限次重试。`retries=MAX`要求一旦写入数据失败,就无限重试。 - - - -### 3. Producer 丢失数据 - -如果 Producer 端设置了 `acks=all`,则不会丢失数据。 - -Leader 在所有的 Follower 都同步到了消息之后,才认为本次写成功。如果没满足这个条件,生产者会进行无限次重试。 - - - -## 消息重复消费问题 - -### 原理 - -Consumer 消费了数据后,每个一段时间,会将已消费过的消息的 Offset 进行提交,这样,重启后,可以继续从上次消费过的 Offset 来继续消费。测试时,直接 kill 进程,然后再重启后,会导致 Consumer 将有些消息处理了,但是还未来得及提交 Offset,重启后,少数消息会再消费一次。 - -### 解决 - -需要结合具体业务来思考,可从以下几个思路来考虑: - -- 如果要将数据写入数据库中,先根据主键查查询,如果这数据已存在,就不用插入数据了。 -- 向 Redis 中写入数据,可以使用 set,这样数据不会重复 -- 基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。 \ No newline at end of file diff --git "a/docs/Kafka/5_Kafka\347\211\271\347\202\271.md" "b/docs/Kafka/5_Kafka\347\211\271\347\202\271.md" deleted file mode 100644 index 0db5f19f..00000000 --- "a/docs/Kafka/5_Kafka\347\211\271\347\202\271.md" +++ /dev/null @@ -1,78 +0,0 @@ -# Kafka 特点 - -Kafka 特点: - -- 高可用 -- 持久性 -- 数据不易丢失 -- 高吞吐量 - -## Kafka 高可用 - -基于**副本机制**实现 Kafka 的高可用。 - - - -## Kafka 持久性 - -Kafka 集群接收到 Producer 发过来的消息后,将其持久化到磁盘。此外,还支持数据备份。 - - - -## Kafka 数据不易丢失 - -通过合理的配置,Kafka 消息不易丢失。 - - - -## Kafka 高吞吐量 - -Kafka 高吞吐量的原因: - -- 分区 -- 网路传输 -- 顺序读写 -- 零拷贝 - -### 分区 - -当生产者向对应 Topic 传递消息,消息通过**负载均衡机制**传递到不同的 Partition 以减轻单个服务器实例的压力; - -一个 Consumer Group 中可以有多个 Consumer,多个 Consumer 可以同时消费不同 Partition 的消息,大大的提高了消费者的并行消费能力。 - - - -### 网络传输 - -- 批量发送:在发送消息的时候,Kafka 不会直接将少量数据发送出去,否则每次发送少量的数据会增加网络传输频率,降低网络传输效率。Kafka 会先将消息缓存在内存中,当超过一个的大小或者超过一定的时间,那么会将这些消息进行批量发送。 -- 端到端压缩: Kfaka会将这些批量的数据进行压缩,将一批消息打包后进行压缩,发送给 Broker 服务器后,最终这些数据还是提供给消费者用,所以数据在服务器上还是保持压缩状态,不会进行解压,而且频繁的压缩和解压也会降低性能,最终还是以压缩的方式传递到消费者的手上,在 Consumer 端进行解压。 - - - -### 顺序读写 - -Kafka 是个可持久化的日志服务,它将数据以数据日志的形式进行追加,最后持久化在磁盘中。 - -Kafka 消息存储时依赖于**文件系统**。为了利用数据的**局部相关性**:操作系统从磁盘中**以数据块为单位**读取数据,将一个数据块读入内存中,如果有相邻的数据,就不用再去磁盘中读取。所以,在某些情况下,**顺序磁盘访问能比随机内存访问还要快**。同时在写数据的时候也是将一整块数据块写入磁盘中,大大提升 I / O 效率。 - - - -### 零拷贝 - -普通的数据拷贝: - -
- -零拷贝主要的任务是避免 CPU 做大量的数据拷贝任务,减少不必要的拷贝。 - -**内存映射文件(Memory Mapped Files,mmap)**在 64 位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的页缓存来实现文件到物理内存的直接映射。 - -
- -使用 mmap 替代 read 很明显减少了 1 次拷贝,当拷贝数据量很大时,无疑提升了效率。 - - - -# 参考资料 - -- [解密Kafka吞吐量高的原因](https://news.cndns.com/ArticlesDetail/articlesdel/id/9685) \ No newline at end of file diff --git "a/docs/MySQL/1_\351\224\201\346\234\272\345\210\266.md" "b/docs/MySQL/1_\351\224\201\346\234\272\345\210\266.md" index 308ff73b..d3998817 100644 --- "a/docs/MySQL/1_\351\224\201\346\234\272\345\210\266.md" +++ "b/docs/MySQL/1_\351\224\201\346\234\272\345\210\266.md" @@ -50,7 +50,7 @@ - 会出现死锁 - 锁定粒度介于表锁和行锁之间,并发度一般 -
+
diff --git "a/docs/MySQL/2_\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\347\216\260.md" "b/docs/MySQL/2_\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\347\216\260.md" index 1d34445c..575e0580 100644 --- "a/docs/MySQL/2_\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\347\216\260.md" +++ "b/docs/MySQL/2_\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\347\216\260.md" @@ -32,7 +32,7 @@ UPDATE name SET name="c" WHERE id=1; 因为没有使用 `START TRANSACTION` 将上面的操作当成一个事务来执行,根据 MySQL 的 AUTOCOMMIT 机制,每个操作都会被当成一个事务来执行,所以上面的操作总共涉及到三个事务。 -
+
undo log 主要有两个作用: @@ -79,7 +79,7 @@ InnoDB 存储引擎在开启一个新事务后,执行每个 select 语句前 事务可见性示意图: -
+
### 快照读 & 当前读 @@ -159,7 +159,7 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE; 如下图所示: -
+
### 几个问题 @@ -179,7 +179,7 @@ delete from tb where id = 9 根据 id=9 条件定位,此时给 id = 9 的索引加上记录锁,根据 name 值(name是主键)到主索引中检索获得记录,再给该记录加上记录锁。 -
+
> 问题二:间隙锁是否用在非唯一索引的当前读中? @@ -191,7 +191,7 @@ delete from tb1 where id = 9 -- key 是非唯一索引 ``` -
+
可以看出,在 (6,9]、(9,11] 加了间隙锁。 @@ -205,7 +205,7 @@ delete from tb2 where id = 9 -- 没有为 id 建立索引 ``` -
+
此时对所有的间隙都上锁(功能上相当于锁表)。 diff --git "a/docs/MySQL/3_\347\264\242\345\274\225.md" "b/docs/MySQL/3_\347\264\242\345\274\225.md" index d8b1fa1d..b08a6ddf 100644 --- "a/docs/MySQL/3_\347\264\242\345\274\225.md" +++ "b/docs/MySQL/3_\347\264\242\345\274\225.md" @@ -55,7 +55,7 @@ c)非叶子节点的指针:P[1],P[2],... ,P[M];其中 P[1] 指向关键字小于 K[1] 的子树,P[M] 指向关键字大于 K[M-1] 的子树,其他 P[i] 关键字属于(K[i-1],K[i]) 的子树 -
+
### B+ 树 @@ -69,7 +69,7 @@ B+ 树是 B 树的变体,其定义基本与 B 树相同,除了: - 所有叶子节点均有一个链指针指向下一个叶子节点 -
+
数据库系统普遍采用 B+ 树作为索引结构,主要有以下原因: @@ -110,7 +110,7 @@ MySQL 索引使用的是 B 树中的 B+ 树,但索引是在存储引擎层实 MyISAM 引擎使用 B+ 树作索引结构,**叶子节点的 data 域存放的是数据记录的地址**,所有索引均是非聚集索引。 -
+
上图是一个 MyISAM 表的主索引(Primary key)示意图。 @@ -118,7 +118,7 @@ MyISAM 引擎使用 B+ 树作索引结构,**叶子节点的 data 域存放的 在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,而辅助索引的 **key 可以重复**。如果在 Col2 上建立一个辅助索引,则该辅助索引的结构如下: -
+
同样也是一棵 B+ 树,data 域保存数据记录的地址。 @@ -130,7 +130,7 @@ InnoDB 也使用 B+ 树作为索引结构。有且仅有一个聚集索引,和 InnoDB 的数据文件本身就是索引文件。MyISAM 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在 InnoDB 中,表数据文件本身就是按 B+ 树组织的一个索引结构,这棵树的**叶子节点 data 域保存了完整的数据记录**。这个索引的 key 是数据表的主键,因此 **InnoDB 表数据文件本身就是主索引**。 -
+
上图是 InnoDB 主索引(同时也是数据文件)的示意图。可以看到叶子节点包含了完整的数据记录。 @@ -142,7 +142,7 @@ InnoDB 的数据文件本身就是索引文件。MyISAM 索引文件和数据文 与 MyISAM 索引的不同是 **InnoDB 的辅助索引 data 域存储相应记录主键的值**而不是地址。例如,定义在 Col3 上的一个辅助索引: -
+
diff --git "a/docs/MySQL/4_MySQL\346\236\266\346\236\204.md" "b/docs/MySQL/4_MySQL\346\236\266\346\236\204.md" index eea5bfd0..38a768d9 100644 --- "a/docs/MySQL/4_MySQL\346\236\266\346\236\204.md" +++ "b/docs/MySQL/4_MySQL\346\236\266\346\236\204.md" @@ -12,7 +12,7 @@ 主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。**现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始就被当做默认存储引擎了**。 -
+
diff --git "a/docs/MySQL/5_MySQL\344\274\230\345\214\226.md" "b/docs/MySQL/5_MySQL\344\274\230\345\214\226.md" index 339723de..d470d532 100644 --- "a/docs/MySQL/5_MySQL\344\274\230\345\214\226.md" +++ "b/docs/MySQL/5_MySQL\344\274\230\345\214\226.md" @@ -1,4 +1,4 @@ -# MySQL 优化 +# MySQL 调优 ## SQL 语句优化 diff --git "a/docs/MySQL/6_MySQL\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/docs/MySQL/6_MySQL\346\225\260\346\215\256\347\261\273\345\236\213.md" index e55b7d56..b15db3d3 100644 --- "a/docs/MySQL/6_MySQL\346\225\260\346\215\256\347\261\273\345\236\213.md" +++ "b/docs/MySQL/6_MySQL\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -24,7 +24,7 @@ VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内 MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。 -### 1. DATETIME +### DATETIME 能够保存从 1000 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。 @@ -32,7 +32,7 @@ MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。 默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATETIME 值,例如“2008-01-16 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。 -### 2. TIMESTAMP +### TIMESTAMP 和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年到 2038 年。 @@ -50,7 +50,24 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 - TIMESTAMP 只需要使用 4 个字节的存储空间,但 DATETIME 需要耗费 8 个字节的存储空间。但是,这样同样造成了一个问题,TIMESTAMP 表示的时间范围更小。 - - DATETIME :1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 - - TIMESTAMP: 1970-01-01 00:00:01 ~ 2037-12-31 23:59:59 + - DATETIME :`1000-01-01 00:00:00 ~ 9999-12-31 23:59:59` + - TIMESTAMP: `1970-01-01 00:00:00 ~ 2037-12-31 23:59:59` 注意 5.6.4 之后的 MySQL 多出了一个需要 0 ~ 3 字节的小数位。DATETIME 和 TIMESTAMP 会有几种不同的存储空间占用。 + +### 数值型时间戳 + +时间戳的定义是从一个基准时间 [ 1970-1-1 00:00:00 +0:00 ] 开始算起,用整数表示,以秒计时,随着时间的流逝这个时间整数不断增加。 + +一个数值,就可以完美地表示时间了,而且这个数值是一个绝对数值,即无论的身处地球的任何角落,这个表示时间的时间戳,都是一样的,生成的数值都是一样的,并且没有时区的概念。 + +MySQL 中可以使用 int 或者 bigint 类型的时间戳来表示时间。 + +小结: + +| 日期类型 | 存储空间 | 日期格式 | 日期范围 | 时区问题 | +| --------- | -------- | ------------------- | ---------------------------------------------- | -------- | +| DATETIME | 8 字节 | yyyy-MM-dd HH:mm:ss | 1000-01-01 00:00:00 ~
9999-12-31 23:59:59 | 存在 | +| TIMESTAMP | 4 字节 | yyyy-MM-dd HH:mm:ss | 1970-01-01 00:00:00 ~
2037-12-31 23:59:59 | 不存在 | +| 时间戳 | 4 字节 | 数值 | 1970-01-01 00:00:00 之后的时间 | 不存在 | + diff --git "a/docs/MySQL/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" "b/docs/MySQL/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" deleted file mode 100644 index c80a19fb..00000000 --- "a/docs/MySQL/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" +++ /dev/null @@ -1,34 +0,0 @@ -# 主流消息中间件 - -## 1. ActiveMQ - -ActiveMQ 是 Apache 出品的最流行的、性能强劲的开源消息总线,并且其是一个完全支持 JMS 规范的消息中间件。其丰富的 API、多种集群构建模式使得它成为业界老牌消息中间件,广泛应用于中小型企业。 - -## 2. Kafka - -Kafka 是 LinkedIn 开源的分布式发布-订阅消息系统,目前属于 Apache 顶级项目。 - -Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8 版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。 - -## 3. RocketMQ - -RocketMQ 是阿里开源的消息中间件,目前也已经孵化为 Apache 顶级项目,它是纯 Java 开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。 - -RocketMQ 思路起源于 Kafka,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog 分发等场景。 - -## 4. RabbitMQ - -RabbitMQ 是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。 - -AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP 协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。 - -## 对比 - -| 消息中间件 | ActiveMQ | Kafka | RocketMQ | RabbitMQ | -| :----------------------: | :-----------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :------------------------------------------------: | -| *吞吐量* | 万数量级 | 十万级,高吞吐 | 十万级,高吞吐 | 万数量级 | -| *Topic 数量对吞吐量影响* | / | Topic 从几十到几百时,吞吐量会大幅度下降,
在同等机器下,Kafka 尽量保证 Topic 数量不要过多,如果要支撑大规模的 Topic,需要增加更多的机器 | Topic 可达百/千级,吞吐量下降幅度小
在同等机器下,可以支撑大量的 Topic | / | -| *时效性* | 毫秒级 | 毫秒级 | 毫秒级 | 微秒级 | -| *可用性* | 高
基于主从架构实现高可用高 | 非常高
分布式架构 | 非常高
分布式架构 | 高
基于主从架构实现高可用高 | -| *可靠性* | 丢失数据的概率低 | 优化参数配置,
可以做到零丢失 | 优化参数配置,
可以做到零丢失 | 基本不会丢失数据 | -| *功能* | 功能较完备 | 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用 | MQ 功能较为完善,还是分布式的,扩展性好 | 基于 ErLang 开发,并发能力很强,性能极好,延时很低 | \ No newline at end of file diff --git "a/docs/MySQL/RabbitMQ/2_RabbitMQ\346\225\264\345\220\210SpringBoot.md" "b/docs/MySQL/RabbitMQ/2_RabbitMQ\346\225\264\345\220\210SpringBoot.md" deleted file mode 100644 index e69de29b..00000000 diff --git "a/docs/MySQL/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" "b/docs/MySQL/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" deleted file mode 100644 index 4945be10..00000000 --- "a/docs/MySQL/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" +++ /dev/null @@ -1,76 +0,0 @@ -# RabbitMQ 概述 - -## 简介 - -RabbitMQ 是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用中间共享数据,RabbitMQ 是使用 **Erlang 语言**来编写的,并且 RabbitMQ 是基于 AMQP 协议的。 - -特点: - -- 开源、性能优秀,稳定性好 -- 提供可靠性消息投递模式(confirm)、返回模式(return) -- 与 SpringAOP 完美的整合、API 丰富 -- 集群模式丰富,表达式配置,HA 模式,镜像队列模型 -- 保证数据不丢失的前提做到高可靠性、可用性 - -RabbitMQ 高性能的原因: - -**Erlang 语言**最初用在交换机的架构模式,这样使得 RabbitMQ 在 Broker 之间进行数据交互的性能时非常优秀的。Erlang 的优点:Erlang 有着和原生 Socket 一样的延迟。 - -## AMQP 协议 - -AMQP(Advanced Message Queuing Protocol)协议,即高级消息队列协议。 - -AMQP 是具有现在特征的二进制协议。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。 - -### 协议模型 - - - -### 核心概念 - - - - - -![1574044351197](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574044351197.png) - - - - - -![1574044966299](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574044966299.png) - - - - - -![1574045181833](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045181833.png) - - - -![1574045266808](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045266808.png) - -![1574045345331](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045345331.png) - -![1574045528395](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045528395.png) - -![1574045635960](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045635960.png) - - - -![1574045733769](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045733769.png) - - - -![1574044393028](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574044393028.png) - -![1574045701316](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045701316.png) - - - -![1574045865612](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574045865612.png) - - - -![1574044458688](C:\Users\DHA\AppData\Roaming\Typora\typora-user-images\1574044458688.png) - diff --git "a/docs/MySQL/RabbitMQ/3_\346\266\210\346\201\257\345\217\257\351\235\240\346\200\247\346\212\225\351\200\222\347\232\204\350\247\243\345\206\263\346\226\271\346\241\210\345\256\236\347\216\260.md" "b/docs/MySQL/RabbitMQ/3_\346\266\210\346\201\257\345\217\257\351\235\240\346\200\247\346\212\225\351\200\222\347\232\204\350\247\243\345\206\263\346\226\271\346\241\210\345\256\236\347\216\260.md" deleted file mode 100644 index e69de29b..00000000 diff --git "a/docs/MySQL/\345\210\207\345\210\206\345\244\215\345\210\266\351\227\256\351\242\230.md" "b/docs/MySQL/\345\210\207\345\210\206\345\244\215\345\210\266\351\227\256\351\242\230.md" new file mode 100644 index 00000000..b8567dd9 --- /dev/null +++ "b/docs/MySQL/\345\210\207\345\210\206\345\244\215\345\210\266\351\227\256\351\242\230.md" @@ -0,0 +1,8 @@ +# 一、切分 + + + + + +# 二、复制 + diff --git "a/docs/OO/2_\345\210\233\345\273\272\345\236\213.md" "b/docs/OO/2_\345\210\233\345\273\272\345\236\213.md" index 35a293b4..27f2ac57 100644 --- "a/docs/OO/2_\345\210\233\345\273\272\345\236\213.md" +++ "b/docs/OO/2_\345\210\233\345\273\272\345\236\213.md" @@ -12,7 +12,7 @@ 私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。 -

+

### Implementation @@ -279,7 +279,7 @@ public class Singleton { 客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 -

+

### Implementation @@ -376,7 +376,7 @@ public class Client { 下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。该方法是抽象的,需要由子类去实现。 -

+

### Implementation @@ -440,7 +440,7 @@ public class ConcreteFactory2 extends Factory { 从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。 -

+

### Implementation @@ -536,7 +536,7 @@ public class Client { 当然,光有指导者是不够的,必须要有能具体实现每步的对象,在生成器模式中称这些实现对象为**生成器**。 这样一来,**指导者就是可以重用的构建过程,而生成器是可以被切换的具体实现**。 -

+

### Implementation1 @@ -746,7 +746,7 @@ public class Client { 生成器的调用顺序: -

+

### Implementation2 @@ -836,7 +836,7 @@ abcdefghijklmnopqrstuvwxyz ### Class Diagram -

+

### Implementation diff --git "a/docs/OO/3_\350\241\214\344\270\272\345\236\213.md" "b/docs/OO/3_\350\241\214\344\270\272\345\236\213.md" index 9b5f8286..e91dd3cc 100644 --- "a/docs/OO/3_\350\241\214\344\270\272\345\236\213.md" +++ "b/docs/OO/3_\350\241\214\344\270\272\345\236\213.md" @@ -11,7 +11,7 @@ - Handler:定义处理请求的接口,并且实现后继链(successor) -

+

### Implementation @@ -158,7 +158,7 @@ request-2 is handle by ConcreteHandler2 - Invoker:通过它来调用命令 - Client:可以设置命令与命令的接收者 -

+

### Implementation1 ```java @@ -232,7 +232,7 @@ public class Client { 设计一个遥控器,可以控制电灯开关。 -

+

```java public interface Command { @@ -349,7 +349,7 @@ public class Client { - TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression。 - Context:上下文,包含解释器之外的一些全局信息。 -

+

### Implementation @@ -482,7 +482,7 @@ false - Iterator 主要定义了 hasNext() 和 next() 方法。 - Client 组合了 Aggregate,为了迭代遍历 Aggregate,也需要组合 Iterator。 -

+

### Implementation @@ -571,17 +571,17 @@ public class Client { - Mediator:中介者,定义一个接口用于与各同事(Colleague)对象通信。 - Colleague:同事,相关对象 -

+

### Implementation Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时需要去操作其它对象,形成了下面这种依赖结构: -

+

使用中介者模式可以将复杂的依赖结构变成星形结构: -

+

```java public abstract class Colleague { @@ -744,7 +744,7 @@ doSprinkler() 备忘录实际上有两个接口,一个是提供给 Caretaker 的窄接口:它只能将备忘录传递给其它对象; 一个是提供给 Originator 的宽接口,允许它访问到先前状态所需的所有数据。理想情况是只允许 Originator 访问本备忘录的内部状态。 -

+

### Implementation @@ -916,7 +916,7 @@ public class Client { 主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。 -

+

### Class Diagram @@ -924,13 +924,13 @@ public class Client { 观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。 -

+

### Implementation 天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。 -

+

```java public interface Subject { @@ -1059,7 +1059,7 @@ State:状态接口,用来封装与上下文的**一个特定状态所对应 ConcreteState:具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理。 -

+

### Implementation1 实现在线投票: @@ -1080,7 +1080,7 @@ ConcreteState:具体实现状态处理的类,每个类实现一个跟上下 程序结构如下图: -

+

```java /** @@ -1213,7 +1213,7 @@ public class Client { 糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。 -

+

```java public interface State { @@ -1514,7 +1514,7 @@ No gumball dispensed - Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。 - Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。 -

+

### 与状态模式的比较 @@ -1535,7 +1535,7 @@ No gumball dispensed 2. 对老客户报的价格,根据客户年限,给予一定的折扣 3. 对大客户报的价格,根据大客户的累计消费金额,给予一定的折扣 -

+

```java /** @@ -1702,13 +1702,13 @@ squeak! ### Class Diagram -

+

### Implementation 冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。 -

+

```java public abstract class CaffeineBeverage { @@ -1805,7 +1805,7 @@ Tea.addCondiments - ConcreteVisitor:具体访问者,存储遍历过程中的累计结果 - ObjectStructure:对象结构,可以是组合结构,或者是一个集合。 -

+

### Implementation @@ -2010,7 +2010,7 @@ Number of items: 6 ### Class Diagram -

+

### Implementation diff --git "a/docs/OO/4_\347\273\223\346\236\204\345\236\213.md" "b/docs/OO/4_\347\273\223\346\236\204\345\236\213.md" index 4839eb59..f3144f52 100644 --- "a/docs/OO/4_\347\273\223\346\236\204\345\236\213.md" +++ "b/docs/OO/4_\347\273\223\346\236\204\345\236\213.md" @@ -6,7 +6,7 @@ 把一个类接口转换成另一个用户需要的接口。 -

+

### Class Diagram Target:定义客户端需要的跟特定领域相关的接口。 @@ -16,7 +16,7 @@ Adaptee:已经存在的接口,通常能满足客户端的功能要求, Adapter:适配器,把Adaptee适配成为Client需要的Target。 -

+

### Implementation1 美国的电饭煲是在电压为 110V 下工作,而中国的电饭煲在电压 220V 下工作。要求将在美国使用的电饭煲适配成能在中国使用。 @@ -182,7 +182,7 @@ public class Client { - Abstraction:定义抽象类的接口 - Implementor:定义实现类接口 -

+

### Implementation @@ -343,7 +343,7 @@ Composite:组合对象,通常会存储子组件,定义包含子组件的 组合对象拥有一个或者多个组件对象,因此组合对象的操作可以委托给组件对象去处理,而组件对象可以是另一个组合对象或者叶子对象。 -

+

### Implementation1 商品类别树的管理,比如有如下所示的商品类别树: @@ -640,7 +640,7 @@ public class Client { 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。 -

+

### Implementation1 给普通手机装饰上彩铃等功能。 @@ -778,7 +778,7 @@ IPhone打电话 下图表示在 DarkRoast 饮料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它们都继承自相同父类,都有 cost() 方法,外层类的 cost() 方法调用了内层类的 cost() 方法。 -

+

```java public interface Beverage { @@ -883,7 +883,7 @@ public class Client { ### Class Diagram -

+

### Implementation @@ -942,7 +942,7 @@ public class Client { - IntrinsicState:内部状态,享元对象共享内部状态 - ExtrinsicState:外部状态,每个享元对象的外部状态不同 -

+

### Implementation @@ -1042,7 +1042,7 @@ Java 利用缓存来加速大量小对象的访问时间。 - RealSubject:具体的目标对象,真正实现目标接口要求的功能。 -

+

### Implementation diff --git "a/docs/OO/6_\345\205\263\347\263\273\347\261\273\345\233\276.md" "b/docs/OO/6_\345\205\263\347\263\273\347\261\273\345\233\276.md" index f7c1fa10..a0532acf 100644 --- "a/docs/OO/6_\345\205\263\347\263\273\347\261\273\345\233\276.md" +++ "b/docs/OO/6_\345\205\263\347\263\273\347\261\273\345\233\276.md" @@ -6,7 +6,7 @@ 用来描述继承关系,在 Java 中使用 extends 关键字。 -

+

```text @startuml @@ -27,7 +27,7 @@ Vihical <|-- Trunck 用来实现一个接口,在 Java 中使用 implements 关键字。 -

+

```text @startuml @@ -48,7 +48,7 @@ MoveBehavior <|.. Run 表示整体由部分组成,但是整体和部分不是强依赖的,整体不存在了部分还是会存在。 -

+

```text @startuml @@ -71,7 +71,7 @@ Computer o-- Screen 和聚合不同,组合中整体和部分是强依赖的,整体不存在了部分也不存在了。比如公司和部门,公司没了部门就不存在了。但是公司和员工就属于聚合关系了,因为公司没了员工还在。 -

+

```text @startuml @@ -92,7 +92,7 @@ Company *-- DepartmentB 表示不同类对象之间有关联,这是一种静态关系,与运行过程的状态无关,在最开始就可以确定。因此也可以用 1 对 1、多对 1、多对多这种关联关系来表示。比如学生和学校就是一种关联关系,一个学校可以有很多学生,但是一个学生只属于一个学校,因此这是一种多对一的关系,在运行开始之前就可以确定。 -

+

```text @startuml @@ -115,7 +115,7 @@ School "1" - "n" Student - A 类是 B 类方法当中的一个参数; - A 类向 B 类发送消息,从而影响 B 类发生变化。 -

+

```text @startuml diff --git a/docs/README.md b/docs/README.md index 8a522bbe..03951a42 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,6 +28,7 @@ - [JVM 调优](JVM/4_JVM调优.md) - [类文件结构](JVM/5_类文件结构.md) - [类加载机制](JVM/6_类加载机制.md) +- [Java 程序编译和运行过程](JVM/7_Java程序编译和运行过程.md) ## Java 并发 @@ -68,9 +69,9 @@ # 📝 编程题 -## 数据结构相关 +## 数据结构系列 -- [数组和矩阵](AimForOffer/数据结构相关/1_数组和矩阵.md) +- [数组 & 矩阵](AimForOffer/数据结构相关/1_数组和矩阵.md) - [字符串](AimForOffer/数据结构相关/2_字符串.md) - [链表](AimForOffer/数据结构相关/3_链表.md) - [树](AimForOffer/数据结构相关/4_树.md) @@ -79,7 +80,7 @@ - [堆](AimForOffer/数据结构相关/7_堆.md) - [ 哈希.](AimForOffer/数据结构相关/8_哈希.md) -## 算法相关 +## 算法思维系列 - [查找](AimForOffer/算法思想相关/1_查找.md) - [排序](AimForOffer/算法思想相关/2_排序.md) @@ -110,6 +111,7 @@ - [MySQL架构](MySQL/4_MySQL架构.md) - [MySQL优化](MySQL/5_MySQL优化.md) - [MySQL数据类型](MySQL/6_MySQL数据类型.md) +- [切分 & 复制问题](MySQL/切分复制问题.md) - [补充知识](MySQL/6_补充知识.md) ## Redis @@ -121,64 +123,101 @@ - [Redis 持久化机制](Redis/5_持久化机制.md) - [Redis 事务](Redis/6_事务.md) - [缓存问题](Redis/7_缓存问题.md) +- [Redis 部署方式](Redis/8_部署方式.md) +- [Redis 实战](Redis/9_实战.md) -# ☎️ 常用框架 +# 🎓 系统设计 -## Spring +- [系统设计基础](1_基础.md) -## SpringCloud +## 安全性 -## Zookeeper +- [Cookie & Session &Token](Safety/Cookie_Session_Token.md) +- [常见攻击技术及防御](Safety/常见攻击技术及防御.md) -## Kafka +## 分布式 -## ElasticSearch +- [分布式系统基本概念](distribution/1_分布式系统设计理念.md) +- [CAP 理论 & BASE 理论](distribution/2_CAP理论.md) +- [分布式锁](distribution/3_分布式锁.md) +- [分布式事务](distribution/4_分布式事务.md) +- [Paxos 算法 & Raft 算法](distribution/5_Paxos算法.md) -# 📖 系统设计 +## 集群 -## Web 安全 +- [负载均衡](cluster/1_负载均衡.md) +- [集群下的 Session 管理](cluster/2_集群下的Session管理.md) -- [常见安全问题](Safety/1_常见安全问题.md) -- [跨站脚本攻击](Safety/2_跨站脚本攻击.md) -- [跨站请求伪造](Safety/3_跨站请求伪造.md) -- [Cookies问题](Safety/4_Cookies问题.md) -- [点击劫持问题](Safety/5_点击劫持问题.md) -- [传输安全](Safety/6_传输安全.md) -- [密码安全](Safety/7_密码安全.md) -- [接入层注入问题](Safety/8_接入层注入问题.md) -- [接入层上传问题](Safety/9_接入层上传问题.md) -- [信息泄露](Safety/10_信息泄露.md) -- [DoS攻击](Safety/11_DoS攻击.md) -- [重放攻击](Safety/12_重放攻击.md) +## 缓存 -## 分布式 +- [缓存需要考虑的问题](cache/1_缓存需要考虑的问题.md) +- [缓存常见问题](cache/2_缓存常见问题.md) +- [数据分布](cache/3_数据分布.md) -- [分布式系统设计理念](distribution/1_分布式系统设计理念.md) -- [CAP理论](distribution/2_CAP理论.md) -- [BASE理论](distribution/3_BASE理论.md) -- [分布式锁](distribution/4_分布式锁.md) -- [分布式事务](distribution/5_分布式事务.md) -- [分布式缓存的一致性哈希算法](distribution/6_分布式缓存的一致性哈希算法.md) +## 消息队列 -## 网站架构 +- [消息队列](1_消息队列.md) +- [Kafka 原理及应用](Kafka&RabbitMQ/Kafka.md) +- [RabbitMQ 原理及应用](Kafka&RabbitMQ/RabbitMQ.md) +- [Kafka & RabbitMQ 比较](Kafka&RabbitMQ/Kafka_RabbitMQ.md) -- [网站架构](web_architecture/1_网站架构.md) -- [设计秒杀系统](web_architecture/2_设计秒杀系统.md) +# ☎️ 常用框架 -# 💪 工具 +## Spring + +- [Spring 概述](Spring/1_Spring概述.md) +- [Spring IoC 原理](Spring/2_SpringIoC原理.md) +- [Spring AOP 原理](Spring/3_SpringAOP原理.md) +- [Spring MVC 原理](Spring/4_SpringMVC原理.md) +- [Spring 事务管理](Spring/5_Spring事务管理.md) +- [Spring 中用到的设计模式](Spring/6_Spring中用到的设计模式.md) +- [MyBatis](Spring/7_MyBatis.md) + +## SpringBoot + +- [SpringBoot 概述](SpringBoot/1_SpringBoot概述.md) +- [配置文件](SpringBoot/2_配置文件.md) +- [常用注解](SpringBoot/3_常用注解.md) +- [请求参数校验](SpringBoot/4_请求参数校验.md) +- [全局异常处理](SpringBoot/5_全局异常处理.md) +- [实现定时任务](SpringBoot/6_实现定时任务.md) + +## Zookeeper + +- [Zookeeper 概述](Zookeeper/1_概述.md) +- [Zookeeper 数据模型](Zookeeper/2_数据模型.md) +- [Zookeeper 的原理](Zookeeper/3_原理.md) +- [Zookeeper 的应用](Zookeeper/4_应用.md) + +# 📖 工具 ## Git - [git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) - [git - 图解](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) +- [github - 小技巧](https://snailclimb.gitee.io/javaguide/#/docs/tools/Github%E6%8A%80%E5%B7%A7) -## Github +## Docker -- [github - 小技巧](https://snailclimb.gitee.io/javaguide/#/docs/tools/Github%E6%8A%80%E5%B7%A7) +- [Docker 概述](https://snailclimb.gitee.io/javaguide/#/docs/tools/Docker) +- [Docker 实战](https://snailclimb.gitee.io/javaguide/#/docs/tools/Docker%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98) # 📚 参考资料 -- [小专栏](reference/小专栏.md) -- [参考仓库](reference/参考仓库.md) -- [参考书籍](reference/参考书籍.md) -- [慕课网](reference/慕课网.md) +## 参考仓库 + +- [Java 基础知识](reference/Java基础_1.md) +- [Java 进阶知识](reference/Java进阶_1.md) +- [编程题](reference/编程题_1.md) + +## 参考书籍 + +- [Java 基础](reference/Java基础_2.md) +- [编程题](reference/编程题_2.md) +- [数据库](reference/数据库.md) +- [常用框架](reference/常用框架.md) + +## 小专栏 + +- [后端面试进阶指南](https://xiaozhuanlan.com/CyC2018) +- [Java 面试进阶指南](https://xiaozhuanlan.com/javainterview) \ No newline at end of file diff --git a/docs/README_1.md b/docs/README_1.md deleted file mode 100644 index d6b5618f..00000000 --- a/docs/README_1.md +++ /dev/null @@ -1,324 +0,0 @@ -# ✏️ 计算机基础 - -🌐 `:globe_with_meridians:` - -| 🚀 `:rocket:` | ✈️ `:airplane:` | 🚁 `:helicopter:` | -| ------------ | -------------- | ---------------- | -| | | | - - - -## 🌐 计算机网络 - -- [概述](Net/1_概述.md) -- [物理层](Net/2_物理层.md) -- [数据链路层](Net/3_数据链路层.md) -- [网络层](Net/4_网络层.md) -- [运输层](Net/5_运输层.md) -- [应用层](Net/6_应用层.md) - -## 🌐 操作系统 - -- [第一节 操作系统概述](OS/1_操作系统概述.md) -- [第二节 进程管理](OS/2_进程管理.md) -- [第三节 死锁](OS/3_死锁.md) -- [第四节 内存管理](OS/4_内存管理.md) -- [第五节 设备管理](OS/4_设备管理.md) -- [第六节 链接](OS/6_链接.md) - -## 🌐 数据结构和算法 - -- [第一节 概述](data_structure/1_概述.md) -- [第二节 线性表](data_structure/2_线性表.md) -- [第三节 栈和队列](data_structure/3_栈和队列.md) -- [第四节 树](data_structure/4_树.md) -- [第五节 图](data_structure/5_图.md) -- [第六节 集合和映射](data_structure/6_集合和映射.md) -- [第七节 并查集](data_structure/7_并查集.md) -- [第八节 优先队列和堆](data_structure/8_优先队列和堆.md) -- [第九节 哈希表](data_structure/9_哈希表.md) -- [第十节 排序](data_structure/10_排序.md) -- [第十一节 线段树](data_structure/11_线段树.md) -- [第十二节 Trie树](data_structure/12_Trie树.md) -- [第十三节 AVL](data_structure/13_AVL.md) -- [第十四节 红黑树](data_structure/14_红黑树.md) - -## 🌐 HTTP - -- [第一节 HTTP概述](HTTP/1_HTTP概述.md) -- [第二节 HTTP状态码](HTTP/2_HTTP状态码.md) -- [第三节 具体应用](HTTP/3_具体应用.md) -- [第四节 HTTPS](HTTP/4_HTTPS.md) -- [第五节 get和post比较](HTTP/5_get和post比较.md) - -## 🌐 Linux - -- [第一节 Linux概论](Linux/1_Linux概论.md) -- [第二节 Linux文件系统](Linux/2_Linux文件系统.md) -- [第三节 Linux常用命令](Linux/3_Linux常用命令.md) -- [第四节 Liunx进程管理](Linux/4_Liunx进程管理.md) -- [第五节 Linux压缩与打包](Linux/5_Linux压缩与打包.md) - -# ☕️ Java - -## 🌈 Java 基础 - -- [第一节 数据类型](JavaBasics/1_数据类型.md) -- [第二节 String](JavaBasics/2_String.md) -- [第三节 运算](JavaBasics/3_运算.md) -- [第四节 Object通用方法](JavaBasics/4_Object通用方法.md) -- [第五节 关键字](JavaBasics/5_关键字.md) -- [第六节 反射](JavaBasics/6_反射.md) -- [第七节 异常](JavaBasics/7_异常.md) -- [第八节 泛型](JavaBasics/8_泛型.md) -- [第九节 注解](JavaBasics/9_注解.md) -- [第十节 Java常见对象](JavaBasics/10_Java常见对象.md) -- [第十一节 抽象类和接口](JavaBasics/11_抽象类和接口.md) -- [第十二节 其他](JavaBasics/12_其他.md) - -## 🌈 Java 容器 - -- [第一节 Java容器概览](JavaContainer/1_Java容器概览.md) -- [第二节 容器中的设计模式](JavaContainer/2_容器中的设计模式.md) -- [第三节 容器源码分析 - List](JavaContainer/3_容器源码分析%20-%20List.md) -- [第四节 容器源码分析 - Map](JavaContainer/4_容器源码分析%20-%20Map.md) -- [第五节 容器源码分析 - 并发容器](JavaContainer/5_容器源码分析%20-%20并发容器.md) - -## 🌈 Java 虚拟机 - -- [第一节 运行时数据区域](JVM/1_JVM.md) -- [第二节 HotSpot 虚拟机对象](JVM/2_JVM.md) -- [第三节 String 类和常量池](JVM/3_JVM.md) -- [第四节 8 种基本类型的包装类和常量池](JVM/4_JVM.md) -- [第五节 垃圾收集](JVM/5_JVM.md) -- [第六节 内存分配与回收策略](JVM/6_JVM.md) -- [第七节 类加载机制](JVM/7_JVM.md) - -## 🌈 Java 并发 - -- [第一节 基础知识](Java_Concurrency/1_基础知识.md) -- [第二节 并发理论](Java_Concurrency/2_并发理论.md) -- [第三节 并发关键字](Java_Concurrency/3_并发关键字.md) -- [第四节 Lock 体系](Java_Concurrency/4_Lock%20体系.md) -- [第五节 原子操作类](Java_Concurrency/5_原子操作类.md) -- [第六节 并发容器](Java_Concurrency/6_并发容器.md) -- [第七节 并发工具](Java_Concurrency/7_并发工具.md) -- [第八节 线程池](Java_Concurrency/8_线程池.md) -- [第九节 并发实践](Java_Concurrency/9_并发实践.md) - -## 🌈 JavaIO - -- [第一节 概览](JavaIO/1_概览.md) -- [第二节 磁盘操作](JavaIO/2_磁盘操作.md) -- [第三节 字节操作](JavaIO/3_字节操作.md) -- [第四节 字符操作](JavaIO/4_字符操作.md) -- [第五节 对象操作](JavaIO/5_对象操作.md) -- [第六节 网络操作](JavaIO/6_网络操作.md) -- [第七节 NIO](JavaIO/7_NIO.md) -- [第八节 JavaIO方式](JavaIO/8_JavaIO方式.md) - -## 🌈 正则表达式 - -- [第一节 概述](Regex/1_概述.md) -- [第二节 应用](Regex/2_应用.md) - -# 👫 面向对象 - -## 🚩 设计模式 - -- [第一节 概述](OO/1_概述.md) -- [第二节 创建型](OO/2_创建型.md) -- [第三节 行为型](OO/3_行为型.md) -- [第四节 结构型](OO/4_结构型.md) - -## 🚩 面向对象思想 - -- [第一节 面向对象三大特性](OO/5_面向对象三大特性.md) -- [第二节 关系类图](OO/6_关系类图.md) -- [第三节 面向对象设计原则](OO/7_面向对象设计原则.md) - -# 📝 编程题 - -## 🚀 剑指 Offer 编程题 - -> **数据结构相关** - -- [第一节 数组和矩阵](AimForOffer/数据结构相关/1_数组和矩阵.md) -- [第二节 字符串](AimForOffer/数据结构相关/2_字符串.md) -- [第三节 链表](AimForOffer/数据结构相关/3_链表.md) -- [第四节 树](AimForOffer/数据结构相关/4_树.md) -- [第五节 栈](AimForOffer/数据结构相关/5_栈.md) -- [第六节 队列](AimForOffer/数据结构相关/6_队列.md) -- [第七节 堆](AimForOffer/数据结构相关/7_堆.md) -- [第八节 哈希.](AimForOffer/数据结构相关/8_哈希.md) - -> **算法相关** - -- [第一节 查找](AimForOffer/算法思想相关/1_查找.md) -- [第二节 排序](AimForOffer/算法思想相关/2_排序.md) -- [第三节 动态规划](AimForOffer/算法思想相关/3_动态规划.md) -- [第四节 搜索](AimForOffer/算法思想相关/4_搜索.md) -- [第五节 排列组合](AimForOffer/算法思想相关/5_排列组合.md) -- [第六节 贪心](AimForOffer/算法思想相关/6_贪心.md) -- [第七节 数学运算](AimForOffer/算法思想相关/7_数学运算.md) -- [第八节 其他](AimForOffer/算法思想相关/8_其他.md) - -## 🚀 LeetCode 编程题 - -> **数据结构相关** - -- [第一节 数组问题](LeetCode/数据结构相关/1_数组问题.md) -- [第二节 链表问题](LeetCode/数据结构相关/2_链表问题.md) -- [第三节 栈和队列](LeetCode/数据结构相关/3_栈和队列.md) -- [第四节 二叉树](LeetCode/数据结构相关/4_二叉树.md) -- [第五节 字符串](LeetCode/数据结构相关/5_字符串.md) -- [第六节 哈希](LeetCode/数据结构相关/6_哈希.md) -- [第七节 图](LeetCode/数据结构相关/7_图.md) -- [第八节 数据结构设计](LeetCode/数据结构相关/8_数据结构设计.md) - -> **算法思想相关** - -- [第一节 排序](LeetCode/算法思想相关/1_排序.md) -- [第二节 分治思想](LeetCode/算法思想相关/2_分治思想.md) -- [第三节 贪心思想](LeetCode/算法思想相关/3_贪心思想.md) -- [第四节 LRU](LeetCode/算法思想相关/4_LRU.md) -- [第五节 DFS](LeetCode/算法思想相关/5_DFS.md) -- [第六节 回溯法](LeetCode/算法思想相关/6_回溯法.md) -- [第七节 动态规划](LeetCode/算法思想相关/7_动态规划.md) -- [第八节 数学问题](LeetCode/算法思想相关/8_数学问题.md) - -# 💾 数据库 - -## ✈️ DataBase - -- [第一节 数据库系统原理](DataBase/1_数据库系统原理.md) -- [第二节 关系数据库设计理论](DataBase/2_关系数据库设计理论.md) -- [第三节 设计关系型数据库](DataBase/3_设计关系型数据库.md) -- [第四节 SQL](DataBase/4_SQL.md) -- [第五节 LeetCode_Database题解](DataBase/5_LeetCode_Database题解.md) - -## ✈️ MySQL - -- [第一节 锁机制](MySQL/1_锁机制.md) -- [第二节 事务隔离级别实现](MySQL/2_事务隔离级别实现.md) -- [第三节 索引](MySQL/3_索引.md) -- [第四节 MySQL架构](MySQL/4_MySQL架构.md) -- [第五节 MySQL优化](MySQL/5_MySQL优化.md) -- [第六节 补充知识](MySQL/6_补充知识.md) - -## ✈️ Redis - -- [第一节 Redis初探](Redis/1_Redis初探.md) -- [第二节 Redis持久化](Redis/2_Redis持久化.md) -- [第三节 Redis复制](Redis/3_Redis复制.md) -- [第四节 处理系统故障](Redis/4_处理系统故障.md) -- [第五节 Redis事务](Redis/5_Redis事务.md) -- [第六节 Redis性能方面注意事项](Redis/6_Redis性能方面注意事项.md) -- [第七节 降低内存占用](Redis/7_降低内存占用.md) -- [第八节 简单点赞系统](Redis/8_简单点赞系统) - -## ✈️ 海量数据处理 - -- [第一节 概述](MassDataProcessing/1_概述.md) -- [第二节 哈希分治](MassDataProcessing/2_哈希分治.md) -- [第三节 位图](MassDataProcessing/3_位图.md) -- [第四节 布隆过滤器](MassDataProcessing/4_布隆过滤器.md) -- [第五节 Trie树](MassDataProcessing/5_Trie树.md) -- [第六节 数据库](MassDataProcessing/6_数据库.md) -- [第七节 倒排索引](MassDataProcessing/7_倒排索引.md) - -# 🔨 消息中间件 - -## 🚁 Kafka - -- [第一节 消息队列](Kafka/1_消息队列.md) -- [第二节 Kafka的架构](Kafka/2_Kafka的架构.md) -- [第三节 Kafka的高可用原理](Kafka/3_Kafka的高可用原理.md) -- [第四节 Kafka中一些常见问题](Kafka/4_Kafka中一些常见问题.md) -- [第五节 Kafka特点](Kafka/5_Kafka特点.md) - -## 🚁 RabbitMQ - -- [第一节 主流消息中间件](RabbitMQ/1_主流消息中间件.md) -- [第二节 RabbitMQ概述](RabbitMQ/2_RabbitMQ概述.md) -- [第三节 RabbitMQ入门](RabbitMQ/3_RabbitMQ入门.md) -- [第四节 RabbitMQ高级特性](RabbitMQ/4_RabbitMQ高级特性.md) -- [第五节 RabbitMQ整合SpringAMQP](RabbitMQ/5_RabbitMQ整合SpringAMQP.md) -- [第六节 RabbitMQ整合SpringBoot](RabbitMQ/6_RabbitMQ整合SpringBoot.md) -- [RabbitMQ 官网](https://www.rabbitmq.com/) - -# 📖 系统设计 - -## ♨️ 常用框架 - -- [第一节 SpringMVC](SSM/1_SpringMVC.md) -- [第二节 SpringIOC](SSM/2_SpringIOC.md) -- [第三节 SpringAOP](SSM/3_SpringAOP.md) -- [第四节 Spring事务管理](SSM/4_Spring事务管理.md) -- [第五节 Spring中Bean的作用域](SSM/5_Spring中Bean的作用域.md) -- [第六节 Spring中Bean的生命周期](SSM/6_Spring中Bean的生命周期.md) -- [第七节 Spring中常见注解](SSM/7_Spring中常见注解.md) -- [第八节 Spring中涉及到的设计模式](SSM/8_Spring中涉及到的设计模式.md) -- [第九节 MyBaits](SSM/9_MyBaits.md) - -## ♨️ Web 安全 - -- [第一节 常见安全问题](Safety/1_常见安全问题.md) -- [第二节 跨站脚本攻击](Safety/2_跨站脚本攻击.md) -- [第三节 跨站请求伪造](Safety/3_跨站请求伪造.md) -- [第四节 Cookies问题](Safety/4_Cookies问题.md) -- [第五节 点击劫持问题](Safety/5_点击劫持问题.md) -- [第六节 传输安全](Safety/6_传输安全.md) -- [第七节 密码安全](Safety/7_密码安全.md) -- [第八节 接入层注入问题](Safety/8_接入层注入问题.md) -- [第九节 接入层上传问题](Safety/9_接入层上传问题.md) -- [第十节 信息泄露](Safety/10_信息泄露.md) -- [第十一节 DoS攻击](Safety/11_DoS攻击.md) -- [第十二节 重放攻击](Safety/12_重放攻击.md) - -## ♨️ 分布式 - -- [第一节 分布式系统设计理念](distribution/1_分布式系统设计理念.md) -- [第二节 CAP理论](distribution/2_CAP理论.md) -- [第三节 BASE理论](distribution/3_BASE理论.md) -- [第四节 分布式锁](distribution/4_分布式锁.md) -- [第五节 分布式事务](distribution/5_分布式事务.md) -- [第六节 分布式缓存的一致性哈希算法](distribution/6_分布式缓存的一致性哈希算法.md) - -## ♨️ 微服务 - -## ♨️ 网站架构 - -- [网站架构](web_architecture/1_网站架构.md) -- [设计秒杀系统](web_architecture/2_设计秒杀系统.md) - -# 💻 工具 - -## 🔑 Git - -- [git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) -- [git - 图解](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) - -## 🔑 Maven - -- [Maven](Maven/1_Maven.md) -- [Maven 下载](http://maven.apache.org/download.cgi) -- [Maven 官网](https://maven.apache.org/) - -## 🔑 Nginx - -## 🔑 Docker - - - -# 🔧 进阶指南 - -- [后端面试进阶指南](https://xiaozhuanlan.com/CyC2018) -- [Java 面试进阶指南](https://xiaozhuanlan.com/javainterview) -- [编码规范指南](https://github.com/alibaba/p3c) - -# 🙊 参考资料 - -- [参考仓库](reference/参考仓库.md) -- [参考书籍](reference/参考书籍.md) -- [慕课网](reference/慕课网.md) diff --git "a/docs/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" "b/docs/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" deleted file mode 100644 index c80a19fb..00000000 --- "a/docs/RabbitMQ/1_\344\270\273\346\265\201\346\266\210\346\201\257\344\270\255\351\227\264\344\273\266.md" +++ /dev/null @@ -1,34 +0,0 @@ -# 主流消息中间件 - -## 1. ActiveMQ - -ActiveMQ 是 Apache 出品的最流行的、性能强劲的开源消息总线,并且其是一个完全支持 JMS 规范的消息中间件。其丰富的 API、多种集群构建模式使得它成为业界老牌消息中间件,广泛应用于中小型企业。 - -## 2. Kafka - -Kafka 是 LinkedIn 开源的分布式发布-订阅消息系统,目前属于 Apache 顶级项目。 - -Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8 版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。 - -## 3. RocketMQ - -RocketMQ 是阿里开源的消息中间件,目前也已经孵化为 Apache 顶级项目,它是纯 Java 开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。 - -RocketMQ 思路起源于 Kafka,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog 分发等场景。 - -## 4. RabbitMQ - -RabbitMQ 是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。 - -AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP 协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。 - -## 对比 - -| 消息中间件 | ActiveMQ | Kafka | RocketMQ | RabbitMQ | -| :----------------------: | :-----------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :------------------------------------------------: | -| *吞吐量* | 万数量级 | 十万级,高吞吐 | 十万级,高吞吐 | 万数量级 | -| *Topic 数量对吞吐量影响* | / | Topic 从几十到几百时,吞吐量会大幅度下降,
在同等机器下,Kafka 尽量保证 Topic 数量不要过多,如果要支撑大规模的 Topic,需要增加更多的机器 | Topic 可达百/千级,吞吐量下降幅度小
在同等机器下,可以支撑大量的 Topic | / | -| *时效性* | 毫秒级 | 毫秒级 | 毫秒级 | 微秒级 | -| *可用性* | 高
基于主从架构实现高可用高 | 非常高
分布式架构 | 非常高
分布式架构 | 高
基于主从架构实现高可用高 | -| *可靠性* | 丢失数据的概率低 | 优化参数配置,
可以做到零丢失 | 优化参数配置,
可以做到零丢失 | 基本不会丢失数据 | -| *功能* | 功能较完备 | 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用 | MQ 功能较为完善,还是分布式的,扩展性好 | 基于 ErLang 开发,并发能力很强,性能极好,延时很低 | \ No newline at end of file diff --git "a/docs/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" "b/docs/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" deleted file mode 100644 index aeab0f78..00000000 --- "a/docs/RabbitMQ/2_RabbitMQ\346\246\202\350\277\260.md" +++ /dev/null @@ -1,256 +0,0 @@ -# RabbitMQ 概述 - -## 简介 - -RabbitMQ 是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用中间共享数据,RabbitMQ 是使用 **Erlang 语言**来编写的,并且 RabbitMQ 是基于 AMQP 协议的。 - -特点: - -- 开源、性能优秀,稳定性好 -- 提供可靠性消息投递模式(confirm)、返回模式(return) -- 与 SpringAOP 完美的整合、API 丰富 -- 集群模式丰富,表达式配置,HA 模式,镜像队列模型 -- 保证数据不丢失的前提做到高可靠性、可用性 - -RabbitMQ 高性能的原因: - -**Erlang 语言**最初用在交换机的架构模式,这样使得 RabbitMQ 在 Broker 之间进行数据交互的性能时非常优秀的。Erlang 的优点:Erlang 有着和原生 Socket 一样的延迟。 - -## AMQP 协议 - -AMQP(Advanced Message Queuing Protocol)协议,即高级消息队列协议。 - -AMQP 是具有现在特征的二进制协议。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。 - -### 协议模型 - -
- -### 核心概念 - -- Server - - 又称 Broker,接受客户端的连接,实现 AMQP 实体服务 - -- Connection - - 连接,应用程序与 Broker 的网络连接 - -- Channel - - 网络通信,几乎所有的操作都在 Channel 中进行,Channel 是进行消息读写的通道。客户端可建立多个 Channel,每个 Channel 代表一个会话任务。 - -- Message - - 消息,服务器和应用程序之间传送的数据,由 Properties 和 Body 组成。Properties 可以对消息进行设置,比如消息的优先级、延迟等高级特性;Body 则就是消息体内容。 - -- Virtual Host - - 虚拟主机,用于进行逻辑隔离,最上层的消息路由。 - - 一个 Virtual Host 里面可以有若干个 Exchange 和 Queue,同一个 Virtual Host 里面不能有相同名称的 Exchange 或 Queue。 - -- Exchange - - 交换机,接受消息,根据路由键转发消息到绑定的队列。 - -- Binding - - Exchange 和 Queue 之间的虚拟连接,Binding 中可以包含 Routing Key - -- Routing Key - - 一个路由规则,虚拟机可用它来确定如何路由一个特定消息 - -- Queue - - 也称为 Message Queue(消息队列),保存消息并将它们转发给消费者 - - - -## RabbitMQ 整体架构 - -
- - - -## RabbitMQ 消息流转 - -
- -## RabbitMQ 简单使用 - -### 1. 启动服务器 - -```html -rabbitmq-server start & -``` - -### 2. 停止服务器 - -```html -rabbitmqctl stop_app -``` - -### 3. 插件管理 - -```html -rabbitmq-plugins enable rabbitmq_management -``` - -### 4. 查看管控台 - -```html -http://localhost:15672/ - -# 用户名 guest -# 密码 guest -``` - - - -## 命令行基础操作 - -### 1. 应用 - -- 关闭应用 - - ```html - rabbitmqctl stop_app - ``` - -- 启动应用 - - ```html - rabbitmqctl start_app - ``` -- 查看节点状态 - - ```html - rabbitmqctl status - ``` - -### 2. 用户 - -- 添加用户 - - ```html - rabbitmqctl add_user username password - ``` - -- 删除用户 - - ```html - rabbitmqctl delete_user username - ``` - -- 列出所有用户 - - ```html - rabbitmqctl list_users - ``` - -- 清除用户权限 - - ```html - rabbitmqctl clear_permissions -p vhostpath username - ``` - -- 列出用户权限 - - ```html - rabbitmqctl list_user_permissions username - ``` - -- 修改密码 - - ```html - rabbitmqctl change_password username newpassword - ``` - -- 设置用户权限 - - ```html - rabbitmqctl set_permissions -p vhostpath username ".*" ".*" ".*" - ``` - -### 3. 虚拟主机 - -- 创建虚拟主机 - - ```html - rabbitmqctl add_vhost vhostpath - ``` - -- 删除虚拟主机 - - ```html - rabbitmqctl delete_vhost vhostpath - ``` - -- 列出所有虚拟主机 - - ```html - rabbitmqctl list_vhosts - ``` - -- 列出虚拟主机上所有权限 - - ```html - rabbitmqctl list_permissions -p vhostpath - ``` - -### 4. 队列 - -- 查看所有队列信息 - - ```html - rabbitmqctl list_queues - ``` - -- 清除队列里的消息 - - ```html - rabbitmqctl -p vhostpath purge_queue blue - ``` - - - -## 命令行高级操作 - -- 移除所有数据 - - ```html - rabbitmqctl reset - # 要在 rabbitmqctl stop_app 之后使用 - ``` - -- 组成集群命令 - - ```html - rabbitmqctl join_cluster [--ram] - ``` - -- 查看集群状态 - - ```html - rabbitmq cluster_status - ``` - -- 修改集群节点的存储形式 - - ```html - rabbitmqctl change_cluser_node_type disc | ram - ``` - -- 摘除节点(忘记节点) - - ```html - rabbitmqctl forget_cluster_node [--offline] - ``` - -- 修改节点名称 - - ```html - rabbitmqctl rename_cluster_node oldnode1 newnode1 [oldnode2] [newnode2] - ``` diff --git "a/docs/RabbitMQ/3_RabbitMQ\345\205\245\351\227\250.md" "b/docs/RabbitMQ/3_RabbitMQ\345\205\245\351\227\250.md" deleted file mode 100644 index 2f9b833d..00000000 --- "a/docs/RabbitMQ/3_RabbitMQ\345\205\245\351\227\250.md" +++ /dev/null @@ -1,653 +0,0 @@ -# RabbitMQ 入门 - -## 简单案例:消息生产与消费 - -pom.xml 配置 - -```html - - com.rabbitmq - amqp-client - - 3.6.5 - -``` - -### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

简单案例:消息生产与消费

- * 消息生产者 - * Created by DHA on 2019/11/18. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 通过 chanel 发送数据 - for(int i=0;i<10;i++){ - String data="Hello!"; - channel.basicPublish("","test001",null,data.getBytes()); - } - - //5 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - -### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

简单案例:消息生产与消费

- * 消息生产者 - * Created by DHA on 2019/11/18. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 通过 chanel 发送数据 - for(int i=0;i<10;i++){ - String data="Hello!"; - channel.basicPublish("","test001",null,data.getBytes()); - } - - //5 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - -## 交换机(Exchange) - -交换机:接收消息,并根据路由键转发消息所绑定的队列。 - -
- -### 交换机属性 - -- Name - - 交换机名称 - -- Type - - 交换机类型 direct、topic、fanout、headers - -- Durability - - 是否需要持久化,true 为持久化 - -- Auto Delete - - 当最后一个绑定到 Exchange 上的队列删除后,自动删除该 Exchange - -- Internal - - 当前 Exchange 是否用于 RabbitMQ 内部使用,默认为 false - -- Arguments - - 扩展参数,用于扩展 AMQP 协议 - -### 交换机类型 - -#### 1. Direct Exchange - -所有发送到 Direct Exchange 的消息被转发到 routing key 中指定的 Queue。 - -
- -注意:Direct 模式可以使用 RabbitMQ 自带的 Exchange:default Exchange,所以不需要将 Exchange 进行任何绑定(binding)操作,消息传递时,routing key 必须完全匹配才会被队列接收,否则该消息会被抛弃。 - -##### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Direct Exchange

- * 所有发送到 Direct Exchange 的消息被转发到 routing key 中指定的 Queue。 - * 消息生产者 - * Created by DHA on 2019/11/19. - */ -public class Producer4DirectExchange { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_direct_exchange"; - String routingKey = "test.direct"; - - //5 通过 chanel 发送数据 - String msg = "Hello World RabbitMQ 4 Direct Exchange Message ... "; - channel.basicPublish(exchangeName, routingKey , null , msg.getBytes()); - - //6 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - - - -##### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Direct Exchange

- * 所有发送到 Direct Exchange 的消息被转发到 routing key 中指定的 Queue。 - * 消息消费者 - * Created by DHA on 2019/11/19. - */ -public class Consumer4DirectExchange { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName="test_direct_exchange"; - String exchangeType="direct"; - String queueName="test_direct_queue"; - String routingKey="test.direct"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,true,queueingConsumer); - - //7 获取数据 - while(true){ - QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - } -} -``` - - - -#### 2. Topic Exchange - -Topic Exchange 将 routing key 与某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。 - -可以使用**通配符**进行模糊匹配: - -- "#" 表示匹配一个或多个词。"log.#" 能够匹配到 "log.info.oa" -- "*" 表示只能匹配一个词。"log.\*" 值能够匹配到 "log.info" - -
- -##### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Topic Exchange

- * Topic Exchange 将 routing key 与某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。 - * 消息生产者 - * Created by DHA on 2019/11/19. - */ -public class Producer4TopicExchange { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_topic_exchange"; - String routingKey1 = "user.save"; - String routingKey2 = "user.update"; - String routingKey3 = "user.delete.abc"; - - //5 通过 chanel 发送数据 - String msg = "Hello World RabbitMQ 4 Topic Exchange Message ... "; - channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes()); - channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes()); - channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes()); - - //6 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - - - -##### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Topic Exchange

- * Topic Exchange 将 routing key 与某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。 - * 消息消费者 - * Created by DHA on 2019/11/19. - */ -public class Consumer4TopicExchange { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName="test_topic_exchange"; - String exchangeType="topic"; - String queueName="test_topic_queue"; - String routingKey="user.*"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,true,queueingConsumer); - - //7 获取数据 - while(true){ - QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - } -} -``` - - - -#### 3. Fanout Exchange - -Fanout Exchange 不处理 routing key,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到交换机绑定的所有队列上。 - -
- -##### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Fanout Exchange

- * Fanout Exchange 不处理 routing key,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到交换机绑定的所有队列上。 - * 消息生产者 - * Created by DHA on 2019/11/19. - */ -public class Producer4FanoutExchange { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_fanout_exchange"; - - //5 通过 chanel 发送数据 - for(int i = 0; i < 10; i ++) { - String msg = "Hello World RabbitMQ 4 Fanout Exchange Message ..."; - channel.basicPublish(exchangeName, "", null , msg.getBytes()); - } - - //6 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - - - -##### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Fanout Exchange

- * Fanout Exchange 不处理 routing key,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到交换机绑定的所有队列上。 - * 消息消费者 - * Created by DHA on 2019/11/19. - */ -public class Consumer4FanoutExchange { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName="test_fanout_exchange"; - String exchangeType="fanout"; - String queueName="test_fanout_queue"; - String routingKey=""; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,true,queueingConsumer); - - //7 获取数据 - while(true){ - QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - } -} -``` - - - -## 绑定(Binding) - -绑定是指 Exchange 和 Exchange、Queue 之间的连接关系。Binding 中可以包含 routing key 或者参数。 - -## 消息队列(Queue) - -消息队列实际用来存储消息数据。常用属性: - -- Durability - - 是否持久化,Durable:是,Transient:否 - -- Auto Delete - - yes 表示最后一个监听被移除之后,会自动删除该 Queue - -## 虚拟主机(Virtual Host) - -虚拟主机用于进行逻辑隔离,是最长层的消息路由。 - -- 一个虚拟主机中可以有若干个 Exchange 和 Queue -- 同一个虚拟主机中不能有相同名称的 Exchange 或 Queue - -## 消息(Message) - -消息即服务器和应用程序之间传送的数据。本质上就是一段数据,由 Properties 和 Body(Properties)组成。 - -常用属性: - -- Delivery Mode - -- Headers - - 自定义属性 - -### 生产者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeoutException; - -/** - *

消息属性设置

- * 消息生产者 - * Created by DHA on 2019/11/18. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - // 设置自定义属性 - Map headers = new HashMap<>(); - headers.put("attr1", "111"); - headers.put("attr2", "222"); - - //4 设置消息属性 - AMQP.BasicProperties properties=new AMQP.BasicProperties.Builder() - .deliveryMode(2) // 2 表示持久化的投递 - .contentEncoding("UTF-8") // 设置内容编码 - .expiration("10000") // 设置过期时间为 10 秒 - .headers(headers) // 自定义属性 - .build(); - - //5 通过 chanel 发送数据 - for(int i=0;i<5;i++){ - String data="Hello!"; - channel.basicPublish("","test001",properties,data.getBytes()); - } - - //6 关闭相关连接 - channel.close(); - connection.close(); - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; -import com.rabbitmq.client.QueueingConsumer.Delivery; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.TimeoutException; - -/** - *

消息属性设置

- * 消息消费者 - * Created by DHA on 2019/11/18. - */ -public class Consumer { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明一个队列 - String queueName="test001"; - channel.queueDeclare(queueName,true,false,false,null); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,true,queueingConsumer); - - //7 获取数据 - while(true){ - Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - // 获取自定义属性数据 - Map headers=delivery.getProperties().getHeaders(); - System.err.println("headers get attribute attr1 value: " + headers.get("attr1")); - } - } -} -``` - diff --git "a/docs/RabbitMQ/4_RabbitMQ\351\253\230\347\272\247\347\211\271\346\200\247.md" "b/docs/RabbitMQ/4_RabbitMQ\351\253\230\347\272\247\347\211\271\346\200\247.md" deleted file mode 100644 index defefa14..00000000 --- "a/docs/RabbitMQ/4_RabbitMQ\351\253\230\347\272\247\347\211\271\346\200\247.md" +++ /dev/null @@ -1,1011 +0,0 @@ -# RabbitMQ 高级特性 - -## 消息100%可靠性投递的解决方案 - -### 生产端可靠性投递 - -- 保障消息成功发出 -- 保障 MQ 节点的成功接收 -- 发送端收到 MQ 节点(Broker)确认应答 -- **完善的消息补偿机制** - -### 解决方案1:消息落库 - -消息落库,对消息状态进行打标。 - -
- - - -### 解决方案2:二次确认,回调检查 - -消息的延迟投递,做二次确认,回调检查。 - -
- - - -## 消费端幂等性操作 - -- 唯一 ID + 指纹码 机制,利用数据库主键去重 - - 优点:实现简单 - - 缺点:高并罚下有数据库写入的性能瓶颈 - - 解决方案:根据 ID 进行分库分表进行算法路由 - -- 利用 Redis 原子特性实现 - -## Confirm 消息机制 - -消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 - -
- -实现机制: - -- 第一步:在 channel 上开启确认模式 - - ```java - channel.confirmSelect() - ``` - -- 第二步:在 channel 上添加监听 - - ```java - channel.addConfirmListener() - ``` - - 监听成功和失败的返回结果,根据具体的结果对消息进行重新发送或记录日志等后续处理。 - -### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.ConfirmListener; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Confirm 消息机制

- * 消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 - * 消息生产者 - * Created by DHA on 2019/11/18. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 指定消息投递模式:confirm 模式 - channel.confirmSelect(); - - String exchangeName = "test_confirm_exchange"; - String routingKey = "confirm.save"; - - //5 通过 chanel 发送数据 - String msg="Hello!"; - channel.basicPublish(exchangeName,routingKey,null,msg.getBytes()); - - //6 添加一个确认监听 - channel.addConfirmListener(new ConfirmListener() { - @Override - public void handleAck(long l, boolean b) throws IOException { - System.out.println("------ack!-------"); - } - - @Override - public void handleNack(long l, boolean b) throws IOException { - System.out.println("------Nack!-------"); - } - }); - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; -import com.rabbitmq.client.QueueingConsumer.Delivery; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Confirm 消息机制

- * 消息的确认是指生产者投递消息后,如果 Broker 收到消息,则会给生产者一个应答,生产者进行接收应答,用来确定这条消息是否正常地发送到 Broker。 - * 消息消费者 - * Created by DHA on 2019/11/18. - */ -public class Consumer { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName="test_confirm_exchange"; - String exchangeType="topic"; - String queueName="test_confirm_queue"; - String routingKey="confirm.#"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,queueingConsumer); - - //7 获取数据 - while(true){ - Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - } -} -``` - - - -## Return 消息机制 - -消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 - -在某些情况下,如果我们在发送消息的时候,当前的 **Exchange 不存在**或者指定的 **routing key路由不到**,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 - -基础 API 有一个配置项 mandatory - -- 如果为 true,那么监听器会接收到路由不可达的消息,然后进行后续处理 -- 如果为 false, 那么 Broker 端自动删除该消息 - - - -
- - - -### 生产者 - -```java -import com.rabbitmq.client.*; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Return 消息机制

- * 消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 - * 在某些情况下,如果我们在发送消息的时候,当前的 Exchange 不存在或者指定的 routing key路由不到,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 - * - * 消息生产者 - * Created by DHA on 2019/11/18. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 指定消息投递模式:confirmListener 模式 - channel.confirmSelect(); - - String exchangeName = "test_return_exchange"; - String routingKey = "returnListener.save"; - String routingKeyError = "return.save"; - - //5 通过 chanel 发送数据 - String msg="Hello!"; - // mandatory 如果为 true,那么监听器会接收到路由不可达的消息,然后进行后续处理 - // mandatory 如果为 false, 那么 Broker 端自动删除该消息 - channel.basicPublish(exchangeName,routingKeyError,true,null,msg.getBytes()); - - //6 添加一个监听 - channel.addReturnListener(new ReturnListener() { - @Override - public void handleReturn(int replyCode, String replyText, String exchange, - String routingKey, AMQP.BasicProperties properties, byte[] body) - throws IOException { - System.err.println("---------handle return----------"); - System.err.println("replyCode: " + replyCode); - System.err.println("replyText: " + replyText); - System.err.println("exchange: " + exchange); - System.err.println("routingKey: " + routingKey); - System.err.println("properties: " + properties); - System.err.println("body: " + new String(body)); - } - }); - - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; -import com.rabbitmq.client.QueueingConsumer.Delivery; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

Return 消息机制

- * 消息生产者通过制动一个 Exchange 和 routing key,把消息送达到某一个队列中去,然后消费者监听队列,进行消费处理操作。 - * 在某些情况下,如果我们在发送消息的时候,当前的 Exchange 不存在或者指定的 routing key路由不到,此时我们需要监听这种不可达的消息,就要使用 Return Listener。 - * - * 消息消费者 - * Created by DHA on 2019/11/18. - */ -public class Consumer { - public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName="test_return_exchange"; - String exchangeType="topic"; - String queueName="test_return_queue"; - String routingKey="returnListener.#"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,queueingConsumer); - - //7 获取数据 - while(true){ - Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - } -} -``` - - - -## 消费端自定义监听 - -我们一般在代码中编写 while 循环,进行 consumer.nextDelivery 方法获取下一条消息,然后进行消费处理! - -但是,我们使用自定义的 Counsumer 更加方便,解耦性更强,在实际工作中广泛使用。 - -### 自定义消费者 - -实现步骤: - -- 先继承 `com.rabbitmq.client.DefaultConsumer` -- 再重写 `handleDelivery()` 方法 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.DefaultConsumer; -import com.rabbitmq.client.Envelope; - -import java.io.IOException; - -/** - *

自定义消费者

- * 1 先继承 DefaultConsumer - * 2 然后重写 handleDelivery() 方法 - * - * Created by DHA on 2019/11/20. - */ -public class MyConsumer extends DefaultConsumer{ - public MyConsumer(Channel channel) { - super(channel); - } - - @Override - public void handleDelivery(String consumerTag, Envelope envelope, - AMQP.BasicProperties properties, byte[] body) - throws IOException { - System.err.println("----------consumer message-----------"); - System.err.println("consumerTag:"+consumerTag); - System.err.println("envelope:"+envelope); - System.err.println("properties:"+properties); - System.err.println("body:"+new String(body)); - } -} -``` - - - -### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

消费端自定义监听

- * 消息生产者 - * Created by DHA on 2019/11/19. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_consumer_exchange"; - String routingKey = "consumer.save"; - - //5 通过 chanel 发送数据 - String msg = "Hello World RabbitMQ 4 Consumer Exchange Message ... "; - channel.basicPublish(exchangeName, routingKey , true,null , msg.getBytes()); - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; -import com.rabbitmq.client.QueueingConsumer; -import com.rabbitmq.client.QueueingConsumer.Delivery; - -public class Consumer { - - public static void main(String[] args) throws Exception { - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName = "test_consumer_exchange"; - String exchangeType= "topic"; - String routingKey = "consumer.#"; - String queueName = "test_consumer_queue"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - /* - //5 创建消费者 - QueueingConsumer queueingConsumer=new QueueingConsumer(channel); - - //6 设置 channel - channel.basicConsume(queueName,true,queueingConsumer); - - //7 获取数据 - while(true){ - QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery(); - String msg=new String(delivery.getBody()); - System.out.println("消费端:"+msg); - } - */ - - //5 消费端自定义监听 使用 MyConsumer 相应实例 - channel.basicConsume(queueName, true, new MyConsumer(channel)); - } -} -``` - - - -## 消费端限流 - -RabbitMQ 提供了一种 QoS(服务质量保证) 功能,**在非自动确认消息的前提下**,如果一定数目的消息(通过基于 Consume 或者 Channel 设置 QoS 值)未被确认前,不进行消费新的消息。 - -涉及到的方法: - -```erlang -void BasicQoS(unit prefetchSize,ushort prefetchCount,bool global) -``` - -- prefetchSize:0 -- prefetchCount:告知 RabbitMQ 不要同时给一个消费者推送多个 N 个消息,即一旦有 N 个消息还没有 ACK,则该 Consumer 将 block 掉,一直到有消息 ack -- golbal:true 表示将上面设置应用于 Channel;true 表示将上面设置应用于 Consumer。 - -注意: - -- prefetchSize 和 global 这两项,RabbitMQ 没有实现,暂且不研究 -- prefetchCount 在 no_ask-false 的情况下生效,即在自动应答的情况下是不生效的 - -### 生产者 - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -/** - *

消费端限流

- * 消息生产者 - * Created by DHA on 2019/11/19. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_qos_exchange"; - String routingKey = "qos.save"; - - //5 通过 chanel 发送数据 - for(int i=0;i<5;i++){ - String msg = "Hello World RabbitMQ 4 Qos Message ... "; - channel.basicPublish(exchangeName, routingKey , true,null , msg.getBytes()); - } - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.DefaultConsumer; -import com.rabbitmq.client.Envelope; - -import java.io.IOException; - -/** - *

自定义消费者

- * 1 先继承 DefaultConsumer - * 2 然后重写 handleDelivery() 方法 - * - * Created by DHA on 2019/11/20. - */ -public class MyConsumer extends DefaultConsumer{ - - // channel 进行签收 - private Channel channel; - - public MyConsumer(Channel channel) { - super(channel); - this.channel=channel; - } - - @Override - public void handleDelivery(String consumerTag, Envelope envelope, - AMQP.BasicProperties properties, byte[] body) - throws IOException { - System.err.println("----------consumer message-----------"); - System.err.println("consumerTag:"+consumerTag); - System.err.println("envelope:"+envelope); - System.err.println("properties:"+properties); - System.err.println("body:"+new String(body)); - - // false 表示不支持批量签收 - channel.basicAck(envelope.getDeliveryTag(),false); - } -} -``` - - - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -/** - *

消费端限流

- * 消息消费者 - * - * basicQoS(prefetchSize,refetchCount,global) - * - prefetchSize:0 - * - prefetchCount:告知 RabbitMQ 不要同时给一个消费者推送多个 N 个消息,即一旦有 N 个消息还没有 ACK, - * 则该 Consumer 将 block 掉,一直到有消息 ack - * - golbal:true 表示将上面设置应用于 Channel;true 表示将上面设置应用于 Consumer。 - * - * Created by DHA on 2019/11/19. - */ -public class Consumer { - - public static void main(String[] args) throws Exception { - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName = "test_qos_exchange"; - String exchangeType= "topic"; - String routingKey = "qos.#"; - String queueName = "test_qos_queue"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - // 第二个参数为 1,表示一次处理一条消息 - // 第三个参数为 false,表示应用到 Consumer 级别 - channel.basicQos(0,1,false); - - //5 消费端自定义监听 - // 首先将第二个参数设置为 false,进行手动签收 - channel.basicConsume(queueName, false, new MyConsumer(channel)); - } -} -``` - - - -## 消费端 ACK 与重回队列 - -- **消费端的手工 ACK 和 NACK** - - 消费端进行消费时: - - 如果由于业务异常,我们可以进行日志的记录,然后进行补偿; - - 如果由于服务器宕机等严重问题,那么需要手工进行 ACK 保障消费端消费成功 - -- **消费端的重回队列** - - 消费端重回队列是为了对没有成功的消息, 消息会被重新投递给 Broker。一般在使用应用中,都会关闭重回队列,即设置为 false。 - -### 生产者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeoutException; - -/** - *

消费端的手工 ACK 和 NACK

- * 消息生产者 - * - * Created by DHA on 2019/11/19. - */ -public class Producer { - public static void main(String[] args) throws IOException, TimeoutException { - - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - //声明 exchange 名称 - String exchangeName="test_ack_exchange"; - String routingKey = "ack.save"; - - //5 通过 chanel 发送数据 - for(int i =0; i<5; i ++){ - - Map headers = new HashMap(); - headers.put("num", i); - - AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() - .deliveryMode(2) - .contentEncoding("UTF-8") - .headers(headers) - .build(); - String msg = "Hello RabbitMQ ACK Message " + i; - channel.basicPublish(exchangeName, routingKey, true, properties, msg.getBytes()); - } - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.DefaultConsumer; -import com.rabbitmq.client.Envelope; - -import java.io.IOException; - -/** - *

消费端的重回队列

- * 消费端重回队列是为了对没有成功的消息, 消息会被重新投递给 Broker。 - * 一般在使用应用中,都会关闭重回队列,即设置为 false。 - * - * Created by DHA on 2019/11/20. - */ -public class MyConsumer extends DefaultConsumer{ - - // channel 进行签收 - private Channel channel; - - public MyConsumer(Channel channel) { - super(channel); - this.channel=channel; - } - - @Override - public void handleDelivery(String consumerTag, Envelope envelope, - AMQP.BasicProperties properties, byte[] body) - throws IOException { - System.err.println("-----------consume message----------"); - System.err.println("body: " + new String(body)); - - // 为了实验效果明显 - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - Integer num=(Integer) properties.getHeaders().get("num"); - if(num==0){ - // 第二个参数表示是否支持批量签收,如果为 false,表示不支持批量签收 - // 第三个参数表示是否重回队列,如果为 true,表示支持重回队列,则会重回到队列的尾端 - channel.basicNack(envelope.getDeliveryTag(),false,true); - }else{ - // false 表示不支持批量签收 - channel.basicAck(envelope.getDeliveryTag(),false); - } - //channel.basicAck(envelope.getDeliveryTag(),false); - } -} -``` - - - -```java -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -/** - *

消费端的手工 ACK 和 NACK

- * 消息消费者 - * - * Created by DHA on 2019/11/19. - */ -public class Consumer { - - public static void main(String[] args) throws Exception { - //1 创建一个 Connectionfactory,并进行设置 - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - //2 通过连接工厂创建连接 - Connection connection = connectionFactory.newConnection(); - - //3 通过 connecion 创建一个 Channel - Channel channel = connection.createChannel(); - - //4 声明 - String exchangeName = "test_ack_exchange"; - String exchangeType= "topic"; - String routingKey = "ack.#"; - String queueName = "test_ack_queue"; - - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - - //5 消费端自定义监听 - // 首先将第二个参数 autoACK 设置为 false,进行手动签收 - channel.basicConsume(queueName, false, new MyConsumer(channel)); - } -} -``` - - - -## TTL - -TTL(Time To Live)即生存时间。 - -- RabbitMQ 支持**消息**的过期时间,在消息发送时可以进行指定 - -- RabbitMQ 支持**队列**的过期时间,从消息如队列开始计算,只要超过了队列的超时时间配置,那么会自动清除消息 - -## 死信队列(DLX,Dead-Letter-Exchange ) - -利用 DLX,当消息在一个队列中变成死信(dead message)之后,其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 - -消息变成死信的几种情况: - -- 消息被拒绝(basic.reject / basic.nack),并且 requeue=false -- 消息 TTL 过期 -- 队列达到最大长度 - -注意: - -- DLX 也是一个正常的 Exchange,和一般的 Exchange 没有区别,它能在任何队列上被指定,实际上就是设置某个队列的属性。 - -- 当这个队列中有死信时,RabbitMQ 就会自动的将这个消息重新发布到设置的 Exchange 上去,进而被路由到另一个队列。 - -- 死信队列设置需要设置 Exchange 和 队列,然后绑定 - - ```java - channel.exchangeDeclare("dlx.exchange", "topic", true, false, null); - channel.queueDeclare("dlx.queue", true, false, false, null); - channel.queueBind("dlx.queue", "dlx.exchange", "#"); - ``` - - 然后我们进行正常声明 Exchange、队列和绑定,此时需要在队列上加上参数 arguments - - ```java - Map agruments = new HashMap(); - agruments.put("x-dead-letter-exchange", "dlx.exchange"); - //这个agruments属性,要设置到声明队列上 - channel.queueDeclare(queueName, true, false, false, agruments); - ``` - -### 生产者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -/** - *

死信队列

- * 利用 DLX,当消息在一个队列中变成死信(dead message)之后, - * 其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 - * - * 消息生产者 - * Created by DHA on 2019/11/20. - */ -public class Producer { - - public static void main(String[] args) throws Exception { - - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - Connection connection = connectionFactory.newConnection(); - Channel channel = connection.createChannel(); - - String exchange = "test_dlx_exchange"; - String routingKey = "dlx.save"; - - String msg = "Hello RabbitMQ DLX Message"; - - AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() - .deliveryMode(2) - .contentEncoding("UTF-8") - .expiration("10000") - .build(); - channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes()); - } -} -``` - - - -### 消费者 - -```java -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.DefaultConsumer; -import com.rabbitmq.client.Envelope; - -import java.io.IOException; - -/** - *

自定义消费者

- * 1 先继承 DefaultConsumer - * 2 然后重写 handleDelivery() 方法 - * - * Created by DHA on 2019/11/20. - */ -public class MyConsumer extends DefaultConsumer{ - public MyConsumer(Channel channel) { - super(channel); - } - - @Override - public void handleDelivery(String consumerTag, Envelope envelope, - AMQP.BasicProperties properties, byte[] body) - throws IOException { - System.err.println("----------consumer message-----------"); - System.err.println("consumerTag:"+consumerTag); - System.err.println("envelope:"+envelope); - System.err.println("properties:"+properties); - System.err.println("body:"+new String(body)); - } -} -``` - - - -```java -import java.util.HashMap; -import java.util.Map; - -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.ConnectionFactory; - -/** - *

死信队列

- * 利用 DLX,当消息在一个队列中变成死信(dead message)之后, - * 其能被重新 publish 到另一个 Exchange,这个 Exchange 就是 DLX。 - * - * 消息消费者 - * Created by DHA on 2019/11/20. - */ -public class Consumer { - - public static void main(String[] args) throws Exception { - - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.setHost("localhost"); - connectionFactory.setPort(5672); - connectionFactory.setVirtualHost("/"); - - Connection connection = connectionFactory.newConnection(); - Channel channel = connection.createChannel(); - - // 这就是一个普通的交换机 和 队列 以及路由 - String exchangeName = "test_dlx_exchange"; - String routingKey = "dlx.#"; - String queueName = "test_dlx_queue"; - - channel.exchangeDeclare(exchangeName, "topic", true, false, null); - Map agruments = new HashMap(); - agruments.put("x-dead-letter-exchange", "dlx.exchange"); - //这个agruments属性,要设置到声明队列上 - channel.queueDeclare(queueName, true, false,false,agruments); - channel.queueBind(queueName, exchangeName, routingKey); - - //要进行死信队列的声明: - channel.exchangeDeclare("dlx.exchange", "topic", true, false, null); - channel.queueDeclare("dlx.queue", true, false, false, null); - channel.queueBind("dlx.queue", "dlx.exchange", "#"); - - channel.basicConsume(queueName, true, new MyConsumer(channel)); - } -} -``` - - - - - - - diff --git "a/docs/RabbitMQ/5_RabbitMQ\346\225\264\345\220\210SpringAMQP.md" "b/docs/RabbitMQ/5_RabbitMQ\346\225\264\345\220\210SpringAMQP.md" deleted file mode 100644 index 3385a135..00000000 --- "a/docs/RabbitMQ/5_RabbitMQ\346\225\264\345\220\210SpringAMQP.md" +++ /dev/null @@ -1,737 +0,0 @@ -# RabbitMQ 整合 SpringAMQP - -## RabbitAdmin - -RabbitAdmin 类可以很好地操作 RabbitMQ,在 Spring 中直接进行注入即可。 - -### 配置 - -```java - - com.rabbitmq - amqp-client - 3.6.5 - - - - org.springframework.boot - spring-boot-starter-amqp - -``` - - - -### 注入 - -```java -import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; -import org.springframework.amqp.rabbit.connection.ConnectionFactory; -import org.springframework.amqp.rabbit.core.RabbitAdmin; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan({"com.southeast.spring.*"}) -public class RabbitMQConfig { - - @Bean - public ConnectionFactory connectionFactory(){ - CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); - connectionFactory.setAddresses("localhost"); - connectionFactory.setUsername("guest"); - connectionFactory.setPassword("guest"); - connectionFactory.setVirtualHost("/"); - return connectionFactory; - } - - @Bean - public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { - RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); - rabbitAdmin.setAutoStartup(true); - return rabbitAdmin; - } -} -``` - -注意: - -- autoStartup 必须要设置为 true,否则容器不会加载 RabbitAdmin - -### 基础功能操作 - -```java -import java.util.HashMap; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.DirectExchange; -import org.springframework.amqp.core.FanoutExchange; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.TopicExchange; -import org.springframework.amqp.rabbit.core.RabbitAdmin; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -/** - *

RabbitAdmin 测试

- */ -@RunWith(SpringRunner.class) -@SpringBootTest -public class ApplicationTests { - - @Autowired - private RabbitAdmin rabbitAdmin; - - /** - *

测试 RabbitAdmin 的基本基本功能

- * @throws Exception - */ - @Test - public void testAdmin() throws Exception { - // 声明交换机 - rabbitAdmin.declareExchange(new DirectExchange("test.direct", false, false)); - rabbitAdmin.declareExchange(new TopicExchange("test.topic", false, false)); - rabbitAdmin.declareExchange(new FanoutExchange("test.fanout", false, false)); - - // 声明队列 - rabbitAdmin.declareQueue(new Queue("test.direct.queue", false)); - rabbitAdmin.declareQueue(new Queue("test.topic.queue", false)); - rabbitAdmin.declareQueue(new Queue("test.fanout.queue", false)); - - // 声明绑定:注意有 2 种方式 - rabbitAdmin.declareBinding(new Binding("test.direct.queue", - Binding.DestinationType.QUEUE, - "test.direct", "direct", new HashMap<>())); - - rabbitAdmin.declareBinding( - BindingBuilder - .bind(new Queue("test.topic.queue", false)) //直接创建队列 - .to(new TopicExchange("test.topic", false, false)) //直接创建交换机 建立关联关系 - .with("user.#")); //指定路由Key - - - rabbitAdmin.declareBinding( - BindingBuilder - .bind(new Queue("test.fanout.queue", false)) - .to(new FanoutExchange("test.fanout", false, false))); - - //清空队列数据 - rabbitAdmin.purgeQueue("test.topic.queue", false); - } -} -``` - -### RabbitAdmin 源码解析 - -RabbitMQAdmin 底层实现就是从 Spring 容器中获取 Exchange、Binding、routing key 以及 Queue 的 @Bean 声明,然后使用 RabbitTemplate 的 execute 方法执行对应的声明、修改、删除等一系列 RabbitMQ 基础功能操作。 - -```java -this.rabbitTemplate.execute( - new ChannelCallback() { - public Object doInRabbit(Channel channel) throws Exception { - RabbitAdmin.this.declareExchanges(channel, (Exchange[])exchanges.toArray(new Exchange[exchanges.size()])); - RabbitAdmin.this.declareQueues(channel, (Queue[])queues.toArray(new Queue[queues.size()])); - RabbitAdmin.this.declareBindings(channel, (Binding[])bindings.toArray(new Binding[bindings.size()])); - - return null; - } -}); -``` - - - -## SpringAMQP 声明 - -- RabbitMQ 基础 API 中声明一个 Exchange、一个队列、一个绑定: - - ```java - // 声明一个交换机 - channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null); - // 声明一个队列 - channel.queueDeclare(queueName,false,false,false,null); - // 绑定:将一个队列绑定到一个交换机上 - channel.queueBind(queueName,exchangeName,routingKey); - ``` - -- 使用 SpringAMQP 去声明,使用 @Bean 注解 - - ```java - /** - *

针对消费者声明交换机、队列、绑定

- * 1. 设置交换机类型 - * 2. 将队列绑定到交换机 - * - FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念 - * - HeadersExchange :通过添加属性key-value匹配 - * - DirectExchange:按照routingkey分发到指定队列 - * - TopicExchange:多关键字匹配 - */ - // 声明 交换机、队列和绑定 - @Bean - public TopicExchange exchange001() { - return new TopicExchange("topic001", true, false); - } - - @Bean - public Queue queue001() { - return new Queue("queue001", true); //队列持久 - } - - @Bean - public Binding binding001() { - return BindingBuilder.bind(queue001()).to(exchange001()).with("spring.*"); - } - - @Bean - public TopicExchange exchange002() { - return new TopicExchange("topic002", true, false); - } - - @Bean - public Queue queue002() { - return new Queue("queue002", true); //队列持久 - } - - @Bean - public Binding binding002() { - return BindingBuilder.bind(queue002()).to(exchange002()).with("rabbit.*"); - } - - @Bean - public Queue queue003() { - return new Queue("queue003", true); //队列持久 - } - - @Bean - public Binding binding003() { - return BindingBuilder.bind(queue003()).to(exchange001()).with("mq.*"); - } - - @Bean - public Queue queue_image() { - return new Queue("image_queue", true); //队列持久 - } - - @Bean - public Queue queue_pdf() { - return new Queue("pdf_queue", true); //队列持久 - } - ``` - - -## RabbitTemplate - -RabbitTemplate 即消息模板,是在于 SpringAMQP 整合时进行发送消息的关键类,该类提供了丰富的发送消息方法,包括可靠性投递消息方法、回调监听消息接口 ConfirmCallback、返回值确认接口 ReturnCallback 等等。同样我们需要进行注入到 Spring 容器中,然后直接使用。 - -```java -@Bean -public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { - RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); - return rabbitTemplate; -} -``` - -```java -@Autowired -private RabbitTemplate rabbitTemplate; - -/** - *

rabbitTemplate 测试发送消息

- * @throws Exception - */ -@Test -public void testSendMessage() throws Exception { - //1 创建消息 - MessageProperties messageProperties = new MessageProperties(); - messageProperties.getHeaders().put("desc", "信息描述.."); - messageProperties.getHeaders().put("type", "自定义消息类型.."); - Message message = new Message("Hello RabbitMQ".getBytes(), messageProperties); - - rabbitTemplate.convertAndSend("topic001", "spring.amqp", message, new MessagePostProcessor() { - @Override - public Message postProcessMessage(Message message) throws AmqpException { - System.err.println("------添加额外的设置---------"); - message.getMessageProperties().getHeaders().put("desc", "额外修改的信息描述"); - message.getMessageProperties().getHeaders().put("attr", "额外新加的属性"); - return message; - } - }); -} - -@Test -public void testSendMessage2() throws Exception { - //1 创建消息 - MessageProperties messageProperties = new MessageProperties(); - messageProperties.setContentType("text/plain"); - Message message = new Message("mq 消息1234".getBytes(), messageProperties); - - rabbitTemplate.send("topic001", "spring.abc", message); - - rabbitTemplate.convertAndSend("topic001", "spring.amqp", "hello object message send!"); - rabbitTemplate.convertAndSend("topic002", "rabbit.abc", "hello object message send!!!"); -} -``` - -## SimpleMessageListenerContainer - -SimpleMessageListenerContainer 即简单消息监听容器。 - -该类非常强大,我们可以对他进行很多设置,对于消费者的配置项,这个类都可以满足。 - -使用 SimpleMessageListenerContainer 可以监听多个队列、设置消费者数量、批量消费。 - -```java -/** - *

设置 简单消息监听容器

- * @param connectionFactory - * @return {@link SimpleMessageListenerContainer} - */ -@Bean -public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) { - - SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); - - //监听多个队列 - container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf()); - container.setConcurrentConsumers(1); - container.setMaxConcurrentConsumers(5); - container.setDefaultRequeueRejected(false); - container.setAcknowledgeMode(AcknowledgeMode.AUTO); - container.setConsumerTagStrategy(new ConsumerTagStrategy() { - @Override - public String createConsumerTag(String queue) { - return queue + "_" + UUID.randomUUID().toString(); - } - }); - - //设置监听器 - container.setMessageListener(new ChannelAwareMessageListener() { - @Override - public void onMessage(Message message, Channel channel) throws Exception { - String msg = new String(message.getBody()); - System.err.println("消费者: " + msg); - } - }); - - return container; -} -``` - - - -## MessageListenerAdapter - -MessageListenerAdapter 即消息监听适配器,通过 MessageListenerAdapter 的代码我们可以看出如下核心属性: - -- defaultListenerMethod:默认监听方法名称 - -- Delegate 委托对象:实际真实的委托对象,用于处理消息 - -- queueOrTagToMathodName:队列标识与方法名称组成的集合 - - 可以将队列和方法名称绑定,即指定队列里的消息会被绑定的方法所接受处理 - -### Adpater - -```java -/** - *

设置 简单消息监听容器

- * @param connectionFactory - * @return {@link SimpleMessageListenerContainer} - */ -@Bean -public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) { - - SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); - - //监听多个队列 - container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf()); - container.setConcurrentConsumers(1); - container.setMaxConcurrentConsumers(5); - container.setDefaultRequeueRejected(false); - container.setAcknowledgeMode(AcknowledgeMode.AUTO); - container.setConsumerTagStrategy(new ConsumerTagStrategy() { - @Override - public String createConsumerTag(String queue) { - return queue + "_" + UUID.randomUUID().toString(); - } - }); - - //设置监听器 - /*container.setMessageListener(new ChannelAwareMessageListener() { - @Override - public void onMessage(Message message, Channel channel) throws Exception { - String msg = new String(message.getBody()); - System.err.println("消费者: " + msg); - } - });*/ - - /** - * defaultListenerMethod 方式 - */ - /*// 设置适配器,作为参数 - MessageListenerAdapter adapter=new MessageListenerAdapter(new MessageDelegate()); - // 未指定监听方法,由默认的 handleMessage 处理 - container.setMessageListener(adapter);*/ - - /** - * 指定自定义监听方法方式 - */ - /*MessageListenerAdapter adapter=new MessageListenerAdapter(new MessageDelegate()); - // 指定 consumeMessage 监听方法,参数是字节数组 - adapter.setDefaultListenerMethod("consumeMessage"); - // 也可以添加一个转换器: 从字节数组转换为String - adapter.setMessageConverter(new TextMessageConverter()); - container.setMessageListener(adapter);*/ - - /** - * 将队列和方法名称绑定 - */ - MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); - - Map queueOrTagToMethodName = new HashMap<>(); - queueOrTagToMethodName.put("queue001", "method1"); - queueOrTagToMethodName.put("queue002", "method2"); - adapter.setQueueOrTagToMethodName(queueOrTagToMethodName); - - //自定义的方法参数是 String 类型 - adapter.setMessageConverter(new TextMessageConverter()); - container.setMessageListener(adapter); - - return container; -} -``` - - - -### Delegate - -```java -/** - *

消息委托

- * 默认方法是 handleMessage(byte[]) - * 自定义方法是 consumeMessage(byte[]) 和 consumeMessage(String ) - * Created by DHA on 2019/11/22. - */ -public class MessageDelegate { - - /** - *

默认方法

- * @param messageBody 消息体,注意是字节数组 - */ - public void handleMessage(byte[] messageBody) { - System.err.println("默认方法, 消息内容:" + new String(messageBody)); - } - - /** - *

自定义方法

- * @param messageBody 消息体,注意是字节数组 - */ - public void consumeMessage(byte[] messageBody) { - System.err.println("字节数组方法, 消息内容:" + new String(messageBody)); - } - - /** - *

自定义方法

- * @param messageBody 消息体,注意是字符串,需要自定义转换器 - */ - public void consumeMessage(String messageBody) { - System.err.println("字符串方法, 消息内容:" + messageBody); - } - - /** - *

自定义方法

- * method1 方法与 queue001 匹配 - * @param messageBody - */ - public void method1(String messageBody) { - System.err.println("method1 收到消息内容:" + new String(messageBody)); - } - - /** - *

自定义方法

- * method2 方法与 queue002 匹配 - * @param messageBody - */ - public void method2(String messageBody) { - System.err.println("method2 收到消息内容:" + new String(messageBody)); - } -} -``` - -### TextMessageConverter - -```java -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.support.converter.MessageConversionException; -import org.springframework.amqp.support.converter.MessageConverter; - -public class TextMessageConverter implements MessageConverter { - - @Override - public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { - return new Message(object.toString().getBytes(), messageProperties); - } - - @Override - public Object fromMessage(Message message) throws MessageConversionException { - String contentType = message.getMessageProperties().getContentType(); - if(null != contentType && contentType.contains("text")) { - return new String(message.getBody()); - } - return message.getBody(); - } -} -``` - - - -## MessageConverter - -MessageConverter 即消息转换器,在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或者指定自定义的转换器,就需要使用 MessageConverter。 - -### 消息委托 - -```java -import com.southeast.spring.entity.Order; -import com.southeast.spring.entity.Packaged; - -import java.io.File; -import java.util.Map; - -/** - *

消息委托

- */ -public class MyMessageDelegate { - - /** - *

支持 Json 格式

- * @param messageBody json 实际上就是 map - */ - public void consumeMessage(Map messageBody) { - System.err.println("map方法, 消息内容:" + messageBody); - } - - /** - *

支持 Java 对象转换

- * @param order {@link Order} - */ - public void consumeMessage(Order order) { - System.err.println("order对象, 消息内容, id: " + order.getId() + - ", name: " + order.getName() + - ", content: "+ order.getContent()); - } - - /** - *

支持 Java 对象多隐射转换

- * @param pack {@link Packaged} - */ - public void consumeMessage(Packaged pack) { - System.err.println("package对象, 消息内容, id: " + pack.getId() + - ", name: " + pack.getName() + - ", content: "+ pack.getDescription()); - } - - /** - *

支持自定义转换器

- * @param file - */ - public void consumeMessage(File file) { - System.err.println("文件对象 方法, 消息内容:" + file.getName()); - } -} -``` - - - -### Json 转换器 - -```java -/** - * 支持json格式的转换器 - */ -MessageListenerAdapter adapter = new MessageListenerAdapter(new MyMessageDelegate()); -adapter.setDefaultListenerMethod("consumeMessage"); - -Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); -adapter.setMessageConverter(jackson2JsonMessageConverter); - -container.setMessageListener(adapter); -``` - - - -### Java 对象转换 - -```java -/** - * 支持 java 对象转换 - * DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持java对象转换 - */ -MessageListenerAdapter adapter = new MessageListenerAdapter(new MyMessageDelegate()); -adapter.setDefaultListenerMethod("consumeMessage"); - -Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); - -DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper(); -jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper); - -adapter.setMessageConverter(jackson2JsonMessageConverter); -container.setMessageListener(adapter); -``` - - - -### Java 对象多映射转换 - -```java -/** - * 支持java对象多映射转换 - * DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持java对象多映射转换 - */ -MessageListenerAdapter adapter = new MessageListenerAdapter(new MyMessageDelegate()); -adapter.setDefaultListenerMethod("consumeMessage"); -Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); -DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper(); - -Map> idClassMapping = new HashMap>(); -idClassMapping.put("order", com.southeast.spring.entity.Order.class); -idClassMapping.put("packaged", com.southeast.spring.entity.Packaged.class); - -javaTypeMapper.setIdClassMapping(idClassMapping); - -jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper); -adapter.setMessageConverter(jackson2JsonMessageConverter); -container.setMessageListener(adapter); -``` - - - -### 自定义二进制转换器 - -```java -/** - * 自定义转换器 - */ -MessageListenerAdapter adapter = new MessageListenerAdapter(new MyMessageDelegate()); -adapter.setDefaultListenerMethod("consumeMessage"); - -//全局的转换器: -ContentTypeDelegatingMessageConverter convert = new ContentTypeDelegatingMessageConverter(); - -TextMessageConverter textConvert = new TextMessageConverter(); -convert.addDelegate("text", textConvert); -convert.addDelegate("html/text", textConvert); -convert.addDelegate("xml/text", textConvert); -convert.addDelegate("text/plain", textConvert); - -Jackson2JsonMessageConverter jsonConvert = new Jackson2JsonMessageConverter(); -convert.addDelegate("json", jsonConvert); -convert.addDelegate("application/json", jsonConvert); - -ImageMessageConverter imageConverter = new ImageMessageConverter(); -convert.addDelegate("image/png", imageConverter); -convert.addDelegate("image", imageConverter); - -PDFMessageConverter pdfConverter = new PDFMessageConverter(); -convert.addDelegate("application/pdf", pdfConverter); - - -adapter.setMessageConverter(convert); -container.setMessageListener(adapter); -``` - -自定义消息转换器,需要实现 MessageConverter 接口,然后重写: - -```java -toMessage() // Java 对象转换为 Message -fromMessage() // Message 对象转换为 Java 对象 -``` - - - -#### 1. pdf 转换器 - -```java -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.UUID; - -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.support.converter.MessageConversionException; -import org.springframework.amqp.support.converter.MessageConverter; - -public class PDFMessageConverter implements MessageConverter { - - @Override - public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { - throw new MessageConversionException(" convert error ! "); - } - - @Override - public Object fromMessage(Message message) throws MessageConversionException { - System.err.println("-----------PDF MessageConverter----------"); - - byte[] body = message.getBody(); - String fileName = UUID.randomUUID().toString(); - String path = "F:/Projects/RabbitMQ/rabbitmq-spring/testForConverterDest/" + fileName + ".pdf"; - File f = new File(path); - try { - Files.copy(new ByteArrayInputStream(body), f.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - return f; - } - -} -``` - -#### 2. 图片转换器 - -```java -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.UUID; - -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.support.converter.MessageConversionException; -import org.springframework.amqp.support.converter.MessageConverter; - -public class ImageMessageConverter implements MessageConverter { - - @Override - public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { - throw new MessageConversionException(" convert error ! "); - } - - @Override - public Object fromMessage(Message message) throws MessageConversionException { - System.err.println("-----------Image MessageConverter----------"); - - Object _extName = message.getMessageProperties().getHeaders().get("extName"); - String extName = _extName == null ? "png" : _extName.toString(); - - byte[] body = message.getBody(); - String fileName = UUID.randomUUID().toString(); - String path = "F:/Projects/RabbitMQ/rabbitmq-spring/testForConverterDest/" + fileName + "." + extName; - File f = new File(path); - try { - Files.copy(new ByteArrayInputStream(body), f.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - return f; - } -} -``` \ No newline at end of file diff --git "a/docs/RabbitMQ/6_RabbitMQ\346\225\264\345\220\210SpringBoot.md" "b/docs/RabbitMQ/6_RabbitMQ\346\225\264\345\220\210SpringBoot.md" deleted file mode 100644 index 7539c854..00000000 --- "a/docs/RabbitMQ/6_RabbitMQ\346\225\264\345\220\210SpringBoot.md" +++ /dev/null @@ -1,302 +0,0 @@ -# RabbitMQ 整合 SpringBoot - -## 生产者 - -### application.properties 配置 - -```html -spring.rabbitmq.addresses=localhost:5672 -spring.rabbitmq.username=guest -spring.rabbitmq.password=guest -spring.rabbitmq.virtual-host=/ -spring.rabbitmq.connection-timeout=15000 - -spring.rabbitmq.publisher-confirms=true -spring.rabbitmq.publisher-returns=true -# 注意: -# mandatory 如果为 true,那么监听器会接收到路由不可达的消息,然后进行后续处理 -# mandatory 如果为 false, 那么 Broker 端自动删除该消息 -spring.rabbitmq.template.mandatory=true -``` - -### MainConfig - -```java -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.TopicExchange; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan({"com.southeast.springboot.*"}) -public class MainConfig { - - @Bean - public TopicExchange exchange_1(){ - return new TopicExchange("exchange-1",true,false); - } - - @Bean - public Queue queue_1(){ - return new Queue("queue-1",true); - } - - @Bean - public Binding binding_1(){ - return BindingBuilder.bind(queue_1()).to(exchange_1()).with("springboot.#"); - } - - @Bean - public TopicExchange exchange_2(){ - return new TopicExchange("exchange-2",true,false); - } - - @Bean - public Queue queue_2(){ - return new Queue("queue-2",true); - } - - @Bean - public Binding binding_2(){ - return BindingBuilder.bind(queue_2()).to(exchange_2()).with("springboot.*"); - } -} -``` - - - -### RabbitSender - -- publisher-confirms - - 实现一个监听器用于监听 Broker 端给我们返回的确认请求 - -- publisher-confirms - - 保证消息对 Broker 端是可达的,如果出现 routing key 不可达的情况,则使用监听器对不可达的消息进行后续的处理,保证消息的路由成功。 - -```java -import java.util.Map; - -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback; -import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback; -import org.springframework.amqp.rabbit.support.CorrelationData; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; - -import com.southeast.springboot.entity.Order; -/** - *

消息发送者

- */ -@Component -public class RabbitSender { - - //自动注入RabbitTemplate模板类 - @Autowired - private RabbitTemplate rabbitTemplate; - - //回调函数: confirm确认 - final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() { - @Override - public void confirm(CorrelationData correlationData, boolean ack, String cause) { - System.err.println("correlationData: " + correlationData); - System.err.println("ack: " + ack); - if(!ack){ - System.err.println("异常处理...."); - } - } - }; - - //回调函数: return返回 - final ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() { - @Override - public void returnedMessage(org.springframework.amqp.core.Message message, int replyCode, String replyText, - String exchange, String routingKey) { - System.err.println("return exchange: " + exchange + ", routingKey: " - + routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText); - } - }; - - /** - *

发送消息方法调用: 构建Message消息

- * @param message - * @param properties - * @throws Exception - */ - public void send(Object message, Map properties) throws Exception { - MessageHeaders mhs = new MessageHeaders(properties); - Message msg = MessageBuilder.createMessage(message, mhs); - rabbitTemplate.setConfirmCallback(confirmCallback); - rabbitTemplate.setReturnCallback(returnCallback); - - CorrelationData correlationData = new CorrelationData(); - //id + 时间戳 全局唯一 - correlationData.setId("123456"); - rabbitTemplate.convertAndSend("exchange-1", "springboot.abc", msg, correlationData); - } - - /** - *

发送消息方法调用: 构建自定义对象消息

- * @param order - * @throws Exception - */ - public void sendOrder(Order order) throws Exception { - rabbitTemplate.setConfirmCallback(confirmCallback); - rabbitTemplate.setReturnCallback(returnCallback); - //id + 时间戳 全局唯一 - CorrelationData correlationData = new CorrelationData(); - correlationData.setId("678910"); - rabbitTemplate.convertAndSend("exchange-2", "spring.def", order, correlationData); - } - -} -``` - - - -## 消费者 - -### 消费端核心配置 - -```html -# 配置为手工确认模式 -spring.rabbitmq.listener.simple.acknowledge-mode=manual -# 设置消费端的监听个数和最大个数,控制消费端的并发数量 -spring.rabbitmq.listener.simple.concurrency=5 -spring.rabbitmq.listener.simple.max-concurrency=10 - -# 交换机、队列、routing key 配置 -spring.rabbitmq.listener.order.queue.name=queue-2 -spring.rabbitmq.listener.order.queue.durable=true -spring.rabbitmq.listener.order.exchange.name=exchange-2 -spring.rabbitmq.listener.order.exchange.durable=true -spring.rabbitmq.listener.order.exchange.type=topic -spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true -spring.rabbitmq.listener.order.key=springboot.* -``` - - - -### @RabbitListener 注解 - -@RabbitListener 是一个组合注解,里面可以配置注解 @QueueBinding、@Queue、@Exchange 直接通过这个注解一次性配置交换机、队列、绑定、 routing key。 - -```java -@RabbitListener(bindings = @QueueBinding( - value = @Queue(value = "queue-1", - durable="true"), - exchange = @Exchange(value = "exchange-1", - durable="true", - type= "topic", - ignoreDeclarationExceptions = "true"), - key = "springboot.*" - ) - ) -``` - -将配置写在代码中,不太灵活,所以使用配置文件改进:在 `application.peoperties` 文件中 - -```html -spring.rabbitmq.listener.msg.queue.name=queue-1 -spring.rabbitmq.listener.msg.queue.durable=true -spring.rabbitmq.listener.msg.exchange.name=exchange-1 -spring.rabbitmq.listener.msg.exchange.durable=true -spring.rabbitmq.listener.msg.exchange.type=topic -spring.rabbitmq.listener.msg.exchange.ignoreDeclarationExceptions=true -spring.rabbitmq.listener.msg.key=springboot.* -``` - - - -改进后的代码: - - - -```java -@RabbitListener(bindings = @QueueBinding( - value = @Queue(value = "${spring.rabbitmq.listener.msg.queue.name}", - durable="${spring.rabbitmq.listener.msg.queue.durable}"), - exchange = @Exchange(value = "${spring.rabbitmq.listener.msg.exchange.name}", - durable="${spring.rabbitmq.listener.msg.exchange.durable}", - type= "${spring.rabbitmq.listener.msg.exchange.type}", - ignoreDeclarationExceptions = "${spring.rabbitmq.listener.msg.exchange.ignoreDeclarationExceptions}"), - key = "${spring.rabbitmq.listener.msg.key}" - ) - ) -``` - - - -### RabbitReceiver - -```java -import java.util.Map; - -import com.southeast.springboot.entity.Order; -import org.springframework.amqp.rabbit.annotation.Exchange; -import org.springframework.amqp.rabbit.annotation.Queue; -import org.springframework.amqp.rabbit.annotation.QueueBinding; -import org.springframework.amqp.rabbit.annotation.RabbitHandler; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.amqp.support.AmqpHeaders; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.Headers; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.stereotype.Component; - -import com.rabbitmq.client.Channel; - -@Component -public class RabbitReceiver { - - - @RabbitListener(bindings = @QueueBinding( - value = @Queue(value = "queue-1", - durable="true"), - exchange = @Exchange(value = "exchange-1", - durable="true", - type= "topic", - ignoreDeclarationExceptions = "true"), - key = "springboot.*" - ) - ) - @RabbitHandler - public void onMessage(Message message, Channel channel) throws Exception { - System.err.println("--------------------------------------"); - System.err.println("消费端Payload: " + message.getPayload()); - Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG); - //手工ACK - channel.basicAck(deliveryTag, false); - } - - - // 使用 配置文件 - @RabbitListener(bindings = @QueueBinding( - value = @Queue(value = "${spring.rabbitmq.listener.order.queue.name}", - durable="${spring.rabbitmq.listener.order.queue.durable}"), - exchange = @Exchange(value = "${spring.rabbitmq.listener.order.exchange.name}", - durable="${spring.rabbitmq.listener.order.exchange.durable}", - type= "${spring.rabbitmq.listener.order.exchange.type}", - ignoreDeclarationExceptions = "${spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions}"), - key = "${spring.rabbitmq.listener.order.key}" - ) - ) - @RabbitHandler - public void onOrderMessage(@Payload Order order, - Channel channel, - @Headers Map headers) throws Exception { - System.err.println("--------------------------------------"); - System.err.println("消费端order: " + order.getId()); - Long deliveryTag = (Long)headers.get(AmqpHeaders.DELIVERY_TAG); - //手工ACK - channel.basicAck(deliveryTag, false); - } -} -``` \ No newline at end of file diff --git "a/docs/Redis/1_\346\246\202\350\277\260.md" "b/docs/Redis/1_\346\246\202\350\277\260.md" index 89d5e019..92dabc04 100644 --- "a/docs/Redis/1_\346\246\202\350\277\260.md" +++ "b/docs/Redis/1_\346\246\202\350\277\260.md" @@ -96,5 +96,3 @@ ZSet 可以实现有序性操作,从而实现排行榜等功能。 一般像 MySQL 这类的数据库的 QPS(Query Per Second,服务器每秒可以执行的查询次数)大概都在 1w 左右(4 核 8g) ,使用 Redis 缓存之后很容易达到 10 w+,甚至最高能达到 30 w+(单机 Redis 的情况,Redis 集群的话会更高)。 由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库,也就提高了系统整体的并发。 - -补充:[缓存](https://www.cyc2018.xyz/%E5%85%B6%E5%AE%83/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BC%93%E5%AD%98.html#%E4%B8%80%E3%80%81%E7%BC%93%E5%AD%98%E7%89%B9%E5%BE%81) \ No newline at end of file diff --git "a/docs/Redis/3_\345\215\225\347\272\277\347\250\213\346\250\241\345\236\213.md" "b/docs/Redis/3_\345\215\225\347\272\277\347\250\213\346\250\241\345\236\213.md" index 35d4b859..50cd7fd4 100644 --- "a/docs/Redis/3_\345\215\225\347\272\277\347\250\213\346\250\241\345\236\213.md" +++ "b/docs/Redis/3_\345\215\225\347\272\277\347\250\213\346\250\241\345\236\213.md" @@ -12,7 +12,7 @@ Redis 基于 Reactor 模式开发了自己的网络事件处理器,这个处 多路复用主要有三种技术:select,poll,epoll。epoll 是最新的也是目前最好的多路复用技术。 - +
### 文件事件处理器 @@ -52,7 +52,7 @@ Redis 选择使用单线程模型处理来自客户端的绝大多数网络请 对于 Redis 中的一些超大键值对,几十 MB 或者几百 MB 的数据并不能在几毫秒的时间内处理完,Redis 可能会需要在释放内存空间上消耗较多的时间。其实释放内存空间的工作可以由后台线程异步进行处理,只需要将键从元数据中删除,而真正的删除操作会在后台异步执行。Redis 引入多线程后,对于一些**大键值对的删除操作**,可以通过**多线程非阻塞地释放内存空间**减少对 Redis 主线程阻塞的时间,提高执行的效率。 -总的来说,Redis 6.0 之前主要还是单线程处理。 +总的来说,**Redis 6.0 之前主要还是单线程处理**。 @@ -78,6 +78,24 @@ io-threads 2 # 官网建议 4 核的机器建议设置为2或3个线程,8 核 ### Redis 6.0 多线程的实现机制 +实现机制流程如下: + +- 主线程负责接收建立连接请求,获取 Socket 放入等待队列 +- 主线程处理完读事件之后,通过轮询调度方法将这些连接分配给这些 IO 线程 +- 主线程阻塞等待 IO 线程读取 Socket 完毕 +- 主线程执行请求命令,请求数据读取并解析完成 +- 主线程阻塞等待 IO 线程将数据回写 Socket 完毕 +- 解除绑定,清空等待队列 + +其中 IO 线程: +- 要么同时在读 Socket,要么同时在写,不会同时读或写 +- 只负责读写 Socket 解析命令,不负责命令处理 + +
### Redis 6.0 多线程和 Memcached 多线程模型对比 + +相同点:都采用了 Master 线程-Worker 线程模型 + +不同点:Memcached 执行主逻辑也是在 Worker 线程里,模型更加简单,实现了真正的线程隔离,符合我们对线程隔离的常规理解。而 Redis 把处理逻辑交还给 Master 线程,虽然一定程度上增加了模型复杂度,但也解决了线程并发安全等问题。 \ No newline at end of file diff --git "a/docs/Redis/5_\346\214\201\344\271\205\345\214\226\346\234\272\345\210\266.md" "b/docs/Redis/5_\346\214\201\344\271\205\345\214\226\346\234\272\345\210\266.md" index 67093b6d..ded71902 100644 --- "a/docs/Redis/5_\346\214\201\344\271\205\345\214\226\346\234\272\345\210\266.md" +++ "b/docs/Redis/5_\346\214\201\344\271\205\345\214\226\346\234\272\345\210\266.md" @@ -89,7 +89,7 @@ AOF 持久化存在的问题: BGREWRITEAOF 原理: -
+
Redis 维护一个 AOF 重写缓冲区(aof_rewrite_buf)。在子进程创建新的 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。 diff --git "a/docs/Redis/7_\347\274\223\345\255\230\351\227\256\351\242\230.md" "b/docs/Redis/7_\347\274\223\345\255\230\351\227\256\351\242\230.md" index 66e48d2b..509860c5 100644 --- "a/docs/Redis/7_\347\274\223\345\255\230\351\227\256\351\242\230.md" +++ "b/docs/Redis/7_\347\274\223\345\255\230\351\227\256\351\242\230.md" @@ -54,7 +54,7 @@ 可以令 k 和 m 都大一些会使得误判率降低,但是这会带来更高的时间和空间开销。 - +
补充:[布隆过滤器详解](https://github.com/Snailclimb/JavaGuide/blob/master/docs/cs-basics/data-structure/bloom-filter.md) diff --git "a/docs/Redis/8_\346\225\260\346\215\256\344\270\200\350\207\264\346\200\247\351\227\256\351\242\230.md" "b/docs/Redis/8_\346\225\260\346\215\256\344\270\200\350\207\264\346\200\247\351\227\256\351\242\230.md" deleted file mode 100644 index e69de29b..00000000 diff --git "a/docs/Redis/8_\351\203\250\347\275\262\346\226\271\345\274\217.md" "b/docs/Redis/8_\351\203\250\347\275\262\346\226\271\345\274\217.md" new file mode 100644 index 00000000..744745c6 --- /dev/null +++ "b/docs/Redis/8_\351\203\250\347\275\262\346\226\271\345\274\217.md" @@ -0,0 +1,350 @@ +Redis 有以下 4 种部署方式: + +# 一、单机模式 + +最基本的部署方式,只需要一台机器负责读写,一般只用于开发人员开发自测。 + +# 二、主从复制模式 + +对于缓存来说,一般都是用来支撑**读高并发**的,主从(Master-Slave)模式架构,一主多从,其中 Master 负责写,并且将数据复制到其它的 Slave 节点,而 Slave 节点负责读。所有的**读请求全部访问 Slave节点**,这样也可以很轻松实现水平扩容,支撑读高并发。 + +单机的 Redis,能够承载的 QPS 大概就在上万到几万不等。对于主从架构,增加 Slave 节点的数量可以使得 Redis的 QPS 达到 10 万以上。 + +
+ +## 主从同步方法 + +Master 节点接收到写请求并处理后,需要告知 Slave 节点数据发生变化,保证主从节点数据一致即为主从同步。主从同步方法有:增量同步、快照同步和无盘复制。 + +### 增量同步 + +Redis 同步的是指令流,Mater 节点会将对自己的状态产生修改的指令记录在本地 buffer 中,然后异步将 buffer 中的指令同步到 Slave 节点,Slave 节点一边执行同步的指令流来达到和 Master 节点一样的状态,一边向主节点反馈同步偏移量。 + +Slave 节点同步数据的时候不会影响 Master 节点的正常工作,也不会影响自己对外提供读服务的功能,Slave 节点会用旧的数据来提供服务,当同步完成后,需要删除旧数据集,加载新数据,此时会暂停对外服务。 + +因为内存的 buffer 是有限的,所以 Master 节点不能将所有的指令都记录在内存 buffer 中。Redis 的复制内存 buffer 是一个定长的环形数组,如果数组内容满了,就会从头开始覆盖前面的内容。 + +### 快照同步 + +节点间网络通信不好,当 Slave 节点同步的速度不如 Master 节点接收新写请求的速度时,buffer 中会丢失一部分指令,Slave 节点中的数据将与 Master 节点中的数据不一致,此时将会触发快照同步。 + +快照同步先在 Master 节点执行 bgsave 生成 rdb 快照文件,然后将快照文件的内容全部传送到 Slave 节点。Slave 节点将快照文件接受完毕后,立即执行一次**全量加载**,加载前会将当前内存数据清空。加载完毕后通知 Master 节点继续进行增量同步。 + +在整个快照同步进行的过程中,Master 节点的 buffer 仍在往前移动,如果快照同步的时间过长或者 buffer 太小,同步期间的增量指令在 buffer 中被覆盖,这样就会导致快照同步完成后无法进行增量复制,然后会再次发起快照同步,如此极有可能会陷入快照同步的死循环。所以需要配置一个合适的 buffer 大小参数,避免快照复制的死循环。 + +
+ +### 无盘复制 + +在进行快照同步时,存在大量的文件 IO 操作,特别是对于非 SSD 磁盘存储时,快照会对系统的负载产生较大影响。特别是当系统正在进行 AOF 的 fsync 操作时如果发生快照复制,fsync 将会被推迟执行,这就会严重影响 Master 节点的服务效率。 + +从 Redis 2.8.18 版开始支持无盘复制。无盘复制指的是 Master 节点会**一边遍历内存,一遍将序列化的内容发送给 Slave 节点,而不是生成完整的 rdb 快照文件后才进行 IO 传输**。Slave 节点还是跟之前一样,先将接收到的内容存储到磁盘文件中,再进行一次性加载。 + +## 主从同步完整流程 + +### 1. 建立连接 + +- Slave 节点配置文件中的 slaveof 配置项中配置 Master 节点的 IP 和 port 后, Slave 节点就知道自己要和那个 Master 节点进行连接。 +- Slave 节点内部有个定时任务,会每秒检查自己要连接的 Master 节点是否上线,如果发现 Master 节点上线,就跟 Master 节点进行网络连接,此时还没有进行主从同步。 +- Slave 节点发送 ping 命令给 Master 节点进行连接,如果设置了口令认证(Master 节点设置了requirepass),那么 Slave 节点必须发送正确的口令(masterauth)进行认证。 + +### 2. 快照同步 + +- Master 和 Slave 节点连接成功后,判断是否进行快照同步:如果 Slave 节点发现已经连接过某个 `run id` 的 Master 节点,则此次连接为重新连接,不会进行快照同步。相同 IP 和 port 的 Master 节点每次重启服务都会生成一个新的 `run id`,所以每次 Master 节点重启服务都会进行一次快照同步,如果想重启主节点服务而不改变 `run id`,使用 `redis-cli debug reload` 命令。 + +- 进行快照同步开始后, Master 节点在本地生成一份 rdb 快照文件,并将这个 rdb 文件发送给 Slave 节点,如果复制时间超过 60 秒(配置项:`repl-timeout`),那么就会认为复制失败,所以数据量比较大,要适当调大这个参数的值。 + + 进行快照同步时,Master 节点会把接收到的新请求命令写到 buffer 中,当快照同步完成后,再把 buffer 中的指令增量同步到 Slave 节点。如果在快照同步期间,内存缓冲区大小超过 64MB / 256MB 的状态持续时间超过60s(配置项:`client-output-buffer-limit slave 256MB 64MB 60`),那么快照同步失败。 + +- Slave 节点接收到 rdb 快照文件后,清空自己的旧数据,然后重新加载 rdb 到自己的内存中,在这个过程中基于旧的数据对外提供服务。如果 Master 节点开启了AOF,那么在快照同步结束后会立即执行 BGREWRITEAOF 命令,重写 AOF 文件。 + +- Master 节点维护了一个 backlog 文件,默认大小是 1MB 。Master 节点向 Slave 节点发送全量数据(即 rdb 快照文件)时,也会同步到 backlog 中,这样当发送全量数据这个过程意外中断后,从 backlog 文件中可以得知数据有哪些是发送成功了,哪些还没有发送,然后当主从节点再次连接后,从失败的地方开始增量同步。**当快照同步连接中断后,主从节点再次连接并非是第一次连接,进行增量同步,而不是继续进行快照同步**。 + +### 3. 增量同步 + +- 快照同步完成后,Master 节点后续接收到写请求导致数据变化后,将和 Slave 节点进行增量同步,遇到 buffer 溢出则会再触发快照同步。 + +## 主从同步补充 + +- 主从节点都会维护一个 offset,随着 Master 节点的数据变化以及主从同步的进行,主从节点会不断累加自己维护的 offset,Slave 节点每秒都会上报自己的 offset 给 Master 节点,Master 节点也会保存每个 Slave 节点的 offset,这样主从节点就能知道互相之间的数据一致性情况。 + + Slave 节点发送`psync runid offset`命令给 Master 节点从而开始主从同步,Master 节点会根据自身的情况返回响应信息,可能是`FULLRESYNC runid offset`触发快照复制,也可能是 `CONTINUE` 触发增量复制。 + +- 主从节点因为网络原因导致断开,当网络接通后,不需要手工干预,可以自动重新连接。 + +- Master 节点如果发现有多个 Slave 节点连接,在快照同步过程中仅仅会生成一个 red 快照文件,用一份数据服务所有 Slave 节点进行快照同步。 + +- Slave 节点不会处理过期 key,当 Slave 节点处理了一个过期 key,会模拟一条 del 命令发送给 Slave 节点。 + +- 主从节点会保持心跳(heartbeat)来检测对方是否在线,Master 节点默认每隔 10 秒发送一次 heartbeat,Slave 节点默认每隔 1 秒发送一个heartbeat。 + +- 建议 Master 节点使用 AOF+RDB 的持久化方式,并且在 Master 节点定期备份 red 快照文件,而 Slave 节点不要开启 AOF 机制,原因有两个: + + - Slave 节点开启 AOF 会降低性能 + - 如果 Master 节点数据丢失,数据同步给 Slave 节点后,Slave 节点会收到空数据,如果开启了 AOF,会生成空的 AOF 文件,基于 AOF 恢复数据后,全部数据就都丢失了,而如果不开启 AOF 机制, Slave 节点启动后,基于自身的 rdb 快照文件恢复数据,不至于丢失全部数据。 + +扩展:[主从模式实战](https://www.jianshu.com/p/f0e042b95249) + + + +# 三、哨兵模式 + +在 Redis 主从复制模式下,一旦 Master 节点由于故障不能提供服务,需要**人工**将 Slave 节点晋升为 Master 节点,再通知所有的程序把 Master 地址统统改一遍,然后重新上线。 + +Redis 从 2.8 开始正式提供了 **哨兵 (sentinel) 架构**来解决这个问题。 + +Redis 中多个 sentinel 组成**分布式架构**,持续监控主从节点的健康状况,当 Master 节点挂掉时,自动选择一个最优的 Slave 节点切换为 Master 节点。客户端在连接集群时,会先连接 sentinel,通过 sentinel 来查询 Master 节点的地址,然后再去连接 Master 节点进行数据交互。当 Master 节点发生故障时,客户端会重新向 sentinel 获取地址,sentinel 会将最新的 Master 节点地址告诉客户端,这样应用程序将无需重启即可自动完成节点切换。 + +
+ +sentinel 集群在 Redis 主从架构高可用中起到的 4 个作用: + +- 集群监控 + sentinel 节点会定期检测 Redis 数据节点、其余 sentinel 节点是否故障。 +- 故障转移 + 实现 Slave 节点晋升为 Master 节点并维护后续正确的主从关系。 +- 配置中心 + sentinel 架构中,客户端在初始化的时候连接的是 sentinel 集群,从中获取 Master 节点信息。 +- 消息通知 + sentinel 节点会将故障转移的结果通知给客户端。 + +注意:使用 sentinel 集群而不是单个 sentinel 节点去监控 Redis 主从架构,这是因为: + +- 对于节点的故障判断由多个 sentinel 节点共同完成,这样可**有效防止误判**。 +- sentinel 集群可以保证自身的**高可用性**,即某个 sentinel 节点自身故障也不会影响 sentinel 集群的健壮性。 + +## 监控功能 + +sentinel 集群通过 3 个定时监控任务完成对各个节点发现和监控: + +- 每隔10 秒,每个 sentinel 节点会向 Master 节点和 Slave 节点发送 info 命令获取 Redis 主从架构的最新情况。 +- 每隔 2 秒,每个 sentinel 节点会向 Redis 数据节点的 `__sentinel__:hello` 这个channel(频道)发送一条消息,该定时任务可以完成以下 2 个工作: + - 发现新的 sentinel节点 + - sentinel 节点之间交换 Master 节点的状态,用于确认 Master 下线和故障处理的 Leader 选举。 +- 每隔 1 秒,每个 sentinel 节点会向 Master 节点、Slave 节点、其余 sentinel 节点发送一条 ping 命令做一次心跳检测,来确认这些节点是否可达。 + +## sdown & odown + +sdown 即主观下线 (subjective down) :一个 sentinel 节点每隔 1 秒对 Master 节点、Slave 节点、其他 sentinel 节点发送 ping 命令做心跳检测,当某个节点超过 + `down-after-milliseconds` 没有进行有效回复,该 sentinel 节点就会认为该节点下线,这就是主观下线。 + +odown 即客观下线 (objective down) :超过 quorum 数量(quorum可配置)的 sentinel 节点认为 Master 节点确实有问题,即大部分是 sentinel 节点都对 Master 节点的下线做了同意的判定,这就是客观下线。 + +## quorum & majority + +只有大于等于 quorum 数量的 sentinel 节点都认为 Master 主观下线,sentinel 集群才会认为 Master 客观下线。 + +quorum 可在 sentinel.conf 中手动配置,默认值为 2: + +```conf +# sentinel monitor [master-name] [master-ip] [master-port] [quorum] +sentinel monitor testmaster 127.0.0.1 6379 2 +# quorum 默认值是 2 +``` + +majority 代表 sentinel 集群中大部分 sentinel 节点数,majority 的计算方法为:majority = num(sentinels) / 2 + 1。例如 2 个节点的 sentinel 集群的 majority 为 2 + 3 个节点的 sentinel 集群的 majority 为 2;4 个节点的 sentinel 集群的 majority为 3。 + +只有大于等于 max(quorum, majority) 个节点给某个 sentinel 节点投票,该 sentinel 节点才能被选为 Leader。 + +注意:sentinel 集群的节点个数至少为 3 个。 + +原因如下:假设当节点数为 2 时,此时一个 sentinel 节点宕机,那么剩余一个节点是无法让自己成为 Leader 的,因为 2 个节点的 sentinel 集群的 majority 是 2,此时没有 2 个节点都给剩余的节点投票,也就无法选择出 Leader,从而无法进行故障转移。 + +此外最好把 quorum 的值设置为小于等于 majority,否则即使 sentinel 集群剩余的节点满足 majority 数,但是有可能不能满足 quorum 数,那还是无法选举 Leader,也就不能进行故障转移。 + +## Leader 选举 + +当 sentinel 集群确认某个 Master 是客观下线了,需要选举出一个 **Leader 节点来进行故障转移**,选举过程如下: + +- 每个在线的 sentinel 节点都有资格成为 Leader,当某个 sentinel 节点确认 Master 节点 odown 时,会向其他 sentinel 节点发送 `sentinel is-master-down-by-addr`命令,要求将自己设置为 Leader。 +- 每个 sentinel 节点都只能投出一票,如果该 sentinel 节点得到的**票数大于 max(quorum, num(sentinels) / 2 + 1)** ,那么该 sentinel 节点成为 Leader。 +- 如果一次选举没有选举出 Leader,那么会进行下一次选举。 + +一般情况下,哪个 sentinel 节点最先确认 Master 客观下线,该 sentinel 节点就会成为执行故障转移的 Leader。 + +## 新 Master 选择 + +要执行故障转移,首先要从 Slave 中选择一个作为新的 Master。 + +不选择不健康的 Slave,以下状态的 slave 是不健康的: + +- 主观下线的 Slave +- 与 Master 失联超过`down-after-milliseconds * 10`秒的 Slave +- 大于等于 5 秒没有回复过 sentinel 节点 ping 响应的 Slave + +对健康的 slave 进行排序: + +- 选择 priority(可配置,默认100)最低的 Slave 节点,如果有优先级相同的节点,进行下一步。注意如果 priority=0,那么禁止该节点成为 Master +- 选择复制偏移量最大的 Slave 节点(复制的最完整),如果有复制偏移量相等的节点,进行下一步 +- 选择 runid 最小的 Slave 节点 + +## 故障转移 + +选举出 Leader 和新 Master 后,由 Leader 进行故障转移: + +- Leader 对选举出的新 Master(此时还是 Slave)执行 `slaveof no one` 命令让其成为 Master。 +- Leader 向剩余 Slave 发送命令,使它们称为新 Master 的 Slave。 +- Leader 会将原来的 Master 更新为 Slave,并保持着对其关注,当其恢复后命令它去复制新 Master。 + +## configuration epoch + +configuration epoch 是当前 Redis 主从架构的配置版本号,无论是 sentinel 集群选举 Leader 还是进行故障转移的时候,要求各 sentinel 节点得到的 configuration epoch 都是相同的,`sentinel is-master-down-by-addr` 命令中就必须有当前配置版本号这个参数,在选举 Leader 过程中,如果本次选举失败,那么进行下一次选举,就会更新配置版本号,也就是说,每次选举都对应一个新的 configuration epoch,在故障转移的过程中,也要求各个 sentinel 节点使用相同的 configuration epoch。 + +在故障转移成功之后,Leader 会更新生成最新的 master 配置,configuration epoch 也会更新,然后同步给其他的 sentinel 节点,这样保证 sentinel 集群中保存的 Master 和 Slave 配置都是最新的,当 Client 请求的时候就会拿到最新的配置信息。 + +## 数据丢失问题 + +### 数据丢失原因 + +Redis sentinel 可能会导致数据丢失: + +- 异步复制导致的数据丢失 + + Master 到 Slave 的复制是异步的,所以可能有部分数据还没复制到 Slave,Master 就宕机了,此时这部分数据就丢失了。 + +- 脑裂导致的数据丢失 + + 某个 Master 所在机器突然网络故障,跟其他 Slave 机器不能连接,但是实际上 Master 还运行着。sentinel 会认为该 Master 宕机了,然后开启选举,将其他 Slave 切换成了 Master,集群里就会有两个 Master,也就是所谓的脑裂。 + + 虽然某个 Slave 被切换成了 Master,但是 Client 还没来得及切换到新的 Master,还继续写向旧 Master 。旧 Master 再次恢复的时候,会被作为一个 Slave 挂到新的 Master 上去,自己的数据会清空,重新从新的 Master 复制数据,而新的 Master 并没有后来 Client 写入的数据,这部分数据就丢失了。 + +### 解决方案 + +Redis 提供了两个配置参数可以尽量丢失少的数据: + +```conf +min-slaves-to-write 1 +min-slaves-max-lag 10 +``` + +Master 至少有 1 个 slave,数据复制和同步的延迟不能超过 10 秒。如果说一旦所有的 Slave,数据复制和同步的延迟都超过了 10 秒钟,那么 Master 就不会再接收任何请求。 + +- 减少异步复制数据的丢失 + + `min-slaves-max-lag` 配置可确保一旦 Slave 复制数据和 ack 延时太长,就认为可能 Master 宕机后损失的数据太多了,那么就拒绝写请求,这样可以把 Master 宕机时由于部分数据未同步到 Slave 导致的数据丢失降低的可控范围内。 + +- 减少脑裂的数据丢失 + + 如果一个 Master 出现了脑裂,跟其他 Slave 丢了连接,那么上面两个配置可以确保如果不能继续给指定数量的 Slave 发送数据且 Slave 超过 10 秒没有给自己 ack 消息,那么就直接拒绝客户端的写请求。因此在脑裂场景下,最多就丢失 10 秒的数据。 + +注意:redis-2.6 版本提供的是 redis sentinel v1 版本,但是功能性和健壮性都有一些问题。如果想使用 redis sentinel 的话,建议使用 2.8 以上版本。 + +扩展:[哨兵模式实战](https://www.jianshu.com/p/9d873e7a205a) + + + +# 四、Cluster 集群模式 + +## Redis Cluster 架构 + +单 Master 架构中 Master 节点的数据和 Slave 节点的数据是一模一样的,Master 节点的最多能容纳多少数据量,Slave 节点也就只能容纳这么多数据。当数据量超过 Master 的内存,Redis 会使用 LRU 算法清除部分数据。如果确实要容纳更多的数据量,Redis 主从架构是无法解决这个问题的。 + +Redis Cluster 是 Redis 的**分布式解决方案**,Redis 3.0 正式推出,解决单Master 架构的内存、并发、流量等瓶颈,以达到负载均衡的目的。 + +
+ +Redis cluster 适用于海量数据、高并发、高可用场景,在 Redis Cluster 架构中: + +- 每个 Master 负责整个集群的一部分数据,每个节点负责数据量可能不一样 +- 每个 Master 的角色是对等的,每个 Master 节点都可以有多个 Slave 节点,当一个 Master 节点挂掉后,它的其中一个 Slave 节点升级为 Master +- Redis Cluster 已经自动具备了主从复制能力,直接集成了 replication 和 sentinel 的功能。 + +## 分布式寻址算法 + +### Hash 算法 + +#### 思路 + +根据 key 计算 Hash 值,然后对节点数取模,将 key 分配到对应的 Master 中。 + +#### 问题 + +一旦某个 Master 宕机,就需要调整 hash 算法,所有的数据都需要重新计算取模,然后重新分配数据。大部分的请求都无法正确的拿到数据,从而不得不去访问数据库,在高并发场景下,这样是不能接受的,所以目前分布式缓存不再使用此种算法分配数据。 + +### 一致性 Hash 算法 + +#### 思路 + +将哈希空间 [0, 2^n-1] 看成一个哈希环,每个服务器节点都配置到哈希环上。每个数据对象通过哈希取模得到哈希值之后,存放到哈希环中**顺时针方向**第一个大于等于该哈希值的节点上。 + +例如有 Object A、Object B、Object C、Object D 四个数据对象,经过哈希计算后,在哈希环上的位置如下: + +
+ +根据一致性 Hash 算法:Object A 会被定位到 Node A 上;Object B 会被定位到 Node B 上;Object C 会被定位到 Node C 上;Object D 会被定位到 Node D 上。 + +一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点: + +例如删除节点 C,只需将 C 上的数据分布到节点 D 即可。 + +
+ +例如新增节点 X,只需要将它前一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。 + +
+ +综上所述,一致性 Hash 算法对于节点的增减都只需**重定位哈希环中的一小部分数据**,具有**较好的容错性和可扩展性**。 + +#### 问题 + +- 加减节点会造成哈希环中部分数据无法命中,当一个 Master 挂掉之后,例如节点 A 挂掉,那么当请求从 A 获取数据时,是获取不到的,于是继续顺时针去节点 B、节点 C、节点 D 获取数据,当然也是获取不到的,需要手动处理这些无法命中的数据 +- 节点数量越多,增减节点带来的影响越小,因此不适用与集群中只有少量节点的情况 +- 容易造成数据热点问题 + +#### 优化-虚拟节点 + +一致性哈希存在数据分布不均匀的问题,节点存储的数据量有可能会存在很大的不同。数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。 + +
+ +解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得多,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 + +例如针对上面的情况,可以为每台服务器计算 3 个虚拟节点: + +- Node A 的 3 个虚拟节点:"Node A#1"、"Node A#2"、"Node A#3" +- Node B 的 3 个虚拟节点:"Node B#1"、"Node B#2"、"Node B#3" + +
+ +同时**数据定位算法不变**,只是多了一步虚拟节点到实际节点的映射过程,例如"Node A#1"、"Node A#2"、"Node A#3" 这 3 个虚拟节点的数据均定位到 Node A 上,解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为 32 甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。 + +### hash slot 算法 + +#### 思路 + +Redis Cluster **使用 16384 个槽 (slot)** 来管理一段整数集合 (哈希值),slot 是集群内数据管理和迁移的基本单位。 + +每个 Master 节点负责管理一部分 slot,例如有 5 个节点,那个每个节点管理大约 3276 (16384 / 5 )个槽。对每个 key 使用 CRC32 算法进行哈希得到哈希值,使用哈希值对 16384 进行取模,得到此数据应该分配到的 slot 编号。每个 Master 管理的 slot 的信息就缓存在本地,客户端连接集群时,会获取集群 slot 配置信息,从而通过 key 精确找到 slot 所在的节点,此外还可以强制分配某个 key 到指定的 slot 上。 + +#### 优点 + +- 解耦数据和节点之间的关系,简化了节点扩容和收缩难度: + + 增加一个 Master,就让其他的 Master 分一部分 slot 给新的 Master 管理; + + 移除一个 Master,就把这个 Master 管理的 slot 分配给其他的 Master。 + +- 某个 Master 挂掉,不影响整个集群,因为请求是到 slot,而不是到 Master,但在 slot 迁移完成之前,请求到挂掉的节点也是不行的。 + +- slot 迁移的过程是很快的 + +- 节点自身维护 slot 的映射关系,无需人为管理 + +- 支持槽、节点、key之间的映射关系查询 + +### Redis 故障恢复 + +判断故障的逻辑其实与哨兵模式有点类似,在集群中,每个节点都会**定期的向其他节点发送 ping 命令**,通过有没有收到回复来判断其他节点是否已经下线。 + +如果**长时间没有回复,那么发起 ping 命令的节点就会认为目标节点疑似下线**,也可以和哨兵一样称作主观下线,当集群中超过半数的节点都认为该节点下线则判定该节点下线。 + +对宕机的 Master 节点,从其所有的 Slave 节点中选择一个切换成 Master,需要检查每个 Slave 节点与 Master 节点断开连接的时间,如果超过了 `cluster-node-timeout * cluster-slave-validity-factor` ,那么该 Slave 就没有资格切换成 Master。 + +每个 Slave 节点,都根据自己对 Master 复制数据的 offset,来设置一个选举时间,offset 越大(复制数据越多)的 Slave 节点,选举时间越靠前,优先进行选举。 + +所有的 Master 节点给要进行选举的 Slave 进行投票,如果超过半数的 Master 节点都投票给了某个 Slave 节点,那么选举通过,那个该 Slave 节点可以切换成 Master。 + +扩展:[Redis Cluster搭建及测试](https://www.jianshu.com/p/48713d6f35b8) + +补充:[Redis-简书](https://www.jianshu.com/nb/33672761) diff --git "a/docs/Redis/9_\345\256\236\346\210\230.md" "b/docs/Redis/9_\345\256\236\346\210\230.md" index 8b137891..3759be90 100644 --- "a/docs/Redis/9_\345\256\236\346\210\230.md" +++ "b/docs/Redis/9_\345\256\236\346\210\230.md" @@ -1 +1,32 @@ +# Redis 实战——实现简单点赞系统 + +该点赞系统功能如下: + +- 可以发布文章 +- 可以对文章进行点赞 +- 在首页可以按文章的发布时间或者文章的点赞数进行排序显示 + +## 文章信息存储 + +文章包括标题、作者、赞数等信息,在关系型数据库中很容易构建一张表来存储这些信息,在 Redis 中可以使用 HASH 来存储每种信息以及其对应的值的映射。 + +
+ +## 点赞功能实现 + +当有用户为一篇文章点赞时,除了要对该文章的 votes 字段进行加 1 操作,还必须记录该用户已经对该文章进行了点赞,防止用户点赞次数超过 1。可以建立文章的已投票用户集合来进行记录。 + +为了节约内存,规定一篇文章发布满一周之后,就不能再对它进行投票,而文章的已投票集合也会被删除,可以为文章的已投票集合设置一个一周的过期时间就能实现这个规定。 + +
+ +## 对文章进行排序 + +为了按发布时间和点赞数进行排序,可以建立一个文章发布时间的有序集合和一个文章点赞数的有序集合。(下图中的 score 就是这里所说的点赞数;下面所示的有序集合分值并不直接是时间和点赞数,而是根据时间和点赞数间接计算出来的) + +
+ +115423 号用户给 100408 号文章投票的时候,数据结构发生的变化: + +
diff --git "a/docs/Redis/cankao/1_Redis\345\210\235\346\216\242.md" "b/docs/Redis/cankao/1_Redis\345\210\235\346\216\242.md" deleted file mode 100644 index 85e48143..00000000 --- "a/docs/Redis/cankao/1_Redis\345\210\235\346\216\242.md" +++ /dev/null @@ -1,307 +0,0 @@ -# 初探 Redis - -## Redis 简介 - -Redis 是一个速度非常快的非关系型数据库(non-relational database)/ NoSQL 数据库。 - -Redis 不使用表,也不会预定义或者强制去要求用户对 Redis 存储不同的数据进行关联。 - -> **Redis 为什么速度非常快?** - -- **纯内存操作** - - 数据存在内存中,类似于 HashMap。HashMap 的优势就是查找和操作的时间复杂度都是 O(1) - -- **数据结构简单** - - 不仅数据结构简单,而且对数据操作也简单 - -- **单线程** - - 避免了频繁的上下文切换,也不存在多进程或者多线程导致的切换而消耗 CPU 资源,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗 - -## Redis 数据结构 - -Redis 存储键(key)和 5 种不同类型的值(value)之间的映射。这 5 中类型分别为: - -STRING(字符串)、LIST(列表)、HASH(散列)、SET(集合)和 ZSET(有序集合)。 - -| 结构类型 | 结构存储的值 | -| :------: | :----------------------------------------------------------: | -| STRING | 字符串、整数或者浮点数 | -| LIST | 一个链表,链表上的每个节点都包含了一个字符串 | -| HASH | 包含键值对的无序散列表 | -| SET | 包含字符串的无序收集器 | -| ZSET | 字符串成员(member)与浮点数(score)分值之间的有序映射,
元素的排列顺序由分值大小决定 | - - - -### 1. STRING(字符串) - -字符串示例,键为 hello,值为 world: - -
- -- 字符串命令: - - | 命令 | 行为 | 时间复杂度 | - | :--: | :------------------------------------------------: | :--------: | - | GET | 获取存储在给定键中的值 | O(1) | - | SET | 设置存储在给定键中的值 | O(1) | - | DEL | 删除存储在给定键中的值(这个命令可以用于所有类型) | O(1) | - | INCR | 自增 | O(1) | - | DECR | 自减 | O(1) | - -- 使用 - - ```html - 127.0.0.1:6379> set hello world - OK - 127.0.0.1:6379> get hello - "world" - 127.0.0.1:6379> del hello - (integer) 1 - 127.0.0.1:6379> get hello - (nil) - ``` - - ```html - 127.0.0.1:6379> set num 1 - OK - 127.0.0.1:6379> incr num - (integer) 2 - 127.0.0.1:6379> get num - "2" - ``` - - -### 2. LIST(列表) - -list-key 是一个包含 3 个元素的列表键,列表中的元素是可以重复的: - -
- -- 列表命令: - - | 命令 | 行为 | 时间复杂度 | - | :----: | :--------------------------------------: | :--------: | - | LPUSH | 将给定值推入链表的左端 | O(N) | - | RPUSH | 将给定值推入链表的右端 | O(N) | - | LRANGE | 获取列表在给定范围上的所有值 | O(N) | - | LINDEX | 获取列表在给定位置上的单个元素 | O(N) | - | LPOP | 从链表的左端弹出一个值,并返回被弹出的值 | O(1) | - -- 使用 - - ```html - 127.0.0.1:6379> rpush list-key item - (integer) 1 - 127.0.0.1:6379> rpush list-key item2 - (integer) 2 - 127.0.0.1:6379> rpush list-key item - (integer) 3 # 返回的列表长度 - ``` - - ```html - 127.0.0.1:6379> lrange list-key 0 -1 - 1) "item" - 2) "item2" - 3) "item" - # 使用 0 为范围的开始索引,-1 为范围索引的结束索引,可以去除列表包含的所有元素 - 127.0.0.1:6379> lindex list-key 1 - "item2" - ``` - - ```html - 127.0.0.1:6379> lpop list-key - "item" - 127.0.0.1:6379> lrange list-key 0 -1 - 1) "item2" - 2) "item" - ``` - - -### 3. HASH(散列) - -hash-key 是一个包含两个键值对的散列键: - -
- -- 散列命令: - - | 命令 | 行为 | 时间复杂度 | - | :-----: | :--------------------------------------: | :--------: | - | HSET | 在散列表中关联其给定的键值对 | O(1) | - | HGET | 获取指定散列键的值 | O(1) | - | HGETALL | 获取散列包含的所有键值对 | O(N) | - | HDEL | 如果给定键存在于散列表中,那么移除这个键 | O(N) | - -- 使用 - - ```html - 127.0.0.1:6379> hset hash-key sub-key1 value1 - (integer) 1 - 127.0.0.1:6379> hset hash-key sub-key2 value2 - (integer) 1 - 127.0.0.1:6379> hset hash-key sub-key1 value2 - (integer) 0 - 127.0.0.1:6379> hgetall hash-key - 1) "sub-key1" - 2) "value2" - 3) "sub-key2" - 4) "value2" - ``` - - ```html - 127.0.0.1:6379> hdel hash-key sub-key2 - (integer) 1 - 127.0.0.1:6379> hdel hash-key sub-key2 - (integer) 0 - 127.0.0.1:6379> hget hash-key sub-key1 - "value2" - 127.0.0.1:6379> hgetall hash-key - 1) "sub-key1" - 2) "value2" - ``` - - -### 4. SET(集合) - -set-key 是一个包含 3 个元素的集合键: - -
- - - -- 集合命令: - - | 命令 | 行为 | 时间复杂度 | - | :-------: | :------------------------------------------: | :--------: | - | SADD | 将给定元素添加到集合 | O(N) | - | SMEMBERS | 返回集合包含的所有元素 | O(N) | - | SREM | 如果给定的元素存在于集合中,那么一处这个元素 | O(N) | - | SISMEMBER | 检查给定元素是否存在于集合中 | O(1) | - -- 使用 - - ```html - 127.0.0.1:6379> sadd set-key item - (integer) 1 - 127.0.0.1:6379> sadd set-key item2 - (integer) 1 - 127.0.0.1:6379> sadd set-key item3 - (integer) 1 - 127.0.0.1:6379> sadd set-key item - (integer) 0 - 127.0.0.1:6379> smembers set-key - 1) "item" - 2) "item3" - 3) "item2" - ``` - - ```html - 127.0.0.1:6379> sismember set-key item4 - (integer) 0 - 127.0.0.1:6379> sismember set-key item - (integer) 1 - ``` - - ```html - 127.0.0.1:6379> srem set-key item - (integer) 1 - 127.0.0.1:6379> srem set-key item - (integer) 0 - 127.0.0.1:6379> smembers set-key - 1) "item3" - 2) "item2" - ``` - - - -### 5. ZSET(有序集合) - -zset-key 是已一个包含 2 个元素的有序集合键: - -
- -- 有序集合命令: - - | 命令 | 行为 | 时间复杂度 | - | :-----------: | :------------------------------------------------------: | :---------: | - | ZADD | 将一个带有给定分值的成员添加到有序集合里面 | O(Mlog(N)) | - | ZRANGE | 根据元素在有序排列中所处的位置,从有序集合中获取多个元素 | O(log(N)+M) | - | ZRANGEBYSCORE | 获取有序集合在给定范围内的所有元素 | O(log(N)+M) | - | ZREM | 如果给定成员存在于有序集合,那么移除这个成员 | O(Mlog(N)) | - -- 使用 - - ```html - 127.0.0.1:6379> zadd zset-key 728 member1 - (integer) 1 - 127.0.0.1:6379> zadd zset-key 982 member2 - (integer) 1 - 127.0.0.1:6379> zadd zset-key 982 member2 - (integer) 0 - 127.0.0.1:6379> zrange zset-key 0 -1 withscores - 1) "member1" - 2) "728" - 3) "member2" - 4) "982" - ``` - - ```html - 127.0.0.1:6379> zrangebyscore zset-key 0 800 withscores - 1) "member1" - 2) "728" - ``` - - ```html - 127.0.0.1:6379> zrem zset-key member1 - (integer) 1 - 127.0.0.1:6379> zrem zset-key member1 - (integer) 0 - 127.0.0.1:6379> zrange zset-key 0 -1 withscores - 1) "member2" - 2) "982" - ``` - - -> **扩展** - -- [Redis 常用命令时间复杂度](https://blog.csdn.net/zzm848166546/article/details/80360665) -- [Redis 命令大全](https://redis.io/commands) - - - -## Redis 与 Memcached - -两者都是非关系型内存键值数据库,主要有以下不同: - -### 数据类型 - -- Redis 支持五种不同的数据类型,可以更灵活地解决问题 - -- Memcached 仅支持字符串类型 - -### 数据持久化 - -- Redis 支持两种持久化策略:RDB 快照和 AOF 日志 - -- Memcached 不支持持久化。 - -### 分布式 - -- Redis Cluster 实现了分布式的支持 - -- Memcached 不支持分布式,只能通过在客户端使用一致性哈希来实现分布式存储,这种方式在存储和查询时都需要先在客户端计算一次数据所在的节点。 - -### 内存管理机制 - -- 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘,而 Memcached 的数据则会一直在内存中。 -- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。 - -### 线程模型 - -- Redis 使用单线程的多路 IO 复用模型 - -- Memcached 是多线程,非阻塞IO复用的网络模型 \ No newline at end of file diff --git "a/docs/Redis/cankao/1_\346\246\202\350\277\260.md" "b/docs/Redis/cankao/1_\346\246\202\350\277\260.md" deleted file mode 100644 index 30435c24..00000000 --- "a/docs/Redis/cankao/1_\346\246\202\350\277\260.md" +++ /dev/null @@ -1,12 +0,0 @@ -# Redis 概述 - -Redis 是速度非常快的**非关系型(NoSQL)**基于**内存**的**键值**数据库。其中,键的类型只能为字符串,值支持五种数据类型:字符串(stirng)、列表(list)、集合(set)、散列表(hash)、有序集合(zset)。 - -Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展**读性能**,使用分片来扩展**写性能**。 - -Redis 除了做缓存之外,也经常用来做分布式锁,甚至是消息队列。 - - - -![1631625686492](C:\Users\DuHouAn\AppData\Roaming\Typora\typora-user-images\1631625686492.png) - diff --git "a/docs/Redis/cankao/2_Redis\346\214\201\344\271\205\345\214\226.md" "b/docs/Redis/cankao/2_Redis\346\214\201\344\271\205\345\214\226.md" deleted file mode 100644 index 2f822159..00000000 --- "a/docs/Redis/cankao/2_Redis\346\214\201\344\271\205\345\214\226.md" +++ /dev/null @@ -1,145 +0,0 @@ -# Redis 持久化 - -Redis 是内存型数据库,为了保证数据断电后不丢失,需要将内存中的数据持久化到磁盘上;另一方面,保存中间结果,不必重新计算。 - -持久化有 2 种: - -- 快照持久化:将存在某一时刻的所有数据都写入磁盘中 -- AOF 持久化:在执行写命令时,将被执行的写命令复制到文件中 - -Redis 提供的持久化配置选项: - -```html -# 快照持久化 -save 60 1000 -stop-writes-on-bgsave-error yes -rdbcompression no - -# AOF 持久化 -appendonly yes -appendfsync always # 同步选项 -auto-aof-rewrite-percentage 100 -auto-aof-rewrite-min-size 64mb - -# 共享选项,决定了快照文件和 AOF 文件的保存位置 -dir ./ -``` - - - -## 快照持久化 - -快照持久化是通过创建快照来获得 Redis 存储在内存中数据在某个时间点上的副本。在创建快照后,用户可对快照备份,可将快照留在原地以便重启 Redis 时使用。 - -### 快照持久化配置 - -```html -save 60 10000 -# 在60秒(1分钟)之后,如果至少有10000个键发生变化,Redis 就会自动触发 BGSAVE 命令创建快照。 - -stop-writes-on-bgsave-error yes -# 表示备份进程出错的时候,主进程就停止接收新的写入操作,是为了保护持久化数据的一致性。 - -rdbcompression no -# RDB 的压缩设置为 no,因为压缩会占用更多的 CPU 资源。 -``` - - - -### 创建快照的方法 - -- BGAVSE 命令 - - 客户端向 Redis 发送 BGSAVE 命令来创建一个快照。对于支持 BGSAVE 命令的平台来说(基本上所有平台支持,除了Windows平台),**Redis 会调用 fork 来创建一个子进程,然后子进程负责将快照写入硬盘,而主进程则继续处理命令请求**。 - -- 用户设置 save 配置选项 - - ```html - save 60 10000 - # 从 redis 最近一次创建快照之后算起,满足 “60 s 内 10000 次写入”,Redis 会自动触发 BGSAVE 命令 - ``` - - - -### 存在的问题 - -- 如果系统发生故障,将会丢失**最近一次创建快照之后的数据** -- 如果数据量很大,保存快照的时间会很长 - - - -## AOF 持久化 - -AOF 持久化将被执行的写命令写到 AOF 文件末尾,记录数据发生的变化。Redis 值要从头到尾重新执行一次 AOF - -文件包含的所有写命令,就可恢复 AOF 文件所记录的数据。 - -默认情况下,Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启: - -```html -appendonly yes -``` - - - -### 快照持久化配置 - -```java -appendonly yes - -appendfsync always # 同步选项 - -auto-aof-rewrite-percentage 100 - -auto-aof-rewrite-min-size 64mb -``` - - - -### 同步选项 - -使用 AOF 持久化需要设置同步选项,从而确保写命令什么时候会同步到磁盘文件上。 - -| 同步选项 | 同步频率 | 说明 | -| :------: | :--------------------------------------------: | :----------------------------------------------------------: | -| always | 每个 Redis 写命令都要同步写入磁盘 | 当系统发生崩溃时,丢失的数据减到最少;
需要对磁盘大量写入,速度会受到磁盘限制 | -| everysec | 每秒执行一次同步,显示地将多个写命令同步到磁盘 | 性能上和不使用任何持久化特性时相差无几,
可保证数据即使出现系统崩溃,用户也最多只会丢失 1 秒内产生的数据 | -| no | 由操作系统来决定何时进行同步 | 不会对 Redis 性能产生影响,但系统崩溃将导致 Redis 丢失不定量的数据,
若用户写入磁盘处理写入速度不够快,当缓冲区被等待写入磁盘的数据填满时,Redis 写入操作会被阻塞,并导致 Redis 处理命令请求变慢 | - - - -## 重写 / 压缩 AOF 文件 - -AOF 持久化存在的问题: - -- 随着 Redis 不断运行,AOF 文件的体积会不断增长,占用更多的磁盘空间 -- 若 AOF 文件体积非常大,则恢复的时间可能会比较长 - -为了解决 AOF 文件不断增大的问题,我们采用重写 / 压缩 AOF 文件的方式: - -用户 Redis 发送 BGREWRITEAOF 命令,通过移除 AOF 文件中冗余命令来重写 AOF 文件来减小 AOF 文件的体积。 - -(新的 AOF 文件和原有的 AOF 文件所保存的数据状态是一致的,但是体积更小)。 - -BGREWRITEAOF 原理: - -
- -Redis 维护 AOF 重写缓冲区和 AOF 缓冲区。子进程创建新的 AOF 文件期间,记录服务器执行的所有写命令会同时写入 2 个缓冲区中,使得新旧两个 AOF 文件中所保存的数据状态一致。 - - - -## 对比 - -| 持久化方式 | 优点 | 缺点 | -| :--------: | :--------------------------------------------------: | :----------------------------------------------------------: | -| 快照持久化 | 文件小,恢复快 | 会丢失最近一次生成快照后写入的数据;
是压缩文件,可读性较差 | -| AOF 持久化 | 可读性好;
数据不易丢失(丢失 1 秒内产生的数据) | 文件体积大,占用磁盘空间;
恢复时间长 | - - - -## 优化 - -Redis 4.0 以后将快照和 AOF 混合持久化(默认关闭,使用 `aof-user-rdb-preamble`开启),AOF 重写时将快照写入 AOF 文件开头。 - -这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据,当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。 \ No newline at end of file diff --git "a/docs/Redis/cankao/3_Redis\345\244\215\345\210\266.md" "b/docs/Redis/cankao/3_Redis\345\244\215\345\210\266.md" deleted file mode 100644 index 7198853f..00000000 --- "a/docs/Redis/cankao/3_Redis\345\244\215\345\210\266.md" +++ /dev/null @@ -1,5 +0,0 @@ -# Redis 复制 - -## 配置 - -## Redis 复制启动过程 diff --git "a/docs/Redis/cankao/4_\345\244\204\347\220\206\347\263\273\347\273\237\346\225\205\351\232\234.md" "b/docs/Redis/cankao/4_\345\244\204\347\220\206\347\263\273\347\273\237\346\225\205\351\232\234.md" deleted file mode 100644 index 29d25f59..00000000 --- "a/docs/Redis/cankao/4_\345\244\204\347\220\206\347\263\273\347\273\237\346\225\205\351\232\234.md" +++ /dev/null @@ -1,2 +0,0 @@ -# 处理系统故障 - diff --git "a/docs/Redis/cankao/5_Redis\344\272\213\345\212\241.md" "b/docs/Redis/cankao/5_Redis\344\272\213\345\212\241.md" deleted file mode 100644 index 13ed34bc..00000000 --- "a/docs/Redis/cankao/5_Redis\344\272\213\345\212\241.md" +++ /dev/null @@ -1,33 +0,0 @@ -# Redis 事务 - -## 命令 - -- MULTI命令: - - 将客户端从非事务状态切换到事务状态,标志着事务的开始。 - -- EXEC命令: - - 客户端向服务端发送该命令后,服务器会遍历这个客户端的事务队列,并将所有命令的执行结果返回给客户端。 - -- WATCH命令: - - 乐观锁,可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行的时候,检查被监视的键是否至少有一个已经被修改过了,如果有,服务器将拒绝执行该事务,并向客户端返回代表事务执行失败的空回复。 - -## 简述 - -**Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务功能**。 - -事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制。服务器在执行事务期间,不会改去执行其它客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。 - -事务中的多个命令被一次性发送给服务器,而不是一条一条发送,这种方式被称为**pipeline**。 - -注意: - -- Redis 最简单的事务实现方式是使用 MULTI 和 EXEC 命令将事务操作包围起来。 - -- 使用 pineline 的好处:Redis 使用的是客户端 / 服务器(C/S)模型和请求/响应协议的 TCP 服务器。Redis 客户端与 Redis 服务器之间使用 TCP 协议进行连接,一个客户端可以通过一个 Socket 连接发起多个请求命令。每个请求命令发出后客户端通常会阻塞并等待 Redis 服务器处理,Redis 处理完请求命令后会将结果通过响应报文返回给客户端,因此当执行多条命令的时候都需要等待上一条命令执行完毕才能执行。 - - pipeline 可以一次性发送多条命令并在执行完后一次性将结果返回,可以减少客户端与服务器之间的**网络通信次数**从而提升性能,并且 **pineline 基于队列**,而队列的特点是先进先出,这样就保证数据的**顺序性**。 - -- Redis 的事务和传统关系型数据库事务的最大区别在于,**Redis 不支持事务回滚机制(rollback)**,即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。因为其作者认为,Redis 事务执行时错误通常都是编程错误产生的,这种错误通常只会出现在开发环境中,而很少会在实际的生产环境中出现,所以他任务没有必要开发 Redis 的回滚功能。 \ No newline at end of file diff --git "a/docs/Redis/cankao/6_Redis\346\200\247\350\203\275\346\226\271\351\235\242\346\263\250\346\204\217\344\272\213\351\241\271.md" "b/docs/Redis/cankao/6_Redis\346\200\247\350\203\275\346\226\271\351\235\242\346\263\250\346\204\217\344\272\213\351\241\271.md" deleted file mode 100644 index 7e7be7de..00000000 --- "a/docs/Redis/cankao/6_Redis\346\200\247\350\203\275\346\226\271\351\235\242\346\263\250\346\204\217\344\272\213\351\241\271.md" +++ /dev/null @@ -1,2 +0,0 @@ -# Redis 性能方面注意事项 - diff --git "a/docs/Redis/cankao/7_\351\231\215\344\275\216\345\206\205\345\255\230\345\215\240\347\224\250.md" "b/docs/Redis/cankao/7_\351\231\215\344\275\216\345\206\205\345\255\230\345\215\240\347\224\250.md" deleted file mode 100644 index e99bc3f1..00000000 --- "a/docs/Redis/cankao/7_\351\231\215\344\275\216\345\206\205\345\255\230\345\215\240\347\224\250.md" +++ /dev/null @@ -1,2 +0,0 @@ -# 降低内存占用 - diff --git "a/docs/Redis/cankao/8_\347\256\200\345\215\225\347\202\271\350\265\236\347\263\273\347\273\237.md" "b/docs/Redis/cankao/8_\347\256\200\345\215\225\347\202\271\350\265\236\347\263\273\347\273\237.md" deleted file mode 100644 index 85ea9405..00000000 --- "a/docs/Redis/cankao/8_\347\256\200\345\215\225\347\202\271\350\265\236\347\263\273\347\273\237.md" +++ /dev/null @@ -1,33 +0,0 @@ -# 简单点赞系统 - -该点赞系统功能如下: - -- 可以发布文章 -- 可以对文章进行点赞 -- 在首页可以按文章的发布时间或者文章的点赞数进行排序显示 - -## 文章信息 - -文章包括标题、作者、赞数等信息,在关系型数据库中很容易构建一张表来存储这些信息,在 Redis 中可以使用 HASH 来存储每种信息以及其对应的值的映射。 - -
- - - -## 点赞功能 - -当有用户为一篇文章点赞时,除了要对该文章的 votes 字段进行加 1 操作,还必须记录该用户已经对该文章进行了点赞,防止用户点赞次数超过 1。可以建立文章的已投票用户集合来进行记录。 - -为了节约内存,规定一篇文章发布满一周之后,就不能再对它进行投票,而文章的已投票集合也会被删除,可以为文章的已投票集合设置一个一周的过期时间就能实现这个规定。 - -
- -## 对文章进行排序 - -为了按发布时间和点赞数进行排序,可以建立一个文章发布时间的有序集合和一个文章点赞数的有序集合。(下图中的 score 就是这里所说的点赞数;下面所示的有序集合分值并不直接是时间和点赞数,而是根据时间和点赞数间接计算出来的) - -
- -115423 号用户给 100408 号文章投票的时候,数据结构发生的变化: - -
diff --git "a/docs/Redis/cankao/9_\344\275\277\347\224\250\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/docs/Redis/cankao/9_\344\275\277\347\224\250\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index d5000a0d..00000000 --- "a/docs/Redis/cankao/9_\344\275\277\347\224\250\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,106 +0,0 @@ -# 使用缓存常见问题 - -## 缓存雪崩 - -### 问题 - -缓存雪崩是指在我们设置缓存时采用了**相同的过期时间**,导致**缓存在某一时刻同时失效**,请求全部转发到数据库,数据库瞬时压力过重雪崩。 - -### 解决 - -缓存雪崩的事前事中事后的解决方案如下: - -- 事前: - - 尽量保证整个 Redis 集群的高可用性; - - 选择合适的内存淘汰策略。比如将缓存失效时间分散开。 - -- 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 雪崩。 - -- 事后:利用 Redis 持久化机制保存的数据快速恢复缓存。 - -## 缓存穿透 - -### 问题 - -缓存穿透是指查询**一个一定不存在的数据**,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,数据库可能就挂掉了,有人利用不存在的键频繁攻击我们的应用,这就是漏洞。 - -### 解决 - -- 简单粗暴的方法:如果一个查询返回的数据为空(不管数据是否存在,还是系统故障),我们仍然把这个**空结果进行缓存**,但它的过期时间会很短,最长不超过 5 分钟。 -- **布隆过滤器**:布隆过滤器能够以极小的空间开销解决海量数据判重问题。**一个一定不存在的数据会被该过滤器拦截掉**,从而避免了对底层存储系统的查询压力。 - -## 缓存击穿 - -### 问题 - -缓存击穿是指某个键非常热点,访问非常频繁,处于集中式高并发访问的情况。当缓存在某个时间点过期的时,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。 - -### 解决 - -- 将热点数据设置为**永远不过期**。不会出现热点键过期问题。 -- 基于 Redis 或 Zookeeper 实现互斥锁。根据键获得的值为空时,先加锁,然后从数据库加载数据,加载完毕后再释放锁。其他线程发现获取锁失败,等待一段时间后重试。 - -## 双写一致性问题 - -一致性问题是分布式常见问题,还可以再分为**最终一致性**和**强一致性**。 - -数据库和缓存双写,就必然会存在不一致的问题。答这个问题,如果对数据有强一致性要求,则数据不能放入缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。 - -### 策略一:先删除缓存,再更新数据库 - -> **存在的问题** - -数据更新,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后更新数据的程序完成了数据库的修改,此时,数据库和缓存中的数据又不一致了。 - -并发场景下分析: - -- 线程A删除了缓存 -- 线程B查询,发现缓存已不存在 -- 线程B去数据库查询得到旧值 -- 线程B将旧值写入缓存 -- 线程A将新值写入数据库 - -所以也会导致数据库和缓存不一致的问题。 - -> **解决方案** - -读请求和写请求串行化,串到一个**内存队列**里去,这样就可以保证一定不会出现不一致的情况。串行化之后,就会导致系统的**吞吐量会大幅度的降低**,用比正常情况下多几倍的机器去支撑线上的一个请求。 - -> **问题:为什么是删除缓存,而不是更新缓存?** - -原因:如果每次更新了数据库,都要更新缓存【这里指的是频繁更新的场景,这会耗费一定的性能】,倒不如直接删除掉。等再次读取时,缓存里没有,那再去数据库找,在数据库找到再写到缓存里边(体现**懒加载**)。 - -举个例子,一个缓存涉及的表的字段,在 1 分钟内就修改了 100 次,那么缓存更新 100 次;但是这个缓存在 1 分钟内只被**读取**了 1 次,有**大量的冷数据**。实际上,如果你只是删除缓存的话,那么在 1 分钟内,这个缓存不过就重新计算一次而已,开销大幅度降低。 - -其实删除缓存,而不是更新缓存,就是一个 lazy 计算的思想,**不要每次都重新做复杂的计算,不管它会不会用到,而是让它在需要被使用时才重新计算**。 - -### 策略二:Cache Aside Pattern - -Cache Aside Pattern 最经典的缓存结合数据库读写的模式。 - -- 读的时候,先读缓存,缓存中没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。 -- 更新的时候,先更新数据库,然后再删除缓存。 - -> **存在的问题** - -先修改数据库,再删除缓存。 - -如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现不一致。 - -如果在高并发的场景下,出现数据库与缓存数据不一致的**概率特别低**,也不是没有: - -- 缓存**刚好**失效 -- 线程A查询数据库,得一个旧值 -- 线程B将新值写入数据库 -- 线程B删除缓存 -- 线程A将查到的旧值写入缓存 - -要达成上述情况,还是说一句**概率特别低**: - -> 因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,**而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存**,所有的这些条件都具备的概率基本并不大。 - -### 策略三:读请求和写请求串行化 - -读请求和写请求串行化,串入到一个内存队列。读串行化可保证一定不会出现双写一致性的情况,但会导致系统吞吐量大幅降低,需要比正常情况下多几倍的机器去支持线上一个请求,若不是严格要求双写一致性,则最好不要使用。 \ No newline at end of file diff --git a/docs/SSM/2_SpringIOC.md b/docs/SSM/2_SpringIOC.md deleted file mode 100644 index be3c8721..00000000 --- a/docs/SSM/2_SpringIOC.md +++ /dev/null @@ -1,186 +0,0 @@ -# SpringIOC - -## IOC - -### IOC 概念 - -IOC,即控制反转(Iversion of Control)是一种**设计思想**。 - -- **控制** - - 控制对象的创建及销毁(生命周期)。 - -- **反转** - - 将对象的控制权交给 IoC 容器。 - -所有的类都会在 Spring 容器中注册,告诉 Spring 你是个什么东西,你需要什么东西,然后 Spring 会在系统运行到适当的时候,把你需要的东西主动给你 - -**所有类的创建、销毁都由 Spring 来控制,也就是说控制对象生命周期的不是引用它的对象,而是 Spring**。对于某个具体对象而言,以前是它控制其他对象,现在所有对象都被 Spring 控制。 - -### 依赖注入 - -说到控制反转,则不得不说依赖注入(Dependency Injection,DI) 。 - -所谓依赖注入就是**将底层类作为参数传递给上层类,实现上层对下层的控制**,**依赖注入实现控制反转**。 - -举例说明依赖注入:以生产行李箱为例。 - -> 传统设计思路: - -先设计轮子,然后根据轮子 size 来设计底盘,再根据底盘来设计箱体,最后设计好行李箱。 - -可这样表示: - -
- -相应的代码如下: - -
- -size 是固定值,可以进行相应的改进: - -
- -> 使用 DI 方式进行改进: - -先设计行李箱的大概样子,再根据行李箱的样子设计箱体,根据箱体去设计底盘,然后去设计轮子。 - -
- -改进后相应的代码如下: - -
- -不难理解,依赖注入就是**将底层类作为参数传递给上层类,实现上层对下层的控制**。 - -### IoC 和 DI 的关系 - -使用 DI 去实现 IoC。 - -DI 的 4 中方式: - -- setter 注入 -- 构造器注入 -- 注解注入 -- 接口注入 - -依赖倒置原则、IoC、DI 和 IoC 容器的关系: - -
- -使用 IoC 容器的好处: - -- 避免在各处使用 new 来创建类,并且可统一维护 -- 创建实例时,不需要了解其中的细节 - - - -## SpringIOC - -### IoC 容器的初始化过程 - -
- -- Resource 定位(即 BeanDefinition 的资源定位,Resource 为各种形式的 BeanDefinition 的使用都提供了统一的接口) -- BeanDefinition 的载入 -- 向 IoC 容器中注册 BeanDefinition (实际上 IoC 容器内部维护一个 HashMap,注册过程就是将 BeanDefinition 添加至 HashMap 中) - -## IoC 加载过程 - -
- -IoC 容器其实就是一个大工厂,它用来管理我们所有的对象以及依赖关系: - -- 根据 Bean 配置信息在容器内部创建 Bean 定义注册表 -- 根据注册表加载,实例化 Bean,**建立 Bean 与 Bean 之间的依赖关系** -- 将 Bean 实例放入 Spring IoC 容器中,等待应用程序调用 - - - -## BeanFactory 和 ApplicationContext - -### BeanFactory - -- IoC 容器要实现的最基础的接口 -- 采用**延迟初始化策略**(容器初始化完成后并不会创建 Bean 对象,只有当收到初始化请求时才进行初始化) -- 由于是延迟初始化策略,因此启动速度较快,占用资源较少 - -### ApplicationConext - -- 在 BeanFactory 基础上,增加了更为高级的特性:事件发布、国际化等。 -- 在容器启动时,完成所有 Bean 的创建 -- 启动时间较长,占用资源较多 - -> **注意:BeanFactory 和 FactoryBean 的区别** - -- BeanFactory 是 IoC 最基本的容器,负责生产和管理 Bean,为其他具体的 IoC 容器提供了最基本的规范。 - -- FactoryBean 是一个 Bean,是一个接口,当 IoC 容器中的 Bean 实现了 FactoryBean 后,通过 getBean(String beanName) 获取到的 Bean 对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象。 - - 要想获取 FactoryBean 的实现类对象,就是在 beanName 前面加上 "&"。 - - - -## getBean 代码逻辑 - -- 获取参数 name 转化为 beanName -- 从缓存中加载实例 -- 实例化 Bean -- 检测 parentBeanFactory(若无缓存数据,直接到 parentBeanFactory 中去加载) -- 初始化依赖的 Bean -- 返回 Bean - - - -## Spring 中循环依赖 - -### 类的实例化和类的初始化 - -- 类的实例化是指创建一个类的实例(对象)的过程 -- 类的初始化是指为类中各个类成员(被static修饰的成员变量)赋初始值的过程,是**类生命周期中的一个阶段**。 - -在 Spring 容器中我们的类又是什么时候进行初始化和实例化的呢? - -- Spring 中**所有 Bean 默认都是单例模式**,所以 Bean 的初始化和实例化都是在加载进入 Bean 容器时做的 -- 如果想使用时再初始化,那么可以把类定义为原型模式 - -### 循环依赖 - -若 A 中有 B 的属性,B 中有 A 的属性,则当进行依赖注入时,就会产生 A 还未创建完,因为对 B 的创建再次返回创建 A。 - -### 解决循环依赖 - -单例对象,在 Spring IoC 容器中,有且仅有一个对象,将对象放入缓存中。Spring 中使用“三级缓存”: - -- SingletonObjects:单例对象的缓存(存储实例化完成的 Bean) -- earlySingletonObjects:提前曝光的单例对象的缓存(存储正在实例化的 Bean) -- SingletonFactories:单例 ObjectFactory 的缓存 - -举例说明解决循环依赖(A 中有B,B 中有 A)的具体过程: - -Spring 中单例对象的初始化主要分为 3 步: - -第一步:createBeanInstance - -第二步:populateBean 填充属性 - -第三步:intializeBean 初始化 - -在进行 createBeanInstance 后,该单例对象此时已被创建,Spring 将该对象**提前曝光到 SingeltonFacoties 中**。 - -- A 完成 createBeanInstance ,并且提前曝光到 SingeltonFacoties 中 -- A 进行第二步,发现需要依赖 B,尝试获取 B -- B 开始创建,B 完成 createBeanInstance,发现需要依赖 A,尝试获取 A:先尝试从 SingletonObjects 中获取,发现不存在,因为 A 未初始化完全;再尝试从 earlySingletonObjects 中获取;再去 SingeltonFacoties 中获取,此时 B 获取 A,并将 A 放入 earlySingletonObjects 中,再删除 A 在 SingeltonFacoties 中对应的 ObjectFactory。 -- B 获取 A,顺利完成第二、三步,并将初始化完成的 B 放入 SingletonObjects 中。 -- 此时返回创建 A,A 可获取 B,顺利完成第二、三步,A 初始化完成, 将 A 放入 SingletonObjects 中。 - -注意:Spring 中循环依赖有 2 种: - -- 构造器循环依赖:因为提前曝光到 SingletonFactories 中的前提是需要执行构造方法,所以使用 “三级缓存” 无法解决 -- setter 循环依赖 - -### 总结 - -- 尽量不要使用基于构造器的 DI,使用基于 setter 的 DI -- 使用 @Autowired 注解,让 Spring 决定合适的时机 \ No newline at end of file diff --git a/docs/SSM/3_SpringAOP.md b/docs/SSM/3_SpringAOP.md deleted file mode 100644 index 13e950f4..00000000 --- a/docs/SSM/3_SpringAOP.md +++ /dev/null @@ -1,46 +0,0 @@ -# SpringAOP - -## AOP - -AOP,即面向切面编程(Aspect Oriented Programing)。实际上是将一些通用的功能横向抽取出来:一方面,可减少系统的代码;另一方面,降低模块间的耦合度,比较好的维护和扩展。 - - - -## AOP 相关术语 - -| 术语 | 描述 | -| :----------------: | :----------------------------------------------------------: | -| Joinpoint(连接点) | 所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是**方法**,因为Spring只支持**方法类型的连接点**。 | -| Pointcut(切入点) | 所谓切入点是指我们要**对哪些Joinpoint进行拦截**的定义。 | -| Advice(通知/增强) | 所谓通知是指拦截到Joinpoint之后所要做的事情就是**通知**。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能) | -| Introduction(引介) | 引介是一种**特殊的通知**在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field | -| Target(目标对象) | 代理的目标对象 | -| Weaving(织入) | 是指把增强应用到目标对象来创建新的代理对象的过程。 有三种织入方式: Spring采用**动态代理织入**,而AspectJ采用**编译期织入**和**类装载期织入** | -| Proxy(代理) | 一个类被AOP织入增强后,就产生一个结果代理类 | -| Aspect(切面) | 是切入点和通知(/引介)的结合 | - -- 示例:在 IUserDao() 中 - - ```java - public interface IUserDao { - void add(); - void delete(); - void update(); - void search(); - } - // IUserDao 被增强的对象,就是 Target(目标对象) - // add()、delete()、update() 和 search() 都是 JoinPoint(连接点) - // 这里要对 add() 和 update() JoinPoint 进行拦截,则 add() 和 update() 就是 Pointcut(切入点) - // Advice 指的是要增强的代码,也就是代码的增强 - // Weaving:指的是把增强(Advice)应用到目标对象(Target)创建新的代理对象得人过程 - // Aspect:是切入点和通知的结合,在 add 或 delete 方法上应用增强 - ``` - - - -## AOP 底层原理 - -AOP 的底层原理是代理机制: - -- 类实现了接口,JDK 动态代理 -- 类未实现任何接口,Cglib 动态代理 \ No newline at end of file diff --git "a/docs/SSM/4_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" "b/docs/SSM/4_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" deleted file mode 100644 index c6284d5e..00000000 --- "a/docs/SSM/4_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" +++ /dev/null @@ -1,139 +0,0 @@ -# Spring 事务管理 - -## 编程式事务和声明式事务 - -### 编程式事务 - -编程式事务:指的是通过编码方式实现事务,类似 JDBC 编程实现事务管理,比如 jdbcTemplate、TransactionalTemplate。 - -### 声明式事务 - -声明式事务实现方式: - -- XML 实现 -- @Transactional 注解实现 - -### 比较 - -编程式事务: - -- 优点:显示调用,不易出错 -- 缺点:侵入式代码,编码量大 - -声明式事务: - -- 优点:简介,对代码入侵小 -- 缺点:隐藏实现细节,出错不易定位 - -## Spring 事务管理 - -Spring 事务的本质是**基于数据库对事务的支持**,没有数据库对事务的支持,Spring 本身无法提供事务管理功能。 - -Spring 事务通过 AOP 动态代理来是实现。 - -通常先在配置文件中**开启事务**,然后通过 xml 文件或者注解**配置执行方法**,在调用方法时,Spring 会自动生成代理,在调用前设置事务操作,调用方法后进行事务回滚或者提交操作。 - -## Spring 中事务隔离级别 - -事务隔离级别是指多个事务之间的隔离程度。 - -TransactionDefinition 接口中定义了五个表示隔离级别的常量: - -| 隔离级别 | 说明 | -| :------------------------------------: | :----------------------------------------------------------: | -| ISOLATION_DEFAULT(默认) | 这是默认值,表示使用底层数据库的默认隔离级别。 | -| ISOLATION_READ_UNCOMMITTED(读未提交) | 该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据,该级别不能防止脏读和不可重复读,因此很少使用该隔离级别 | -| ISOLATION_READ_COMMITTED(读可提交) | 该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值 | -| ISOLATION_REPEATABLE_READ(可重复读) | 该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读 | -| ISOLATION_SERIALIZABLE(可串行化) | 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是,这将严重影响程序的性能,通常情况下也不会用到该级别 | - - - -## Spring 七种事务传播类型 - -- **PROPAGATION_REQUIRED(required)** - - 如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。 - -- PROPAGATION_SUPPORTS(support) - - 表示支持当前事务,如果当前没有事务,就以无事务方式执行。 - -- PROPAGATION_MANDATORY(mandatory) - - 表示使用当前的事务,如果当前没有事务,就抛出异常。 - -- **PROPAGATION_REQUIRES_NEW(required_new)** - - 表示新建事务,如果当前存在事务,把当前事务挂起。 - -- **PROPAGATION_NOT_SUPPORTED(not_support)** - - 表示以无事务方式执行操作,如果当前存在事务,就把当前事务挂起。 - -- PROPAGATION_NEVER(never) - - 表示以无事务方式执行,如果当前存在事务,则抛出异常。 - -- PROPAGATION_NESTED(nested) - - 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 - -举例说明事务传播类型: - -- StudentServiceImplA - -```java -StudentServiceImplA implements StudentService{ - @Autowired - studentDao; - - @Autowired - studentService; - - @Transactional(required) //事务传播特性为 requried - insertA(){ - //...对数据库操作,插入 A 数据 - - studentService.insertB();// 插入 B 数据 - - //..i/o 异常 - } -} -``` - -- StudentServiceImplB - -```java -StudentServiceImplB implements StudentService{ - @Autowired - studentDao; - - @Transactional - insertB(){ - - //...对数据库操作,插入 B 数据 - - } -} -``` - -StudentServiceImplB 中 insertB() 中传播类型如果是 required,数据库中既没有 A 数据,也没有 B 数据; - -(insertA() 和 insertB() 属于同一个事务,发生异常,事务回滚) - -StudentServiceImplB 中 insertB() 中传播类型如果是 required_new,数据库中没有 A 数据,但是有 B 数据; - -(insertB() 创建了一个新事务,insertA() 中发生异常,事务回滚) - -StudentServiceImplB 中 insertB() 中传播类型如果是 not_supported,数据库中没有 A 数据,但是有 B 数据 - -(insertB() 以非事务方式只想,执行 insertA() 的事务回滚,insertB()中不会发生回滚) - - - -注意:insertB() 为何要放入 StudentServiceImplB 中? - -Spring 的事务机制是使用 AOP 代理实现的。 - -如果在 StudentServiceImplA 中使用 insertB() ,insertA() 中在调用 insertB() 是通过当前对象来调用 doB() 的,而不是通过代理来调用 doB() 的,此时 doB() 上加事务注解就失效了。 \ No newline at end of file diff --git "a/docs/SSM/5_Spring\344\270\255Bean\347\232\204\344\275\234\347\224\250\345\237\237.md" "b/docs/SSM/5_Spring\344\270\255Bean\347\232\204\344\275\234\347\224\250\345\237\237.md" deleted file mode 100644 index ca384c86..00000000 --- "a/docs/SSM/5_Spring\344\270\255Bean\347\232\204\344\275\234\347\224\250\345\237\237.md" +++ /dev/null @@ -1,124 +0,0 @@ -# Spring 中 Bean 的作用域 - -Spring Framework 支持五种作用域: - -| 类别 | 说明 | -| :-----------: | :----------------------------------------------------------: | -| singleton | 在 SpringIoC 容器中仅存在一个 Bean 实例,Bean 以单例方式存在 | -| prototype | 每次从容器中调用 Bean 时,都返回一个新的实例 | -| request | 每次HTTP请求都会创建一个新的 Bean,该作用域仅适用于 WebApplicationContext 环境 | -| session | 同一个 Http Session 共享一个 Bean,不同 Session 使用不同 Bean,仅适用于WebApplicationContext 环境 | -| globalSession | 一般同于 Portlet 应用环境,该作用域仅适用于 WebApplicationContext 环境 | - -注意:五种作用域中,request、session 和 global session 三种作用域仅在基于 web 的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。 - -## 1. singleton - -当一个 Bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个**共享的 Bean 实例**, 并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,则只会**返回 Bean 的同一实例**。 - -singleton 是单例类型(对应于单例模式),就是**在创建容器时就同时自动创建一个Bean对象**, 不管你是否使用,但我们可以指定Bean节点的 lazy-init="true" 来延迟初始化Bean, 这时候,只有在第一次获取Bean时才会初始化Bean,即第一次请求该bean时才初始化。 每次获取到的对象都是同一个对象。 注意,singleton 作用域是Spring中的**缺省作用域**。 - -- 配置文件XML中将 Bean 定义成 singleton : - - ```html - - ``` - -- @Scope 注解的方式: - -```java -@Service -@Scope("singleton") -public class ServiceImpl{ - -} -``` - - - -## 2. prototype - -当一个Bean的作用域为 prototype,表示一个 Bean 定义对应多个对象实例。 prototype 作用域的 Bean 会导致在每次对该 Bean 请求 (将其注入到另一个 Bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。 prototype 是原型类型,它在我们创建容器的时候并没有实例化, 而是当我们获取Bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。 - -根据经验,**对有状态的 Bean 应该使用 prototype 作用域,而对无状态的 Bean 则应该使用 singleton 作用域。** - -- 配置文件XML中将 Bean 定义成 prototype : - -```html - -``` - -或者 - -```html - -``` - -- @Scope 注解的方式: - -```java -@Service -@Scope("prototype") -public class ServiceImpl{ - -} -``` - - - -> **Spring 中线程安全问题** - -有状态 Bean 和 无状态 Bean: - -- **有状态 Bean** - - 对象中有实例变量(成员变量),可保存数据; - - 非线程安全。 - -- **无状态 Bean** - - 对象中午实例变量,不能保存数据,可在多线程环境下共享; - - 线程安全。 - -Spring 中有状态 Bean 如何保证线程安全? - -2 种方式保证线程安全: - -- 采用 ThreadLocal 进行处理 -- 采用原型模式,每次有 Bean 请求时,都会创建一个新的 Bean 实例 - - - -## 3. request - -request只适用于**Web程序**,每一次 HTTP 请求都会产生一个新的 Bean , 同时该 Bean 仅在当前HTTP request内有效,当请求结束后,该对象的生命周期即告结束。 - -在 XML 中将 bean 定义成 request ,可以这样配置: - -- 配置文件XML中将 Bean 定义成 prototype : - -```html - -``` - - - -## 4. session - -session只适用于**Web程序**, session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 Bean, 同时**该 Bean 仅在当前 HTTP session 内有效**。 与request作用域一样,可以根据需要放心的更改所创建实例的内部状态, 而别的 HTTP session 中根据 userPreferences 创建的实例, 将不会看到这些特定于某个 HTTP session 的状态变化。 当HTTP session最终被废弃的时候,在该HTTP session作用域内的bean也会被废弃掉。 - -```html - -``` - - - -## 5. globalSession - -globalSession 作用域**类似于标准的 HTTP session** 作用域, 不过仅仅在基于 portlet 的 Web 应用中才有意义。 Portlet 规范定义了全局 Session 的概念, 它被所有构成某个 portlet web 应用的各种不同的 portlet所共享。 在globalSession 作用域中定义的 bean 被限定于全局portlet Session的生命周期范围内。 - -```html - -``` \ No newline at end of file diff --git "a/docs/SSM/6_Spring\344\270\255Bean\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237.md" "b/docs/SSM/6_Spring\344\270\255Bean\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237.md" deleted file mode 100644 index 31784113..00000000 --- "a/docs/SSM/6_Spring\344\270\255Bean\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237.md" +++ /dev/null @@ -1,44 +0,0 @@ -# Spring中Bean的生命周期 - -## Bean 的创建过程 - -
- - - -## Bean 的销毁过程 - -- 若实现了 DisposableBean 接口,则会调用 destroy 方法 -- 若配置了 destroy-method 属性,则会调用其配置的销毁方法 - - - -## 详细过程 - -
- - - -1、Spring 对 Bean 进行实例化。 - -2、Spring 将值和 Bean 的引用注入到 Bean 对应的属性中。 - -3、如果 Bean 实现了 BeanNameAware 接口,Spring 将 bean 的 id 传递给 setBeanName() 接口方法。 - -4、如果 Bean 实现了 BeanFactoryAware 接口,Spring 将调用 setBeanFactory() 接口方法,将 BeanFactory 容器实例传入。 - -5、如果 Bean 实现了 ApplicationContextAware 接口,Spring 将调用 setApplicationContext() 接口方法,将应用上下文的引用传入。 - -6、如果 Bean 实现了BeanPostProcessor 接口,Spring 将调用 postProcessBeforeInitialization() 接口方法。 - -7、如果 Bean 实现了InitializingBean 接口,Spring 将调用他们的 afterPropertiesSet() 接口方法 - -8、如果Bean 实现了 init-method 声明了初始化方法,该方法也会被调用。 - -9、如果 Bean 实现了BeanPostProcessor 接口,Spring 将调用 postProcessAfterInitialization() 接口方法。 - -10、此时 Bean 已经准备就绪,可以被应用程序使用了,他们将一一直驻留在应用上下文中,一直到该应用上下文被销毁。 - -11、如果 Bean 实现了 DisposableBean 接口,Spring 将调用它的 destroy() 接口方法。 - -12、如果 Bean 使用 destroy-method 声明了销毁方法,方法也会被调用。 \ No newline at end of file diff --git "a/docs/SSM/7_Spring\344\270\255\345\270\270\350\247\201\346\263\250\350\247\243.md" "b/docs/SSM/7_Spring\344\270\255\345\270\270\350\247\201\346\263\250\350\247\243.md" deleted file mode 100644 index 7c0450db..00000000 --- "a/docs/SSM/7_Spring\344\270\255\345\270\270\350\247\201\346\263\250\350\247\243.md" +++ /dev/null @@ -1,99 +0,0 @@ -# Spring 中常见注解 - -## @Contoller - -SpringMVC 中,控制器 Controller 负责处理 DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个 Model,然后再把该 Model 返回给对应的 View 进行展示。 - -SpringMVC 提供了一个非常简便的定义 Controller 的方法,你无需继承特定的类或者接口,只需使用 @Controller 标记一个类是 Contoller。 - -## @RequestMapping - -使用 @RequestMapping 来映射 URL 到控制器,或者到 Controller 控制器的处理方法上。method 的值一旦指定,则处理方法只对指定的 HTTP method 类型请求处理。 - -可以为多个方法映射相同的 URI,不同的 HTTP method 类型,Spring MVC 根据请求的 method 类型是可以区分开这些方法的。 - -## @RequestParam 和 @PathVariable - -在 SpringMVC 中,两者的作用都是将 request 里的参数的值绑定到 Controller 里的方法参数中,区别在于 URL 的写法不同。 - -- 使用 @RequestParam 时,URL 是这样的: - -```html -http://host:port/path?参数名=参数值 -``` - -- 使用 @PathVariable 时,URL 是这样的: - -```html -http://host:port/path/参数值 -``` - -## @Autowired - -@Autowired 可以对成员变量、成员方法和构造函数进行标注,来完成自动装配工作。 - -## @Service、 @Contrller、 @Repository 和 @Component - - @Service、 @Contrller、 @Repository 其实这 3 个注解和 @Component 是等效的,用在实现类上: - -- @Service 用于标注业务层组件 -- @Controller 用于标注控制层组件 -- @Repository 用于编著数据访问组件 -- @Component 泛指组件,当组件不好归类时,可以使用这个注解进行标注 - -## @Value - -在 Spring 3.0 中,可以通过使用 @Value,对一些如 xxx.properties 文件中的文件,进行键值对的注入。 - -## @ResponseBody - -该注解用于将 Controller 中方法返回的对象,通过适当的 HttpMessageConverter 转换为指定的格式后,写入到 Response 对象的 bodys 数据区。 - - - -> **@Autowired 和 @Resource 的区别** - -@Autowired - -- 是 Spring 提供的注解 - -- 采用的策略是**按照类型**注入的 - - ```java - public class UserService{ - @Autowired - userDao; //在 Spring 容器中找到类型为 userDao 的类,将其注入 - } - ``` - - 存在问题:同一类型有多个 Bean,可以使用 @Qualifier 具体去装配哪个对象。 - - ```java - public class UserService{ - @Autowired - @Qualifier(name="userDao") - userDao; //在 Spring 容器中找到类型为 userDao 的类,将其注入 - } - ``` - - @Resource - -- J2EE 提供的注解 - -- 默认是**按照名称**注入的 - - ```java - Service{ - @Resource - userDao; //自动按名称进行装配 - - @Resource(name="studentDao") - studentDao; //按名称进行装配,找不到会抛出异常 - - @Resource(type="TeacherDao") - teacherDao; //按类型进行装配,找不到或者找到多个都会抛出异常 - - @Resource(name="manDao",type="ManDao") - manDao;//找唯一匹配的 Bean 进行装配,如果找不到则会抛出异常 - } - ``` diff --git "a/docs/SSM/8_Spring\344\270\255\346\266\211\345\217\212\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/docs/SSM/8_Spring\344\270\255\346\266\211\345\217\212\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" deleted file mode 100644 index 0597d148..00000000 --- "a/docs/SSM/8_Spring\344\270\255\346\266\211\345\217\212\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ /dev/null @@ -1,37 +0,0 @@ -# Spring中涉及到的设计模式 - -## 工厂模式 - -- [工厂模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/2_%E5%88%9B%E5%BB%BA%E5%9E%8B.md#2-%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82simple-factory) - -BeanFactory 用来创建各种不同的 Bean。 - -## 代理模式 - -- [代理模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/4_%E7%BB%93%E6%9E%84%E5%9E%8B.md#7-%E4%BB%A3%E7%90%86proxy) - -AOP、事务都大量运用了代理模式。 - -## 单例模式 - -- [单例模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/2_%E5%88%9B%E5%BB%BA%E5%9E%8B.md#1-%E5%8D%95%E4%BE%8Bsingleton) - -在 Spring 配置文件中定义的 Bean 默认为单利模式。 - -## 原型模式 - -- [原型模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/2_%E5%88%9B%E5%BB%BA%E5%9E%8B.md#6-%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8Fprototype) - -特点在于通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的"原型",这个原型是可定制的。 - -## 责任链模式 - -- [责任链模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/3_%E8%A1%8C%E4%B8%BA%E5%9E%8B.md#1-%E8%B4%A3%E4%BB%BB%E9%93%BEchain-of-responsibility) - -在 SpringMVC 中,会经常使用一些拦截器(HandlerInterceptor),当存在多个拦截器的时候,所有的拦截器就构成了一条拦截器链。 - -## 观察者模式 - -- [观察者模式](https://github.com/DuHouAn/Java/blob/master/docs/OO/3_%E8%A1%8C%E4%B8%BA%E5%9E%8B.md#7-%E8%A7%82%E5%AF%9F%E8%80%85observer) - -Spring 中提供了一种监听机制,即 ApplicationListenber,可以实现 Spring 容器内的事件监听。 \ No newline at end of file diff --git a/docs/SSM/9_MyBaits.md b/docs/SSM/9_MyBaits.md deleted file mode 100644 index c91882c9..00000000 --- a/docs/SSM/9_MyBaits.md +++ /dev/null @@ -1,9 +0,0 @@ -# MyBatis - -> MyBatis 中使用 # 和使用 $ 的区别? - -- #{xxx} 语句拼接使用的是 PreparedStatement,会有类型转换,比较安全。 - - 简单讲,#{xxx} 是经过预编译的是安全的 - -- ${xxx}未经过预编译,仅仅是变量的值,是不安全的,可能会**存在 SQL 注入**的风险。 diff --git "a/docs/Safety/11_DoS\346\224\273\345\207\273.md" "b/docs/Safety/11_DoS\346\224\273\345\207\273.md" index 9f4597fb..6428706c 100644 --- "a/docs/Safety/11_DoS\346\224\273\345\207\273.md" +++ "b/docs/Safety/11_DoS\346\224\273\345\207\273.md" @@ -28,6 +28,3 @@ - 防雪崩机制 - 有损服务 - CDN - - - diff --git "a/docs/Safety/2_\350\267\250\347\253\231\350\204\232\346\234\254\346\224\273\345\207\273.md" "b/docs/Safety/2_\350\267\250\347\253\231\350\204\232\346\234\254\346\224\273\345\207\273.md" index 243430cf..2160320f 100644 --- "a/docs/Safety/2_\350\267\250\347\253\231\350\204\232\346\234\254\346\224\273\345\207\273.md" +++ "b/docs/Safety/2_\350\267\250\347\253\231\350\204\232\346\234\254\346\224\273\345\207\273.md" @@ -178,6 +178,4 @@ localhost:1521?from=Bai ### CSP -内容安全策略(Content Security Policy):用于指定那些内容可执行。 - -- [CSP简介](https://blog.csdn.net/Fly_hps/article/details/86466367) +[CSP](https://blog.csdn.net/Fly_hps/article/details/86466367) 即内容安全策略(Content Security Policy):用于指定哪些内容可执行。 \ No newline at end of file diff --git "a/docs/Safety/7_\345\257\206\347\240\201\345\256\211\345\205\250.md" "b/docs/Safety/7_\345\257\206\347\240\201\345\256\211\345\205\250.md" index f7572661..beab3301 100644 --- "a/docs/Safety/7_\345\257\206\347\240\201\345\256\211\345\205\250.md" +++ "b/docs/Safety/7_\345\257\206\347\240\201\345\256\211\345\205\250.md" @@ -36,7 +36,7 @@ - 彩虹表会失效(数量太大,无法建立通用性) - 时解密唱本增大 N 倍 -## 密码加固 +## 密码加盐 - 在用户表中加上 `salt`字段 - 如果用户没有 `salt` 值,则需要升级 diff --git a/docs/Safety/Cookie_Session_Token.md b/docs/Safety/Cookie_Session_Token.md new file mode 100644 index 00000000..617051a2 --- /dev/null +++ b/docs/Safety/Cookie_Session_Token.md @@ -0,0 +1,706 @@ +# 一、Cookie + +## Cookie 简介 + +Cookie 意为“甜饼”,是由 W3C 组织提出,最早由 Netscape 社区发展的一种机制。 +目前 Cookie 已经成为标准,所有的主流浏览器如 IE、Netscape、Firefox、Opera 等都支持 Cookie。 + +由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。 +怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。 +这样服务器就能从通行证上确认客户身份了,这就是 Cookie 的工作原理。 + +Cookie 实际上是一小段的文本信息。 +客户端请求服务器,如果服务器需要记录该用户状态,就使用 response 向客户端浏览器颁发一个 Cookie。 +**客户端浏览器会把 Cookie 保存起来**。 +当浏览器再请求该网站时,浏览器把请求的网址连同该 Cookie 一同提交给服务器。 +服务器检查该 Cookie,以此来辨认用户状态。 +服务器还可以根据需要修改 Cookie 的内容。 + +## Cookie 机制 + +Cookie 技术是**客户端的解决方案**,Cookie 就是由**服务器发给客户端**的特殊信息,而这些信息以文本文件的方式**存放在客户端**, +然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。 + +具体过程如下: + +1. 用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器; +2. 服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体 + (Response Body)中的,而是存放于HTTP响应头(Response Header) +3. 客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置。 + 对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings[用户名]\Cookies目录中找到存储的Cookie; +4. 客户端再次向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。 + 而这次,Cookie信息则存放在HTTP请求头(equest Header)了。 + +## HTTP 的 Cookie 机制 + +Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。 +一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。 +这就意味着服务器无法从连接上**跟踪会话**。 +举个例子,用户A购买了一件商品放入购物车内, +当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。 +要跟踪该会话,必须引入一种机制。 +​ +Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。 +在Session出现之前,基本上所有的网站都**采用Cookie来跟踪会话**。 + +## Set-Cookie 和 Cookie + +两个Http头部和Cookie有关 : Set-Cookie和Cookie + +当服务器返回给客户端一个Http响应信息时,其中如果包含Set-Cookie这个头部,说明: + +1. 指示客户端建立一个cookie +2. 在后续的Http请求中自动发送这个cookie到服务器端,直到这个cookie过期。 +3. 如果cookie的生存时间是整个会话期间的话,那么浏览器会将 cookie 保存在内存中, + 浏览器关闭时就会自动清除这个cookie。 +4. 如果将 cookie 保存在客户端的硬盘中,浏览器关闭的话,该 cookie 也不会被清除, + 下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。 + +一个cookie的设置以及发送过程分为以下四步: + +- 1. **客户端发送一个http请求到服务器端** +- 1. **服务器端发送一个http响应到客户端,其中包含Set-Cookie头部** +- 1. **客户端发送一个http请求到服务器端,其中包含Cookie头部** +- 1. **服务器端发送一个http响应到客户端** + +
+ +在客户端的第二次请求中包含Cookie头部,提供给了服务器端可以用来唯一标识客户端身份的信息。 +这时,服务器端也就可以判断客户端是否启用了cookie。 +尽管,用户可能在和应用程序交互的过程中突然禁用cookie的使用, +但是,这个情况基本是不太可能发生的,所以可以不加以考虑,这在实践中也被证明是对的。 + +## Cookie 的不可跨域名性 + +很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。 +那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢? + +答案是否定的。Cookie具有**不可跨域名性**。 +根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。 +Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。 + +Cookie在客户端是由**浏览器来管理**的。 +浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。 +浏览器判断一个网站是否能操作另一个网站Cookie的依据是**域名**。 +Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。 + +- 注意: + +虽然网站images.google.com与网站www.google.com同属于Google, +但是域名不一样,二者同样不能互相操作彼此的Cookie。 + +用户登录网站www.google.com之后会发现访问images.google.com时登录信息仍然有效,而普通的Cookie是做不到的。 +这是因为Google做了特殊处理。 + +## 简单案例 : 记录上次访问时间 + +> cookie的API + +```java +new Cookie(String key,String value); +String getName();//获取cookie的key(名称) +String getValue();//获取cookie的值 +void setMaxAge(int);//设置cookie在浏览器存活时间,单位:秒 +//如果设置成0:表示删除高cookie(前提:路径必须一致) +void setPath(String path);//设置cookie的路径 +//当我们访问的路径中包含次cookie的path,才会携带cookie +//默认访问路径:访问Servlet的路径,从"/项目名称"开始,到最后一个"/"结束。比如:/demo/a/b,默认路径为/demo/a +//手动设置路径:以"/项目名称"开始,以"/"结尾 +``` + +> 写回浏览器 + +```java +response.addCookie(Cookie); +``` + +> 获取cookie + +```java +Cookie[] request.getCookies(); +``` + +- 核心代码: + +```java +/** + * 根据 cookie名称获取Cookie 的工具类 + */ +public class CookieUtils { + public static Cookie getCookieByName(String name,Cookie[] cookies){ + if(cookies != null){ + for(Cookie cookie : cookies){ + if(name.equals(cookie.getName())){ + return cookie; + } + } + } + return null; + } +} +``` + +```java +public class RecordServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + //1.设置编码 + response.setContentType("text/html;charset=utf-8"); + PrintWriter w = response.getWriter(); + + //2.获取指定名称的Cookie + Cookie cookie = CookieUtils.getCookieByName("record",request.getCookies()); + + //3.判断cookie是否为空; + // 若为null,则说明是第一次访问; + // 若不为 null,则根据cookie显示上一次的访问时间 + if(cookie == null){ + w.write("这是您第一次访问"); + }else{ + long lastTime= Long.parseLong(cookie.getValue()); + w.write("您上次访问的时间:"+ new Date(lastTime).toLocaleString()); + } + + //4.记录当前访问时间,并且该信息存入cookie中 + Cookie c = new Cookie("record",System.currentTimeMillis()+""); + //设置cookie的有效期是 1 小时 + c.setMaxAge(60*60); + response.addCookie(c); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPost(request,response); + } +} +``` + +- [该案例完整代码](https://github.com/DuHouAn/Java/tree/master/JavaWeb/Login) + +## Cookie 案例 : 浏览记录 + +- 核心代码1:记录商品浏览记录 + +```java +/** + * 记录商品浏览记录,只展示3个商品 + */ +public class CategoryServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + //获取当前访问商品的id + String id = request.getParameter("id"); + + Cookie c = CookieUtils.getCookieByName("ids",request.getCookies()); + + //判断该 cookie 是否为空 + String ids=""; + if(c == null){ + //若为空,说明之前没有访问记录 + //将当前商品的id放入ids中 + ids = id; + }else{ + //若不为空,获取值。也就是之前浏览的商品编号,使用 "-"进行连接 + ids = c.getValue(); + + //将 ids 通过"-"进行分割,然后存入list中,方便后续的操作 + String[] categoryIds = ids.split("-"); + LinkedList categories = new LinkedList<>(); + if(categories != null){ + for(String categoryId : categoryIds){ + categories.add(categoryId); + } + } + //判断之前记录中有无该商品 + if(categories.contains(id)){ + //若有,删除原来的id,将当前的id放入前面 + categories.remove(id); + }else{ + // 若没有 + // 继续判断长度是否>=3 + // 若>=3,移除最后一个,将当前的id放入最前面 + // 若<3,直接将当前的id放入最前面. + if(categories.size() >= 3){ + categories.removeLast(); + } + } + //不管如何,id都是最新浏览的,直接加入到前面 + categories.addFirst(id); + + ids=""; + for(String categoryId : categories){ + ids += (categoryId + "-"); + } + ids = ids.substring(0,ids.length()-1); + } + + //创建cookie + c=new Cookie("ids",ids); + //设置访问路径 + c.setPath(request.getContextPath()+"/"); + //设置存活时间 + c.setMaxAge(60); + + //写回浏览器 + response.addCookie(c); + + //跳转到指定的商品页面上 + response.sendRedirect(request.getContextPath()+"/category_info"+id+".htm"); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPost(request,response); + } +} +``` + +- 显示浏览记录 + +```html +
    + <% + //获取指定名称的cookie ids + Cookie c= CookieUtils.getCookieByName("ids", request.getCookies()); + + //判断ids是否为空 + if(c==null){ + %> +

    暂无浏览记录

    + <% + }else{//ids=3-2-1 + String[] arr=c.getValue().split("-"); + for(String id:arr){ + %> +
  • + <% + } + } + %> +
+``` + +- 核心代码2:清空浏览记录 + +```java +/** + * 清空浏览记录 + */ +public class ClearServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Cookie c = new Cookie("ids",""); + + //cookie的路径与 CategoryServlet中的cookie中的路径要相同 + c.setPath(request.getContextPath()+"/"); + //直接将cookie设置成无效 + c.setMaxAge(0); + response.addCookie(c); + + //重定向 + response.sendRedirect(request.getContextPath()+"/category_list.jsp"); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPost(request,response); + } +} +``` + +- 注意: + +1. cookie是不能跨浏览器的 +2. cookie不支持中文,需要编码 + + + +# 二、Session + +## Session 简介 + +Session是一种记录客户状态的机制,不同于Cookie的是Cookie保存在客户端浏览器中,而Session保存在服务器上。 +客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。 +客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。 + +如果说Cookie机制是通过检查客户身上的"通行证"来确定客户身份的话, +那么Session机制就是通过检查服务器上的"客户明细表"来确认客户身份。 +Session相当于程序在服务器上建立的一份客户档案, +客户来访的时候只需要查询客户档案表就可以了。 + +## Session 机制 + +一方面,我们可以把**客户端浏览器与服务器之间一系列交互的动作**称为一个 Session。 +从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等。 + +另一方面,Session指的是**服务器端为客户端所开辟的存储空间**,该空间保存的信息就是用于保持状态。 +从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从Session中获取匹配的内容等。 + +- 要使用Session,当然是先要创建Session。那么Session在何时创建呢? + +1. Session在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法, + 在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。 + 创建Session的同时,**服务器会为该Session生成唯一的session id**, + 这个session id在随后的请求中会被用来重新获得已经创建的Session +2. Session被创建之后,就可以调用Session相关的方法往Session中增加内容了, + 而这些内容只会保存在服务器中,发到客户端的只有session id + +1. 当客户端再次发送请求的时候,会将这个session id带上, + 服务器接受到请求之后就会依据session id找到相应的Session,从而再次使用Session。 + +## Session 的生命周期 + +Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在**内存**中。 +**每个用户都会有一个独立的Session**。 +如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。 +因此,Session里的信息应该尽量精简。 + +**Session在用户第一次访问服务器的时候自动创建**。 +需要注意只有访问JSP、Servlet等程序时才会创建Session, +只访问HTML、IMAGE等静态资源并不会创建Session。 +如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。 + +Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。 +用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。 + +## Session 的有效期 + +由于会有越来越多的用户访问服务器,因此Session也会越来越多。 +为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。 +这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。 + +Session的超时时间为maxInactiveInterval属性, +可以通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(longinterval)修改。 + +Session的超时时间也可以在web.xml中修改。 +另外,通过调用Session的invalidate()方法可以使Session失效。 + +## Session 案例 : 购物车 + +> 获取Session + +```java +HttpSession getSession(); //request.getSession() +``` + +> 域对象 + +```java +xxxAttribute //存放私有数据 +``` + +> 域对象生命周期 + +- 创建:第一次调用request.getSession() +- 销毁: + +1. 服务器非正常关闭; +2. session超时; + +默认超时时间:30 min + +手动设置超时:setMaxInactiveInterval(int) (单位:秒) + +1. 手动设置; + +Session接口中的invalidate()方法 + +```java +public void invalidate() +``` + +- 核心代码1:将商品添加到购物车 + +```java +public class CartServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html;charset=utf-8"); + PrintWriter out=response.getWriter(); + + //1.获取商品名称 + String name = request.getParameter("name"); + + //2.获取购物车,实际上就是存入session的map + HashMap map = (HashMap) request.getSession().getAttribute("cart"); + + Integer num = null; + + //3.判断购物车是否为空 + if(map==null){ + //3.1 购物车为空,说明是第一次将商品放入购物车 + //先创建购物车, + map = new HashMap<>(); + request.getSession().setAttribute("cart",map); + num = 1; + }else{ + //3.2 购物车不为空,判断该商品之前是否已经加入购物车 + num = map.get(name); + if(num == null){ + //num==null,说明该商品之前未加入购物车 + num = 1; + }else{ + num ++ ; + } + } + map.put(name,num); + + //4.提示信息 + out.print("
已经将"+name+"添加到购物车中
"); + out.print("
继续购物

"); + out.print("
查看购物车
"); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPost(request,response); + } +} +``` + +- 显示购物车中信息 + +```java + +
+ 继续购物      + 清空购物车      +
+
+ 订单详情 + + + + + + + <% + HashMap map = (HashMap)request.getSession().getAttribute("cart"); + if(map==null){ + out.print(""); + }else{ + for(String name : map.keySet()){ + out.print(""); + + out.print(""); + out.print(""); + + out.print(""); + } + } + %> + +
商品数量
亲,购物车空空,先去逛逛~~
"); + out.print(name); + out.print(""); + out.print(map.get(name)); + out.print("
+
+
+
+ +``` + +- 核心代码2:清空购物车 + +```java +public class ClearCartServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getSession().invalidate(); + + response.sendRedirect(request.getContextPath()+"/cart.jsp"); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPost(request,response); + } +} +``` + +- [Coookie和Session案例的完整代码](https://github.com/DuHouAn/Java/tree/master/JavaWeb/Category) + +## 实现会话跟踪的技术 + +- **Cookie** + +向客户端发送Cookie : + +```java +Cookie c =new Cookie("name","value"); //创建Cookie +c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天 +response.addCookie(c); //把Cookie放入到HTTP响应中 +``` + +从客户端读取Cookie : + +```java +String name ="name"; +Cookie[]cookies =request.getCookies(); +if(cookies !=null){ + for(int i= 0;i +``` + +优点: Cookie被禁时可以使用 + +缺点: 所有页面必须是表单提交之后的结果。 + +- **session** + +当一个用户第一次访问某个网站时会自动创建 HttpSession,**每个用户可以访问他自己的HttpSession**。 + +可以通过HttpServletRequest对象的getSession方法获得HttpSession。 +通过HttpSession的setAttribute方法可以将一个值放在HttpSession中, +通过调用 HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。 + +与上面三种方式不同的是,**HttpSession放在服务器的内存中**,因此不要将过大的对象放在里面。 +即使目前的Servlet容器可以在内存将满时将 HttpSession 中的对象移到其他存储设备中,但是这样势必影响性能。 +添加到 HttpSession 中的值可以是任意Java对象,这个对象最好实现了 Serializable接口, +这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。 + +# 三、Cookie 和 Session 区别 + +- HTTP协议是**无状态的协议**,服务端需要记录用户的状态,就需要用某种机制来**识别具体的用户**,这个机制就是Session。 + Session典型的应用场景就是购物车,当点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的, + 所以服务端要为特定的用户创建了特定的Session,用于**标识这个用户,并且跟踪用户**,这样才知道购物车里面的商品情况。 + 这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。 + 集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群, + 用来保存用户会话,这个时候 Session 信息都是放在内存的,此外,一些缓存服务比如Memcached之类的来放 Session。 +- 服务端使用Cookie来识别特定的客户。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。 + 实际上大多数的应用都是用 Cookie 来实现Session跟踪的, + 第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个session id, + 以后每次请求把这个 session id发送到服务器,这样就可以使用对应的Seesion了。 + 如果客户端的浏览器禁用了 Cookie 怎么办? + 一般这种情况下,会使用一种叫做**URL重写的技术**来进行**会话跟踪**, + 即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。 +- Cookie其实还可以用在一些方便用户的场景下, + 设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办? + 这个信息可以写到Cookie里面,访问网站的时候, + 网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了, + 能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。 + +总结: + +- Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中。 +- Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。 + +# 四、Token + +## 服务器验证方式存在的一些问题 + +- 内存开销 + + 每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。 + +- CSRF,跨站请求伪造 + + 进行 Session 认证的时候,我们一般使用 Cookie 来存储 sessionId,当我们登陆后后端生成一个 sessionId 放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个 sessionId,客户端登录以后每次请求都会带上这个 sessionId,服务端通过这个 sessionId 来标识用户。如果别人通过 Cookie 拿到了 sessionId 后就可以代替该用户访问系统了。 + +- 可扩展性 + + 由于sessions 存放在服务器内存中,伴随而来的是可扩展性问题。当我们想要增加服务器来解决负载问题时,session 里的关键性信息会限制我们的扩展。 + +## 基于 Token 的验证原理 + +基于 Token 的身份验证是**无状态的**,我们不用将用户信息存在服务器或 Session 中。没有 session 信息意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录和已经登录到了哪里。客户端每次请求都需要 Token。**Token 应该在 HTTP 的头部发送从而保证了 HTTP 请求无状态**。我们也需要设置服务器属性: + +```html +Access-Control-Allow-Origin: * +``` + +来让服务器能接受来是所有域的请求。 + +具体实现思路: + +- 客户端使用用户名跟密码请求登录 +- 服务端收到请求,去验证用户名与密码 +- 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端 +- 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里 +- 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token +- 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据 + +## Tokens 的优势 + +- 无状态、可扩展 + + 在客户端存储的 Token 是无状态的,并且能够被扩展。基于这种无状态和不存储 Session 信息,负载均衡服务器能够将用户的请求传递到任何一台服务器上,因为服务器与用户信息没有关联。相反在传统方式中,我们必须将请求发送到一台存储了该用户 Session 的服务器上(称为 Session 亲和性),因此当用户量大时,可能会造成 一些拥堵,使用 Token 完美解决了此问题。 + +- 安全性 + + 请求中发送 Token 而不是 Cookie,这能够防止 CSRF(跨站请求伪造)攻击。即使在客户端使用 Cookie 存储 Token,Cookie 也仅仅是一个存储机制而不是用于认证。 + +- 可扩展性 + + 使用 Tokens 能够与其它应用共享权限。例如,能将一个博客帐号和自己的 QQ 号关联起来。当通过一个第三方平台登录 QQ 时,我们可以将一个博客发到 QQ 平台中。使用 Token,可以给第三方应用程序提供自定义的权限限制。当用户想让一个第三方应用程序访问它们的数据时,我们可以通过建立自己的 API,给出具有特殊权限的 Tokens。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +可扩展性: +CORS (跨域资源共享):当我们扩展应用程序,让数据能够从不同设备上访问时,跨域资源的共享会是一个让人头疼的问题。在使用 Ajax 抓取另一个域的资源时(移动端访问我们的 API 服务器),可能会出现禁止请求的情况。 +:用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。 +在这些问题中,可扩展性是最突出的。因此我们有必要去寻求一种更有行之有效的方法。 +———————————————— +版权声明:本文为CSDN博主「wnvalentin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 +原文链接:https://blog.csdn.net/wnvalentin/article/details/89854980 + diff --git "a/docs/Safety/\345\270\270\350\247\201\346\224\273\345\207\273\346\212\200\346\234\257\345\217\212\351\230\262\345\276\241.md" "b/docs/Safety/\345\270\270\350\247\201\346\224\273\345\207\273\346\212\200\346\234\257\345\217\212\351\230\262\345\276\241.md" new file mode 100644 index 00000000..c63adaf0 --- /dev/null +++ "b/docs/Safety/\345\270\270\350\247\201\346\224\273\345\207\273\346\212\200\346\234\257\345\217\212\351\230\262\345\276\241.md" @@ -0,0 +1,319 @@ +# 一、跨站脚本攻击(XSS) + +## 概念 + +跨站脚本攻击(Cross-Site Scripting, XSS),可以将代码注入到用户浏览的网页上,这种代码包括 HTML 和 JavaScript。 + + + +## 攻击原理 + +
+ + + +## 危害 + +- 偷取网站任意数据 +- 偷取用户资料 +- 劫持前端逻辑 +- 显示伪造的文章或者图片 + + + +## 攻击分类 + +### 1. 反射型 + +反射型指的是 url 参数直接注入。比如:在浏览器地址栏中 + +```html +localhost:1521?from=Bai +``` + + + +### 2. 存储型 + +存储到数据库后读取时注入。 + +一个攻击者在论坛的楼层中包含了一段 JavaScript 代码,并且服务器没有正确进行过滤,那就会造在浏览这个页面时会执行这段 JavaScript 代码。 + + + +## XSS 攻击注入点 + +### 1. HTML 节点内容 + +```html +
+ #{content} +
+``` + +注入点: + +```html +
+ +
+``` + +### 2. HTML 属性 + +```html + +``` + +注入点: + +```html + +``` + +其中 1" onerror="alert(1) 就是 #{image} 。这里可看出 ``多了一个属性 onerror。 + +### 3. JavaScript 代码 + +```html + +``` + +注入点: + +```html + +``` + +其中 hello";alert(1);" 就是 #{data}。这里可看出实际上是即为 data 赋值,也进行了 alert 操作。 + +### 4. 富文本 + +富文本需要保留 HTML,但 HTML 存在 XSS 攻击风险。 + + + +## 防御 + +### 浏览器自带防御 + +使用浏览器自带防御可防御一些 XSS。但是存在一些不足: + +- 只能对参数出现在 HMTL 内容或属性的反射型 XSS 进行防御 +- 并不是所有浏览器都支持对 XSS 的防御 + +### HTML 内容 + +```html +
+ +
+``` + +解决: + +- 将 `<` 转义为 `<` +- 将 `>` 转义为 `>` + +转义后: + +```html +<div> + <script> + </script> +</div> +``` + +### HTML 属性 + +```html + +``` + +解决: + +- 将 `"`转义为 `&quto;` +- 将 `'`转义为 `'` +- 将空格转义为 ` ` + +转义后: + +```html + +``` + +### JavaScript 代码 + +```java + +``` + +解决: + +- 将 `"`转义为 `\"` +- 将 `\`转义为 `\\` +- 或者转化为 json + +转义后: + +```html + +``` + +### 富文本 + +[按**白名单**保留部分标签和属性。](https://github.com/leizongmin/js-xss/blob/master/README.zh.md) + +### CSP + +[CSP](https://blog.csdn.net/Fly_hps/article/details/86466367) 即内容安全策略(Content Security Policy):用于指定哪些内容可执行。 + + + + + +# 二、跨站请求伪造(CSRF) + +## 概念 + +跨站请求伪造(Cross-site request forgery,CSRF),是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。 + +XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户浏览器的信任。 + + + +## 攻击原理 + +
+ +- 用户登录 A 网站 +- A 网站确认身份 +- B 网站页面向 A 网站发起请求(带 A 网站身份) + - B 网站向 A 网站请求,带 A 网站 Cookies + - 不访问 A 网站前端 + - referer 为 B 网站 + + + +## 危害 + +- 利用用户登录态 +- 用户不知情 +- 完成业务请求 + + + +## 防御 + +### 带 A 网站 Cookies + +利用 Cookie 中新增**属性 same-site**,禁止第三方网站带 Cookies。但是这样适配性比较差,目前只有 Chrome 支持。 + +### 不访问 A 网站前端 + +在前端页面加入验证消息,有 2 种方式: + +- **验证码** + + 因为 CSRF 攻击是在用户无意识的情况下发生的,所以要求用户输入验证码可以让用户知道自己正在做的操作。 + +- **token** + + 例如服务器生成随机数并附加在表单中,并要求客户端传回这个随机数。 + +### referer 为 B 网站 + +**验证 referer**。判断请求的来源是否合法。 + + + +# 三、SQL 注入 + +## 概念 + +服务器上的数据库运行非法的 SQL 语句,主要通过拼接来完成。 + +## 攻击原理 + +例如一个网站登录验证的 SQL 查询代码为: + +```sql +SELECT * FROM users WHERE (name = '${userName}') and (pw = '${passWord}'); +``` + +如果填入以下内容: + +```sql +userName = 1' OR '1'='1 +passWord = 1' OR '1'='1 +``` + +那么 SQL 查询字符串为: + +```sql +SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1'); +``` + +此时无需验证通过就能执行以下查询: + +```sql +SELECT * FROM users; +``` + +## 危害 + +- 猜解密码 +- 获取数据 +- 删库删表 +- 拖库 + +## 防御 + +- 关闭错误输出(只能在一定程度上增加 SQL 注入的难度,并不能解决 SQL 注入问题) +- 检查数据类型 +- 对数据进行转义 +- 使用**参数化查询**(推荐使用) +- 使用 [ORM](https://www.cnblogs.com/best/p/9711215.html#_label0)(对象关系映射) + + + +# 四、DoS 攻击 + +## 概念 + +拒绝服务攻击(denial-of-service attack,DoS),亦称洪水攻击,模拟正常用户使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致正常用户无法访问。 + +## 类型 + +- TCP 半连接 +- HTTP 连接 +- DNS + +## DDoS + +分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。 + +## 防御 + +- 防火墙 +- 交换机、路由器 +- 流量清洗 +- 高仿 IP + +## 预防 + +- 避免重逻辑业务 +- 快速失败快速返回 +- 防雪崩机制 +- 有损服务 +- CDN \ No newline at end of file diff --git "a/docs/Spring/1_Spring\346\246\202\350\277\260.md" "b/docs/Spring/1_Spring\346\246\202\350\277\260.md" new file mode 100644 index 00000000..56b6d066 --- /dev/null +++ "b/docs/Spring/1_Spring\346\246\202\350\277\260.md" @@ -0,0 +1,187 @@ +# Spring 概述 + +## Spring 的特性 + +Spring 基于 J2EE 技术实现了一套**轻量级**的 Java Web Service 系统应用框架,旨在提高开发人员的开发效率以及系统的可维护性。Spring 的特性包括: + +- 轻量级 + + 从 Jar 包的大小上来说,核心 Jar 包 `spring-web-5.2.0.RELEASE.jar`和 `spring-core-5.2.0.RELEASE.jar`均为 1.4 M 左右; + + 从系统的资源使用上来说,Spring 运行期间只需要少量的操作系统资源(内存和 CPU)便能稳定运行。 + +- 面向容器 + + Spring 实现了对象的配置化生成和对象的生命周期管理,所以是面向容器的。 + +- 控制反转 + +- 面向切面 + +- 框架灵活 + +## Spring 的模块 + +Spring 为企业应用程序提供一站式服务。Spring 模块提供的常用模块有核心容器层(Core Container)、数据访问层(Data Access)、Web 应用层(Web Access)。 + +### 核心容器层 + +核心容器层包括 Spring-Beans、Spring-Core、Spring-Context 等模块。 + +- Spring-Beans + + 基于工厂模式实现对象的创建。Spring-Beans 通过 xml 配置文件实现了声明式的对象管理,将对象之间复杂的依赖关系从实际编码逻辑中解耦出来。 + +- Spring-Core + + Spring 的核心功能实现,提供 IoC 依赖注入功能的支持。 + +- Spring-Context + + 在 Spring-Beans 和 Spring-Core 模块的基础上构建起来的。Spring-Context 模块继承自 Spring-Beans 模块,并且添加了国际化、事件传播、资源加载和透明地创建上下文等功能。 + +### 数据访问层 + +数据访问层包括:JDBC、ORM、OXM、JMS 和 TX 模块。 + +- JDBC (Java Data Base Connectivity) + + 提供了对数据库访问的抽象 JDBC。不同的数据库都有自己独立的 API 用于操作数据库,而 Java 程序只需要和 JDBC API 交互,这样就屏蔽了数据库的影响。 + +- ORM (Object Relational Mapping) + + 提供对 Hibernate 等 ORM 框架的支持。 + +- OXM (Object XML Mapping) + + 提供对 Castor 等 OXM 框架的支持。 + +- JMS (Java Message Service) + + JMS 模块包括消息的生产和消费功能。从 Spring 4.1 开始,Spring 集成了 Spring-Messaging 模块,用于实现对消息队列的支持。 + +- TX + + 提供对事务的支持。 + +### Web 应用层 + +Web 应用层主要包括 Web 交互和数据传输等相关功能,包括 Web、Web-MVC、Web-Socket 和 Web-Flux。 + +- Web + + 提供了面向 Web 应用的基本功能。 + +- Web-MVC + + 提供对 Spring MVC 的实现。 + +- Web-Socket + + 提供了对 WebSocket 的支持,WebSocket 可以让客户端和服务端进行双向通信。 + +- Web-Flux + + 提供对 WebFlux 的支持。 + + 目前最新的 5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。 + +### 其他重要模块 + +- Spring AOP + + 提供了面向切面的编程实现,允许应用程序通过定义方法拦截器和切入点来实现系统功能和业务功能之间的解耦。 + +- Spring Aspects + + 提供了 Spring 与 AspectJ 的集成,是一个面向切面编程的模块。 + +## Spring 的注解 + +### @Contoller + +SpringMVC 中,控制器 Controller 负责处理 DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个 Model,然后再把该 Model 返回给对应的 View 进行展示。 + +SpringMVC 提供了一个非常简便的定义 Controller 的方法,无需继承特定的类或者接口,只需使用 @Controller 标记一个类是 Contoller。 + +### @RequestMapping + +使用 @RequestMapping 来映射 URL 到 Controller,或者到 Controller 的处理方法上。method 的值一旦指定,则处理方法只对指定的 HTTP method 类型请求处理。 + +可以为多个方法映射相同的 URL 和不同的 HTTP method 类型,Spring MVC 根据请求的 method 类型是可以区分开这些方法的。 + +### @RequestParam & @PathVariable + +在 SpringMVC 中,两者的作用都是将 request 里的参数值绑定到 Controller 里的方法参数中,区别在于 URL 的写法不同。 + +- 使用 @RequestParam 时,URL 是这样的: + +```html +http://host:port/path?参数名=参数值 +``` + +- 使用 @PathVariable 时,URL 是这样的: + +```html +http://host:port/path/参数值 +``` + +### @ResponseBody + +该注解用于将 Controller 中方法返回的对象,通过适当的 HttpMessageConverter 转换为指定的格式后,写入到 Response 对象的 bodys 数据区。 + +### @Service & @Controller & @Repository & @Component + + @Service、 @Contrller、 @Repository 其实这 3 个注解和 @Component 是等效的,用在实现类上: + +- @Service 用于标注业务层组件 +- @Controller 用于标注控制层组件 +- @Repository 用于编著数据访问组件 +- @Component 泛指组件,当组件不好归类时,可以使用这个注解进行标注 + +### @Value + +在 Spring 3.0 中,可以通过使用 @Value,对一些如 xxx.properties 文件中的文件,进行键值对的注入。 + +### @Autowired + +@Autowired 可以对成员变量、成员方法和构造函数进行标注,来完成自动装配工作。 + +### @Autowired & @Resource + +@Autowired 是 Spring 提供的注解,采用的策略是**按照类型**注入的: + +```java +public class UserService{ + @Autowired + userDao; // 在 Spring 容器中找到类型为 UserDao 的对象,将其注入 +} +``` + +存在问题:同一类型有多个 Bean,可以使用 @Qualifier 具体去装配哪个对象。 + +```java +public class UserService{ + @Autowired + @Qualifier(name="userDao") + userDao; // 在 Spring 容器中找到类型为 UserDao,名称为 userDao 的对象,将其注入 +} +``` + + @Resource 是 J2EE 提供的注解,默认是**按照名称**注入的: + +```java +Service{ + @Resource + userDao; // 自动按名称进行装配 + + @Resource(name="studentDao") + studentDao; // 按名称进行装配,找不到会抛出异常 + + @Resource(type="TeacherDao") + teacherDao; // 按类型进行装配,找不到或者找到多个都会抛出异常 + + @Resource(name="manDao",type="ManDao") + manDao;// 找唯一匹配的 Bean 进行装配,如果找不到则会抛出异常 +} +``` diff --git "a/docs/Spring/2_SpringIoC\345\216\237\347\220\206.md" "b/docs/Spring/2_SpringIoC\345\216\237\347\220\206.md" new file mode 100644 index 00000000..875edb55 --- /dev/null +++ "b/docs/Spring/2_SpringIoC\345\216\237\347\220\206.md" @@ -0,0 +1,421 @@ +# Spring IoC 原理 + +## IoC (Inverse of Control) + +IOC,即控制反转(Inverse of Control)是一种**设计思想**,并不是一个具体的技术实现。 + +- 控制:控制对象的创建及销毁(生命周期)。 +- 反转:将对象的控制权交给 IoC 容器。 + +**所有类的创建、销毁都由 Spring 来控制,也就是说控制对象生命周期的不是引用它的对象,而是 Spring**。对于某个具体对象而言,以前是它控制其他对象,现在所有对象都被 Spring 控制。 + +## 依赖注入 (Dependency Injection) + +依赖注入就是**将底层类作为参数传递给上层类,实现上层对下层的控制**,**依赖注入实现控制反转**。 + +举例说明依赖注入:以生产行李箱为例。 + +**传统设计思路**:先设计轮子,然后根据轮子 size 来设计底盘,再根据底盘来设计箱体,最后设计好行李箱。 + +可这样表示: + +
+ +相应代码代码: + +
+ +size 是固定值,可以进行相应的改进: + +
+ +**依赖注入设计思路**: + +先设计行李箱的大概样子,再根据行李箱的样子设计箱体,根据箱体去设计底盘,然后去设计轮子。 + +
+ +相应代码如下: + +
+ +不难理解,依赖注入就是**将底层类作为参数传递给上层类,实现上层对下层的控制**。 + +Spring 支持 4 种依赖注入:setter 注入、构造器注入、注解注入和接口注入。 + +### setter 注入 + +```xml + + + + + + + + + + + + + +``` + +```java +public class ExampleBean { + + private AnotherBean beanOne; + + private YetAnotherBean beanTwo; + + private int i; + + public void setBeanOne(AnotherBean beanOne) { + this.beanOne = beanOne; + } + + public void setBeanTwo(YetAnotherBean beanTwo) { + this.beanTwo = beanTwo; + } + + public void setIntegerProperty(int i) { + this.i = i; + } +} +``` + +### 构造器注入 + +```xml + + + + + + + + +``` + +```java +public class ExampleBean { + + private AnotherBean beanOne; + + private YetAnotherBean beanTwo; + + private int i; + + public ExampleBean( + AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { + this.beanOne = anotherBean; + this.beanTwo = yetAnotherBean; + this.i = i; + } +} +``` + +### 注解注入 + +```java +public class ExampleBean { + + @Autowired + @Qualifier("anotherExampleBean") + private AnotherBean beanOne; + + @Autowired + @Qualifier("yetAnotherBean") + private YetAnotherBean beanTwo; + + @Value("1") + private int i; +} +``` + +### 接口注入 + +接口注入模式因为历史较为悠久,在很多容器中都已经得到应用。但由于其在灵活性、易用性上不如其他注入模式,因而在 IOC 的专题世界内并不被看好。 + + + +## IoC 和 DI 的关系 + +依赖注入实现控制反转。 + +依赖倒置原则、IoC、DI 和 IoC 容器的关系: + +
+ +补充:[控制反转-知乎解答](https://www.zhihu.com/question/23277575/answer/169698662) + + + +## IoC 容器 + +IoC 容器指具有依赖注入功能的容器。 + +IoC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。 + +Spring 通过**配置文件**描述 IoC 容器管理的对象。Spring IoC 容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。一般使用基于 xml 配置文件进行配置元数据,而且 Spring 与配置文件完全解耦的,可以使用其他任何可能的方式进行配置元数据,比如注解、基于 Java 文件的、基于属性文件的配置都可以。 + +Spring IoC 容器的代表就是 `org.springframework.beans` 包下的 **BeanFactory** 接口: + +- IoC 容器要实现的最基础的接口 +- 采用**延迟初始化策略**(容器初始化完成后并不会创建 Bean 对象,只有当收到初始化请求时才进行初始化) +- 由于是延迟初始化策略,因此启动速度较快,占用资源较少 + +`org.springframework.context` 包下的 **ApplicationContext** 接口扩展了 BeanFactory: + +- 在 BeanFactory 基础上,增加了更为高级的特性:事件发布、国际化等。 +- 在容器启动时,完成所有 Bean 的创建 +- 启动时间较长,占用资源较多 + +### IoC 容器初始化过程 + +
+ +- Resource 定位:即 BeanDefinition 的资源定位,Resource 为各种形式的 BeanDefinition 的使用都提供了统一的接口 +- BeanDefinition 的载入 +- 向 IoC 容器中注册 BeanDefinition:实际上 IoC 容器内部维护一个 HashMap,注册过程就是将 BeanDefinition 添加至 HashMap 中。 + +### Spring Bean 的装配流程 + +
+ +IoC 容器其实就是一个大工厂,它用来管理我们所有的对象以及依赖关系: + +- Spring 在启动时会从 xml 配置文件/注解中读取应用程序提供的 Bean 配置信息,并在 Spring 容器中生成一份相应的 Bean 定义注册表 +- 根据注册表实例化 Bean,装配好 Bean 之间的依赖关系 +- 将 Bean 实例放入 Spring IoC 容器中,等待应用程序调用 + +### getBean 方法 + +ApplicationContext 接口获取 Bean 的方法: + +| 方法 | 说明 | +| --------------------------------------------- | ------------------------------------------------------------ | +| Object getBean(String name) | 根据名称返回一个 Bean,**客户端需要自己进行类型转换** | +| T getBean(String name, Class requiredType) | 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常 | +| T getBean(Class requiredType) | 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,如果没有或有多于一个Bean存在容器将抛出异常 | +| Map getBeansOfType(Class type) | 根据指定的类型返回一个键值为名字和值为 Bean 对象的Map,如果没有Bean对象存在则返回空的 Map | + +getBean(name) 代码逻辑: + +- 获取参数 name 转化为 beanName +- 从缓存中加载实例 +- 实例化 Bean +- 检测 parentBeanFactory(若无缓存数据,直接到 parentBeanFactory 中去加载) +- 初始化依赖的 Bean +- 返回 Bean + +> **注意:BeanFactory 和 FactoryBean 的区别** + +- BeanFactory 是 IoC 最基本的容器,负责生产和管理 Bean,为其他具体的 IoC 容器提供了最基本的规范。 +- FactoryBean 是一个 Bean,是一个接口,当 IoC 容器中的 Bean 实现了 FactoryBean 后,通过 getBean(String beanName) 获取到的 Bean 对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象。**要想获取 FactoryBean 的实现类对象,就是在 beanName 前面加上 "&"**。 + + + +## Spring 中 Bean 的作用域 + +### singleton + +singleton 即单例模式。singleton 作用域是 Spring 中的**缺省作用域**。 + +当一个 Bean 的作用域为 singleton,那么 Spring IoC 容器中只会存在一个**共享的 Bean 实例**, 并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,则只会**返回 Bean 的同一实例**。 + +可以指定 Bean 节点的 lazy-init="true" 来延迟初始化 Bean, 此时只有在第一次获取 Bean 时才会初始化 Bean,即第一次请求该 Bean 时才初始化。 每次获取到的对象都是同一个对象。 + +配置文件 XML 中将 Bean 定义成 singleton : + +```html + +``` + +@Scope 注解的方式: + +```java +@Service +@Scope("singleton") +public class ServiceImpl{ +} +``` + +### prototype + +prototype 即原型模式。当一个 Bean 的作用域为 prototype,表示一个 Bean 定义对应多个对象实例。 prototype 作用域的 Bean 会导致在每次对该 Bean 请求(将其注入到另一个 Bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 Bean 实例。 + +在创建容器的时候并没有实例化, 而是当我们获取 Bean 的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。 + +配置文件 XML 中将 Bean 定义成 prototype : + +```html + +``` + +或者 + +```html + +``` + +@Scope 注解的方式: + +```java +@Service +@Scope("prototype") +public class ServiceImpl{ +} +``` + +> **Spring 中线程安全问题** + +有状态 Bean & 无状态 Bean: + +- **有状态 Bean** + + 对象中有实例变量(成员变量),可保存数据; + + **非线程安全**。 + +- **无状态 Bean** + + 对象中无实例变量,不能保存数据,可在多线程环境下共享; + + **线程安全**。 + +Spring 采用两种方式保证线程安全: + +- 采用 ThreadLocal 进行处理 +- 采用原型模式,每次有 Bean 请求时,都会创建一个新的 Bean 实例 + +所以根据经验,**对有状态的 Bean 应该使用 prototype 作用域,而对无状态的 Bean 则应该使用 singleton 作用域。** + +### request + +request 只适用于**Web程序**,每一次 HTTP 请求都会产生一个新的 Bean , 同时该 Bean 仅在当前HTTP request 内有效,当请求结束后,该对象的生命周期即告结束。 + +在 XML 中将 Bean 定义成 request ,可以这样配置: + +```html + +``` + +### session + +session 只适用于**Web程序**, session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 Bean, 同时**该 Bean 仅在当前 HTTP session 内有效**。 与 request 作用域一样,可以根据需要放心的更改所创建实例的内部状态, 而别的 HTTP session 中根据 userPreferences 创建的实例, 将不会看到这些特定于某个 HTTP session 的状态变化。 当HTTP session最终被废弃的时候,在该 HTTP session 作用域内的 Bean 也会被废弃掉。 + +```html + +``` + +### globalSession + +globalSession 作用域**类似于标准的 HTTP session** 作用域, 不过仅仅在基于 portlet 的 Web 应用中才有意义。 Portlet 规范定义了全局 Session 的概念, 它被所有构成某个 portlet web 应用的各种不同的 portlet所共享。 在 globalSession 作用域中定义的 Bean 被限定于全局 portlet Session 的生命周期范围内。 + +```html + +``` + +注意:五种作用域中,request、session 和 globalSession 三种作用域仅在基于 Web 的应用中使用(不必关心你所采用的是什么 Web 应用框架),只能用在基于 Web 的 Spring ApplicationContext 环境。 + + + +## Spring 中 Bean 的生命周期 + +Spring bean 的生命周期执行如下图: + +
+ +1、Spring 对 Bean 进行实例化。 + +2、Spring 将值和 Bean 的引用注入到 Bean 对应的属性中。 + +3、如果 Bean 实现了 BeanNameAware 接口,则会调用其实现的 setBeanName() 方法, + +Spring 会将 bean 的 id 传递给 setBeanName() 接口方法。 + +4、如果 Bean 实现了 BeanFactoryAware 接口,则会调用其实现的 setBeanFactory() 方法,将 BeanFactory 容器实例作为传入参数。 + +5、如果 Bean 实现了 ApplicationContextAware 接口,则会调用其实现的 setApplicationContext() 方法,将应用上下文的引用作为传入参数。 + +6、如果 Bean 实现了 BeanPostProcessor 接口,Spring 将调用 postProcessBeforeInitialization() 接口方法。 + +7、如果 Bean 实现了InitializingBean 接口,Spring 将调用 afterPropertiesSet() 接口方法。 + +8、如果Bean 实现了 init-method 声明了初始化方法,该方法也会被调用。 + +9、如果 Bean 实现了 BeanPostProcessor 接口,Spring 将调用 postProcessAfterInitialization() 接口方法。 + +10、此时 Bean 已经准备就绪,可以被应用程序使用了,他们将会一直驻留在应用上下文中,一直到该应用上下文被销毁。 + +11、如果 Bean 实现了 DisposableBean 接口,Spring 将调用它的 destroy() 接口方法。 + +12、如果 Bean 使用 destroy-method 声明了销毁方法,方法也会被调用。 + + + +## 循环依赖问题 + +循环依赖指的是若 A 中有 B 的属性,B 中有 A 的属性,则当进行依赖注入时,就会产生 A 还未创建完,因为对 B 的创建再次返回创建 A。 + +### 类的实例化 & 类的初始化 + +类的实例化是指创建一个类的实例(对象)的过程。 + +类的初始化是指为类中各个类成员(被 static 修饰的成员变量)赋初始值的过程,是**类生命周期中的一个阶段**。 + +### Spring 中类的实例化 & 类的初始化 + +Spring 中**所有 Bean 默认都是单例模式**,所以 Bean 的初始化和实例化都是在加载进入 Bean 容器时进行的。如果想使用时再初始化,那么可以把类定义为原型模式。 + +### 三级缓存 + +单例对象,在 Spring IoC 容器中,有且仅有一个对象,将对象放入缓存中。 + +Spring 中使用 “三级缓存”: + +```java +// 一级缓存:单例对象的缓存(存储实例化完成的 Bean) +/** Cache of singleton objects: bean name --> bean instance */ +private final Map singletonObjects = new ConcurrentHashMap(256); + +// 三级缓存:单例 ObjectFactory 的缓存 +/** Cache of singleton factories: bean name --> ObjectFactory */ +private final Map> singletonFactories = new HashMap>(16); + +// 二级缓存:提前曝光的单例对象的缓存(存储正在实例化的 Bean) +/** Cache of early singleton objects: bean name --> bean instance */ +private final Map earlySingletonObjects = new HashMap(16); +``` + +举例说明解决循环依赖(A 中有B,B 中有 A)的具体过程: + +Spring 中单例对象的初始化主要分为 3 步: + +- 第一步:createBeanInstance +- 第二步:populateBean 填充属性 +- 第三步:intializeBean 初始化 + +在进行 createBeanInstance 后,该单例对象此时已被创建,Spring 将该对象**提前曝光到 singeltonFacoties 中**。 + +- A 完成 createBeanInstance ,并且**提前曝光到 singeltonFacoties 中** +- A 进行第二步,发现需要依赖 B,尝试获取 B +- B 开始创建,B 完成 createBeanInstance,发现需要依赖 A,尝试获取 A:先尝试从 singletonObjects 中获取,发现不存在,因为 A 未初始化完全;再尝试从 earlySingletonObjects 中获取;再去 singletonFactories 中获取,此时 B 获取 A,并将 A 放入 earlySingletonObjects 中,再删除 A 在singletonFactories 中对应的 ObjectFactory。 +- B 获取 A,顺利完成第二、三步,将初始化完成的 B 放入 singletonObjects 中。 +- 此时返回创建 A,A 可获取 B,顺利完成第二、三步,A 初始化完成, 将 A 放入 singletonObjects 中。 + +> **Spring 2 种循环依赖:构造器循环依赖 & setter 循环依赖** + +- 构造器循环依赖:因为提前曝光到 singletonFactories 中的前提是需要执行构造方法,所以使用 “三级缓存” 无法解决该种循环依赖。 +- setter 循环依赖 + +所以在使用 Spring 框架进行开发时: + +- 尽量不要使用基于构造器的依赖注入方式,使用基于 setter 的依赖注入方式 +- 使用 @Autowired 注解,让 Spring 决定合适的时机 + +# 补充 + +- [Spring 官网](https://docs.spring.io/spring-framework/docs/current/reference/html/index.html) +- [Spring 循环依赖及三级缓存](https://blog.csdn.net/u012098021/article/details/107352463?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link) diff --git "a/docs/Spring/3_SpringAOP\345\216\237\347\220\206.md" "b/docs/Spring/3_SpringAOP\345\216\237\347\220\206.md" new file mode 100644 index 00000000..c6da0ca1 --- /dev/null +++ "b/docs/Spring/3_SpringAOP\345\216\237\347\220\206.md" @@ -0,0 +1,92 @@ +# Spring AOP 原理 + +AOP 即面向切面编程(Aspect Oriented Programing),实际上是将一些通用的功能横向抽取出来: + +- 一方面,减少系统的重复代码 +- 另一方面,降低模块间的耦合度,比较好维护和扩展 + +Spring AOP 将应用分为核心关注点和横切关注点。业务处理流程为核心关注点,被业务所依赖的公共部分为横切关注点。横切关注点的特点是其行为经常发生在核心关注点多出,而多处操作基本相似,比如权限认证、日志、事务等。AOP 的核心思想是将核心关注点和横切关注点分离开来,以降低模块耦合度。 + +Spring AOP 的应用场景主要有: + +- 权限统一管理授权 +- 缓存统一维护 +- 数据懒加载 +- 资源池统一申请和管理 +- 统一事务管理 + +## AOP 相关术语 + +| 术语 | 解释 | 描述 | +| :----------: | --------- | :----------------------------------------------------------: | +| Joinpoint | 连接点 | 所谓连接点是指那些被拦截到的点。在 Spring 中,这些点指的是**方法**,因为 Spring 只支持**方法类型的连接点**。 | +| Pointcut | 切入点 | 所谓切入点是指我们要**对哪些 Joinpoint 进行拦截**的定义。 | +| Advice | 通知/增强 | 所谓通知是指拦截到 Joinpoint 之后要执行的具体操作。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能) | +| Introduction | 引介 | 引介是一种**特殊的通知**。在不修改类代码的前提下,可以在运行期为类动态地添加一些方法或字段 | +| Target | 目标对象 | 代理的目标对象 | +| Weaving | 织入 | 是指把增强应用到目标对象来创建新的代理对象的过程。 有三种织入方式:Spring 采用**动态代理织入**,而 AspectJ 采用**编译期织入**和**类装载期织入** | +| Proxy | 代理 | 一个类被 AOP 织入增强后,就产生一个结果代理类 | +| Aspect | 切面 | 是切入点和通知(/引介)的结合 | + +例如在 IUserDao 接口中: + +```java +public interface IUserDao { + void add(); + void delete(); + void update(); + void search(); +} +``` + +- IUserDao 被增强的对象,就是 Target(目标对象) +- add()、delete()、update() 和 search() 都是 JoinPoint(连接点) +- 这里要对 add() 和 update() JoinPoint 进行拦截,则 add() 和 update() 就是 Pointcut(切入点) +- Advice 指的是要增强的代码,也就是代码的增强 +- Weaving:指的是把增强(Advice)应用到目标对象(Target)创建新的代理对象的过程 +- Aspect:是切入点和通知的结合,在 add 或 update 方法上应用增强 + +## AOP 底层原理 + +AOP 的底层原理是动态代理机制: + +- 类实现了接口,JDK 动态代理 +- 类未实现任何接口,Cglib 动态代理 + +## AOP 的 5 种通知类型 + +- 前置通知 + + 在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。 + +- 后置通知 + + 在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。 + +- 成功通知 + + 在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。 + +- 异常通知 + + 在连接点抛出异常后执行。 + +- 环绕通知 + + 环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理连接点(调用ProceedingJoinPoint 的 proceed 方法)还是中断执行。 + +五种通知的执行顺序为:前置通知、环绕通知、成功通知/异常通知、后置通知。 + +## Spring AOP & AspectJ AOP + +- 增强时机 + + Spring AOP 是运行时增强;AspectJ 是编译时增强 + +- 底层原理 + + Spring AOP 基于代理;AspectJ 基于字节码操作 (Bytecode Manipulation) + +- 性能 + + AspectJ 相比于 Spring AOP 功能更加强大,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。Spring AOP 相对来说更简单,并且 Spring AOP 已集成了 AspectJ,如果切面较少,那么两者性能差异不大,当切面较多时,最好选择 AspectJ ,它比 Spring AOP 快很多。 diff --git a/docs/SSM/1_SpringMVC.md "b/docs/Spring/4_SpringMVC\345\216\237\347\220\206.md" similarity index 50% rename from docs/SSM/1_SpringMVC.md rename to "docs/Spring/4_SpringMVC\345\216\237\347\220\206.md" index ea890aa1..42723ef6 100644 --- a/docs/SSM/1_SpringMVC.md +++ "b/docs/Spring/4_SpringMVC\345\216\237\347\220\206.md" @@ -1,69 +1,81 @@ -# SpringMVC +# Spring MVC 原理 -## MVC +## MVC (Model-View-Controller) -即 Model-View-Controller,是一种复合模式。 +MVC 即 Model-View-Controller,是一种复合模式。 - Model:模型。封装数据源和所有基于这些数据的操作 - View:视图。用来显现模型 - Controller:控制器。封装外界作用于模型的操作 -其中,模型利用 “观察者模式” 让 Controller 和视图随最新的状态改变而更新;View 和 Controller 实现 “策略模式”,控制器是视图的行为,若希望有不同的行为,可直接换一个控制器;视图内部利用“组合模式”。 +模型利用 “观察者模式” 让控制器和视图随最新的状态改变而更新; -优点: +视图和控制器实现 “策略模式”,控制器是视图的行为,若希望有不同的行为,可直接换一个控制器; + +视图内部则是利用 “组合模式”。 + +MVC 具有以下优点: - 三个模块可共享一个模型,大大提高代码的可重用性 - 三个模块相互独立,耦合性较低 - Controller 提高了应用程序的灵活性,使用 Controller 可连接不同模型和视图去满足用户的需求 -## SpringMVC +## Spring MVC SpringMVC 是一种基于 Java,实现了 Web MVC 设计模式,请求驱动类型的轻量级 Web 框架。优点如下: - 基于组件技术。全部的应用对象,无论是控制器、视图,还是业务对象之类都是 Java 组件。并且和 Spring 提供的其他基础结构紧密集成; - 不依赖于 Servlert API; -- 可以任意使用各种视图技术,而不仅仅局限于jspl; +- 可以任意使用各种视图技术,而不仅仅局限于 jspl; - 支持各种请求资源的映射策略; - 易扩展。 ### 原理 -SpringMVC 框架是以请求为驱动,围绕 Servlet 设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。 其中**核心类是 DispatcherServlet**,它是一个 Servlet,顶层实现 Servlet 接口。 +Spring MVC 框架是以请求为驱动,围绕 **DispatcherServlet** 设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。 原理图如下: -
- +
+- 客户端发起 HTTP 请求,将请求提交到 DispatcherServlet。 +- 寻找处理器:由 DispatcherServlet 查询一个或多个 HandlerMapping,找到处理该请求的 Contoller。 +- 调用处理器:DispatcherServlet 将请求提交到 Controller。 +- 调用业务处理逻辑并返回结果:Controller 调用业务处理逻辑后,返回 ModelAndView。 +- 处理视图映射并返回模型:DispatcherServlet 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 指定的视图。 +- HTTP 响应:视图负责将结果在客户端浏览器上渲染和展示。 ### 重要组件 -#### 1、DispatcherServlet +#### DispatcherServlet - 说明:前端控制器,不需要工程师开发,由 SpringMVC 框架提供。 - 作用:**Spring MVC 的入口。接收请求,响应结果,相当于转发器,中央处理器**。DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,**DispatcherServlet 降低了组件之间的耦合度**。 -#### 2、HandlerMapping +#### HandlerMapping -- 说明:处理器映射器,不需要工程师开发,由 SpringMVC 框架提供。 -- 作用:**根据请求的 url 查找 Handler**。SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 +- 说明:处理器映射器,不需要工程师开发,由 Spring MVC 框架提供。 +- 作用:**根据请求的 url 查找 Handler**。Spring MVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 -#### 3、HandlerAdapter +#### HandlerAdapter - 说明:处理器适配器。 -- 作用:**按照特定规则(HandlerAdapter要求的规则)执行 Handler**。通过 HandlerAdapter 对处理器进行执行,这是[适配器模式](https://duhouan.github.io/Java/#/OO/4_%E7%BB%93%E6%9E%84%E5%9E%8B?id=_1-%e9%80%82%e9%85%8d%e5%99%a8%ef%bc%88adapter%ef%bc%89)的应用,通过扩展适配器可以对更多类型的处理器进行执行。 +- 作用:**按照特定规则(HandlerAdapter要求的规则)执行 Handler**。通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 -#### 4、Handler +#### Handler - 说明:处理器,需要工程师开发。 - 注意:编写 Handler 时按照 HandlerAdapter 的要求的规则去做,这样适配器才可以去正确执行 Handler, Handler 是**后端控制器**,在 DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。 由于 Handler 涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发 Handler。 -#### 5、ViewResolver +#### ViewResolver + +- 说明:视图解析器,不需要工程师开发,由 Spring MVC 框架提供。 + +- 作用:**进行视图解析,根据逻辑视图名解析成真正的视图**。ViewResolver 负责将处理结果生成 View 视图, ViewResolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再**生成 View 视图对象**。 -- 说明:视图解析器,不需要工程师开发,由 SpringMVC 框架提供。 -- 作用:**进行视图解析,根据逻辑视图名解析成真正的视图**。ViewResolver 负责将处理结果生成 View 视图, ViewResolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对View 进行渲染将处理结果通过页面展示给用户。 SpringMVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView等。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要工程师根据业务需求开发具体的页面。 + Spring MVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView等。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要工程师根据业务需求开发具体的页面。 -#### 6、View +#### View - 说明:视图 View,需要工程师开发。 -- 作用:**View 是一个接口,实现类支持不同的 View类型(jsp、freemarker、pdf…)**。 \ No newline at end of file +- 作用:**View 是一个接口,实现类支持不同的 View 类型(jsp、freemarker、pdf…)**。 diff --git "a/docs/Spring/5_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" "b/docs/Spring/5_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" new file mode 100644 index 00000000..1480f92a --- /dev/null +++ "b/docs/Spring/5_Spring\344\272\213\345\212\241\347\256\241\347\220\206.md" @@ -0,0 +1,406 @@ +# Spring 事务管理 + +## 编程式事务 & 声明式事务 + +### 编程式事务 + +编程式事务指的是通过编码方式实现事务,类似 JDBC 编程实现事务管理,比如 TransactionalTemplate 或者 TransactionManager。 + +```java +@Autowired +private TransactionTemplate transactionTemplate; + +public void testTransaction() { + + transactionTemplate.execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { + + try { + // 业务代码 + } catch (Exception e){ + // 回滚 + transactionStatus.setRollbackOnly(); + } + } + }); +} +``` + +```java +@Autowired +private PlatformTransactionManager transactionManager; + +public void testTransaction() { + + TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + // 业务代码 + transactionManager.commit(status); + } catch (Exception e) { + // 回滚 + transactionManager.rollback(status); + } +} +``` + +### 声明式事务 + +声明式事务在 **XML 配置文件中配置**或者直接基于**注解**,其中基于`@Transactional` 的全注解方式使用最多。 + +| 事务方式 | 优点 | 缺点 | +| :--------: | :----------------: | :------------------------: | +| 编程式事务 | 显示调用,不易出错 | 侵入式代码,编码量大 | +| 声明式事务 | 简单,对代码侵入小 | 隐藏实现细节,出错不易定位 | + + + +## Spring 事务管理接口 + +Spring 框架中,事务管理相关最重要的 3 个接口如下: + +- PlatformTransactionManager:(平台)事务管理器 +- TransactionDefinition:事务定义信息(隔离级别、传播行为、超时、只读、回滚) +- TransactionStatus:事务运行状态 + +**所谓事务管理,实质上就是按照给定的事务规则来执行提交或者回滚操作**。其中,“给定的事务规则”是用 TransactionDefinition 表示的,“按照……来执行提交或者回滚操作”是用 PlatformTransactionManager 表示的,而 TransactionStatus 可以看作代表事务本身。 + +### PlatformTransactionManager + +**Spring 并不直接管理事务,而是提供了多种事务管理器** 。Spring 事务管理是通过 PlatformTransactionManager 接口体现的,该接口是 Spring事务策略的核心。通过该接口,Spring 为各个平台如 JDBC (DataSourceTransactionManager)、Hibernate (HibernateTransactionManager)、JPA (JpaTransactionManager) 等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。 + +```java +public interface PlatformTransactionManager { + + //平台无关的获得事务的方法 + TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; + + //平台无关的事务提交方法 + void commit(TransactionStatus status) throws TransactionException; + + //平台无关的事务回滚方法 + void rollback(TransactionStatus status) throws TransactionException; +} +``` + +比如我们在使用 JDBC 进行数据持久化操作时,进行如下配置: + +```xml + + + + + +``` + +### TransactionDefinition + +TransactionDefinition 接口用于定义事务属性,事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了以下 5 个方面: + +- 事务隔离级别 +- 事务传播行为 +- 回滚规则 +- 是否只读 +- 事务超时 + +### TransactionStatus + +TransactionStatus 接口用来记录事务的状态,该接口定义了一组方法,用来获取或判断事务的相应状态信息。 + +```java +public interface TransactionStatus{ + boolean isNewTransaction(); // 是否是新的事务 + boolean hasSavepoint(); // 是否有恢复点 + void setRollbackOnly(); // 设置为只回滚 + boolean isRollbackOnly(); // 是否为只回滚 + boolean isCompleted; // 是否已完成 +} +``` + + + +## Spring 事务属性 + +### 事务隔离级别 + +事务隔离级别是指多个事务之间的隔离程度。 + +TransactionDefinition 接口中定义了 5 个表示隔离级别的常量: + +```java +public interface TransactionDefinition { + ... + int ISOLATION_DEFAULT = -1; + int ISOLATION_READ_UNCOMMITTED = 1; + int ISOLATION_READ_COMMITTED = 2; + int ISOLATION_REPEATABLE_READ = 4; + int ISOLATION_SERIALIZABLE = 8; + ... +} +``` + +```java +// 事务隔离级别对应的枚举 +public enum Isolation { + DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), + READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED), + REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ), + SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE); + + private final int value; + + Isolation(int value) { + this.value = value; + } + + public int value() { + return this.value; + } + +} +``` + +| 隔离级别 | 解释 | 说明 | +| :------------------------: | -------- | :----------------------------------------------------------: | +| ISOLATION_DEFAULT | 默认 | 这是默认值,表示使用底层数据库的默认隔离级别。 | +| ISOLATION_READ_UNCOMMITTED | 读未提交 | 该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据,该级别不能防止脏读和不可重复读,因此很少使用该隔离级别 | +| ISOLATION_READ_COMMITTED | 读可提交 | 该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下推荐的隔离级别 | +| ISOLATION_REPEATABLE_READ | 可重复读 | 该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读,但幻读仍有可能发生 | +| ISOLATION_SERIALIZABLE | 可串行化 | 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是,这将严重影响程序的性能,通常情况下也不会用到该级别 | + +### 事务传播行为 + +**事务传播行为是为了解决业务层方法之间互相调用的事务问题**。 + +当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。 + +TransactionDefinition 接口中定义了 5t个表示传播行为的常量: + +```java +public interface TransactionDefinition { + int PROPAGATION_REQUIRED = 0; + int PROPAGATION_SUPPORTS = 1; + int PROPAGATION_MANDATORY = 2; + int PROPAGATION_REQUIRES_NEW = 3; + int PROPAGATION_NOT_SUPPORTED = 4; + int PROPAGATION_NEVER = 5; + int PROPAGATION_NESTED = 6; + ... +} +``` + +```java +// 事务传播行为对应的枚举 +public enum Propagation { + REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), + SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), + MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), + REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), + NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), + NEVER(TransactionDefinition.PROPAGATION_NEVER), + NESTED(TransactionDefinition.PROPAGATION_NESTED); + + private final int value; + + Propagation(int value) { + this.value = value; + } + + public int value() { + return this.value; + } + +} +``` + +| 传播行为 | 简写 | 说明 | +| :-----------------------: | :-----------: | :----------------------------------------------------------: | +| PROPAGATION_REQUIRED | required | 如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。 | +| PROPAGATION_SUPPORTS | supports | 表示支持当前事务,如果当前没有事务,就以无事务方式执行。 | +| PROPAGATION_MANDATORY | mandatory | 表示使用当前的事务,如果当前没有事务,就抛出异常。 | +| PROPAGATION_REQUIRES_NEW | required_new | 表示新建事务,如果当前存在事务,把当前事务挂起。 | +| PROPAGATION_NOT_SUPPORTED | not_supported | 表示以无事务方式执行操作,如果当前存在事务,就把当前事务挂起。 | +| PROPAGATION_NEVER | never | 表示以无事务方式执行,如果当前存在事务,则抛出异常。 | +| PROPAGATION_NESTED | nested | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 | + +举例说明事务传播类型: + +```java +StudentServiceImplA implements StudentService{ + @Autowired + studentDao; + + @Autowired + studentService; + + @Transactional(required) // 事务传播特性为 requried: 如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。 + insertA(){ + // 对数据库操作,插入 A 数据 + studentService.insertB(); // 插入 B 数据 + // I/O 异常 + } +} +``` + +```java +StudentServiceImplB implements StudentService{ + @Autowired + studentDao; + + @Transactional + insertB(){ + // 对数据库操作,插入 B 数据 + } +} +``` + +分以下几种情况讨论: + +- 若 StudentServiceImplB 中 insertB() 中传播类型是 required,数据库中既没有 A 数据,也没有 B 数据,则 insertA() 和 insertB() 属于同一个事务,发生异常,事务回滚即可。 +- 若 StudentServiceImplB 中 insertB() 中传播类型是 required_new,数据库中没有 A 数据,但是有 B 数据,则 insertB() 创建了一个新事务,insertA() 中发生异常,该事务回滚。 +- 若 StudentServiceImplB 中 insertB() 中传播类型是 not_supported,数据库中没有 A 数据,但是有 B 数据,则 insertB() 以非事务方式执行,执行 insertA() 的事务回滚,insertB() 中不会发生回滚 + +**注意:insertB() 为何要放入 StudentServiceImplB 中?** + +Spring 的事务机制是基于 AOP 代理实现的。如果在 StudentServiceImplA 中使用 insertB() ,insertA() 中在调用 insertB() 是通过当前对象来调用 insertB() 的,而不是通过代理来调用 insertB() 的,此时 insertB() 上加**事务注解就失效了**。 + +### 事务超时属性 + +事务超时指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒,默认值为 -1。 + +### 事务只读属性 + +对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务。 + +只读事务不涉及数据的修改,数据库会提供一些优化手段,适合用在有多条数据库查询操作的方法中。 + +### 事务回滚规则 + +默认情况下,事务只有遇到运行期异常时才会回滚,Error 也会导致事务回滚,但遇到检查型异常时不会回滚。 + + + +## @Transactional 注解 + +@Transactional 注解可以使用在类上,表明该注解对该类中所有的 public 方法都生效。也可以使用在方法上,但是注解只能应用到 public 方法上,否则不生效。 + +### 源码解析 + +```java +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface Transactional { + + @AliasFor("transactionManager") + String value() default ""; + + @AliasFor("value") + String transactionManager() default ""; + + // 事务的传播行为,默认值为 REQUIRED + Propagation propagation() default Propagation.REQUIRED; + + // 事务隔离级别,默认值为 DEFAULT + Isolation isolation() default Isolation.DEFAULT; + + // 事务的超时时间,默认值为-1,即不会超时 + int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; + + // 指定事务是否为只读事务,默认值为 false + boolean readOnly() default false; + + // 用于指定能够触发事务回滚的异常类型 + // Class[] 说明可以指定多个异常类型 + Class[] rollbackFor() default {}; + + String[] rollbackForClassName() default {}; + + Class[] noRollbackFor() default {}; + + String[] noRollbackForClassName() default {}; + +} +``` + +### 工作机制 + +@Transactional 的工作机制是基于 Spring AOP 实现的。 + +如果一个类或者一个类中的 public 方法被标注 @Transactional 注解的话,Spring 容器就会在启动的时候为其创建一个代理类,在调用被 @Transactional 注解的 public 方法的时,实际调用的是 TransactionInterceptor 类中的 invoke() 方法。invoke() 方法会在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成后提交事务。 + +### 事务失效问题 + +#### 1. 同一个类中方法调用 + +在同一个类中的其他没有被 @Transactional 注解的方法内部调用 @Transactional 注解的方法,则 @Transactional 注解的方法的事务会失效。 + +这是因为Spring AOP 代理造成的,因为只有当 @Transactional`注解的方法在类以外被调用的时候,Spring 事务管理才生效。 + +```java +@Service +public class StudentService { + + private void insertA() { + // insertA() 中调用 insertB() 是通过当前对象来调用 insertB() 的,而不是通过代理来调用 insertB() 的,此时insertB()上加事务注解就失效了。 + insertB(); + // ... + } + + // 事务注解失效 + @Transactional + public void insertB() { + // ... + } +}Copy to clipboardErrorCopied +``` + +可以采用以下 2 种方式解决事务失效问题: + +- 避免同一类中自调用 +- 使用 AspectJ 取代 Spring AOP 代理 + +#### 2. try-catch 导致事务失效 + +```java +StudentServiceImplA implements StudentService{ + @Autowired + studentDao; + + @Autowired + studentService; + + @Transactional + insertA(){ + try { + // 对数据库操作,插入 A 数据 + studentService.insertB(); // 插入 B 数据 + } catch (Exception e) { + e.printStackTrace(); + } + } +} +``` + +如果 insertB() 内部抛了异常,被 insertA() 方法 catch 了该异常,则该事务不能正常回滚。 + +这是因为当 ServiceB 中抛出异常后,ServiceB 标识当前事务需要 rollback 。但是ServiceA 中由于捕获这个异常并进行处理,ServiceA 认为当前事务应该正常commit ,会抛出UnexpectedRollbackException 异常。 + +Spring 的事务是在调用业务方法之前开始的,业务方法执行完毕之后才执行 commit 或者 rollback,事务是否执行取决于是否抛出运行时异常。如果抛出运行时异常并在业务方法中没有 catch 到的话,事务会回滚。 + +解决该事务失效问题: + +在业务方法中一般不需要 catch 异常,如果非要 catch 则一定要抛出运行时异常,或者注解中指定抛异常类 @Transactional(rollbackFor=Exception.class)。 + +#### 3. 数据库引擎不支持事务 + +事务能否生效数据库引擎是否支持事务是关键。 + +常用的 MySQL 数据库默认使用支持事务的InnoDB 存储引擎。如果数据库引擎切换成不支持事务的 MyIsam,那么事务就从根本上失效了。 + +### 使用注意事项 + +- 正确的设置 @Transactional 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败 +- @Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用 +- 避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效 diff --git "a/docs/Spring/6_Spring\344\270\255\347\224\250\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/docs/Spring/6_Spring\344\270\255\347\224\250\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" new file mode 100644 index 00000000..4eb9f6e4 --- /dev/null +++ "b/docs/Spring/6_Spring\344\270\255\347\224\250\345\210\260\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -0,0 +1,102 @@ +# Spring 中涉及到的设计模式 + +## 工厂模式 + +Spring 使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 Bean。 + +```java +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.FileSystemXmlApplicationContext; + +public class App { + public static void main(String[] args) { + ApplicationContext context = new FileSystemXmlApplicationContext( + "xxxx"); + + context.getBean("xxx"); // 使用 ApplicationContext 创建 Bean + } +} +``` + +## 单例模式 + +Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式: + +```java +// 通过 ConcurrentHashMap(线程安全) 实现单例注册表 +private final Map singletonObjects = new ConcurrentHashMap(64); + +public Object getSingleton(String beanName, ObjectFactory singletonFactory) { + Assert.notNull(beanName, "'beanName' must not be null"); + synchronized (this.singletonObjects) { + // 检查缓存中是否存在实例 + Object singletonObject = this.singletonObjects.get(beanName); + if (singletonObject == null) { + //... + try { + singletonObject = singletonFactory.getObject(); + } + //... + // 如果实例对象不不存在,那么注册到单例注册表中。 + addSingleton(beanName, singletonObject); + } + return (singletonObject != NULL_OBJECT ? singletonObject : null); + } + } + // 将对象添加到单例注册表 + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); + + } + } +} +``` + +Spring 实现单例的方式: + +- XML 配置方式: + + ```xml + + ``` + +- 注解方式: + + ```java + @Service + @Scope("singleton") + public class TestServiceImpl{ + } + ``` + +## 原型模式 + +Spring 实现原型方式: + +Spring 实现单例的方式: + +- XML 配置方式: + + ```xml + + ``` + +- 注解方式: + + ```java + @Service + @Scope("prototype") + public class TestServiceImpl{ + } + ``` + +## 代理模式 + +Spring AOP、Spring 事务管理都大量运用了代理模式。 + +## 适配器模式 + +Spring AOP 的增强或通知 (Advice) 使用到了适配器模式,与之相关的接口是 AdvisorAdapter 。Advice 常用的类型有:BeforeAdvice(前置通知)、AfterAdvice(后置通知)等,每个类型 Advice 都有对应的拦截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter。Spring 预定义的 Advice 要通过对应的适配器,适配成 MethodInterceptor 接口(方法拦截器)类型的对象,例如 MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice。 + +Spring MVC 中的 DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler 后,开始由 HandlerAdapter 处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。 diff --git a/docs/Spring/7_MyBatis.md b/docs/Spring/7_MyBatis.md new file mode 100644 index 00000000..9c7e4777 --- /dev/null +++ b/docs/Spring/7_MyBatis.md @@ -0,0 +1,123 @@ +# Mybatis 基本原理 + +MyBatis 是 Apache 的一个 Java 开源项目,是一款优秀的持久层框架。 + +支持定制化 SQL、存储过程以及高级映射。Mybatis 可将 SQL 语句配置在 XML 文件中,避免将 SQL 语句硬编码在 Java 类中。MyBatis 具有如下特点: + +- 通过参数映射方式,可以将参数灵活的配置在 SQL 语句中的配置文件中,避免在 Java 类中配置参数(JDBC) +- 通过输出映射机制,将结果集的检索自动映射成相应的 Java 对象,避免对结果集手工检索(JDBC) +- Mybatis 通过 XML 配置文件对数据库连接进行管理 + +## 核心类 + +### SqlSession + +SqlSession 相当于一个会话,每次访问数据库都需要这样一个会话,类似 JDBC 中的 Connection,但是现在几乎所有的连接都是使用的连接池技术,用完后直接归还而不会像 SqlSession 一样销毁。 + +注意 SqlSession 不是线程安全的,应该设置为线程私有。每次创建的 SqlSession 都必须及时关闭它,如果 SQLSession 长期存在就会使数据库连接池的活动资源减少,对系统性能的影响很大,可以在 finally 代码块中将其关闭。此外 SqlSession 存活于一个应用的请求和操作,可以执行多条 SQL语句,保证事务的一致性。 + +SqlSession 在执行过程中,包括以下对象: + +- **Executor** + + 即执行器,负责调度 StatementHandler、ParameterHandler、ResultSetHandler 等来执行对应的 SQL 语句。 + +- **StatementHandler** + + 使用数据库的 Statement(PreparedStatement)执行操作。 + +- **ParamentHandler** + + 来处理 SQL 参数。 + +- **ResultSetHandler** + + 封装并处理数据集。 + +### SqlSessionFactory + +SqlSessionFactory 用于创建 SqlSession。每次应用程序访问数据库时, 需要通过 SqlSessionFactory 创建 SqlSession,显然 SqlSessionFactory 和整个 Mybatis 的生命周期是相同的。 + +SqlSessionFactory 是线程安全的,应用运行迁建不要重复创建多次,因为创建多个可能为消耗尽数据库的连接资源,建议使用单例模式。 + +### SqlSessionaFactoryBuilder + +SqlSessionaFactoryBuilder 用于创建 SqlSessionFactory,该类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域。 + +### Mapper + +Mapper 接口的实例是从 SqlSession 中获取,作用是发送 SQL,然后返回我们需要的结果,或者执行 SQL 从而更改数据库的数据,因此它应该在 SqlSession 的事务方法之内。 + +在 Spring 管理的 Bean 中, Mapper 是单例的。 + +## 功能架构 + +
+ +### 接口层 + +提供给外部使用的接口 API,开发人员通过这些本地 API 来操作数据库。 + +接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。 + +### 数据处理层 + +负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要功能是根据调用的请求完成一次数据库操作。 + +- 加载配置:配置来源有配置文件或者注解,将 SQL 的配置信息加载成为一个个 MappedStatement 对象(包括了传入参数映射配置、执行的 SQL 语句、结果映射配置),存储在内存中。 +- SQL解析:当 API 接口层接收到调用请求时,会接收到传入 SQL 的 ID 和传入对象(可以是 Map、JavaBean 或者基本数据类型),Mybatis 会根据 SQL 的 ID 找到对应的 MappedStatement,然后根据传入参数对象对MappedStatement 进行解析,解析后可以得到最终要执行的 SQL 语句和参数。 +- SQL执行:将最终得到的 SQL 和参数拿到数据库进行执行,得到操作数据库的结果。 +- 结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean 或者基本数据类型,并将最终结果返回。 + +### 基础支撑层 + +负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。 + +## 执行流程 + +- Mybatis 配置 + + sqlMapConfig.xml 文件是 Mybatis 的全局配置文件,配置了 Mybatis的运行环境等信息。Mapper.xml 文件即 SQL 映射文件,文件中配置了操作数据库的 SQL 语句,需要在 sqlMapConfig.xml 中加载。 + +- 通过 Mybatis 环境等配置信息构造 SqlSessionFactory + +- 通过 SqlSessionFactory 创建 SqlSession,操作数据库需要通过 SqlSession进行。 + +- Mybatis 自定义了 Executor 执行器操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。 + +- MappedStatement 是 Mybatis 一个底层封装对象,包装 Mybatis 配置信息及 SQL 映射信息等。Mapper.xml 文件中一个 SQL 对应一个 MappedStatement对象,SQL 的 id 即 MappedStatement 的 id。 + +- MappedStatement 对 SQL 执行输入参数进行定义,包括 HashMap、基本类型、pojo,Executor 通过MappedStatement 在执行 SQL 前将输入的 Java 对象映射至 SQL 中,输入参数映射就是 jdbc 编程中对preparedStatement 设置参数。 + +- MappedStatement 对 SQL 执行输出结果进行定义,包括 HashMap、基本类型、pojo,Executor 通过MappedStatement 在执行 SQL 后将输出结果映射至 Java对象中,输出结果映射过程相当于 jdbc 编程中对结果的解析处理过程。 + +
+ +## 缓存机制 + +MyBatis 的缓存分为一级缓存和二级缓存。默认情况下一级缓存是开启的。 + +
+ +### 一级缓存 + +一级缓存指 SqlSession 级别的缓存,在同一个 SqlSession 中执行相同的 SQL 语句查询时将查询结果集缓存。一级缓存最多能缓存 1024 条 SQL 语句。 + +当客户端第一次发出一个 SQL 查询语句时,MyBatis 执行 SQL 查询并将查询结果写入 SqlSession 的一级缓存,当第二次有相同的 SQL 查询语句时,则直接从缓存中获取。当同一个 SqlSession 多次发出相同的 SQL 查询语句时,MyBatis 直接从缓存中获取数据。如果两次查询中出现 commit 操作(新增、删除、修改),则认为数据发生了变化,Mybaits 会把该 SqlSession 中的一级缓存区域全部清空,当下次再到缓存中查找时将找不到对应的缓存数据,因此需要再次从数据库中查询数据并将查询的结果写入缓存。 + +### 二级缓存 + +二级缓存指跨 SqlSession 的缓存,即 Mapper 级别的缓存。在 Mapper 级别的缓存内,不同的 SqlSession 缓存可以共享。 + +Mapper 以命名空间为单位创建缓存数据结构,数据结构是 Map 类型,Map 中 Key 为`MapperId + Offset + Limit + SQL + 所有入参`。开启二级缓存后,会使用 CachingExecutor 装饰 Executor ,在进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询。 + +开启二级缓存需要做一下配置: + +- 在全局配置中启用二级缓存配置。 +- 在对应的 Mappper.xml 中配置 Cache 节点。 +- 在对应的 select 查询节点中添加 userCache=true。 + +# MyBatis 面试题 + +- [MyBatis 面试题集锦](https://snailclimb.gitee.io/javaguide/#/docs/system-design/framework/mybatis/mybatis-interview) +- [Mybatis 的常见面试题](https://blog.csdn.net/eaphyy/article/details/71190441) diff --git "a/docs/SpringBoot/1_SpringBoot\346\246\202\350\277\260.md" "b/docs/SpringBoot/1_SpringBoot\346\246\202\350\277\260.md" new file mode 100644 index 00000000..678f2770 --- /dev/null +++ "b/docs/SpringBoot/1_SpringBoot\346\246\202\350\277\260.md" @@ -0,0 +1,65 @@ +# Spring Boot 概述 + +## Spring Boot 特点 + +SpringBoot 是由 pivotal 团队开发的全新的Spring 框架,其设计初衷是**简化 Spring 应用复杂的搭建和开发过程**。该框架提供了一套简单的 Spring 模块依赖和管理工具,从而避免了开发人员处理复杂的模块依赖和版本冲突问题,同事提供打包即可用 Web 服务。 + +SpringBoot 特点如下: + +- 快速创建独立的 Spring 应用程序 +- 嵌入 Tomcat Web 容器,可快速部署 +- 自动配置 JAR 包依赖和版本控制,简化 Maven 配置 +- 自动装配 Spring 实例,不需要 XML 配置 +- 提供诸如性能指标、健康检查、外部配置等线上监控和配置功能。 + +## Spring Boot Application Starters + +Starters 是一组**资源依赖描述**,用于为不同的 SpringBoot 应用提供一站式服务,而不必像传统的 Spring 项目那样,需要开发人员处理服务和服务之间的复杂依赖关系。例如,如果需要开发 REST 服务或 Web 应用程序时,只需只需添加一个 **spring-boot-starter-web** 依赖就可以了,具体的依赖细节由 Starters 统一处理,不需要应用程序分别处理各个 Jar 包之间的依赖关系。 + +```html + + + org.springframework.boot + spring-boot-starter-web + +``` + +## Spring Boot 支持的内嵌 Servlet 容器 + +Spring Boot 支持的内嵌 Servlet 容器有: + +- Tomcat 9.0 +- Jetty 9.4 +- Undertow 2.0 + +Spring Boot ( spring-boot-starter-web) 使用 Tomcat 作为默认的嵌入式 Servlet 容器,如果需要使用 Jetty 的话需要修改 pom.xml (Maven) 或者 build.gradle (Gradle) 文件配置。 + +```html + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + + org.springframework.boot + spring-boot-starter-jetty + +``` + +```html +// 修改 build.gradle 文件配置(看上去更加简洁) +compile("org.springframework.boot:spring-boot-starter-web") { + exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' +} +compile("org.springframework.boot:spring-boot-starter-jetty") +``` + diff --git "a/docs/SpringBoot/2_\351\205\215\347\275\256\346\226\207\344\273\266.md" "b/docs/SpringBoot/2_\351\205\215\347\275\256\346\226\207\344\273\266.md" new file mode 100644 index 00000000..92f4732c --- /dev/null +++ "b/docs/SpringBoot/2_\351\205\215\347\275\256\346\226\207\344\273\266.md" @@ -0,0 +1,214 @@ +# 配置文件 + +## YAML 文件 + +我们可以通过 application.properties / application.yml 对 Spring Boot 程序进行简单的配置。 + +YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写,是一种人类可读的数据序列化语言。相比于 properties 文件,YAML 配置的方式更加直观清晰,简介明了,有层次感。 + +properties 配置方式: + +```html +server.port=8330 +spring.dubbo.applicaiton.name=dubbo-consumer +spring.dubbo.applicaiton.registry=zookeeper:127.0.0.1:2181 +``` + +yaml 配置方式: + +```html +server: + prot:8330 +spring: + dubbo: + application: + name:dubbo-consumer + registry:zookeeper:127.0.0.1:2181 +``` + +但是 YAML 配置的方式有一个缺点,那就是不支持 @PropertySource 注解导入自定义的 YAML 配置。 + +## 读取配置文件 + +### @Value 方式 + +```java +@Value("${xxx}") +String xxx; +``` + +根据传入的 xxx 获取相应的值,@Value 方式一般同于读取比较简单的配置信息,但是并不建议使用。 + +### @ConfigurationProperties 方式 + +定义一个 LibraryProperties 类: + +```java +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import java.util.List; + +// 使用 @Component 注解声明,可以像使用普通 Bean 一样将其注入到类中使用。 +@Component +@ConfigurationProperties(prefix = "library") +@Setter +@Getter +@ToString +class LibraryProperties { + private String location; + private List books; + + @Setter + @Getter + @ToString + static class Book { + String name; + String description; + } +} +``` + + + +```java +package cn.javaguide.readconfigproperties; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ReadConfigPropertiesApplication implements InitializingBean { + + // 注入使用 + private final LibraryProperties library; + + public ReadConfigPropertiesApplication(LibraryProperties library) { + this.library = library; + } + + public static void main(String[] args) { + SpringApplication.run(ReadConfigPropertiesApplication.class, args); + } + + @Override + public void afterPropertiesSet() { + System.out.println(library.getLocation()); + System.out.println(library.getBooks()); + } +} +``` + +### @ConfigurationProperties 方式 + +@ConfigurationProperties 方式不仅可以读取数据,还可以对读取的数据进行校验。 + +```html +user: + name: xxx + email: 123455@ +``` + +```java +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; + +// 注意:这里 ProfileProperties 类没有加 @Component 注解。 +@Getter +@Setter +@ToString +@ConfigurationProperties("user") +@Validated +public class ProfileProperties { + @NotEmpty + private String name; + + @Email + @NotEmpty + private String email; + + // 配置文件中没有读取到的话就用默认值 + private Boolean handsome = Boolean.TRUE; +} +``` + +```java +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +@SpringBootApplication +// 使用 @EnableConfigurationProperties 注册我们的配置 Bean。 +@EnableConfigurationProperties(ProfileProperties.class) +public class ReadConfigPropertiesApplication implements InitializingBean { + private final ProfileProperties profileProperties; + + public ReadConfigPropertiesApplication(ProfileProperties profileProperties) { + this.profileProperties = profileProperties; + } + + public static void main(String[] args) { + SpringApplication.run(ReadConfigPropertiesApplication.class, args); + } + + @Override + public void afterPropertiesSet() { + System.out.println(profileProperties.toString()); + } +} +``` + +邮箱格式不正确,所以程序运行的时候就报错,也就保证了数据类型的安全性。 + +### @PropertySource 方式 + +```java +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component +// @PropertySource 注解方式读取指定的 .properties 文件 +@PropertySource("classpath:website.properties") +@Getter +@Setter +class WebSite { + @Value("${url}") + private String url; +} +``` + +使用: + +```java +@Autowired +private WebSite webSite; + +System.out.println(webSite.getUrl()); +``` + +## Spring Boot 加载配置文件的优先级 + +Spring 读取配置文件也是有优先级的,其中: + +- 项目目录下的 config 目录下的 applicaiton.yml 的优先级最高; +- resources 目录下的 config 目录下的 application.yml 的优先级次之; +- resources 目录下的 application.yml 优先级最低。 + +
\ No newline at end of file diff --git "a/docs/SpringBoot/3_\345\270\270\347\224\250\346\263\250\350\247\243.md" "b/docs/SpringBoot/3_\345\270\270\347\224\250\346\263\250\350\247\243.md" new file mode 100644 index 00000000..aa907675 --- /dev/null +++ "b/docs/SpringBoot/3_\345\270\270\347\224\250\346\263\250\350\247\243.md" @@ -0,0 +1,102 @@ +# 常用注解 + +## @SpringBootApplication + +Spring Boot 项目的基石,创建 Spring Boot 项目之后会默认在主类加上。 + +@SpringBootApplication 可以认为是 **@Configuration** 、**@EnableAutoConfiguration** 和 **@ComponentScan** 注解的集合。这三个注解的具体作用如下: + +- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制 +- @ComponentScan: 扫描被 @Component / @Service / @Controller 注解的 Bean,注解默认会扫描该类所在的包下所有的类。 +- @Configuration:允许在 Spring 上下文中注册额外的 Bean 或导入其他配置类 + +@EnableAutoConfiguration 注解是启动自动配置的关键,其源码如下: + +```java +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.context.annotation.Import; + +@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 {}; +} +``` + +@EnableAutoConfiguration 注解通过 Spring 提供的 @Import 注解导入 AutoConfigurationImportSelector 类。AutoConfigurationImportSelector 类中 getCandidateConfigurations 方法会将所有自动配置类的信息以 List 的形式返回,这些配置信息会被 Spring 容器当作 Bean 来进行管理。 + +```java + protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { + List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), + 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; + } +``` + +补充:[SpringBoot 自动装配原理](https://www.cnblogs.com/javaguide/p/springboot-auto-config.html) + + + +## Spring Bean 相关注解 + +- Autowired + + 自动导入对象到类中,被注入进的类同样要被 Spring 容器管理。 + +- @RestController + + @RestController 注解是 @Controller和 @ResponseBody 的合集,表示这是个控制器 Bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。 + +- @Component + + 可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用 @Component 注解标注。 + +- @Repository + + 对应持久层即 Dao 层,主要用于数据库相关操作。 + +- @Service + + 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。 + +- @Controller + + 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。 + + + +## 处理常见的 HTTP 请求类型 + +- @GetMapping:GET 请求 +- @PostMapping:POST 请求 +- @PutMapping:PUT 请求 +- @DeleteMapping:DELETE 请求 + + + +## 前后端传值 + +- @RequestParam & @Pathvairable + + @PathVariable用于获取路径参数; + + @RequestParam用于获取查询参数。 + +- @RequestBody + + 用于读取 request 请求(可能是 POST、PUT、DELETE、GET 请求)的 Body 部分并且 Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用HttpMessageConverter 或者自定义的 HttpMessageConverter 将请求的 Body 中的 json 字符串转换为 java 对象。 \ No newline at end of file diff --git "a/docs/SpringBoot/4_\350\257\267\346\261\202\345\217\202\346\225\260\346\240\241\351\252\214.md" "b/docs/SpringBoot/4_\350\257\267\346\261\202\345\217\202\346\225\260\346\240\241\351\252\214.md" new file mode 100644 index 00000000..10867edb --- /dev/null +++ "b/docs/SpringBoot/4_\350\257\267\346\261\202\345\217\202\346\225\260\346\240\241\351\252\214.md" @@ -0,0 +1,121 @@ +# 请求参数校验 + +我们需要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。Spring Boot 程序做请求参数校验,需要引入 **spring-boot-starter-web** 依赖。 + +## 常用校验注解 + +### JSR 校验注解 + +- @Null + + 被注释的元素必须为 null + +- @NotNull + + 被注释的元素必须不为 null + +- @AssertTrue + + 被注释的元素必须为 true + +- @AssertFalse + + 被注释的元素必须为 false + +- @Min(value) + + 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 + +- @Max(value) + + 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 + +- @DecimalMin(value) + + 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 + +- @DecimalMax(value) + + 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 + +- @Size(max=, min=) + + 被注释的元素的大小必须在指定的范围内 + +- @Digits (integer, fraction) + + 被注释的元素必须是一个数字,其值必须在可接受的范围内 + +- @Past + + 被注释的元素必须是一个过去的日期 + +- @Future + + 被注释的元素必须是一个将来的日期 + +- @Pattern(regex=,flag=) + + 被注释的元素必须符合指定的正则表达式 + +### Hibernate Validator 校验注解 + +- @NotBlank(message =) + + 验证字符串非 null,且长度必须大于 0 + +- @Email + + 被注释的元素必须是电子邮箱地址 + +- @Length(min=,max=) + + 被注释的字符串的大小必须在指定的范围内 + +- @NotEmpty + + 被注释的字符串的必须非空 + +- @Range(min=,max=,message=) + + 被注释的元素必须在合适的范围内 + +## 验证请求参数 Path Variables 和 Request Parameters + +```java +@RestController +@RequestMapping("/api") +// 使用 @Validated 注解,告诉 Spring 去校验方法参数。 +@Validated +public class PersonController { + + @GetMapping("/person/{id}") + // 校验请求参数 Path Variables + public ResponseEntity getPersonByID(@Valid @PathVariable("id") @Max(value = 5,message = "超过 id 的范围了") Integer id) { + return ResponseEntity.ok().body(id); + } + + @PutMapping("/person") + // 校验请求参数 Request Parameters + public ResponseEntity getPersonByName(@Valid @RequestParam("name") @Size(max = 6,message = "超过 name 的范围了") String name) { + return ResponseEntity.ok().body(name); + } +} +``` + +## 验证请求体 + +在需要验证的参数上加上了@Valid 注解,如果验证失败,它将抛出 MethodArgumentNotValidException。默认情况下,Spring 会将此异常转换为 HTTP Status 400(错误请求)。 + +```java +@RestController +@RequestMapping("/api") +public class PersonController { + + @PostMapping("/person") + public ResponseEntity getPerson(@RequestBody @Valid Person person) { + return ResponseEntity.ok().body(person); + } +} +``` + diff --git "a/docs/SpringBoot/5_\345\205\250\345\261\200\345\274\202\345\270\270\345\244\204\347\220\206.md" "b/docs/SpringBoot/5_\345\205\250\345\261\200\345\274\202\345\270\270\345\244\204\347\220\206.md" new file mode 100644 index 00000000..2fba31ac --- /dev/null +++ "b/docs/SpringBoot/5_\345\205\250\345\261\200\345\274\202\345\270\270\345\244\204\347\220\206.md" @@ -0,0 +1,3 @@ +# 全局异常处理 + +待补充。 \ No newline at end of file diff --git "a/docs/SpringBoot/6_\345\256\236\347\216\260\345\256\232\346\227\266\344\273\273\345\212\241.md" "b/docs/SpringBoot/6_\345\256\236\347\216\260\345\256\232\346\227\266\344\273\273\345\212\241.md" new file mode 100644 index 00000000..0d093d60 --- /dev/null +++ "b/docs/SpringBoot/6_\345\256\236\347\216\260\345\256\232\346\227\266\344\273\273\345\212\241.md" @@ -0,0 +1,22 @@ +# 实现定时任务 + +基于 SpringBoot 的 @Scheduled 注解就能很方便地创建一个定时任务。 + +```java +@Component +public class ScheduledTasks { + private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class); + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + /** + * fixedRate:即固定速率执行,单位是毫秒,这里 5000 表示每 5 秒执行一次。 + */ + @Scheduled(fixedRate = 5000) + public void reportCurrentTimeWithFixedRate() { + log.info("Current Thread : {}", Thread.currentThread().getName()); + log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date())); + } +} +``` + +然后需要在启动类中加上 @EnableScheduling 注解,这样才可以启动定时任务。@EnableScheduling 注解的作用是发现注解 @Scheduled 的任务并在后台执行该任务。 \ No newline at end of file diff --git a/docs/SpringBoot/8_SpringBoot.md b/docs/SpringBoot/8_SpringBoot.md new file mode 100644 index 00000000..8ccf0907 --- /dev/null +++ b/docs/SpringBoot/8_SpringBoot.md @@ -0,0 +1,51 @@ +# SpringBoot + +## 简介 + +SpringBoot 是由 pivotal 团队开发的全新的Spring 框架,其设计初衷是简化 Spring 应用复杂的搭建和开发过程。该框架提供了一套简单的 Spring 模块依赖和管理工具,从而避免了开发人员处理复杂的模块依赖和版本冲突问题,同事提供打包即可用 Web 服务。 + +SpringBoot 特点如下: + +- 快速创建独立的 Spring 应用程序 +- 嵌入 Tomcat Web 容器,可快速部署。 +- 自动配置 JAR 包依赖和版本控制,简化 Maven 配置 +- 自动装配 Spring 实例,不需要 XML 配置 +- 提供诸如性能指标、健康检查、外部配置等线上监控和配置功能。 + +## 常用注解 + +### @SpringBootApplication + +Spring Boot 项目的基石,创建 SpringBoot 项目之后会默认在主类加上。 + +@SpringBootApplication 可以认为是 @Configuration 、@EnableAutoConfiguration 和 @ComponentScan 注解的集合。其中 + +- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制 +- @ComponentScan: 扫描被 @Component / @Service / @Controller 注解的 Bean,注解默认会扫描该类所在的包下所有的类。 +- @Configuration:允许在 Spring 上下文中注册额外的 Bean 或导入其他配置类 + +### @Value & @ ConfigurationProperties & @PropertySource + +通过 @Value("${property}") 读取比较简单的配置信息; + +通过 @ConfigurationProperties 读取配置信息并与 bean 绑定; + +通过 @PropertySource 读取指定 properties 文件。 + +### @ControllerAdvice & @ExceptionHandler + +@ControllerAdvice:注解定义全局异常处理类 + +@ExceptionHandler:注解声明异常处理方法 + +## 实战 + +- [SpringBoot 官网](https://spring.io/projects/spring-boot/) + +- [SpringBoot 实战](https://snailclimb.gitee.io/springboot-guide/#/) + +# SpringBoot 面试题 + +- [SpringBoot 自动装配原理](https://www.cnblogs.com/javaguide/p/springboot-auto-config.html) + +- [Spring Boot面试题(2020最新版)](https://thinkwon.blog.csdn.net/article/details/104397299?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link) diff --git "a/docs/Zookeeper/1_\346\246\202\350\277\260.md" "b/docs/Zookeeper/1_\346\246\202\350\277\260.md" new file mode 100644 index 00000000..ced63e54 --- /dev/null +++ "b/docs/Zookeeper/1_\346\246\202\350\277\260.md" @@ -0,0 +1,51 @@ +# Zookeeper 概述 + +ZooKeeper 是一个开源的**分布式协调服务**,它的设计目标为分布式软件提供一致性服务。 + +ZooKeeper 提供了一个类似 Linux 文件系统的树形结构,Zookeeper 的每个节点既可以是目录也可以是数据,同时 Zookeeper 提供了对每个节点的监控与通知机制。基于 Zookeeper 的一致性服务,可以方便地实现分布式锁、分布式选举、数据发布订阅、配置中心等功能。 + +## 特点 + +- 原子性 + + 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。 + +- 顺序一致性 + + 从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。 + +- 可靠性 + + 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。 + +- 单一系统映像 + + 无论客户端连到哪一个 ZooKeeper 服务器,其看到的服务端数据模型都是一致的。 + +## 典型应用场景 + +- 统一命名服务 + + 可以通过 ZooKeeper 的顺序节点生成全局唯一 ID。 + +- 分布式锁 + + 通过创建唯一节点获得分布式锁,当获得锁的一方执行完相关代码或者是挂掉之后就释放锁。 + +- 数据发布 / 订阅 + + 通过 **Watcher 机制**可以很方便地实现数据发布 / 订阅。将数据发布到 ZooKeeper 被监听的节点上,其他机器可通过监听 ZooKeeper 上节点的变化来实现配置的动态更新。 + +## 支持的框架 + +- Kafka + + ZooKeeper 主要为 Kafka 提供 Broker 和 Topic 的注册以及多个 Partition 的负载均衡等功能。 + +- HBase + + ZooKeeper 确保 Hbase 整个集群只有一个 Master 以及保存和提供 regionserver 状态信息(是否在线)等功能。 + +- Hadoop + + ZooKeeper 为 NameNode 提供高可用支持。 \ No newline at end of file diff --git "a/docs/Zookeeper/2_\346\225\260\346\215\256\346\250\241\345\236\213.md" "b/docs/Zookeeper/2_\346\225\260\346\215\256\346\250\241\345\236\213.md" new file mode 100644 index 00000000..045b82f4 --- /dev/null +++ "b/docs/Zookeeper/2_\346\225\260\346\215\256\346\250\241\345\236\213.md" @@ -0,0 +1,80 @@ +# Zookeeper 的数据模型 + +ZooKeeper 使用一个树形结构的命令空间表示其数据结构。ZooKeeper 树中的每个节点称为一个 Znode,Znode是 ZooKeeper 中数据的最小单元并且每个 Znode 都有一个唯一的路径标识。**ZooKeeper 主要是用来协调服务的,而不是用来存储业务数据的,一般不要放比较大的数据在 Znode 上,所以 ZooKeeper 给出的上限是每个结点的数据大小最大是 1M。** + +ZooKeeper 的每个节点不经存储了数据信息,同时提供对节点信息监控 (Watch) 等操作。 + +每个节点还可以拥有 N 个子节点,最上层是根节点以“/”来代表,Zookeeper 的数据模型如下图: + +
+ +## Znode 数据模型 + +Znode 兼具文件和目录两种特点:既可以像文件一样保存和维护数据,又可以像目录一样作为路径标识的一部分。每个 Znode 有 3 部分组成: + +- Stat + + 状态信息,用于存储 Znode 的版本、权限和时间戳等信息。 + +- Data + + Znode 中具体存储的数据。 + +- Children + + Znode 子节点的信息描述。 + +Znode 节点虽然可以存储数据,但并不能存储大量数据,主要是用来存储分布式应用中的配置文件、集群状态等元数据信息。 + +## Znode 节点类型 + +Zookeeper 中节点有 3 种:永久节点、临时节点、有序节点。节点的类型在创建时被确定并且不能改变。 + +- 永久节点 + + 一旦创建就一直存在即使 ZooKeeper 集群宕机,直到将其删除。该类节点一般用于存储一些永久性的配置信息。 + +- 临时节点 + + 如果会话结束或者超时临时节点就会消失。此外,**临时节点只能做叶子节点** ,不能创建子节点。 + +- 有序节点 + + 在节点名的后面加一个数字后缀,并且是有序的,例如生成的有序节点为 /lock/node-0000000000,它的下一个有序节点则为 /lock/node-0000000001,以此类推。显然有序节点包括永久有序结点和临时有序节点。 + +## Znode 访问控制 + +### ACL + +每个 Znode 节点都有一个访问控制列表(Access Control List,ACL),该列表规定了用户对节点的访问权限,应用程序可以根据需求将用户分为只读、只写和读写用户。对于 Znode 操作的权限,ZooKeeper 提供了以下 5 种: + +- READ:获取节点数据和列出其子节点 +- WRITE:设置 / 更新节点数据 +- ADMIN: 设置节点 ACL 权限 +- DELETE:删除子节点 +- CREATE:创建子节点 + +对于身份认证,提供了以下几种方式: + +- world: 默认方式,所有用户都可无条件访问。 +- auth:不使用任何 id,代表任何已认证的用户。 +- digest:用户名+密码认证方式。 +- ip:对指定 IP 进行限制。 + +### 原子操作 + +每个 Znode 节点上的数据都具有原子操作的特性,读操作将获取与节点相关的数据,写操作将替换节点上的数据。 + +## Watcher + +Watcher 即事件监听器,是 ZooKeeper 中的一个很重要的特性。 + +ZooKeeper 允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。 + +## Session + +Session 即会话,可以看作是 ZooKeeper 服务器与客户端的之间的一个 TCP 长连接,通过这个连接,客户端能够通过心跳检测与服务器是否保持有效的会话,也能够向 ZooKeeper 服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的 Watcher 事件通知。 + +Session 有一个属性叫做:sessionTimeout ,即会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在 sessionTimeout 规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。 + +另外,在为客户端创建会话之前,服务端首先会为每个客户端都分配一个 sessionID。由于 sessionID是 ZooKeeper 会话的一个重要标识,许多与会话相关的运行机制都是基于这个 sessionID 的,因此无论是哪台服务器为客户端分配的 sessionID,都必须是全局唯一的。 \ No newline at end of file diff --git "a/docs/Zookeeper/3_\345\216\237\347\220\206.md" "b/docs/Zookeeper/3_\345\216\237\347\220\206.md" new file mode 100644 index 00000000..1c7db949 --- /dev/null +++ "b/docs/Zookeeper/3_\345\216\237\347\220\206.md" @@ -0,0 +1,152 @@ +# Zookeeper 原理 + +## ZooKeeper 集群的角色 + +Zookeeper 是一个基于主从复制的高可用集群。通常 3 台服务器就可构成一个 ZooKeeper 集群。ZooKeeper 官方提供的架构图就是一个 ZooKeeper 集群整体对外提供服务。 + +
+ +每一个 Server 代表一个安装 ZooKeeper 服务的服务器,组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。 + +Zookeeper 的角色包括 Leader、Follower 和 Observer。 + +### Leader + +一个运行中的 Zookeeper 集群只有一个 Leader 服务,Leader 服务主要有 2 个职责: + +- 负责集群数据的写操作 +- 发起并维护各个 Follower 及 Observer 之间的心跳以监听集群的运行状态。 + +Zookeeper 集群中所有写操作都必须经过 Leader,只有 Leader 写操作完成后,才将写操作广播到其他 Follower。只有超过半数节点(不包括 Observer 节点)写入成功时,该写请求才算写成功。 + +### Follower + +一个运行中的 Zookeeper 集群只有一个 Follower,Follower 通过心跳和 Leader 保持连接。Follower 服务主要有 2 个职责: + +- 负责集群数据的读操作 +- 参与集群的 Leader 选举 + +Follower 在接收到一个客户端请求后会先判断该请求是读请求还是写请求,如果是读请求,那么 Follower 从本地节点上读取数据并返回给客户端;如果是写请求,那么 Follower 会将写请求转发给 Leader 来处理;此外,如果 Leader 失效, Follower 需要在集群选举时进行投票。 + +### Observer + +一个运行中的 Zookeeper 集群只有一个 Observer,Observer 的主要职责是负责集群数据的读操作。Observer 与 Follower 的功能类似,但是 Observer 无投票权。 + +Zookeeper 集群在运行过程中需要支持更多的客户端并发操作,就需要更多的服务实例,而更多的服务实例会使集群投票阶段变得复杂,集群选主时间过程,不利于集群故障快速恢复。因此,Zookeeper 中引入 Observer,Observer 不参与投票,但是接收来自客户端的连接并响应客户端的读请求,将写请求转发给 Leader。加入更多的 Observer节点,不仅提高了 Zookeeper 集群的吞吐量,也保障了系统的稳定性。 + +
+ +## ZAB 协议 + +ZAB(ZooKeeper Atomic Broadcast) 协议即 Zookeeper 原子广播协议。 + +在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。 + +### Epoch & Zxid + +Epoch 即**当前集群的周期号(年代号)**,集群的每次 Leader 变更都会产生一个新的周期号,周期号的产生规则是在上一周期号的基础上加 1,当之前的 Leader 崩溃恢复后会发现自己的周期号比当前的周期号小,说明此时集群已经产生了新的 Leader,旧的 Leader 会再次以 Follower 的角色进入集群。 + +Zxid 即 ZAB 协议的事务编号,是一个 64 bit 的数据,其中低 32 bit 是一个单调递增的计数器,对于客户端的每一个事务请求,计数器都加 1,高 32 bit 存储 Epoch。每次选举产生一个新的 Leader 时,该 Leader 都会从当前服务器日志中取出最大的 Zxid,获取其中搞 32 bit 的 Epoch 值并加 1,作为新的 Epoch,并将低 32 bit 从 0 开始计数。Zxid 用于标识一次提议的 id,为了保证顺序性,Zxid 必须单调递增。 + +### ZAB 协议的 2 种模式 + +ZAB 协议有 2 种模式:恢复模式和广播模式。 + +- 恢复模式(集群选主) + + 在集群启动、集群重启或者 Leader 奔溃后,集群将开始选主,该过程即为恢复模式。 + +- 广播模式(数据同步) + + 当 Leader 被选举出来后,Leader 将最新的集群状态广播给其他 Follower,该过程即为广播模式。在半数以上是我 Follower 完成与 Leader 状态同步后,广播模式结束。这里的**状态同步是指数据同步**,用来保证集群中存在过半的机器能够和 Leader 的数据状态保持一致。 + +### ZAB 协议的 4 个阶段 + +#### 1. 选举阶段 (Leader Election) + +在集群选举开始时,所有节点都处于选举阶段。当某一个节点的票数查过半数节点后,该节点将被当选为**准 Leader** 。 + +只有到达广播阶段后,准 Leader 才会成为真正的 Leader。 + +选举阶段的目的是产生一个准 Leader。 + +#### 2. 发现阶段 (Discovery) + +在发现阶段,Followers 开始和准 Leader 进行通信,同步 Followers 最近接收的事务提议。此时,准 Leader 会产生一个新的 Epoch,并尝试让 Followers 接收该 Epoch 后再更新到本地。 + +发现阶段的一个 Follower 只会连接一个 Leader,如果节点 1 认为节点 2 是 Leader,那么节点 1 就是就会尝试连接节点 2,若连接被拒绝,则集群会重新进入选举阶段。 + +发现阶段的主要目的是发现大多数节点接收的最新提议。 + +#### 3. 同步阶段 (Synchronization) + +同步阶段主要是利用 Leader 前一阶段获得的最新提议信息同步到集群中所有副本,只有当半数以上的节点都同步完成后,准 Leader 才会成为真正的 Leader。 + +同步阶段完成后集群选主操作才完成,新的 Leader 将产生。 + +#### 4. 广播阶段 (Broadcast) + +到了广播阶段,ZooKeeper 集群才能正式对外提供事务服务,并且 Leader 进行消息广播,将其上的状态通知到其他 Follower。如果有新的节点加入,那么 Leader 需要对新节点进行状态同步。 + +ZAB 协议的 Java + +## Zookeeper 选举机制和流程 + +### Zookeeper 选举机制 + +每个 Server 都可提议自己是 Leader,并为自己投票,然后将投票结果与其他 Server 的选票进行对比,权重大的胜出。具体选举过程如下: + +- 每个 Server 启动后都询问其他 Server 给谁投票,其他 Server 根据自己的状态回复自己推荐的 Leader 返回对应的 Leader id 和 Zxid。在集群初次启动时,每个 Server 都会推荐自己为 Leader。 +- 当 Server 收到所有其他 Server 回复后,计算出 Zxid 最大的 Server,并将该 Server 设置成下一次要投票的 Server。 +- 计算过程中票数最多的 Server 将成为获胜者,如果获胜者的票数超过集群个数的一半,则该 Server 就被推选为 Leader。否则继续投票,直到 Leader 被选举出来。 +- Leader 等待其他 Server 连接。 +- Follower 连接 Leader,将最大的 Zxid 发送给 Leader。 +- Leader 根据 Follower 的 Zxid 确定同步点,至此,选举阶段完成。 + +在选举阶段完成后,Leader 通知其他 Follower,集群已成为 Uptodate 状态,Follower 收到 Uptodate 消息后,接收客户端请求开始对外提供服务。 + +### ZAB 协议的 Java 实现 + +ZAB 协议的 Java 实现与其定义略有不同,在实际实现时,选举阶段采用 Fast Leader Election 模式。在该模式下,节点首先向所有 Server 提议自己要成为 Leader,当其它 Server 收到提议后,判断 Epoch 信息并接受对方的提议,然后向对方发送接收提议完成的消息;同时,在 Java 的实现过程中将发现阶段和同步阶段合并为恢复阶段(Recovery)。因此,ZAB 协议的 Java 实现只有 3 个阶段:Fast Leader Election、Recovery 和 Broadcast。 + +### 具体选举过程 + +以 5 台 Server 选主为例: + +- S1 启动 + + S1 提议自己为 Leader 并为自己投票,然后将投票结果发送给其他 Server,此时其他 Server 还未启动,因此收不到任何反馈信息。S1 就处于 Looking 状态。 + +- S2 启动 + + S2 提议自己为 Leader 并为自己投票,然后与 S1 交换投票结果,由于 S2 的 Zxid 大于 S1 的 Zxid,S2 胜出,但是投票未过半,S1 和 S2 均处于 Looking 状态。 + +- S3 启动 + + S3 提议自己为 Leader 并为自己投票,然后与 S1、S2 交换投票结果,由于 S3 的 Zxid 值最大,所以 S3 胜出。此时 S3 的票数过半,S3 就是 Leader,S1 和 S2 成为 Follower。 + +- S4 启动 + + S4 提议自己为 Leader 并为自己投票,然后与 S1、S2、S3 交换投票结果,发现 S3 已经成为 Leader,S4 就成为 Follower。 + +- S5 启动 + + S5 提议自己为 Leader 并为自己投票,然后与 S1、S2、S3和 S4 交换投票结果,发现 S3 已经成为 Leader,S5 就成为 Follower。 + +
+ +## 关于 ZooKeeper 集群的几个问题 + +- ZooKeeper 集群中一般部署奇数台 Server,why ? + + 这是因为 ZooKeeper 集群在宕掉几个 Server 后,如果剩下的 Server 数大于宕掉的 Server 数的话整个 ZooKeeper 才依然可用。假如我们的集群中有 n 台 Server ,那么也就是剩下的服务数必须大于 n/2。 + + 假设有 3 台服务器,那么最大允许宕掉 1 台 ZooKeeper 服务器,如果我们有 4 台的的时候也同样只允许宕掉 1 台;假如有 5 台服务器,那么最大允许宕掉 2 台 ZooKeeper 服务器,如果我们有 6 台的的时候也同样只允许宕掉 2 台。可以看出,2n 和 2n-1 的容错度是一样的,所以采用奇数台 Server 就行了。 + +- ZooKeeper 为何采用选举过半机制? + + 采用过半机制是如何防止集群脑裂。 + + 集群脑裂指的是对于一个集群,如果发生网络故障,Server 之间不能正常通信,集群被割裂成几个小集群,此时子集群各自进行选主导致“脑裂”的情况。 + + 假设一个由 6 台服务器所组成的集群,部署在了 2 个机房,每个机房 3 台。正常情况下只有 1 个 Leader,但是当两个机房中间网络断开的时候,每个机房的 3 台服务器都会认为另一个机房的 3 台服务器下线,而选出自己的 Leader 并对外提供服务。若没有过半机制,当网络恢复的时候会发现有 2 个 Leader。这好比原来的 1 个大脑(Leader)分散成了 2 个大脑,这就发生了脑裂现象。脑裂期间 2 个 “大脑” 都可能对外提供了服务,会带来数据一致性等问题。而 ZooKeeper 的过半机制导致不可能产生 2 个 Leader,因为少于等于一半是不可能产生 Leader 的,这就使得不论机房的机器如何分配都不可能发生脑裂。 diff --git "a/docs/Zookeeper/4_\345\272\224\347\224\250.md" "b/docs/Zookeeper/4_\345\272\224\347\224\250.md" new file mode 100644 index 00000000..4a1826b1 --- /dev/null +++ "b/docs/Zookeeper/4_\345\272\224\347\224\250.md" @@ -0,0 +1,33 @@ +# Zookeeper 的应用 + +## Zookeeper 应用场景 + +### 统一命名服务 + +在分布式环境中,应用程序经常需要对服务进行统一命名,以便识别不同的服务和快速获取服务列表,应用程序可以将服务名称和服务地址信息维护在 Zookeeper 上,客户端通过 Zookeeper 获取可用服务列表。 + +### 配置管理 + +在分布式环境下,应用程序可以将配置文件统一在 Zookeeper 上管理。配置信息可以按照系统配置、告警配置、业务开关配置等分类存储在不同的 Znode 上,各个服务在启动的时候从 Zookeeper 上读取配置,同时监听各个节点的 Znode 数据,一旦 Znode 中的配置被修改,Zookeeper 将通知各个服务然后在线更新配置。 + +使用 Zookeeper 做统一配置管理,不但避免了维护散落在各个服务器上的配置文件的复杂性,同时在配置信息变化时能够及时通知各个服务器在线更新配置,而不用重启服务。 + +### 集群管理 + +在分布式环境下,实时管理每个服务的状态是 Zookeeper 使用最广的场景,常见的 Hbase、Kafka 和 HDFS 等集群都依赖 Zookeeper 做统一的状态管理。 + +### 分布式通知协调 + +基于 Znode 的临时结点和 Watch 特性,应用程序可以很容易地实现一个分布式通知协调系统。比如在集群中为每个服务器都创建一个周期为 30 s 的临时节点作为服务状态监控,要求每个服务每 10 s 定时向 Zookeeper 汇报监控状态。当 Zookeeper 连接 30 s 未收到服务的状态反馈时,则可以认为该服务异常,将其从服务列表中移除,同时将该结果通知其他监控该节点状态的服务。 + +### 分布式锁 + +由于 Zookeeper 是强一致性的,多个客户端同时在 Zookeeper 上创建相同的 Znode 时,只有一个能创建。基于该机制,应用程序可以实现锁的独占性,当多个客户端同时在 Zookeeper 上创建相同的 Znode 时,创建成功的那个客户端将得到锁,其他客户端则等待。 + +将锁节点设置为 EPHEMERAL_SEQUENTIAL,则该 Znode 可掌握全局锁的访问时序。 + +## Zookeeper 实战 + +- [Zookeeper 官网](https://zookeeper.apache.org/) +- [Zookeeper 实战](https://snailclimb.gitee.io/javaguide/#/docs/system-design/distributed-system/zookeeper/zookeeper-in-action) + diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 85456c5e..1a7a8681 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -1,4 +1,4 @@ -
+
@@ -19,9 +19,9 @@ 数据库

+ 系统设计 常用框架 - 系统设计 - 工具 + 工具 参考资料

diff --git a/docs/_pics/AimToOffer/0038204c-4b8a-42a5-921d-080f6674f989.png b/docs/_pics/AimToOffer/0038204c-4b8a-42a5-921d-080f6674f989.png deleted file mode 100644 index 31a2d8d2..00000000 Binary files a/docs/_pics/AimToOffer/0038204c-4b8a-42a5-921d-080f6674f989.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/047faac4-a368-4565-8331-2b66253080d3.jpg b/docs/_pics/AimToOffer/047faac4-a368-4565-8331-2b66253080d3.jpg deleted file mode 100644 index f6506214..00000000 Binary files a/docs/_pics/AimToOffer/047faac4-a368-4565-8331-2b66253080d3.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg b/docs/_pics/AimToOffer/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg deleted file mode 100644 index 0e9bbc86..00000000 Binary files a/docs/_pics/AimToOffer/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/0ad9f7ba-f408-4999-a77a-9b73562c9088.gif b/docs/_pics/AimToOffer/0ad9f7ba-f408-4999-a77a-9b73562c9088.gif deleted file mode 100644 index 81ebc9d2..00000000 Binary files a/docs/_pics/AimToOffer/0ad9f7ba-f408-4999-a77a-9b73562c9088.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg b/docs/_pics/AimToOffer/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg deleted file mode 100644 index 068f6dee..00000000 Binary files a/docs/_pics/AimToOffer/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/0dae7e93-cfd1-4bd3-97e8-325b032b716f.gif b/docs/_pics/AimToOffer/0dae7e93-cfd1-4bd3-97e8-325b032b716f.gif deleted file mode 100644 index c8507532..00000000 Binary files a/docs/_pics/AimToOffer/0dae7e93-cfd1-4bd3-97e8-325b032b716f.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/1176f9e1-3442-4808-a47a-76fbaea1b806.png b/docs/_pics/AimToOffer/1176f9e1-3442-4808-a47a-76fbaea1b806.png deleted file mode 100644 index 581673ff..00000000 Binary files a/docs/_pics/AimToOffer/1176f9e1-3442-4808-a47a-76fbaea1b806.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/13454fa1-23a8-4578-9663-2b13a6af564a.jpg b/docs/_pics/AimToOffer/13454fa1-23a8-4578-9663-2b13a6af564a.jpg deleted file mode 100644 index 5284457b..00000000 Binary files a/docs/_pics/AimToOffer/13454fa1-23a8-4578-9663-2b13a6af564a.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/17e301df-52e8-4886-b593-841a16d13e44.png b/docs/_pics/AimToOffer/17e301df-52e8-4886-b593-841a16d13e44.png deleted file mode 100644 index b1ae4d1c..00000000 Binary files a/docs/_pics/AimToOffer/17e301df-52e8-4886-b593-841a16d13e44.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/195f8693-5ec4-4987-8560-f25e365879dd.png b/docs/_pics/AimToOffer/195f8693-5ec4-4987-8560-f25e365879dd.png deleted file mode 100644 index b2ea3f87..00000000 Binary files a/docs/_pics/AimToOffer/195f8693-5ec4-4987-8560-f25e365879dd.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png b/docs/_pics/AimToOffer/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png deleted file mode 100644 index 44b12ccd..00000000 Binary files a/docs/_pics/AimToOffer/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png b/docs/_pics/AimToOffer/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png deleted file mode 100644 index e3082177..00000000 Binary files a/docs/_pics/AimToOffer/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/31d9adce-2af8-4754-8386-0aabb4e500b0.png b/docs/_pics/AimToOffer/31d9adce-2af8-4754-8386-0aabb4e500b0.png deleted file mode 100644 index 1248f60f..00000000 Binary files a/docs/_pics/AimToOffer/31d9adce-2af8-4754-8386-0aabb4e500b0.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/3ea280b5-be7d-471b-ac76-ff020384357c.gif b/docs/_pics/AimToOffer/3ea280b5-be7d-471b-ac76-ff020384357c.gif deleted file mode 100644 index 4c8540a9..00000000 Binary files a/docs/_pics/AimToOffer/3ea280b5-be7d-471b-ac76-ff020384357c.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/4240a69f-4d51-4d16-b797-2dfe110f30bd.png b/docs/_pics/AimToOffer/4240a69f-4d51-4d16-b797-2dfe110f30bd.png deleted file mode 100644 index d889e516..00000000 Binary files a/docs/_pics/AimToOffer/4240a69f-4d51-4d16-b797-2dfe110f30bd.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/424f34ab-a9fd-49a6-9969-d76b42251365.png b/docs/_pics/AimToOffer/424f34ab-a9fd-49a6-9969-d76b42251365.png deleted file mode 100644 index d5c1a58d..00000000 Binary files a/docs/_pics/AimToOffer/424f34ab-a9fd-49a6-9969-d76b42251365.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/42661013-750f-420b-b3c1-437e9a11fb65.png b/docs/_pics/AimToOffer/42661013-750f-420b-b3c1-437e9a11fb65.png deleted file mode 100644 index 964f97f8..00000000 Binary files a/docs/_pics/AimToOffer/42661013-750f-420b-b3c1-437e9a11fb65.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/45be9587-6069-4ab7-b9ac-840db1a53744.jpg b/docs/_pics/AimToOffer/45be9587-6069-4ab7-b9ac-840db1a53744.jpg deleted file mode 100644 index 336ee59b..00000000 Binary files a/docs/_pics/AimToOffer/45be9587-6069-4ab7-b9ac-840db1a53744.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/48517227-324c-4664-bd26-a2d2cffe2bfe.png b/docs/_pics/AimToOffer/48517227-324c-4664-bd26-a2d2cffe2bfe.png deleted file mode 100644 index ca11ce32..00000000 Binary files a/docs/_pics/AimToOffer/48517227-324c-4664-bd26-a2d2cffe2bfe.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/48b1d459-8832-4e92-938a-728aae730739.jpg b/docs/_pics/AimToOffer/48b1d459-8832-4e92-938a-728aae730739.jpg deleted file mode 100644 index 8adfea82..00000000 Binary files a/docs/_pics/AimToOffer/48b1d459-8832-4e92-938a-728aae730739.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/49d2adc1-b28a-44bf-babb-d44993f4a2e3.gif b/docs/_pics/AimToOffer/49d2adc1-b28a-44bf-babb-d44993f4a2e3.gif deleted file mode 100644 index e2af5f10..00000000 Binary files a/docs/_pics/AimToOffer/49d2adc1-b28a-44bf-babb-d44993f4a2e3.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png b/docs/_pics/AimToOffer/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png deleted file mode 100644 index 4b485ecd..00000000 Binary files a/docs/_pics/AimToOffer/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg b/docs/_pics/AimToOffer/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg deleted file mode 100644 index f7f3ca5b..00000000 Binary files a/docs/_pics/AimToOffer/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png b/docs/_pics/AimToOffer/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png deleted file mode 100644 index a3fdc228..00000000 Binary files a/docs/_pics/AimToOffer/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/66a01953-5303-43b1-8646-0c77b825e980.png b/docs/_pics/AimToOffer/66a01953-5303-43b1-8646-0c77b825e980.png deleted file mode 100644 index 48a120be..00000000 Binary files a/docs/_pics/AimToOffer/66a01953-5303-43b1-8646-0c77b825e980.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/6980aef0-debe-4b4b-8da5-8b1befbc1408.gif b/docs/_pics/AimToOffer/6980aef0-debe-4b4b-8da5-8b1befbc1408.gif deleted file mode 100644 index 05704a44..00000000 Binary files a/docs/_pics/AimToOffer/6980aef0-debe-4b4b-8da5-8b1befbc1408.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png b/docs/_pics/AimToOffer/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png deleted file mode 100644 index b613aa38..00000000 Binary files a/docs/_pics/AimToOffer/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png b/docs/_pics/AimToOffer/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png deleted file mode 100644 index 125a804c..00000000 Binary files a/docs/_pics/AimToOffer/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg b/docs/_pics/AimToOffer/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg deleted file mode 100644 index 22bf89a3..00000000 Binary files a/docs/_pics/AimToOffer/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/95080fae-de40-463d-a76e-783a0c677fec.gif b/docs/_pics/AimToOffer/95080fae-de40-463d-a76e-783a0c677fec.gif deleted file mode 100644 index 9de55285..00000000 Binary files a/docs/_pics/AimToOffer/95080fae-de40-463d-a76e-783a0c677fec.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif b/docs/_pics/AimToOffer/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif deleted file mode 100644 index c34f7419..00000000 Binary files a/docs/_pics/AimToOffer/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/9dae7475-934f-42e5-b3b3-12724337170a.png b/docs/_pics/AimToOffer/9dae7475-934f-42e5-b3b3-12724337170a.png deleted file mode 100644 index 7508fa08..00000000 Binary files a/docs/_pics/AimToOffer/9dae7475-934f-42e5-b3b3-12724337170a.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg b/docs/_pics/AimToOffer/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg deleted file mode 100644 index 00ea4f6b..00000000 Binary files a/docs/_pics/AimToOffer/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/b0611f89-1e5f-4494-a795-3544bf65042a.gif b/docs/_pics/AimToOffer/b0611f89-1e5f-4494-a795-3544bf65042a.gif deleted file mode 100644 index 3e1fdb8b..00000000 Binary files a/docs/_pics/AimToOffer/b0611f89-1e5f-4494-a795-3544bf65042a.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/b903fda8-07d0-46a7-91a7-e803892895cf.gif b/docs/_pics/AimToOffer/b903fda8-07d0-46a7-91a7-e803892895cf.gif deleted file mode 100644 index 873aac86..00000000 Binary files a/docs/_pics/AimToOffer/b903fda8-07d0-46a7-91a7-e803892895cf.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/ba355101-4a93-4c71-94fb-1da83639727b.jpg b/docs/_pics/AimToOffer/ba355101-4a93-4c71-94fb-1da83639727b.jpg deleted file mode 100644 index b5625ae0..00000000 Binary files a/docs/_pics/AimToOffer/ba355101-4a93-4c71-94fb-1da83639727b.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png b/docs/_pics/AimToOffer/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png deleted file mode 100644 index 92dfa7f5..00000000 Binary files a/docs/_pics/AimToOffer/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png b/docs/_pics/AimToOffer/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png deleted file mode 100644 index 9e8e93c9..00000000 Binary files a/docs/_pics/AimToOffer/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png b/docs/_pics/AimToOffer/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png deleted file mode 100644 index 69fe1ba2..00000000 Binary files a/docs/_pics/AimToOffer/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/c269e362-1128-4212-9cf3-d4c12b363b2f.gif b/docs/_pics/AimToOffer/c269e362-1128-4212-9cf3-d4c12b363b2f.gif deleted file mode 100644 index e372dea1..00000000 Binary files a/docs/_pics/AimToOffer/c269e362-1128-4212-9cf3-d4c12b363b2f.gif and /dev/null differ diff --git a/docs/_pics/AimToOffer/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png b/docs/_pics/AimToOffer/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png deleted file mode 100644 index 8cd71a87..00000000 Binary files a/docs/_pics/AimToOffer/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/cd411a94-3786-4c94-9e08-f28320e010d5.png b/docs/_pics/AimToOffer/cd411a94-3786-4c94-9e08-f28320e010d5.png deleted file mode 100644 index d941a7cb..00000000 Binary files a/docs/_pics/AimToOffer/cd411a94-3786-4c94-9e08-f28320e010d5.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png b/docs/_pics/AimToOffer/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png deleted file mode 100644 index 5a4fdbcf..00000000 Binary files a/docs/_pics/AimToOffer/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg b/docs/_pics/AimToOffer/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg deleted file mode 100644 index fe765547..00000000 Binary files a/docs/_pics/AimToOffer/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg b/docs/_pics/AimToOffer/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg deleted file mode 100644 index dca06e46..00000000 Binary files a/docs/_pics/AimToOffer/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png b/docs/_pics/AimToOffer/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png deleted file mode 100644 index a08e6be1..00000000 Binary files a/docs/_pics/AimToOffer/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png b/docs/_pics/AimToOffer/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png deleted file mode 100644 index 11aaa325..00000000 Binary files a/docs/_pics/AimToOffer/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/e151b5df-5390-4365-b66e-b130cd253c12.png b/docs/_pics/AimToOffer/e151b5df-5390-4365-b66e-b130cd253c12.png deleted file mode 100644 index d1ea8287..00000000 Binary files a/docs/_pics/AimToOffer/e151b5df-5390-4365-b66e-b130cd253c12.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/eaa506b6-0747-4bee-81f8-3cda795d8154.png b/docs/_pics/AimToOffer/eaa506b6-0747-4bee-81f8-3cda795d8154.png deleted file mode 100644 index 2cf0d857..00000000 Binary files a/docs/_pics/AimToOffer/eaa506b6-0747-4bee-81f8-3cda795d8154.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg b/docs/_pics/AimToOffer/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg deleted file mode 100644 index 9aac1677..00000000 Binary files a/docs/_pics/AimToOffer/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg and /dev/null differ diff --git a/docs/_pics/AimToOffer/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png b/docs/_pics/AimToOffer/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png deleted file mode 100644 index 95a55e94..00000000 Binary files a/docs/_pics/AimToOffer/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/f6e146f1-57ad-411b-beb3-770a142164ef.png b/docs/_pics/AimToOffer/f6e146f1-57ad-411b-beb3-770a142164ef.png deleted file mode 100644 index 8b25cf20..00000000 Binary files a/docs/_pics/AimToOffer/f6e146f1-57ad-411b-beb3-770a142164ef.png and /dev/null differ diff --git a/docs/_pics/AimToOffer/fb3b8f7a-4293-4a38-aae1-62284db979a3.png b/docs/_pics/AimToOffer/fb3b8f7a-4293-4a38-aae1-62284db979a3.png deleted file mode 100644 index 6575dc98..00000000 Binary files a/docs/_pics/AimToOffer/fb3b8f7a-4293-4a38-aae1-62284db979a3.png and /dev/null differ diff --git a/docs/_pics/JVM/005b481b-502b-4e3f-985d-d043c2b330aa.png b/docs/_pics/JVM/005b481b-502b-4e3f-985d-d043c2b330aa.png deleted file mode 100644 index 0f8543c2..00000000 Binary files a/docs/_pics/JVM/005b481b-502b-4e3f-985d-d043c2b330aa.png and /dev/null differ diff --git a/docs/_pics/JVM/08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg b/docs/_pics/JVM/08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg deleted file mode 100644 index c87a6f86..00000000 Binary files a/docs/_pics/JVM/08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg and /dev/null differ diff --git a/docs/_pics/JVM/0dd2d40a-5b2b-4d45-b176-e75a4cd4bdbf.png b/docs/_pics/JVM/0dd2d40a-5b2b-4d45-b176-e75a4cd4bdbf.png deleted file mode 100644 index 1bb834c8..00000000 Binary files a/docs/_pics/JVM/0dd2d40a-5b2b-4d45-b176-e75a4cd4bdbf.png and /dev/null differ diff --git a/docs/_pics/JVM/22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg b/docs/_pics/JVM/22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg deleted file mode 100644 index b45bb546..00000000 Binary files a/docs/_pics/JVM/22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg and /dev/null differ diff --git a/docs/_pics/JVM/278fe431-af88-4a95-a895-9c3b80117de3.jpg b/docs/_pics/JVM/278fe431-af88-4a95-a895-9c3b80117de3.jpg deleted file mode 100644 index c2697572..00000000 Binary files a/docs/_pics/JVM/278fe431-af88-4a95-a895-9c3b80117de3.jpg and /dev/null differ diff --git a/docs/_pics/JVM/335fe19c-4a76-45ab-9320-88c90d6a0d7e.png b/docs/_pics/JVM/335fe19c-4a76-45ab-9320-88c90d6a0d7e.png deleted file mode 100644 index 57fad732..00000000 Binary files a/docs/_pics/JVM/335fe19c-4a76-45ab-9320-88c90d6a0d7e.png and /dev/null differ diff --git a/docs/_pics/JVM/4cf711a8-7ab2-4152-b85c-d5c226733807.png b/docs/_pics/JVM/4cf711a8-7ab2-4152-b85c-d5c226733807.png deleted file mode 100644 index 03d1e447..00000000 Binary files a/docs/_pics/JVM/4cf711a8-7ab2-4152-b85c-d5c226733807.png and /dev/null differ diff --git a/docs/_pics/JVM/5778d113-8e13-4c53-b5bf-801e58080b97.png b/docs/_pics/JVM/5778d113-8e13-4c53-b5bf-801e58080b97.png deleted file mode 100644 index b0f94a99..00000000 Binary files a/docs/_pics/JVM/5778d113-8e13-4c53-b5bf-801e58080b97.png and /dev/null differ diff --git a/docs/_pics/JVM/62e77997-6957-4b68-8d12-bfd609bb2c68.jpg b/docs/_pics/JVM/62e77997-6957-4b68-8d12-bfd609bb2c68.jpg deleted file mode 100644 index 2c6a953e..00000000 Binary files a/docs/_pics/JVM/62e77997-6957-4b68-8d12-bfd609bb2c68.jpg and /dev/null differ diff --git a/docs/_pics/JVM/66a6899d-c6b0-4a47-8569-9d08f0baf86c.png b/docs/_pics/JVM/66a6899d-c6b0-4a47-8569-9d08f0baf86c.png deleted file mode 100644 index a8536c94..00000000 Binary files a/docs/_pics/JVM/66a6899d-c6b0-4a47-8569-9d08f0baf86c.png and /dev/null differ diff --git a/docs/_pics/JVM/81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg b/docs/_pics/JVM/81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg deleted file mode 100644 index ecf6a7d0..00000000 Binary files a/docs/_pics/JVM/81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg and /dev/null differ diff --git a/docs/_pics/JVM/83d909d2-3858-4fe1-8ff4-16471db0b180.png b/docs/_pics/JVM/83d909d2-3858-4fe1-8ff4-16471db0b180.png deleted file mode 100644 index 5904529b..00000000 Binary files a/docs/_pics/JVM/83d909d2-3858-4fe1-8ff4-16471db0b180.png and /dev/null differ diff --git a/docs/_pics/JVM/8442519f-0b4d-48f4-8229-56f984363c69.png b/docs/_pics/JVM/8442519f-0b4d-48f4-8229-56f984363c69.png deleted file mode 100644 index b8290f0b..00000000 Binary files a/docs/_pics/JVM/8442519f-0b4d-48f4-8229-56f984363c69.png and /dev/null differ diff --git a/docs/_pics/JVM/9bbddeeb-e939-41f0-8e8e-2b1a0aa7e0a7.png b/docs/_pics/JVM/9bbddeeb-e939-41f0-8e8e-2b1a0aa7e0a7.png deleted file mode 100644 index 02b1f35a..00000000 Binary files a/docs/_pics/JVM/9bbddeeb-e939-41f0-8e8e-2b1a0aa7e0a7.png and /dev/null differ diff --git a/docs/_pics/JVM/b2b77b9e-958c-4016-8ae5-9c6edd83871e.png b/docs/_pics/JVM/b2b77b9e-958c-4016-8ae5-9c6edd83871e.png deleted file mode 100644 index c376a027..00000000 Binary files a/docs/_pics/JVM/b2b77b9e-958c-4016-8ae5-9c6edd83871e.png and /dev/null differ diff --git a/docs/_pics/JVM/c625baa0-dde6-449e-93df-c3a67f2f430f.jpg b/docs/_pics/JVM/c625baa0-dde6-449e-93df-c3a67f2f430f.jpg deleted file mode 100644 index 4a6d5197..00000000 Binary files a/docs/_pics/JVM/c625baa0-dde6-449e-93df-c3a67f2f430f.jpg and /dev/null differ diff --git a/docs/_pics/JVM/ccd773a5-ad38-4022-895c-7ac318f31437.png b/docs/_pics/JVM/ccd773a5-ad38-4022-895c-7ac318f31437.png deleted file mode 100644 index e4706e59..00000000 Binary files a/docs/_pics/JVM/ccd773a5-ad38-4022-895c-7ac318f31437.png and /dev/null differ diff --git a/docs/_pics/JVM/f99ee771-c56f-47fb-9148-c0036695b5fe.jpg b/docs/_pics/JVM/f99ee771-c56f-47fb-9148-c0036695b5fe.jpg deleted file mode 100644 index 96e22a72..00000000 Binary files a/docs/_pics/JVM/f99ee771-c56f-47fb-9148-c0036695b5fe.jpg and /dev/null differ diff --git a/docs/_pics/JVM/j_1.png b/docs/_pics/JVM/j_1.png deleted file mode 100644 index a0a2f2b1..00000000 Binary files a/docs/_pics/JVM/j_1.png and /dev/null differ diff --git a/docs/_pics/JVM/j_2.png b/docs/_pics/JVM/j_2.png deleted file mode 100644 index a490d7a4..00000000 Binary files a/docs/_pics/JVM/j_2.png and /dev/null differ diff --git a/docs/_pics/JVM/j_3.png b/docs/_pics/JVM/j_3.png deleted file mode 100644 index 7b03cc79..00000000 Binary files a/docs/_pics/JVM/j_3.png and /dev/null differ diff --git a/docs/_pics/JVM/j_4.jpg b/docs/_pics/JVM/j_4.jpg deleted file mode 100644 index f926506d..00000000 Binary files a/docs/_pics/JVM/j_4.jpg and /dev/null differ diff --git a/docs/_pics/JVM/j_5.png b/docs/_pics/JVM/j_5.png deleted file mode 100644 index b08d3f66..00000000 Binary files a/docs/_pics/JVM/j_5.png and /dev/null differ diff --git a/docs/_pics/JVM/j_6.png b/docs/_pics/JVM/j_6.png deleted file mode 100644 index 23d123f0..00000000 Binary files a/docs/_pics/JVM/j_6.png and /dev/null differ diff --git a/docs/_pics/JVM/j_7.png b/docs/_pics/JVM/j_7.png deleted file mode 100644 index 6d883eb0..00000000 Binary files a/docs/_pics/JVM/j_7.png and /dev/null differ diff --git a/docs/_pics/JVM/j_8.jpg b/docs/_pics/JVM/j_8.jpg deleted file mode 100644 index 6320473b..00000000 Binary files a/docs/_pics/JVM/j_8.jpg and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_1.png b/docs/_pics/MessageQueuue/mq_1.png deleted file mode 100644 index 069b7e17..00000000 Binary files a/docs/_pics/MessageQueuue/mq_1.png and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_2.png b/docs/_pics/MessageQueuue/mq_2.png deleted file mode 100644 index b48fb693..00000000 Binary files a/docs/_pics/MessageQueuue/mq_2.png and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_3.png b/docs/_pics/MessageQueuue/mq_3.png deleted file mode 100644 index 656e6501..00000000 Binary files a/docs/_pics/MessageQueuue/mq_3.png and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_4.png b/docs/_pics/MessageQueuue/mq_4.png deleted file mode 100644 index fd93e1ab..00000000 Binary files a/docs/_pics/MessageQueuue/mq_4.png and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_5.png b/docs/_pics/MessageQueuue/mq_5.png deleted file mode 100644 index 875b8ec3..00000000 Binary files a/docs/_pics/MessageQueuue/mq_5.png and /dev/null differ diff --git a/docs/_pics/MessageQueuue/mq_6.png b/docs/_pics/MessageQueuue/mq_6.png deleted file mode 100644 index 25e1d0ab..00000000 Binary files a/docs/_pics/MessageQueuue/mq_6.png and /dev/null differ diff --git a/docs/_pics/baseball/b_1.jpg b/docs/_pics/baseball/b_1.jpg deleted file mode 100644 index db55d014..00000000 Binary files a/docs/_pics/baseball/b_1.jpg and /dev/null differ diff --git a/docs/_pics/baseball/b_2.jpg b/docs/_pics/baseball/b_2.jpg deleted file mode 100644 index ff90fcf6..00000000 Binary files a/docs/_pics/baseball/b_2.jpg and /dev/null differ diff --git a/docs/_pics/draw.io/JVM.drawio b/docs/_pics/draw.io/JVM.drawio deleted file mode 100644 index a397820e..00000000 --- a/docs/_pics/draw.io/JVM.drawio +++ /dev/null @@ -1 +0,0 @@ -5Z1bd5s4EMc/jR67B3EzPPqW5HQ3J93tbvb0KYcaxaZLUIpxk+ynX2EgNhqlZamRkJyX2OL++0ujGY2EkTN/eL7Mo8fNNY1JimwrfkbOAtk2trDF/pUlL1WJ59UF6zyJ650OBR+Tf0lzZF26S2Kybe1YUJoWyWO7cEWzjKyKVlmU5/Spvds9TdtXfYzWBBR8XEUpLP07iYtNXYpt67DhiiTrTX1p1wqrDQ9Rs3O953YTxfTpqMhZImeeU1pUn+jnL+UD2FYafWYQ9/tVRzagDkc9PM9JykBfVF/Zh/ro1lYr4Z81J1lxfFMXbxwQz26+bW9+/W1q39z+9fX29+2Vc/fOqc7yLUp35Pj2tsVLQyunuywm5Uks5MyeNklBPj5Gq3LrE6sfrGxTPJTPhtnH+yRN5zSlOfue0YztNFvnUZywe2yKke3c7//YtvrqJC/I85uPhY8QXRL6QIr8he3SHODXWrw0YlVfnw7KBnXRpqVpXZ/qurR+PbF9LEFN8X8QdY0jancj6gyG1BMg9dOihEOzosXW/7qjzYZ3273lmbIdcPD4fNjIPq3L/+9vr9k2tPRRMEfBBC1dNJuhqducnd1sdYFqd6AjQ1y0xcoJu2b0eb9Dqe0jTbJij8ObIW/BSqJdQav72h8Qpck6Y59Tcl+eqtQtYYZqWhcXtKwNW1Y5kmz9Z/llwSrYSVR22yL7UORQILI9lMaTNzVmT5/11xgtPTTDiFXYZYgCB02DsiS4QGGwL5mUn5cBmuJy00H46qpnIDwWGEyMZUofDia9j0IHBYt9w16gcL4vYfVh3+anFgrOUnGRQZfa1pvaNYDik7IVB1WrnzZNe1m27oP0HgrDM23sjqW6sWMMtE+Yn78t7qwO5LdFTv8hnDsk8JAa4CuGieQC5A9JHJeXEXpfbf/sFB5V0JbBgyq4UkWw9XdSOaRYYNRETP3BmBoQSgU/7ihETAdz/DEMpqCV0AyqyATLbfyicIpjSrJ4Wg60HCgdMaz2JjEYZPkhkqNH9gSP3JTlJI2K5Fv79CIO9RU+lP3vd0yDF/7itU+ypbt8RerjjsdMuFO9qvD2qYooX5MCnGovzeuj/4Ra/rmp5ZxOLdeSrZYojDVJLffHDaKrWi43zIR96WoFhqv12tf8fNty4LCBbLVE4wRGq9W/bQG1pLetxk4Yq5bHI+7ftjy+C5TetmwYlZulFghtTudl2EOqNbUXHz6tLz5d/TH38M3q+st7+t6ApJ3NyyExxSREqn/WzrVGhrRDmDlypB7f0lUj7RALjhypz+ciVCPtELCNHOlEYbpeiLRDVDVypMHYuqcOoc/IkWJrbP2TKBO1LWhO7rSDy7tTEudAidFCdypJaRQLcnwjJ8t7VcrJQq+qIot1I8s7V8rJQucqieJYN6y8g6UcK3SwdLWyvKOlHC10tCpboB1Z3t9SThb6W0lOil2e6UYWuF2q0XYZFx45UzBOL3HqiZhph9HbkTMFeUXlTG3tmYIMhXKm+g9c+3zSWjlT/UeuJwqn8omZ6j90HY6ujxKNCp5qln81lb+c8x2g6eQsJnbjidcS2AmgwKJ86immFYoF1n+MknfsZM5/FSd69XeWecdOPVP9nWXesVPPVH9nmXfs1DPV31nmHTv1TPV3lnnHTj1T6Cxrl4vgO36ZazTEUGEyQruayvf86qHCVISjG1S+61cPFcZ1rm5Q+b5fPVQYS3m6QeU7f+VQm4sdQfV1g8r3/uqhmj5xHCQm+k8cBwuepE8cdzvEFFqrBVIe/ZfQgEUZQy6hEavVIVrRWi2QTOnftib8eLf8tmX6smqgVv+2BdSS37ZMX1YNkmqsbTFvwcKBgy3P9YOgn3SBYI319847tI6mL7gGOYnTLeGVv3DNM91bBGnX/mqFMhdci9UyfcE1yE2dzreX37aaGzBWLZD1Ot2Ca/lqTUy3hMD/4GeW9HY4fCxXKdP9etBn9VUK9FiylTLdpwc5aj6p1zf+sl3JSpnutYPMd/++ird/8vuqwPS+CuTU+7Yr3gLKbleBDZSaAKlGnuLA1tjyxgEch4UzHIx9V23XmcPD4e8yF8Jc/IIFW3Lxw77aOh/8XadXDYcfzq8wuPaDpXXKaz8cAzPY9vdd2TgY/uZnCc7D+AD8gh9lkYsfev4G1/6+SxWGww/deYNtP5hpo9r2h3C2jMHGB+BXbnxg2GVw7e+7pmc4/F3m9ZuLX7nxgVGvwcYHzNtTbnxg1Gtw7e/79o3h8MOwCy7VMAZ/37WHg+HHTSBynn2vcs8TW2cVePV9Uc2A/GHkZTD/vi+1GZA/DL0Mtj+Av3r70+WH18zlr9r7xNZZBV99XwA1IP+zyjkC/urtT5el2ubyV29/YNbRYPvT92VpA/KH8a/B9gfwV25/BL9QbrD9eXMGsDr+MP49I/4Djv+wrzkt35/4uu2SPdTmmsak3OM/7Vldj6M2FP01ltqHqfgyYx4hYbZ9WGmkWanTfakccAgtYArOJumv7zXY4bMhqy2jqtN5GHyv7Wt8zvG1TZC9yc8fKloePvKYZcgy4jOyt8iyTMM04CE9l9aDsXIkVRqrRp3jJf2T6Z7Ke0xjVg8aCs4zkZZDZ8SLgkVi4KNVxU/DZnueDUctacImjpeIZlPvz2ksDq3XMYzO/yNLk4Ma2dYVOdVtlaM+0Jifei47RPam4ly0Jb77Tb6/ZWR0Bxg27dqeGqfaPuBffzrnT59f/U8vu+fANz8+dKHy84ZlAP5Ta0JBhRzU3o52nW3FCrE0qh7pvtBqMl9odmT92dXiorE+HVLBXkoaSfsEekJ2cBC5BMOEIq3LluF9emYwVLBPs2zDM16Br+AF9AqSisYpvLt2I8veN39Qp16AVYKdR+QuTNfsgfyB8ZyJ6gL9VBRLc64kTpR56vRiusp36Gnl6qRKo8k1tNWnUeH7FVjby1hX/FjEEsWtAdAsIP8vAdpZxJm8KczODMxuJiRgvBADvN0/jlxXPNRNlvOhgemU564SSknzDF3kG4gQFGJEXESwLPhb5BE9ALxvO4bqMaYXkBdDDmtR8d/ZiMUZYmmWJgWYETDFwB9IHlNIiL6qyNM4lsPMimYoq7WEgPGSEPCMEKy1dIBX0wFudOD+r4O/ybx4MSPMJd7VhOCumHdlgiURi6IJh1CzI9jBayI9Sr2mdV/uddZC+nGCdPnOtO+OGLGnjDhvqX2yrvZjzEjszGmfWDvbdd/wfDcn/tkDHlkLa2+CdUFzBp7GMIqjDNFuELtK7w3yoqNbGNNqeNJcclDs6vIdbiXjDIfvy3D2WhzrC/CtBcWK2Jd3XIltRus6jYYEsXMqXnvlXySIP2Blbc8K08a4aKOAt3/tG20vC2u769dYlwEzLJ7cp+/hBabFj1XEljdXQauE3YpH5nleOBxqX8UyKtIvwznMkatGeOZpc8TTYrSHMrLHO2A7TdWrf4ceByLDQJY3CtTiMAnUaO067W+QnzmVH1xLyAaRR3kKhdfxzOY4+oQCTxYCH3kOCh+R5yPizCSYG6dZ6OV7MkLoIe8RBc47yz7mOPuY9+3mq11tzennmmdW1byQc+02GnaC/23Fd9+/8x3ENIa30pkDmfmm11Jz5jNQf8W16xQWNZiwiuWi3qDAaApbpPPPTf4qBndYumsaSGxLmY6aeeAA4a1k7ih4e89tv+EpvjK2FzM0Ci75qoG+tEg+SWP74Kz5IWGUZB1y16a/HmUzn5RuU6bSL0GBifw2IYfIC1HooCBEpMm6niXztuyFG34hwQZNiv7P83tl6gbB5j90TQKz+5rfbsPdTyJ2+Bc= \ No newline at end of file diff --git a/docs/_pics/draw.io/kafka.drawio b/docs/_pics/draw.io/kafka.drawio deleted file mode 100644 index 39ee7e7b..00000000 --- a/docs/_pics/draw.io/kafka.drawio +++ /dev/null @@ -1 +0,0 @@ -7Z1dc9o4FIZ/DZft+Jtw2SRN2pl2NrOZ3XYvXayAdw1ijCmwv35tkImt1y6gWBZIm5tgYQv7fSzpnKMje+DezTaPabiYfqURSQaOFW0G7v3AcWzLtvJ/Rcl2X+L7rGCSxhHb6bXgOf6XlEey0lUckWVtx4zSJIsX9cIxnc/JOKuVhWlK1/XdXmhS/9VFOCFQ8DwOEyz9FkfZdF96Y1mv5Z9IPJmyX3Zv2BezsNyXFSynYUTXlSL348C9SynN9p/oj7+L83esJPyRa7jbb39kqdPrUbPNHUlynR/2m/kHdnTtWyvmLzUl86x6Ug8tB4yektVtSj//+fTO/vr8x2f/8WnxjtXyM0xWTJunlEarMUnZBWbbUrSUruYRKSqzB+7tehpn5HkRjotv1/ltkpdNs1nCvp6kYRTnJ3ZHE5rujndfdn/5dy9xkpTlczrPK7hlZ0HSjGxaL8+uSPVI6Ixk6TbfhR3gMSTbEuZ+c13luy+aVtCWR4Xsjpoc6nWqJJiYZwjrgLBvE7RBtF9pHIXL6aHqDtS1g7q8AcobWA36upYsgV28c8M0i7OYzkHp/LqzupzLLKX/EE7QBo3DJJ7M881xrlPeJtzbQsU470k+sC9mcRQVP9PI75Ww1QMTB5l4DUgcWUS8c255q/NbvgNFHauuqH2qpNI09a9eU88T1FRazxFcvaaB6H0qTdPhcU1zW2lRfHxJyOZDYcTlWpB5xD7ej5NwuYzHdWn3lZAIzLmjSlWU8BuUKMtSkoRZ/LNefZM67BeeaDzPKh0GdMGcwEu6SseEHVU1zriKPOdIRVmYTkgGFe1gHS5bnN/oOL8KK3aXXxMovhcKBEHBEMFXJBlU6UIZQ8rlx1ZRUlCRbFLoW+lN6uBgvZUUVCSb1AnOml6keLdXmBRfkWxS6PVpTkrUoABSPRsU9gneoFakINIhPE71TeoEf0grUnZXvR9UJJvUjWmkurIooCLZpEzzpxx79N7vaKTCqiTTctCqQFyXEUNmJ9ppkLNEqSpu7KCp4Bokf8NUSr/yY4zZM0j+honCfuVH88s3R/7DtjL5MXIdGCS/6jlDB03aoUHyKx960U69MUh+1UOvi8H8kUHyqx56XYzQl9MrJujvqh57XQf1tw3SX/Xg65oWo3W6mvWFiiRHKFx0EgxqKKent8hqKLoHXvkkLeGpXO/mSEWSG4qn+6Q7pNP5o25IQUWySek+lQttSjg3jG9TPU8QerqbCUBKdIIQSPU8QeidkC581aQg8VXUoAuO5QPKJqX7pDtPSrj340n13vudkNp81aTAohh2ZVHwFUkmVeqhLSloU6KkoE31TUp3Kx1IiVoUQKpni8LX3UoHi6IrUn0nh/m6W+lASjRGAaR6jlH4plnpEJgT7v16XsLh6277ASnRaBKQ6jma5OseoQVSI+GES2CFVcmmpXt6LESUROMUEFHqOU5R/pw5pETHKiDV81gV6O5TASnxHhBY9d4DBo5htIT9Kogq9exXBegBazz1Lv60jvYb5G0P60BTQeP06NY5Q1XyD3H813hxANz9qjMUhzioa7w0BuRXnZ87xFEah2l95VednT7EoVfjtRmtnogy+TGirPHajNYkEGXyY5hY47UZrRETZfI3pNxa+urPxxeVLw4YYuxd47UxEN5VbnliQF3j3gfkV977oNur8djbmi6hSv6y9ZlhebbO1yqTH91ejYM+ramSyuRHt1fjoE9rXoky+dHt1Tjo05rSrUx+dHs1Dvq05r8pkx/dXo3nW8Sf5C1LfnR7NXa7Wtc9KpMfvV6dow68/sqjDqOGR0Jg9yPz9QBdvyUEJFbdw4waJtSvW2KInSmX+Ly81cZXL5BNnH0v5H/vs62/Kt/cbxiZ3ca21iMcT0rJT2SX/fGLS1CavMKlnLguB0r40b58RS25KzmYcFvZbVHssDz7fF9voX2FnebFjDBAeKl2WtftfXRhg5ZtnZf719je62AGxVUVf83yXW7emcu3BVuw7br8uMlXJP1FHxiFMRWq73QElU8m7B/qeevpdIYKo5Yl/ghpcCP6zue1rfMW9F/l264CnpjT2RqUhqqkE+vASL50YtBxilqy0HGeaMl2R+u8BV5XSQt6xDL09ub+kK9I+quv/rddWjtNUdsFusy+bZczXxRzlU0Q3AfRJgjuQ+9NEDNIvnz8DYBdhofOTvVND40Ec1K1V17WbCwB1WFQ28G4yKdv+gKAzkt9E0A7wCgA6lvA9bzaqOsobevrSdXBuJ4XHXUNw+UcUXuoHAbmmWg9OkMoQH3fhP6EWQTUD88YAtOaAAYwlRPAsJZZBNS3AfSTLzXZufPUoLaH9SuD0fBCJFNgwFO51MO4nlUYnZurlwcDPekvJIxy4Rzrd5Iskni8NATOYYUAgzNCNofYW09w0Mt+oElC1ybi8ayLw4N+t7l4/P5aT76ZUppVJzbyK5x+pREp9vgP \ No newline at end of file diff --git "a/docs/_pics/draw.io/\345\215\241\345\214\205\351\241\271\347\233\256.drawio" "b/docs/_pics/draw.io/\345\215\241\345\214\205\351\241\271\347\233\256.drawio" deleted file mode 100644 index 056336aa..00000000 --- "a/docs/_pics/draw.io/\345\215\241\345\214\205\351\241\271\347\233\256.drawio" +++ /dev/null @@ -1 +0,0 @@ -7Vxbb6s4EP41PBaBwWAegSbnSGdXqrbSnt19qRxwErYEcoD0sr9+bW4B4yQ0DaRtUlVNsc0Q5vs8Mx4PSJq7evmW4PXy99gnoQQU/0XSbiUAVEVV6AdreS1aICwbFkngl4O2DffBf6Q6s2zdBD5JWwOzOA6zYN1u9OIoIl7WasNJEj+3h83jsH3VNV6QTsO9h8Nu68/Az5ZFK7KUbft3EiyW5ZVNrexY4Wps2ZAusR8/N5q0iaS5SRxnxX/x7F/2/YES4hnVYT6uOLPS018Yr21X+WdBNnfJ5s+faPnj8WYravXikpAqf1oc0n9Kka3e/dLqu01IlB26anWlfqLLm3nC4YY07y7NXitd43RdQDgPXgiV5SyzFdOESv9dkyRYkYwk9DiKI3qGg8NgEdFDj35X1u7UKlbogY/TJROSHwSrHGZnHkdZyTEVbNtvg9WC3k4YzOjfVephQj9d7C3Jwx/ED9KHuyT2N14mp08LelZ5JyTJyAvHkgN6UxtofSMxvaHklZ5XSoGaXsgp5wpAJXeet8zTUdG0bJBOL4fhkuuLWjJo0qHE6Q2YaYcxizdZGETEradfR/dMTwGdUL8xXt/FaZAFMYNtFmdZvGoMsEs8s3gtQrdBBgr0ml1/9bJgVkfGz6kmr17TX+GDP3sIojTDkZfjHYShG4dxkn9ZDUxMzUG0nZ7mB1Rw1VcyaihgVb0NrGp0gVUrQzEKsvphZA/i1gCE1zOy0UTZCe06DqIsvyPo0F9FVnUoAbf+lCAV4uY9CMI9XXlP+dnoqcR1e4rjbRvVOXTUfDDkm4smtS2hPZT+lndDkskTKW5K3WGaWoz1gtSLH1I8J7KH13gWhEH2Km/SfPBQNEQVnSpfDAT2ZUwWwsMsrBRXWfAG6cTkOkjb3L862HtcJPEm8hu0nec/lVuwK2/EiNxxTZXnWGYZi0Rspggw9fxIkQMai8yDyCeJ7NErgqmPM0w/WHtKPx/xioQkjm7mCSE3a/pNbvJvQuWCqcoCn+n9Ml7fqADJ62gxmFFqk0Fkk0Ylg9GDDFkSP9ZxGOOA0P0UwxrAKvkP75j2eZhGoIAE05cEa3lF0pRywF1ieu3wRMwTc3ooCgCzzQFRwDGuXzI7JPhO5x45wASwPzyYh/Gzt8RJJrOZOGPyNOd5GWTkns4+NvKZjuu6MR8S5OsiQiEw0wxjSGRQGxlDF8zOUacnEkxPI8zKudJCx/i1iauOmzSfRdQ+Kqq+ftl20v8W+ecEShaUkCFNDAkhyTErufRrFqLLgTwHqMozDvgWTmVQ1wR118qBn3arwPfDXSypjHVhRUYyz/XxAfMMhsK/uv4ABDAlS5dsdCXA/mjNBDI8MwfUwz66rRyR+nasG0poahetDqhbzu8J5pahCBSrDadZUXpkIPPKWqaSY7MWy5VsV5rokjOVbDUfo0r29DoDRct2oPQMj4ajSY8VE4l8myU+mXJDnKaB10aoOIH4nbzncbpq6AIKVFG1JSTEWfDUvqZIP+UV7tiqeguFwU1YxGk4jTeJR8qTmqlJTo6qHRCU4WRBso6gHK36ro8HEIi86BsB7LG8+bQ4qzpo4WMdiTMw9ssZGmaRoyxMarrG0XvMObXQNrPozHhTsz3JjbcrWUX4pEm2wgw8s/SoYcWLq16mFQdcJG2e24pXc37IMGoobfILU0EKURXFpLXhPb02uzmDjJI3qtg/SyriUzWRbmtH9VX6wMOJf5Tui0l8aw0Ig8Y5RGDJiDkBTYGqCU1UxZPnSuaBbrrgAkBRPjYo2nBeaY8PUkrgFbbQZ6M01mnfsuFXB8Xw1lCLNn03BwfzT1oP/3QJq4x6vff26LMtSOMF7Qg/qUbxa2NYuVG6O1pWxNfZgl9IPGlsq4mqAk5jRepUBWRWAqn77AqLf6HkKHnXrWRP8rMUCbmshZoXG17NSy4FwjZJ9G4WkbqnMe1Lt/rg8oIDxAcHZ44NupmlC8DE+NiY9NgSP1GyiGoxef2LWSKZmovy+G96fKPICqhbbl9KY1UcvTaP7hoVelt7dmQEQKPG3EXuW2KcM1LQ9Q5z4HGxAuxykJN0omCBv5A1Rqxwgl1j1Hdbo5sZK5YZxcJDk5x8q5H+tYbc32hWc5wyPBhlXwwKdsLqwqBRYoNqXjUY8wPPH/GFBW3AbK8J6wR2ExjRFuVwwPTY+73U+qxd8384dnDrvrPXbVXbNtfy/v7l/SLURi3v17sr+Y9sa0fxgPz+hnZ+w9ujVv/4VYD0GfN0GrDaIPHK7xt8dwSZnKCB94n1QVd4nxJbCNFpsO0IGhvb7r7k8Lst3UXQNQfKpMC2VReWAOhjGvXdC+NxtuIsiTo6y5Ym+dq5VfF3wTzp2AxRrrwqLRqHKNbVQ3Sctim3tzT04/1/R9TIXgJ28x2nKvzd4yUgK/9tbsSzLpslxqg9oIOd274ZsjfVKe0m4pgVTEZ7jutnXzzD3XUZJ3+0ghp+G5R7rGgqWUa/+sGeHFA/CQd0rjy0NwcGq2KDogTKUBzQ2QR3po2uKwcA1M7Ogd2VFafnQD790W1uEPLGLws0tMyPBrQopTMU0AZz6zbMu1wJ7V8hXAoHPoDBP8GjPF8usG9n46B25J46L8jgURw6qBel9cZI/bhV0Rxd3sO8y2Uh3nVtT3tqOXufp1UVs8vvwVb3UJQjHG2FNcqGis6VH+qGKVB7nZFrPTOiwKH0Lkq/XbbxhYgzvggcXdKEzmx+B82Zff6HLCHkgiHzWKB5QaBf6dqpgDZ2J8/e62eRhCbbdRLzoUqrHvayfSmfJ9cFr6dRq1k3iic1epQnfclnVhD3RDvk05R9J7PJv29E61uJerLp3ON9k18TQ071xrEPHvEYGkY/z/vWWmKkiq8zaDGxsTtr8v6H6h0tz5rkJcXsEaI97yS6YLvf4ZdgI33UcmGjRxblU7yRSLV2VCI1NSvyqNpwL2TcncV4b/G+KB3NdiT1Rte1eP+dFDIsSzYty0KmaQHLQKgbop1ortLD7YvMC3O/fRu8Nvkf7Vnbdps4FP0aHpOFuNjw6AuJ23EnTpiZjPuSJUAGpTKiQvjSr6/ExTZGdTxdcdO1JnkJbIkjae+jLZ1EM0fLzS2DWfKJRohohh5tNHOsGQbQgS5+SWRbIbYOKiBmOKo77QEff0PNlzVa4AjlrY6cUsJx1gZDmqYo5C0MMkbX7W4LStqjZjBGHcAPIemijzjiSb0KS9/jE4TjpBnZqRuWsOlbA3kCI7o+gExPM0eMUl490eBZzt/QCQwEh2W/6suGJ+RfeWS+nM5RiuMh1Of0n/BqH2q5GSEiyL+pXsVDHbLVejrabrUMpfylUZuROqEhvtvMgu3N9N78NH5++MMv3I/1J/oKkgI1q+sRMcgwz2AqCeLbmvTe10KyMlzQlF/lZUoMRAdgZZt9o3iKy9+epQ1HmutoXk9zTG2ga56tOY42rJCB5trywRXdvGZIMfdq1DpGpdBuAgZHG4knfCmVAHKSnNEvaEQJZQJJaYrkBDEhRxAkOE7FaygIRAIfrhDjWOTToG5Y4iiSwwzXCebIz2Aox1yL3SMwRos0QpJGfTctGQBtjrLxBX3AQVbcIrpEnG3Fd3WUJnnrLdmrX9f7/AaGVWHJQW43mQzrLRXvAhuHWVengzo1NpZ/tUCrz+FDMB0S5+E5uH1UpsaRIG1iVNQdaKWQ5VJUgl6bS0PBpaXgElivQKa3vv3X6/sk+zwATupvsw9/FueQidJoIK1RpimBeY7DU7muGaZe/oiWCOZJqQLYcYqijoH+HKMHlNl6l7EGY4hAjlftMVUs1iPMKE75XjCz19LLPZIhpwULUf3NocUdhQH26TgcshjxTpxS0d2azxI5s4r0ceXOWDT5gHoOnU7pQiFykQtdancLWGNsXOiYdmGxQVAX7eSJOLIy+RhCFv23XSdyZuGEKJSJVRn42FUlVuDYln1Jqzv2OsO9dmQum7oN+nbfAUZnv1qK5HuN3aoUEnSExCnm5SXnzZSLbORE1gvKOUZg9nqXdFbH+F2UC2+zSfLFyv4Gj3cT994bBeZfb3Kf2aWFwPplL1M2Dsay+/vVRtq7ccbdRpEmr3G3UaZJd4O/H8f8x3o57s+dx5Z1Os7rncfxOF99fPKyYnqnz2yq338zZ+dcumCeVfXpAm+kZocKZ4hhMQV0arPt6seW8PIFL8satrSXuoAW5rjDx3gZi0URHMil5SEUB8jNCIYJenpAEc6fZoxGRciv81V8yaLj6Kbc7+5My7mMf/t9b7Z1oEuosZiv+HzytX+qHpU8nuXfjsq/fcQPrLiK9VtbscJELuDLR+oDXSH/hXxZKf8ZvrynCbx8h2qx+GPH/pWlad+6tttXKLt7GAJb4e32hUg3/oeku8b1W9Nudmh/LzLURYZ7XGScZVIXO6OsjnDvZf5ZZf4v01G87v+EX90m9/8HMb3v \ No newline at end of file diff --git "a/docs/_pics/draw.io/\346\266\210\346\201\257\351\230\237\345\210\227.drawio" "b/docs/_pics/draw.io/\346\266\210\346\201\257\351\230\237\345\210\227.drawio" deleted file mode 100644 index e5f1acab..00000000 --- "a/docs/_pics/draw.io/\346\266\210\346\201\257\351\230\237\345\210\227.drawio" +++ /dev/null @@ -1 +0,0 @@ -5VjJbtswEP0aHgNoX46Sl/TQogUcIOipoCRaZkuLLkXHdr6+Q4mKtSVODBsI3JOHjzMj8r2hhjKyJ+v9vcCb1TeeEYYsI9sje4osyzRMA34UcqgR1zBrIBc0005HYEGfSROp0S3NSNlxlJwzSTddMOVFQVLZwbAQfNd1W3LWfeoG52QALFLMhugjzeRK7yIwjvgXQvOVfrJl6Ik1bnw1UK5wxnctyJ4heyI4l7XFk99q/ZbBcAIcVn51ZMPTMWq9nxAGPM/rIRg6ujNr0P5WBSlke1HzVwJ+FVn+8PBzYUy8pf/X9mePkX+nV/OE2Za0l1fKQ0MW7HGjTJxKLpAd71ZUksUGpwrcQYEAtpJrtTsTTJ2QCEn2r67UbO36nvA1keIALvuG7zpCV5ejh7ujVA20aqnUqId1ceQvea02qZqXD3Bkn+aIFFmk6hJGKcNlSdMxUkg2KMuTlLQ27Y5susEEYVjSp276MSb0E35wWsgj436Xcb9HZcm3IiU6pl1ivTSm+XYeiUVO5CBPpcrLns8Xyh0KNXNRMEehiWYhggIJwPBQbKMoqKY8FEyqKQtFMzRzUByj2BvIK/i2yEimxTxxAJaUsQln6qxArJ25JMgcwEsp+B/SmgmsxPa8Cx2ZoMu8NzwzpjVSP861Do13phY+CucomlZagGFeVAtighr+mBah59v4Qlo4zifTwh/RYsh8QzhMgTTRHFkeg5XFiQArV5Z2DsPKcFHkKufQRbFRRU2rQwTDCIX2q30kPTAKCr6jlSS11F+TFwCnf/KqAL5vJWQh4zIvg5Sk6ZjMSeA68Mq8iMzm6TY1KvPV+lRw+33KMXoNJjyvUfWPaD/PlRtVePtKWT2G+1X/XqX6ja2f58pKNReaW5aqf2sLz5TKfzvNtZUafsoofox1ORAM3vmyK5EgJX3GSeWg2sNGrbJatxsjdwoI3kpe1h+yKgAzmhdgM7JUqVQjofB9GWlYctXKSuhstMgf1GB651yo7Xhdms2RvjNWLNa12o45/D66SeKd4LMR7/wfxNvWZyN+/EMT7rxwBdb3X2d4fTZf1BlcrG9Kr34fcN+llv1xtWB4/Kut7iPH/yvt2T8=7ZjbctowEIafRpfp+Ix9aXNIO9NOO0kP6aVsC+NGWFQWBfL0Xdky+JRAoW5mkl6h/SWt5P1WrEbIHC+31xyvFh9YTCgytHiLzAkyDF3TNfiRyq5UbE0vhYSnsRp0EG7TB1LNVOo6jUneGCgYoyJdNcWIZRmJREPDnLNNc9ic0eaqK5yQjnAbYdpVv6WxWJSqZXsH/S1Jk4Va2dDUvpe4GquEfIFjtqlJ5hSZY86YKFss/CH3b2gUhxDDYlw5s4oTvnl35d7Ns693D9uV+PIzpjfzq4Or5XZMKAR/VprQUC4bvU97238tJ5k4tmq10mmu1cf8wnRN6l+Xi10VawjRSjZxJBhHZrBZpILcrnAkxQ3kF2gLsZTB0aGpHBIuyLYF68j29VrQrglbEsF3MG9bMSzdqIy1lLmp4VfSokbeVRpWCZfs/Rp1JipYfxA483jgSBb7MtfBiijO8zTqixSJO6l+XpxqkbB7IlFpnFAs0l/NNfvCo1b4xNJMHDCMmhhGrfjmbM0joubUk7HlRtef9iMwT4jo+ClQ7b/5fHpWl97URu4MeTqaegiyxoWGgwIT+W7R5SB3XHQZyJ+iqYWCAAVOhzln6ywmsSJ85KjMU0rHjMpTBXPN2CZubIGeC87uSa3HNULTcQY8XGbrdBnd06UbPUllDXW87DMBjZA3Q/6kAAQN/a8CIjogGvUB8pyRif8lIF17bkJOD6EujwoDdAEwf4YMh8LOgpBDK5EtNdjzioaNfFsO9mwUaMWsSXHewPSRZz5anKIdTYHrCfUpLBPgfbgXcHSfFGnxcS3AC+mHP3cjEkV98EPXtuDfdTj4+vHa18t+sOI3urz4QTz47g4MrTK+S+ONXZmTbb1zslPWRUUTbqlFXTn2x/NcxXVPdtcP8NTqup/4iJ+Bq6v7ctPD+p8eF6eHd3l6XIT5ufC177zemfhGT7sZmF71ETV8Mj7aMu9QhDIomtw4ydMHHBYD5HFdyV0W+7YDZE9AwWvB8vK9QU7ANE0yaFMyl65kbU0jTH0lCyarew7FPs2Sz9KYXFlDVmKndQ3rKcV9GWQMVYl1/RXTMFs0nOeG0fMoADdXuLbCLVZdYa3uDbi4yxfEOnfjl8+w/Wdmn4TQHAxh92Xg9Z4n3TqNxhkHCszDI2tZmg4v1eb0Nw==7Zlbc6s2EIB/jR7d4SYMj2DstDNtTzp2p6dPHQEypsaIghzb+fVdgQjX2qkTmk7Tp0graYX3W2l3FaQvDueHnGS7H1hIE6Qp4RnpHtI0VVEV+CMkl0qCsRREeRzKSY1gHT/TeqWUHuOQFp2JnLGEx1lXGLA0pQHvyEies1N32pYl3V0zEtGBYB2QZCj9JQ75rpKamtLIv6VxtJM7a4ocOJB6rhQUOxKyU0ukL5G+yBnjVYv5v4vv15SE+GDDcl61sraTdynSy1O2US77n1dL59nbPs5mjarDeUETMP6q6kJDquyMXtf28mtzmvJbu9Y7DVTra3PtfnnYzvZ/5Mn+Jx58Z+ZyifJEkiNt/7qCX2pbg4ky0SQBZznS3dMu5nSdkUAIT+BfINvxgzCOCk2pkOacnnuwbny+2jLaA2UHyvMLrDvXDCs10mMN2T01+GvRrkXekjIiHS560au1mUhj/Q3DqbcNR9PQEb4OvSAhRREHY5ai4cDV77NTyxJ4xBK1LKcJ4fFTd88x88gdHlmc8gbDvIth3rNvwY55QOWatjP21KjqdT2c5BHlAz0lqpfffD89bUhviZG1QraKljYCr7GgYSJXR45VDpnIWpRDGnKWaGkg10WuOWCes2Ma0lASvnFUtnGSLFgiThWs1UNMrdAAecFztqetEUvzddOc8HAZVheHNjxdqjbiVMZUx0u/E9Ac2SvkeCUgaKjvCoiqgGg+Bsg25zr5JwGpykcTMkYIDXnUGGAIgDkrpJkJfJnr59CKREtOtu2ygZGDxWQbI1cpV3nleYOug2z9L4NTcEli4PqK+ORXDvC9/yIgwT4q3eLLkYMWOg5/awU0CMbg+xY24HadDr56O/aNsp8s+OG3Bz+wR375Ch2l7vwqOt/guuud24PeRfbeFDQhSy3jyq3I8FHB1VB6UdG+L7oaxnU9E0dX85PmRlrP7P3z91p8mnVdz8T45p8UXz8nte/EN7+uZmJ61oCeMI9yKAYQIUrxLracFvEz8csJ4rLNxEeWn41dhD2QkCNnRfUcIBaQJI5SaCd0K1SJ0BdDle5IMWci+BYQi+M02oiONzOmDJRmL0saiZRjDqRNFShrj2rTgMSHHIRdUr/ISmN8Dji69m+DM1LDQ6IJWSYknTLjNIYJK8aS2CCT/e8z7F9t+FUE9XcguM5+PGyi3x7PfDNLV7tsUzjp2OuVqEGgarCaigPKRdsSZaGoL6AxH3B6S0243W618bIgNH0TT1kT9tMEc3ieJisJR3G8w5vYvWUBPcf8a60D2q1V0GsWic47lRJVOnDbO2+WHPpHJj2DkgPfl/QYuJezTlZyjNp6/EHPXYj3OrgJHK98V7DEfeC69VPS8PlueGN3j3XKxPNA5w6QovqiDsB3ymeI/lV9iMNQbDN6vzQ30JTvCH3WeHhhWBMF4FFo4498/0O7Cs2eDBp0m398VQez+e+hvvwT \ No newline at end of file diff --git a/docs/_pics/hbase/h_1.png b/docs/_pics/hbase/h_1.png deleted file mode 100644 index a3c980dd..00000000 Binary files a/docs/_pics/hbase/h_1.png and /dev/null differ diff --git a/docs/_pics/hbase/h_10.jpg b/docs/_pics/hbase/h_10.jpg deleted file mode 100644 index 8a8808f4..00000000 Binary files a/docs/_pics/hbase/h_10.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_11.jpg b/docs/_pics/hbase/h_11.jpg deleted file mode 100644 index 0d661cbe..00000000 Binary files a/docs/_pics/hbase/h_11.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_12.png b/docs/_pics/hbase/h_12.png deleted file mode 100644 index 106e433d..00000000 Binary files a/docs/_pics/hbase/h_12.png and /dev/null differ diff --git a/docs/_pics/hbase/h_13.png b/docs/_pics/hbase/h_13.png deleted file mode 100644 index 196d2a2a..00000000 Binary files a/docs/_pics/hbase/h_13.png and /dev/null differ diff --git a/docs/_pics/hbase/h_14.png b/docs/_pics/hbase/h_14.png deleted file mode 100644 index 34de5769..00000000 Binary files a/docs/_pics/hbase/h_14.png and /dev/null differ diff --git a/docs/_pics/hbase/h_15.png b/docs/_pics/hbase/h_15.png deleted file mode 100644 index c27ebee1..00000000 Binary files a/docs/_pics/hbase/h_15.png and /dev/null differ diff --git a/docs/_pics/hbase/h_16.png b/docs/_pics/hbase/h_16.png deleted file mode 100644 index 58d687c2..00000000 Binary files a/docs/_pics/hbase/h_16.png and /dev/null differ diff --git a/docs/_pics/hbase/h_17.png b/docs/_pics/hbase/h_17.png deleted file mode 100644 index 7061e461..00000000 Binary files a/docs/_pics/hbase/h_17.png and /dev/null differ diff --git a/docs/_pics/hbase/h_18.png b/docs/_pics/hbase/h_18.png deleted file mode 100644 index 729e2375..00000000 Binary files a/docs/_pics/hbase/h_18.png and /dev/null differ diff --git a/docs/_pics/hbase/h_19.jpg b/docs/_pics/hbase/h_19.jpg deleted file mode 100644 index 81b4ef27..00000000 Binary files a/docs/_pics/hbase/h_19.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_2.jpg b/docs/_pics/hbase/h_2.jpg deleted file mode 100644 index 0592ad2a..00000000 Binary files a/docs/_pics/hbase/h_2.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_20.png b/docs/_pics/hbase/h_20.png deleted file mode 100644 index baa82860..00000000 Binary files a/docs/_pics/hbase/h_20.png and /dev/null differ diff --git a/docs/_pics/hbase/h_21.jpg b/docs/_pics/hbase/h_21.jpg deleted file mode 100644 index 8efad160..00000000 Binary files a/docs/_pics/hbase/h_21.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_22.jpg b/docs/_pics/hbase/h_22.jpg deleted file mode 100644 index 27bbff6b..00000000 Binary files a/docs/_pics/hbase/h_22.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_23.jpg b/docs/_pics/hbase/h_23.jpg deleted file mode 100644 index 7a191277..00000000 Binary files a/docs/_pics/hbase/h_23.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_24.jpg b/docs/_pics/hbase/h_24.jpg deleted file mode 100644 index 1067eeac..00000000 Binary files a/docs/_pics/hbase/h_24.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_25.jpg b/docs/_pics/hbase/h_25.jpg deleted file mode 100644 index 8e0dd086..00000000 Binary files a/docs/_pics/hbase/h_25.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_26.png b/docs/_pics/hbase/h_26.png deleted file mode 100644 index 9b7fa021..00000000 Binary files a/docs/_pics/hbase/h_26.png and /dev/null differ diff --git a/docs/_pics/hbase/h_3.jpg b/docs/_pics/hbase/h_3.jpg deleted file mode 100644 index 27f0cec0..00000000 Binary files a/docs/_pics/hbase/h_3.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_4.jpg b/docs/_pics/hbase/h_4.jpg deleted file mode 100644 index a1b7b87a..00000000 Binary files a/docs/_pics/hbase/h_4.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_5.jpg b/docs/_pics/hbase/h_5.jpg deleted file mode 100644 index e1a1b630..00000000 Binary files a/docs/_pics/hbase/h_5.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_6.jpg b/docs/_pics/hbase/h_6.jpg deleted file mode 100644 index b73f85d4..00000000 Binary files a/docs/_pics/hbase/h_6.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_7.jpg b/docs/_pics/hbase/h_7.jpg deleted file mode 100644 index 70d82114..00000000 Binary files a/docs/_pics/hbase/h_7.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_8.jpg b/docs/_pics/hbase/h_8.jpg deleted file mode 100644 index 60af46e4..00000000 Binary files a/docs/_pics/hbase/h_8.jpg and /dev/null differ diff --git a/docs/_pics/hbase/h_9.jpg b/docs/_pics/hbase/h_9.jpg deleted file mode 100644 index e571c5fd..00000000 Binary files a/docs/_pics/hbase/h_9.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_1.png b/docs/_pics/java-notes/book/book_1.png deleted file mode 100644 index 19d4da8b..00000000 Binary files a/docs/_pics/java-notes/book/book_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_10.jpg b/docs/_pics/java-notes/book/book_10.jpg deleted file mode 100644 index 14bac71c..00000000 Binary files a/docs/_pics/java-notes/book/book_10.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_11.jpg b/docs/_pics/java-notes/book/book_11.jpg deleted file mode 100644 index 0dd78c71..00000000 Binary files a/docs/_pics/java-notes/book/book_11.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_12.jpg b/docs/_pics/java-notes/book/book_12.jpg deleted file mode 100644 index a76d4c70..00000000 Binary files a/docs/_pics/java-notes/book/book_12.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_13.jpg b/docs/_pics/java-notes/book/book_13.jpg deleted file mode 100644 index 2230c4aa..00000000 Binary files a/docs/_pics/java-notes/book/book_13.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_14.jpg b/docs/_pics/java-notes/book/book_14.jpg deleted file mode 100644 index 86686f9a..00000000 Binary files a/docs/_pics/java-notes/book/book_14.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_15.jpg b/docs/_pics/java-notes/book/book_15.jpg deleted file mode 100644 index c01e0ed1..00000000 Binary files a/docs/_pics/java-notes/book/book_15.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_16.jpg b/docs/_pics/java-notes/book/book_16.jpg deleted file mode 100644 index 7454069e..00000000 Binary files a/docs/_pics/java-notes/book/book_16.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_17.jpg b/docs/_pics/java-notes/book/book_17.jpg deleted file mode 100644 index 00769928..00000000 Binary files a/docs/_pics/java-notes/book/book_17.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_18.jpg b/docs/_pics/java-notes/book/book_18.jpg deleted file mode 100644 index 1837ec8c..00000000 Binary files a/docs/_pics/java-notes/book/book_18.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_19.jpg b/docs/_pics/java-notes/book/book_19.jpg deleted file mode 100644 index 8faa080a..00000000 Binary files a/docs/_pics/java-notes/book/book_19.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_2.png b/docs/_pics/java-notes/book/book_2.png deleted file mode 100644 index bf39b5ee..00000000 Binary files a/docs/_pics/java-notes/book/book_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_20.jpg b/docs/_pics/java-notes/book/book_20.jpg deleted file mode 100644 index 3e18c643..00000000 Binary files a/docs/_pics/java-notes/book/book_20.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_21.jpg b/docs/_pics/java-notes/book/book_21.jpg deleted file mode 100644 index b893c5fb..00000000 Binary files a/docs/_pics/java-notes/book/book_21.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_22.jpg b/docs/_pics/java-notes/book/book_22.jpg deleted file mode 100644 index 481b7ffd..00000000 Binary files a/docs/_pics/java-notes/book/book_22.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_23.jpg b/docs/_pics/java-notes/book/book_23.jpg deleted file mode 100644 index 94a4d901..00000000 Binary files a/docs/_pics/java-notes/book/book_23.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_3.png b/docs/_pics/java-notes/book/book_3.png deleted file mode 100644 index b2062a70..00000000 Binary files a/docs/_pics/java-notes/book/book_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_4.jpg b/docs/_pics/java-notes/book/book_4.jpg deleted file mode 100644 index 2a76e311..00000000 Binary files a/docs/_pics/java-notes/book/book_4.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_5.jpg b/docs/_pics/java-notes/book/book_5.jpg deleted file mode 100644 index 9c57f957..00000000 Binary files a/docs/_pics/java-notes/book/book_5.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_6.jpg b/docs/_pics/java-notes/book/book_6.jpg deleted file mode 100644 index 9f380a82..00000000 Binary files a/docs/_pics/java-notes/book/book_6.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_7.jpg b/docs/_pics/java-notes/book/book_7.jpg deleted file mode 100644 index a856d63f..00000000 Binary files a/docs/_pics/java-notes/book/book_7.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_8.jpg b/docs/_pics/java-notes/book/book_8.jpg deleted file mode 100644 index 49d6012a..00000000 Binary files a/docs/_pics/java-notes/book/book_8.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/book/book_9.jpg b/docs/_pics/java-notes/book/book_9.jpg deleted file mode 100644 index 0a27b6b3..00000000 Binary files a/docs/_pics/java-notes/book/book_9.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/1.png b/docs/_pics/java-notes/dataStructure/1.png deleted file mode 100644 index 048a68a4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/2.png b/docs/_pics/java-notes/dataStructure/2.png deleted file mode 100644 index 022ba597..00000000 Binary files a/docs/_pics/java-notes/dataStructure/2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/3.png b/docs/_pics/java-notes/dataStructure/3.png deleted file mode 100644 index 81810b7c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/4.png b/docs/_pics/java-notes/dataStructure/4.png deleted file mode 100644 index 2625c4d8..00000000 Binary files a/docs/_pics/java-notes/dataStructure/4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/array/array_1.png b/docs/_pics/java-notes/dataStructure/array/array_1.png deleted file mode 100644 index 1fdfd6df..00000000 Binary files a/docs/_pics/java-notes/dataStructure/array/array_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/array/array_2.png b/docs/_pics/java-notes/dataStructure/array/array_2.png deleted file mode 100644 index 5550a76e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/array/array_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/array/array_3.png b/docs/_pics/java-notes/dataStructure/array/array_3.png deleted file mode 100644 index 839c48e4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/array/array_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/array/array_4.png b/docs/_pics/java-notes/dataStructure/array/array_4.png deleted file mode 100644 index 818492ea..00000000 Binary files a/docs/_pics/java-notes/dataStructure/array/array_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/array/array_5.png b/docs/_pics/java-notes/dataStructure/array/array_5.png deleted file mode 100644 index 429ca838..00000000 Binary files a/docs/_pics/java-notes/dataStructure/array/array_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_1.png b/docs/_pics/java-notes/dataStructure/avl/avl_1.png deleted file mode 100644 index cb24300b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_10.png b/docs/_pics/java-notes/dataStructure/avl/avl_10.png deleted file mode 100644 index d16d06fd..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_11.png b/docs/_pics/java-notes/dataStructure/avl/avl_11.png deleted file mode 100644 index f075d70b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_12.png b/docs/_pics/java-notes/dataStructure/avl/avl_12.png deleted file mode 100644 index 3888a84e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_13.png b/docs/_pics/java-notes/dataStructure/avl/avl_13.png deleted file mode 100644 index 31fe8bce..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_14.png b/docs/_pics/java-notes/dataStructure/avl/avl_14.png deleted file mode 100644 index ea6332f3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_15.png b/docs/_pics/java-notes/dataStructure/avl/avl_15.png deleted file mode 100644 index 0f02b43b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_2.png b/docs/_pics/java-notes/dataStructure/avl/avl_2.png deleted file mode 100644 index 22f8286a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_3.png b/docs/_pics/java-notes/dataStructure/avl/avl_3.png deleted file mode 100644 index 1d31f6d0..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_4.png b/docs/_pics/java-notes/dataStructure/avl/avl_4.png deleted file mode 100644 index 7827e574..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_5.png b/docs/_pics/java-notes/dataStructure/avl/avl_5.png deleted file mode 100644 index f329dae5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_6.png b/docs/_pics/java-notes/dataStructure/avl/avl_6.png deleted file mode 100644 index f0d72c7f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_7.png b/docs/_pics/java-notes/dataStructure/avl/avl_7.png deleted file mode 100644 index e83e07d7..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_8.png b/docs/_pics/java-notes/dataStructure/avl/avl_8.png deleted file mode 100644 index 3101c610..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/avl/avl_9.png b/docs/_pics/java-notes/dataStructure/avl/avl_9.png deleted file mode 100644 index 23ef04c9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/avl/avl_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_00.png b/docs/_pics/java-notes/dataStructure/bst/bst_00.png deleted file mode 100644 index babc7b96..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_00.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_01.png b/docs/_pics/java-notes/dataStructure/bst/bst_01.png deleted file mode 100644 index 2764e6a5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_01.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_02.png b/docs/_pics/java-notes/dataStructure/bst/bst_02.png deleted file mode 100644 index ccd50d82..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_02.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_03.png b/docs/_pics/java-notes/dataStructure/bst/bst_03.png deleted file mode 100644 index 4b1d56a7..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_03.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_04.png b/docs/_pics/java-notes/dataStructure/bst/bst_04.png deleted file mode 100644 index c19043c2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_04.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_05.png b/docs/_pics/java-notes/dataStructure/bst/bst_05.png deleted file mode 100644 index 05cacf0a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_05.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_06.png b/docs/_pics/java-notes/dataStructure/bst/bst_06.png deleted file mode 100644 index 25dd1819..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_06.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_07.png b/docs/_pics/java-notes/dataStructure/bst/bst_07.png deleted file mode 100644 index 5d0aadc7..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_07.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_08.png b/docs/_pics/java-notes/dataStructure/bst/bst_08.png deleted file mode 100644 index f0ff9ed6..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_08.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_09.png b/docs/_pics/java-notes/dataStructure/bst/bst_09.png deleted file mode 100644 index 3e3596db..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_09.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_10.png b/docs/_pics/java-notes/dataStructure/bst/bst_10.png deleted file mode 100644 index d93b45d9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_11.png b/docs/_pics/java-notes/dataStructure/bst/bst_11.png deleted file mode 100644 index 5739bf60..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_12.png b/docs/_pics/java-notes/dataStructure/bst/bst_12.png deleted file mode 100644 index 84f35f4a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_13.png b/docs/_pics/java-notes/dataStructure/bst/bst_13.png deleted file mode 100644 index 88677f2b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_14.png b/docs/_pics/java-notes/dataStructure/bst/bst_14.png deleted file mode 100644 index 22cd89ad..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_15.png b/docs/_pics/java-notes/dataStructure/bst/bst_15.png deleted file mode 100644 index 8dd45a29..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_16.png b/docs/_pics/java-notes/dataStructure/bst/bst_16.png deleted file mode 100644 index b6b7e060..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_17.png b/docs/_pics/java-notes/dataStructure/bst/bst_17.png deleted file mode 100644 index b7a4fc43..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_18.png b/docs/_pics/java-notes/dataStructure/bst/bst_18.png deleted file mode 100644 index 48b3f41c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_19.png b/docs/_pics/java-notes/dataStructure/bst/bst_19.png deleted file mode 100644 index 689a0d74..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/bst_20.png b/docs/_pics/java-notes/dataStructure/bst/bst_20.png deleted file mode 100644 index e32f8e19..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/bst_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_1.png b/docs/_pics/java-notes/dataStructure/bst/stack_1.png deleted file mode 100644 index 46c36a6e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_2.png b/docs/_pics/java-notes/dataStructure/bst/stack_2.png deleted file mode 100644 index 03c91208..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_3.png b/docs/_pics/java-notes/dataStructure/bst/stack_3.png deleted file mode 100644 index 8bd22f76..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_4.png b/docs/_pics/java-notes/dataStructure/bst/stack_4.png deleted file mode 100644 index 5bf4fdbb..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_5.png b/docs/_pics/java-notes/dataStructure/bst/stack_5.png deleted file mode 100644 index 04e4cfcd..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_6.png b/docs/_pics/java-notes/dataStructure/bst/stack_6.png deleted file mode 100644 index bf97bff9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/bst/stack_7.png b/docs/_pics/java-notes/dataStructure/bst/stack_7.png deleted file mode 100644 index 4bf60208..00000000 Binary files a/docs/_pics/java-notes/dataStructure/bst/stack_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_1.png b/docs/_pics/java-notes/dataStructure/ds_1.png deleted file mode 100644 index 609571bf..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_10.png b/docs/_pics/java-notes/dataStructure/ds_10.png deleted file mode 100644 index 9970a6c4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_11.png b/docs/_pics/java-notes/dataStructure/ds_11.png deleted file mode 100644 index 2f8b2d9a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_12.png b/docs/_pics/java-notes/dataStructure/ds_12.png deleted file mode 100644 index f8037339..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_13.png b/docs/_pics/java-notes/dataStructure/ds_13.png deleted file mode 100644 index 0635fe9f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_14.png b/docs/_pics/java-notes/dataStructure/ds_14.png deleted file mode 100644 index 73c04e73..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_15.png b/docs/_pics/java-notes/dataStructure/ds_15.png deleted file mode 100644 index 86943cd6..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_16.png b/docs/_pics/java-notes/dataStructure/ds_16.png deleted file mode 100644 index bfcf76c9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_17.png b/docs/_pics/java-notes/dataStructure/ds_17.png deleted file mode 100644 index 82fa2a1e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_18.png b/docs/_pics/java-notes/dataStructure/ds_18.png deleted file mode 100644 index 3132f10f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_19.png b/docs/_pics/java-notes/dataStructure/ds_19.png deleted file mode 100644 index dbac0f3a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_2.png b/docs/_pics/java-notes/dataStructure/ds_2.png deleted file mode 100644 index 9c954ec2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_20.png b/docs/_pics/java-notes/dataStructure/ds_20.png deleted file mode 100644 index 273ae055..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_21.png b/docs/_pics/java-notes/dataStructure/ds_21.png deleted file mode 100644 index 03935e3f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_21.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_22.png b/docs/_pics/java-notes/dataStructure/ds_22.png deleted file mode 100644 index 4d25b1d3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_22.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_23.png b/docs/_pics/java-notes/dataStructure/ds_23.png deleted file mode 100644 index 810d88a4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_23.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_3.png b/docs/_pics/java-notes/dataStructure/ds_3.png deleted file mode 100644 index 9c901543..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_4.png b/docs/_pics/java-notes/dataStructure/ds_4.png deleted file mode 100644 index f96603ad..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_5.png b/docs/_pics/java-notes/dataStructure/ds_5.png deleted file mode 100644 index e86adf53..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_6.png b/docs/_pics/java-notes/dataStructure/ds_6.png deleted file mode 100644 index 76feac80..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_7.png b/docs/_pics/java-notes/dataStructure/ds_7.png deleted file mode 100644 index f8b7a7aa..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_8.png b/docs/_pics/java-notes/dataStructure/ds_8.png deleted file mode 100644 index d926fa86..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/ds_9.png b/docs/_pics/java-notes/dataStructure/ds_9.png deleted file mode 100644 index 42aa0197..00000000 Binary files a/docs/_pics/java-notes/dataStructure/ds_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/graph/14_1.png b/docs/_pics/java-notes/dataStructure/graph/14_1.png deleted file mode 100644 index e4e8daac..00000000 Binary files a/docs/_pics/java-notes/dataStructure/graph/14_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/graph/14_2.png b/docs/_pics/java-notes/dataStructure/graph/14_2.png deleted file mode 100644 index 9515ba5b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/graph/14_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/graph/14_3.png b/docs/_pics/java-notes/dataStructure/graph/14_3.png deleted file mode 100644 index e3856961..00000000 Binary files a/docs/_pics/java-notes/dataStructure/graph/14_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/graph/14_4.png b/docs/_pics/java-notes/dataStructure/graph/14_4.png deleted file mode 100644 index 5e8c304d..00000000 Binary files a/docs/_pics/java-notes/dataStructure/graph/14_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_1.png b/docs/_pics/java-notes/dataStructure/hash/13_1.png deleted file mode 100644 index 5be4bb04..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_2.png b/docs/_pics/java-notes/dataStructure/hash/13_2.png deleted file mode 100644 index d096905f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_3.png b/docs/_pics/java-notes/dataStructure/hash/13_3.png deleted file mode 100644 index f41c13dd..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_4.png b/docs/_pics/java-notes/dataStructure/hash/13_4.png deleted file mode 100644 index b9a9e8a2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_5.png b/docs/_pics/java-notes/dataStructure/hash/13_5.png deleted file mode 100644 index d24ffc10..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_6.png b/docs/_pics/java-notes/dataStructure/hash/13_6.png deleted file mode 100644 index 6b422f33..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/hash/13_7.png b/docs/_pics/java-notes/dataStructure/hash/13_7.png deleted file mode 100644 index fd31f45e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/hash/13_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/heap/heap_1.png b/docs/_pics/java-notes/dataStructure/heap/heap_1.png deleted file mode 100644 index 679349fa..00000000 Binary files a/docs/_pics/java-notes/dataStructure/heap/heap_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/heap/heap_2.png b/docs/_pics/java-notes/dataStructure/heap/heap_2.png deleted file mode 100644 index 5a8f6121..00000000 Binary files a/docs/_pics/java-notes/dataStructure/heap/heap_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/heap/heap_3.png b/docs/_pics/java-notes/dataStructure/heap/heap_3.png deleted file mode 100644 index beb6d5f5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/heap/heap_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/heap/heap_4.png b/docs/_pics/java-notes/dataStructure/heap/heap_4.png deleted file mode 100644 index 324a9606..00000000 Binary files a/docs/_pics/java-notes/dataStructure/heap/heap_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/heap/heap_5.png b/docs/_pics/java-notes/dataStructure/heap/heap_5.png deleted file mode 100644 index ca89c4c0..00000000 Binary files a/docs/_pics/java-notes/dataStructure/heap/heap_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_1.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_1.png deleted file mode 100644 index 60319a11..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_10.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_10.png deleted file mode 100644 index 13a24ecb..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_11.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_11.png deleted file mode 100644 index 9562a271..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_12.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_12.png deleted file mode 100644 index 9a664338..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_13.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_13.png deleted file mode 100644 index 29c37b9c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_14.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_14.png deleted file mode 100644 index 73c32f05..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_15.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_15.png deleted file mode 100644 index 4122bbf3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_16.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_16.png deleted file mode 100644 index 05afeb8e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_17.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_17.png deleted file mode 100644 index 4253aeac..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_2.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_2.png deleted file mode 100644 index 445fb91a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_3.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_3.png deleted file mode 100644 index 987245a3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_4.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_4.png deleted file mode 100644 index 4ad908d4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_5.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_5.png deleted file mode 100644 index 2f460915..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_6.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_6.png deleted file mode 100644 index 33078fe0..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_7.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_7.png deleted file mode 100644 index 67f1a681..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_8.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_8.png deleted file mode 100644 index 3b859ee1..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_9.png b/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_9.png deleted file mode 100644 index bd5c0895..00000000 Binary files a/docs/_pics/java-notes/dataStructure/linkedlist/linkedlist_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/lr/lr_1.png b/docs/_pics/java-notes/dataStructure/lr/lr_1.png deleted file mode 100644 index 37b6112c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/lr/lr_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/lr/lr_2.png b/docs/_pics/java-notes/dataStructure/lr/lr_2.png deleted file mode 100644 index a54e2388..00000000 Binary files a/docs/_pics/java-notes/dataStructure/lr/lr_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/lr/lr_3.png b/docs/_pics/java-notes/dataStructure/lr/lr_3.png deleted file mode 100644 index 3f80501a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/lr/lr_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/lr/lr_4.png b/docs/_pics/java-notes/dataStructure/lr/lr_4.png deleted file mode 100644 index 862d3244..00000000 Binary files a/docs/_pics/java-notes/dataStructure/lr/lr_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/minSpanTree/15_1.png b/docs/_pics/java-notes/dataStructure/minSpanTree/15_1.png deleted file mode 100644 index bef9f484..00000000 Binary files a/docs/_pics/java-notes/dataStructure/minSpanTree/15_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/minSpanTree/15_2.png b/docs/_pics/java-notes/dataStructure/minSpanTree/15_2.png deleted file mode 100644 index 8d54ca66..00000000 Binary files a/docs/_pics/java-notes/dataStructure/minSpanTree/15_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/minSpanTree/15_3.png b/docs/_pics/java-notes/dataStructure/minSpanTree/15_3.png deleted file mode 100644 index dea2df7a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/minSpanTree/15_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/minSpanTree/15_4.png b/docs/_pics/java-notes/dataStructure/minSpanTree/15_4.png deleted file mode 100644 index ca82370d..00000000 Binary files a/docs/_pics/java-notes/dataStructure/minSpanTree/15_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/minSpanTree/15_5.png b/docs/_pics/java-notes/dataStructure/minSpanTree/15_5.png deleted file mode 100644 index 96065623..00000000 Binary files a/docs/_pics/java-notes/dataStructure/minSpanTree/15_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_1.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_1.png deleted file mode 100644 index c9835b8f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_10.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_10.png deleted file mode 100644 index 3f02d09c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_11.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_11.png deleted file mode 100644 index 59f9dc4e..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_12.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_12.png deleted file mode 100644 index 09adc3c4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_13.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_13.png deleted file mode 100644 index 96d236b6..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_14.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_14.png deleted file mode 100644 index 9817e18b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_15.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_15.png deleted file mode 100644 index a1d2707f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_16.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_16.png deleted file mode 100644 index 180ab3d9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_17.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_17.png deleted file mode 100644 index e77f9196..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_18.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_18.png deleted file mode 100644 index c525a2b5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_19.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_19.png deleted file mode 100644 index 17d2279b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_2.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_2.png deleted file mode 100644 index a389e992..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_20.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_20.png deleted file mode 100644 index 6b9b1015..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_21.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_21.png deleted file mode 100644 index 446d9e24..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_21.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_23.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_23.png deleted file mode 100644 index 9d7ea819..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_23.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_24.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_24.png deleted file mode 100644 index 115e82f2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_24.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_25.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_25.png deleted file mode 100644 index a3876e3b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_25.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_3.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_3.png deleted file mode 100644 index 658ad0ed..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_4.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_4.png deleted file mode 100644 index 4858df2a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_5.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_5.png deleted file mode 100644 index d90946b5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_6.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_6.png deleted file mode 100644 index df6839a5..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_8.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_8.png deleted file mode 100644 index f99ca2a7..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/redBlackTree/12_9.png b/docs/_pics/java-notes/dataStructure/redBlackTree/12_9.png deleted file mode 100644 index 920b8f8b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/redBlackTree/12_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree.png deleted file mode 100644 index 17a6f4ca..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree00.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree00.png deleted file mode 100644 index 6d70a1a4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree00.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree01.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree01.png deleted file mode 100644 index c3b86b11..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree01.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_2.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_2.png deleted file mode 100644 index f497d07f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_3.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_3.png deleted file mode 100644 index 9e218f40..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_4.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_4.png deleted file mode 100644 index 991dd72b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_5.png b/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_5.png deleted file mode 100644 index 205fec50..00000000 Binary files a/docs/_pics/java-notes/dataStructure/segmentTree/segmentTree_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/map_1.png b/docs/_pics/java-notes/dataStructure/setAndMap/map_1.png deleted file mode 100644 index a906a105..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/map_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/map_2.png b/docs/_pics/java-notes/dataStructure/setAndMap/map_2.png deleted file mode 100644 index 58083c2f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/map_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/set_1.png b/docs/_pics/java-notes/dataStructure/setAndMap/set_1.png deleted file mode 100644 index 06b47d84..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/set_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/set_2.png b/docs/_pics/java-notes/dataStructure/setAndMap/set_2.png deleted file mode 100644 index 57ca60b6..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/set_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/set_3.png b/docs/_pics/java-notes/dataStructure/setAndMap/set_3.png deleted file mode 100644 index 4235a13c..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/set_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/setAndMap/set_4.png b/docs/_pics/java-notes/dataStructure/setAndMap/set_4.png deleted file mode 100644 index b3a446e3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/setAndMap/set_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_1.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_1.png deleted file mode 100644 index 35a3fb5d..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_10.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_10.png deleted file mode 100644 index 216fca58..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_11.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_11.png deleted file mode 100644 index c4f4ea57..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_2.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_2.png deleted file mode 100644 index a0ac3c67..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_3.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_3.png deleted file mode 100644 index 01447a0a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_4.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_4.png deleted file mode 100644 index 33276f8f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_5.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_5.png deleted file mode 100644 index 19388d75..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_6.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_6.png deleted file mode 100644 index a526f1c2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_7.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_7.png deleted file mode 100644 index 26a3f101..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_8.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_8.png deleted file mode 100644 index 9997aabb..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/shortestPath/16_9.png b/docs/_pics/java-notes/dataStructure/shortestPath/16_9.png deleted file mode 100644 index d6a11f7f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/shortestPath/16_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_1.png b/docs/_pics/java-notes/dataStructure/stack/queue_1.png deleted file mode 100644 index b1b89409..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_2.png b/docs/_pics/java-notes/dataStructure/stack/queue_2.png deleted file mode 100644 index eb14afd9..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_3.png b/docs/_pics/java-notes/dataStructure/stack/queue_3.png deleted file mode 100644 index 728e840f..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_4.png b/docs/_pics/java-notes/dataStructure/stack/queue_4.png deleted file mode 100644 index 02bd21b3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_5.png b/docs/_pics/java-notes/dataStructure/stack/queue_5.png deleted file mode 100644 index c3b1eaa2..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_6.png b/docs/_pics/java-notes/dataStructure/stack/queue_6.png deleted file mode 100644 index 94458b16..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/queue_7.png b/docs/_pics/java-notes/dataStructure/stack/queue_7.png deleted file mode 100644 index aae4455a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/queue_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/stack_1.png b/docs/_pics/java-notes/dataStructure/stack/stack_1.png deleted file mode 100644 index 8c88f27b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/stack_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/stack/stack_2.png b/docs/_pics/java-notes/dataStructure/stack/stack_2.png deleted file mode 100644 index 658939ab..00000000 Binary files a/docs/_pics/java-notes/dataStructure/stack/stack_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_1.png b/docs/_pics/java-notes/dataStructure/sz_1.png deleted file mode 100644 index 7763fe92..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_2.png b/docs/_pics/java-notes/dataStructure/sz_2.png deleted file mode 100644 index 62e90ee3..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_3.png b/docs/_pics/java-notes/dataStructure/sz_3.png deleted file mode 100644 index d4642907..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_4.png b/docs/_pics/java-notes/dataStructure/sz_4.png deleted file mode 100644 index ccf10672..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_5.png b/docs/_pics/java-notes/dataStructure/sz_5.png deleted file mode 100644 index bc14b56b..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/sz_6.png b/docs/_pics/java-notes/dataStructure/sz_6.png deleted file mode 100644 index f8eb1844..00000000 Binary files a/docs/_pics/java-notes/dataStructure/sz_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/trie/trie_1.png b/docs/_pics/java-notes/dataStructure/trie/trie_1.png deleted file mode 100644 index 40a7e2db..00000000 Binary files a/docs/_pics/java-notes/dataStructure/trie/trie_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/trie/trie_2.png b/docs/_pics/java-notes/dataStructure/trie/trie_2.png deleted file mode 100644 index a80cdb79..00000000 Binary files a/docs/_pics/java-notes/dataStructure/trie/trie_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_1.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_1.png deleted file mode 100644 index f09e91e1..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_10.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_10.png deleted file mode 100644 index f63f7b1a..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_2.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_2.png deleted file mode 100644 index e74ae1b4..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_3.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_3.png deleted file mode 100644 index ed737b84..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_4.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_4.png deleted file mode 100644 index a91b8381..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_5.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_5.png deleted file mode 100644 index e72818a6..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_6.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_6.png deleted file mode 100644 index 0fd49f44..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_7.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_7.png deleted file mode 100644 index 61ea9717..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_8.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_8.png deleted file mode 100644 index a0e0f003..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/uf_9.png b/docs/_pics/java-notes/dataStructure/unionFind/uf_9.png deleted file mode 100644 index f75a0943..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/uf_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/unionFind_1.png b/docs/_pics/java-notes/dataStructure/unionFind/unionFind_1.png deleted file mode 100644 index a693fe3d..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/unionFind_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/dataStructure/unionFind/unionFind_2.png b/docs/_pics/java-notes/dataStructure/unionFind/unionFind_2.png deleted file mode 100644 index afd1b566..00000000 Binary files a/docs/_pics/java-notes/dataStructure/unionFind/unionFind_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/061c88c1-572f-424f-b580-9cbce903a3fe.png b/docs/_pics/java-notes/database/061c88c1-572f-424f-b580-9cbce903a3fe.png deleted file mode 100644 index eb25a980..00000000 Binary files a/docs/_pics/java-notes/database/061c88c1-572f-424f-b580-9cbce903a3fe.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/0ea37ee2-c224-4c79-b895-e131c6805c40.png b/docs/_pics/java-notes/database/0ea37ee2-c224-4c79-b895-e131c6805c40.png deleted file mode 100644 index 79ec18df..00000000 Binary files a/docs/_pics/java-notes/database/0ea37ee2-c224-4c79-b895-e131c6805c40.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/1202b2d6-9469-4251-bd47-ca6034fb6116.png b/docs/_pics/java-notes/database/1202b2d6-9469-4251-bd47-ca6034fb6116.png deleted file mode 100644 index b44fa996..00000000 Binary files a/docs/_pics/java-notes/database/1202b2d6-9469-4251-bd47-ca6034fb6116.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/185b9c49-4c13-4241-a848-fbff85c03a64.png b/docs/_pics/java-notes/database/185b9c49-4c13-4241-a848-fbff85c03a64.png deleted file mode 100644 index 6f56bc5e..00000000 Binary files a/docs/_pics/java-notes/database/185b9c49-4c13-4241-a848-fbff85c03a64.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/1a851e90-0d5c-4d4f-ac54-34c20ecfb903.jpg b/docs/_pics/java-notes/database/1a851e90-0d5c-4d4f-ac54-34c20ecfb903.jpg deleted file mode 100644 index 4809984f..00000000 Binary files a/docs/_pics/java-notes/database/1a851e90-0d5c-4d4f-ac54-34c20ecfb903.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/292b4a35-4507-4256-84ff-c218f108ee31.jpg b/docs/_pics/java-notes/database/292b4a35-4507-4256-84ff-c218f108ee31.jpg deleted file mode 100644 index 38e0905b..00000000 Binary files a/docs/_pics/java-notes/database/292b4a35-4507-4256-84ff-c218f108ee31.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png b/docs/_pics/java-notes/database/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png deleted file mode 100644 index b486ec02..00000000 Binary files a/docs/_pics/java-notes/database/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/423f2a40-bee1-488e-b460-8e76c48ee560.png b/docs/_pics/java-notes/database/423f2a40-bee1-488e-b460-8e76c48ee560.png deleted file mode 100644 index 7b8c8c08..00000000 Binary files a/docs/_pics/java-notes/database/423f2a40-bee1-488e-b460-8e76c48ee560.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/485fdf34-ccf8-4185-97c6-17374ee719a0.png b/docs/_pics/java-notes/database/485fdf34-ccf8-4185-97c6-17374ee719a0.png deleted file mode 100644 index f9f73faf..00000000 Binary files a/docs/_pics/java-notes/database/485fdf34-ccf8-4185-97c6-17374ee719a0.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/6019b2db-bc3e-4408-b6d8-96025f4481d6.png b/docs/_pics/java-notes/database/6019b2db-bc3e-4408-b6d8-96025f4481d6.png deleted file mode 100644 index 900ee963..00000000 Binary files a/docs/_pics/java-notes/database/6019b2db-bc3e-4408-b6d8-96025f4481d6.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg b/docs/_pics/java-notes/database/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg deleted file mode 100644 index d6471621..00000000 Binary files a/docs/_pics/java-notes/database/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/72fe492e-f1cb-4cfc-92f8-412fb3ae6fec.png b/docs/_pics/java-notes/database/72fe492e-f1cb-4cfc-92f8-412fb3ae6fec.png deleted file mode 100644 index 748980c4..00000000 Binary files a/docs/_pics/java-notes/database/72fe492e-f1cb-4cfc-92f8-412fb3ae6fec.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg b/docs/_pics/java-notes/database/7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg deleted file mode 100644 index 31c70314..00000000 Binary files a/docs/_pics/java-notes/database/7ab8ca28-2a41-4adf-9502-cc0a21e63b51.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/7bd202a7-93d4-4f3a-a878-af68ae25539a.png b/docs/_pics/java-notes/database/7bd202a7-93d4-4f3a-a878-af68ae25539a.png deleted file mode 100644 index 711fb45b..00000000 Binary files a/docs/_pics/java-notes/database/7bd202a7-93d4-4f3a-a878-af68ae25539a.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/7c54de21-e2ff-402e-bc42-4037de1c1592.png b/docs/_pics/java-notes/database/7c54de21-e2ff-402e-bc42-4037de1c1592.png deleted file mode 100644 index 8b5ce204..00000000 Binary files a/docs/_pics/java-notes/database/7c54de21-e2ff-402e-bc42-4037de1c1592.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/7ec9d619-fa60-4a2b-95aa-bf1a62aad408.jpg b/docs/_pics/java-notes/database/7ec9d619-fa60-4a2b-95aa-bf1a62aad408.jpg deleted file mode 100644 index 5753388e..00000000 Binary files a/docs/_pics/java-notes/database/7ec9d619-fa60-4a2b-95aa-bf1a62aad408.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/88ff46b3-028a-4dbb-a572-1f062b8b96d3.png b/docs/_pics/java-notes/database/88ff46b3-028a-4dbb-a572-1f062b8b96d3.png deleted file mode 100644 index c6344ad2..00000000 Binary files a/docs/_pics/java-notes/database/88ff46b3-028a-4dbb-a572-1f062b8b96d3.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/8b798007-e0fb-420c-b981-ead215692417.jpg b/docs/_pics/java-notes/database/8b798007-e0fb-420c-b981-ead215692417.jpg deleted file mode 100644 index dd218133..00000000 Binary files a/docs/_pics/java-notes/database/8b798007-e0fb-420c-b981-ead215692417.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png b/docs/_pics/java-notes/database/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png deleted file mode 100644 index ba045e20..00000000 Binary files a/docs/_pics/java-notes/database/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/B_plus_tree.png b/docs/_pics/java-notes/database/B_plus_tree.png deleted file mode 100644 index c5e8961d..00000000 Binary files a/docs/_pics/java-notes/database/B_plus_tree.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_1.png b/docs/_pics/java-notes/database/MySQL_1.png deleted file mode 100644 index 74d42d53..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_2.png b/docs/_pics/java-notes/database/MySQL_2.png deleted file mode 100644 index 8764a2f9..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_3.png b/docs/_pics/java-notes/database/MySQL_3.png deleted file mode 100644 index 503ef3b2..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_4.png b/docs/_pics/java-notes/database/MySQL_4.png deleted file mode 100644 index 7d57aae5..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_6.gif b/docs/_pics/java-notes/database/MySQL_6.gif deleted file mode 100644 index cac12c03..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_6.gif and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_7.png b/docs/_pics/java-notes/database/MySQL_7.png deleted file mode 100644 index 47a0dc18..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/MySQL_8.png b/docs/_pics/java-notes/database/MySQL_8.png deleted file mode 100644 index 7fef7ba5..00000000 Binary files a/docs/_pics/java-notes/database/MySQL_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/a58e294a-615d-4ea0-9fbf-064a6daec4b2.png b/docs/_pics/java-notes/database/a58e294a-615d-4ea0-9fbf-064a6daec4b2.png deleted file mode 100644 index fdefb823..00000000 Binary files a/docs/_pics/java-notes/database/a58e294a-615d-4ea0-9fbf-064a6daec4b2.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/beba612e-dc5b-4fc2-869d-0b23408ac90a.png b/docs/_pics/java-notes/database/beba612e-dc5b-4fc2-869d-0b23408ac90a.png deleted file mode 100644 index b24241d1..00000000 Binary files a/docs/_pics/java-notes/database/beba612e-dc5b-4fc2-869d-0b23408ac90a.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png b/docs/_pics/java-notes/database/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png deleted file mode 100644 index add3c5d4..00000000 Binary files a/docs/_pics/java-notes/database/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg b/docs/_pics/java-notes/database/c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg deleted file mode 100644 index 593513fe..00000000 Binary files a/docs/_pics/java-notes/database/c28c6fbc-2bc1-47d9-9b2e-cf3d4034f877.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/c2d343f7-604c-4856-9a3c-c71d6f67fecc.png b/docs/_pics/java-notes/database/c2d343f7-604c-4856-9a3c-c71d6f67fecc.png deleted file mode 100644 index 84b2898b..00000000 Binary files a/docs/_pics/java-notes/database/c2d343f7-604c-4856-9a3c-c71d6f67fecc.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/c8d18ca9-0b09-441a-9a0c-fb063630d708.png b/docs/_pics/java-notes/database/c8d18ca9-0b09-441a-9a0c-fb063630d708.png deleted file mode 100644 index 514ab054..00000000 Binary files a/docs/_pics/java-notes/database/c8d18ca9-0b09-441a-9a0c-fb063630d708.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png b/docs/_pics/java-notes/database/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png deleted file mode 100644 index f8550a11..00000000 Binary files a/docs/_pics/java-notes/database/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db.png b/docs/_pics/java-notes/database/db.png deleted file mode 100644 index a41b0eb8..00000000 Binary files a/docs/_pics/java-notes/database/db.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_1.png b/docs/_pics/java-notes/database/db_1.png deleted file mode 100644 index f097290d..00000000 Binary files a/docs/_pics/java-notes/database/db_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_10.png b/docs/_pics/java-notes/database/db_10.png deleted file mode 100644 index 5d20fba8..00000000 Binary files a/docs/_pics/java-notes/database/db_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_11.png b/docs/_pics/java-notes/database/db_11.png deleted file mode 100644 index 7c8b3df9..00000000 Binary files a/docs/_pics/java-notes/database/db_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_12.png b/docs/_pics/java-notes/database/db_12.png deleted file mode 100644 index 67b11d24..00000000 Binary files a/docs/_pics/java-notes/database/db_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_13.png b/docs/_pics/java-notes/database/db_13.png deleted file mode 100644 index 3916e93b..00000000 Binary files a/docs/_pics/java-notes/database/db_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_14.png b/docs/_pics/java-notes/database/db_14.png deleted file mode 100644 index 968f5b58..00000000 Binary files a/docs/_pics/java-notes/database/db_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_15.png b/docs/_pics/java-notes/database/db_15.png deleted file mode 100644 index dd2b185a..00000000 Binary files a/docs/_pics/java-notes/database/db_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_16.png b/docs/_pics/java-notes/database/db_16.png deleted file mode 100644 index a9d55fd4..00000000 Binary files a/docs/_pics/java-notes/database/db_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_17.png b/docs/_pics/java-notes/database/db_17.png deleted file mode 100644 index 8f1f54f6..00000000 Binary files a/docs/_pics/java-notes/database/db_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_18.png b/docs/_pics/java-notes/database/db_18.png deleted file mode 100644 index e7399df8..00000000 Binary files a/docs/_pics/java-notes/database/db_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_19.png b/docs/_pics/java-notes/database/db_19.png deleted file mode 100644 index f5ee41cc..00000000 Binary files a/docs/_pics/java-notes/database/db_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_2.png b/docs/_pics/java-notes/database/db_2.png deleted file mode 100644 index bf345f40..00000000 Binary files a/docs/_pics/java-notes/database/db_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_3.png b/docs/_pics/java-notes/database/db_3.png deleted file mode 100644 index 5c50f36b..00000000 Binary files a/docs/_pics/java-notes/database/db_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_4.png b/docs/_pics/java-notes/database/db_4.png deleted file mode 100644 index 8c44e8c0..00000000 Binary files a/docs/_pics/java-notes/database/db_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_5.png b/docs/_pics/java-notes/database/db_5.png deleted file mode 100644 index 81c9f2c8..00000000 Binary files a/docs/_pics/java-notes/database/db_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_6.png b/docs/_pics/java-notes/database/db_6.png deleted file mode 100644 index 22d5b499..00000000 Binary files a/docs/_pics/java-notes/database/db_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_7.png b/docs/_pics/java-notes/database/db_7.png deleted file mode 100644 index ec99338f..00000000 Binary files a/docs/_pics/java-notes/database/db_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_8.png b/docs/_pics/java-notes/database/db_8.png deleted file mode 100644 index c3b8b28b..00000000 Binary files a/docs/_pics/java-notes/database/db_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/db_9.png b/docs/_pics/java-notes/database/db_9.png deleted file mode 100644 index 6e35eb8a..00000000 Binary files a/docs/_pics/java-notes/database/db_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/dd782132-d830-4c55-9884-cfac0a541b8e.png b/docs/_pics/java-notes/database/dd782132-d830-4c55-9884-cfac0a541b8e.png deleted file mode 100644 index e338c1bb..00000000 Binary files a/docs/_pics/java-notes/database/dd782132-d830-4c55-9884-cfac0a541b8e.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/de9b9ea0-1327-4865-93e5-6f805c48bc9e.png b/docs/_pics/java-notes/database/de9b9ea0-1327-4865-93e5-6f805c48bc9e.png deleted file mode 100644 index cfabd4d7..00000000 Binary files a/docs/_pics/java-notes/database/de9b9ea0-1327-4865-93e5-6f805c48bc9e.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg b/docs/_pics/java-notes/database/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg deleted file mode 100644 index 0968e1bc..00000000 Binary files a/docs/_pics/java-notes/database/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/e41405a8-7c05-4f70-8092-e961e28d3112.jpg b/docs/_pics/java-notes/database/e41405a8-7c05-4f70-8092-e961e28d3112.jpg deleted file mode 100644 index 7fef7ba5..00000000 Binary files a/docs/_pics/java-notes/database/e41405a8-7c05-4f70-8092-e961e28d3112.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/database/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png b/docs/_pics/java-notes/database/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png deleted file mode 100644 index 26799762..00000000 Binary files a/docs/_pics/java-notes/database/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/fb327611-7e2b-4f2f-9f5b-38592d408f07.png b/docs/_pics/java-notes/database/fb327611-7e2b-4f2f-9f5b-38592d408f07.png deleted file mode 100644 index 774ecf10..00000000 Binary files a/docs/_pics/java-notes/database/fb327611-7e2b-4f2f-9f5b-38592d408f07.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/leetcode_1.png b/docs/_pics/java-notes/database/leetcode_1.png deleted file mode 100644 index 88583f00..00000000 Binary files a/docs/_pics/java-notes/database/leetcode_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/leetcode_2.png b/docs/_pics/java-notes/database/leetcode_2.png deleted file mode 100644 index 1fe2db8d..00000000 Binary files a/docs/_pics/java-notes/database/leetcode_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/leetcode_3.png b/docs/_pics/java-notes/database/leetcode_3.png deleted file mode 100644 index 21cd8fe0..00000000 Binary files a/docs/_pics/java-notes/database/leetcode_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/master-slave-proxy.png b/docs/_pics/java-notes/database/master-slave-proxy.png deleted file mode 100644 index 66be0d61..00000000 Binary files a/docs/_pics/java-notes/database/master-slave-proxy.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/master-slave.png b/docs/_pics/java-notes/database/master-slave.png deleted file mode 100644 index 594a183a..00000000 Binary files a/docs/_pics/java-notes/database/master-slave.png and /dev/null differ diff --git a/docs/_pics/java-notes/database/r_1 b/docs/_pics/java-notes/database/r_1 deleted file mode 100644 index 9f0d22dc..00000000 Binary files a/docs/_pics/java-notes/database/r_1 and /dev/null differ diff --git a/docs/_pics/java-notes/database/r_2 b/docs/_pics/java-notes/database/r_2 deleted file mode 100644 index 69aac318..00000000 Binary files a/docs/_pics/java-notes/database/r_2 and /dev/null differ diff --git a/docs/_pics/java-notes/distribution/cap.png b/docs/_pics/java-notes/distribution/cap.png deleted file mode 100644 index 5000a877..00000000 Binary files a/docs/_pics/java-notes/distribution/cap.png and /dev/null differ diff --git a/docs/_pics/java-notes/distribution/cap_2.png b/docs/_pics/java-notes/distribution/cap_2.png deleted file mode 100644 index 4a99129a..00000000 Binary files a/docs/_pics/java-notes/distribution/cap_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/00_1.png b/docs/_pics/java-notes/java/00_1.png deleted file mode 100644 index db310c1f..00000000 Binary files a/docs/_pics/java-notes/java/00_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/01_1.png b/docs/_pics/java-notes/java/01_1.png deleted file mode 100644 index d5884935..00000000 Binary files a/docs/_pics/java-notes/java/01_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/01_2.png b/docs/_pics/java-notes/java/01_2.png deleted file mode 100644 index b8624ac1..00000000 Binary files a/docs/_pics/java-notes/java/01_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/02_1.png b/docs/_pics/java-notes/java/02_1.png deleted file mode 100644 index 897a510b..00000000 Binary files a/docs/_pics/java-notes/java/02_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/02_2.png b/docs/_pics/java-notes/java/02_2.png deleted file mode 100644 index 7a3d9fc1..00000000 Binary files a/docs/_pics/java-notes/java/02_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/04_01.png b/docs/_pics/java-notes/java/04_01.png deleted file mode 100644 index cf9e87d9..00000000 Binary files a/docs/_pics/java-notes/java/04_01.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/06_00.png b/docs/_pics/java-notes/java/06_00.png deleted file mode 100644 index 994c15c4..00000000 Binary files a/docs/_pics/java-notes/java/06_00.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/16_00.jpg b/docs/_pics/java-notes/java/16_00.jpg deleted file mode 100644 index 7701e8b1..00000000 Binary files a/docs/_pics/java-notes/java/16_00.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/java/16_03.jpg b/docs/_pics/java-notes/java/16_03.jpg deleted file mode 100644 index 43e9fed1..00000000 Binary files a/docs/_pics/java-notes/java/16_03.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/java/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png b/docs/_pics/java-notes/java/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png deleted file mode 100644 index e4286077..00000000 Binary files a/docs/_pics/java-notes/java/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/3fdfc89d-719e-4d93-b518-29fa612b3b18.png b/docs/_pics/java-notes/java/3fdfc89d-719e-4d93-b518-29fa612b3b18.png deleted file mode 100644 index 781dca88..00000000 Binary files a/docs/_pics/java-notes/java/3fdfc89d-719e-4d93-b518-29fa612b3b18.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/49495c95-52e5-4c9a-b27b-92cf235ff5ec.png b/docs/_pics/java-notes/java/49495c95-52e5-4c9a-b27b-92cf235ff5ec.png deleted file mode 100644 index 662d99c3..00000000 Binary files a/docs/_pics/java-notes/java/49495c95-52e5-4c9a-b27b-92cf235ff5ec.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/49d6de7b-0d0d-425c-9e49-a1559dc23b10.png b/docs/_pics/java-notes/java/49d6de7b-0d0d-425c-9e49-a1559dc23b10.png deleted file mode 100644 index eea3c6b4..00000000 Binary files a/docs/_pics/java-notes/java/49d6de7b-0d0d-425c-9e49-a1559dc23b10.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/4d930e22-f493-49ae-8dff-ea21cd6895dc.png b/docs/_pics/java-notes/java/4d930e22-f493-49ae-8dff-ea21cd6895dc.png deleted file mode 100644 index 7ee2ffb4..00000000 Binary files a/docs/_pics/java-notes/java/4d930e22-f493-49ae-8dff-ea21cd6895dc.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/67bf5487-c45d-49b6-b9c0-a058d8c68902.png b/docs/_pics/java-notes/java/67bf5487-c45d-49b6-b9c0-a058d8c68902.png deleted file mode 100644 index b63baeb2..00000000 Binary files a/docs/_pics/java-notes/java/67bf5487-c45d-49b6-b9c0-a058d8c68902.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/80804f52-8815-4096-b506-48eef3eed5c6.png b/docs/_pics/java-notes/java/80804f52-8815-4096-b506-48eef3eed5c6.png deleted file mode 100644 index 06c8760b..00000000 Binary files a/docs/_pics/java-notes/java/80804f52-8815-4096-b506-48eef3eed5c6.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/8fe838e3-ef77-4f63-bf45-417b6bc5c6bb.png b/docs/_pics/java-notes/java/8fe838e3-ef77-4f63-bf45-417b6bc5c6bb.png deleted file mode 100644 index 2e53fbe3..00000000 Binary files a/docs/_pics/java-notes/java/8fe838e3-ef77-4f63-bf45-417b6bc5c6bb.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/952e06bd-5a65-4cab-82e4-dd1536462f38.png b/docs/_pics/java-notes/java/952e06bd-5a65-4cab-82e4-dd1536462f38.png deleted file mode 100644 index 4983142a..00000000 Binary files a/docs/_pics/java-notes/java/952e06bd-5a65-4cab-82e4-dd1536462f38.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/ClienteServidorSockets1521731145260.jpg b/docs/_pics/java-notes/java/ClienteServidorSockets1521731145260.jpg deleted file mode 100644 index 18976fb3..00000000 Binary files a/docs/_pics/java-notes/java/ClienteServidorSockets1521731145260.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/java/PPjwP.png b/docs/_pics/java-notes/java/PPjwP.png deleted file mode 100644 index 80631505..00000000 Binary files a/docs/_pics/java-notes/java/PPjwP.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy0G.png b/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy0G.png deleted file mode 100644 index 124ec977..00000000 Binary files a/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy0G.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy4q.png b/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy4q.png deleted file mode 100644 index 7a202d35..00000000 Binary files a/docs/_pics/java-notes/java/SoWkIImgAStDuUBAp2j9BKfBJ4vLy4q.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png b/docs/_pics/java-notes/java/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png deleted file mode 100644 index d2559cf3..00000000 Binary files a/docs/_pics/java-notes/java/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png b/docs/_pics/java-notes/java/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png deleted file mode 100644 index dd32da70..00000000 Binary files a/docs/_pics/java-notes/java/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png and /dev/null differ diff --git a/docs/_pics/java-notes/java/f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg b/docs/_pics/java-notes/java/f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg deleted file mode 100644 index d710e659..00000000 Binary files a/docs/_pics/java-notes/java/f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/java/threadPool.png b/docs/_pics/java-notes/java/threadPool.png deleted file mode 100644 index 7efa6898..00000000 Binary files a/docs/_pics/java-notes/java/threadPool.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/array/array_01.png b/docs/_pics/java-notes/leetcode/array/array_01.png deleted file mode 100644 index c7cf3d0d..00000000 Binary files a/docs/_pics/java-notes/leetcode/array/array_01.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/array/array_02.png b/docs/_pics/java-notes/leetcode/array/array_02.png deleted file mode 100644 index d4aaffa5..00000000 Binary files a/docs/_pics/java-notes/leetcode/array/array_02.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/array/array_03.png b/docs/_pics/java-notes/leetcode/array/array_03.png deleted file mode 100644 index 1450b10d..00000000 Binary files a/docs/_pics/java-notes/leetcode/array/array_03.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/array/array_04.png b/docs/_pics/java-notes/leetcode/array/array_04.png deleted file mode 100644 index e7663a64..00000000 Binary files a/docs/_pics/java-notes/leetcode/array/array_04.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/array/array_05.png b/docs/_pics/java-notes/leetcode/array/array_05.png deleted file mode 100644 index d68a40da..00000000 Binary files a/docs/_pics/java-notes/leetcode/array/array_05.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_1.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_1.png deleted file mode 100644 index 6e1f1b5e..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_10.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_10.png deleted file mode 100644 index 44aebf9e..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_11.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_11.png deleted file mode 100644 index 8ed6eecf..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_12.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_12.png deleted file mode 100644 index ba3163fe..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_13.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_13.png deleted file mode 100644 index e2f6d4d3..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_14.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_14.png deleted file mode 100644 index b6331d27..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_15.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_15.png deleted file mode 100644 index 909aeeb1..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_16.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_16.png deleted file mode 100644 index 0ea9cad5..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_17.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_17.png deleted file mode 100644 index 66736fef..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_18.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_18.png deleted file mode 100644 index 920e918b..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_19.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_19.png deleted file mode 100644 index 3763557e..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_2.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_2.png deleted file mode 100644 index f59c0c48..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_20.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_20.png deleted file mode 100644 index 58f6da7c..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_21.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_21.png deleted file mode 100644 index 73142c37..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_21.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_22.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_22.png deleted file mode 100644 index 3ed5fb51..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_22.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_23.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_23.png deleted file mode 100644 index 42b7c305..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_23.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_24.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_24.png deleted file mode 100644 index 1ea5720a..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_24.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_25.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_25.png deleted file mode 100644 index 888cb6c4..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_25.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_26.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_26.png deleted file mode 100644 index 8c7b8942..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_26.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_27.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_27.png deleted file mode 100644 index e6b99579..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_27.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_28.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_28.png deleted file mode 100644 index 3969ba13..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_28.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_3.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_3.png deleted file mode 100644 index 0036f91e..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_4.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_4.png deleted file mode 100644 index 958005ec..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_5.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_5.png deleted file mode 100644 index 443e3a88..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_6.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_6.png deleted file mode 100644 index cc09d8e7..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_7.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_7.png deleted file mode 100644 index 29cd4865..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_8.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_8.png deleted file mode 100644 index c5476080..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/backtrack/backtrack_9.png b/docs/_pics/java-notes/leetcode/backtrack/backtrack_9.png deleted file mode 100644 index 0a054ea6..00000000 Binary files a/docs/_pics/java-notes/leetcode/backtrack/backtrack_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_1.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_1.png deleted file mode 100644 index 81d04271..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_10.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_10.png deleted file mode 100644 index 8fcb0561..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_11.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_11.png deleted file mode 100644 index 6ed45552..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_13.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_13.png deleted file mode 100644 index 317dddf4..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_14.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_14.png deleted file mode 100644 index c6d75749..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_15.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_15.png deleted file mode 100644 index fc77e5de..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_2.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_2.png deleted file mode 100644 index 73dbce00..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_3.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_3.png deleted file mode 100644 index bda5a311..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_4.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_4.png deleted file mode 100644 index 432c2b9b..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_5.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_5.png deleted file mode 100644 index 79892231..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_6.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_6.png deleted file mode 100644 index d3a8c107..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_7.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_7.png deleted file mode 100644 index 43bf7d20..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_8.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_8.png deleted file mode 100644 index ea13e9ac..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_9.png b/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_9.png deleted file mode 100644 index 017952d8..00000000 Binary files a/docs/_pics/java-notes/leetcode/binaryTree/binaryTree_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_1.png b/docs/_pics/java-notes/leetcode/dp/dp_1.png deleted file mode 100644 index 33b55e33..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_10.png b/docs/_pics/java-notes/leetcode/dp/dp_10.png deleted file mode 100644 index 1ff25c9a..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_11.png b/docs/_pics/java-notes/leetcode/dp/dp_11.png deleted file mode 100644 index a5f200e7..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_12.png b/docs/_pics/java-notes/leetcode/dp/dp_12.png deleted file mode 100644 index d3b94fba..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_13.png b/docs/_pics/java-notes/leetcode/dp/dp_13.png deleted file mode 100644 index 16ddd43f..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_14.png b/docs/_pics/java-notes/leetcode/dp/dp_14.png deleted file mode 100644 index 1ea45c5c..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_15.png b/docs/_pics/java-notes/leetcode/dp/dp_15.png deleted file mode 100644 index f4abec3e..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_16.png b/docs/_pics/java-notes/leetcode/dp/dp_16.png deleted file mode 100644 index 2756995c..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_17.png b/docs/_pics/java-notes/leetcode/dp/dp_17.png deleted file mode 100644 index 6dff07c8..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_18.png b/docs/_pics/java-notes/leetcode/dp/dp_18.png deleted file mode 100644 index ffcd62f6..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_19.png b/docs/_pics/java-notes/leetcode/dp/dp_19.png deleted file mode 100644 index 3f3c9aca..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_2.png b/docs/_pics/java-notes/leetcode/dp/dp_2.png deleted file mode 100644 index 3d9fd50d..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_20.png b/docs/_pics/java-notes/leetcode/dp/dp_20.png deleted file mode 100644 index 9f49363c..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_21.png b/docs/_pics/java-notes/leetcode/dp/dp_21.png deleted file mode 100644 index e4f48597..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_21.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_22.png b/docs/_pics/java-notes/leetcode/dp/dp_22.png deleted file mode 100644 index 2e4f6b4e..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_22.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_23.png b/docs/_pics/java-notes/leetcode/dp/dp_23.png deleted file mode 100644 index bd3815ea..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_23.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_24.png b/docs/_pics/java-notes/leetcode/dp/dp_24.png deleted file mode 100644 index 4a8e68e8..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_24.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_25.gif b/docs/_pics/java-notes/leetcode/dp/dp_25.gif deleted file mode 100644 index c0522889..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_25.gif and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_3.png b/docs/_pics/java-notes/leetcode/dp/dp_3.png deleted file mode 100644 index eb37b4c9..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_4.png b/docs/_pics/java-notes/leetcode/dp/dp_4.png deleted file mode 100644 index 951b4776..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_5.png b/docs/_pics/java-notes/leetcode/dp/dp_5.png deleted file mode 100644 index 57e1b081..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_6.png b/docs/_pics/java-notes/leetcode/dp/dp_6.png deleted file mode 100644 index b17fce41..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_7.png b/docs/_pics/java-notes/leetcode/dp/dp_7.png deleted file mode 100644 index ea11b879..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_8.png b/docs/_pics/java-notes/leetcode/dp/dp_8.png deleted file mode 100644 index 402929d1..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/dp/dp_9.png b/docs/_pics/java-notes/leetcode/dp/dp_9.png deleted file mode 100644 index d1fa7e64..00000000 Binary files a/docs/_pics/java-notes/leetcode/dp/dp_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/find/find_1.png b/docs/_pics/java-notes/leetcode/find/find_1.png deleted file mode 100644 index 83246508..00000000 Binary files a/docs/_pics/java-notes/leetcode/find/find_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_1.png b/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_1.png deleted file mode 100644 index 1ff25c9a..00000000 Binary files a/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_2.png b/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_2.png deleted file mode 100644 index 266a4687..00000000 Binary files a/docs/_pics/java-notes/leetcode/greedyAlgorithms/ga_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_1.png b/docs/_pics/java-notes/leetcode/list/list_1.png deleted file mode 100644 index 585d1d56..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_10.png b/docs/_pics/java-notes/leetcode/list/list_10.png deleted file mode 100644 index e382e8a0..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_11.png b/docs/_pics/java-notes/leetcode/list/list_11.png deleted file mode 100644 index f77a2d89..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_12.png b/docs/_pics/java-notes/leetcode/list/list_12.png deleted file mode 100644 index 4a4c57d7..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_13.png b/docs/_pics/java-notes/leetcode/list/list_13.png deleted file mode 100644 index 61020ab2..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_14.png b/docs/_pics/java-notes/leetcode/list/list_14.png deleted file mode 100644 index a5aa664d..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_15.png b/docs/_pics/java-notes/leetcode/list/list_15.png deleted file mode 100644 index 54fefaf9..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_16.png b/docs/_pics/java-notes/leetcode/list/list_16.png deleted file mode 100644 index 4146c34a..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_17.png b/docs/_pics/java-notes/leetcode/list/list_17.png deleted file mode 100644 index c502f049..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_18.png b/docs/_pics/java-notes/leetcode/list/list_18.png deleted file mode 100644 index d55ea3f9..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_18.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_19.png b/docs/_pics/java-notes/leetcode/list/list_19.png deleted file mode 100644 index f353582b..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_19.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_2.png b/docs/_pics/java-notes/leetcode/list/list_2.png deleted file mode 100644 index 2a0833b3..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_20.png b/docs/_pics/java-notes/leetcode/list/list_20.png deleted file mode 100644 index e0eef68f..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_20.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_21.png b/docs/_pics/java-notes/leetcode/list/list_21.png deleted file mode 100644 index 09b342d9..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_21.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_22.png b/docs/_pics/java-notes/leetcode/list/list_22.png deleted file mode 100644 index 2afc066d..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_22.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_23.png b/docs/_pics/java-notes/leetcode/list/list_23.png deleted file mode 100644 index f627b2a7..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_23.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_24.png b/docs/_pics/java-notes/leetcode/list/list_24.png deleted file mode 100644 index edfa8365..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_24.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_3.png b/docs/_pics/java-notes/leetcode/list/list_3.png deleted file mode 100644 index eaa78050..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_4.png b/docs/_pics/java-notes/leetcode/list/list_4.png deleted file mode 100644 index 2e98e4f7..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_5.png b/docs/_pics/java-notes/leetcode/list/list_5.png deleted file mode 100644 index 34a23477..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_6.png b/docs/_pics/java-notes/leetcode/list/list_6.png deleted file mode 100644 index 24581d88..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_7.png b/docs/_pics/java-notes/leetcode/list/list_7.png deleted file mode 100644 index 16cc8c39..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_8.png b/docs/_pics/java-notes/leetcode/list/list_8.png deleted file mode 100644 index f44ecf7d..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/list/list_9.png b/docs/_pics/java-notes/leetcode/list/list_9.png deleted file mode 100644 index 205a3bfb..00000000 Binary files a/docs/_pics/java-notes/leetcode/list/list_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/math/math_1.png b/docs/_pics/java-notes/leetcode/math/math_1.png deleted file mode 100644 index 930382c5..00000000 Binary files a/docs/_pics/java-notes/leetcode/math/math_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_1.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_1.png deleted file mode 100644 index b37208eb..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_10.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_10.png deleted file mode 100644 index 0b52e1be..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_10.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_11.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_11.png deleted file mode 100644 index 09931d48..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_12.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_12.png deleted file mode 100644 index 74ef244f..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_2.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_2.png deleted file mode 100644 index 493ff443..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_3.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_3.png deleted file mode 100644 index 8d683d6d..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_4.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_4.png deleted file mode 100644 index e79cb1b2..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_5.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_5.png deleted file mode 100644 index 28326468..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_6.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_6.png deleted file mode 100644 index e78336b4..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_7.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_7.png deleted file mode 100644 index 7b6ac17e..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_8.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_8.png deleted file mode 100644 index 5fbd2d38..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/stackQueue/stack_9.png b/docs/_pics/java-notes/leetcode/stackQueue/stack_9.png deleted file mode 100644 index 2fac440e..00000000 Binary files a/docs/_pics/java-notes/leetcode/stackQueue/stack_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/string/str_1.png b/docs/_pics/java-notes/leetcode/string/str_1.png deleted file mode 100644 index 07acaafe..00000000 Binary files a/docs/_pics/java-notes/leetcode/string/str_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc.png deleted file mode 100644 index dc99e67c..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_2.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_2.png deleted file mode 100644 index 6c374d39..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_3.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_3.png deleted file mode 100644 index e1570b18..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_4.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_4.png deleted file mode 100644 index 2755f443..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_5.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_5.png deleted file mode 100644 index 61641485..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_6.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_6.png deleted file mode 100644 index 34c5de21..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_7.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_7.png deleted file mode 100644 index aff5087a..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/leetcode/timeComplexity/tc_8.png b/docs/_pics/java-notes/leetcode/timeComplexity/tc_8.png deleted file mode 100644 index 6286cbed..00000000 Binary files a/docs/_pics/java-notes/leetcode/timeComplexity/tc_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/03f47940-3843-4b51-9e42-5dcaff44858b.jpg b/docs/_pics/java-notes/network/03f47940-3843-4b51-9e42-5dcaff44858b.jpg deleted file mode 100644 index 9a6f75c6..00000000 Binary files a/docs/_pics/java-notes/network/03f47940-3843-4b51-9e42-5dcaff44858b.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/0a9f4125-b6ab-4e94-a807-fd7070ae726a.png b/docs/_pics/java-notes/network/0a9f4125-b6ab-4e94-a807-fd7070ae726a.png deleted file mode 100644 index 395d9201..00000000 Binary files a/docs/_pics/java-notes/network/0a9f4125-b6ab-4e94-a807-fd7070ae726a.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492928105791_3.png b/docs/_pics/java-notes/network/1492928105791_3.png deleted file mode 100644 index d18fc1ca..00000000 Binary files a/docs/_pics/java-notes/network/1492928105791_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492928416812_4.png b/docs/_pics/java-notes/network/1492928416812_4.png deleted file mode 100644 index a43a731b..00000000 Binary files a/docs/_pics/java-notes/network/1492928416812_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492929000361_5.png b/docs/_pics/java-notes/network/1492929000361_5.png deleted file mode 100644 index 919d1222..00000000 Binary files a/docs/_pics/java-notes/network/1492929000361_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492929444818_6.png b/docs/_pics/java-notes/network/1492929444818_6.png deleted file mode 100644 index 0aea3f9a..00000000 Binary files a/docs/_pics/java-notes/network/1492929444818_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492929553651_7.png b/docs/_pics/java-notes/network/1492929553651_7.png deleted file mode 100644 index 13cf0b4e..00000000 Binary files a/docs/_pics/java-notes/network/1492929553651_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1492930243286_8.png b/docs/_pics/java-notes/network/1492930243286_8.png deleted file mode 100644 index 6ee721ff..00000000 Binary files a/docs/_pics/java-notes/network/1492930243286_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/1556770b-8c01-4681-af10-46f1df69202c.jpg b/docs/_pics/java-notes/network/1556770b-8c01-4681-af10-46f1df69202c.jpg deleted file mode 100644 index 94d1adc2..00000000 Binary files a/docs/_pics/java-notes/network/1556770b-8c01-4681-af10-46f1df69202c.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/168e893c-e4a0-4ba4-b81f-9d993483abd0.jpg b/docs/_pics/java-notes/network/168e893c-e4a0-4ba4-b81f-9d993483abd0.jpg deleted file mode 100644 index cbb68f98..00000000 Binary files a/docs/_pics/java-notes/network/168e893c-e4a0-4ba4-b81f-9d993483abd0.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/1ab49e39-012b-4383-8284-26570987e3c4.jpg b/docs/_pics/java-notes/network/1ab49e39-012b-4383-8284-26570987e3c4.jpg deleted file mode 100644 index 48a91211..00000000 Binary files a/docs/_pics/java-notes/network/1ab49e39-012b-4383-8284-26570987e3c4.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/2017-06-11-ca.png b/docs/_pics/java-notes/network/2017-06-11-ca.png deleted file mode 100644 index 550292c1..00000000 Binary files a/docs/_pics/java-notes/network/2017-06-11-ca.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/21041ec2-babb-483f-bf47-8b8148eec162.png b/docs/_pics/java-notes/network/21041ec2-babb-483f-bf47-8b8148eec162.png deleted file mode 100644 index 7de9b57a..00000000 Binary files a/docs/_pics/java-notes/network/21041ec2-babb-483f-bf47-8b8148eec162.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/23ba890e-e11c-45e2-a20c-64d217f83430.png b/docs/_pics/java-notes/network/23ba890e-e11c-45e2-a20c-64d217f83430.png deleted file mode 100644 index 5fccbd1c..00000000 Binary files a/docs/_pics/java-notes/network/23ba890e-e11c-45e2-a20c-64d217f83430.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/2719067e-b299-4639-9065-bed6729dbf0b.png b/docs/_pics/java-notes/network/2719067e-b299-4639-9065-bed6729dbf0b.png deleted file mode 100644 index 95057e05..00000000 Binary files a/docs/_pics/java-notes/network/2719067e-b299-4639-9065-bed6729dbf0b.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/2ad244f5-939c-49fa-9385-69bc688677ab.jpg b/docs/_pics/java-notes/network/2ad244f5-939c-49fa-9385-69bc688677ab.jpg deleted file mode 100644 index 5c1e0af9..00000000 Binary files a/docs/_pics/java-notes/network/2ad244f5-939c-49fa-9385-69bc688677ab.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/2d09a847-b854-439c-9198-b29c65810944.png b/docs/_pics/java-notes/network/2d09a847-b854-439c-9198-b29c65810944.png deleted file mode 100644 index 384f7ef0..00000000 Binary files a/docs/_pics/java-notes/network/2d09a847-b854-439c-9198-b29c65810944.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/3939369b-3a4a-48a0-b9eb-3efae26dd400.png b/docs/_pics/java-notes/network/3939369b-3a4a-48a0-b9eb-3efae26dd400.png deleted file mode 100644 index c2cf9d1b..00000000 Binary files a/docs/_pics/java-notes/network/3939369b-3a4a-48a0-b9eb-3efae26dd400.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png b/docs/_pics/java-notes/network/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png deleted file mode 100644 index 8e363e47..00000000 Binary files a/docs/_pics/java-notes/network/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/426df589-6f97-4622-b74d-4a81fcb1da8e.png b/docs/_pics/java-notes/network/426df589-6f97-4622-b74d-4a81fcb1da8e.png deleted file mode 100644 index 98327bba..00000000 Binary files a/docs/_pics/java-notes/network/426df589-6f97-4622-b74d-4a81fcb1da8e.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/45e0e0bf-386d-4280-a341-a0b9496c7674.png b/docs/_pics/java-notes/network/45e0e0bf-386d-4280-a341-a0b9496c7674.png deleted file mode 100644 index 32fb94aa..00000000 Binary files a/docs/_pics/java-notes/network/45e0e0bf-386d-4280-a341-a0b9496c7674.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/46cec213-3048-4a80-aded-fdd577542801.jpg b/docs/_pics/java-notes/network/46cec213-3048-4a80-aded-fdd577542801.jpg deleted file mode 100644 index 32e1f3d5..00000000 Binary files a/docs/_pics/java-notes/network/46cec213-3048-4a80-aded-fdd577542801.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/50d38e84-238f-4081-8876-14ef6d7938b5.jpg b/docs/_pics/java-notes/network/50d38e84-238f-4081-8876-14ef6d7938b5.jpg deleted file mode 100644 index 6546cefa..00000000 Binary files a/docs/_pics/java-notes/network/50d38e84-238f-4081-8876-14ef6d7938b5.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg b/docs/_pics/java-notes/network/51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg deleted file mode 100644 index 595cdc58..00000000 Binary files a/docs/_pics/java-notes/network/51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/55dc4e84-573d-4c13-a765-52ed1dd251f9.png b/docs/_pics/java-notes/network/55dc4e84-573d-4c13-a765-52ed1dd251f9.png deleted file mode 100644 index 525b323a..00000000 Binary files a/docs/_pics/java-notes/network/55dc4e84-573d-4c13-a765-52ed1dd251f9.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/5999e5de-7c16-4b52-b3aa-6dc7b58c7894.png b/docs/_pics/java-notes/network/5999e5de-7c16-4b52-b3aa-6dc7b58c7894.png deleted file mode 100644 index a61a7dc4..00000000 Binary files a/docs/_pics/java-notes/network/5999e5de-7c16-4b52-b3aa-6dc7b58c7894.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/5aa82b89-f266-44da-887d-18f31f01d8ef.png b/docs/_pics/java-notes/network/5aa82b89-f266-44da-887d-18f31f01d8ef.png deleted file mode 100644 index 68310502..00000000 Binary files a/docs/_pics/java-notes/network/5aa82b89-f266-44da-887d-18f31f01d8ef.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/66192382-558b-4b05-a35d-ac4a2b1a9811.jpg b/docs/_pics/java-notes/network/66192382-558b-4b05-a35d-ac4a2b1a9811.jpg deleted file mode 100644 index eec226c5..00000000 Binary files a/docs/_pics/java-notes/network/66192382-558b-4b05-a35d-ac4a2b1a9811.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/69f16984-a66f-4288-82e4-79b4aa43e835.jpg b/docs/_pics/java-notes/network/69f16984-a66f-4288-82e4-79b4aa43e835.jpg deleted file mode 100644 index 03b7f3da..00000000 Binary files a/docs/_pics/java-notes/network/69f16984-a66f-4288-82e4-79b4aa43e835.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/7b038838-c75b-4538-ae84-6299386704e5.jpg b/docs/_pics/java-notes/network/7b038838-c75b-4538-ae84-6299386704e5.jpg deleted file mode 100644 index 919a0e58..00000000 Binary files a/docs/_pics/java-notes/network/7b038838-c75b-4538-ae84-6299386704e5.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/7b3efa99-d306-4982-8cfb-e7153c33aab4.png b/docs/_pics/java-notes/network/7b3efa99-d306-4982-8cfb-e7153c33aab4.png deleted file mode 100644 index 21aafd0a..00000000 Binary files a/docs/_pics/java-notes/network/7b3efa99-d306-4982-8cfb-e7153c33aab4.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png b/docs/_pics/java-notes/network/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png deleted file mode 100644 index b636edf5..00000000 Binary files a/docs/_pics/java-notes/network/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/8006a450-6c2f-498c-a928-c927f758b1d0.png b/docs/_pics/java-notes/network/8006a450-6c2f-498c-a928-c927f758b1d0.png deleted file mode 100644 index ac453eeb..00000000 Binary files a/docs/_pics/java-notes/network/8006a450-6c2f-498c-a928-c927f758b1d0.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/85c05fb1-5546-4c50-9221-21f231cdc8c5.jpg b/docs/_pics/java-notes/network/85c05fb1-5546-4c50-9221-21f231cdc8c5.jpg deleted file mode 100644 index 4b911193..00000000 Binary files a/docs/_pics/java-notes/network/85c05fb1-5546-4c50-9221-21f231cdc8c5.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/86e6a91d-a285-447a-9345-c5484b8d0c47.png b/docs/_pics/java-notes/network/86e6a91d-a285-447a-9345-c5484b8d0c47.png deleted file mode 100644 index 56f83eaf..00000000 Binary files a/docs/_pics/java-notes/network/86e6a91d-a285-447a-9345-c5484b8d0c47.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/910f613f-514f-4534-87dd-9b4699d59d31.png b/docs/_pics/java-notes/network/910f613f-514f-4534-87dd-9b4699d59d31.png deleted file mode 100644 index 28362d47..00000000 Binary files a/docs/_pics/java-notes/network/910f613f-514f-4534-87dd-9b4699d59d31.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/92ad9bae-7d02-43ba-8115-a9d6f530ca28.png b/docs/_pics/java-notes/network/92ad9bae-7d02-43ba-8115-a9d6f530ca28.png deleted file mode 100644 index 7b85c49a..00000000 Binary files a/docs/_pics/java-notes/network/92ad9bae-7d02-43ba-8115-a9d6f530ca28.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/9cd0ae20-4fb5-4017-a000-f7d3a0eb3529.png b/docs/_pics/java-notes/network/9cd0ae20-4fb5-4017-a000-f7d3a0eb3529.png deleted file mode 100644 index 49da824e..00000000 Binary files a/docs/_pics/java-notes/network/9cd0ae20-4fb5-4017-a000-f7d3a0eb3529.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/HTTP1_x_Connections.png b/docs/_pics/java-notes/network/HTTP1_x_Connections.png deleted file mode 100644 index d8c18a3c..00000000 Binary files a/docs/_pics/java-notes/network/HTTP1_x_Connections.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/HTTP_RequestMessageExample.png b/docs/_pics/java-notes/network/HTTP_RequestMessageExample.png deleted file mode 100644 index 8fd213cb..00000000 Binary files a/docs/_pics/java-notes/network/HTTP_RequestMessageExample.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/HTTP_ResponseMessageExample.png b/docs/_pics/java-notes/network/HTTP_ResponseMessageExample.png deleted file mode 100644 index 1adf26c5..00000000 Binary files a/docs/_pics/java-notes/network/HTTP_ResponseMessageExample.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/How-HTTPS-Works.png b/docs/_pics/java-notes/network/How-HTTPS-Works.png deleted file mode 100644 index c10605f7..00000000 Binary files a/docs/_pics/java-notes/network/How-HTTPS-Works.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/_u4E0B_u8F7D.png b/docs/_pics/java-notes/network/_u4E0B_u8F7D.png deleted file mode 100644 index 9da97330..00000000 Binary files a/docs/_pics/java-notes/network/_u4E0B_u8F7D.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/a314bb79-5b18-4e63-a976-3448bffa6f1b.png b/docs/_pics/java-notes/network/a314bb79-5b18-4e63-a976-3448bffa6f1b.png deleted file mode 100644 index 1a5a6474..00000000 Binary files a/docs/_pics/java-notes/network/a314bb79-5b18-4e63-a976-3448bffa6f1b.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/a3253deb-8d21-40a1-aae4-7d178e4aa319.jpg b/docs/_pics/java-notes/network/a3253deb-8d21-40a1-aae4-7d178e4aa319.jpg deleted file mode 100644 index 23258afa..00000000 Binary files a/docs/_pics/java-notes/network/a3253deb-8d21-40a1-aae4-7d178e4aa319.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/a6026bb4-3daf-439f-b1ec-a5a24e19d2fb.jpg b/docs/_pics/java-notes/network/a6026bb4-3daf-439f-b1ec-a5a24e19d2fb.jpg deleted file mode 100644 index 4ff577e2..00000000 Binary files a/docs/_pics/java-notes/network/a6026bb4-3daf-439f-b1ec-a5a24e19d2fb.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/a74b70ac-323a-4b31-b4d5-90569b8a944b.png b/docs/_pics/java-notes/network/a74b70ac-323a-4b31-b4d5-90569b8a944b.png deleted file mode 100644 index 3d686121..00000000 Binary files a/docs/_pics/java-notes/network/a74b70ac-323a-4b31-b4d5-90569b8a944b.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/aa29cc88-7256-4399-8c7f-3cf4a6489559.png b/docs/_pics/java-notes/network/aa29cc88-7256-4399-8c7f-3cf4a6489559.png deleted file mode 100644 index 9b93237e..00000000 Binary files a/docs/_pics/java-notes/network/aa29cc88-7256-4399-8c7f-3cf4a6489559.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/ac106e7e-489a-4082-abd9-dabebe48394c.jpg b/docs/_pics/java-notes/network/ac106e7e-489a-4082-abd9-dabebe48394c.jpg deleted file mode 100644 index 0d323411..00000000 Binary files a/docs/_pics/java-notes/network/ac106e7e-489a-4082-abd9-dabebe48394c.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/af198da1-2480-4043-b07f-a3b91a88b815.png b/docs/_pics/java-notes/network/af198da1-2480-4043-b07f-a3b91a88b815.png deleted file mode 100644 index 34d7a286..00000000 Binary files a/docs/_pics/java-notes/network/af198da1-2480-4043-b07f-a3b91a88b815.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/b54eeb16-0b0e-484c-be62-306f57c40d77.jpg b/docs/_pics/java-notes/network/b54eeb16-0b0e-484c-be62-306f57c40d77.jpg deleted file mode 100644 index 692a0357..00000000 Binary files a/docs/_pics/java-notes/network/b54eeb16-0b0e-484c-be62-306f57c40d77.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/b9d79a5a-e7af-499b-b989-f10483e71b8b.jpg b/docs/_pics/java-notes/network/b9d79a5a-e7af-499b-b989-f10483e71b8b.jpg deleted file mode 100644 index b7502831..00000000 Binary files a/docs/_pics/java-notes/network/b9d79a5a-e7af-499b-b989-f10483e71b8b.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/be5c2c61-86d2-4dba-a289-b48ea23219de.jpg b/docs/_pics/java-notes/network/be5c2c61-86d2-4dba-a289-b48ea23219de.jpg deleted file mode 100644 index a2965a7d..00000000 Binary files a/docs/_pics/java-notes/network/be5c2c61-86d2-4dba-a289-b48ea23219de.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/bf16c541-0717-473b-b75d-4115864f4fbf.jpg b/docs/_pics/java-notes/network/bf16c541-0717-473b-b75d-4115864f4fbf.jpg deleted file mode 100644 index a83ba275..00000000 Binary files a/docs/_pics/java-notes/network/bf16c541-0717-473b-b75d-4115864f4fbf.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/c3369072-c740-43b0-b276-202bd1d3960d.jpg b/docs/_pics/java-notes/network/c3369072-c740-43b0-b276-202bd1d3960d.jpg deleted file mode 100644 index 17a2e9bf..00000000 Binary files a/docs/_pics/java-notes/network/c3369072-c740-43b0-b276-202bd1d3960d.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/c4c14368-519c-4a0e-8331-0a553715e3e7.jpg b/docs/_pics/java-notes/network/c4c14368-519c-4a0e-8331-0a553715e3e7.jpg deleted file mode 100644 index 0cb4f0a0..00000000 Binary files a/docs/_pics/java-notes/network/c4c14368-519c-4a0e-8331-0a553715e3e7.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/c5022dd3-be22-4250-b9f6-38ae984a04d7.jpg b/docs/_pics/java-notes/network/c5022dd3-be22-4250-b9f6-38ae984a04d7.jpg deleted file mode 100644 index 3eb79406..00000000 Binary files a/docs/_pics/java-notes/network/c5022dd3-be22-4250-b9f6-38ae984a04d7.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/c9cfcd20-c901-435f-9a07-3e46830c359f.jpg b/docs/_pics/java-notes/network/c9cfcd20-c901-435f-9a07-3e46830c359f.jpg deleted file mode 100644 index 813b5142..00000000 Binary files a/docs/_pics/java-notes/network/c9cfcd20-c901-435f-9a07-3e46830c359f.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/cbf50eb8-22b4-4528-a2e7-d187143d57f7.png b/docs/_pics/java-notes/network/cbf50eb8-22b4-4528-a2e7-d187143d57f7.png deleted file mode 100644 index 27f2b742..00000000 Binary files a/docs/_pics/java-notes/network/cbf50eb8-22b4-4528-a2e7-d187143d57f7.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/d4c3a4a1-0846-46ec-9cc3-eaddfca71254.jpg b/docs/_pics/java-notes/network/d4c3a4a1-0846-46ec-9cc3-eaddfca71254.jpg deleted file mode 100644 index bbc7f102..00000000 Binary files a/docs/_pics/java-notes/network/d4c3a4a1-0846-46ec-9cc3-eaddfca71254.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/d4eef1e2-5703-4ca4-82ab-8dda93d6b81f.png b/docs/_pics/java-notes/network/d4eef1e2-5703-4ca4-82ab-8dda93d6b81f.png deleted file mode 100644 index 4f62e6f5..00000000 Binary files a/docs/_pics/java-notes/network/d4eef1e2-5703-4ca4-82ab-8dda93d6b81f.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg b/docs/_pics/java-notes/network/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg deleted file mode 100644 index 8090706b..00000000 Binary files a/docs/_pics/java-notes/network/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/ddcf2327-8d84-425d-8535-121a94bcb88d.jpg b/docs/_pics/java-notes/network/ddcf2327-8d84-425d-8535-121a94bcb88d.jpg deleted file mode 100644 index 2a95d92d..00000000 Binary files a/docs/_pics/java-notes/network/ddcf2327-8d84-425d-8535-121a94bcb88d.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/e3124763-f75e-46c3-ba82-341e6c98d862.jpg b/docs/_pics/java-notes/network/e3124763-f75e-46c3-ba82-341e6c98d862.jpg deleted file mode 100644 index 80643657..00000000 Binary files a/docs/_pics/java-notes/network/e3124763-f75e-46c3-ba82-341e6c98d862.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png b/docs/_pics/java-notes/network/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png deleted file mode 100644 index 105916c6..00000000 Binary files a/docs/_pics/java-notes/network/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/e92d0ebc-7d46-413b-aec1-34a39602f787.png b/docs/_pics/java-notes/network/e92d0ebc-7d46-413b-aec1-34a39602f787.png deleted file mode 100644 index 1090a779..00000000 Binary files a/docs/_pics/java-notes/network/e92d0ebc-7d46-413b-aec1-34a39602f787.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/ea5f3efe-d5e6-499b-b278-9e898af61257.jpg b/docs/_pics/java-notes/network/ea5f3efe-d5e6-499b-b278-9e898af61257.jpg deleted file mode 100644 index a07e736d..00000000 Binary files a/docs/_pics/java-notes/network/ea5f3efe-d5e6-499b-b278-9e898af61257.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/ed5522bb-3a60-481c-8654-43e7195a48fe.png b/docs/_pics/java-notes/network/ed5522bb-3a60-481c-8654-43e7195a48fe.png deleted file mode 100644 index 1c153a8a..00000000 Binary files a/docs/_pics/java-notes/network/ed5522bb-3a60-481c-8654-43e7195a48fe.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/f0a31c04-6e26-408c-8395-88f4e2ae928b.jpg b/docs/_pics/java-notes/network/f0a31c04-6e26-408c-8395-88f4e2ae928b.jpg deleted file mode 100644 index 99eb3168..00000000 Binary files a/docs/_pics/java-notes/network/f0a31c04-6e26-408c-8395-88f4e2ae928b.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/f61b5419-c94a-4df1-8d4d-aed9ae8cc6d5.png b/docs/_pics/java-notes/network/f61b5419-c94a-4df1-8d4d-aed9ae8cc6d5.png deleted file mode 100644 index dc0d4e34..00000000 Binary files a/docs/_pics/java-notes/network/f61b5419-c94a-4df1-8d4d-aed9ae8cc6d5.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/f87afe72-c2df-4c12-ac03-9b8d581a8af8.jpg b/docs/_pics/java-notes/network/f87afe72-c2df-4c12-ac03-9b8d581a8af8.jpg deleted file mode 100644 index 6a090993..00000000 Binary files a/docs/_pics/java-notes/network/f87afe72-c2df-4c12-ac03-9b8d581a8af8.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/fa2273c3-1b5f-48ce-8e8b-441a4116c1c4.jpg b/docs/_pics/java-notes/network/fa2273c3-1b5f-48ce-8e8b-441a4116c1c4.jpg deleted file mode 100644 index 42d3c743..00000000 Binary files a/docs/_pics/java-notes/network/fa2273c3-1b5f-48ce-8e8b-441a4116c1c4.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/net_1.png b/docs/_pics/java-notes/network/net_1.png deleted file mode 100644 index 819f735a..00000000 Binary files a/docs/_pics/java-notes/network/net_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/net_2.png b/docs/_pics/java-notes/network/net_2.png deleted file mode 100644 index e5939399..00000000 Binary files a/docs/_pics/java-notes/network/net_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/network-of-networks.gif b/docs/_pics/java-notes/network/network-of-networks.gif deleted file mode 100644 index 7473f913..00000000 Binary files a/docs/_pics/java-notes/network/network-of-networks.gif and /dev/null differ diff --git a/docs/_pics/java-notes/network/socket_tcp.png b/docs/_pics/java-notes/network/socket_tcp.png deleted file mode 100644 index 912c7e9b..00000000 Binary files a/docs/_pics/java-notes/network/socket_tcp.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/socket_tcp_struct.png b/docs/_pics/java-notes/network/socket_tcp_struct.png deleted file mode 100644 index 8faa8b2a..00000000 Binary files a/docs/_pics/java-notes/network/socket_tcp_struct.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/socket_udp.png b/docs/_pics/java-notes/network/socket_udp.png deleted file mode 100644 index 8d240886..00000000 Binary files a/docs/_pics/java-notes/network/socket_udp.png and /dev/null differ diff --git a/docs/_pics/java-notes/network/ssl-offloading.jpg b/docs/_pics/java-notes/network/ssl-offloading.jpg deleted file mode 100644 index 8f01a418..00000000 Binary files a/docs/_pics/java-notes/network/ssl-offloading.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/network/urlnuri.jpg b/docs/_pics/java-notes/network/urlnuri.jpg deleted file mode 100644 index be05f018..00000000 Binary files a/docs/_pics/java-notes/network/urlnuri.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/01_1.png b/docs/_pics/java-notes/oo/01_1.png deleted file mode 100644 index 19408656..00000000 Binary files a/docs/_pics/java-notes/oo/01_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/02_01.png b/docs/_pics/java-notes/oo/02_01.png deleted file mode 100644 index 74ef6cf0..00000000 Binary files a/docs/_pics/java-notes/oo/02_01.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/02_2.png b/docs/_pics/java-notes/oo/02_2.png deleted file mode 100644 index 3a21ee3f..00000000 Binary files a/docs/_pics/java-notes/oo/02_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/04_1.png b/docs/_pics/java-notes/oo/04_1.png deleted file mode 100644 index f8f072a8..00000000 Binary files a/docs/_pics/java-notes/oo/04_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/04_2.png b/docs/_pics/java-notes/oo/04_2.png deleted file mode 100644 index 6b24cfe7..00000000 Binary files a/docs/_pics/java-notes/oo/04_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/04_3.png b/docs/_pics/java-notes/oo/04_3.png deleted file mode 100644 index c3dba285..00000000 Binary files a/docs/_pics/java-notes/oo/04_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png b/docs/_pics/java-notes/oo/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png deleted file mode 100644 index 4d9e3e21..00000000 Binary files a/docs/_pics/java-notes/oo/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/0df5d84c-e7ca-4e3a-a688-bb8e68894467.png b/docs/_pics/java-notes/oo/0df5d84c-e7ca-4e3a-a688-bb8e68894467.png deleted file mode 100644 index 78a69978..00000000 Binary files a/docs/_pics/java-notes/oo/0df5d84c-e7ca-4e3a-a688-bb8e68894467.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/11236498-1417-46ce-a1b0-e10054256955.png b/docs/_pics/java-notes/oo/11236498-1417-46ce-a1b0-e10054256955.png deleted file mode 100644 index 19cd1543..00000000 Binary files a/docs/_pics/java-notes/oo/11236498-1417-46ce-a1b0-e10054256955.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/137c593d-0a9e-47b8-a9e6-b71f540b82dd.png b/docs/_pics/java-notes/oo/137c593d-0a9e-47b8-a9e6-b71f540b82dd.png deleted file mode 100644 index a5ac33ca..00000000 Binary files a/docs/_pics/java-notes/oo/137c593d-0a9e-47b8-a9e6-b71f540b82dd.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/13b0940e-d1d7-4b17-af4f-b70cb0a75e08.png b/docs/_pics/java-notes/oo/13b0940e-d1d7-4b17-af4f-b70cb0a75e08.png deleted file mode 100644 index 27f1c9f1..00000000 Binary files a/docs/_pics/java-notes/oo/13b0940e-d1d7-4b17-af4f-b70cb0a75e08.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/1818e141-8700-4026-99f7-900a545875f5.png b/docs/_pics/java-notes/oo/1818e141-8700-4026-99f7-900a545875f5.png deleted file mode 100644 index 1523ad79..00000000 Binary files a/docs/_pics/java-notes/oo/1818e141-8700-4026-99f7-900a545875f5.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/1fc969e4-0e7c-441b-b53c-01950d2f2be5.png b/docs/_pics/java-notes/oo/1fc969e4-0e7c-441b-b53c-01950d2f2be5.png deleted file mode 100644 index 0f7d6660..00000000 Binary files a/docs/_pics/java-notes/oo/1fc969e4-0e7c-441b-b53c-01950d2f2be5.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/396be981-3f2c-4fd9-8101-dbf9c841504b.jpg b/docs/_pics/java-notes/oo/396be981-3f2c-4fd9-8101-dbf9c841504b.jpg deleted file mode 100644 index 60c19f88..00000000 Binary files a/docs/_pics/java-notes/oo/396be981-3f2c-4fd9-8101-dbf9c841504b.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/3d5b828e-5c4d-48d8-a440-281e4a8e1c92.png b/docs/_pics/java-notes/oo/3d5b828e-5c4d-48d8-a440-281e4a8e1c92.png deleted file mode 100644 index 2f39530c..00000000 Binary files a/docs/_pics/java-notes/oo/3d5b828e-5c4d-48d8-a440-281e4a8e1c92.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/5359cbf5-5a79-4874-9b17-f23c53c2cb80.jpg b/docs/_pics/java-notes/oo/5359cbf5-5a79-4874-9b17-f23c53c2cb80.jpg deleted file mode 100644 index a449f38c..00000000 Binary files a/docs/_pics/java-notes/oo/5359cbf5-5a79-4874-9b17-f23c53c2cb80.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/562f2844-d77c-40e0-887a-28a7128abd42.png b/docs/_pics/java-notes/oo/562f2844-d77c-40e0-887a-28a7128abd42.png deleted file mode 100644 index b74f69b7..00000000 Binary files a/docs/_pics/java-notes/oo/562f2844-d77c-40e0-887a-28a7128abd42.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/691f11eb-31a7-46be-9de1-61f433c4b3c7.png b/docs/_pics/java-notes/oo/691f11eb-31a7-46be-9de1-61f433c4b3c7.png deleted file mode 100644 index b61e2174..00000000 Binary files a/docs/_pics/java-notes/oo/691f11eb-31a7-46be-9de1-61f433c4b3c7.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/77931a4b-72ba-4016-827d-84b9a6845a51.png b/docs/_pics/java-notes/oo/77931a4b-72ba-4016-827d-84b9a6845a51.png deleted file mode 100644 index 6f8a3c52..00000000 Binary files a/docs/_pics/java-notes/oo/77931a4b-72ba-4016-827d-84b9a6845a51.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/794239e3-4baf-4aad-92df-f02f59b2a6fe.png b/docs/_pics/java-notes/oo/794239e3-4baf-4aad-92df-f02f59b2a6fe.png deleted file mode 100644 index 7adddd91..00000000 Binary files a/docs/_pics/java-notes/oo/794239e3-4baf-4aad-92df-f02f59b2a6fe.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/7a3c6a30-c735-4edb-8115-337288a4f0f2.jpg b/docs/_pics/java-notes/oo/7a3c6a30-c735-4edb-8115-337288a4f0f2.jpg deleted file mode 100644 index 8d40765e..00000000 Binary files a/docs/_pics/java-notes/oo/7a3c6a30-c735-4edb-8115-337288a4f0f2.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/82cfda3b-b53b-4c89-9fdb-26dd2db0cd02.jpg b/docs/_pics/java-notes/oo/82cfda3b-b53b-4c89-9fdb-26dd2db0cd02.jpg deleted file mode 100644 index 2b510c43..00000000 Binary files a/docs/_pics/java-notes/oo/82cfda3b-b53b-4c89-9fdb-26dd2db0cd02.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/8668a3e1-c9c7-4fcb-98b2-a96a5d841579.png b/docs/_pics/java-notes/oo/8668a3e1-c9c7-4fcb-98b2-a96a5d841579.png deleted file mode 100644 index 9eda1deb..00000000 Binary files a/docs/_pics/java-notes/oo/8668a3e1-c9c7-4fcb-98b2-a96a5d841579.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/867e93eb-3161-4f39-b2d2-c0cd3788e194.png b/docs/_pics/java-notes/oo/867e93eb-3161-4f39-b2d2-c0cd3788e194.png deleted file mode 100644 index 26cb0153..00000000 Binary files a/docs/_pics/java-notes/oo/867e93eb-3161-4f39-b2d2-c0cd3788e194.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/LOun2W9134NxVugmbJPp15d4LalxC4O.png b/docs/_pics/java-notes/oo/LOun2W9134NxVugmbJPp15d4LalxC4O.png deleted file mode 100644 index 188460a5..00000000 Binary files a/docs/_pics/java-notes/oo/LOun2W9134NxVugmbJPp15d4LalxC4O.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILK8IatCoQn.png b/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILK8IatCoQn.png deleted file mode 100644 index da66da14..00000000 Binary files a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILK8IatCoQn.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmB2xEJyv.png b/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmB2xEJyv.png deleted file mode 100644 index e5ae5234..00000000 Binary files a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmB2xEJyv.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJ4ylIar.png b/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJ4ylIar.png deleted file mode 100644 index e31398b6..00000000 Binary files a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJ4ylIar.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJyrBBKh.png b/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJyrBBKh.png deleted file mode 100644 index 055d995e..00000000 Binary files a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmJyrBBKh.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmpiyjo2_.png b/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmpiyjo2_.png deleted file mode 100644 index 37f32c4c..00000000 Binary files a/docs/_pics/java-notes/oo/SoWkIImgAStDuU8goIp9ILLmpiyjo2_.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/a40661e4-1a71-46d2-a158-ff36f7fc3331.png b/docs/_pics/java-notes/oo/a40661e4-1a71-46d2-a158-ff36f7fc3331.png deleted file mode 100644 index e980a2e3..00000000 Binary files a/docs/_pics/java-notes/oo/a40661e4-1a71-46d2-a158-ff36f7fc3331.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/a6c20f60-5eba-427d-9413-352ada4b40fe.png b/docs/_pics/java-notes/oo/a6c20f60-5eba-427d-9413-352ada4b40fe.png deleted file mode 100644 index 11d36653..00000000 Binary files a/docs/_pics/java-notes/oo/a6c20f60-5eba-427d-9413-352ada4b40fe.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/ae1b27b8-bc13-42e7-ac12-a2242e125499.png b/docs/_pics/java-notes/oo/ae1b27b8-bc13-42e7-ac12-a2242e125499.png deleted file mode 100644 index 27977740..00000000 Binary files a/docs/_pics/java-notes/oo/ae1b27b8-bc13-42e7-ac12-a2242e125499.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/b0f61ac2-a4b6-4042-9cf0-ccf4238c1ff7.png b/docs/_pics/java-notes/oo/b0f61ac2-a4b6-4042-9cf0-ccf4238c1ff7.png deleted file mode 100644 index 73dad483..00000000 Binary files a/docs/_pics/java-notes/oo/b0f61ac2-a4b6-4042-9cf0-ccf4238c1ff7.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/b1df9732-86ce-4d69-9f06-fba1db7b3b5a.jpg b/docs/_pics/java-notes/oo/b1df9732-86ce-4d69-9f06-fba1db7b3b5a.jpg deleted file mode 100644 index a71d167e..00000000 Binary files a/docs/_pics/java-notes/oo/b1df9732-86ce-4d69-9f06-fba1db7b3b5a.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/c2cbf5d2-82af-4c78-bd43-495da5adf55f.png b/docs/_pics/java-notes/oo/c2cbf5d2-82af-4c78-bd43-495da5adf55f.png deleted file mode 100644 index 70ecc3ec..00000000 Binary files a/docs/_pics/java-notes/oo/c2cbf5d2-82af-4c78-bd43-495da5adf55f.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/c3c1c0e8-3a78-4426-961f-b46dd0879dd8.png b/docs/_pics/java-notes/oo/c3c1c0e8-3a78-4426-961f-b46dd0879dd8.png deleted file mode 100644 index 48e980fc..00000000 Binary files a/docs/_pics/java-notes/oo/c3c1c0e8-3a78-4426-961f-b46dd0879dd8.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/c5085437-54df-4304-b62d-44b961711ba7.png b/docs/_pics/java-notes/oo/c5085437-54df-4304-b62d-44b961711ba7.png deleted file mode 100644 index 36c948aa..00000000 Binary files a/docs/_pics/java-notes/oo/c5085437-54df-4304-b62d-44b961711ba7.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/c79da808-0f28-4a36-bc04-33ccc5b83c13.png b/docs/_pics/java-notes/oo/c79da808-0f28-4a36-bc04-33ccc5b83c13.png deleted file mode 100644 index 91e2c144..00000000 Binary files a/docs/_pics/java-notes/oo/c79da808-0f28-4a36-bc04-33ccc5b83c13.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/c9cfd600-bc91-4f3a-9f99-b42f88a5bb24.jpg b/docs/_pics/java-notes/oo/c9cfd600-bc91-4f3a-9f99-b42f88a5bb24.jpg deleted file mode 100644 index fa7ce3ae..00000000 Binary files a/docs/_pics/java-notes/oo/c9cfd600-bc91-4f3a-9f99-b42f88a5bb24.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/d0afdd23-c9a5-4d1c-9b3d-404bff3bd0d1.png b/docs/_pics/java-notes/oo/d0afdd23-c9a5-4d1c-9b3d-404bff3bd0d1.png deleted file mode 100644 index 58ff84fe..00000000 Binary files a/docs/_pics/java-notes/oo/d0afdd23-c9a5-4d1c-9b3d-404bff3bd0d1.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/d52270b4-9097-4667-9f18-f405fc661c99.png b/docs/_pics/java-notes/oo/d52270b4-9097-4667-9f18-f405fc661c99.png deleted file mode 100644 index 347fe316..00000000 Binary files a/docs/_pics/java-notes/oo/d52270b4-9097-4667-9f18-f405fc661c99.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/dd3b289c-d90e-44a6-a44c-4880517eb1de.png b/docs/_pics/java-notes/oo/dd3b289c-d90e-44a6-a44c-4880517eb1de.png deleted file mode 100644 index 51055a2b..00000000 Binary files a/docs/_pics/java-notes/oo/dd3b289c-d90e-44a6-a44c-4880517eb1de.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/e6bded8e-41a0-489a-88a6-638e88ab7666.jpg b/docs/_pics/java-notes/oo/e6bded8e-41a0-489a-88a6-638e88ab7666.jpg deleted file mode 100644 index f4aa12a0..00000000 Binary files a/docs/_pics/java-notes/oo/e6bded8e-41a0-489a-88a6-638e88ab7666.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/oo/ec923dc7-864c-47b0-a411-1f2c48d084de.png b/docs/_pics/java-notes/oo/ec923dc7-864c-47b0-a411-1f2c48d084de.png deleted file mode 100644 index 007e9646..00000000 Binary files a/docs/_pics/java-notes/oo/ec923dc7-864c-47b0-a411-1f2c48d084de.png and /dev/null differ diff --git a/docs/_pics/java-notes/oo/f9978fa6-9f49-4a0f-8540-02d269ac448f.png b/docs/_pics/java-notes/oo/f9978fa6-9f49-4a0f-8540-02d269ac448f.png deleted file mode 100644 index 7da6d4b2..00000000 Binary files a/docs/_pics/java-notes/oo/f9978fa6-9f49-4a0f-8540-02d269ac448f.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/014fbc4d-d873-4a12-b160-867ddaed9807.jpg b/docs/_pics/java-notes/os/014fbc4d-d873-4a12-b160-867ddaed9807.jpg deleted file mode 100644 index 39c003ce..00000000 Binary files a/docs/_pics/java-notes/os/014fbc4d-d873-4a12-b160-867ddaed9807.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/042cf928-3c8e-4815-ae9c-f2780202c68f.png b/docs/_pics/java-notes/os/042cf928-3c8e-4815-ae9c-f2780202c68f.png deleted file mode 100644 index 57d8c810..00000000 Binary files a/docs/_pics/java-notes/os/042cf928-3c8e-4815-ae9c-f2780202c68f.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/075e1977-7846-4928-96c8-bb5b0268693c.jpg b/docs/_pics/java-notes/os/075e1977-7846-4928-96c8-bb5b0268693c.jpg deleted file mode 100644 index b8b100a0..00000000 Binary files a/docs/_pics/java-notes/os/075e1977-7846-4928-96c8-bb5b0268693c.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/22de0538-7c6e-4365-bd3b-8ce3c5900216.png b/docs/_pics/java-notes/os/22de0538-7c6e-4365-bd3b-8ce3c5900216.png deleted file mode 100644 index 8d7dc098..00000000 Binary files a/docs/_pics/java-notes/os/22de0538-7c6e-4365-bd3b-8ce3c5900216.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/271ce08f-c124-475f-b490-be44fedc6d2e.png b/docs/_pics/java-notes/os/271ce08f-c124-475f-b490-be44fedc6d2e.png deleted file mode 100644 index 8de6367b..00000000 Binary files a/docs/_pics/java-notes/os/271ce08f-c124-475f-b490-be44fedc6d2e.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/2_14_microkernelArchitecture.jpg b/docs/_pics/java-notes/os/2_14_microkernelArchitecture.jpg deleted file mode 100644 index 21c2a58f..00000000 Binary files a/docs/_pics/java-notes/os/2_14_microkernelArchitecture.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/2ac50b81-d92a-4401-b9ec-f2113ecc3076.png b/docs/_pics/java-notes/os/2ac50b81-d92a-4401-b9ec-f2113ecc3076.png deleted file mode 100644 index 173ce970..00000000 Binary files a/docs/_pics/java-notes/os/2ac50b81-d92a-4401-b9ec-f2113ecc3076.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/3cd630ea-017c-488d-ad1d-732b4efeddf5.png b/docs/_pics/java-notes/os/3cd630ea-017c-488d-ad1d-732b4efeddf5.png deleted file mode 100644 index 9dc77733..00000000 Binary files a/docs/_pics/java-notes/os/3cd630ea-017c-488d-ad1d-732b4efeddf5.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg b/docs/_pics/java-notes/os/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg deleted file mode 100644 index f6ddd2c2..00000000 Binary files a/docs/_pics/java-notes/os/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/4e2485e4-34bd-4967-9f02-0c093b797aaa.png b/docs/_pics/java-notes/os/4e2485e4-34bd-4967-9f02-0c093b797aaa.png deleted file mode 100644 index a5643118..00000000 Binary files a/docs/_pics/java-notes/os/4e2485e4-34bd-4967-9f02-0c093b797aaa.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/50831a6f-2777-46ea-a571-29f23c85cc21.jpg b/docs/_pics/java-notes/os/50831a6f-2777-46ea-a571-29f23c85cc21.jpg deleted file mode 100644 index 4a3f798b..00000000 Binary files a/docs/_pics/java-notes/os/50831a6f-2777-46ea-a571-29f23c85cc21.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/53cd9ade-b0a6-4399-b4de-7f1fbd06cdfb.png b/docs/_pics/java-notes/os/53cd9ade-b0a6-4399-b4de-7f1fbd06cdfb.png deleted file mode 100644 index 2666f9c2..00000000 Binary files a/docs/_pics/java-notes/os/53cd9ade-b0a6-4399-b4de-7f1fbd06cdfb.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/5942debd-fc00-477a-b390-7c5692cc8070.jpg b/docs/_pics/java-notes/os/5942debd-fc00-477a-b390-7c5692cc8070.jpg deleted file mode 100644 index 62b39e4b..00000000 Binary files a/docs/_pics/java-notes/os/5942debd-fc00-477a-b390-7c5692cc8070.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/5f5ef0b6-98ea-497c-a007-f6c55288eab1.png b/docs/_pics/java-notes/os/5f5ef0b6-98ea-497c-a007-f6c55288eab1.png deleted file mode 100644 index a3ea0a24..00000000 Binary files a/docs/_pics/java-notes/os/5f5ef0b6-98ea-497c-a007-f6c55288eab1.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png b/docs/_pics/java-notes/os/62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png deleted file mode 100644 index 3a41cdce..00000000 Binary files a/docs/_pics/java-notes/os/62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/658fc5e7-79c0-4247-9445-d69bf194c539.png b/docs/_pics/java-notes/os/658fc5e7-79c0-4247-9445-d69bf194c539.png deleted file mode 100644 index f488859e..00000000 Binary files a/docs/_pics/java-notes/os/658fc5e7-79c0-4247-9445-d69bf194c539.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/6729baa0-57d7-4817-b3aa-518cbccf824c.jpg b/docs/_pics/java-notes/os/6729baa0-57d7-4817-b3aa-518cbccf824c.jpg deleted file mode 100644 index 7035f001..00000000 Binary files a/docs/_pics/java-notes/os/6729baa0-57d7-4817-b3aa-518cbccf824c.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/76a49594323247f21c9b3a69945445ee.png b/docs/_pics/java-notes/os/76a49594323247f21c9b3a69945445ee.png deleted file mode 100644 index 788ba0b1..00000000 Binary files a/docs/_pics/java-notes/os/76a49594323247f21c9b3a69945445ee.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg b/docs/_pics/java-notes/os/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg deleted file mode 100644 index 642aba6b..00000000 Binary files a/docs/_pics/java-notes/os/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/7b281b1e-0595-402b-ae35-8c91084c33c1.png b/docs/_pics/java-notes/os/7b281b1e-0595-402b-ae35-8c91084c33c1.png deleted file mode 100644 index 9308ecb6..00000000 Binary files a/docs/_pics/java-notes/os/7b281b1e-0595-402b-ae35-8c91084c33c1.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/83185315-793a-453a-a927-5e8d92b5c0ef.jpg b/docs/_pics/java-notes/os/83185315-793a-453a-a927-5e8d92b5c0ef.jpg deleted file mode 100644 index cb83edea..00000000 Binary files a/docs/_pics/java-notes/os/83185315-793a-453a-a927-5e8d92b5c0ef.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/8c662999-c16c-481c-9f40-1fdba5bc9167.png b/docs/_pics/java-notes/os/8c662999-c16c-481c-9f40-1fdba5bc9167.png deleted file mode 100644 index ff810e91..00000000 Binary files a/docs/_pics/java-notes/os/8c662999-c16c-481c-9f40-1fdba5bc9167.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/924914c0-660c-4e4a-bbc0-1df1146e7516.jpg b/docs/_pics/java-notes/os/924914c0-660c-4e4a-bbc0-1df1146e7516.jpg deleted file mode 100644 index 5bb29598..00000000 Binary files a/docs/_pics/java-notes/os/924914c0-660c-4e4a-bbc0-1df1146e7516.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/BSD_disk.png b/docs/_pics/java-notes/os/BSD_disk.png deleted file mode 100644 index 48b0e0e8..00000000 Binary files a/docs/_pics/java-notes/os/BSD_disk.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/ProcessState.png b/docs/_pics/java-notes/os/ProcessState.png deleted file mode 100644 index 39269579..00000000 Binary files a/docs/_pics/java-notes/os/ProcessState.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/a6ac2b08-3861-4e85-baa8-382287bfee9f.png b/docs/_pics/java-notes/os/a6ac2b08-3861-4e85-baa8-382287bfee9f.png deleted file mode 100644 index 26b0bd03..00000000 Binary files a/docs/_pics/java-notes/os/a6ac2b08-3861-4e85-baa8-382287bfee9f.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg b/docs/_pics/java-notes/os/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg deleted file mode 100644 index 67b2264d..00000000 Binary files a/docs/_pics/java-notes/os/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/b1fa0453-a4b0-4eae-a352-48acca8fff74.png b/docs/_pics/java-notes/os/b1fa0453-a4b0-4eae-a352-48acca8fff74.png deleted file mode 100644 index 842b2f6c..00000000 Binary files a/docs/_pics/java-notes/os/b1fa0453-a4b0-4eae-a352-48acca8fff74.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg b/docs/_pics/java-notes/os/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg deleted file mode 100644 index a3e1a656..00000000 Binary files a/docs/_pics/java-notes/os/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/b8081c84-62c4-4019-b3ee-4bd0e443d647.jpg b/docs/_pics/java-notes/os/b8081c84-62c4-4019-b3ee-4bd0e443d647.jpg deleted file mode 100644 index 58fb0a05..00000000 Binary files a/docs/_pics/java-notes/os/b8081c84-62c4-4019-b3ee-4bd0e443d647.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/c037c901-7eae-4e31-a1e4-9d41329e5c3e.png b/docs/_pics/java-notes/os/c037c901-7eae-4e31-a1e4-9d41329e5c3e.png deleted file mode 100644 index 9e2feb27..00000000 Binary files a/docs/_pics/java-notes/os/c037c901-7eae-4e31-a1e4-9d41329e5c3e.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/cf4386a1-58c9-4eca-a17f-e12b1e9770eb.png b/docs/_pics/java-notes/os/cf4386a1-58c9-4eca-a17f-e12b1e9770eb.png deleted file mode 100644 index 9b9f3838..00000000 Binary files a/docs/_pics/java-notes/os/cf4386a1-58c9-4eca-a17f-e12b1e9770eb.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png b/docs/_pics/java-notes/os/d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png deleted file mode 100644 index cc971351..00000000 Binary files a/docs/_pics/java-notes/os/d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png b/docs/_pics/java-notes/os/e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png deleted file mode 100644 index b4c565fb..00000000 Binary files a/docs/_pics/java-notes/os/e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png b/docs/_pics/java-notes/os/e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png deleted file mode 100644 index bffe7520..00000000 Binary files a/docs/_pics/java-notes/os/e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/eb859228-c0f2-4bce-910d-d9f76929352b.png b/docs/_pics/java-notes/os/eb859228-c0f2-4bce-910d-d9f76929352b.png deleted file mode 100644 index 7104f020..00000000 Binary files a/docs/_pics/java-notes/os/eb859228-c0f2-4bce-910d-d9f76929352b.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png b/docs/_pics/java-notes/os/ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png deleted file mode 100644 index 25ed7497..00000000 Binary files a/docs/_pics/java-notes/os/ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/ed523051-608f-4c3f-b343-383e2d194470.png b/docs/_pics/java-notes/os/ed523051-608f-4c3f-b343-383e2d194470.png deleted file mode 100644 index 1f703e2f..00000000 Binary files a/docs/_pics/java-notes/os/ed523051-608f-4c3f-b343-383e2d194470.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/f0574025-c514-49f5-a591-6d6a71f271f7.jpg b/docs/_pics/java-notes/os/f0574025-c514-49f5-a591-6d6a71f271f7.jpg deleted file mode 100644 index 66a2ecbe..00000000 Binary files a/docs/_pics/java-notes/os/f0574025-c514-49f5-a591-6d6a71f271f7.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/f900f266-a323-42b2-bc43-218fdb8811a8.jpg b/docs/_pics/java-notes/os/f900f266-a323-42b2-bc43-218fdb8811a8.jpg deleted file mode 100644 index 95b92d60..00000000 Binary files a/docs/_pics/java-notes/os/f900f266-a323-42b2-bc43-218fdb8811a8.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/f9f2a16b-4843-44d1-9759-c745772e9bcf.jpg b/docs/_pics/java-notes/os/f9f2a16b-4843-44d1-9759-c745772e9bcf.jpg deleted file mode 100644 index b6a0ba79..00000000 Binary files a/docs/_pics/java-notes/os/f9f2a16b-4843-44d1-9759-c745772e9bcf.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/flow.png b/docs/_pics/java-notes/os/flow.png deleted file mode 100644 index aa0492a4..00000000 Binary files a/docs/_pics/java-notes/os/flow.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/inode_with_signatures.jpg b/docs/_pics/java-notes/os/inode_with_signatures.jpg deleted file mode 100644 index 518ba5ac..00000000 Binary files a/docs/_pics/java-notes/os/inode_with_signatures.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/os/linux-filesystem.png b/docs/_pics/java-notes/os/linux-filesystem.png deleted file mode 100644 index ae965295..00000000 Binary files a/docs/_pics/java-notes/os/linux-filesystem.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/linux_1.png b/docs/_pics/java-notes/os/linux_1.png deleted file mode 100644 index 592d2095..00000000 Binary files a/docs/_pics/java-notes/os/linux_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/os/tGPV0.png b/docs/_pics/java-notes/os/tGPV0.png deleted file mode 100644 index 89fb7bfe..00000000 Binary files a/docs/_pics/java-notes/os/tGPV0.png and /dev/null differ diff --git a/docs/_pics/java-notes/sfatety/safety_1.png b/docs/_pics/java-notes/sfatety/safety_1.png deleted file mode 100644 index c5a218cc..00000000 Binary files a/docs/_pics/java-notes/sfatety/safety_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/sfatety/safety_2.png b/docs/_pics/java-notes/sfatety/safety_2.png deleted file mode 100644 index a00616a9..00000000 Binary files a/docs/_pics/java-notes/sfatety/safety_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/sfatety/safety_3.png b/docs/_pics/java-notes/sfatety/safety_3.png deleted file mode 100644 index feadf5df..00000000 Binary files a/docs/_pics/java-notes/sfatety/safety_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/sfatety/safety_4.png b/docs/_pics/java-notes/sfatety/safety_4.png deleted file mode 100644 index 0af5922c..00000000 Binary files a/docs/_pics/java-notes/sfatety/safety_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/01_1.png b/docs/_pics/java-notes/sort/01_1.png deleted file mode 100644 index 3b05b25b..00000000 Binary files a/docs/_pics/java-notes/sort/01_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/01_2.png b/docs/_pics/java-notes/sort/01_2.png deleted file mode 100644 index c4592305..00000000 Binary files a/docs/_pics/java-notes/sort/01_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/01_3.png b/docs/_pics/java-notes/sort/01_3.png deleted file mode 100644 index fc0999f9..00000000 Binary files a/docs/_pics/java-notes/sort/01_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/02_1.png b/docs/_pics/java-notes/sort/02_1.png deleted file mode 100644 index 79105257..00000000 Binary files a/docs/_pics/java-notes/sort/02_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/02_2.png b/docs/_pics/java-notes/sort/02_2.png deleted file mode 100644 index e8a69bff..00000000 Binary files a/docs/_pics/java-notes/sort/02_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/02_3.png b/docs/_pics/java-notes/sort/02_3.png deleted file mode 100644 index 86e2294f..00000000 Binary files a/docs/_pics/java-notes/sort/02_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_1.png b/docs/_pics/java-notes/sort/03_1.png deleted file mode 100644 index 77868686..00000000 Binary files a/docs/_pics/java-notes/sort/03_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_2.png b/docs/_pics/java-notes/sort/03_2.png deleted file mode 100644 index 6e8383f3..00000000 Binary files a/docs/_pics/java-notes/sort/03_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_3.png b/docs/_pics/java-notes/sort/03_3.png deleted file mode 100644 index 5299728f..00000000 Binary files a/docs/_pics/java-notes/sort/03_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_4.png b/docs/_pics/java-notes/sort/03_4.png deleted file mode 100644 index dc44da3d..00000000 Binary files a/docs/_pics/java-notes/sort/03_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_5.png b/docs/_pics/java-notes/sort/03_5.png deleted file mode 100644 index d49b1727..00000000 Binary files a/docs/_pics/java-notes/sort/03_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/03_6.png b/docs/_pics/java-notes/sort/03_6.png deleted file mode 100644 index 3d5adabd..00000000 Binary files a/docs/_pics/java-notes/sort/03_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/04_1.gif b/docs/_pics/java-notes/sort/04_1.gif deleted file mode 100644 index 2a556955..00000000 Binary files a/docs/_pics/java-notes/sort/04_1.gif and /dev/null differ diff --git a/docs/_pics/java-notes/sort/05_1.png b/docs/_pics/java-notes/sort/05_1.png deleted file mode 100644 index 9d720f4f..00000000 Binary files a/docs/_pics/java-notes/sort/05_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/sort/06_1.png b/docs/_pics/java-notes/sort/06_1.png deleted file mode 100644 index 325d983e..00000000 Binary files a/docs/_pics/java-notes/sort/06_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/01_1.png b/docs/_pics/java-notes/spring/01_1.png deleted file mode 100644 index 1bcb8af0..00000000 Binary files a/docs/_pics/java-notes/spring/01_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/01_2.png b/docs/_pics/java-notes/spring/01_2.png deleted file mode 100644 index 58360fb4..00000000 Binary files a/docs/_pics/java-notes/spring/01_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/02_1.png b/docs/_pics/java-notes/spring/02_1.png deleted file mode 100644 index c4748cda..00000000 Binary files a/docs/_pics/java-notes/spring/02_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/03_1.png b/docs/_pics/java-notes/spring/03_1.png deleted file mode 100644 index 75e9c190..00000000 Binary files a/docs/_pics/java-notes/spring/03_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/03_2.png b/docs/_pics/java-notes/spring/03_2.png deleted file mode 100644 index 21fb3e30..00000000 Binary files a/docs/_pics/java-notes/spring/03_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/03_3.png b/docs/_pics/java-notes/spring/03_3.png deleted file mode 100644 index 81b2ba88..00000000 Binary files a/docs/_pics/java-notes/spring/03_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/03_4.png b/docs/_pics/java-notes/spring/03_4.png deleted file mode 100644 index e91de3b9..00000000 Binary files a/docs/_pics/java-notes/spring/03_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/03_5.png b/docs/_pics/java-notes/spring/03_5.png deleted file mode 100644 index 59f9aa87..00000000 Binary files a/docs/_pics/java-notes/spring/03_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/05_1.jpg b/docs/_pics/java-notes/spring/05_1.jpg deleted file mode 100644 index 16f76ddb..00000000 Binary files a/docs/_pics/java-notes/spring/05_1.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/spring/06_1.jpg b/docs/_pics/java-notes/spring/06_1.jpg deleted file mode 100644 index 19019d55..00000000 Binary files a/docs/_pics/java-notes/spring/06_1.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/spring/06_2.jpg b/docs/_pics/java-notes/spring/06_2.jpg deleted file mode 100644 index 202d1bf2..00000000 Binary files a/docs/_pics/java-notes/spring/06_2.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/spring/SpringMCVInterview_00.jpg b/docs/_pics/java-notes/spring/SpringMCVInterview_00.jpg deleted file mode 100644 index 3f21b38b..00000000 Binary files a/docs/_pics/java-notes/spring/SpringMCVInterview_00.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_1.png b/docs/_pics/java-notes/spring/ioc_1.png deleted file mode 100644 index 2c3f84df..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_11.png b/docs/_pics/java-notes/spring/ioc_11.png deleted file mode 100644 index 7fb5fa81..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_11.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_12.png b/docs/_pics/java-notes/spring/ioc_12.png deleted file mode 100644 index 3ada545f..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_12.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_13.png b/docs/_pics/java-notes/spring/ioc_13.png deleted file mode 100644 index 69570fa5..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_13.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_14.png b/docs/_pics/java-notes/spring/ioc_14.png deleted file mode 100644 index 048cf914..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_14.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_15.png b/docs/_pics/java-notes/spring/ioc_15.png deleted file mode 100644 index 3f3b6b1e..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_15.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_16.png b/docs/_pics/java-notes/spring/ioc_16.png deleted file mode 100644 index d6b807fb..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_16.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_17.png b/docs/_pics/java-notes/spring/ioc_17.png deleted file mode 100644 index 29fb311d..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_17.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_2.png b/docs/_pics/java-notes/spring/ioc_2.png deleted file mode 100644 index d9073ab8..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_3.png b/docs/_pics/java-notes/spring/ioc_3.png deleted file mode 100644 index 8dadc8eb..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_3.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_4.png b/docs/_pics/java-notes/spring/ioc_4.png deleted file mode 100644 index ce1f0a84..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_4.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_5.png b/docs/_pics/java-notes/spring/ioc_5.png deleted file mode 100644 index 29a7f660..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_5.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_6.png b/docs/_pics/java-notes/spring/ioc_6.png deleted file mode 100644 index 5a4c4332..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_6.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_7.png b/docs/_pics/java-notes/spring/ioc_7.png deleted file mode 100644 index 84cbfe90..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_7.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_8.png b/docs/_pics/java-notes/spring/ioc_8.png deleted file mode 100644 index aa0aaba8..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_8.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/ioc_9.png b/docs/_pics/java-notes/spring/ioc_9.png deleted file mode 100644 index 3032221e..00000000 Binary files a/docs/_pics/java-notes/spring/ioc_9.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/spring_1.gif b/docs/_pics/java-notes/spring/spring_1.gif deleted file mode 100644 index 2671173e..00000000 Binary files a/docs/_pics/java-notes/spring/spring_1.gif and /dev/null differ diff --git a/docs/_pics/java-notes/spring/spring_1.png b/docs/_pics/java-notes/spring/spring_1.png deleted file mode 100644 index 03d3d768..00000000 Binary files a/docs/_pics/java-notes/spring/spring_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/spring_2.png b/docs/_pics/java-notes/spring/spring_2.png deleted file mode 100644 index 08ef4ee4..00000000 Binary files a/docs/_pics/java-notes/spring/spring_2.png and /dev/null differ diff --git a/docs/_pics/java-notes/spring/springmvc_1.png b/docs/_pics/java-notes/spring/springmvc_1.png deleted file mode 100644 index 8891be88..00000000 Binary files a/docs/_pics/java-notes/spring/springmvc_1.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/04f41228-375d-4b7d-bfef-738c5a7c8f07.jpg b/docs/_pics/java-notes/systemDesign/04f41228-375d-4b7d-bfef-738c5a7c8f07.jpg deleted file mode 100644 index 17eb93b6..00000000 Binary files a/docs/_pics/java-notes/systemDesign/04f41228-375d-4b7d-bfef-738c5a7c8f07.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/0b587744-c0a8-46f2-8d72-e8f070d67b4b.jpg b/docs/_pics/java-notes/systemDesign/0b587744-c0a8-46f2-8d72-e8f070d67b4b.jpg deleted file mode 100644 index 7b88e7a0..00000000 Binary files a/docs/_pics/java-notes/systemDesign/0b587744-c0a8-46f2-8d72-e8f070d67b4b.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/0ee0f61b-c782-441e-bf34-665650198ae0.jpg b/docs/_pics/java-notes/systemDesign/0ee0f61b-c782-441e-bf34-665650198ae0.jpg deleted file mode 100644 index f3e7163b..00000000 Binary files a/docs/_pics/java-notes/systemDesign/0ee0f61b-c782-441e-bf34-665650198ae0.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/10.gif b/docs/_pics/java-notes/systemDesign/10.gif deleted file mode 100644 index d52a911e..00000000 Binary files a/docs/_pics/java-notes/systemDesign/10.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/11.gif b/docs/_pics/java-notes/systemDesign/11.gif deleted file mode 100644 index 5d9c6f00..00000000 Binary files a/docs/_pics/java-notes/systemDesign/11.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521118015898.gif b/docs/_pics/java-notes/systemDesign/111521118015898.gif deleted file mode 100644 index 5c31da1d..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521118015898.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521118445538.gif b/docs/_pics/java-notes/systemDesign/111521118445538.gif deleted file mode 100644 index 323d129c..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521118445538.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521118483039.gif b/docs/_pics/java-notes/systemDesign/111521118483039.gif deleted file mode 100644 index a81124dd..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521118483039.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521118640738.gif b/docs/_pics/java-notes/systemDesign/111521118640738.gif deleted file mode 100644 index 7a7b05a9..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521118640738.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521119203347.gif b/docs/_pics/java-notes/systemDesign/111521119203347.gif deleted file mode 100644 index 37cdb5a5..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521119203347.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/111521119368714.gif b/docs/_pics/java-notes/systemDesign/111521119368714.gif deleted file mode 100644 index 216c3033..00000000 Binary files a/docs/_pics/java-notes/systemDesign/111521119368714.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/15313ed8-a520-4799-a300-2b6b36be314f.jpg b/docs/_pics/java-notes/systemDesign/15313ed8-a520-4799-a300-2b6b36be314f.jpg deleted file mode 100644 index cbba7f36..00000000 Binary files a/docs/_pics/java-notes/systemDesign/15313ed8-a520-4799-a300-2b6b36be314f.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/1a9977e4-2f5c-49a6-aec9-f3027c9f46a7.png b/docs/_pics/java-notes/systemDesign/1a9977e4-2f5c-49a6-aec9-f3027c9f46a7.png deleted file mode 100644 index 590a4299..00000000 Binary files a/docs/_pics/java-notes/systemDesign/1a9977e4-2f5c-49a6-aec9-f3027c9f46a7.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg b/docs/_pics/java-notes/systemDesign/1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg deleted file mode 100644 index e4f0f3ac..00000000 Binary files a/docs/_pics/java-notes/systemDesign/1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/2018040302.jpg b/docs/_pics/java-notes/systemDesign/2018040302.jpg deleted file mode 100644 index 27daefae..00000000 Binary files a/docs/_pics/java-notes/systemDesign/2018040302.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/211c60d4-75ca-4acd-8a4f-171458ed58b4.jpg b/docs/_pics/java-notes/systemDesign/211c60d4-75ca-4acd-8a4f-171458ed58b4.jpg deleted file mode 100644 index efb47ffc..00000000 Binary files a/docs/_pics/java-notes/systemDesign/211c60d4-75ca-4acd-8a4f-171458ed58b4.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/2766d04f-7dad-42e4-99d1-60682c9d5c61.jpg b/docs/_pics/java-notes/systemDesign/2766d04f-7dad-42e4-99d1-60682c9d5c61.jpg deleted file mode 100644 index f9a9489b..00000000 Binary files a/docs/_pics/java-notes/systemDesign/2766d04f-7dad-42e4-99d1-60682c9d5c61.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/2991c772-fb1c-4051-a9c7-932b68e76bd7.jpg b/docs/_pics/java-notes/systemDesign/2991c772-fb1c-4051-a9c7-932b68e76bd7.jpg deleted file mode 100644 index d99eb3a7..00000000 Binary files a/docs/_pics/java-notes/systemDesign/2991c772-fb1c-4051-a9c7-932b68e76bd7.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg b/docs/_pics/java-notes/systemDesign/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg deleted file mode 100644 index 983ddd70..00000000 Binary files a/docs/_pics/java-notes/systemDesign/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/31d99967-1171-448e-8531-bccf5c14cffe.jpg b/docs/_pics/java-notes/systemDesign/31d99967-1171-448e-8531-bccf5c14cffe.jpg deleted file mode 100644 index 61e00649..00000000 Binary files a/docs/_pics/java-notes/systemDesign/31d99967-1171-448e-8531-bccf5c14cffe.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/3b0d1aa8-d0e0-46c2-8fd1-736bf08a11aa.jpg b/docs/_pics/java-notes/systemDesign/3b0d1aa8-d0e0-46c2-8fd1-736bf08a11aa.jpg deleted file mode 100644 index f7e9f145..00000000 Binary files a/docs/_pics/java-notes/systemDesign/3b0d1aa8-d0e0-46c2-8fd1-736bf08a11aa.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/44edefb7-4b58-4519-b8ee-4aca01697b78.jpg b/docs/_pics/java-notes/systemDesign/44edefb7-4b58-4519-b8ee-4aca01697b78.jpg deleted file mode 100644 index 32d0f3d2..00000000 Binary files a/docs/_pics/java-notes/systemDesign/44edefb7-4b58-4519-b8ee-4aca01697b78.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/66402828-fb2b-418f-83f6-82153491bcfe.jpg b/docs/_pics/java-notes/systemDesign/66402828-fb2b-418f-83f6-82153491bcfe.jpg deleted file mode 100644 index fc86a236..00000000 Binary files a/docs/_pics/java-notes/systemDesign/66402828-fb2b-418f-83f6-82153491bcfe.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/685a692f-8f76-4cac-baac-b68e2df9a30f.jpg b/docs/_pics/java-notes/systemDesign/685a692f-8f76-4cac-baac-b68e2df9a30f.jpg deleted file mode 100644 index a1d12d17..00000000 Binary files a/docs/_pics/java-notes/systemDesign/685a692f-8f76-4cac-baac-b68e2df9a30f.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg b/docs/_pics/java-notes/systemDesign/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg deleted file mode 100644 index d82f46eb..00000000 Binary files a/docs/_pics/java-notes/systemDesign/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/7.gif b/docs/_pics/java-notes/systemDesign/7.gif deleted file mode 100644 index fad88513..00000000 Binary files a/docs/_pics/java-notes/systemDesign/7.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/76a25fc8-a579-4d7c-974b-7640b57fbf39.jpg b/docs/_pics/java-notes/systemDesign/76a25fc8-a579-4d7c-974b-7640b57fbf39.jpg deleted file mode 100644 index fd13a137..00000000 Binary files a/docs/_pics/java-notes/systemDesign/76a25fc8-a579-4d7c-974b-7640b57fbf39.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/9.gif b/docs/_pics/java-notes/systemDesign/9.gif deleted file mode 100644 index f81aa264..00000000 Binary files a/docs/_pics/java-notes/systemDesign/9.gif and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png b/docs/_pics/java-notes/systemDesign/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png deleted file mode 100644 index c7f87138..00000000 Binary files a/docs/_pics/java-notes/systemDesign/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/MultiNode-SessionReplication.jpg b/docs/_pics/java-notes/systemDesign/MultiNode-SessionReplication.jpg deleted file mode 100644 index 0223bd80..00000000 Binary files a/docs/_pics/java-notes/systemDesign/MultiNode-SessionReplication.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/MultiNode-SpringSession.jpg b/docs/_pics/java-notes/systemDesign/MultiNode-SpringSession.jpg deleted file mode 100644 index 38d56e2c..00000000 Binary files a/docs/_pics/java-notes/systemDesign/MultiNode-SpringSession.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/MultiNode-StickySessions.jpg b/docs/_pics/java-notes/systemDesign/MultiNode-StickySessions.jpg deleted file mode 100644 index a7e1c6aa..00000000 Binary files a/docs/_pics/java-notes/systemDesign/MultiNode-StickySessions.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/b988877c-0f0a-4593-916d-de2081320628.jpg b/docs/_pics/java-notes/systemDesign/b988877c-0f0a-4593-916d-de2081320628.jpg deleted file mode 100644 index 67339134..00000000 Binary files a/docs/_pics/java-notes/systemDesign/b988877c-0f0a-4593-916d-de2081320628.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/bc603930-d74d-4499-a3e7-2d740fc07f33.png b/docs/_pics/java-notes/systemDesign/bc603930-d74d-4499-a3e7-2d740fc07f33.png deleted file mode 100644 index 6c9a572e..00000000 Binary files a/docs/_pics/java-notes/systemDesign/bc603930-d74d-4499-a3e7-2d740fc07f33.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/bee1ff1d-c80f-4b3c-b58c-7073a8896ab2.jpg b/docs/_pics/java-notes/systemDesign/bee1ff1d-c80f-4b3c-b58c-7073a8896ab2.jpg deleted file mode 100644 index e4becc19..00000000 Binary files a/docs/_pics/java-notes/systemDesign/bee1ff1d-c80f-4b3c-b58c-7073a8896ab2.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg b/docs/_pics/java-notes/systemDesign/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg deleted file mode 100644 index 30956ccf..00000000 Binary files a/docs/_pics/java-notes/systemDesign/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/c5f611f0-fd5c-4158-9003-278141136e6e.jpg b/docs/_pics/java-notes/systemDesign/c5f611f0-fd5c-4158-9003-278141136e6e.jpg deleted file mode 100644 index 473091be..00000000 Binary files a/docs/_pics/java-notes/systemDesign/c5f611f0-fd5c-4158-9003-278141136e6e.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/ddb5ff4c-4ada-46aa-9bf1-140bdb5e4676.jpg b/docs/_pics/java-notes/systemDesign/ddb5ff4c-4ada-46aa-9bf1-140bdb5e4676.jpg deleted file mode 100644 index 73b3d739..00000000 Binary files a/docs/_pics/java-notes/systemDesign/ddb5ff4c-4ada-46aa-9bf1-140bdb5e4676.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/e3bf5de4-ab1e-4a9b-896d-4b0ad7e9220a.jpg b/docs/_pics/java-notes/systemDesign/e3bf5de4-ab1e-4a9b-896d-4b0ad7e9220a.jpg deleted file mode 100644 index a3ead324..00000000 Binary files a/docs/_pics/java-notes/systemDesign/e3bf5de4-ab1e-4a9b-896d-4b0ad7e9220a.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/f1109d04-3c67-48a3-9963-2c475f94e175.jpg b/docs/_pics/java-notes/systemDesign/f1109d04-3c67-48a3-9963-2c475f94e175.jpg deleted file mode 100644 index cdd1b55e..00000000 Binary files a/docs/_pics/java-notes/systemDesign/f1109d04-3c67-48a3-9963-2c475f94e175.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/f7ecbb8d-bb8b-4d45-a3b7-f49425d6d83d.jpg b/docs/_pics/java-notes/systemDesign/f7ecbb8d-bb8b-4d45-a3b7-f49425d6d83d.jpg deleted file mode 100644 index ab51d486..00000000 Binary files a/docs/_pics/java-notes/systemDesign/f7ecbb8d-bb8b-4d45-a3b7-f49425d6d83d.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg b/docs/_pics/java-notes/systemDesign/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg deleted file mode 100644 index 36c1d9b7..00000000 Binary files a/docs/_pics/java-notes/systemDesign/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/kafka_00.png b/docs/_pics/java-notes/systemDesign/kafka_00.png deleted file mode 100644 index 298481f2..00000000 Binary files a/docs/_pics/java-notes/systemDesign/kafka_00.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/kafka_01.png b/docs/_pics/java-notes/systemDesign/kafka_01.png deleted file mode 100644 index 42a54e20..00000000 Binary files a/docs/_pics/java-notes/systemDesign/kafka_01.png and /dev/null differ diff --git a/docs/_pics/java-notes/systemDesign/kafka_02.png b/docs/_pics/java-notes/systemDesign/kafka_02.png deleted file mode 100644 index 30d18e3a..00000000 Binary files a/docs/_pics/java-notes/systemDesign/kafka_02.png and /dev/null differ diff --git a/docs/_pics/kafka/k_1.png b/docs/_pics/kafka/k_1.png deleted file mode 100644 index 42a54e20..00000000 Binary files a/docs/_pics/kafka/k_1.png and /dev/null differ diff --git a/docs/_pics/kafka/k_10.png b/docs/_pics/kafka/k_10.png deleted file mode 100644 index 9ce858ea..00000000 Binary files a/docs/_pics/kafka/k_10.png and /dev/null differ diff --git a/docs/_pics/kafka/k_2.png b/docs/_pics/kafka/k_2.png deleted file mode 100644 index 1e3fb16b..00000000 Binary files a/docs/_pics/kafka/k_2.png and /dev/null differ diff --git a/docs/_pics/kafka/k_3.png b/docs/_pics/kafka/k_3.png deleted file mode 100644 index 22c3fe1e..00000000 Binary files a/docs/_pics/kafka/k_3.png and /dev/null differ diff --git a/docs/_pics/kafka/k_4.png b/docs/_pics/kafka/k_4.png deleted file mode 100644 index a6494999..00000000 Binary files a/docs/_pics/kafka/k_4.png and /dev/null differ diff --git a/docs/_pics/kafka/k_5.png b/docs/_pics/kafka/k_5.png deleted file mode 100644 index 16fe2936..00000000 Binary files a/docs/_pics/kafka/k_5.png and /dev/null differ diff --git a/docs/_pics/kafka/k_6.png b/docs/_pics/kafka/k_6.png deleted file mode 100644 index a5a888ed..00000000 Binary files a/docs/_pics/kafka/k_6.png and /dev/null differ diff --git a/docs/_pics/kafka/k_7.png b/docs/_pics/kafka/k_7.png deleted file mode 100644 index fcde5b03..00000000 Binary files a/docs/_pics/kafka/k_7.png and /dev/null differ diff --git a/docs/_pics/kafka/k_8.png b/docs/_pics/kafka/k_8.png deleted file mode 100644 index 44d8fe9d..00000000 Binary files a/docs/_pics/kafka/k_8.png and /dev/null differ diff --git a/docs/_pics/kafka/k_9.png b/docs/_pics/kafka/k_9.png deleted file mode 100644 index dd8eb14a..00000000 Binary files a/docs/_pics/kafka/k_9.png and /dev/null differ diff --git a/docs/_pics/leetcode/127.png b/docs/_pics/leetcode/127.png deleted file mode 100644 index 529a8276..00000000 Binary files a/docs/_pics/leetcode/127.png and /dev/null differ diff --git a/docs/_pics/leetcode/17.png b/docs/_pics/leetcode/17.png deleted file mode 100644 index 2b5fcfad..00000000 Binary files a/docs/_pics/leetcode/17.png and /dev/null differ diff --git a/docs/_pics/leetcode/243.png b/docs/_pics/leetcode/243.png deleted file mode 100644 index cc2f7dc4..00000000 Binary files a/docs/_pics/leetcode/243.png and /dev/null differ diff --git a/docs/_pics/leetcode/257_1.png b/docs/_pics/leetcode/257_1.png deleted file mode 100644 index 384ede5c..00000000 Binary files a/docs/_pics/leetcode/257_1.png and /dev/null differ diff --git a/docs/_pics/leetcode/257_2.png b/docs/_pics/leetcode/257_2.png deleted file mode 100644 index 79892231..00000000 Binary files a/docs/_pics/leetcode/257_2.png and /dev/null differ diff --git a/docs/_pics/leetcode/257_3.png b/docs/_pics/leetcode/257_3.png deleted file mode 100644 index d3a8c107..00000000 Binary files a/docs/_pics/leetcode/257_3.png and /dev/null differ diff --git a/docs/_pics/leetcode/279_1.png b/docs/_pics/leetcode/279_1.png deleted file mode 100644 index cb498a9e..00000000 Binary files a/docs/_pics/leetcode/279_1.png and /dev/null differ diff --git a/docs/_pics/leetcode/279_2.png b/docs/_pics/leetcode/279_2.png deleted file mode 100644 index 373f05b0..00000000 Binary files a/docs/_pics/leetcode/279_2.png and /dev/null differ diff --git a/docs/_pics/leetcode/279_3.png b/docs/_pics/leetcode/279_3.png deleted file mode 100644 index 34095a9e..00000000 Binary files a/docs/_pics/leetcode/279_3.png and /dev/null differ diff --git a/docs/_pics/leetcode/46_1.png b/docs/_pics/leetcode/46_1.png deleted file mode 100644 index f0862e06..00000000 Binary files a/docs/_pics/leetcode/46_1.png and /dev/null differ diff --git a/docs/_pics/leetcode/51_1.png b/docs/_pics/leetcode/51_1.png deleted file mode 100644 index 0f6f4d33..00000000 Binary files a/docs/_pics/leetcode/51_1.png and /dev/null differ diff --git a/docs/_pics/leetcode/51_2.png b/docs/_pics/leetcode/51_2.png deleted file mode 100644 index edea2826..00000000 Binary files a/docs/_pics/leetcode/51_2.png and /dev/null differ diff --git a/docs/_pics/leetcode/l_1.png b/docs/_pics/leetcode/l_1.png deleted file mode 100644 index 3faec6ce..00000000 Binary files a/docs/_pics/leetcode/l_1.png and /dev/null differ diff --git a/docs/_pics/leetcode/l_2.png b/docs/_pics/leetcode/l_2.png deleted file mode 100644 index d5a2019b..00000000 Binary files a/docs/_pics/leetcode/l_2.png and /dev/null differ diff --git a/docs/_pics/logo_1.png b/docs/_pics/logo_1.png deleted file mode 100644 index f909159b..00000000 Binary files a/docs/_pics/logo_1.png and /dev/null differ diff --git a/docs/_pics/mcard/m_1.png b/docs/_pics/mcard/m_1.png deleted file mode 100644 index 4b5c7244..00000000 Binary files a/docs/_pics/mcard/m_1.png and /dev/null differ diff --git a/docs/_pics/mcard/m_10.png b/docs/_pics/mcard/m_10.png deleted file mode 100644 index 86488d22..00000000 Binary files a/docs/_pics/mcard/m_10.png and /dev/null differ diff --git a/docs/_pics/mcard/m_11.png b/docs/_pics/mcard/m_11.png deleted file mode 100644 index b59715ef..00000000 Binary files a/docs/_pics/mcard/m_11.png and /dev/null differ diff --git a/docs/_pics/mcard/m_12.png b/docs/_pics/mcard/m_12.png deleted file mode 100644 index 3ca85215..00000000 Binary files a/docs/_pics/mcard/m_12.png and /dev/null differ diff --git a/docs/_pics/mcard/m_13.png b/docs/_pics/mcard/m_13.png deleted file mode 100644 index 1df2ec64..00000000 Binary files a/docs/_pics/mcard/m_13.png and /dev/null differ diff --git a/docs/_pics/mcard/m_2.png b/docs/_pics/mcard/m_2.png deleted file mode 100644 index 5810e47f..00000000 Binary files a/docs/_pics/mcard/m_2.png and /dev/null differ diff --git a/docs/_pics/mcard/m_3.png b/docs/_pics/mcard/m_3.png deleted file mode 100644 index da1f3b47..00000000 Binary files a/docs/_pics/mcard/m_3.png and /dev/null differ diff --git a/docs/_pics/mcard/m_4.png b/docs/_pics/mcard/m_4.png deleted file mode 100644 index d3844f93..00000000 Binary files a/docs/_pics/mcard/m_4.png and /dev/null differ diff --git a/docs/_pics/mcard/m_5.png b/docs/_pics/mcard/m_5.png deleted file mode 100644 index f4f4bc2e..00000000 Binary files a/docs/_pics/mcard/m_5.png and /dev/null differ diff --git a/docs/_pics/mcard/m_6.png b/docs/_pics/mcard/m_6.png deleted file mode 100644 index 5470e346..00000000 Binary files a/docs/_pics/mcard/m_6.png and /dev/null differ diff --git a/docs/_pics/mcard/m_7.png b/docs/_pics/mcard/m_7.png deleted file mode 100644 index 7dc446ec..00000000 Binary files a/docs/_pics/mcard/m_7.png and /dev/null differ diff --git a/docs/_pics/mcard/m_8.png b/docs/_pics/mcard/m_8.png deleted file mode 100644 index 7eb26665..00000000 Binary files a/docs/_pics/mcard/m_8.png and /dev/null differ diff --git a/docs/_pics/mcard/m_9.png b/docs/_pics/mcard/m_9.png deleted file mode 100644 index 6577b921..00000000 Binary files a/docs/_pics/mcard/m_9.png and /dev/null differ diff --git a/docs/_pics/others/class_loader.png b/docs/_pics/others/class_loader.png deleted file mode 100644 index e6dedf9f..00000000 Binary files a/docs/_pics/others/class_loader.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_1.png b/docs/_pics/pics/blog/aqs_1.png deleted file mode 100644 index 3e42b225..00000000 Binary files a/docs/_pics/pics/blog/aqs_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_10.png b/docs/_pics/pics/blog/aqs_10.png deleted file mode 100644 index 15320c5e..00000000 Binary files a/docs/_pics/pics/blog/aqs_10.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_11.png b/docs/_pics/pics/blog/aqs_11.png deleted file mode 100644 index 5bdb9cd5..00000000 Binary files a/docs/_pics/pics/blog/aqs_11.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_12.png b/docs/_pics/pics/blog/aqs_12.png deleted file mode 100644 index 3f7073ec..00000000 Binary files a/docs/_pics/pics/blog/aqs_12.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_2.png b/docs/_pics/pics/blog/aqs_2.png deleted file mode 100644 index 12b7530b..00000000 Binary files a/docs/_pics/pics/blog/aqs_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_3.png b/docs/_pics/pics/blog/aqs_3.png deleted file mode 100644 index 7b41eae2..00000000 Binary files a/docs/_pics/pics/blog/aqs_3.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_4.png b/docs/_pics/pics/blog/aqs_4.png deleted file mode 100644 index 8d85dd73..00000000 Binary files a/docs/_pics/pics/blog/aqs_4.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_5.png b/docs/_pics/pics/blog/aqs_5.png deleted file mode 100644 index 57ba383d..00000000 Binary files a/docs/_pics/pics/blog/aqs_5.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_6.png b/docs/_pics/pics/blog/aqs_6.png deleted file mode 100644 index 374011f0..00000000 Binary files a/docs/_pics/pics/blog/aqs_6.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_7.png b/docs/_pics/pics/blog/aqs_7.png deleted file mode 100644 index 57b1e46e..00000000 Binary files a/docs/_pics/pics/blog/aqs_7.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_8.png b/docs/_pics/pics/blog/aqs_8.png deleted file mode 100644 index a55c11df..00000000 Binary files a/docs/_pics/pics/blog/aqs_8.png and /dev/null differ diff --git a/docs/_pics/pics/blog/aqs_9.png b/docs/_pics/pics/blog/aqs_9.png deleted file mode 100644 index 7490cab2..00000000 Binary files a/docs/_pics/pics/blog/aqs_9.png and /dev/null differ diff --git a/docs/_pics/pics/blog/b_1.png b/docs/_pics/pics/blog/b_1.png deleted file mode 100644 index 4023ab87..00000000 Binary files a/docs/_pics/pics/blog/b_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/h_1.png b/docs/_pics/pics/blog/h_1.png deleted file mode 100644 index 2e53fbe3..00000000 Binary files a/docs/_pics/pics/blog/h_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/h_2.png b/docs/_pics/pics/blog/h_2.png deleted file mode 100644 index eea3c6b4..00000000 Binary files a/docs/_pics/pics/blog/h_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/k_1.png b/docs/_pics/pics/blog/k_1.png deleted file mode 100644 index 68631bd0..00000000 Binary files a/docs/_pics/pics/blog/k_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/k_2.png b/docs/_pics/pics/blog/k_2.png deleted file mode 100644 index 1ee37ac4..00000000 Binary files a/docs/_pics/pics/blog/k_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/ka_1.png b/docs/_pics/pics/blog/ka_1.png deleted file mode 100644 index 771cdb8d..00000000 Binary files a/docs/_pics/pics/blog/ka_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/ka_2.png b/docs/_pics/pics/blog/ka_2.png deleted file mode 100644 index d50b6047..00000000 Binary files a/docs/_pics/pics/blog/ka_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/ka_3.png b/docs/_pics/pics/blog/ka_3.png deleted file mode 100644 index 1bdee84d..00000000 Binary files a/docs/_pics/pics/blog/ka_3.png and /dev/null differ diff --git a/docs/_pics/pics/blog/ka_4.png b/docs/_pics/pics/blog/ka_4.png deleted file mode 100644 index 6df6b9e6..00000000 Binary files a/docs/_pics/pics/blog/ka_4.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_1.png b/docs/_pics/pics/blog/key_1.png deleted file mode 100644 index e3a9bf9b..00000000 Binary files a/docs/_pics/pics/blog/key_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_2.png b/docs/_pics/pics/blog/key_2.png deleted file mode 100644 index 950eca00..00000000 Binary files a/docs/_pics/pics/blog/key_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_3.png b/docs/_pics/pics/blog/key_3.png deleted file mode 100644 index 4031c097..00000000 Binary files a/docs/_pics/pics/blog/key_3.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_4.png b/docs/_pics/pics/blog/key_4.png deleted file mode 100644 index 7427cc43..00000000 Binary files a/docs/_pics/pics/blog/key_4.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_5.png b/docs/_pics/pics/blog/key_5.png deleted file mode 100644 index 0280a2af..00000000 Binary files a/docs/_pics/pics/blog/key_5.png and /dev/null differ diff --git a/docs/_pics/pics/blog/key_6.png b/docs/_pics/pics/blog/key_6.png deleted file mode 100644 index dfeeb327..00000000 Binary files a/docs/_pics/pics/blog/key_6.png and /dev/null differ diff --git a/docs/_pics/pics/blog/lp_1.png b/docs/_pics/pics/blog/lp_1.png deleted file mode 100644 index c7e7974f..00000000 Binary files a/docs/_pics/pics/blog/lp_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/m_1.jpg b/docs/_pics/pics/blog/m_1.jpg deleted file mode 100644 index 3692acbd..00000000 Binary files a/docs/_pics/pics/blog/m_1.jpg and /dev/null differ diff --git a/docs/_pics/pics/blog/m_1.png b/docs/_pics/pics/blog/m_1.png deleted file mode 100644 index 9392717b..00000000 Binary files a/docs/_pics/pics/blog/m_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/m_2.jpg b/docs/_pics/pics/blog/m_2.jpg deleted file mode 100644 index 5c68f854..00000000 Binary files a/docs/_pics/pics/blog/m_2.jpg and /dev/null differ diff --git a/docs/_pics/pics/blog/m_2.png b/docs/_pics/pics/blog/m_2.png deleted file mode 100644 index 7896512a..00000000 Binary files a/docs/_pics/pics/blog/m_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/m_3.jpg b/docs/_pics/pics/blog/m_3.jpg deleted file mode 100644 index 84a35441..00000000 Binary files a/docs/_pics/pics/blog/m_3.jpg and /dev/null differ diff --git a/docs/_pics/pics/blog/m_4.jpg b/docs/_pics/pics/blog/m_4.jpg deleted file mode 100644 index ed052b83..00000000 Binary files a/docs/_pics/pics/blog/m_4.jpg and /dev/null differ diff --git a/docs/_pics/pics/blog/m_5.png b/docs/_pics/pics/blog/m_5.png deleted file mode 100644 index 7775f0b6..00000000 Binary files a/docs/_pics/pics/blog/m_5.png and /dev/null differ diff --git a/docs/_pics/pics/blog/ms_1.png b/docs/_pics/pics/blog/ms_1.png deleted file mode 100644 index 21240d2d..00000000 Binary files a/docs/_pics/pics/blog/ms_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/net_1.jpg b/docs/_pics/pics/blog/net_1.jpg deleted file mode 100644 index 13b609a4..00000000 Binary files a/docs/_pics/pics/blog/net_1.jpg and /dev/null differ diff --git a/docs/_pics/pics/blog/s_1.png b/docs/_pics/pics/blog/s_1.png deleted file mode 100644 index c0d478af..00000000 Binary files a/docs/_pics/pics/blog/s_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_2.png b/docs/_pics/pics/blog/s_2.png deleted file mode 100644 index 07a127ac..00000000 Binary files a/docs/_pics/pics/blog/s_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_3.png b/docs/_pics/pics/blog/s_3.png deleted file mode 100644 index 6a99dd76..00000000 Binary files a/docs/_pics/pics/blog/s_3.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_4.png b/docs/_pics/pics/blog/s_4.png deleted file mode 100644 index 33189c0b..00000000 Binary files a/docs/_pics/pics/blog/s_4.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_5.png b/docs/_pics/pics/blog/s_5.png deleted file mode 100644 index d841a621..00000000 Binary files a/docs/_pics/pics/blog/s_5.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_6.png b/docs/_pics/pics/blog/s_6.png deleted file mode 100644 index 42895a69..00000000 Binary files a/docs/_pics/pics/blog/s_6.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_7.png b/docs/_pics/pics/blog/s_7.png deleted file mode 100644 index d92ba074..00000000 Binary files a/docs/_pics/pics/blog/s_7.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_8.png b/docs/_pics/pics/blog/s_8.png deleted file mode 100644 index 6153c579..00000000 Binary files a/docs/_pics/pics/blog/s_8.png and /dev/null differ diff --git a/docs/_pics/pics/blog/s_9.png b/docs/_pics/pics/blog/s_9.png deleted file mode 100644 index d32a9e84..00000000 Binary files a/docs/_pics/pics/blog/s_9.png and /dev/null differ diff --git a/docs/_pics/pics/blog/trie_1.png b/docs/_pics/pics/blog/trie_1.png deleted file mode 100644 index 40a7e2db..00000000 Binary files a/docs/_pics/pics/blog/trie_1.png and /dev/null differ diff --git a/docs/_pics/pics/blog/trie_2.png b/docs/_pics/pics/blog/trie_2.png deleted file mode 100644 index a80cdb79..00000000 Binary files a/docs/_pics/pics/blog/trie_2.png and /dev/null differ diff --git a/docs/_pics/pics/blog/zky_1.jpg b/docs/_pics/pics/blog/zky_1.jpg deleted file mode 100644 index c51cb947..00000000 Binary files a/docs/_pics/pics/blog/zky_1.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/051e436c-0e46-4c59-8f67-52d89d656182.png b/docs/_pics/pics/concurrent/051e436c-0e46-4c59-8f67-52d89d656182.png deleted file mode 100644 index e3054539..00000000 Binary files a/docs/_pics/pics/concurrent/051e436c-0e46-4c59-8f67-52d89d656182.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/066f9c11-0154-42c3-8685-301a70e9bd39.jpg b/docs/_pics/pics/concurrent/066f9c11-0154-42c3-8685-301a70e9bd39.jpg deleted file mode 100644 index 84d371b8..00000000 Binary files a/docs/_pics/pics/concurrent/066f9c11-0154-42c3-8685-301a70e9bd39.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/3144015c-dcfb-47ac-94a5-bab3b78b0f14.jpg b/docs/_pics/pics/concurrent/3144015c-dcfb-47ac-94a5-bab3b78b0f14.jpg deleted file mode 100644 index a805e7f9..00000000 Binary files a/docs/_pics/pics/concurrent/3144015c-dcfb-47ac-94a5-bab3b78b0f14.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/390c913b-5f31-444f-bbdb-2b88b688e7ce.jpg b/docs/_pics/pics/concurrent/390c913b-5f31-444f-bbdb-2b88b688e7ce.jpg deleted file mode 100644 index 78eb732b..00000000 Binary files a/docs/_pics/pics/concurrent/390c913b-5f31-444f-bbdb-2b88b688e7ce.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/54e6d499-80df-488e-aa7e-081766c41538.jpg b/docs/_pics/pics/concurrent/54e6d499-80df-488e-aa7e-081766c41538.jpg deleted file mode 100644 index 0ffa2a5b..00000000 Binary files a/docs/_pics/pics/concurrent/54e6d499-80df-488e-aa7e-081766c41538.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/5e6e05d6-1028-4f5c-b9bd-1a40b90d6070.jpg b/docs/_pics/pics/concurrent/5e6e05d6-1028-4f5c-b9bd-1a40b90d6070.jpg deleted file mode 100644 index f2a6c03a..00000000 Binary files a/docs/_pics/pics/concurrent/5e6e05d6-1028-4f5c-b9bd-1a40b90d6070.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/8162aebb-8fd2-4620-b771-e65751ba7e41.png b/docs/_pics/pics/concurrent/8162aebb-8fd2-4620-b771-e65751ba7e41.png deleted file mode 100644 index 2fa69582..00000000 Binary files a/docs/_pics/pics/concurrent/8162aebb-8fd2-4620-b771-e65751ba7e41.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/847b9ba1-b3cd-4e52-aa72-dee0222ae09f.jpg b/docs/_pics/pics/concurrent/847b9ba1-b3cd-4e52-aa72-dee0222ae09f.jpg deleted file mode 100644 index c68fd3ef..00000000 Binary files a/docs/_pics/pics/concurrent/847b9ba1-b3cd-4e52-aa72-dee0222ae09f.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/912a7886-fb1d-4a05-902d-ab17ea17007f.jpg b/docs/_pics/pics/concurrent/912a7886-fb1d-4a05-902d-ab17ea17007f.jpg deleted file mode 100644 index e30c6908..00000000 Binary files a/docs/_pics/pics/concurrent/912a7886-fb1d-4a05-902d-ab17ea17007f.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/94414cd3-5db9-4aca-a2af-539140955c62.jpg b/docs/_pics/pics/concurrent/94414cd3-5db9-4aca-a2af-539140955c62.jpg deleted file mode 100644 index 5c53d38b..00000000 Binary files a/docs/_pics/pics/concurrent/94414cd3-5db9-4aca-a2af-539140955c62.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/96706658-b3f8-4f32-8eb3-dcb7fc8d5381.jpg b/docs/_pics/pics/concurrent/96706658-b3f8-4f32-8eb3-dcb7fc8d5381.jpg deleted file mode 100644 index c4e77ba1..00000000 Binary files a/docs/_pics/pics/concurrent/96706658-b3f8-4f32-8eb3-dcb7fc8d5381.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/b6a7e8af-91bf-44b2-8874-ccc6d9d52afc.jpg b/docs/_pics/pics/concurrent/b6a7e8af-91bf-44b2-8874-ccc6d9d52afc.jpg deleted file mode 100644 index 96b80deb..00000000 Binary files a/docs/_pics/pics/concurrent/b6a7e8af-91bf-44b2-8874-ccc6d9d52afc.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/baaa681f-7c52-4198-a5ae-303b9386cf47.png b/docs/_pics/pics/concurrent/baaa681f-7c52-4198-a5ae-303b9386cf47.png deleted file mode 100644 index 6664d398..00000000 Binary files a/docs/_pics/pics/concurrent/baaa681f-7c52-4198-a5ae-303b9386cf47.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/bb6a49be-00f2-4f27-a0ce-4ed764bc605c.png b/docs/_pics/pics/concurrent/bb6a49be-00f2-4f27-a0ce-4ed764bc605c.png deleted file mode 100644 index 07d8692d..00000000 Binary files a/docs/_pics/pics/concurrent/bb6a49be-00f2-4f27-a0ce-4ed764bc605c.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/bc5826f5-014d-47b4-9a76-d86b80968643.jpg b/docs/_pics/pics/concurrent/bc5826f5-014d-47b4-9a76-d86b80968643.jpg deleted file mode 100644 index b27cd02f..00000000 Binary files a/docs/_pics/pics/concurrent/bc5826f5-014d-47b4-9a76-d86b80968643.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_1.png b/docs/_pics/pics/concurrent/c_1.png deleted file mode 100644 index 30910c3a..00000000 Binary files a/docs/_pics/pics/concurrent/c_1.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_10.png b/docs/_pics/pics/concurrent/c_10.png deleted file mode 100644 index 7356cf7c..00000000 Binary files a/docs/_pics/pics/concurrent/c_10.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_11.png b/docs/_pics/pics/concurrent/c_11.png deleted file mode 100644 index d8b6778c..00000000 Binary files a/docs/_pics/pics/concurrent/c_11.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_12.png b/docs/_pics/pics/concurrent/c_12.png deleted file mode 100644 index ba59e5f7..00000000 Binary files a/docs/_pics/pics/concurrent/c_12.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_13.png b/docs/_pics/pics/concurrent/c_13.png deleted file mode 100644 index f825ab24..00000000 Binary files a/docs/_pics/pics/concurrent/c_13.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_14.png b/docs/_pics/pics/concurrent/c_14.png deleted file mode 100644 index eded5fe7..00000000 Binary files a/docs/_pics/pics/concurrent/c_14.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_15.png b/docs/_pics/pics/concurrent/c_15.png deleted file mode 100644 index 7a704f2d..00000000 Binary files a/docs/_pics/pics/concurrent/c_15.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_16.png b/docs/_pics/pics/concurrent/c_16.png deleted file mode 100644 index 7417cbad..00000000 Binary files a/docs/_pics/pics/concurrent/c_16.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_17.png b/docs/_pics/pics/concurrent/c_17.png deleted file mode 100644 index 469916fb..00000000 Binary files a/docs/_pics/pics/concurrent/c_17.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_18.png b/docs/_pics/pics/concurrent/c_18.png deleted file mode 100644 index e90c55bc..00000000 Binary files a/docs/_pics/pics/concurrent/c_18.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_19.png b/docs/_pics/pics/concurrent/c_19.png deleted file mode 100644 index fffc0dc3..00000000 Binary files a/docs/_pics/pics/concurrent/c_19.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_2.png b/docs/_pics/pics/concurrent/c_2.png deleted file mode 100644 index d5f7564c..00000000 Binary files a/docs/_pics/pics/concurrent/c_2.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_20.png b/docs/_pics/pics/concurrent/c_20.png deleted file mode 100644 index e23da54e..00000000 Binary files a/docs/_pics/pics/concurrent/c_20.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_21.png b/docs/_pics/pics/concurrent/c_21.png deleted file mode 100644 index 71556948..00000000 Binary files a/docs/_pics/pics/concurrent/c_21.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_22.png b/docs/_pics/pics/concurrent/c_22.png deleted file mode 100644 index 032269ec..00000000 Binary files a/docs/_pics/pics/concurrent/c_22.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_23.png b/docs/_pics/pics/concurrent/c_23.png deleted file mode 100644 index 90065cc5..00000000 Binary files a/docs/_pics/pics/concurrent/c_23.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_24.png b/docs/_pics/pics/concurrent/c_24.png deleted file mode 100644 index f9685021..00000000 Binary files a/docs/_pics/pics/concurrent/c_24.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_3.png b/docs/_pics/pics/concurrent/c_3.png deleted file mode 100644 index 079f2c70..00000000 Binary files a/docs/_pics/pics/concurrent/c_3.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_4.png b/docs/_pics/pics/concurrent/c_4.png deleted file mode 100644 index 267d5b5d..00000000 Binary files a/docs/_pics/pics/concurrent/c_4.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_5.png b/docs/_pics/pics/concurrent/c_5.png deleted file mode 100644 index 7b46cdd4..00000000 Binary files a/docs/_pics/pics/concurrent/c_5.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_6.png b/docs/_pics/pics/concurrent/c_6.png deleted file mode 100644 index 0be9ad77..00000000 Binary files a/docs/_pics/pics/concurrent/c_6.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_7.png b/docs/_pics/pics/concurrent/c_7.png deleted file mode 100644 index c81810a8..00000000 Binary files a/docs/_pics/pics/concurrent/c_7.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_8.png b/docs/_pics/pics/concurrent/c_8.png deleted file mode 100644 index 53a32162..00000000 Binary files a/docs/_pics/pics/concurrent/c_8.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/c_9.png b/docs/_pics/pics/concurrent/c_9.png deleted file mode 100644 index 8d798968..00000000 Binary files a/docs/_pics/pics/concurrent/c_9.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/d2a12961-2b36-4463-b017-ca46a3308b8e.png b/docs/_pics/pics/concurrent/d2a12961-2b36-4463-b017-ca46a3308b8e.png deleted file mode 100644 index ce6663bc..00000000 Binary files a/docs/_pics/pics/concurrent/d2a12961-2b36-4463-b017-ca46a3308b8e.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/de9d8133-4c98-4e07-b39c-302e162784ea.jpg b/docs/_pics/pics/concurrent/de9d8133-4c98-4e07-b39c-302e162784ea.jpg deleted file mode 100644 index 4a923dd8..00000000 Binary files a/docs/_pics/pics/concurrent/de9d8133-4c98-4e07-b39c-302e162784ea.jpg and /dev/null differ diff --git a/docs/_pics/pics/concurrent/e19452dd-220a-4a6b-bcb0-91ad5e5c4706.png b/docs/_pics/pics/concurrent/e19452dd-220a-4a6b-bcb0-91ad5e5c4706.png deleted file mode 100644 index c21e9af2..00000000 Binary files a/docs/_pics/pics/concurrent/e19452dd-220a-4a6b-bcb0-91ad5e5c4706.png and /dev/null differ diff --git a/docs/_pics/pics/concurrent/f944fac3-482b-4ca3-9447-17aec4a3cca0.png b/docs/_pics/pics/concurrent/f944fac3-482b-4ca3-9447-17aec4a3cca0.png deleted file mode 100644 index 56f05611..00000000 Binary files a/docs/_pics/pics/concurrent/f944fac3-482b-4ca3-9447-17aec4a3cca0.png and /dev/null differ diff --git a/docs/_pics/redis/0ea37ee2-c224-4c79-b895-e131c6805c40.png b/docs/_pics/redis/0ea37ee2-c224-4c79-b895-e131c6805c40.png deleted file mode 100644 index 837088e8..00000000 Binary files a/docs/_pics/redis/0ea37ee2-c224-4c79-b895-e131c6805c40.png and /dev/null differ diff --git a/docs/_pics/redis/1202b2d6-9469-4251-bd47-ca6034fb6116.png b/docs/_pics/redis/1202b2d6-9469-4251-bd47-ca6034fb6116.png deleted file mode 100644 index 0db77ec4..00000000 Binary files a/docs/_pics/redis/1202b2d6-9469-4251-bd47-ca6034fb6116.png and /dev/null differ diff --git a/docs/_pics/redis/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png b/docs/_pics/redis/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png deleted file mode 100644 index 4f3d0ccd..00000000 Binary files a/docs/_pics/redis/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png and /dev/null differ diff --git a/docs/_pics/redis/485fdf34-ccf8-4185-97c6-17374ee719a0.png b/docs/_pics/redis/485fdf34-ccf8-4185-97c6-17374ee719a0.png deleted file mode 100644 index 7f842458..00000000 Binary files a/docs/_pics/redis/485fdf34-ccf8-4185-97c6-17374ee719a0.png and /dev/null differ diff --git a/docs/_pics/redis/6019b2db-bc3e-4408-b6d8-96025f4481d6.png b/docs/_pics/redis/6019b2db-bc3e-4408-b6d8-96025f4481d6.png deleted file mode 100644 index 79388c09..00000000 Binary files a/docs/_pics/redis/6019b2db-bc3e-4408-b6d8-96025f4481d6.png and /dev/null differ diff --git a/docs/_pics/redis/7bd202a7-93d4-4f3a-a878-af68ae25539a.png b/docs/_pics/redis/7bd202a7-93d4-4f3a-a878-af68ae25539a.png deleted file mode 100644 index d325c907..00000000 Binary files a/docs/_pics/redis/7bd202a7-93d4-4f3a-a878-af68ae25539a.png and /dev/null differ diff --git a/docs/_pics/redis/7c54de21-e2ff-402e-bc42-4037de1c1592.png b/docs/_pics/redis/7c54de21-e2ff-402e-bc42-4037de1c1592.png deleted file mode 100644 index 5f493376..00000000 Binary files a/docs/_pics/redis/7c54de21-e2ff-402e-bc42-4037de1c1592.png and /dev/null differ diff --git a/docs/_pics/redis/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png b/docs/_pics/redis/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png deleted file mode 100644 index 61717a26..00000000 Binary files a/docs/_pics/redis/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png and /dev/null differ diff --git a/docs/_pics/redis/beba612e-dc5b-4fc2-869d-0b23408ac90a.png b/docs/_pics/redis/beba612e-dc5b-4fc2-869d-0b23408ac90a.png deleted file mode 100644 index 158015bc..00000000 Binary files a/docs/_pics/redis/beba612e-dc5b-4fc2-869d-0b23408ac90a.png and /dev/null differ diff --git a/docs/_pics/redis/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png b/docs/_pics/redis/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png deleted file mode 100644 index 14c225b3..00000000 Binary files a/docs/_pics/redis/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png and /dev/null differ diff --git a/docs/_pics/redis/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png b/docs/_pics/redis/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png deleted file mode 100644 index b721cc0a..00000000 Binary files a/docs/_pics/redis/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png and /dev/null differ diff --git a/docs/_pics/redis/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png b/docs/_pics/redis/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png deleted file mode 100644 index ccc91793..00000000 Binary files a/docs/_pics/redis/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png and /dev/null differ diff --git a/docs/_pics/redis/fb327611-7e2b-4f2f-9f5b-38592d408f07.png b/docs/_pics/redis/fb327611-7e2b-4f2f-9f5b-38592d408f07.png deleted file mode 100644 index 774ecf10..00000000 Binary files a/docs/_pics/redis/fb327611-7e2b-4f2f-9f5b-38592d408f07.png and /dev/null differ diff --git a/docs/_pics/redis/r_1.png b/docs/_pics/redis/r_1.png deleted file mode 100644 index 8b7b822a..00000000 Binary files a/docs/_pics/redis/r_1.png and /dev/null differ diff --git a/docs/_pics/redis/r_10.png b/docs/_pics/redis/r_10.png deleted file mode 100644 index a5ce5187..00000000 Binary files a/docs/_pics/redis/r_10.png and /dev/null differ diff --git a/docs/_pics/redis/r_11.jpg b/docs/_pics/redis/r_11.jpg deleted file mode 100644 index 3b506337..00000000 Binary files a/docs/_pics/redis/r_11.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_12.jpg b/docs/_pics/redis/r_12.jpg deleted file mode 100644 index e6d88249..00000000 Binary files a/docs/_pics/redis/r_12.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_13.jpg b/docs/_pics/redis/r_13.jpg deleted file mode 100644 index dcbd3ef0..00000000 Binary files a/docs/_pics/redis/r_13.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_14.jpg b/docs/_pics/redis/r_14.jpg deleted file mode 100644 index 6d2fd9fd..00000000 Binary files a/docs/_pics/redis/r_14.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_15.jpg b/docs/_pics/redis/r_15.jpg deleted file mode 100644 index 68fc7d4e..00000000 Binary files a/docs/_pics/redis/r_15.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_16.jpg b/docs/_pics/redis/r_16.jpg deleted file mode 100644 index 9d839eea..00000000 Binary files a/docs/_pics/redis/r_16.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_17.jpg b/docs/_pics/redis/r_17.jpg deleted file mode 100644 index c7a91ab4..00000000 Binary files a/docs/_pics/redis/r_17.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_18.jpg b/docs/_pics/redis/r_18.jpg deleted file mode 100644 index e0dd6416..00000000 Binary files a/docs/_pics/redis/r_18.jpg and /dev/null differ diff --git a/docs/_pics/redis/r_19.png b/docs/_pics/redis/r_19.png deleted file mode 100644 index 898361b9..00000000 Binary files a/docs/_pics/redis/r_19.png and /dev/null differ diff --git a/docs/_pics/redis/r_2.png b/docs/_pics/redis/r_2.png deleted file mode 100644 index 24d19da1..00000000 Binary files a/docs/_pics/redis/r_2.png and /dev/null differ diff --git a/docs/_pics/redis/r_3.png b/docs/_pics/redis/r_3.png deleted file mode 100644 index a61f2337..00000000 Binary files a/docs/_pics/redis/r_3.png and /dev/null differ diff --git a/docs/_pics/redis/r_4.png b/docs/_pics/redis/r_4.png deleted file mode 100644 index 7c915784..00000000 Binary files a/docs/_pics/redis/r_4.png and /dev/null differ diff --git a/docs/_pics/redis/r_5.png b/docs/_pics/redis/r_5.png deleted file mode 100644 index bc3a2997..00000000 Binary files a/docs/_pics/redis/r_5.png and /dev/null differ diff --git a/docs/_pics/redis/r_6.png b/docs/_pics/redis/r_6.png deleted file mode 100644 index 6144c24b..00000000 Binary files a/docs/_pics/redis/r_6.png and /dev/null differ diff --git a/docs/_pics/redis/r_7.png b/docs/_pics/redis/r_7.png deleted file mode 100644 index ad4eb80b..00000000 Binary files a/docs/_pics/redis/r_7.png and /dev/null differ diff --git a/docs/_pics/redis/r_8.png b/docs/_pics/redis/r_8.png deleted file mode 100644 index 055bf629..00000000 Binary files a/docs/_pics/redis/r_8.png and /dev/null differ diff --git a/docs/_pics/redis/r_9.png b/docs/_pics/redis/r_9.png deleted file mode 100644 index b7e58eb3..00000000 Binary files a/docs/_pics/redis/r_9.png and /dev/null differ diff --git a/docs/_pics/redis/redis_1.png b/docs/_pics/redis/redis_1.png deleted file mode 100644 index 1fc9381d..00000000 Binary files a/docs/_pics/redis/redis_1.png and /dev/null differ diff --git a/docs/_pics/redis/redis_2.png b/docs/_pics/redis/redis_2.png deleted file mode 100644 index 4499813b..00000000 Binary files a/docs/_pics/redis/redis_2.png and /dev/null differ diff --git a/docs/_pics/redis/redis_3.png b/docs/_pics/redis/redis_3.png deleted file mode 100644 index 140d3628..00000000 Binary files a/docs/_pics/redis/redis_3.png and /dev/null differ diff --git a/docs/_pics/redis/redis_4.png b/docs/_pics/redis/redis_4.png deleted file mode 100644 index 66d618b0..00000000 Binary files a/docs/_pics/redis/redis_4.png and /dev/null differ diff --git a/docs/_pics/redis/redis_5.png b/docs/_pics/redis/redis_5.png deleted file mode 100644 index 7e4c94fc..00000000 Binary files a/docs/_pics/redis/redis_5.png and /dev/null differ diff --git a/docs/_pics/redis/redis_6.png b/docs/_pics/redis/redis_6.png deleted file mode 100644 index 0acc4624..00000000 Binary files a/docs/_pics/redis/redis_6.png and /dev/null differ diff --git a/docs/_pics/redis/redis_7.png b/docs/_pics/redis/redis_7.png deleted file mode 100644 index 95eb0858..00000000 Binary files a/docs/_pics/redis/redis_7.png and /dev/null differ diff --git a/docs/_pics/redis/redis_8.png b/docs/_pics/redis/redis_8.png deleted file mode 100644 index 17674dac..00000000 Binary files a/docs/_pics/redis/redis_8.png and /dev/null differ diff --git a/docs/_pics/redis/redis_9.png b/docs/_pics/redis/redis_9.png deleted file mode 100644 index 72d349ae..00000000 Binary files a/docs/_pics/redis/redis_9.png and /dev/null differ diff --git a/docs/_pics/xyjy.png b/docs/_pics/xyjy.png deleted file mode 100644 index 015e315b..00000000 Binary files a/docs/_pics/xyjy.png and /dev/null differ diff --git a/docs/_pics/zookeeper/z_2.png b/docs/_pics/zookeeper/z_2.png deleted file mode 100644 index cf8a5923..00000000 Binary files a/docs/_pics/zookeeper/z_2.png and /dev/null differ diff --git a/docs/_pics/zookeeper/z_3.png b/docs/_pics/zookeeper/z_3.png deleted file mode 100644 index 65956b97..00000000 Binary files a/docs/_pics/zookeeper/z_3.png and /dev/null differ diff --git a/docs/_pics/zookeeper/z_4.png b/docs/_pics/zookeeper/z_4.png deleted file mode 100644 index 716297ef..00000000 Binary files a/docs/_pics/zookeeper/z_4.png and /dev/null differ diff --git a/docs/_pics/zookeeper/z_5.jpg b/docs/_pics/zookeeper/z_5.jpg deleted file mode 100644 index aba9c7e5..00000000 Binary files a/docs/_pics/zookeeper/z_5.jpg and /dev/null differ diff --git a/docs/_pics/zookeeper/z_6.jpg b/docs/_pics/zookeeper/z_6.jpg deleted file mode 100644 index 24b8a8f1..00000000 Binary files a/docs/_pics/zookeeper/z_6.jpg and /dev/null differ diff --git "a/docs/cache/1_\347\274\223\345\255\230\351\234\200\350\246\201\350\200\203\350\231\221\347\232\204\351\227\256\351\242\230.md" "b/docs/cache/1_\347\274\223\345\255\230\351\234\200\350\246\201\350\200\203\350\231\221\347\232\204\351\227\256\351\242\230.md" new file mode 100644 index 00000000..cb9b1194 --- /dev/null +++ "b/docs/cache/1_\347\274\223\345\255\230\351\234\200\350\246\201\350\200\203\350\231\221\347\232\204\351\227\256\351\242\230.md" @@ -0,0 +1,54 @@ +# 缓存需要考虑的问题 + +## 缓存命中率 + +当某个请求能够通过访问缓存而得到响应时,称为缓存命中。缓存命中率越高,缓存的利用率也就越高。 + +## 最大空间 + +缓存通常位于**内存**中,内存的空间通常比磁盘空间小的多,因此缓存的最大空间不可能非常大。当缓存存放的数据量超过最大空间时,就需要**淘汰部分数据**来存放新到达的数据。常见的数据淘汰策略: + +- FIFO(First In First Out) + + FIFO 即先进先出策略,在实时性的场景下,需要经常访问最新的数据,那么就可以使用 FIFO,使得最先进入的数据(最晚的数据)被淘汰。 + +- LRU(Least Recently Used) + + LRU 即最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最久的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 + +- LFU(Least Frequently Used) + + LFU 即最不经常使用策略,优先淘汰一段时间内使用次数最少的数据。 + +## 缓存位置 + +缓存位置一般有: + +- 浏览器 + + 当 HTTP 响应允许进行缓存时,浏览器会将 HTML、CSS、JavaScript、图片等静态资源进行缓存。 + +- 反向代理 + + 反向代理**位于服务器之前**,请求与响应都需要经过反向代理。通过将数据缓存在反向代理,在用户请求反向代理时就可以直接使用缓存进行响应。 + +- 本地缓存 + + 使用 Guava Cache 将数据缓存在服务器本地内存中,服务器代码可以直接读取本地内存中的缓存,速度非常快。 + +- 分布式缓存 + + 使用 **Redis、Memcache** 等分布式缓存将数据缓存在分布式缓存系统中。相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现难度和性能开销上都非常大。 + +- 数据库缓存 + + MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率。 + +- CPU 多级缓存 + + CPU 为了解决运算速度与主存 IO 速度不匹配的问题,引入了多级缓存结构,同时使用 MESI 等缓存一致性协议来解决多核 CPU 缓存数据一致性的问题。 + +- Java 内部的缓存 + + Java 为了优化空间,提高字符串、基本数据类型包装类的创建效率,设计了字符串常量池及 Byte、Short、Character、Integer、Long、Boolean 这六种包装类缓冲池。 + diff --git "a/docs/cache/2_\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/docs/cache/2_\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" new file mode 100644 index 00000000..2702d9ef --- /dev/null +++ "b/docs/cache/2_\347\274\223\345\255\230\345\270\270\350\247\201\351\227\256\351\242\230.md" @@ -0,0 +1,45 @@ +# 缓存常见问题 + +## 缓存穿透 + +指的是对某个一定不存在的数据进行请求,该请求将会穿透缓存到达数据库。 + +解决方案: + +- 对这些不存在的数据缓存一个空数据; +- 对这类请求进行过滤。 + +## 缓存雪崩 + +指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。 + +在有缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。 + +解决方案: + +- 为了防止缓存在同一时间大面积过期导致的缓存雪崩,可以通过观察用户行为,合理设置缓存过期时间来实现; +- 为了防止缓存服务器宕机出现的缓存雪崩,可以使用分布式缓存,分布式缓存中每一个节点只缓存部分的数据,当某个节点宕机时可以保证其它节点的缓存仍然可用。 +- 也可以进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 + +## 缓存一致性 + +缓存一致性要求数据更新的同时缓存数据也能够实时更新。 + +解决方案: + +- 在数据更新的同时立即去更新缓存; +- 在读缓存之前先判断缓存是否是最新的,如果不是最新的先进行更新。 + +要保证缓存一致性需要付出很大的代价,缓存数据最好是那些对一致性要求不高的数据,允许缓存数据存在一些脏数据。 + +## 缓存 “无底洞” 现象 + +指的是为了满足业务要求添加了大量缓存节点,但是**性能不但没有好转反而下降了的现象**。 + +产生原因:缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点,随着缓存节点数目的增加,键值分布到更多的节点上,导致客户端一次批量操作会涉及多次网络操作,这意味着批量操作的耗时会随着节点数目的增加而不断增大。此外,网络连接数变多,对节点的性能也有一定影响。 + +解决方案: + +- 优化批量数据操作命令; +- 减少网络通信次数; +- 降低接入成本,使用长连接 / 连接池,NIO 等。 \ No newline at end of file diff --git "a/docs/cache/3_\346\225\260\346\215\256\345\210\206\345\270\203.md" "b/docs/cache/3_\346\225\260\346\215\256\345\210\206\345\270\203.md" new file mode 100644 index 00000000..70ec2ffb --- /dev/null +++ "b/docs/cache/3_\346\225\260\346\215\256\345\210\206\345\270\203.md" @@ -0,0 +1,16 @@ +# 数据分布 + +## 哈希分布 + +哈希分布就是将数据计算哈希值之后,按照哈希值分配到不同的节点上。例如有 N 个节点,数据的主键为 key,则将该数据分配的节点序号为:hash(key)%N。 + +传统的哈希分布算法存在一个问题:当节点数量变化时,也就是 N 值变化,那么几乎所有的数据都需要重新分布,将导致大量的数据迁移。 + +## 顺序分布 + +将数据划分为多个连续的部分,按数据的 ID 或者时间分布到不同节点上。例如 User 表的 ID 范围为 1 ~ 7000,使用顺序分布可以将其划分成多个子表,对应的主键范围为 1 ~ 1000,1001 ~ 2000,...,6001 ~ 7000。 + +顺序分布相比于哈希分布的主要优点如下: + +- 能保持数据原有的顺序; +- 并且能够准确控制每台服务器存储的数据量,从而使得存储空间的利用率最大。 \ No newline at end of file diff --git "a/docs/cluster/1_\350\264\237\350\275\275\345\235\207\350\241\241.md" "b/docs/cluster/1_\350\264\237\350\275\275\345\235\207\350\241\241.md" new file mode 100644 index 00000000..e759cf6a --- /dev/null +++ "b/docs/cluster/1_\350\264\237\350\275\275\345\235\207\350\241\241.md" @@ -0,0 +1,3 @@ +# 负载均衡 + +待补充。 \ No newline at end of file diff --git "a/docs/cluster/2_\351\233\206\347\276\244\344\270\213\347\232\204Session\347\256\241\347\220\206.md" "b/docs/cluster/2_\351\233\206\347\276\244\344\270\213\347\232\204Session\347\256\241\347\220\206.md" new file mode 100644 index 00000000..2950e6c7 --- /dev/null +++ "b/docs/cluster/2_\351\233\206\347\276\244\344\270\213\347\232\204Session\347\256\241\347\220\206.md" @@ -0,0 +1,3 @@ +# 集群下的 Session 管理 + +待补充。 diff --git "a/docs/distribution/1_\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\350\256\276\350\256\241\347\220\206\345\277\265.md" "b/docs/distribution/1_\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\350\256\276\350\256\241\347\220\206\345\277\265.md" index 9b53c4bc..066c0fbe 100644 --- "a/docs/distribution/1_\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\350\256\276\350\256\241\347\220\206\345\277\265.md" +++ "b/docs/distribution/1_\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\350\256\276\350\256\241\347\220\206\345\277\265.md" @@ -2,6 +2,12 @@ ## 目标 +分布式架构的应用十分广泛: + +- 分布式文件系统:比如 Hadoop 的HDFS ,Google 的 GFS,淘宝的 TFS 等。 +- 分布式缓存系统:Memcache,Hbase 等。 +- 分布式数据库:MySQL ,Mariadb,PostgreSQL 等。 + 分布式系统的目标是提升系统的**整体性能**和**吞吐量**另外还要尽量保证分布式系统的**容错性**。 ## 设计思路 @@ -11,7 +17,7 @@ - 中心化 - 去中心化 -### 1. 中心化 +### 中心化 - **2 种角色** @@ -25,7 +31,7 @@ 最大问题是“领导”的安危问题,如果“领导”出了问题,则群龙无首。 -### 2. 去中心化 +### 去中心化 - **地位平等** @@ -39,17 +45,80 @@ 一般的设计思路是,当集群判断发生了脑裂问题时,规模较小的集群就“自杀”或者拒绝服务。 -## 分布式与集群 +## 基本概念 + +### 分布式与集群 + +**分布式指的是一个业务拆分为多个子业务,部署在不同服务器上**。比如一个电商系统,用户模块部署在 server1, 订单模块部署在 server2,促销模块部署在 server3,商品模块部署在 server4,他们之间通过远程 RPC 实现服务调用,这就叫分布式。强调的是不同功能模块,单独部署在不同的 server上,所有 server 加起来是一个完整的系统。 + +**集群指的是同一业务,部署在多个服务器上,更多强调的是灾备**。比如一个电商系统,完整的部署在 server1 上一个,同样完整的部署在 server2 上,当 server1宕机,server2 仍然可以正常提供请求服务,这叫集群。同样对于某一功能模块,比如用户模块部署在 server1 上,同样部署在 server2 上,也叫做集群。分布式系统的每个功能模块节点,都可以用多机做成集群。 + +拿做菜示例,假如一个厨师做菜要经历切菜,炒菜两个功能,饭店为了提高速度招了两个厨师,每个厨师的工作一样,都是切菜,炒菜,这是集群。还有另一种方法提高效率,饭店招了一个切菜师傅,配合厨师,厨师不管切菜,只管炒菜了,和切菜师傅共同配合把菜做好,这叫分布式。 + +### Nginx + +Nginx 作用是反向代理和负载均衡。 + +反向代理是指请求真实是到 server1 中,但是系统中为了统一或者做比如单点登录,会在 server2 服务器上安装一个 nginx,里面配置到 server1 的反向代理,那么之后请求 url 就可以写 server2 的地址,发出后到 server2, server2 会转发到 server1 上,类似一种代理的模式。 + +负载均衡是指如果一个系统的请求很多,我们可以把请求转发到不同的服务器上,用来分流。就类似于接了一个水管放水,水流量很大时候,水压大很可能会让一个水管爆炸,这时候接三个水管,就没问题了(这三个水管就是一个集群)。类似的在 nginx 服务器中配了 3 个 Tomcat 服务器,每个 Tomcat 服务器上都部署了整个系统,那么当请求数大的时候,可以分发到不同的 Tomcat。(其实这里每个 Tomcat 上部署同一个功能模块也叫集群)。 + +### RPC + +RPC (Remote Procedure Call) 即远程过程调用,对于分布式系统来讲,Tomcat1 上部署了用户模块,Tomcat2 上部署了订单模块,当用户下单时,请求到 Tomcat2,这时候可能要判断这个用户是否是 vip,或者是否有优惠券,这些方法是在 Tomcat1 用户模块上的,那么 Tomcat2 调用 Tomcat1 的服务获取这些信息,就叫 RPC 调用。 + +RPC 调用底层涉及到对象的序列化,反序列化,HTTP/TCP 传输,网络异步传输 Netty。 + +### 分布式 Java 应用 + +网络通信: + +- 协议 + + TCP/IP + + UDP/IP + +- IO + + BIO + + NIO-Reactor + + AIO-Proactor + +基于消息方式的系统间通信: + +- socket 方式 + + 基于 Java 包:TCP/IP、UDP/IP + + 基于框架:Netty、Dubbo + +- 消息方式 + + 基于 Java 包:JMS + + 基于框架:RabbitMQ、RocketMQ + +基于远程调用方式的系统间通信: + +- 基于 Java 包 -- 分布式 + WebService - 一个业务拆分为多个子业务,部署在不同服务器上 +- 基于框架 -- 集群 + Spring RMI、CXF - 同一业务,部署在多个服务器上 +### 消息中间件(MQ) +MQ 消息中间件在分布式系统中的作用有很多,但是经常用到的还是**异步解耦**。 +比如天猫下单流程,当用户支付后,后台接口执行的操作可能包括:1 验签,2 支付密码校验,3 扣库存,4 用户积分增加等等操作,其实我们希望的是2操作执行成功后立即给用户结果提示,而不是等到后续各个操作完成后才去提示,因为后续的操作往往大部分是rpc调用,方法执行时间相对较长。另外对于下单支付这个操作,3和4是后续业务的需要,在设计上不能和下单支付本身出现强耦合度。所以这里我们可以引入 MQ 解决,也就是说1和2执行完成后,生产者只需要通知下3和4,把后续的操作扔给消息队列,立即返回。这里的 MQ 起到的作用一个是异步调用,一个是解耦。 +### NoSQL(非关系型数据库) +NoSQL 是所有非关系型数据库的统称,在分布式系统中用到很多,主要用来提高 QPS(query per second)。 +Redis 常用作缓存,或者内存数据库,小巧强大,什么数据适合放在 Redis 也就是缓存中,一个是经常查询的,需要频繁磁盘 io 的,例如有个快件系统,有个需求是当快件状态为异常时候,需要发送邮件提醒给系统管理员。接口入参是快件id,通常做法我们需要拿到id,去数据库查状态,然后发送,但是快件基数很大时候每天的问题件也可能会很多,接口调用频繁时候就需要改进做法,这时我们可以把快件状态信息放在redis里面,key是快件id, value是快进状态,每次进入接口时候直接redis里面取status就可以,速度很快。另一个是查询数据缓慢的,可以放在缓存中。 diff --git "a/docs/distribution/2_CAP\347\220\206\350\256\272.md" "b/docs/distribution/2_CAP\347\220\206\350\256\272.md" index 8d10ab4a..714a0a7d 100644 --- "a/docs/distribution/2_CAP\347\220\206\350\256\272.md" +++ "b/docs/distribution/2_CAP\347\220\206\350\256\272.md" @@ -1,8 +1,8 @@ -# CAP 理论 +# 一、CAP 理论 分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。 -
+
## 一致性(Consistency) @@ -22,11 +22,39 @@ 在分区容忍性条件下,分布式系统在遇到任何网络分区故障的时候,仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。 -> **权衡** +## 总结 在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际上是要在**可用性(P)和一致性(C)之间做权衡**。 可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时, - 为了保证一致性(CP),不能访问未同步完成的节点,也就失去了部分可用性,zookeeper其实就是追求的强一致; -- 为了保证可用性(AP),放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性,这是很多分布式系统设计时的选择,后面的BASE也是根据AP来扩展。 \ No newline at end of file +- 为了保证可用性(AP),放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性,这是很多分布式系统设计时的选择,后面的BASE也是根据AP来扩展。 + +注意:如果系统没有发生 ”分区“ 的话,节点间的网络连接通信正常的话,也就不存在 P 了。此时需要考虑保证 CA 了。 + +# 二、BASE 理论 + +在分布式系统中,我们往往追求的是**可用性**,它的重要程序比一致性要高,那么如何实现高可用性呢? 前人已经给我们提出来了另外一个理论,就是 BASE 理论,它是用来对 CAP 定理进行进一步扩充的,更具体地说,**BASE 是 CAP 理论中 AP 方案的延伸。** + +BASE 是基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)三个短语的缩写。 + +BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。 + +## 基本可用 (Basically Available) + +指分布式系统在出现故障的时候,保证核心可用,允许损失部分可用性。 + +例如,电商在做促销时,为了保证购物系统的稳定性,部分消费者可能会被引导到一个降级的页面。 + +## 软状态 (Soft state) + +指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在时延。 + +## 最终一致性 (Eventually Consistent) + +最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能达到一致的状态。 + +**ACID 要求强一致性**,通常运用在传统的数据库系统上。而 BASE 要求最终一致性,通过**牺牲强一致性来达到可用性**,通常运用在大型分布式系统中。 + +在实际的分布式场景中,不同业务单元和组件对一致性的要求是不同的,因此 ACID 和 BASE 往往会结合在一起使用。 \ No newline at end of file diff --git "a/docs/distribution/3_BASE\347\220\206\350\256\272.md" "b/docs/distribution/3_BASE\347\220\206\350\256\272.md" deleted file mode 100644 index 800e499b..00000000 --- "a/docs/distribution/3_BASE\347\220\206\350\256\272.md" +++ /dev/null @@ -1,25 +0,0 @@ -# BASE 理论 - -在分布式系统中,我们往往追求的是**可用性**,它的重要程序比一致性要高,那么如何实现高可用性呢? 前人已经给我们提出来了另外一个理论,就是BASE理论,它是用来对CAP定理进行进一步扩充的。 - -BASE 是基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)三个短语的缩写。 - -BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。 - -## 基本可用 - -指分布式系统在出现故障的时候,保证核心可用,允许损失部分可用性。 - -例如,电商在做促销时,为了保证购物系统的稳定性,部分消费者可能会被引导到一个降级的页面。 - -## 软状态 - -指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在时延。 - -## 最终一致性 - -最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能达到一致的状态。 - -ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE 要求最终一致性,通过牺牲强一致性来达到可用性,通常运用在大型分布式系统中。 - -在实际的分布式场景中,不同业务单元和组件对一致性的要求是不同的,因此 ACID 和 BASE 往往会结合在一起使用。 \ No newline at end of file diff --git "a/docs/distribution/4_\345\210\206\345\270\203\345\274\217\351\224\201.md" "b/docs/distribution/3_\345\210\206\345\270\203\345\274\217\351\224\201.md" similarity index 94% rename from "docs/distribution/4_\345\210\206\345\270\203\345\274\217\351\224\201.md" rename to "docs/distribution/3_\345\210\206\345\270\203\345\274\217\351\224\201.md" index b3f96690..12cdc4b0 100644 --- "a/docs/distribution/4_\345\210\206\345\270\203\345\274\217\351\224\201.md" +++ "b/docs/distribution/3_\345\210\206\345\270\203\345\274\217\351\224\201.md" @@ -45,7 +45,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 -
+
@@ -57,7 +57,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父节点为 /app1。 -

+

### 2. 节点类型 diff --git "a/docs/distribution/4_\345\210\206\345\270\203\345\274\217id.md" "b/docs/distribution/4_\345\210\206\345\270\203\345\274\217id.md" new file mode 100644 index 00000000..96fae9b3 --- /dev/null +++ "b/docs/distribution/4_\345\210\206\345\270\203\345\274\217id.md" @@ -0,0 +1,46 @@ +# 分布式 ID + +## 分布式 ID + +我们知道 ID 是数据的唯一标识,比如比如身份证 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品。分布式 ID 是分布式系统下的 ID,分布式 ID 不存在与现实生活中,属于计算机系统中的一个概念。一个最基本的分布式 ID 需要满足以下要求: + +- 全局唯一 + +- 高性能 + + 生成速度快,对本地资源消耗小 + +- 高可用 + + 生成分布式 ID 的服务要保证可用性无限接近于 100% + +- 拿来即可用 + +除此之外,设计一个比较好的分布式 ID 还应保证: + +- 安全性 + + ID 不应该包含敏感信息 + +- 有序递增 + + 如果要把 ID 存放在数据库的话,ID 的有序性可以提升数据库写入速度。并且,很多时候 ,我们还很有可能会直接通过 ID 来进行排序。 + +- 可独立部署 + + 独立部署就是分布式系统单独有一个**发号器服务**,专门用来生成分布式 ID。这样就生成 ID 的服务可以和业务相关的服务解耦。不过,这样同样带来了网络调用消耗增加的问题。总的来说,如果需要用到分布式 ID 的场景比较多的话,独立部署的发号器服务还是很有必要的。 + +- 包含具体业务含义 + + + +## 分布式 ID 生成方案 + +### 数据库 + +### 算法 + +### 开源框架 + + + diff --git "a/docs/distribution/5_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distribution/4_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" similarity index 93% rename from "docs/distribution/5_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" rename to "docs/distribution/4_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" index 928c4125..86081ddd 100644 --- "a/docs/distribution/5_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" +++ "b/docs/distribution/4_\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" @@ -25,7 +25,7 @@ -

+

**阶段2:提交阶段(commit phase)** @@ -33,7 +33,7 @@ 需要注意的是,在准备阶段,参与者执行了事务,但是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。 -

+

### 存在的问题 @@ -89,7 +89,7 @@ TCC 即补偿事务,其实就是采用的**补偿机制**,其核心思想是 3. 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。 4. 如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。 -
+
这种方案遵循 BASE 理论,采用的是最终一致性,笔者认为是这几种方案里面比较适合实际业务场景的,即不会出现像 2PC 那样复杂的实现(当调用链很长的时候,2PC的可用性是非常低的),也不会像TCC那样可能出现确认或者回滚不了的情况。 diff --git "a/docs/distribution/5_Paxos\347\256\227\346\263\225.md" "b/docs/distribution/5_Paxos\347\256\227\346\263\225.md" new file mode 100644 index 00000000..8815cf14 --- /dev/null +++ "b/docs/distribution/5_Paxos\347\256\227\346\263\225.md" @@ -0,0 +1,8 @@ +# 一、Paxos 算法 + +- [分布式系列文章——Paxos算法原理与推导](https://www.cnblogs.com/linbingdong/p/6253479.html) + +# 二、Raft 算法 + +- [拜占庭将军问题](https://blog.csdn.net/bjweimengshu/article/details/80222416) +- [Raft 算法动画详解](http://thesecretlivesofdata.com/raft/) \ No newline at end of file diff --git "a/docs/distribution/6_\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230\347\232\204\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214\347\256\227\346\263\225.md" "b/docs/distribution/6_\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230\347\232\204\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214\347\256\227\346\263\225.md" deleted file mode 100644 index b0bebd02..00000000 --- "a/docs/distribution/6_\345\210\206\345\270\203\345\274\217\347\274\223\345\255\230\347\232\204\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214\347\256\227\346\263\225.md" +++ /dev/null @@ -1,80 +0,0 @@ -# 分布式缓存的一致性哈希算法 - -## Hash 算法 - -根据键值,首先计算哈希值,然后对节点数取模,然后映射在不同的 Master 节点上。 - -一旦某一个 Master 节点宕机,当请求过来时,会基于最新的剩余 Master 节点数去取模,尝试去获取数据,导致大部分的请求过来,全部无法拿到有效的缓存,大量的流量涌入数据库。 - -换句话说,**当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端数据库请求数据**。 - -## 一致性 Hash 算法 - -一致性 Hash 算法将整个哈希值空间组织成一个**虚拟的圆环**,假设某哈希函数 H 的值空间为0~2^32-1(即哈希值是一个32位无符号整形)。 - -整个空间按**顺时针方向**组织,圆环的正上方的点代表0,0 点右侧的第一个点代表1,以此类推,2、3 ... 2^32-1,也就是说 0 点左侧的第一个点代表 2^32-1, 0 和 2^32-1 在零点中方向重合,我们把这个由 2^32 个点组成的圆环称为**哈希环**。 - -
- -将各个服务器进行哈希,具体可以选择服务器的 IP 或主机名作为关键字进行哈希,这样每台机器就能**确定其在哈希环上的位置**。假设将 4 台服务器的 IP 地址哈希后在哈希环的位置如下: - -
- -接下来使用如下算法定位数据访问到相应服务器: - -将数据键使用相同的函数 Hash 计算出哈希值,并确定此数据在环上的位置,从此位置**沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器**。 - -例如有 Object A、Object B、Object C、Object D 四个数据对象,经过哈希计算后,在哈希环上的位置如下: - -
- -根据一致性 Hash 算法: - -Object A 会被定位到 Node A 上; - -Object B 会被定位到 Node B 上; - -Object C 会被定位到 Node C 上; - -Object D 会被定位到 Node D 上。 - -### 容错性和可扩展性 - -假设 Node C 宕机,可以看到此时对象 A、B、D 不会受到影响,只有对象 C 被重定位到 Node D。 - -
- -通常情况下,一致性 Hash 算法中,如果一台服务器不可用,则**受影响的数据**仅仅是此服务器到其环空间中前一台服务器(即沿着**逆时针方向行走遇到的第一台服务器**)之间数据,其它数据不会受到影响。 - -下面考虑另外一种情况:如果在系统中增加一台服务器 Node X。 - -此时对象 A、B、D 不受影响,只有对象 C 需要重定位到新的Node X 。 - -
- -通常情况下,一致性 Hash 算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它数据也不会受到影响。 - -综上所述,一致性 Hash 算法对于节点的增减都只需**重定位哈希环中的一小部分数据**,具有**较好的容错性和可扩展性**。 - -### 数据倾斜问题 - -一致性 Hash 算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题。例如系统中只有 2 台服务器,如下所示: - -
- -此时必然造成大量数据集中到 Node A 上,而只有极少量会定位到 Node B 上。 - -为了解决这种数据倾斜问题,一致性 Hash 算法引入了**虚拟节点机制**,即**对每一个服务节点计算多个哈希**,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器 IP 或主机名的后面增加编号来实现。 - -例如针对上面的情况,可以为每台服务器计算 3 个虚拟节点: - -- Node A 的 3 个虚拟节点:"Node A#1"、"Node A#2"、"Node A#3" -- Node B 的 3 个虚拟节点:"Node B#1"、"Node B#2"、"Node B#3" - -进行哈希计算后,六个虚拟节点在哈希环中的位置如下: - -
- -同时**数据定位算法不变**,只是多了一步虚拟节点到实际节点的映射过程,例如"Node A#1"、"Node A#2"、"Node A#3" 这 3 个虚拟节点的数据均定位到 Node A 上,解决了服务节点少时数据倾斜的问题。 - -在实际应用中,通常将虚拟节点数设置为 32 甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。 \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 5d0be969..018c63a2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,7 +6,7 @@ - +