Compare commits
6 Commits
ff9efdd3d0
...
26afcc7706
Author | SHA1 | Date | |
---|---|---|---|
|
26afcc7706 | ||
|
44b39e9866 | ||
|
b59f2cc30a | ||
|
4d09f56304 | ||
|
15712fcccd | ||
|
d7ae36692f |
24
README.md
@ -34,10 +34,10 @@
|
||||
|
||||
你可能需要:
|
||||
|
||||
* [项目介绍](./docs/javaguide/intro)
|
||||
* [贡献指南](./docs/javaguide/contribution-guideline)
|
||||
* [常见问题](./docs/javaguide/faq)
|
||||
* [项目代办](./docs/javaguide/todo)
|
||||
* [项目介绍](./docs/javaguide/intro.md)
|
||||
* [贡献指南](./docs/javaguide/contribution-guideline.md)
|
||||
* [常见问题](./docs/javaguide/faq.md)
|
||||
* [项目代办.md](./docs/javaguide/todo)
|
||||
|
||||
## Java
|
||||
|
||||
@ -92,14 +92,14 @@
|
||||
|
||||
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机(第3版)》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
|
||||
|
||||
1. **[Java 内存区域](https://javaguide.cn/java/jvm/jvm-garbage-collection/)**
|
||||
2. **[JVM 垃圾回收](https://javaguide.cn/java/jvm/jvm-garbage-collection/)**
|
||||
3. [JDK 监控和故障处理工具](https://javaguide.cn/java/jvm/jdk-monitoring-and-troubleshooting-tools/)
|
||||
4. [类文件结构](https://javaguide.cn/java/jvm/class-file-structure/)
|
||||
5. **[类加载过程](https://javaguide.cn/java/jvm/class-loading-process/)**
|
||||
6. [类加载器](https://javaguide.cn/java/jvm/classloader/)
|
||||
7. **[【待完成】最重要的 JVM 参数总结(翻译完善了一半)](https://javaguide.cn/java/jvm/jvm-parameters-intro/)**
|
||||
8. **[【加餐】大白话带你认识 JVM](https://javaguide.cn/java/jvm/jvm-intro/)**
|
||||
1. **[Java 内存区域](./docs/java/jvm/memory-area)**
|
||||
2. **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)**
|
||||
3. [JDK 监控和故障处理工具](./docs/java/jvm/jdk-monitoring-and-troubleshooting-tools.md)
|
||||
4. [类文件结构](./docs/java/jvm/class-file-structure.md)
|
||||
5. **[类加载过程](./docs/java/jvm/class-loading-process.md)**
|
||||
6. [类加载器](./docs/java/jvm/classloader.md)
|
||||
7. **[【待完成】最重要的 JVM 参数总结(翻译完善了一半)](./docs/java/jvm/jvm-parameters-intro.md)**
|
||||
8. **[【加餐】大白话带你认识 JVM](./docs/java/jvm/jvm-intro.md)**
|
||||
|
||||
### 新特性
|
||||
|
||||
|
@ -109,7 +109,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
|
||||
#### 数字签名
|
||||
|
||||
好,到这一小节,已经是 SSL/TLS 的尾声了。上一小节提到了数字签名,数字签名要解决的问题,是防止证书被伪造。第三方信赖机构 CA 之所以能被信赖,就是靠数字签名技术。
|
||||
好,到这一小节,已经是 SSL/TLS 的尾声了。上一小节提到了数字签名,数字签名要解决的问题,是防止证书被伪造。第三方信赖机构 CA 之所以能被信赖,就是 **靠数字签名技术** 。
|
||||
|
||||
数字签名,是 CA 在给服务器颁发证书时,使用散列+加密的组合技术,在证书上盖个章,以此来提供验伪的功能。具体行为如下:
|
||||
|
||||
@ -121,24 +121,20 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
|
||||

|
||||
|
||||
注意,验证身份的证书一定是由 CA 的公钥进行签名,而不能由发送者自己来签名。这是为了抵抗以下的攻击场景:
|
||||
|
||||
> 攻击者使用某种手段,欺骗了客户端,将服务器的公钥替换为攻击者的诱饵公钥。
|
||||
>
|
||||
> 假使证书的签名使用的是服务器的私钥,那么客户端在解码的时候,将会使用假的服务器公钥(实则为诱饵公钥)。那么,如果该证书实则由攻击者(使用自己的私钥签名)发出,那么客户端就会成功验证(攻击者的)身份为真,从而信赖了证书中的公钥。
|
||||
>
|
||||
> 如果使用 CA 的私钥和公钥来对签名处理,则不会出现上述问题。
|
||||
|
||||
总结来说,带有证书的公钥传输机制如下:
|
||||
|
||||
1. 设有服务器 S,客户端 C,和第三方信赖机构 CA。
|
||||
2. S 信任 CA,CA 是知道 S 公钥的,CA 向 S 颁发证书。并附上 CA 私钥对消息摘要的加密签名。
|
||||
3. S 获得 CA 颁发的证书,将该证书传递给 C。
|
||||
4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书山的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
|
||||
4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
|
||||
5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。
|
||||
|
||||

|
||||
|
||||
对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看[数字签名及数字证书原理](https://www.bilibili.com/video/BV18N411X7ty/)这个视频,这是我看过最清晰的讲解。
|
||||
|
||||

|
||||
|
||||
## 总结
|
||||
|
||||
- **端口号** :HTTP 默认是 80,HTTPS 默认是 443。
|
||||
|
@ -136,7 +136,7 @@ tag:
|
||||
|
||||
👨💻**面试官** :**你知道什么是死锁吗?**
|
||||
|
||||
🙋 **我** :多个进程可以竞争有限数量的资源。当一个进程申请资源时,如果这时没有可用资源,那么这个进程进入等待状态。有时,如果所申请的资源被其他等待进程占有,那么该等待进程有可能再也无法改变状态。这种情况称为 **死锁**。
|
||||
🙋 **我** :死锁描述的是这样一种情况:多个进程/线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于进程/线程被无限期地阻塞,因此程序不可能正常终止。
|
||||
|
||||
### 2.7 死锁的四个条件
|
||||
|
||||
|
@ -117,7 +117,7 @@ tag:
|
||||
|
||||
* drop(丢弃数据): `drop table 表名` ,直接将表都删除掉,在删除表的时候使用。
|
||||
* truncate (清空数据) : `truncate table 表名` ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。
|
||||
* delete(删除数据) : `delete from 表名 where 列名=值`,删除某一列的数据,如果不加 where 子句和`truncate table 表名`作用类似。
|
||||
* delete(删除数据) : `delete from 表名 where 列名=值`,删除某一行的数据,如果不加 where 子句和`truncate table 表名`作用类似。
|
||||
|
||||
truncate 和不带 where 子句的 delete、以及 drop 都会删除表内的数据,但是 **truncate 和 delete 只删除数据不删除表的结构(定义),执行 drop 语句,此表的结构也会删除,也就是执行 drop 之后对应的表不复存在。**
|
||||
|
||||
|
@ -2,21 +2,25 @@
|
||||
|
||||
在分布式系统中,不同的节点进行数据/信息共享是一个基本的需求。
|
||||
|
||||
比较简单粗暴的方法集中式发散消息,简单来说就是一个主节点同时共享最新信息给其他所有节点。但是,这种方法缺陷太多,节点多的时候不光同步消息的效率低,还太依赖与主节点,存在单点风险。
|
||||
一种比较简单粗暴的方法就是 **集中式发散消息**,简单来说就是一个主节点同时共享最新信息给其他所有节点,比较适合中心化系统。这种方法的缺陷也很明显,节点多的时候不光同步消息的效率低,还太依赖与中心节点,存在单点风险问题。
|
||||
|
||||
于是,分散式发散消息的 Gossip 协议就诞生了。
|
||||
于是,**分散式发散消息** 的 **Gossip 协议** 就诞生了。
|
||||
|
||||
## Gossip 协议介绍
|
||||
|
||||
Gossip 直译过来就是闲话、流言蜚语的意思。流言蜚语有什么特点呢?容易被传播,你传我我传他,然后大家都知道了。
|
||||
Gossip 直译过来就是闲话、流言蜚语的意思。流言蜚语有什么特点呢?容易被传播且传播速度还快,你传我我传他,然后大家都知道了。
|
||||
|
||||
Gossip 协议也叫 Epidemic 协议(流行病协议)或者 Epidemic propagation 算法(疫情传播算法),别名很多。不过,这些名字的特点是都具有 **随机传播特性** 的特点(联想一下病毒传播、癌细胞扩散等生活中常见的情景),这也正是 Gossip 协议最主要的特点。
|
||||

|
||||
|
||||
Gossip 协议也叫 Epidemic 协议(流行病协议)或者 Epidemic propagation 算法(疫情传播算法),别名很多。不过,这些名字的特点都具有 **随机传播特性** (联想一下病毒传播、癌细胞扩散等生活中常见的情景),这也正是 Gossip 协议最主要的特点。
|
||||
|
||||
Gossip 协议最早是在 ACM 上的一篇 1987 年发表的论文 [《Epidemic Algorithms for Replicated Database Maintenance》](https://dl.acm.org/doi/10.1145/41840.41841)中被提出的。根据论文标题,我们大概就能知道 Gossip 协议当时提出的主要应用是在分布式数据库系统中各个副本节点同步数据。
|
||||
|
||||
正如其名一样,这是一种随机且带有传染性的方式将信息传播到整个网络中,并在一定时间内,使得系统内的所有节点数据一致。
|
||||
正如 Gossip 协议其名一样,这是一种随机且带有传染性的方式将信息传播到整个网络中,并在一定时间内,使得系统内的所有节点数据一致。
|
||||
|
||||
下面我们来对 Gossip 协议的定义做一个总结: **Gossip 协议是一种允许在分布式系统中共享状态的通信协议,通过这种通信协议,我们可以将信息传播给网络或集群中的所有成员。**
|
||||
在 Gossip 协议下,没有所谓的中心节点,每个节点周期性地随机找一个节点互相同步彼此的信息,理论上来说,各个节点的状态最终会保持一致。
|
||||
|
||||
下面我们来对 Gossip 协议的定义做一个总结: **Gossip 协议是一种允许在分布式系统中共享状态的去中心化通信协议,通过这种通信协议,我们可以将信息传播给网络或集群中的所有成员。**
|
||||
|
||||
## Gossip 协议应用
|
||||
|
||||
|
After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 5.1 KiB |
@ -5,5 +5,78 @@ tag:
|
||||
- 分布式协议&算法
|
||||
---
|
||||
|
||||
Paxos 算法诞生于 1990 年,这是一种解决分布式系统一致性的经典算法 。但是,由于 Paxos 算法在国际上被公认的非常难以理解和实现,因此不断有人尝试简化这一算法。到了2013 年才诞生了一个比 Paxos 算法更易理解和实现的分布式一致性算法—[Raft 算法](https://javaguide.cn/distributed-system/theorem&algorithm&protocol/raft-algorithm/)。
|
||||
## 背景
|
||||
|
||||
|
||||
|
||||
## Paxos 算法介绍
|
||||
|
||||
Paxos 算法是 Leslie Lamport([莱斯利·兰伯特](https://zh.wikipedia.org/wiki/莱斯利·兰伯特))在 **1990** 年提出了一种分布式系统共识算法。
|
||||
|
||||
> 很多人会误把 Paxos 看作是一致性算法。
|
||||
>
|
||||
> ⚠️注意:**Paxos 不是一致性算法而是共识算法,一致性和共识并不是一个概念。**
|
||||
|
||||
为了介绍 Paxos 算法,兰伯特专门写了一篇幽默风趣的论文。在这篇论文中,他虚拟了一个叫做 Paxos 的希腊城邦来更形象化地介绍 Paxos 算法。不过,审稿人可不觉得论文太幽默是一件好事,他们就给兰伯特说:“如果你想要成功发表这篇论文的话,必须删除所有 Paxos 相关的故事背景”。兰伯特一听就不开心了:“我凭什么修改啊,你们这些审稿人就是缺乏幽默细胞,发不了就不发了呗!”。
|
||||
|
||||
于是乎,提出 Paxos 算法的那篇论文在当时并没有被成功发表。
|
||||
|
||||
直到 1998 年,系统研究中心 (Systems Research Center,SRC)的两个大佬需要找一些合适的算法来服务他们正在构建的分布式系统,Paxos 算法刚好可以解决他们的部分需求。因此,兰伯特就把论文发给了他们。在看了论文之后,这俩大佬觉得论文还是挺不错的。于是,兰伯特在 **1998** 年重新发表论文 [《The Part-Time Parliament》](http://lamport.azurewebsites.net/pubs/lamport-paxos.pdf)。
|
||||
|
||||
论文发表之后,各路学者直呼看不懂,言语中还略显调侃之意。这谁忍得了,在 **2001** 年的时候,兰伯特又写了一篇 [《Paxos Made Simple》](http://lamport.azurewebsites.net/pubs/paxos-simple.pdf) 的论文来简化对 Paxos 的介绍,主要讲述两阶段共识协议部分。
|
||||
|
||||
这篇论文就 14 页,相比于 《The Part-Time Parliament》的33 页精简了不少。最关键的是这篇论文的摘要就一句话:
|
||||
|
||||

|
||||
|
||||
> The Paxos algorithm, when presented in plain English, is very simple.
|
||||
|
||||
翻译过来的意思大概就是:当我用无修饰的英文来描述时,Paxos 算法真心简单!
|
||||
|
||||
有没有感觉到来自兰伯特大佬满满地嘲讽的味道?
|
||||
|
||||
兰伯特当时提出的 Paxos 算法主要包含 2 个部分:
|
||||
|
||||
- **Basic Paxos 算法** : 描述的是多节点之间如何就某个值(提案 Value)达成共识。
|
||||
- **Multi-Paxos 思想** : 描述的是执行多个 Basic Paxos 实例,就一系列值达成共识。Multi-Paxos 说白了就是执行多次 Basic Paxos ,核心还是 Basic Paxos 。
|
||||
|
||||
由于 Paxos 算法在国际上被公认的非常难以理解和实现,因此不断有人尝试简化这一算法。到了2013 年才诞生了一个比 Paxos 算法更易理解和实现的共识算法—[Raft 算法](https://javaguide.cn/distributed-system/theorem&algorithm&protocol/raft-algorithm.html) 。更具体点来说,Raft 是Multi-Paxos的一个变种,其简化了 Multi-Paxos 的思想,变得更容易被理解以及工程实现。
|
||||
|
||||
Paxos是第一个被证明完备的共识算法(前提是不存在拜占庭将军问题,也就是没有恶意节点),除了 Raft 算法之外,当前最常用的一些共识算法比如 ZAB 协议、 Fast Paxos 算法都是基于 Paxos 算法改进的。
|
||||
|
||||
针对存在恶意节点的情况,一般使用的是工作量证明(POW,Proof-of-Work)、权益证明(PoS,Proof-of-Stake )等共识算法。这类共识算法最典型的应用就是区块链,就比如说前段时间以太坊官方宣布其共识机制正在从工作量证明(PoW)转变为权益证明(PoS)。
|
||||
|
||||
区块链系统使用的共识算法需要解决的核心问题是 **拜占庭将军问题** ,这和我们日常接触到的 ZooKeeper、Etcd、Consul 等分布式中间件不太一样。
|
||||
|
||||
下面我们来对 Paxos 算法的定义做一个总结:
|
||||
|
||||
- Paxos 算法是兰伯特在 **1990** 年提出了一种分布式系统共识算法。
|
||||
- 兰伯特当时提出的 Paxos 算法主要包含 2 个部分:Basic Paxos 算法和Multi-Paxos 思想。
|
||||
- Raft 算法、ZAB 协议、 Fast Paxos 算法都是基于 Paxos 算法改进而来。。
|
||||
|
||||
## 一致性(Consistency)与共识(Consensus)
|
||||
|
||||
|
||||
|
||||
## Basic Paxos 算法
|
||||
|
||||
Basic Paxos 中存在 3 个重要的角色:
|
||||
|
||||
1. **提议者(Proposer)**:也可以叫做协调者(coordinator),提议者负责接受客户端发起的提议,然后尝试让接受者接受该提议,同时保证即使多个提议者的提议之间产生了冲突,那么算法都能进行下去;
|
||||
2. **接受者(Acceptor)**:也可以叫做投票员(voter),负责对提议者的提议投票,同时需要记住自己的投票历史;
|
||||
3. **学习者(Learner)**:如果有超过半数接受者就某个提议达成了共识,那么学习者就需要接受这个提议,并就该提议作出运算,然后将运算结果返回给客户端。
|
||||
|
||||

|
||||
|
||||
## Multi Paxos 思想
|
||||
|
||||
因为兰伯特提到的 Multi-Paxos 思想,缺少代码实现的必要细节(比如怎么选举领导者),所以在理解上比较难。
|
||||
|
||||
⚠️**注意** : Multi-Paxos 只是一种思想,这种思想的核心就是通过多个 Basic Paxos 实例就一系列值达成共识。
|
||||
|
||||
二阶段提交是达成共识常用的方式,Basic Paxos 就是通过二阶段提交的方式来达成共识。Basic Paxos 还支持容错,少于一般的节点出现故障时,集群也能正常工作。
|
||||
|
||||
## 参考
|
||||
|
||||
- https://zh.wikipedia.org/wiki/Paxos
|
||||
- 分布式系统中的一致性与共识算法:http://www.xuyasong.com/?p=1970
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@ -266,7 +266,28 @@ public final class String implements java.io.Serializable, Comparable<String>, C
|
||||
>
|
||||
> 相关阅读:[如何理解 String 类型值的不可变? - 知乎提问](https://www.zhihu.com/question/20618891/answer/114125846)
|
||||
>
|
||||
> 补充(来自[issue 675](https://github.com/Snailclimb/JavaGuide/issues/675)):在 Java 9 之后,`String` 、`StringBuilder` 与 `StringBuffer` 的实现改用 byte 数组存储字符串。
|
||||
> 补充(来自[issue 675](https://github.com/Snailclimb/JavaGuide/issues/675)):在 Java 9 之后,`String` 、`StringBuilder` 与 `StringBuffer` 的实现改用 `byte` 数组存储字符串。
|
||||
>
|
||||
> ```java
|
||||
> public final class String implements java.io.Serializable,Comparable<String>, CharSequence {
|
||||
> // @Stable 注解表示变量最多被修改一次,称为“稳定的”。
|
||||
> @Stable
|
||||
> private final byte[] value;
|
||||
> }
|
||||
>
|
||||
> abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
> byte[] value;
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> **Java 9 为何要将 `String` 的底层实现由 `char[]` 改成了 `byte[]` ?**
|
||||
>
|
||||
> 新版的 String 其实支持两个编码方案: Latin-1 和 UTF-16。如果字符串中包含的汉字没有超过 Latin-1 可表示范围内的字符,那就会使用 Latin-1 作为编码方案。Latin-1 编码方案下,`byte` 占一个字节(8位),`char` 占用2个字节(16),`byte` 相较 `char` 节省一半的内存空间。
|
||||
>
|
||||
> 如果字符串中包含的汉字超过 Latin-1 可表示范围内的字符,`byte` 和 `char` 所占用的空间是一样的。
|
||||
>
|
||||
> 这是官方的介绍:https://openjdk.java.net/jeps/254 。
|
||||
|
||||
`StringBuilder` 与 `StringBuffer` 都继承自 `AbstractStringBuilder` 类,在 `AbstractStringBuilder` 中也是使用字符数组保存字符串,不过没有使用 `final` 和 `private` 关键字修饰,最关键的是这个 `AbstractStringBuilder` 类还提供了很多修改字符串的方法比如 `append` 方法。
|
||||
|
||||
|
@ -204,10 +204,6 @@ JDK 提供了很多内置的注解(比如 `@Override` 、`@Deprecated`),
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
<p style="font-size:13px;text-align:right">图片来自:https://chercher.tech/java-programming/exceptions-java</p>
|
||||
|
||||
### Exception 和 Error 有什么区别?
|
||||
|
||||
在 Java 中,所有的异常都有一个共同的祖先 `java.lang` 包中的 `Throwable` 类。`Throwable` 类有两个重要的子类:
|
||||
|
@ -92,8 +92,8 @@ public class MultiThread {
|
||||
|
||||
## 说说并发与并行的区别?
|
||||
|
||||
- **并发:** 同一时间段,多个任务都在执行 (单位时间内不一定同时执行);
|
||||
- **并行:** 单位时间内,多个任务同时执行。
|
||||
- **并发**:两个及两个以上的作业在同一 **时间段** 内执行。
|
||||
- **并行**:两个及两个以上的作业在同一 **时刻** 执行。
|
||||
|
||||
## 为什么要使用多线程呢?
|
||||
|
||||
|
@ -24,5 +24,5 @@ category: 开源项目
|
||||
## Markdown
|
||||
|
||||
- **[MarkText](https://github.com/marktext/marktext)** :一个简单而优雅的开源 Markdown 编辑器,专注于速度和可用性。Linux、macOS 和 Windows 均适用。
|
||||
- **[Typora](https://www.typora.io/)** :我一直用的一款 Markdown 工具,直接文件夹试图和目录试图,支持 Markdown 格式直接导出成 PDF、HTML 等格式。
|
||||
- **[Markdown Here](https://github.com/adam-p/markdown-here)** :使用 Markdown 语法发邮件,并且提供多种主题,快来拯救你的邮件格式吧!
|
||||
- **[Typora](https://www.typora.io/)** :我一直用的一款 Markdown 工具,直接文件夹视图和目录视图,支持 Markdown 格式直接导出成 PDF、HTML 等格式。
|
||||
- **[Markdown Here](https://github.com/adam-p/markdown-here)** :使用 Markdown 语法发邮件,并且提供多种主题,快来拯救你的邮件格式吧!
|
||||
|