Skip to content

Commit 048d5a9

Browse files
authored
Merge pull request Snailclimb#1 from Snailclimb/master
Merge
2 parents 83c3f0b + a0c9f93 commit 048d5a9

20 files changed

+1114
-106
lines changed

README.md

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
22

3-
**[推荐一下阿里云双11的活动:云服务器1折起,仅86元/年,限量抢购!](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** (仅限新人,老用户可以考虑使用家人或者朋友账号购买,推荐799/3年 2核4G 这个性价比和适用面更广
3+
**[推荐一下阿里云双11的活动:云服务器1折起,仅86元/年,限量抢购!](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** (仅限新人,老用户可以考虑使用家人或者朋友账号购买,推荐799/3年 2核4G 这个性价比和适用面更广。不懂怎么使用云服务器的朋友可以看这篇[阿里云服务器使用经验](docs/tools/阿里云服务器使用经验.md))。
44

55
<p align="center">
66
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
@@ -35,22 +35,29 @@
3535
- [JVM](#jvm)
3636
- [I/O](#io)
3737
- [Java 8](#java-8)
38-
- [编程规范](#编程规范)
38+
- [优雅 Java 代码必备实践(Java编程规范)](#优雅-java-代码必备实践java编程规范)
3939
- [网络](#网络)
4040
- [操作系统](#操作系统)
41+
4142
- [Linux相关](#linux相关)
4243
- [数据结构与算法](#数据结构与算法)
4344
- [数据结构](#数据结构)
4445
- [算法](#算法)
4546
- [数据库](#数据库)
4647
- [MySQL](#mysql)
4748
- [Redis](#redis)
49+
- [数据库扩展](#数据库扩展)
4850
- [系统设计](#系统设计)
4951
- [常用框架(Spring/SpringBoot、Zookeeper ... )](#常用框架)
50-
- [数据通信(消息队列、Dubbo ... )](#数据通信)
52+
- [数据通信/中间件(消息队列、RPC ... )](#数据通信中间件)
5153
- [权限认证](#权限认证)
54+
- [分布式 & 微服务](#分布式--微服务)
55+
- [API 网关](#api-网关)
56+
- [配置中心](#配置中心)
57+
- [唯一 id 生成](#唯一-id-生成)
58+
- [服务治理:服务注册与发现、服务路由控制](#服务治理服务注册与发现服务路由控制)
59+
- [架构](#架构)
5260
- [设计模式(工厂模式、单例模式 ... )](#设计模式)
53-
- [网站架构](#网站架构)
5461
- [面试指南](#面试指南)
5562
- [备战面试](#备战面试)
5663
- [常见面试题总结](#常见面试题总结)
@@ -110,9 +117,9 @@
110117
* [Java 8 学习资源推荐](docs/java/What's%20New%20in%20JDK8/Java8教程推荐.md)
111118
* [Java8 forEach 指南](docs/java/What's%20New%20in%20JDK8/Java8foreach指南.md)
112119

113-
### 编程规范
120+
### 优雅 Java 代码必备实践(Java编程规范)
114121

115-
- [Java 编程规范](docs/java/Java编程规范.md)
122+
* [Java 编程规范以及优雅Java代码实践总结](docs/java/Java编程规范.md)
116123

117124
## 网络
118125

@@ -159,6 +166,11 @@
159166
* [Redis 总结](docs/database/Redis/Redis.md)
160167
* [Redlock分布式锁](docs/database/Redis/Redlock分布式锁.md)
161168
* [如何做可靠的分布式锁,Redlock真的可行么](docs/database/Redis/如何做可靠的分布式锁,Redlock真的可行么.md)
169+
* [几种常见的 Redis 集群以及使用场景](docs/database/Redis/redis集群以及应用场景.md)
170+
171+
### 数据库扩展
172+
173+
代办......
162174

163175
## 系统设计
164176

@@ -178,15 +190,16 @@
178190
- [ZooKeeper 相关概念总结](docs/system-design/framework/ZooKeeper.md)
179191
- [ZooKeeper 数据模型和常见命令](docs/system-design/framework/ZooKeeper数据模型和常见命令.md)
180192

181-
### 数据通信
193+
### 数据通信/中间件
182194

183195
- [数据通信(RESTful、RPC、消息队列)相关知识点总结](docs/system-design/data-communication/summary.md)
184196

185-
#### Dubbo
197+
#### RPC
186198

187199
- [Dubbo 总结:关于 Dubbo 的重要知识点](docs/system-design/data-communication/dubbo.md)
200+
- [服务之间的调用为啥不直接用 HTTP 而用 RPC?](docs/system-design/data-communication/why-use-rpc.md)
188201

189-
#### 消息中间件
202+
#### 消息队列
190203

191204
- [消息队列总结](docs/system-design/data-communication/message-queue.md)
192205
- [RabbitMQ 入门](docs/system-design/data-communication/rabbitmq.md)
@@ -200,15 +213,36 @@
200213
- **[JWT 优缺点分析以及常见问题解决方案](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)**
201214
- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)**
202215

203-
### 设计模式
216+
### 分布式 & 微服务
204217

205-
- [设计模式系列文章](docs/system-design/设计模式.md)
218+
- [分布式应该学什么](docs/system-design/website-architecture/分布式.md)
219+
220+
#### API 网关
221+
222+
网关主要用于请求转发、安全认证、协议转换、容灾。
223+
224+
- [浅析如何设计一个亿级网关(API Gateway)](docs/system-design/micro-service/API网关.md)
225+
226+
#### 配置中心
227+
228+
代办......
229+
230+
#### 唯一 id 生成
206231

207-
### 网站架构
232+
[分布式id生成方案总结](docs/system-design/micro-service/分布式id生成方案总结.md)
233+
234+
#### 服务治理:服务注册与发现、服务路由控制
235+
236+
代办......
237+
238+
### 架构
208239

209-
- [一文读懂分布式应该学什么](docs/system-design/website-architecture/分布式.md)
210240
- [8 张图读懂大型网站技术架构](docs/system-design/website-architecture/8%20张图读懂大型网站技术架构.md)
211-
- [【面试精选】关于大型网站系统架构你不得不懂的10个问题](docs/system-design/website-architecture/【面试精选】关于大型网站系统架构你不得不懂的10个问题.md)
241+
- [【面试精选】关于大型网站系统架构你不得不懂的10个问题](docs/system-design/website-architecture/关于大型网站系统架构你不得不懂的10个问题.md)
242+
243+
### 设计模式
244+
245+
- [设计模式系列文章](docs/system-design/设计模式.md)
212246

213247
## 面试指南
214248

@@ -239,6 +273,7 @@
239273

240274
- [Java学习路线和方法推荐](docs/questions/java-learning-path-and-methods.md)
241275
- [Java培训四个月能学会吗?](docs/questions/java-training-4-month.md)
276+
- [新手学习Java,有哪些Java相关的博客,专栏,和技术学习网站推荐?](docs/questions/java-learning-website-blog.md)
242277

243278
## 工具
244279

@@ -248,9 +283,13 @@
248283

249284
### Docker
250285

251-
* [Docker 入门](docs/tools/Docker.md)
286+
* [Docker 基本概念解读](docs/tools/Docker.md)
252287
* [一文搞懂 Docker 镜像的常用操作!](docs/tools/Docker-Image.md)
253288

289+
### 其他
290+
291+
- [阿里云服务器使用经验](docs/tools/阿里云服务器使用经验.md)
292+
254293
## 资源
255294

256295
### 书单
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
相关阅读:
2+
3+
- [史上最全Redis高可用技术解决方案大全](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484850&idx=1&sn=3238360bfa8105cf758dcf7354af2814&chksm=cea24a79f9d5c36fb2399aafa91d7fb2699b5006d8d037fe8aaf2e5577ff20ae322868b04a87&token=1082669959&lang=zh_CN&scene=21#wechat_redirect)
4+
5+
# Redis 集群以及应用
6+
7+
## 集群
8+
### 主从复制
9+
#### 主从链(拓扑结构)
10+
![主从](https://user-images.githubusercontent.com/26766909/67539461-d1a26c00-f714-11e9-81ae-61fa89faf156.png)
11+
12+
![主从](https://user-images.githubusercontent.com/26766909/67539485-e0891e80-f714-11e9-8980-d253239fcd8b.png)
13+
14+
#### 复制模式
15+
- 全量复制:master 全部同步到 slave
16+
- 部分复制:slave 数据丢失进行备份
17+
18+
#### 问题点
19+
- 同步故障
20+
- 复制数据延迟(不一致)
21+
- 读取过期数据(Slave 不能删除数据)
22+
- 从节点故障
23+
- 主节点故障
24+
- 配置不一致
25+
- maxmemory 不一致:丢失数据
26+
- 优化参数不一致:内存不一致.
27+
- 避免全量复制
28+
- 选择小主节点(分片)、低峰期间操作.
29+
- 如果节点运行 id 不匹配(如主节点重启、运行 id 发送变化),此时要执行全量复制,应该配合哨兵和集群解决.
30+
- 主从复制挤压缓冲区不足产生的问题(网络中断,部分复制无法满足),可增大复制缓冲区( rel_backlog_size 参数).
31+
- 复制风暴
32+
33+
### 哨兵机制
34+
#### 拓扑图
35+
![image](https://user-images.githubusercontent.com/26766909/67539495-f0086780-f714-11e9-9eab-c11a163ac6c0.png)
36+
37+
#### 节点下线
38+
- 客观下线
39+
- 所有 Sentinel 节点对 Redis 节点失败要达成共识,即超过 quorum 个统一.
40+
- 主管下线
41+
- 即 Sentinel 节点对 Redis 节点失败的偏见,超出超时时间认为 Master 已经宕机.
42+
#### leader选举
43+
- 选举出一个 Sentinel 作为 Leader:集群中至少有三个 Sentinel 节点,但只有其中一个节点可完成故障转移.通过以下命令可以进行失败判定或领导者选举.
44+
- 选举流程
45+
1. 每个主观下线的 Sentinel 节点向其他 Sentinel 节点发送命令,要求设置它为领导者.
46+
1. 收到命令的 Sentinel 节点如果没有同意通过其他 Sentinel 节点发送的命令,则同意该请求,否则拒绝.
47+
1. 如果该 Sentinel 节点发现自己的票数已经超过 Sentinel 集合半数且超过 quorum,则它成为领导者.
48+
1. 如果此过程有多个 Sentinel 节点成为领导者,则等待一段时间再重新进行选举.
49+
#### 故障转移
50+
- 转移流程
51+
1. Sentinel 选出一个合适的 Slave 作为新的 Master(slaveof no one 命令).
52+
1. 向其余 Slave 发出通知,让它们成为新 Master 的 Slave( parallel-syncs 参数).
53+
1. 等待旧 Master 复活,并使之称为新 Master 的 Slave.
54+
1. 向客户端通知 Master 变化.
55+
- 从 Slave 中选择新 Master 节点的规则(slave 升级成 master 之后)
56+
1. 选择 slave-priority 最高的节点.
57+
1. 选择复制偏移量最大的节点(同步数据最多).
58+
1. 选择 runId 最小的节点.
59+
#### 读写分离
60+
#### 定时任务
61+
- 每 1s 每个 Sentinel 对其他 Sentinel 和 Redis 执行 ping,进行心跳检测.
62+
- 每 2s 每个 Sentinel 通过 Master 的 Channel 交换信息(pub - sub).
63+
- 每 10s 每个 Sentinel 对 Master 和 Slave 执行 info,目的是发现 Slave 节点、确定主从关系.
64+
65+
### 分布式集群(Cluster)
66+
#### 拓扑图
67+
68+
![image](https://user-images.githubusercontent.com/26766909/67539510-f8f93900-f714-11e9-9d8d-08afdecff95a.png)
69+
70+
#### 通讯
71+
##### 集中式
72+
> 将集群元数据(节点信息、故障等等)几种存储在某个节点上.
73+
- 优势
74+
1. 元数据的更新读取具有很强的时效性,元数据修改立即更新
75+
- 劣势
76+
1. 数据集中存储
77+
##### Gossip
78+
![image](https://user-images.githubusercontent.com/26766909/67539546-16c69e00-f715-11e9-9891-1e81b6af624c.png)
79+
80+
- [Gossip 协议](https://www.jianshu.com/p/8279d6fd65bb)
81+
82+
#### 寻址分片
83+
##### hash取模
84+
- hash(key)%机器数量
85+
- 问题
86+
1. 机器宕机,造成数据丢失,数据读取失败
87+
1. 伸缩性
88+
##### 一致性hash
89+
- ![image](https://user-images.githubusercontent.com/26766909/67539595-352c9980-f715-11e9-8e4a-9d9c04027785.png)
90+
91+
- 问题
92+
1. 一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成缓存热点的问题。
93+
- 解决方案
94+
- 可以通过引入虚拟节点机制解决:即对每一个节点计算多个 hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。
95+
##### hash槽
96+
- CRC16(key)%16384
97+
-
98+
![image](https://user-images.githubusercontent.com/26766909/67539610-3fe72e80-f715-11e9-8e0d-ea58bc965795.png)
99+
100+
101+
102+
103+
104+
105+
## 使用场景
106+
### 热点数据
107+
### 会话维持 session
108+
### 分布式锁 SETNX
109+
### 表缓存
110+
### 消息队列 list
111+
### 计数器 string
112+
113+
114+
115+
116+
117+
## 缓存设计
118+
### 更新策略
119+
- LRU、LFU、FIFO 算法自动清除:一致性最差,维护成本低.
120+
- 超时自动清除(key expire):一致性较差,维护成本低.
121+
- 主动更新:代码层面控制生命周期,一致性最好,维护成本高.
122+
### 更新一致性
123+
- 读请求:先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应.
124+
- 写请求:先删除缓存,然后再更新数据库(避免大量地写、却又不经常读的数据导致缓存频繁更新).
125+
### 缓存粒度
126+
- 通用性:全量属性更好.
127+
- 占用空间:部分属性更好.
128+
- 代码维护成本.
129+
130+
### 缓存穿透
131+
> 当大量的请求无命中缓存、直接请求到后端数据库(业务代码的 bug、或恶意攻击),同时后端数据库也没有查询到相应的记录、无法添加缓存.
132+
这种状态会一直维持,流量一直打到存储层上,无法利用缓存、还会给存储层带来巨大压力.
133+
>
134+
#### 解决方案
135+
1. 请求无法命中缓存、同时数据库记录为空时在缓存添加该 key 的空对象(设置过期时间),缺点是可能会在缓存中添加大量的空值键(比如遭到恶意攻击或爬虫),而且缓存层和存储层数据短期内不一致;
136+
1. 使用布隆过滤器在缓存层前拦截非法请求、自动为空值添加黑名单(同时可能要为误判的记录添加白名单).但需要考虑布隆过滤器的维护(离线生成/ 实时生成).
137+
### 缓存雪崩
138+
> 缓存崩溃时请求会直接落到数据库上,很可能由于无法承受大量的并发请求而崩溃,此时如果只重启数据库,或因为缓存重启后没有数据,新的流量进来很快又会把数据库击倒
139+
>
140+
#### 出现后应对
141+
- 事前:Redis 高可用,主从 + 哨兵,Redis Cluster,避免全盘崩溃.
142+
- 事中:本地 ehcache 缓存 + hystrix 限流 & 降级,避免数据库承受太多压力.
143+
- 事后:Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据.
144+
#### 请求过程
145+
1. 用户请求先访问本地缓存,无命中后再访问 Redis,如果本地缓存和 Redis 都没有再查数据库,并把数据添加到本地缓存和 Redis;
146+
1. 由于设置了限流,一段时间范围内超出的请求走降级处理(返回默认值,或给出友情提示).
147+
148+
149+

docs/database/事务隔离级别(图文详解).md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131

3232
1. **原子性:** 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
33-
2. **一致性:** 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的
33+
2. **一致性:** 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的
3434
3. **隔离性:** 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
3535
4. **持久性:** 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
3636

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
- 公众号和Github待发文章:[数据库:数据库连接池原理详解与自定义连接池实现](https://www.fangzhipeng.com/javainterview/2019/07/15/mysql-connector-pool.html)
2+
- [基于JDBC的数据库连接池技术研究与应用](http://blog.itpub.net/9403012/viewspace-111794/)
3+
- [数据库连接池技术详解](https://juejin.im/post/5b7944c6e51d4538c86cf195)
4+
5+
数据库连接本质就是一个 socket 的连接。数据库服务端还要维护一些缓存和用户权限信息之类的 所以占用了一些内存
6+
7+
连接池是维护的数据库连接的缓存,以便将来需要对数据库的请求时可以重用这些连接。为每个用户打开和维护数据库连接,尤其是对动态数据库驱动的网站应用程序的请求,既昂贵又浪费资源。**在连接池中,创建连接后,将其放置在池中,并再次使用它,因此不必建立新的连接。如果使用了所有连接,则会建立一个新连接并将其添加到池中。**连接池还减少了用户必须等待建立与数据库的连接的时间。
8+
9+
操作过数据库的朋友应该都知道数据库连接池这个概念,它几乎每天都在和我们打交道,但是你真的了解 **数据库连接池** 吗?
10+
11+
### 没有数据库连接池之前
12+
13+
我相信你一定听过这样一句话:**Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁**
14+
15+
16+
17+
18+
19+
20+
21+

docs/java/Java基础知识.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,9 @@ hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返
338338

339339
### 为什么要有 hashCode
340340

341-
**我们先以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode:** 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 `equals()`方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。
341+
**我们先以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode:** 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 `equals()`方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。
342342

343-
通过我们可以看出:`hashCode()` 的作用就是**获取哈希码**,也称为散列码;它实际上是返回一个int整数。这个**哈希码的作用**是确定该对象在哈希表中的索引位置。**`hashCode() `在散列表中才有用,在其它情况下没用。**在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
343+
通过我们可以看出:`hashCode()` 的作用就是**获取哈希码**,也称为散列码;它实际上是返回一个int整数。这个**哈希码的作用**是确定该对象在哈希表中的索引位置。**`hashCode() `在散列表中才有用,在其它情况下没用**。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
344344

345345
### hashCode()与equals()的相关规定
346346

@@ -419,7 +419,7 @@ final关键字主要用在三个地方:变量、方法、类。
419419

420420
- **public string getMessage()**:返回异常发生时的简要描述
421421
- **public string toString()**:返回异常发生时的详细信息
422-
- **public string getLocalizedMessage()**:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
422+
- **public string getLocalizedMessage()**:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
423423
- **public void printStackTrace()**:在控制台上打印Throwable对象封装的异常信息
424424

425425
### 异常处理总结

0 commit comments

Comments
 (0)