[docs update]picture url
This commit is contained in:
parent
0d7578c511
commit
a430800f04
|
|
@ -13,3 +13,4 @@
|
|||
dist/
|
||||
# Build files
|
||||
packages/*/lib/
|
||||
traversal-folder-replace-string.py
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<p style="text-align:center">
|
||||
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width=""/>
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width=""/>
|
||||
</a>
|
||||
</p>
|
||||
<p style="text-align:center">
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<tr>
|
||||
<td style="text-align:center" valign="middle">
|
||||
<a href="https://sourl.cn/e7ee87">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiu.png" style="margin: 0 auto;width:850px" /></a>
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiu.png" style="margin: 0 auto;width:850px" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
|||
868
README.md
868
README.md
|
|
@ -1,434 +1,434 @@
|
|||
推荐你通过在线阅读网站进行阅读,体验更好,速度更快!
|
||||
|
||||
* **[JavaGuide 在线阅读网站(新版,推荐👍)](https://javaguide.cn/)**
|
||||
* [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/)
|
||||
|
||||
<div align="center">
|
||||
<p>
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiu.png" style="margin: 0 auto; width: 850px;" />
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width="" />
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读" /></a>
|
||||
<img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars" />
|
||||
<img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks" />
|
||||
<img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues" />
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/Snailclimb/JavaGuide">Github</a> |
|
||||
<a href="https://gitee.com/SnailClimb/JavaGuide">Gitee</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
> 1. **面试专版** :准备面试的小伙伴可以考虑面试专版:[《Java 面试指北 》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) (质量很高,专为面试打造,配合 JavaGuide 食用)。
|
||||
> 1. **知识星球** :专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入 [JavaGuide 知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。
|
||||
> 2. **转载须知** :以下所有文章如非文首说明为转载皆为我(Guide 哥)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
|
||||
<div align="center">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
</div>
|
||||
## 项目相关
|
||||
|
||||
* [项目介绍](./docs/javaguide/intro.md)
|
||||
* [贡献指南](./docs/javaguide/contribution-guideline.md)
|
||||
* [常见问题](./docs/javaguide/faq.md)
|
||||
* [项目待办](./docs/javaguide/todo.md)
|
||||
|
||||
## Java
|
||||
|
||||
### 基础
|
||||
|
||||
**知识点/面试题总结** : (必看:+1: ):
|
||||
|
||||
- [Java 基础常见知识点&面试题总结(上)](./docs/java/basis/java-basic-questions-01.md)
|
||||
- [Java 基础常见知识点&面试题总结(中)](./docs/java/basis/java-basic-questions-02.md)
|
||||
- [Java 基础常见知识点&面试题总结(下)](./docs/java/basis/java-basic-questions-03.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [为什么 Java 中只有值传递?](./docs/java/basis/why-there-only-value-passing-in-java.md)
|
||||
- [Java 序列化详解](./docs/java/basis/serialization.md)
|
||||
- [泛型&通配符详解](./docs/java/basis/generics-and-wildcards.md)
|
||||
- [Java 反射机制详解](./docs/java/basis/reflection.md)
|
||||
- [Java 代理模式详解](./docs/java/basis/proxy.md)
|
||||
- [BigDecimal 详解](./docs/java/basis/bigdecimal.md)
|
||||
- [Java 魔法类 Unsafe 详解](./docs/java/basis/unsafe.md)
|
||||
- [Java SPI 机制详解](./docs/java/basis/spi.md)
|
||||
- [Java 语法糖详解](./docs/java/basis/syntactic-sugar.md)
|
||||
|
||||
### 集合
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [Java 集合常见知识点&面试题总结(上)](./docs/java/collection/java-collection-questions-01.md) (必看 :+1:)
|
||||
- [Java 集合常见知识点&面试题总结(下)](./docs/java/collection/java-collection-questions-02.md) (必看 :+1:)
|
||||
- [Java 容器使用注意事项总结](./docs/java/collection/java-collection-precautions-for-use.md)
|
||||
|
||||
**源码分析** :
|
||||
|
||||
* [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md)
|
||||
* [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md)
|
||||
* [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md)
|
||||
|
||||
### IO
|
||||
|
||||
* [IO 基础知识总结](./docs/java/io/io-basis.md)
|
||||
* [IO 设计模式总结](./docs/java/io/io-design-patterns.md)
|
||||
* [IO 模型详解](./docs/java/io/io-model.md)
|
||||
|
||||
### 并发
|
||||
|
||||
**知识点/面试题总结** : (必看 :+1:)
|
||||
|
||||
- [Java 并发常见知识点&面试题总结(上)](./docs/java/concurrent/java-concurrent-questions-01.md)
|
||||
- [Java 并发常见知识点&面试题总结(中)](./docs/java/concurrent/java-concurrent-questions-02.md)
|
||||
- [Java 并发常见知识点&面试题总结(下)](./docs/java/concurrent/java-concurrent-questions-03.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [JMM(Java 内存模型)详解](./docs/java/concurrent/jmm.md)
|
||||
- **线程池** :[Java 线程池详解](./docs/java/concurrent/java-thread-pool-summary.md)、[Java 线程池最佳实践](./docs/java/concurrent/java-thread-pool-best-practices.md)
|
||||
- [ThreadLocal 详解](./docs/java/concurrent/threadlocal.md)
|
||||
- [Java 并发容器总结](./docs/java/concurrent/java-concurrent-collections.md)
|
||||
- [Atomic 原子类总结](./docs/java/concurrent/atomic-classes.md)
|
||||
- [AQS 详解](./docs/java/concurrent/aqs.md)
|
||||
- [CompletableFuture入门](./docs/java/concurrent/completablefuture-intro.md)
|
||||
|
||||
### JVM (必看 :+1:)
|
||||
|
||||
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机(第3版)》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
|
||||
|
||||
- **[Java 内存区域](./docs/java/jvm/memory-area.md)**
|
||||
- **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)**
|
||||
- [类文件结构](./docs/java/jvm/class-file-structure.md)
|
||||
- **[类加载过程](./docs/java/jvm/class-loading-process.md)**
|
||||
- [类加载器](./docs/java/jvm/classloader.md)
|
||||
- [【待完成】最重要的 JVM 参数总结(翻译完善了一半)](./docs/java/jvm/jvm-parameters-intro.md)
|
||||
- [【加餐】大白话带你认识 JVM](./docs/java/jvm/jvm-intro.md)
|
||||
- [JDK 监控和故障处理工具](./docs/java/jvm/jdk-monitoring-and-troubleshooting-tools.md)
|
||||
|
||||
### 新特性
|
||||
|
||||
- **Java 8** :[Java 8 新特性总结(翻译)](./docs/java/new-features/java8-tutorial-translate.md)、[Java8常用新特性总结](./docs/java/new-features/java8-common-new-features.md)
|
||||
- [Java 9 新特性概览](./docs/java/new-features/java9.md)
|
||||
- [Java 10 新特性概览](./docs/java/new-features/java10.md)
|
||||
- [Java 11 新特性概览](./docs/java/new-features/java11.md)
|
||||
- [Java 12~13 新特性概览](./docs/java/new-features/java12-13.md)
|
||||
- [Java 14 新特性概览](./docs/java/new-features/java14.md)
|
||||
- [Java 15 新特性概览](./docs/java/new-features/java15.md)
|
||||
- [Java 16 新特性概览](./docs/java/new-features/java16.md)
|
||||
- [Java 17 新特性概览](./docs/java/new-features/java17.md)
|
||||
- [Java 18 新特性概览](./docs/java/new-features/java18.md)
|
||||
- [Java 19 新特性概览](./docs/java/new-features/java19.md)
|
||||
|
||||
## 计算机基础
|
||||
|
||||
### 操作系统
|
||||
|
||||
- [操作系统常见问题总结!](./docs/cs-basics/operating-system/operating-system-basic-questions-01.md)
|
||||
- [后端程序员必备的 Linux 基础知识总结](./docs/cs-basics/operating-system/linux-intro.md)
|
||||
- [Shell 编程基础知识总结](./docs/cs-basics/operating-system/shell-intro.md)
|
||||
|
||||
### 网络
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [计算机网络常见知识点&面试题总结](./docs/cs-basics/network/other-network-questions.md)
|
||||
- [谢希仁老师的《计算机网络》内容总结(补充)](./docs/cs-basics/network/computer-network-xiexiren-summary.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [OSI 和 TCP/IP 网络分层模型详解(基础)](./docs/cs-basics/network/osi&tcp-ip-model.md)
|
||||
- [应用层常见协议总结(应用层)](./docs/cs-basics/network/application-layer-protocol.md)
|
||||
- [HTTP vs HTTPS(应用层)](./docs/cs-basics/network/http&https.md)
|
||||
- [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0&http1.1.md)
|
||||
- [HTTP 常见状态码(应用层)](./docs/cs-basics/network/http-status-codes.md)
|
||||
- [TCP 三次握手和四次挥手(传输层)](./docs/cs-basics/network/tcp-connection-and-disconnection.md)
|
||||
- [TCP 传输可靠性保障(传输层)](./docs/cs-basics/network/tcp-reliability-guarantee.md)
|
||||
- [ARP 协议详解(网络层)](./docs/cs-basics/network/arp.md)
|
||||
- [网络攻击常见手段总结(安全)](./docs/cs-basics/network/network-attack-means.md)
|
||||
|
||||
### 数据结构
|
||||
|
||||
**图解数据结构:**
|
||||
|
||||
- [线性数据结构 :数组、链表、栈、队列](./docs/cs-basics/data-structure/linear-data-structure.md)
|
||||
- [图](./docs/cs-basics/data-structure/graph.md)
|
||||
- [堆](./docs/cs-basics/data-structure/heap.md)
|
||||
- [树](./docs/cs-basics/data-structure/tree.md) :重点关注[红黑树](./docs/cs-basics/data-structure/red-black-tree.md)、B-,B+,B*树、LSM树
|
||||
|
||||
其他常用数据结构 :
|
||||
|
||||
- [布隆过滤器](./docs/cs-basics/data-structure/bloom-filter.md)
|
||||
|
||||
### 算法
|
||||
|
||||
算法这部分内容非常重要,如果你不知道如何学习算法的话,可以看下我写的:
|
||||
|
||||
* [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。
|
||||
* [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
|
||||
|
||||
**常见算法问题总结** :
|
||||
|
||||
* [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md)
|
||||
* [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
|
||||
* [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
|
||||
* [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md)
|
||||
|
||||
另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
|
||||
|
||||
## 数据库
|
||||
|
||||
### 基础
|
||||
|
||||
- [数据库基础知识总结](./docs/database/basis.md)
|
||||
- [NoSQL 基础知识总结](./docs/database/nosql.md)
|
||||
- [字符集详解](./docs/database/character-set.md)
|
||||
- SQL :
|
||||
- [SQL语法基础知识总结](./docs/database/sql/sql-syntax-summary.md)
|
||||
- [SQL常见面试题总结](./docs/database/sql/sql-questions-01.md)
|
||||
|
||||
|
||||
### MySQL
|
||||
|
||||
**知识点/面试题总结:**
|
||||
|
||||
- **[MySQL 常见知识点&面试题总结](./docs/database/mysql/mysql-questions-01.md)** (必看 :+1:)
|
||||
- [MySQL 高性能优化规范建议总结](./docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md)
|
||||
|
||||
**重要知识点:**
|
||||
|
||||
- [MySQL索引详解](./docs/database/mysql/mysql-index.md)
|
||||
- [MySQL事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md)
|
||||
- [MySQL三大日志(binlog、redo log和undo log)详解](./docs/database/mysql/mysql-logs.md)
|
||||
- [InnoDB 存储引擎对 MVCC 的实现](./docs/database/mysql/innodb-implementation-of-mvcc.md)
|
||||
- [SQL 语句在 MySQL 中的执行过程](./docs/database/mysql/how-sql-executed-in-mysql.md)
|
||||
- [MySQL执行计划分析](./docs/database/mysql/mysql-query-execution-plan.md)
|
||||
- [MySQL自增主键一定是连续的吗](./docs/database/mysql/mysql-auto-increment-primary-key-continuous.md)
|
||||
- [MySQL 时间类型数据存储建议](./docs/database/mysql/some-thoughts-on-database-storage-time.md)
|
||||
- [MySQL 隐式转换造成索引失效](./docs/database/mysql/index-invalidation-caused-by-implicit-conversion.md)
|
||||
|
||||
### Redis
|
||||
|
||||
**知识点/面试题总结** : (必看:+1: ):
|
||||
|
||||
- [Redis 常见知识点&面试题总结(上)](./docs/database/redis/redis-questions-01.md)
|
||||
- [Redis 常见知识点&面试题总结(下)](./docs/database/redis/redis-questions-02.md)
|
||||
|
||||
**重要知识点:**
|
||||
|
||||
- [3种常用的缓存读写策略详解](./docs/database/redis/3-commonly-used-cache-read-and-write-strategies.md)
|
||||
- [Redis 5 种基本数据结构详解](./docs/database/redis/redis-data-structures-01.md)
|
||||
- [Redis 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.md)
|
||||
- [Redis 内存碎片详解](./docs/database/redis/redis-memory-fragmentation.md)
|
||||
- [Redis 集群详解](./docs/database/redis/redis-cluster.md)
|
||||
|
||||
### MongoDB
|
||||
|
||||
- [MongoDB 常见知识点&面试题总结(上)](./docs/database/mongodb/mongodb-questions-01.md)
|
||||
- [MongoDB 常见知识点&面试题总结(下)](./docs/database/mongodb/mongodb-questions-02.md)
|
||||
|
||||
## 搜索引擎
|
||||
|
||||
[Elasticsearch常见面试题总结(付费)](./docs/database/elasticsearch/elasticsearch-questions-01.md)
|
||||
|
||||

|
||||
|
||||
## 开发工具
|
||||
|
||||
### Maven
|
||||
|
||||
[Maven 核心概念总结](./docs/tools/maven/maven-core-concepts.md)
|
||||
|
||||
### Gradle
|
||||
|
||||
[Gradle 核心概念总结](./docs/tools/gradle/gradle-core-concepts.md)(可选,目前国内还是使用 Maven 普遍一些)
|
||||
|
||||
### Docker
|
||||
|
||||
* [Docker 核心概念总结](./docs/tools/docker/docker-intro.md)
|
||||
* [Docker 实战](./docs/tools/docker/docker-in-action.md)
|
||||
|
||||
### Git
|
||||
|
||||
* [Git 核心概念总结](./docs/tools/git/git-intro.md)
|
||||
* [Github 实用小技巧总结](./docs/tools/git/github-tips.md)
|
||||
|
||||
## 系统设计
|
||||
|
||||
- [系统设计常见面试题总结](./docs/system-design/system-design-questions.md)
|
||||
- [设计模式常见面试题总结](./docs/system-design/design-pattern.md)
|
||||
|
||||
### 基础
|
||||
|
||||
- [RestFul API 简明教程](./docs/system-design/basis/RESTfulAPI.md)
|
||||
- [软件工程简明教程简明教程](./docs/system-design/basis/software-engineering.md)
|
||||
- [代码命名指南](./docs/system-design/basis/naming.md)
|
||||
- [代码重构指南](./docs/system-design/basis/refactoring.md)
|
||||
- [单元测试指南](./docs/system-design/basis/unit-test.md)
|
||||
|
||||
### 常用框架
|
||||
|
||||
#### Spring/SpringBoot (必看 :+1:)
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [Spring 常见知识点&面试题总结](./docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md)
|
||||
- [SpringBoot 常见知识点&面试题总结](./docs/system-design/framework/spring/springboot-knowledge-and-questions-summary.md)
|
||||
- [Spring/Spring Boot 常用注解总结](./docs/system-design/framework/spring/spring-common-annotations.md)
|
||||
- [SpringBoot 入门指南](https://github.com/Snailclimb/springboot-guide)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [Spring 事务详解](./docs/system-design/framework/spring/spring-transaction.md)
|
||||
- [Spring 中的设计模式详解](./docs/system-design/framework/spring/spring-design-patterns-summary.md)
|
||||
- [SpringBoot 自动装配原理详解](./docs/system-design/framework/spring/spring-boot-auto-assembly-principles.md)
|
||||
|
||||
#### MyBatis
|
||||
|
||||
[MyBatis 常见面试题总结](./docs/system-design/framework/mybatis/mybatis-interview.md)
|
||||
|
||||
### 安全
|
||||
|
||||
#### 认证授权
|
||||
|
||||
- [认证授权基础概念详解](./docs/system-design/security/basis-of-authority-certification.md)
|
||||
- [JWT 基础概念详解](./docs/system-design/security/jwt-intro.md)
|
||||
- [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages&disadvantages-of-jwt.md)
|
||||
- [SSO 单点登录详解](./docs/system-design/security/sso-intro.md)
|
||||
- [权限系统设计详解](./docs/system-design/security/design-of-authority-system.md)
|
||||
|
||||
|
||||
#### 数据脱敏
|
||||
|
||||
数据脱敏说的就是我们根据特定的规则对敏感信息数据进行变形,比如我们把手机号、身份证号某些位数使用 * 来代替。
|
||||
|
||||
#### 敏感词过滤
|
||||
|
||||
[敏感词过滤方案总结](./docs/system-design/security/sentive-words-filter.md)
|
||||
|
||||
### 定时任务
|
||||
|
||||
[Java 定时任务详解](./docs/system-design/schedule-task.md)
|
||||
|
||||
### Web 实时消息推送
|
||||
|
||||
[Web 实时消息推送详解](./docs/system-design/web-real-time-message-push.md)
|
||||
|
||||
## 分布式
|
||||
|
||||
### 理论&算法&协议
|
||||
|
||||
- [CAP 理论和 BASE 理论解读](./docs/distributed-system/theorem&algorithm&protocol/cap&base-theorem.md)
|
||||
- [Paxos 算法解读](./docs/distributed-system/theorem&algorithm&protocol/paxos-algorithm.md)
|
||||
- [Raft 算法解读](./docs/distributed-system/theorem&algorithm&protocol/raft-algorithm.md)
|
||||
|
||||
### API 网关
|
||||
|
||||
[API 网关详解](./docs/distributed-system/api-gateway.md)
|
||||
|
||||
### 分布式 ID
|
||||
|
||||
[分布式 ID 详解](./docs/distributed-system/distributed-id.md)
|
||||
|
||||
### 分布式锁
|
||||
|
||||
[分布式锁详解](./docs/distributed-system/distributed-lock.md)
|
||||
|
||||
### 分布式事务
|
||||
|
||||
[分布式事务详解](./docs/distributed-system/distributed-transaction.md)
|
||||
|
||||
### 分布式配置中心
|
||||
|
||||
[分布式配置中心详解](./docs/distributed-system/distributed-configuration-center.md)
|
||||
|
||||
### RPC
|
||||
|
||||
* [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md)
|
||||
* [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md)
|
||||
|
||||
### ZooKeeper
|
||||
|
||||
> 前两篇文章可能有内容重合部分,推荐都看一遍。
|
||||
|
||||
- [ZooKeeper 相关概念总结(入门)](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md)
|
||||
- [ZooKeeper 相关概念总结(进阶)](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-plus.md)
|
||||
- [ZooKeeper 实战](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-in-action.md)
|
||||
|
||||
## 高性能
|
||||
|
||||
### 数据库读写分离&分库分表
|
||||
|
||||
[数据库读写分离&分库分表详解](./docs/high-performance/read-and-write-separation-and-library-subtable.md)
|
||||
|
||||
### 负载均衡
|
||||
|
||||
[负载均衡详解](./docs/high-performance/load-balancing.md)
|
||||
|
||||
### SQL 优化
|
||||
|
||||
[常见 SQL 优化手段总结](./docs/high-performance/sql-optimization.md)
|
||||
|
||||
### CDN
|
||||
|
||||
[CDN(内容分发网络)详解](./docs/high-performance/cdn.md)
|
||||
|
||||
### 消息队列
|
||||
|
||||
消息队列在分布式系统中主要是为了解耦和削峰。相关阅读: [消息队列常见问题总结](./docs/high-performance/message-queue/message-queue.md)。
|
||||
|
||||
- **RabbitMQ** : [RabbitMQ 基础知识总结](./docs/high-performance/message-queue/rabbitmq-intro.md)、[RabbitMQ 常见面试题](./docs/high-performance/message-queue/rabbitmq-questions.md)
|
||||
- **RocketMQ** : [RocketMQ 基础知识总结](./docs/high-performance/message-queue/rocketmq-intro.md)、[RocketMQ 常见面试题总结](./docs/high-performance/message-queue/rocketmq-questions.md)
|
||||
- **Kafka** :[Kafka 常见问题总结](./docs/high-performance/message-queue/kafka-questions-01.md)
|
||||
|
||||
## 高可用
|
||||
|
||||
[高可用系统设计指南](./docs/high-availability/high-availability-system-design.md)
|
||||
|
||||
### 冗余设计
|
||||
|
||||
[冗余设计详解](./docs/high-availability/redundancy.md)
|
||||
|
||||
### 限流
|
||||
|
||||
[服务限流详解](./docs/high-availability/limit-request.md)
|
||||
|
||||
### 降级&熔断
|
||||
|
||||
[降级&熔断详解](./docs/high-availability/fallback&circuit-breaker.md)
|
||||
|
||||
### 超时&重试
|
||||
|
||||
[超时&重试详解](./docs/high-availability/timeout-and-retry.md)
|
||||
|
||||
### 集群
|
||||
|
||||
相同的服务部署多份,避免单点故障。
|
||||
|
||||
### 灾备设计和异地多活
|
||||
|
||||
**灾备** = 容灾+备份。
|
||||
|
||||
* **备份** : 将系统所产生的的所有重要数据多备份几份。
|
||||
* **容灾** : 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
|
||||
|
||||
**异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。
|
||||
|
||||
## Star 趋势
|
||||
|
||||

|
||||
|
||||
## 公众号
|
||||
|
||||
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
|
||||
|
||||

|
||||
|
||||
推荐你通过在线阅读网站进行阅读,体验更好,速度更快!
|
||||
|
||||
* **[JavaGuide 在线阅读网站(新版,推荐👍)](https://javaguide.cn/)**
|
||||
* [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/)
|
||||
|
||||
<div align="center">
|
||||
<p>
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiu.png" style="margin: 0 auto; width: 850px;" />
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width="" />
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读" /></a>
|
||||
<img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars" />
|
||||
<img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks" />
|
||||
<img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues" />
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/Snailclimb/JavaGuide">Github</a> |
|
||||
<a href="https://gitee.com/SnailClimb/JavaGuide">Gitee</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
> 1. **面试专版** :准备面试的小伙伴可以考虑面试专版:[《Java 面试指北 》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) (质量很高,专为面试打造,配合 JavaGuide 食用)。
|
||||
> 1. **知识星球** :专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入 [JavaGuide 知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。
|
||||
> 2. **转载须知** :以下所有文章如非文首说明为转载皆为我(Guide 哥)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
|
||||
<div align="center">
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
</div>
|
||||
## 项目相关
|
||||
|
||||
* [项目介绍](./docs/javaguide/intro.md)
|
||||
* [贡献指南](./docs/javaguide/contribution-guideline.md)
|
||||
* [常见问题](./docs/javaguide/faq.md)
|
||||
* [项目待办](./docs/javaguide/todo.md)
|
||||
|
||||
## Java
|
||||
|
||||
### 基础
|
||||
|
||||
**知识点/面试题总结** : (必看:+1: ):
|
||||
|
||||
- [Java 基础常见知识点&面试题总结(上)](./docs/java/basis/java-basic-questions-01.md)
|
||||
- [Java 基础常见知识点&面试题总结(中)](./docs/java/basis/java-basic-questions-02.md)
|
||||
- [Java 基础常见知识点&面试题总结(下)](./docs/java/basis/java-basic-questions-03.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [为什么 Java 中只有值传递?](./docs/java/basis/why-there-only-value-passing-in-java.md)
|
||||
- [Java 序列化详解](./docs/java/basis/serialization.md)
|
||||
- [泛型&通配符详解](./docs/java/basis/generics-and-wildcards.md)
|
||||
- [Java 反射机制详解](./docs/java/basis/reflection.md)
|
||||
- [Java 代理模式详解](./docs/java/basis/proxy.md)
|
||||
- [BigDecimal 详解](./docs/java/basis/bigdecimal.md)
|
||||
- [Java 魔法类 Unsafe 详解](./docs/java/basis/unsafe.md)
|
||||
- [Java SPI 机制详解](./docs/java/basis/spi.md)
|
||||
- [Java 语法糖详解](./docs/java/basis/syntactic-sugar.md)
|
||||
|
||||
### 集合
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [Java 集合常见知识点&面试题总结(上)](./docs/java/collection/java-collection-questions-01.md) (必看 :+1:)
|
||||
- [Java 集合常见知识点&面试题总结(下)](./docs/java/collection/java-collection-questions-02.md) (必看 :+1:)
|
||||
- [Java 容器使用注意事项总结](./docs/java/collection/java-collection-precautions-for-use.md)
|
||||
|
||||
**源码分析** :
|
||||
|
||||
* [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md)
|
||||
* [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md)
|
||||
* [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md)
|
||||
|
||||
### IO
|
||||
|
||||
* [IO 基础知识总结](./docs/java/io/io-basis.md)
|
||||
* [IO 设计模式总结](./docs/java/io/io-design-patterns.md)
|
||||
* [IO 模型详解](./docs/java/io/io-model.md)
|
||||
|
||||
### 并发
|
||||
|
||||
**知识点/面试题总结** : (必看 :+1:)
|
||||
|
||||
- [Java 并发常见知识点&面试题总结(上)](./docs/java/concurrent/java-concurrent-questions-01.md)
|
||||
- [Java 并发常见知识点&面试题总结(中)](./docs/java/concurrent/java-concurrent-questions-02.md)
|
||||
- [Java 并发常见知识点&面试题总结(下)](./docs/java/concurrent/java-concurrent-questions-03.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [JMM(Java 内存模型)详解](./docs/java/concurrent/jmm.md)
|
||||
- **线程池** :[Java 线程池详解](./docs/java/concurrent/java-thread-pool-summary.md)、[Java 线程池最佳实践](./docs/java/concurrent/java-thread-pool-best-practices.md)
|
||||
- [ThreadLocal 详解](./docs/java/concurrent/threadlocal.md)
|
||||
- [Java 并发容器总结](./docs/java/concurrent/java-concurrent-collections.md)
|
||||
- [Atomic 原子类总结](./docs/java/concurrent/atomic-classes.md)
|
||||
- [AQS 详解](./docs/java/concurrent/aqs.md)
|
||||
- [CompletableFuture入门](./docs/java/concurrent/completablefuture-intro.md)
|
||||
|
||||
### JVM (必看 :+1:)
|
||||
|
||||
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机(第3版)》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
|
||||
|
||||
- **[Java 内存区域](./docs/java/jvm/memory-area.md)**
|
||||
- **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)**
|
||||
- [类文件结构](./docs/java/jvm/class-file-structure.md)
|
||||
- **[类加载过程](./docs/java/jvm/class-loading-process.md)**
|
||||
- [类加载器](./docs/java/jvm/classloader.md)
|
||||
- [【待完成】最重要的 JVM 参数总结(翻译完善了一半)](./docs/java/jvm/jvm-parameters-intro.md)
|
||||
- [【加餐】大白话带你认识 JVM](./docs/java/jvm/jvm-intro.md)
|
||||
- [JDK 监控和故障处理工具](./docs/java/jvm/jdk-monitoring-and-troubleshooting-tools.md)
|
||||
|
||||
### 新特性
|
||||
|
||||
- **Java 8** :[Java 8 新特性总结(翻译)](./docs/java/new-features/java8-tutorial-translate.md)、[Java8常用新特性总结](./docs/java/new-features/java8-common-new-features.md)
|
||||
- [Java 9 新特性概览](./docs/java/new-features/java9.md)
|
||||
- [Java 10 新特性概览](./docs/java/new-features/java10.md)
|
||||
- [Java 11 新特性概览](./docs/java/new-features/java11.md)
|
||||
- [Java 12~13 新特性概览](./docs/java/new-features/java12-13.md)
|
||||
- [Java 14 新特性概览](./docs/java/new-features/java14.md)
|
||||
- [Java 15 新特性概览](./docs/java/new-features/java15.md)
|
||||
- [Java 16 新特性概览](./docs/java/new-features/java16.md)
|
||||
- [Java 17 新特性概览](./docs/java/new-features/java17.md)
|
||||
- [Java 18 新特性概览](./docs/java/new-features/java18.md)
|
||||
- [Java 19 新特性概览](./docs/java/new-features/java19.md)
|
||||
|
||||
## 计算机基础
|
||||
|
||||
### 操作系统
|
||||
|
||||
- [操作系统常见问题总结!](./docs/cs-basics/operating-system/operating-system-basic-questions-01.md)
|
||||
- [后端程序员必备的 Linux 基础知识总结](./docs/cs-basics/operating-system/linux-intro.md)
|
||||
- [Shell 编程基础知识总结](./docs/cs-basics/operating-system/shell-intro.md)
|
||||
|
||||
### 网络
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [计算机网络常见知识点&面试题总结](./docs/cs-basics/network/other-network-questions.md)
|
||||
- [谢希仁老师的《计算机网络》内容总结(补充)](./docs/cs-basics/network/computer-network-xiexiren-summary.md)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [OSI 和 TCP/IP 网络分层模型详解(基础)](./docs/cs-basics/network/osi&tcp-ip-model.md)
|
||||
- [应用层常见协议总结(应用层)](./docs/cs-basics/network/application-layer-protocol.md)
|
||||
- [HTTP vs HTTPS(应用层)](./docs/cs-basics/network/http&https.md)
|
||||
- [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0&http1.1.md)
|
||||
- [HTTP 常见状态码(应用层)](./docs/cs-basics/network/http-status-codes.md)
|
||||
- [TCP 三次握手和四次挥手(传输层)](./docs/cs-basics/network/tcp-connection-and-disconnection.md)
|
||||
- [TCP 传输可靠性保障(传输层)](./docs/cs-basics/network/tcp-reliability-guarantee.md)
|
||||
- [ARP 协议详解(网络层)](./docs/cs-basics/network/arp.md)
|
||||
- [网络攻击常见手段总结(安全)](./docs/cs-basics/network/network-attack-means.md)
|
||||
|
||||
### 数据结构
|
||||
|
||||
**图解数据结构:**
|
||||
|
||||
- [线性数据结构 :数组、链表、栈、队列](./docs/cs-basics/data-structure/linear-data-structure.md)
|
||||
- [图](./docs/cs-basics/data-structure/graph.md)
|
||||
- [堆](./docs/cs-basics/data-structure/heap.md)
|
||||
- [树](./docs/cs-basics/data-structure/tree.md) :重点关注[红黑树](./docs/cs-basics/data-structure/red-black-tree.md)、B-,B+,B*树、LSM树
|
||||
|
||||
其他常用数据结构 :
|
||||
|
||||
- [布隆过滤器](./docs/cs-basics/data-structure/bloom-filter.md)
|
||||
|
||||
### 算法
|
||||
|
||||
算法这部分内容非常重要,如果你不知道如何学习算法的话,可以看下我写的:
|
||||
|
||||
* [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。
|
||||
* [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
|
||||
|
||||
**常见算法问题总结** :
|
||||
|
||||
* [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md)
|
||||
* [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
|
||||
* [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
|
||||
* [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md)
|
||||
|
||||
另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
|
||||
|
||||
## 数据库
|
||||
|
||||
### 基础
|
||||
|
||||
- [数据库基础知识总结](./docs/database/basis.md)
|
||||
- [NoSQL 基础知识总结](./docs/database/nosql.md)
|
||||
- [字符集详解](./docs/database/character-set.md)
|
||||
- SQL :
|
||||
- [SQL语法基础知识总结](./docs/database/sql/sql-syntax-summary.md)
|
||||
- [SQL常见面试题总结](./docs/database/sql/sql-questions-01.md)
|
||||
|
||||
|
||||
### MySQL
|
||||
|
||||
**知识点/面试题总结:**
|
||||
|
||||
- **[MySQL 常见知识点&面试题总结](./docs/database/mysql/mysql-questions-01.md)** (必看 :+1:)
|
||||
- [MySQL 高性能优化规范建议总结](./docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md)
|
||||
|
||||
**重要知识点:**
|
||||
|
||||
- [MySQL索引详解](./docs/database/mysql/mysql-index.md)
|
||||
- [MySQL事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md)
|
||||
- [MySQL三大日志(binlog、redo log和undo log)详解](./docs/database/mysql/mysql-logs.md)
|
||||
- [InnoDB 存储引擎对 MVCC 的实现](./docs/database/mysql/innodb-implementation-of-mvcc.md)
|
||||
- [SQL 语句在 MySQL 中的执行过程](./docs/database/mysql/how-sql-executed-in-mysql.md)
|
||||
- [MySQL执行计划分析](./docs/database/mysql/mysql-query-execution-plan.md)
|
||||
- [MySQL自增主键一定是连续的吗](./docs/database/mysql/mysql-auto-increment-primary-key-continuous.md)
|
||||
- [MySQL 时间类型数据存储建议](./docs/database/mysql/some-thoughts-on-database-storage-time.md)
|
||||
- [MySQL 隐式转换造成索引失效](./docs/database/mysql/index-invalidation-caused-by-implicit-conversion.md)
|
||||
|
||||
### Redis
|
||||
|
||||
**知识点/面试题总结** : (必看:+1: ):
|
||||
|
||||
- [Redis 常见知识点&面试题总结(上)](./docs/database/redis/redis-questions-01.md)
|
||||
- [Redis 常见知识点&面试题总结(下)](./docs/database/redis/redis-questions-02.md)
|
||||
|
||||
**重要知识点:**
|
||||
|
||||
- [3种常用的缓存读写策略详解](./docs/database/redis/3-commonly-used-cache-read-and-write-strategies.md)
|
||||
- [Redis 5 种基本数据结构详解](./docs/database/redis/redis-data-structures-01.md)
|
||||
- [Redis 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.md)
|
||||
- [Redis 内存碎片详解](./docs/database/redis/redis-memory-fragmentation.md)
|
||||
- [Redis 集群详解](./docs/database/redis/redis-cluster.md)
|
||||
|
||||
### MongoDB
|
||||
|
||||
- [MongoDB 常见知识点&面试题总结(上)](./docs/database/mongodb/mongodb-questions-01.md)
|
||||
- [MongoDB 常见知识点&面试题总结(下)](./docs/database/mongodb/mongodb-questions-02.md)
|
||||
|
||||
## 搜索引擎
|
||||
|
||||
[Elasticsearch常见面试题总结(付费)](./docs/database/elasticsearch/elasticsearch-questions-01.md)
|
||||
|
||||

|
||||
|
||||
## 开发工具
|
||||
|
||||
### Maven
|
||||
|
||||
[Maven 核心概念总结](./docs/tools/maven/maven-core-concepts.md)
|
||||
|
||||
### Gradle
|
||||
|
||||
[Gradle 核心概念总结](./docs/tools/gradle/gradle-core-concepts.md)(可选,目前国内还是使用 Maven 普遍一些)
|
||||
|
||||
### Docker
|
||||
|
||||
* [Docker 核心概念总结](./docs/tools/docker/docker-intro.md)
|
||||
* [Docker 实战](./docs/tools/docker/docker-in-action.md)
|
||||
|
||||
### Git
|
||||
|
||||
* [Git 核心概念总结](./docs/tools/git/git-intro.md)
|
||||
* [Github 实用小技巧总结](./docs/tools/git/github-tips.md)
|
||||
|
||||
## 系统设计
|
||||
|
||||
- [系统设计常见面试题总结](./docs/system-design/system-design-questions.md)
|
||||
- [设计模式常见面试题总结](./docs/system-design/design-pattern.md)
|
||||
|
||||
### 基础
|
||||
|
||||
- [RestFul API 简明教程](./docs/system-design/basis/RESTfulAPI.md)
|
||||
- [软件工程简明教程简明教程](./docs/system-design/basis/software-engineering.md)
|
||||
- [代码命名指南](./docs/system-design/basis/naming.md)
|
||||
- [代码重构指南](./docs/system-design/basis/refactoring.md)
|
||||
- [单元测试指南](./docs/system-design/basis/unit-test.md)
|
||||
|
||||
### 常用框架
|
||||
|
||||
#### Spring/SpringBoot (必看 :+1:)
|
||||
|
||||
**知识点/面试题总结** :
|
||||
|
||||
- [Spring 常见知识点&面试题总结](./docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md)
|
||||
- [SpringBoot 常见知识点&面试题总结](./docs/system-design/framework/spring/springboot-knowledge-and-questions-summary.md)
|
||||
- [Spring/Spring Boot 常用注解总结](./docs/system-design/framework/spring/spring-common-annotations.md)
|
||||
- [SpringBoot 入门指南](https://github.com/Snailclimb/springboot-guide)
|
||||
|
||||
**重要知识点详解** :
|
||||
|
||||
- [Spring 事务详解](./docs/system-design/framework/spring/spring-transaction.md)
|
||||
- [Spring 中的设计模式详解](./docs/system-design/framework/spring/spring-design-patterns-summary.md)
|
||||
- [SpringBoot 自动装配原理详解](./docs/system-design/framework/spring/spring-boot-auto-assembly-principles.md)
|
||||
|
||||
#### MyBatis
|
||||
|
||||
[MyBatis 常见面试题总结](./docs/system-design/framework/mybatis/mybatis-interview.md)
|
||||
|
||||
### 安全
|
||||
|
||||
#### 认证授权
|
||||
|
||||
- [认证授权基础概念详解](./docs/system-design/security/basis-of-authority-certification.md)
|
||||
- [JWT 基础概念详解](./docs/system-design/security/jwt-intro.md)
|
||||
- [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages&disadvantages-of-jwt.md)
|
||||
- [SSO 单点登录详解](./docs/system-design/security/sso-intro.md)
|
||||
- [权限系统设计详解](./docs/system-design/security/design-of-authority-system.md)
|
||||
|
||||
|
||||
#### 数据脱敏
|
||||
|
||||
数据脱敏说的就是我们根据特定的规则对敏感信息数据进行变形,比如我们把手机号、身份证号某些位数使用 * 来代替。
|
||||
|
||||
#### 敏感词过滤
|
||||
|
||||
[敏感词过滤方案总结](./docs/system-design/security/sentive-words-filter.md)
|
||||
|
||||
### 定时任务
|
||||
|
||||
[Java 定时任务详解](./docs/system-design/schedule-task.md)
|
||||
|
||||
### Web 实时消息推送
|
||||
|
||||
[Web 实时消息推送详解](./docs/system-design/web-real-time-message-push.md)
|
||||
|
||||
## 分布式
|
||||
|
||||
### 理论&算法&协议
|
||||
|
||||
- [CAP 理论和 BASE 理论解读](./docs/distributed-system/theorem&algorithm&protocol/cap&base-theorem.md)
|
||||
- [Paxos 算法解读](./docs/distributed-system/theorem&algorithm&protocol/paxos-algorithm.md)
|
||||
- [Raft 算法解读](./docs/distributed-system/theorem&algorithm&protocol/raft-algorithm.md)
|
||||
|
||||
### API 网关
|
||||
|
||||
[API 网关详解](./docs/distributed-system/api-gateway.md)
|
||||
|
||||
### 分布式 ID
|
||||
|
||||
[分布式 ID 详解](./docs/distributed-system/distributed-id.md)
|
||||
|
||||
### 分布式锁
|
||||
|
||||
[分布式锁详解](./docs/distributed-system/distributed-lock.md)
|
||||
|
||||
### 分布式事务
|
||||
|
||||
[分布式事务详解](./docs/distributed-system/distributed-transaction.md)
|
||||
|
||||
### 分布式配置中心
|
||||
|
||||
[分布式配置中心详解](./docs/distributed-system/distributed-configuration-center.md)
|
||||
|
||||
### RPC
|
||||
|
||||
* [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md)
|
||||
* [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md)
|
||||
|
||||
### ZooKeeper
|
||||
|
||||
> 前两篇文章可能有内容重合部分,推荐都看一遍。
|
||||
|
||||
- [ZooKeeper 相关概念总结(入门)](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md)
|
||||
- [ZooKeeper 相关概念总结(进阶)](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-plus.md)
|
||||
- [ZooKeeper 实战](./docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-in-action.md)
|
||||
|
||||
## 高性能
|
||||
|
||||
### 数据库读写分离&分库分表
|
||||
|
||||
[数据库读写分离&分库分表详解](./docs/high-performance/read-and-write-separation-and-library-subtable.md)
|
||||
|
||||
### 负载均衡
|
||||
|
||||
[负载均衡详解](./docs/high-performance/load-balancing.md)
|
||||
|
||||
### SQL 优化
|
||||
|
||||
[常见 SQL 优化手段总结](./docs/high-performance/sql-optimization.md)
|
||||
|
||||
### CDN
|
||||
|
||||
[CDN(内容分发网络)详解](./docs/high-performance/cdn.md)
|
||||
|
||||
### 消息队列
|
||||
|
||||
消息队列在分布式系统中主要是为了解耦和削峰。相关阅读: [消息队列常见问题总结](./docs/high-performance/message-queue/message-queue.md)。
|
||||
|
||||
- **RabbitMQ** : [RabbitMQ 基础知识总结](./docs/high-performance/message-queue/rabbitmq-intro.md)、[RabbitMQ 常见面试题](./docs/high-performance/message-queue/rabbitmq-questions.md)
|
||||
- **RocketMQ** : [RocketMQ 基础知识总结](./docs/high-performance/message-queue/rocketmq-intro.md)、[RocketMQ 常见面试题总结](./docs/high-performance/message-queue/rocketmq-questions.md)
|
||||
- **Kafka** :[Kafka 常见问题总结](./docs/high-performance/message-queue/kafka-questions-01.md)
|
||||
|
||||
## 高可用
|
||||
|
||||
[高可用系统设计指南](./docs/high-availability/high-availability-system-design.md)
|
||||
|
||||
### 冗余设计
|
||||
|
||||
[冗余设计详解](./docs/high-availability/redundancy.md)
|
||||
|
||||
### 限流
|
||||
|
||||
[服务限流详解](./docs/high-availability/limit-request.md)
|
||||
|
||||
### 降级&熔断
|
||||
|
||||
[降级&熔断详解](./docs/high-availability/fallback&circuit-breaker.md)
|
||||
|
||||
### 超时&重试
|
||||
|
||||
[超时&重试详解](./docs/high-availability/timeout-and-retry.md)
|
||||
|
||||
### 集群
|
||||
|
||||
相同的服务部署多份,避免单点故障。
|
||||
|
||||
### 灾备设计和异地多活
|
||||
|
||||
**灾备** = 容灾+备份。
|
||||
|
||||
* **备份** : 将系统所产生的的所有重要数据多备份几份。
|
||||
* **容灾** : 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
|
||||
|
||||
**异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。
|
||||
|
||||
## Star 趋势
|
||||
|
||||

|
||||
|
||||
## 公众号
|
||||
|
||||
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ tag:
|
|||
|
||||
起初的时候,自己就是玩玩流行蝴蝶剑、单机摩托之类的单机游戏。但是,也没有到沉迷的地步,只是觉得这东西确实挺好玩的,一玩就可以玩一下午,恋恋不舍。
|
||||
|
||||

|
||||

|
||||
|
||||
## 小学毕业后开始有网瘾
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ QQ 飞车这款戏当时还挺火的,很多 90 后的小伙伴应该比较熟
|
|||
|
||||
到了初二的时候,就没玩 QQ 飞车了。我的等级也永久定格在了 **120** 级,这个等级在当时那个升级难的一匹的年代,算的上非常高的等级了。
|
||||
|
||||

|
||||

|
||||
|
||||
## 初二网瘾爆发
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ QQ 飞车这款戏当时还挺火的,很多 90 后的小伙伴应该比较熟
|
|||
|
||||
其实我在之前是从来没有过失眠的经历的。高考前夕,因为害怕自己睡不着,所以,我提前让妈妈去买了几瓶老师推荐的安神补脑液。我到现在还记得这个安神补脑液是敖东牌的。
|
||||
|
||||

|
||||

|
||||
|
||||
高考那几天的失眠,我觉得可能和我喝了老师推荐的安神补脑液有关系,又或者是我自己太过于紧张了。因为那几天睡觉总会感觉有很多蚂蚁在身上爬一样,身上还起了一些小痘痘。
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ tag:
|
|||
|
||||
好家伙!几天没注意,[JavaGuide](https://github.com/Snailclimb/JavaGuide) 这个项目直接上了 100K star。
|
||||
|
||||

|
||||

|
||||
|
||||
其实,这个真没啥好嘚瑟的。因为,教程类的含金量其实是比较低的,Star 数量比较多主要也是因为受众面比较广,大家觉得不错,点个 star 就相当于收藏了。很多特别优秀的框架,star 数量可能只有几 K。所以,单纯看 star 数量没啥意思,就当看个笑话吧!
|
||||
|
||||

|
||||

|
||||
|
||||
维护这个项目的过程中,也被某些人 diss 过:“md项目,没啥含金量,给国人丢脸!”。
|
||||
|
||||
|
|
@ -27,11 +27,11 @@ tag:
|
|||
|
||||
到今天(2021-03-23)为止,这个仓库已经累计有 **2933** 次 commit,累计有 **207** 位朋友参与到了项目中来。
|
||||
|
||||

|
||||

|
||||
|
||||
累计有 **511** 个 **issue** 和 **575** 个 **pr**。所有的 pr 都已经被处理,仅有15 个左右的 issue 我还未抽出时间处理。
|
||||
|
||||

|
||||

|
||||
|
||||
其实,相比于 star 数量,你看看仓库的 issue 和 pr 更能说明你的项目是否有价值。
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ tag:
|
|||
|
||||
谁能想到,培训机构的人竟然找人来让我删文章了!讲真,这俩人是真的奇葩啊!
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
还让我格局大点?我去你丫的!明明就是我的原创,你自己不删,反而找人联系我删除!有脑子不?
|
||||
|
||||
|
|
@ -59,9 +59,9 @@ tag:
|
|||
|
||||
搞笑的是!他们在让我删文的同时,他们 B 站盗发的视频还都在,还在继续为他们引流。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
如果他们把账号注销了,我或许还能考虑放一手。但是,文章是肯定不会删的。
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ tag:
|
|||
|
||||
这一年,我和班里的一群新同学去逛了荆州的很多地方比如荆州博物馆、长江大桥、张居正故居、关帝庙。
|
||||
|
||||

|
||||

|
||||
|
||||
即使如此,我当时还是对未来充满了希望,憧憬着工作之后的生活。
|
||||
|
||||
|
|
@ -42,21 +42,21 @@ tag:
|
|||
|
||||
下面这些都是我和社团的小伙伴利用课外时间自己做的,在圣诞节那周基本都卖完了。我记得,为了能够多卖一些,我们还挨个去每一个寝室推销了一遍。
|
||||
|
||||

|
||||

|
||||
|
||||
我还参加了大一元旦晚会,不过,那次演出我还是没放开,说实话,感觉没有表现出应该有的那味。
|
||||
|
||||

|
||||

|
||||
|
||||
经过这次演出之后,我发现我是真的没有表演的天赋,很僵硬。并且,这种僵硬呆板是自己付出努力之后也没办法改变的。
|
||||
|
||||
下图是某一次社团聚餐,我喝的有点小醉之后,被朋友拍下的。
|
||||
|
||||

|
||||

|
||||
|
||||
那时候,还经常和和社团的几位小伙伴一起去夜走荆州古城墙。
|
||||
|
||||

|
||||

|
||||
|
||||
不知道社团的大家现在过得怎么样呢?
|
||||
|
||||
|
|
@ -76,25 +76,25 @@ tag:
|
|||
|
||||
每个周末我都会从荆州坐车跑到孝感,在各个县城之间来回跑。绝大部分时候,只有我一个人,偶尔也会有几个社团的小伙伴陪我一起。
|
||||
|
||||

|
||||

|
||||
|
||||
记忆犹新,那一年孝感也是闹洪水,还挺严重的。
|
||||
|
||||

|
||||

|
||||
|
||||
有一次我差点回不去学校参加期末考试。虽然没有备考,但是也没有挂过任何一门课,甚至很多科目考的还不错。不过,这还是对我绩点产生了比较大的影响,导致我后面没有机会拿到奖学金。
|
||||
|
||||

|
||||

|
||||
|
||||
这次比较赶时间,所以就坐的是火车回学校。在火车上竟然还和别人撞箱子了!
|
||||
|
||||

|
||||

|
||||
|
||||
当时去小乡镇上的时候,自己最差的时候住过 15 元的旅馆。真的是 15 元,你没看错。就那种老旧民房的小破屋,没有独卫,床上用品也很不卫生,还不能洗澡。
|
||||
|
||||
下面这个还是我住过最豪华的一个,因为当时坐客车去了孝感之后,突然下大雨,我就在车站附近找了一个相对便宜点的。
|
||||
|
||||

|
||||

|
||||
|
||||
为了以更低的价钱租到房子,我经常和房东砍价砍的面红耳赤。
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ tag:
|
|||
|
||||
我一个人给 6 个老师加上 10 来个学生和房东们一家做了一个多月的饭,我的厨艺也因此得到了很大的锻炼。
|
||||
|
||||

|
||||

|
||||
|
||||
这些学生有小学的,也有初中的,都比较听话。有很多还是留守儿童,爸爸妈妈在外打工,跟着爷爷奶奶一起生活。
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ tag:
|
|||
|
||||
学生们都挺听话,没有出现和我们几个老师闹过矛盾。只有两个调皮的小学生被我训斥之后,怀恨在心,写下了一些让我忍俊不禁的话!哈哈哈哈!太可爱了!
|
||||
|
||||

|
||||

|
||||
|
||||
离开之前的前一天的晚上,我和老师们商量请一些近点的同学们来吃饭。我们一大早就出去买菜了,下图是做成后的成品。虽然是比较简单的一顿饭,但我们吃的特别香。
|
||||
|
||||

|
||||

|
||||
|
||||
那天晚上还有几个家长专门跑过来看我做饭,家长们说他们的孩子非常喜欢我做的饭,哈哈哈!我表面淡然说自己做的不好,实则内心暗暗自喜,就很“闷骚”的一个人,哈哈哈!
|
||||
|
||||
|
|
@ -130,25 +130,25 @@ tag:
|
|||
|
||||
大一尾声的时候,还做了一件非常有意义的事情。我和我的朋友们去了一次孤儿院(荆州私立孤儿教养院)。这个孤儿院曾经还被多家电视台报道过,目前也被百度百科收录。
|
||||
|
||||

|
||||

|
||||
|
||||
孤儿院的孩子们,大多是一些无父无母或者本身有一些疾病被父母遗弃的孩子。
|
||||
|
||||
去之前,我们买了很多小孩子的玩具、文具、零食这些东西。这些钱的来源也比较有意义,都是我和社团的一些小伙伴自己去外面兼职赚的一些钱。
|
||||
|
||||

|
||||

|
||||
|
||||
勿以善小而不为!引用《爱的风险》这首歌的一句歌词:“只要人人都献出一点爱,世界将变成美好的人间” 。
|
||||
|
||||
我想看看这个孤儿院的现状,于是在网上有搜了一下,看到了去年 1 月份荆州新闻网的一份报道。
|
||||
|
||||

|
||||

|
||||
|
||||
孤儿教养院创办 33 年来,累计收养孤儿 85 人,其中有 5 人参军入伍报效祖国,20 人上大学,有的早已参加工作并成家立业。
|
||||
|
||||
叔叔也慢慢老了,白发越来越多。有点心酸,想哭,希望有机会再回去看看您!一定会的!
|
||||
|
||||

|
||||

|
||||
|
||||
### 徒步旅行
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ tag:
|
|||
|
||||
我和一群社团的小伙伴,徒步走了接近 45 公里。我们从学校的西校区,徒步走到了枝江那边的一个沙滩。
|
||||
|
||||

|
||||

|
||||
|
||||
是真的全程步行,这还是我第一次走这么远。
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ tag:
|
|||
|
||||
我们在沙滩上露营,烧烤,唱歌跳舞,一直到第二天早上才踏上回学校的路程。
|
||||
|
||||

|
||||

|
||||
|
||||
## 大二
|
||||
|
||||
|
|
@ -182,19 +182,19 @@ tag:
|
|||
|
||||
比如我们一起去了长江边上烧烤露营。
|
||||
|
||||

|
||||

|
||||
|
||||
再比如我们一起去环跑了古城墙。
|
||||
|
||||

|
||||

|
||||
|
||||
大学那会,我还是非常热爱运动的!
|
||||
|
||||

|
||||

|
||||
|
||||
大二那会,我就已经环跑了 3 次古城墙。
|
||||
|
||||

|
||||

|
||||
|
||||
### 加入长大在线
|
||||
|
||||
|
|
@ -202,11 +202,11 @@ tag:
|
|||
|
||||
在百度上,还能搜索到长大在线的词条。
|
||||
|
||||

|
||||

|
||||
|
||||
莫名其妙还被发了一个记者证,哈哈哈!
|
||||
|
||||

|
||||

|
||||
|
||||
我选的是安卓组,然后我就开始了学习安卓开发的旅程。
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ tag:
|
|||
|
||||
再到后面,我留下来当了副站长,继续为组织服务了大半年多。
|
||||
|
||||

|
||||

|
||||
|
||||
### 第一次参加比赛
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ tag:
|
|||
|
||||
参加比赛之前,自己也是一个 PPT 小白,苦心学了一周多之后,我的一个作品竟然顺利获得了第一名。
|
||||
|
||||

|
||||

|
||||
|
||||
也正是因为这次比赛,我免费拥有了自己的第一个机械键盘,这个键盘陪我度过了后面的大学生活。
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ tag:
|
|||
|
||||
每次忙到很晚,一个人走在校园的时候还是很爽的!非常喜欢这种安静的感觉。
|
||||
|
||||

|
||||

|
||||
|
||||
当时身体素质真好,熬夜之后第二天照常起来上课学习。现在熬个夜,后面两天直接就废了!
|
||||
|
||||
|
|
@ -242,13 +242,13 @@ tag:
|
|||
|
||||
那个时候还贼自恋,没事就喜欢自拍一张。
|
||||
|
||||

|
||||

|
||||
|
||||
国庆节的时候也不回家,继续在学校刷 Java 视频和书籍。
|
||||
|
||||
我记得那次国庆节的时候效率还是非常高的,学习起来也特别有动力。
|
||||
|
||||

|
||||

|
||||
|
||||
## 大三
|
||||
|
||||
|
|
@ -262,11 +262,11 @@ tag:
|
|||
|
||||
我的开源项目 JavaGuide 和公众号都是这一年启动的。
|
||||
|
||||

|
||||

|
||||
|
||||
目前的话,JavaGuide 也已经 100k star ,我的公众号也已经有 15w+ 的关注。
|
||||
|
||||

|
||||

|
||||
|
||||
### 接私活赚钱
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ tag:
|
|||
|
||||
商城类型的项目大概的架构图如下(没有找到当时自己画的原图):
|
||||
|
||||

|
||||

|
||||
|
||||
那会商城项目貌似也已经烂大街了,用的人比较多。为了让自己的商城项目更有竞争力,对照着视频教程做完之后,我加入了很多自己的元素比如更换消息队列 ActiveMQ 为 Kafka、增加二级缓存。
|
||||
|
||||
|
|
@ -338,7 +338,7 @@ tag:
|
|||
|
||||
到了武汉之后,我花了一天时间找了一个蛋壳公寓住下。第二天,我就跑去武汉理工大学参加宣讲会。
|
||||
|
||||

|
||||

|
||||
|
||||
当天,我就面试了自己求职过程中的第一家公司—**玄武科技**。
|
||||
|
||||
|
|
@ -356,7 +356,7 @@ tag:
|
|||
|
||||
不过,我最终如愿以偿获得了 ThoughtWorks 的 offer。
|
||||
|
||||

|
||||

|
||||
|
||||
面试 ThoughtWorks 的过程就不多说了,我在[《结束了我短暂的秋招,说点自己的感受》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484842&idx=1&sn=4489dfab0ef2479122b71407855afc71&chksm=cea24a61f9d5c3774a8ed67c5fcc3234cb0741fbe831152986e5d1c8fb4f36a003f4fb2f247e&scene=178&cur_album_id=1323354342556057602#rd)这篇文章中有提到。
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ category: 走近作者
|
|||
|
||||
下面这张是当时拍的毕业照(后排最中间的就是我):
|
||||
|
||||

|
||||

|
||||
|
||||
## 我坚持写了多久博客?
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ category: 走近作者
|
|||
|
||||
下面这张是我大三去三亚的时候拍的:
|
||||
|
||||

|
||||

|
||||
|
||||
其实,我在大学就这么努力地开始赚钱,也主要是因为家庭条件太一般,父母赚钱都太辛苦了!也正是因为我自己迫切地想要减轻父母的负担,所以才会去尝试这么多赚钱的方法。
|
||||
|
||||
|
|
@ -61,4 +61,4 @@ category: 走近作者
|
|||
|
||||
生活本就是有苦有甜。共勉!
|
||||
|
||||

|
||||

|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ star: 2
|
|||
|
||||
在 2019 年 12 月 29 号,经过了大概一年左右的犹豫期,我正式确定要开始做一个自己的星球。
|
||||
|
||||

|
||||

|
||||
|
||||
截止到今天,星球已经有 1.3w+的同学加入。虽然比不上很多大佬,但这于我来说也算是小有成就了,真的很满足了!我确信自己是一个普通人,能做成这些,也不过是在兴趣和运气的加持下赶上了时代而已。
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ star: 2
|
|||
|
||||
简单来说,知识星球就是一个私密交流圈子,主要用途是知识创作者连接铁杆读者/粉丝。相比于微信群,知识星球内容沉淀、信息管理更高效。
|
||||
|
||||

|
||||

|
||||
|
||||
## 我的知识星球能为你提供什么?
|
||||
|
||||
|
|
@ -40,55 +40,55 @@ star: 2
|
|||
|
||||
星球更新了 **《Java 面试指北》**、**《Java 必读源码系列》**(目前已经整理了 Dubbo 2.6.x 、Netty 4.x、SpringBoot2.1 的源码)、 **《从零开始写一个 RPC 框架》**(已更新完) 、**《Kafka 常见面试题/知识点总结》** 等多个优质专栏。
|
||||
|
||||

|
||||

|
||||
|
||||
《Java 面试指北》内容概览:
|
||||
|
||||

|
||||

|
||||
|
||||
### PDF 面试手册
|
||||
|
||||
免费赠送多本优质 PDF 面试手册。
|
||||
|
||||

|
||||

|
||||
|
||||
### 简历修改
|
||||
|
||||
一到面试季,我平均一天晚上至少要看 15 ~30 份简历。过了面试季的话,找我看简历的话会稍微少一些。要不然的话,是真心顶不住!
|
||||
|
||||

|
||||

|
||||
|
||||
简单统计了一下,到目前为止,我至少帮助 **4000+** 位球友提供了免费的简历修改服务。
|
||||
|
||||

|
||||

|
||||
|
||||
我会针对每一份简历给出详细的修改完善建议,用心修改,深受好评!
|
||||
|
||||

|
||||

|
||||
|
||||
### 一对一提问
|
||||
|
||||
你可以和我进行一对一免费提问交流,我会很走心地回答你的问题。到目前为止,已经累计回答了 **1000+** 个读者的提问。
|
||||
|
||||

|
||||

|
||||
|
||||
### 学习打卡
|
||||
|
||||
星球的学习打卡活动可以督促自己和其他球友们一起学习交流。
|
||||
|
||||

|
||||

|
||||
|
||||
看球友们的打卡也能有收货,最重要的是这个学习氛围对于自己自律非常有帮助!
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
### 读书活动
|
||||
|
||||
定期会举办读书活动(奖励丰厚),我会带着大家一起读一些优秀的技术书籍!
|
||||
|
||||

|
||||

|
||||
|
||||
每一期读书活动的获奖率都非常非常非常高!直接超过门票价!!!
|
||||
|
||||
|
|
@ -107,19 +107,19 @@ star: 2
|
|||
|
||||
感兴趣的小伙伴可以看看我在 2020-01-03 发的头条:[做了一个很久没敢做的事情](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486049&idx=1&sn=e0161b409e8f164251bdaa0c83a476bc&chksm=cea245aaf9d5ccbcafdb95a546d959508814085620aabdbb4385c4b8cea6e50bf157c3697041&token=1614894361&lang=zh_CN#rd),去考古一下。
|
||||
|
||||

|
||||

|
||||
|
||||
随着时间推移,星球积累的干货资源越来越多,我花在星球上的时间也越来越多。于是,我将星球的定价慢慢调整为了 **159/年**!后续会将星球的价格调整为 **199/年**,想要加入的小伙伴一定要尽早。
|
||||
|
||||
**这里再送一个 30 元的新人优惠券,数量有限(续费半价)。**
|
||||
|
||||

|
||||

|
||||
|
||||
**进入星球之后,记得添加微信,我会发你详细的星球使用指南。**
|
||||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
**真诚欢迎准备面试的小伙伴加入星球一起交流!真心希望能够帮助到更多小伙伴!**
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ head:
|
|||
|
||||
如果你要系统地学习操作系统的话,最硬核最权威的书籍是 **[《操作系统导论》](https://book.douban.com/subject/33463930/)** 。你可以再配套一个 **[《深入理解计算机系统》](https://book.douban.com/subject/1230413/)** 加深你对计算机系统本质的认识,美滋滋!
|
||||
|
||||

|
||||

|
||||
|
||||
另外,去年新出的一本国产的操作系统书籍也很不错:**[《现代操作系统:原理与实现》](https://book.douban.com/subject/35208251/)** (夏老师和陈老师团队的力作,值得推荐)。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你比较喜欢动手,对于理论知识比较抵触的话,我推荐你看看 **[《30 天自制操作系统》](https://book.douban.com/subject/11530329/)** ,这本书会手把手教你编写一个操作系统。
|
||||
|
||||
纸上学来终觉浅 绝知此事要躬行!强烈推荐 CS 专业的小伙伴一定要多多实践!!!
|
||||
|
||||

|
||||

|
||||
|
||||
其他相关书籍推荐:
|
||||
|
||||
|
|
@ -47,23 +47,23 @@ head:
|
|||
|
||||
课程的大纲如下:
|
||||
|
||||

|
||||

|
||||
|
||||
主要讲了一个基本操作系统中的六个基本模块: CPU 管理、内存管理、外设管理、磁盘管理与文件系统、用户接口和启动模块 。
|
||||
|
||||
课程难度还是比较大的,尤其是课后的 lab。如果大家想要真正搞懂操作系统底层原理的话,对应的 lab 能做尽量做一下。正如李治军老师说的那样:“纸上得来终觉浅,绝知此事要躬行”。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你能独立完成几个 lab 的话,我相信你对操作系统的理解绝对要上升几个台阶。当然了,如果你仅仅是为了突击面试的话,那就不需要做 lab 了。
|
||||
|
||||
说点心里话,我本人非常喜欢李治军老师讲的课,我觉得他是国内不可多得的好老师。他知道我们国内的教程和国外的差距在哪里,也知道国内的学生和国外学生的差距在哪里,他自己在努力着通过自己的方式来缩小这个差距。真心感谢,期待李治军老师的下一个课程。
|
||||
|
||||

|
||||

|
||||
|
||||
还有下面这个国外的课程 [《深入理解计算机系统 》](https://www.bilibili.com/video/av31289365?from=search&seid=16298868573410423104) 也很不错。
|
||||
|
||||

|
||||

|
||||
|
||||
## 计算机网络
|
||||
|
||||
|
|
@ -71,18 +71,18 @@ head:
|
|||
|
||||
要想学好计算机网络,首先要了解的就是 OSI 七层模型或 TCP/IP 五层模型,即应用层(应用层、表示层、会话层)、传输层、网络层、数据链路层、物理层。
|
||||
|
||||

|
||||

|
||||
|
||||
关于这门课,首先强烈推荐参考书是**机械工业出版社的《计算机网络——自顶向下方法》**。该书目录清晰,按照 TCP/IP 五层模型逐层讲解,对每层涉及的技术都展开了详细讨论,基本上高校里开设的课程的教学大纲就是这本书的目录了。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你觉得上面这本书看着比较枯燥的话,我强烈推荐+安利你看看下面这两本非常有趣的网络相关的书籍:
|
||||
|
||||
- [《图解 HTTP》](https://book.douban.com/subject/25863515/ "《图解 HTTP》") : 讲漫画一样的讲 HTTP,很有意思,不会觉得枯燥,大概也涵盖也 HTTP 常见的知识点。因为篇幅问题,内容可能不太全面。不过,如果不是专门做网络方向研究的小伙伴想研究 HTTP 相关知识的话,读这本书的话应该来说就差不多了。
|
||||
- [《网络是怎样连接的》](https://book.douban.com/subject/26941639/ "《网络是怎样连接的》") :从在浏览器中输入网址开始,一路追踪了到显示出网页内容为止的整个过程,以图配文,讲解了网络的全貌,并重点介绍了实际的网络设备和软件是如何工作的。
|
||||
|
||||

|
||||

|
||||
|
||||
除了理论知识之外,学习计算机网络非常重要的一点就是:“**动手实践**”。这点和我们编程差不多。
|
||||
|
||||
|
|
@ -97,11 +97,11 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**1、[哈工大的计算机网络课程](http://www.icourse163.org/course/HIT-154005)** :国家精品课程,截止目前已经开了 10 次课了。大家对这门课的评价都非常高!所以,非常推荐大家看一下!
|
||||
|
||||

|
||||

|
||||
|
||||
**2、[王道考研的计算机网络](https://www.bilibili.com/video/BV19E411D78Q?from=search&seid=17198507506906312317)** :非常适合 CS 专业考研的小朋友!这个视频目前在哔哩哔哩上已经有 1.6w+的点赞。
|
||||
|
||||

|
||||

|
||||
|
||||
## 算法
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
2. [《算法图解》](https://book.douban.com/subject/26979890/)
|
||||
3. [《啊哈!算法》](https://book.douban.com/subject/25894685/)
|
||||
|
||||

|
||||

|
||||
|
||||
我个人比较倾向于 **[《我的第一本算法书》](https://book.douban.com/subject/30357170/)** 这本书籍,虽然它相比于其他两本书集它的豆瓣评分略低一点。我觉得它的配图以及讲解是这三本书中最优秀,唯一比较明显的问题就是没有代码示例。但是,我觉得这不影响它是一本好的算法书籍。因为本身下面这三本入门书籍的目的就不是通过代码来让你的算法有多厉害,只是作为一本很好的入门书籍让你进入算法学习的大门。
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《算法》](https://book.douban.com/subject/19952400/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书内容非常清晰易懂,适合数据结构和算法小白阅读。书中把一些常用的数据结构和算法都介绍到了!
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《编程珠玑》](https://book.douban.com/subject/3227098/)**
|
||||
|
||||

|
||||

|
||||
|
||||
经典名著,ACM 冠军、亚军这种算法巨佬都强烈推荐的一本书籍。这本书的作者也非常厉害,Java 之父 James Gosling 就是他的学生。
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《算法设计手册》](https://book.douban.com/subject/4048566/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这是一本被 Github 上的爆火的计算机自学项目 [Teach Yourself Computer Science](https://link.zhihu.com/?target=https%3A//teachyourselfcs.com/) 强烈推荐的一本算法书籍。
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《剑指 Offer》](https://book.douban.com/subject/6966465/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本面试宝典上面涵盖了很多经典的算法面试题,如果你要准备大厂面试的话一定不要错过这本书。
|
||||
|
||||
|
|
@ -157,13 +157,13 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《程序员代码面试指南(第 2 版)》](https://book.douban.com/subject/30422021/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《程序员代码面试指南(第 2 版)》里的大部分题目相比于《剑指 offer》 来说要难很多,题目涵盖面相比于《剑指 offer》也更加全面。全书一共有将近 300 道真实出现过的经典代码面试题。
|
||||
|
||||
视频的话,推荐北京大学的国家精品课程—**[程序设计与算法(二)算法基础](https://www.icourse163.org/course/PKU-1001894005)**,讲的非常好!
|
||||
|
||||

|
||||

|
||||
|
||||
这个课程把七种基本的通用算法(枚举、二分、递归、分治、动态规划、搜索、贪心)都介绍到了。各种复杂算法问题的解决,都可能用到这些基本的思想。并且,这个课程的一部分的例题和 ACM 国际大学生程序设计竞赛中的中等题相当,如果你能够解决这些问题,那你的算法能力将超过绝大部分的高校计算机专业本科毕业生。
|
||||
|
||||
|
|
@ -175,19 +175,19 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
**[《大话数据结构》](https://book.douban.com/subject/6424904/)**
|
||||
|
||||

|
||||

|
||||
|
||||
入门类型的书籍,读起来比较浅显易懂,适合没有数据结构基础或者说数据结构没学好的小伙伴用来入门数据结构。
|
||||
|
||||
**[《数据结构与算法分析:Java 语言描述》](https://book.douban.com/subject/3351237/)**
|
||||
|
||||

|
||||

|
||||
|
||||
质量很高,介绍了常用的数据结构和算法。
|
||||
|
||||
类似的还有 **[《数据结构与算法分析 :C 语言描述》](https://book.douban.com/subject/1139426/)** 、**[《数据结构与算法分析:C++ 描述》](https://book.douban.com/subject/1971825/)**
|
||||
|
||||

|
||||

|
||||
|
||||
视频的话推荐你看浙江大学的国家精品课程—**[《数据结构》](https://www.icourse163.org/course/ZJU-93001#/info)** 。
|
||||
|
||||
|
|
@ -207,17 +207,17 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
书籍的话,推荐《普林斯顿微积分读本》。这本书详细讲解了微积分基础、极限、连续、微分、导数的应用、积分、无穷级数、泰勒级数与幂级数等内容。
|
||||
|
||||

|
||||

|
||||
|
||||
#### 线性代数(高等代数)
|
||||
|
||||
线性代数的思维模式就更加复杂了一些,它定义了一个全新的数学世界,所有的符号、定理都是全新的,唯一能尝试的去理解的方式,大概就是用几何的方式去理解线性代数了。由于线性代数和几何学有着密不可分的关系,比如空间变换的理论支撑就是线性代数,因此,网上有着各种“可视化学习线性代数”的学习资源,帮助理解线性代数的意义,有助于公式的记忆。
|
||||
|
||||

|
||||

|
||||
|
||||
书籍的话,推荐中科大李尚志老师的 **[《线性代数学习指导》](https://book.douban.com/subject/26390093/)** 。
|
||||
|
||||

|
||||

|
||||
|
||||
#### 概率论与数理统计
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
书籍的话,推荐 **[《概率论与数理统计教程》](https://book.douban.com/subject/34897672/)** 。这本书共八章,前四章为概率论部分,主要叙述各种概率分布及其性质,后四章为数理统计部分,主要叙述各种参数估计与假设检验。
|
||||
|
||||

|
||||

|
||||
|
||||
#### 离散数学(集合论、图论、近世代数等)
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
总的来说,这门课对于各位程序员的职业发展来说,相对不那么重要,但是从难度上来说,学习这门课可以对编程思想有一个较好的巩固。学习资源的话,除了课堂上的幻灯片课件以外,还可以把 《编译原理》 这本书作为参考书,用以辅助自己学不懂的地方(大家口中的龙书,想要啃下来还是有一定难度的)。
|
||||
|
||||

|
||||

|
||||
|
||||
其他书籍推荐:
|
||||
|
||||
|
|
@ -271,4 +271,4 @@ Github 上就有一些名校的计算机网络试验/Project:
|
|||
|
||||
我上面推荐的书籍的难度还是比较高的,真心很难坚持看完。这里强烈推荐[哈工大的编译原理视频课程](https://www.icourse163.org/course/HIT-1002123007),真心不错,还是国家精品课程,关键还是又漂亮有温柔的美女老师讲的!
|
||||
|
||||

|
||||

|
||||
|
|
@ -36,13 +36,13 @@ Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍
|
|||
|
||||
[《数据库系统概念》](https://book.douban.com/subject/10548379/)这本书涵盖了数据库系统的全套概念,知识体系清晰,是学习数据库系统非常经典的教材!不是参考书!
|
||||
|
||||

|
||||

|
||||
|
||||
### 《数据库系统实现》
|
||||
|
||||
如果你也想要研究 MySQL 底层原理的话,我推荐你可以先阅读一下[《数据库系统实现》](https://book.douban.com/subject/4838430/)。
|
||||
|
||||

|
||||

|
||||
|
||||
不管是 MySQL 还是Oracle ,它们总体的架子是差不多的,不同的是其内部的实现比如数据库索引的数据结构、存储引擎的实现方式等等。
|
||||
|
||||
|
|
@ -66,13 +66,13 @@ Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍
|
|||
|
||||
另外,强推一波 **[《MySQL 是怎样运行的》](https://book.douban.com/subject/35231266/)** 这本书,内容很适合拿来准备面试。讲的很细节,但又不枯燥,内容非常良心!
|
||||
|
||||

|
||||

|
||||
|
||||
## PostgreSQL
|
||||
|
||||
和 MySQL 一样,PostgreSQL 也是开源免费且功能强大的关系型数据库。PostgreSQL 的 Slogan 是“**世界上最先进的开源关系型数据库**” 。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,由于 PostgreSQL 的各种新特性过于优秀,使用 PostgreSQL 代替 MySQL 的项目越来越多了。
|
||||
|
||||
|
|
@ -84,13 +84,13 @@ Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍
|
|||
|
||||
刚工作那会需要用到 PostgreSQL ,看了大概 1/3 的内容,感觉还不错。
|
||||
|
||||

|
||||

|
||||
|
||||
### 《PostgreSQL 技术内幕:查询优化深度探索》
|
||||
|
||||
[《PostgreSQL 技术内幕:查询优化深度探索》](https://book.douban.com/subject/30256561/)这本书主要讲了 PostgreSQL 在查询优化上的一些技术实现细节,可以让你对 PostgreSQL 的查询优化器有深层次的了解。
|
||||
|
||||

|
||||

|
||||
|
||||
## Redis
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ icon: "distributed-network"
|
|||
|
||||
## 《深入理解分布式系统》
|
||||
|
||||

|
||||

|
||||
|
||||
**[《深入理解分布式系统》](https://book.douban.com/subject/35794814/)** 是今年 3 月份刚出的一本分布式中文原创书籍,主要讲的是分布式领域的基本概念、常见挑战以及共识算法。
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ icon: "distributed-network"
|
|||
|
||||
作者从 2019 年开始构思《深入理解分布式系统》,2020 年开始动笔,花了接近两年的时间才最终交稿。
|
||||
|
||||

|
||||

|
||||
|
||||
作者专门写了一篇文章来介绍这本书的背后的故事,感兴趣的小伙伴可以自行查阅:https://zhuanlan.zhihu.com/p/487534882 。
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ icon: "distributed-network"
|
|||
|
||||
## 《数据密集型应用系统设计》
|
||||
|
||||

|
||||

|
||||
|
||||
强推一波 **[《Designing Data-Intensive Application》](https://book.douban.com/subject/30329536/)** (DDIA,数据密集型应用系统设计),值得读很多遍!豆瓣有接近 90% 的人看了这本书之后给了五星好评。
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ icon: "distributed-network"
|
|||
|
||||
## 《深入理解分布式事务》
|
||||
|
||||

|
||||

|
||||
|
||||
**[《深入理解分布式事务》](https://book.douban.com/subject/35626925/)** 这本书是的其中一位作者是 Apache ShenYu(incubating)网关创始人、Hmily、RainCat、Myth等分布式事务框架的创始人。
|
||||
|
||||
|
|
@ -46,19 +46,19 @@ icon: "distributed-network"
|
|||
|
||||
## 《从 Paxos 到 Zookeeper》
|
||||
|
||||

|
||||

|
||||
|
||||
**[《从 Paxos 到 Zookeeper》](https://book.douban.com/subject/26292004/)** 是一本带你入门分布式理论的好书。这本书主要介绍几种典型的分布式一致性协议,以及解决分布式一致性问题的思路,其中重点讲解了 Paxos 和 ZAB 协议。
|
||||
|
||||
## 《微服务架构设计模式》
|
||||
|
||||

|
||||

|
||||
|
||||
**[《微服务架构设计模式》](https://book.douban.com/subject/33425123/)** 的作者 Chris Richardson 被评为世界十大软件架构师之一、微服务架构先驱。这本书主要讲的是如何开发和部署生产级别的微服务架构应用,示例代码使用 Java 语言和 Spring 框架。
|
||||
|
||||
## 《凤凰架构》
|
||||
|
||||

|
||||

|
||||
|
||||
**[《凤凰架构》](https://book.douban.com/subject/35492898/)** 这本书是周志明老师多年架构和研发经验的总结,内容非常干货,深度与广度并存,理论结合实践!
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ icon: "distributed-network"
|
|||
|
||||
## 《架构解密》
|
||||
|
||||

|
||||

|
||||
|
||||
[《架构解密》](https://book.douban.com/subject/35093373/)这本书和我渊源颇深,在大三的时候,我曾经在图书馆借阅过这本书的第一版,大概了花了不到一周就看完了。
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ icon: "java"
|
|||
|
||||
**[《Head First Java》](https://book.douban.com/subject/2000732/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《Head First Java》这本书的内容很轻松有趣,可以说是我学习编程初期最喜欢的几本书之一了。同时,这本书也是我的 Java 启蒙书籍。我在学习 Java 的初期多亏了这本书的帮助,自己才算是跨进 Java 语言的大门。
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ icon: "java"
|
|||
|
||||
**[《Java 核心技术卷 1+卷 2》](https://book.douban.com/subject/34898994/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这两本书也非常不错。不过,这两本书的内容很多,全看的话比较费时间。我现在是把这两本书当做工具书来用,就比如我平时写文章的时候,碰到一些 Java 基础方面的问题,经常就翻看这两本来当做参考!
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ icon: "java"
|
|||
|
||||
**[《Java 编程思想》](https://book.douban.com/subject/2130190/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书被很多人称之为 Java 领域的圣经(_感觉有点过了~~~_)。不太推荐编程初学者阅读,有点劝退的味道,稍微有点基础后阅读更好。
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ icon: "java"
|
|||
|
||||
**[《Java 8实战》](https://book.douban.com/subject/26772632/)**
|
||||
|
||||

|
||||

|
||||
|
||||
Java 8 算是一个里程碑式的版本,现在一般企业还是用 Java 8 比较多。掌握 Java 8 的一些新特性比如 Lambda、Strean API 还是挺有必要的。这块的话,我推荐 **[《Java 8 实战》](https://book.douban.com/subject/26772632/)** 这本书。
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ Java 8 算是一个里程碑式的版本,现在一般企业还是用 Java 8
|
|||
|
||||
**[《Java 并发编程之美》](https://book.douban.com/subject/30351286/)**
|
||||
|
||||

|
||||

|
||||
|
||||
_这本书还是非常适合我们用来学习 Java 多线程的。这本书的讲解非常通俗易懂,作者从并发编程基础到实战都是信手拈来。_
|
||||
|
||||
|
|
@ -52,13 +52,13 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
**[《实战 Java 高并发程序设计》](https://book.douban.com/subject/30358019/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这个是我第二本要推荐的书籍,比较适合作为多线程入门/进阶书籍来看。这本书内容同样是理论结合实战,对于每个知识点的讲解也比较通俗易懂,整体结构也比较清。
|
||||
|
||||
**[《深入浅出 Java 多线程》](https://github.com/RedSpider1/concurrent)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本开源书籍是几位大厂的大佬开源的。这几位作者为了写好《深入浅出 Java 多线程》这本书阅读了大量的 Java 多线程方面的书籍和博客,然后再加上他们的经验总结、Demo 实例、源码解析,最终才形成了这本书。
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
**[《Java 并发实现原理:JDK 源码剖析》](https://book.douban.com/subject/35013531/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书是 2020 年新出的,所以,现在知道的人还不是很多。
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
**[《深入理解 Java 虚拟机》](https://book.douban.com/subject/34907497/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书就一句话形容:**国产书籍中的战斗机,实实在在的优秀!** (真心希望国内能有更多这样的优质书籍出现!加油!💪)
|
||||
|
||||
|
|
@ -90,13 +90,13 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
类似的书籍还有 **[《实战 Java 虚拟机》](https://book.douban.com/subject/26354292/)**、**[《虚拟机设计与实现:以 JVM 为例》](https://book.douban.com/subject/34935105/)** ,这两本都是非常不错的!
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
如果你对实战比较感兴趣,想要自己动手写一个简易的 JVM 的话,可以看看 **[《自己动手写 Java 虚拟机》](https://book.douban.com/subject/26802084/)** 这本书。
|
||||
|
||||

|
||||

|
||||
|
||||
书中的代码是基于 Go 语言实现的,搞懂了原理之后,你可以使用 Java 语言模仿着写一个,也算是练练手! 如果你当前没有能力独立使用 Java 语言模仿着写一个的话,你也可以在网上找到很多基于 Java 语言版本的实现,比如[《zachaxy 的手写 JVM 系列》](https://zachaxy.github.io/tags/JVM/) 。
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
第 2 个是你假笨大佬的 **[《JVM 参数【Memory 篇】》](https://club.perfma.com/course/438755/list)** 教程,很厉害了!
|
||||
|
||||

|
||||

|
||||
|
||||
## 常用工具
|
||||
|
||||
|
|
@ -147,19 +147,19 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
|||
|
||||
**[《Spring 实战》](https://book.douban.com/subject/34949443/)**
|
||||
|
||||

|
||||

|
||||
|
||||
不建议当做入门书籍读,入门的话可以找点国人的书或者视频看。这本定位就相当于是关于 Spring 的一个概览,只有一些基本概念的介绍和示例,涵盖了 Spring 的各个方面,但都不够深入。就像作者在最后一页写的那样:“学习 Spring,这才刚刚开始”。
|
||||
|
||||
**[《Spring 5 高级编程》](https://book.douban.com/subject/30452637/)**
|
||||
|
||||

|
||||

|
||||
|
||||
对于 Spring5 的新特性介绍的比较详细,也说不上好。另外,感觉全书翻译的有一点蹩脚的味道,还有一点枯燥。全书的内容比较多,我一般拿来当做工具书参考。
|
||||
|
||||
**[《Spring Boot 编程思想(核心篇)》](https://book.douban.com/subject/33390560/)**
|
||||
|
||||

|
||||

|
||||
|
||||
_稍微有点啰嗦,但是原理介绍的比较清楚。_
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ SpringBoot 解析,不适合初学者。我是去年入手的,现在就看了
|
|||
|
||||
**[《Spring Boot 实战》](https://book.douban.com/subject/26857423/)**
|
||||
|
||||

|
||||

|
||||
|
||||
比较一般的一本书,可以简单拿来看一下。
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ SpringBoot 解析,不适合初学者。我是去年入手的,现在就看了
|
|||
|
||||
**[《Netty 实战》](https://book.douban.com/subject/27038538/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书可以用来入门 Netty ,内容从 BIO 聊到了 NIO、之后才详细介绍为什么有 Netty 、Netty 为什么好用以及 Netty 重要的知识点讲解。
|
||||
|
||||
|
|
@ -183,13 +183,13 @@ SpringBoot 解析,不适合初学者。我是去年入手的,现在就看了
|
|||
|
||||
**[《Netty 进阶之路:跟着案例学 Netty》](https://book.douban.com/subject/30381214/)**
|
||||
|
||||

|
||||

|
||||
|
||||
内容都是关于使用 Netty 的实践案例比如内存泄露这些东西。如果你觉得你的 Netty 已经完全入门了,并且你想要对 Netty 掌握的更深的话,推荐你看一下这本书。
|
||||
|
||||
**[《跟闪电侠学 Netty:Netty 即时聊天实战与底层原理》](https://book.douban.com/subject/35752082/)**
|
||||
|
||||

|
||||

|
||||
|
||||
2022 年 3 月刚刚出版的一本书。这本书分为上下两篇,上篇通过一个即时聊天系统的实战案例带你入门 Netty,下篇通过 Netty 源码分析带你搞清 Netty 比较重要的底层原理。
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ SpringBoot 解析,不适合初学者。我是去年入手的,现在就看了
|
|||
|
||||
**[《Java 性能权威指南》](https://book.douban.com/subject/26740520/)**
|
||||
|
||||

|
||||

|
||||
|
||||
_希望能有更多这 Java 性能优化方面的好书!_
|
||||
|
||||
|
|
@ -211,11 +211,11 @@ O'Reilly 家族书,性能调优的入门书,我个人觉得性能调优是
|
|||
|
||||
目前我觉得能推荐的只有李运华老师的 **[《从零开始学架构》](https://book.douban.com/subject/30335935/)** 和 余春龙老师的 **[《软件架构设计:大型网站技术架构与业务架构融合之道》](https://book.douban.com/subject/30443578/ "《软件架构设计:大型网站技术架构与业务架构融合之道》")** 。
|
||||
|
||||

|
||||

|
||||
|
||||
《从零开始学架构》这本书对应的有一个极客时间的专栏—《从零开始学架构》,里面的很多内容都是这个专栏里面的,两者买其一就可以了。我看了很小一部分,内容挺全面的,是一本真正在讲如何做架构的书籍。
|
||||
|
||||

|
||||

|
||||
|
||||
事务与锁、分布式(CAP、分布式事务......)、高并发、高可用 《软件架构设计:大型网站技术架构与业务架构融合之道》 这本书都有介绍到。
|
||||
|
||||
|
|
@ -223,12 +223,12 @@ O'Reilly 家族书,性能调优的入门书,我个人觉得性能调优是
|
|||
|
||||
**《JavaGuide 面试突击版》**
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
[JavaGuide](https://javaguide.cn/) 的面试版本,涵盖了 Java 后端方面的大部分知识点比如 集合、JVM、多线程还有数据库 MySQL 等内容。
|
||||
|
||||
公众号后台回复 :“**面试突击**” 即可免费获取,无任何套路。
|
||||
|
||||

|
||||

|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@ category: 计算机书籍
|
|||
|
||||
本项目推荐的大部分书籍的 PDF 版本我已经整理到了云盘里,你可以在公众号“**Github掘金计划**” 后台回复“**书籍**”获取到。
|
||||
|
||||

|
||||

|
||||
|
|
@ -10,13 +10,13 @@ Elasticsearch 在 Apache Lucene 的基础上开发而成,学习 ES 之前,
|
|||
|
||||
**[《Lucene实战》](https://book.douban.com/subject/6440615/)** 是国内为数不多的中文版本讲 Lucene 的书籍,适合用来学习和了解 Lucene 相关的概念和常见操作。
|
||||
|
||||

|
||||

|
||||
|
||||
## Elasticsearch
|
||||
|
||||
极客时间的[《Elasticsearch 核心技术与实战》](http://gk.link/a/10bcT "《Elasticsearch 核心技术与实战》")这门课程基于 Elasticsearch 7.1 版本讲解,还算比较新。并且,作者是 eBay 资深技术专家,有 20 年的行业经验,课程质量有保障!
|
||||
|
||||

|
||||

|
||||
|
||||
如果你想看书的话,可以考虑一下 **[《Elasticsearch 实战》](https://book.douban.com/subject/30380439/)** 这本书。不过,需要说明的是,这本书中的 Elasticsearch 版本比较老,你可以将其作为一个参考书籍来看,有一些原理性的东西可以在上面找找答案。
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ head:
|
|||
|
||||
**[《重构》](https://book.douban.com/subject/30468597/)**
|
||||
|
||||

|
||||

|
||||
|
||||
必看书籍!无需多言。编程书籍领域的瑰宝。
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ head:
|
|||
|
||||
**[《Clean Code》](https://book.douban.com/subject/4199741/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《Clean Code》是 Bob 大叔的一本经典著作,强烈建议小伙伴们一定要看看。
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《Effective Java 》](https://book.douban.com/subject/30412517/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《Effective Java 》这本书是 Java 领域国宝级别的书,非常经典。Java 程序员必看!
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《代码大全》](https://book.douban.com/subject/1477390/)**
|
||||
|
||||

|
||||

|
||||
|
||||
其实,《代码大全(第 2 版)》这本书我本身是不太想推荐给大家了。但是,看在它的豆瓣评分这么高的份上,还是拿出来说说吧!
|
||||
|
||||
|
|
@ -54,11 +54,11 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《编写可读代码的艺术》](https://book.douban.com/subject/10797189/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《编写可读代码的艺术》这本书要表达的意思和《Clean Code》很像,你看它俩的目录就可以看出来了。
|
||||
|
||||

|
||||

|
||||
|
||||
在我看来,如果你看过 《Clean Code》 的话,就不需要再看这本书了。当然,如果你有时间和精力,也可以快速过一遍。
|
||||
|
||||
|
|
@ -66,13 +66,13 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
在实践中学习的效果肯定会更好!推荐小伙伴们都抓紧学起来啊!
|
||||
|
||||

|
||||

|
||||
|
||||
## 程序员职业素养
|
||||
|
||||
**[《The Clean Coder》](https://book.douban.com/subject/26919457/)**
|
||||
|
||||

|
||||

|
||||
|
||||
《 The Clean Coder》是 Bob 大叔的又一经典著作。
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《架构整洁之道》](https://book.douban.com/subject/30333919/)**
|
||||
|
||||

|
||||

|
||||
|
||||
你没看错,《架构整洁之道》这本书又是 Bob 大叔的经典之作。
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《人月神话》](https://book.douban.com/subject/1102259/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本书主要描述了软件开发的基本定律:**一个需要 10 天才能干完的活,不可能让 10 个人在 1 天干完!**
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
|||
|
||||
**[《领域驱动设计:软件核心复杂性应对之道》](https://book.douban.com/subject/5344973/)**
|
||||
|
||||

|
||||

|
||||
|
||||
这本领域驱动设计方面的经典之作一直被各种推荐,但是我还来及读。
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ tag:
|
|||
|
||||
常见的内部排序算法有:**插入排序**、**希尔排序**、**选择排序**、**冒泡排序**、**归并排序**、**快速排序**、**堆排序**、**基数排序**等,本文只讲解内部排序算法。用一张图概括:
|
||||
|
||||

|
||||

|
||||
|
||||
**图片名词解释:**
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ tag:
|
|||
|
||||
十种常见排序算法可以分类两大类别:**比较类排序**和**非比较类排序**。
|
||||
|
||||

|
||||

|
||||
|
||||
常见的**快速排序**、**归并排序**、**堆排序**以及**冒泡排序**等都属于**比较类排序算法**。比较类排序是通过比较来决定元素间的相对次序,由于其时间复杂度不能突破 `O(nlogn)`,因此也称为非线性时间比较类排序。在冒泡排序之类的排序中,问题规模为 `n`,又因为需要比较 `n` 次,所以平均时间复杂度为 `O(n²)`。在**归并排序**、**快速排序**之类的排序中,问题规模通过**分治法**消减为 `logn` 次,所以时间复杂度平均 `O(nlogn)`。
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ tag:
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ public static int[] bubbleSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ public static int[] selectionSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ public static int[] insertionSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ public static int[] shellSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ public static int[] merge(int[] arr_1, int[] arr_2) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -411,7 +411,7 @@ public static void quickSort(int[] array, int low, int high) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -505,7 +505,7 @@ public static int[] heapSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -586,7 +586,7 @@ public static int[] countingSort(int[] arr) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
@ -667,7 +667,7 @@ public static List<Integer> bucketSort(List<Integer> arr, int bucket_size) {
|
|||
|
||||
### 图解算法
|
||||
|
||||

|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ tag:
|
|||
|
||||
**二叉树** 的第 i 层至多拥有 `2^(i-1)` 个节点,深度为 k 的二叉树至多总共有 `2^(k+1)-1` 个节点(满二叉树的情况),至少有 2^(k) 个节点(关于节点的深度的定义国内争议比较多,我个人比较认可维基百科对[节点深度的定义](https://zh.wikipedia.org/wiki/%E6%A0%91_(%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)#/%E6%9C%AF%E8%AF%AD))。
|
||||
|
||||

|
||||

|
||||
|
||||
### 满二叉树
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ tag:
|
|||
|
||||
**超文本传输协议(HTTP,HyperText Transfer Protocol)** 主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的,整个过程如下图所示。
|
||||
|
||||

|
||||

|
||||
|
||||
HTTP 协是基于 TCP协议,发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样的话建立的连接就可以在多次请求中被复用了。
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ HTTP 协是基于 TCP协议,发送 HTTP 请求之前首先要建立 TCP 连接
|
|||
|
||||
**简单邮件传输(发送)协议(SMTP,Simple Mail Transfer Protocol)** 基于 TCP 协议,用来发送电子邮件。
|
||||
|
||||

|
||||

|
||||
|
||||
注意⚠️:**接受邮件的协议不是 SMTP 而是 POP3 协议。**
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ FTP 是基于客户—服务器(C/S)模型而设计的,在客户端与 FTP
|
|||
>
|
||||
> 这种将命令和数据分开传送的思想大大提高了 FTP 的效率。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## Telnet:远程登陆协议
|
||||
|
|
@ -84,4 +84,4 @@ FTP 是基于客户—服务器(C/S)模型而设计的,在客户端与 FTP
|
|||
|
||||
**Telnet 和 SSH 之间的主要区别在于 SSH 协议会对传输的数据进行加密保证数据安全性。**
|
||||
|
||||

|
||||

|
||||
|
|
@ -131,7 +131,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
|||
|
||||
对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看[数字签名及数字证书原理](https://www.bilibili.com/video/BV18N411X7ty/)这个视频,这是我看过最清晰的讲解。
|
||||
|
||||

|
||||

|
||||
|
||||
## 总结
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ tag:
|
|||
|
||||
**OSI 七层模型** 是国际标准化组织提出一个网络分层模型,其大体结构以及每一层提供的功能如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
每一层都专注做一件事情,并且每一层都需要使用下一层提供的功能比如传输层需要使用网络层提供的路由和寻址功能,这样传输层才知道把数据传输到哪里去。
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ tag:
|
|||
|
||||
上面这种图可能比较抽象,再来一个比较生动的图片。下面这个图片是我在国外的一个网站上看到的,非常赞!
|
||||
|
||||

|
||||

|
||||
|
||||
**既然 OSI 七层模型这么厉害,为什么干不过 TCP/IP 四 层模型呢?**
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||
|
||||
最后再分享一个关于 OSI 七层模型非常不错的总结图片!
|
||||
|
||||

|
||||

|
||||
|
||||
## TCP/IP 四层模型
|
||||
|
||||
|
|
@ -45,17 +45,17 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||
|
||||
需要注意的是,我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来,不过可以简单将两者对应起来,如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
### 应用层(Application layer)
|
||||
|
||||
**应用层位于传输层之上,主要提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给下一层传输层来传输。** 我们把应用层交互的数据单元称为报文。
|
||||
|
||||

|
||||

|
||||
|
||||
应用层协议定义了网络通信规则,对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如支持 Web 应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。
|
||||
|
||||

|
||||

|
||||
|
||||
应用层常见协议总结,请看这篇文章:[应用层常见协议总结(应用层)](./application-layer-protocol.md)。
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||
1. **传输控制协议 TCP**(Transmisson Control Protocol)--提供 **面向连接** 的,**可靠的** 数据传输服务。
|
||||
2. **用户数据协议 UDP**(User Datagram Protocol)--提供 **无连接** 的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。
|
||||
|
||||

|
||||

|
||||
|
||||
### 网络层(Network layer)
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||
|
||||
互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Internet Prococol)和许多路由选择协议,因此互联网的网络层也叫做 **网际层** 或 **IP 层**。
|
||||
|
||||

|
||||

|
||||
|
||||
**网络层常见协议** :
|
||||
|
||||
|
|
@ -98,13 +98,13 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||
1. 数据链路层(data link layer)通常简称为链路层( 两台主机之间的数据传输,总是在一段一段的链路上传送的)。**数据链路层的作用是将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。**
|
||||
2. **物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异**
|
||||
|
||||

|
||||

|
||||
|
||||
### 总结
|
||||
|
||||
简单总结一下每一层包含的协议和核心技术:
|
||||
|
||||

|
||||

|
||||
|
||||
**应用层协议** :
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ tag:
|
|||
|
||||
## 建立连接-TCP 三次握手
|
||||
|
||||

|
||||

|
||||
|
||||
建立一个 TCP 连接需要“三次握手”,缺一不可 :
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ tag:
|
|||
|
||||
## 断开连接-TCP 四次挥手
|
||||
|
||||

|
||||

|
||||
|
||||
断开一个 TCP 连接则需要“四次挥手”,缺一不可 :
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
|
|||
|
||||
**TCP发送窗口结构图示** :
|
||||
|
||||

|
||||

|
||||
|
||||
- **SND.WND** :发送窗口。
|
||||
- **SND.UNA**:Send Unacknowledged 指针,指向发送窗口的第一个字节。
|
||||
|
|
@ -52,7 +52,7 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
|
|||
|
||||
**TCP 接收窗口结构图示** :
|
||||
|
||||

|
||||

|
||||
|
||||
**接收窗口的大小是根据接收端处理数据的速度动态调整的。** 如果接收端读取数据快,接收窗口可能会扩大。 否则,它可能会缩小。
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
|
|||
|
||||
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
|
||||
|
||||

|
||||

|
||||
|
||||
为了进行拥塞控制,TCP 发送方要维持一个 **拥塞窗口(cwnd)** 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ head:
|
|||
|
||||
## 从认识操作系统开始
|
||||
|
||||

|
||||

|
||||
|
||||
正式开始 Linux 之前,简单花一点点篇幅科普一下操作系统相关的内容。
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ head:
|
|||
|
||||
> 内核(Kernel)在后文中会提到。
|
||||
|
||||

|
||||

|
||||
|
||||
### 操作系统简单分类
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
|
|||
|
||||
下图清晰说明了应用程序、内核、CPU 这三者的关系。
|
||||
|
||||

|
||||

|
||||
|
||||
### 系统调用
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
|
|||
|
||||
我在网上找了一个图,通过这个图可以很清晰的说明用户程序、系统调用、内核和硬件之间的关系。(_太难了~木有自己画_)
|
||||
|
||||

|
||||

|
||||
|
||||
## 初探 Linux
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ head:
|
|||
3. **操作系统存在屏蔽了硬件层的复杂性。** 操作系统就像是硬件使用的负责人,统筹着各种相关事项。
|
||||
4. **操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理**。 内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。
|
||||
|
||||

|
||||

|
||||
|
||||
### 系统调用
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ head:
|
|||
|
||||
🙋 **我:** 好的! 下图是 Java 内存区域,我们从 JVM 的角度来说一下线程和进程之间的关系吧!
|
||||
|
||||

|
||||

|
||||
|
||||
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈**。
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ head:
|
|||
|
||||
图中 2-21 是**进程-资源分配图**的一个例子,其中共有三个资源类,每个进程的资源占有和申请情况已清楚地表示在图中。在这个例子中,由于存在 **占有和等待资源的环路** ,导致一组进程永远处于等待资源的状态,发生了 **死锁**。
|
||||
|
||||

|
||||

|
||||
|
||||
进程-资源分配图中存在环路并不一定是发生了死锁。因为循环等待资源仅仅是死锁发生的必要条件,而不是充分条件。图 2-22 便是一个有环路而无死锁的例子。虽然进程 P1 和进程 P3 分别占用了一个资源 R1 和一个资源 R2,并且因为等待另一个资源 R2 和另一个资源 R1 形成了环路,但进程 P2 和进程 P4 分别占有了一个资源 R1 和一个资源 R2,它们申请的资源得到了满足,在有限的时间里会归还资源,于是进程 P1 或 P3 都能获得另一个所需的资源,环路自动解除,系统也就不存在死锁状态了。
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ ER 图由下面 3 个要素组成:
|
|||
|
||||
下图是一个学生选课的 ER 图,每个学生可以选若干门课程,同一门课程也可以被若干人选择,所以它们之间的关系是多对多(M: N)。另外,还有其他两种实体之间的关系是:1 对 1(1:1)、1 对多(1: N)。
|
||||
|
||||

|
||||

|
||||
|
||||
## 数据库范式了解吗?
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ ER 图由下面 3 个要素组成:
|
|||
|
||||
2NF 在 1NF 的基础之上,消除了非主属性对于码的部分函数依赖。如下图所示,展示了第一范式到第二范式的过渡。第二范式在第一范式的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。
|
||||
|
||||

|
||||

|
||||
|
||||
一些重要的概念:
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ ER 图由下面 3 个要素组成:
|
|||
|
||||
阿里巴巴 Java 开发手册里要求禁止使用存储过程。
|
||||
|
||||

|
||||

|
||||
|
||||
## drop、delete 与 truncate 区别?
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ ASCII 字符集至今为止共定义了 128 个字符,其中有 33 个控制
|
|||
|
||||
由于,ASCII 码可以表示的字符实在是太少了。后来,人们对其进行了扩展得到了 **ASCII 扩展字符集** 。ASCII 扩展字符集使用 8 位(bits)表示一个字符,所以,ASCII 扩展字符集可以定义 256(2^8)个字符。
|
||||
|
||||

|
||||

|
||||
|
||||
### GB2312
|
||||
|
||||
|
|
@ -75,11 +75,11 @@ BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
|
|||
|
||||
你可以通过这个网站在线进行编码和解码:https://www.haomeili.net/HanZi/ZiFuBianMaZhuanHuan
|
||||
|
||||

|
||||

|
||||
|
||||
这样我们就搞懂了乱码的本质: **编码和解码时用了不同或者不兼容的字符集** 。
|
||||
|
||||

|
||||

|
||||
|
||||
为了解决这个问题,人们就想:“如果我们能够有一种字符集将世界上所有的字符都纳入其中就好了!”。
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ UTF-32 的规则最简单,不过缺陷也比较明显,对于英文字母这
|
|||
|
||||
**UTF-8** 是目前使用最广的一种字符编码,。
|
||||
|
||||

|
||||

|
||||
|
||||
## MySQL 字符集
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ MySQL 支持很多种字符编码的方式,比如 UTF-8、GB2312、GBK、BIG5
|
|||
|
||||
你可以通过 `SHOW CHARSET` 命令来查看。
|
||||
|
||||

|
||||

|
||||
|
||||
通常情况下,我们建议使用 UTF-8 作为默认的字符编码方式。
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ MySQL 字符编码集中有两套 UTF-8 编码实现:
|
|||
|
||||
**为什么有两套 UTF-8 编码实现呢?** 原因如下:
|
||||
|
||||

|
||||

|
||||
|
||||
因此,如果你需要存储`emoji`类型的数据或者一些比较复杂的文字、繁体字到 MySQL 数据库的话,数据库的编码一定要指定为`utf8mb4` 而不是`utf8` ,要不然存储的时候就会报错了。
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ tag:
|
|||
|
||||
**Elasticsearch** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -50,6 +50,6 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ MongoDB 的存储结构区别于传统的关系型数据库,主要由如下三
|
|||
|
||||
MongoDB 中的记录就是一个 BSON 文档,它是由键值对组成的数据结构,类似于 JSON 对象,是 MongoDB 中的基本数据单元。字段的值可能包括其他文档、数组和文档数组。
|
||||
|
||||

|
||||

|
||||
|
||||
文档的键是字符串。除了少数例外情况,键可以使用任意 UTF-8 字符。
|
||||
|
||||
|
|
@ -56,13 +56,13 @@ MongoDB 中的记录就是一个 BSON 文档,它是由键值对组成的数据
|
|||
|
||||
> 与 JSON 相比,BSON 着眼于提高存储和扫描效率。BSON 文档中的大型元素以长度字段为前缀以便于扫描。在某些情况下,由于长度前缀和显式数组索引的存在,BSON 使用的空间会多于 JSON。
|
||||
|
||||

|
||||

|
||||
|
||||
#### 集合
|
||||
|
||||
MongoDB 集合存在于数据库中,**没有固定的结构**,也就是 **无模式** 的,这意味着可以往集合插入不同格式和类型的数据。不过,通常情况下,插入集合中的数据都会有一定的关联性。
|
||||
|
||||

|
||||

|
||||
|
||||
集合不需要事先创建,当第一个文档插入或者第一个索引创建时,如果该集合不存在,则会创建一个新的集合。
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ WiredTiger maintains a table's data in memory using a data structure called a B-
|
|||
|
||||
其整体结构如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
如果想要深入研究学习 WiredTiger 存储引擎,推荐阅读 MongoDB 中文社区的 [WiredTiger存储引擎系列](https://mongoing.com/archives/category/wiredtiger%e5%ad%98%e5%82%a8%e5%bc%95%e6%93%8e%e7%b3%bb%e5%88%97)。
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ MongoDB 聚合管道由多个阶段组成,每个阶段在文档通过管道时
|
|||
2. 对这些文档进行一系列运算
|
||||
3. 结果文档输出给下一个阶段
|
||||
|
||||

|
||||

|
||||
|
||||
**常用阶段操作符** :
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ tag:
|
|||
|
||||
复合索引中字段的顺序非常重要,例如下图中的复合索引由`{userid:1, score:-1}`组成,则该复合索引首先按照`userid`升序排序;然后再每个`userid`的值内,再按照`score`降序排序。
|
||||
|
||||

|
||||

|
||||
|
||||
在复合索引中,按照何种方式排序,决定了该索引在查询中是否能被应用到。
|
||||
|
||||
|
|
@ -137,13 +137,13 @@ MongoDB 的复制集群又称为副本集群,是一组维护相同数据集合
|
|||
|
||||
下图是一个典型的三成员副本集群:
|
||||
|
||||

|
||||

|
||||
|
||||
主节点与备节点之间是通过 **oplog(操作日志)** 来同步数据的。oplog 是 local 库下的一个特殊的 **上限集合(Capped Collection)** ,用来保存写操作所产生的增量日志,类似于 MySQL 中 的 Binlog。
|
||||
|
||||
> 上限集合类似于定长的循环队列,数据顺序追加到集合的尾部,当集合空间达到上限时,它会覆盖集合中最旧的文档。上限集合的数据将会被顺序写入到磁盘的固定空间内,所以,I/O 速度非常快,如果不建立索引,性能更好。
|
||||
|
||||

|
||||

|
||||
|
||||
当主节点上的一个写操作完成后,会向 oplog 集合写入一条对应的日志,而从节点则通过这个 oplog 不断拉取到新的日志,在本地进行回放以达到数据同步的目的。
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ MongoDB 的复制集群又称为副本集群,是一组维护相同数据集合
|
|||
|
||||
MongoDB 的分片集群由如下三个部分组成(下图来源于[官方文档对分片集群的介绍](https://www.mongodb.com/docs/manual/sharding/)):
|
||||
|
||||

|
||||

|
||||
|
||||
- **Config Servers**:配置服务器,本质上是一个 MongoDB 的副本集,负责存储集群的各种元数据和配置,如分片地址、Chunks 等
|
||||
- **Mongos**:路由服务,不存具体数据,从 Config 获取集群配置讲请求转发到特定的分片,并且整合分片结果返回给客户端。
|
||||
|
|
@ -209,7 +209,7 @@ MongoDB 支持两种分片算法来满足不同的查询需求(摘自[MongoDB
|
|||
|
||||
**1、基于范围的分片** :
|
||||
|
||||

|
||||

|
||||
|
||||
MongoDB 按照分片键(Shard Key)的值的范围将数据拆分为不同的块(Chunk),每个块包含了一段范围内的数据。当分片键的基数大、频率低且值非单调变更时,范围分片更高效。
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ MongoDB 按照分片键(Shard Key)的值的范围将数据拆分为不同的
|
|||
|
||||
**2、基于 Hash 值的分片**
|
||||
|
||||

|
||||

|
||||
|
||||
MongoDB 计算单个字段的哈希值作为索引值,并以哈希值的范围将数据拆分为不同的块(Chunk)。
|
||||
|
||||
|
|
@ -237,13 +237,13 @@ MongoDB 计算单个字段的哈希值作为索引值,并以哈希值的范围
|
|||
|
||||
默认情况下,一个 Chunk 的最大值默认为 64MB(可调整,取值范围为 1~1024 MB。如无特殊需求,建议保持默认值),进行数据插入、更新、删除时,如果此时 Mongos 感知到了目标 Chunk 的大小或者其中的数据量超过上限,则会触发 **Chunk 分裂**。
|
||||
|
||||

|
||||

|
||||
|
||||
数据的增长会让 Chunk 分裂得越来越多。这个时候,各个分片上的 Chunk 数量可能会不平衡。Mongos 中的 **均衡器(Balancer)** 组件就会执行自动平衡,尝试使各个 Shard 上 Chunk 的数量保持均衡,这个过程就是 **再平衡(Rebalance)**。默认情况下,数据库和集合的 Rebalance 是开启的。
|
||||
|
||||
如下图所示,随着数据插入,导致 Chunk 分裂,让 AB 两个分片有 3 个 Chunk,C 分片只有一个,这个时候就会把 B 分配的迁移一个到 C 分片实现集群数据均衡。
|
||||
|
||||

|
||||

|
||||
|
||||
> Balancer 是 MongoDB 的一个运行在 Config Server 的 Primary 节点上(自 MongoDB 3.4 版本起)的后台进程,它监控每个分片上 Chunk 数量,并在某个分片上 Chunk 数量达到阈值进行迁移。
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ tag:
|
|||
- **优化器:** 按照 MySQL 认为最优的方案去执行。
|
||||
- **执行器:** 执行语句,然后从存储引擎返回数据。 -
|
||||
|
||||

|
||||

|
||||
|
||||
简单来说 MySQL 主要分为 Server 层和存储引擎层:
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ CALL pre_test1();
|
|||
|
||||
1000 万条数据,我用了 33 分钟才跑完(实际时间跟你电脑硬件配置有关)。这里贴几条生成的数据,大致长这样。
|
||||
|
||||

|
||||

|
||||
|
||||
## SQL 测试
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ CALL pre_test1();
|
|||
|
||||
为什么 34 两条 SQL 效率相差那么大,但是同样做对比的 12 两条 SQL 却没什么差别呢?查看一下执行计划,下边分别 1234 条 SQL 的执行计划数据:
|
||||
|
||||

|
||||

|
||||
|
||||
可以看到,124 三条 SQL 都能使用到索引,连接类型都为`ref`,扫描行数都为 1,所以效率非常高。再看看第三条 SQL,没有用上索引,所以为全表扫描,`rows`直接到达 1000 万了,所以性能差别才那么大。
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ INSERT INTO `test1` (`id`, `num1`, `num2`, `type1`, `type2`, `str1`, `str2`) VAL
|
|||
|
||||
然后使用第三条 SQL 语句`SELECT * FROM`test1`WHERE num2 = 10000;`进行查询:
|
||||
|
||||

|
||||

|
||||
|
||||
从结果可以看到,后面插入的三条数据也都匹配上了。那么这个字符串隐式转换的规则是什么呢?为什么`num2='10000a'`、`'010000'`和`'10000'`这三种情形都能匹配上呢?查阅相关资料发现规则如下:
|
||||
|
||||
|
|
@ -140,13 +140,13 @@ INSERT INTO `test1` (`id`, `num1`, `num2`, `type1`, `type2`, `str1`, `str2`) VAL
|
|||
|
||||
现对以上规则做如下测试验证:
|
||||
|
||||

|
||||

|
||||
|
||||
如此也就印证了之前的查询结果了。
|
||||
|
||||
再次写一条 SQL 查询 str1 字段:`SELECT * FROM`test1`WHERE str1 = 1234;`
|
||||
|
||||

|
||||

|
||||
|
||||
## 分析和总结
|
||||
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ hash = hashfunc(key)
|
|||
index = hash % array_size
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
但是!哈希算法有个 **Hash 冲突** 问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 **链地址法**。链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 `HashMap` 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后`HashMap`为了减少链表过长的时候搜索时间过长引入了红黑树。
|
||||
|
||||

|
||||

|
||||
|
||||
为了减少 Hash 冲突的发生,一个好的哈希函数应该“均匀地”将数据分布在整个可能的哈希值集合中。
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ MySQL 8.x 中实现的索引新特性:
|
|||
|
||||
在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引且不允许存在 null 值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。
|
||||
|
||||

|
||||

|
||||
|
||||
## 二级索引(辅助索引)
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ PS: 不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
|
|||
|
||||
二级索引:
|
||||
|
||||

|
||||

|
||||
|
||||
## 聚簇索引与非聚簇索引
|
||||
|
||||
|
|
@ -184,11 +184,11 @@ PS: 不懂的同学可以暂存疑,慢慢往下看,后面会有答案的,
|
|||
|
||||
这是 MySQL 的表的文件截图:
|
||||
|
||||

|
||||

|
||||
|
||||
聚簇索引和非聚簇索引:
|
||||
|
||||

|
||||

|
||||
|
||||
#### 非聚簇索引一定回表查询吗(覆盖索引)?
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ SELECT id FROM table WHERE id=1;
|
|||
> 再如普通索引,如果一条 SQL 需要查询 name,name 字段正好有索引,
|
||||
> 那么直接根据这个索引就可以查到数据,也无需回表。
|
||||
|
||||

|
||||

|
||||
|
||||
### 联合索引
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ tag:
|
|||
|
||||
`MySQL` 日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志 `binlog`(归档日志)和事务日志 `redo log`(重做日志)和 `undo log`(回滚日志)。
|
||||
|
||||

|
||||

|
||||
|
||||
今天就来聊聊 `redo log`(重做日志)、`binlog`(归档日志)、两阶段提交、`undo log` (回滚日志)。
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ tag:
|
|||
|
||||
比如 `MySQL` 实例挂了或宕机了,重启时,`InnoDB`存储引擎会使用`redo log`恢复数据,保证数据的持久性与完整性。
|
||||
|
||||

|
||||

|
||||
|
||||
`MySQL` 中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 `Buffer Pool` 中。
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ tag:
|
|||
|
||||
然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(`redo log buffer`)里,接着刷盘到 `redo log` 文件里。
|
||||
|
||||

|
||||

|
||||
|
||||
> 图片笔误提示:第 4 步 “清空 redo log buffe 刷盘到 redo 日志中”这句话中的 buffe 应该是 buffer。
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ tag:
|
|||
|
||||
另外,`InnoDB` 存储引擎有一个后台线程,每隔`1` 秒,就会把 `redo log buffer` 中的内容写到文件系统缓存(`page cache`),然后调用 `fsync` 刷盘。
|
||||
|
||||

|
||||

|
||||
|
||||
也就是说,一个没有提交事务的 `redo log` 记录,也可能会刷盘。
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ tag:
|
|||
|
||||
因为在事务执行过程 `redo log` 记录是会写入`redo log buffer` 中,这些 `redo log` 记录会被后台线程刷盘。
|
||||
|
||||

|
||||

|
||||
|
||||
除了后台线程每秒`1`次的轮询操作,还有一种情况,当 `redo log buffer` 占用的空间即将达到 `innodb_log_buffer_size` 一半的时候,后台线程会主动刷盘。
|
||||
|
||||
|
|
@ -67,13 +67,13 @@ tag:
|
|||
|
||||
#### innodb_flush_log_at_trx_commit=0
|
||||
|
||||

|
||||

|
||||
|
||||
为`0`时,如果`MySQL`挂了或宕机可能会有`1`秒数据的丢失。
|
||||
|
||||
#### innodb_flush_log_at_trx_commit=1
|
||||
|
||||

|
||||

|
||||
|
||||
为`1`时, 只要事务提交成功,`redo log`记录就一定在硬盘里,不会有任何数据丢失。
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ tag:
|
|||
|
||||
#### innodb_flush_log_at_trx_commit=2
|
||||
|
||||

|
||||

|
||||
|
||||
为`2`时, 只要事务提交成功,`redo log buffer`中的内容只写入文件系统缓存(`page cache`)。
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ tag:
|
|||
|
||||
它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。
|
||||
|
||||

|
||||

|
||||
|
||||
在个**日志文件组**中还有两个重要的属性,分别是 `write pos、checkpoint`
|
||||
|
||||
|
|
@ -108,11 +108,11 @@ tag:
|
|||
|
||||
`write pos` 和 `checkpoint` 之间的还空着的部分可以用来写入新的 `redo log` 记录。
|
||||
|
||||

|
||||

|
||||
|
||||
如果 `write pos` 追上 `checkpoint` ,表示**日志文件组**满了,这时候不能再写入新的 `redo log` 记录,`MySQL` 得停下来,清空一些记录,把 `checkpoint` 推进一下。
|
||||
|
||||

|
||||

|
||||
|
||||
### redo log 小结
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ tag:
|
|||
|
||||
可以说`MySQL`数据库的**数据备份、主备、主主、主从**都离不开`binlog`,需要依靠`binlog`来同步数据,保证数据一致性。
|
||||
|
||||

|
||||

|
||||
|
||||
`binlog`会记录所有涉及更新数据的逻辑操作,并且是顺序写。
|
||||
|
||||
|
|
@ -167,13 +167,13 @@ tag:
|
|||
|
||||
指定`statement`,记录的内容是`SQL`语句原文,比如执行一条`update T set update_time=now() where id=1`,记录的内容如下。
|
||||
|
||||

|
||||

|
||||
|
||||
同步数据时,会执行记录的`SQL`语句,但是有个问题,`update_time=now()`这里会获取当前系统时间,直接执行会导致与原库的数据不一致。
|
||||
|
||||
为了解决这种问题,我们需要指定为`row`,记录的内容不再是简单的`SQL`语句了,还包含操作的具体数据,记录内容如下。
|
||||
|
||||

|
||||

|
||||
|
||||
`row`格式记录的内容看不到详细信息,要通过`mysqlbinlog`工具解析出来。
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ tag:
|
|||
|
||||
`binlog`日志刷盘流程如下
|
||||
|
||||

|
||||

|
||||
|
||||
- **上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快**
|
||||
- **上图的 fsync,才是将数据持久化到磁盘的操作**
|
||||
|
|
@ -206,7 +206,7 @@ tag:
|
|||
|
||||
为`0`的时候,表示每次提交事务都只`write`,由系统自行判断什么时候执行`fsync`。
|
||||
|
||||

|
||||

|
||||
|
||||
虽然性能得到提升,但是机器宕机,`page cache`里面的 binlog 会丢失。
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ tag:
|
|||
|
||||
最后还有一种折中方式,可以设置为`N(N>1)`,表示每次提交事务都`write`,但累积`N`个事务后才`fsync`。
|
||||
|
||||

|
||||

|
||||
|
||||
在出现`IO`瓶颈的场景里,将`sync_binlog`设置成一个比较大的值,可以提升性能。
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ tag:
|
|||
|
||||
在执行更新语句过程,会记录`redo log`与`binlog`两块日志,以基本的事务为单位,`redo log`在事务执行过程中可以不断写入,而`binlog`只有在提交事务时才写入,所以`redo log`与`binlog`的写入时机不一样。
|
||||
|
||||

|
||||

|
||||
|
||||
回到正题,`redo log`与`binlog`两份日志之间的逻辑不一致,会出现什么问题?
|
||||
|
||||
|
|
@ -238,25 +238,25 @@ tag:
|
|||
|
||||
假设执行过程中写完`redo log`日志后,`binlog`日志写期间发生了异常,会出现什么情况呢?
|
||||
|
||||

|
||||

|
||||
|
||||
由于`binlog`没写完就异常,这时候`binlog`里面没有对应的修改记录。因此,之后用`binlog`日志恢复数据时,就会少这一次更新,恢复出来的这一行`c`值是`0`,而原库因为`redo log`日志恢复,这一行`c`值是`1`,最终数据不一致。
|
||||
|
||||

|
||||

|
||||
|
||||
为了解决两份日志之间的逻辑一致问题,`InnoDB`存储引擎使用**两阶段提交**方案。
|
||||
|
||||
原理很简单,将`redo log`的写入拆成了两个步骤`prepare`和`commit`,这就是**两阶段提交**。
|
||||
|
||||

|
||||

|
||||
|
||||
使用**两阶段提交**后,写入`binlog`时发生异常也不会有影响,因为`MySQL`根据`redo log`日志恢复数据时,发现`redo log`还处于`prepare`阶段,并且没有对应`binlog`日志,就会回滚该事务。
|
||||
|
||||

|
||||

|
||||
|
||||
再看一个场景,`redo log`设置`commit`阶段发生异常,那会不会回滚事务呢?
|
||||
|
||||

|
||||

|
||||
|
||||
并不会回滚事务,它会执行上图框住的逻辑,虽然`redo log`是处于`prepare`阶段,但是能通过事务`id`找到对应的`binlog`日志,所以`MySQL`认为是完整的,就会提交事务恢复数据。
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ head:
|
|||
|
||||
关系型数据库中,我们的数据都被存放在了各种表中(比如用户表),表中的每一行就存放着一条数据(比如一个用户的信息)。
|
||||
|
||||

|
||||

|
||||
|
||||
大部分关系型数据库都使用 SQL 来操作数据库中的数据。并且,大部分关系型数据库都支持事务的四大特性(ACID)。
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ SQL 可以帮助我们:
|
|||
|
||||
### 什么是 MySQL?
|
||||
|
||||

|
||||

|
||||
|
||||
**MySQL 是一种关系型数据库,主要用于持久化存储我们的系统中的一些数据比如用户信息。**
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ MySQL 主要具有下面这些优点:
|
|||
|
||||
下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到客户端的一条 SQL 语句在 MySQL 内部是如何执行的。
|
||||
|
||||

|
||||

|
||||
|
||||
从上图可以看出, MySQL 主要由下面几部分构成:
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ MySQL 核心在于存储引擎,想要深入学习 MySQL,必定要深入研
|
|||
|
||||
MySQL 支持多种存储引擎,你可以通过 `show engines` 命令来查看 MySQL 支持的所有存储引擎。
|
||||
|
||||

|
||||

|
||||
|
||||
从上图我们可以查看出, MySQL 当前默认的存储引擎是 InnoDB。并且,所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。
|
||||
|
||||
|
|
@ -115,18 +115,18 @@ MySQL 5.5.5 之前,MyISAM 是 MySQL 的默认存储引擎。5.5.5 版本之后
|
|||
|
||||
你也可以通过 `show variables like '%storage_engine%'` 命令直接查看 MySQL 当前默认的存储引擎。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你只想查看数据库中某个表使用的存储引擎的话,可以使用 `show table status from db_name where name='table_name'`命令。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你想要深入了解每个存储引擎以及它们之间的区别,推荐你去阅读以下 MySQL 官方文档对应的介绍(面试不会问这么细,了解即可):
|
||||
|
||||
- InnoDB 存储引擎详细介绍:https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html 。
|
||||
- 其他存储引擎详细介绍:https://dev.mysql.com/doc/refman/8.0/en/storage-engines.html 。
|
||||
|
||||

|
||||

|
||||
|
||||
### MySQL 存储引擎架构了解吗?
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ MyISAM 不支持,而 InnoDB 支持。
|
|||
|
||||
阿里的《Java 开发手册》也是明确规定禁止使用外键的。
|
||||
|
||||

|
||||

|
||||
|
||||
不过,在代码中进行约束的话,对程序员的能力要求更高,具体是否要采用外键还是要根据你的项目实际情况而定。
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM,索
|
|||
|
||||
InnoDB 的性能比 MyISAM 更强大,不管是在读写混合模式下还是只读模式下,随着 CPU 核数的增加,InnoDB 的读写能力呈线性增长。MyISAM 因为读写不能并发,它的处理能力跟核数没关系。
|
||||
|
||||

|
||||

|
||||
|
||||
**总结** :
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ InnoDB 的性能比 MyISAM 更强大,不管是在读写混合模式下还是
|
|||
|
||||
最后,再分享一张图片给你,这张图片详细对比了常见的几种 MySQL 存储引擎。
|
||||
|
||||

|
||||

|
||||
|
||||
### MyISAM 和 InnoDB 如何选择?
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ select sql_no_cache count(*) from usr;
|
|||
|
||||
上诉问题的答案可以在[《Java 面试指北》(付费)](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) 的 **「技术面试题篇」** 中找到。
|
||||
|
||||

|
||||

|
||||
|
||||
## MySQL 事务
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ select sql_no_cache count(*) from usr;
|
|||
|
||||
事务会把这两个操作就可以看成逻辑上的一个整体,这个整体包含的操作要么都成功,要么都要失败。这样就不会出现小明余额减少而小红的余额却并没有增加的情况。
|
||||
|
||||

|
||||

|
||||
|
||||
### 何谓数据库事务?
|
||||
|
||||
|
|
@ -320,11 +320,11 @@ SQL1,SQL2...
|
|||
COMMIT;
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
另外,关系型数据库(例如:`MySQL`、`SQL Server`、`Oracle` 等)事务都有 **ACID** 特性:
|
||||
|
||||

|
||||

|
||||
|
||||
1. **原子性**(`Atomicity`) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
|
||||
2. **一致性**(`Consistency`): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
|
||||
|
|
@ -333,7 +333,7 @@ COMMIT;
|
|||
|
||||
🌈 这里要额外补充一点:**只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!** 想必大家也和我一样,被 ACID 这个概念被误导了很久! 我也是看周志明老师的公开课[《周志明的软件架构课》](https://time.geekbang.org/opencourse/intro/100064201)才搞清楚的(多看好书!!!)。
|
||||
|
||||

|
||||

|
||||
|
||||
另外,DDIA 也就是 [《Designing Data-Intensive Application(数据密集型应用系统设计)》](https://book.douban.com/subject/30329536/) 的作者在他的这本书中如是说:
|
||||
|
||||
|
|
@ -346,7 +346,7 @@ COMMIT;
|
|||
|
||||
《Designing Data-Intensive Application(数据密集型应用系统设计)》这本书强推一波,值得读很多遍!豆瓣有接近 90% 的人看了这本书之后给了五星好评。另外,中文翻译版本已经在 Github 开源,地址:[https://github.com/Vonng/ddia](https://github.com/Vonng/ddia) 。
|
||||
|
||||

|
||||

|
||||
|
||||
### 并发事务带来了哪些问题?
|
||||
|
||||
|
|
@ -535,7 +535,7 @@ SELECT ... FOR UPDATE;
|
|||
|
||||
《MySQL 技术内幕 InnoDB 存储引擎》这本书对应的描述应该是笔误了。
|
||||
|
||||

|
||||

|
||||
|
||||
### 当前读和快照读有什么区别?
|
||||
|
||||
|
|
@ -615,7 +615,7 @@ CREATE TABLE `sequence_id` (
|
|||
|
||||
可以选择使用云服务厂商提供的开箱即用的文件存储服务,成熟稳定,价格也比较低。
|
||||
|
||||

|
||||

|
||||
|
||||
也可以选择自建文件存储服务,实现起来也不难,基于 FastDFS、MinIO(推荐) 等开源项目就可以实现分布式文件服务。
|
||||
|
||||
|
|
@ -638,7 +638,7 @@ MySQL 提供了两个方法来处理 ip 地址
|
|||
|
||||
[《Java 面试指北》(付费)](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) 的 **「技术面试题篇」** 有一篇文章详细介绍了常见的 SQL 优化手段,非常全面,清晰易懂!
|
||||
|
||||

|
||||

|
||||
|
||||
### 如何分析 SQL 的性能?
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTE
|
|||
|
||||
#### 演示幻读出现的情况
|
||||
|
||||

|
||||

|
||||
|
||||
SQL 脚本 1 在第一次查询工资为 500 的记录时只有一条,SQL 脚本 2 插入了一条工资为 500 的记录,提交之后;SQL 脚本 1 在同一个事务中再次使用当前读查询发现出现了两条工资为 500 的记录这种就是幻读。
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ NoSQL(Not Only SQL 的缩写)泛指非关系型的数据库,主要针对
|
|||
|
||||
NoSQL 数据库代表:HBase 、Cassandra、MongoDB、Redis。
|
||||
|
||||

|
||||

|
||||
|
||||
## SQL 和 NoSQL 有什么区别?
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ NoSQL 数据库主要可以分为下面四种类型:
|
|||
|
||||
下面这张图片来源于 [微软的官方文档 | 关系数据与 NoSQL 数据](https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/relational-vs-nosql-data)。
|
||||
|
||||

|
||||

|
||||
|
||||
## 参考
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Cache Aside Pattern 中服务端需要同时维系 db 和 cache,并且是以 d
|
|||
|
||||
简单画了一张图帮助大家理解写的步骤。
|
||||
|
||||

|
||||

|
||||
|
||||
**读** :
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ Cache Aside Pattern 中服务端需要同时维系 db 和 cache,并且是以 d
|
|||
|
||||
简单画了一张图帮助大家理解读的步骤。
|
||||
|
||||

|
||||

|
||||
|
||||
你仅仅了解了上面这些内容的话是远远不够的,我们还要搞懂其中的原理。
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从
|
|||
|
||||
简单画了一张图帮助大家理解写的步骤。
|
||||
|
||||

|
||||

|
||||
|
||||
**读(Read Through):**
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从
|
|||
|
||||
简单画了一张图帮助大家理解读的步骤。
|
||||
|
||||

|
||||

|
||||
|
||||
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ tag:
|
|||
|
||||
**缓存基础** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -49,6 +49,6 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -7,12 +7,12 @@ tag:
|
|||
|
||||
**Redis 集群** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -50,6 +50,6 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -31,7 +31,7 @@ Redis 3.2 之前,List 底层实现是 LinkedList 或者 ZipList。 Redis 3.2
|
|||
|
||||
未来随着 Redis 新版本的发布,可能会有新的数据结构出现,通过查阅 Redis 官网对应的介绍,你总能获取到最靠谱的信息。
|
||||
|
||||

|
||||

|
||||
|
||||
## String(字符串)
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ String 是 Redis 中最简单同时也是最常用的一个数据结构。
|
|||
|
||||
String 是一种二进制安全的数据结构,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的 base64 编码或者解码或者图片的路径)、序列化后的对象。
|
||||
|
||||

|
||||

|
||||
|
||||
虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 **简单动态字符串**(Simple Dynamic String,**SDS**)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ Redis 中的 List 其实就是链表数据结构的实现。我在 [线性数据
|
|||
|
||||
许多高级编程语言都内置了链表的实现比如 Java 中的 `LinkedList`,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 List 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ Redis 中的 List 其实就是链表数据结构的实现。我在 [线性数据
|
|||
|
||||
我专门画了一个图方便大家理解 `RPUSH` , `LPOP` , `lpush` , `RPOP` 命令:
|
||||
|
||||

|
||||

|
||||
|
||||
**通过 `LRANGE` 查看对应下标范围的列表元素** :
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ Redis 中的 Hash 是一个 String 类型的 field-value(键值对) 的映
|
|||
|
||||
Hash 类似于 JDK1.8 前的 `HashMap`,内部实现也差不多(数组 + 链表)。不过,Redis 的 Hash 做了更多优化。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺
|
|||
|
||||
你可以基于 Set 轻易实现交集、并集、差集的操作,比如你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。这样的话,Set 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -363,14 +363,14 @@ Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺
|
|||
- 举例:网站 UV 统计(数据量巨大的场景还是 `HyperLogLog`更适合一些)、文章点赞、动态点赞等场景。
|
||||
- 相关命令:`SCARD`(获取集合数量) 。
|
||||
|
||||

|
||||

|
||||
|
||||
**需要获取多个数据源交集、并集和差集的场景**
|
||||
|
||||
- 举例 :共同好友(交集)、共同粉丝(交集)、共同关注(交集)、好友推荐(差集)、音乐推荐(差集) 、订阅号推荐(差集+交集) 等场景。
|
||||
- 相关命令:`SINTER`(交集)、`SINTERSTORE` (交集)、`SUNION` (并集)、`SUNIONSTORE`(并集)、`SDIFF`(差集)、`SDIFFSTORE` (差集)。
|
||||
|
||||

|
||||

|
||||
|
||||
**需要随机获取数据源中的元素的场景**
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺
|
|||
|
||||
Sorted Set 类似于 Set,但和 Set 相比,Sorted Set 增加了一个权重参数 `score`,使得集合中的元素能够按 `score` 进行有序排列,还可以通过 `score` 的范围来获取元素的列表。有点像是 Java 中 `HashMap` 和 `TreeSet` 的结合体。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -472,11 +472,11 @@ value1
|
|||
- 举例 :各种排行榜比如直播间送礼物的排行榜、朋友圈的微信步数排行榜、王者荣耀中的段位排行榜、话题热度排行榜等等。
|
||||
- 相关命令 :`ZRANGE` (从小到大排序) 、 `ZREVRANGE` (从大到小排序)、`ZREVRANK` (指定元素排名)。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) 的「技术面试题篇」就有一篇文章详细介绍如何使用 Sorted Set 来设计制作一个排行榜。
|
||||
|
||||

|
||||

|
||||
|
||||
**需要存储的数据有优先级或者重要程度的场景** 比如优先级任务队列。
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
|
|||
|
||||
你可以将 Bitmap 看作是一个存储二进制数字(0 和 1)的数组,数组中每个元素的下标叫做 offset(偏移量)。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -72,11 +72,11 @@ Redis 提供的 HyperLogLog 占用空间非常非常小,只需要 12k 的空
|
|||
|
||||
Redis 官方文档中有对应的详细说明:
|
||||
|
||||

|
||||

|
||||
|
||||
基数计数概率算法为了节省内存并不会直接存储元数据,而是通过一定的概率统计方法预估基数值(集合中包含元素的个数)。因此, HyperLogLog 的计数结果并不是一个精确值,存在一定的误差(标准误差为 `0.81%` 。)。
|
||||
|
||||

|
||||

|
||||
|
||||
HyperLogLog 的使用非常简单,但原理非常复杂。HyperLogLog 的原理以及在 Redis 中的实现可以看这篇文章:[HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的](https://juejin.cn/post/6844903785744056333) 。
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理
|
|||
|
||||
通过 GEO 我们可以轻松实现两个位置距离的计算、获取指定位置附近的元素等功能。
|
||||
|
||||

|
||||

|
||||
|
||||
### 常用命令
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理
|
|||
|
||||
GEO 中存储的地理位置信息的经纬度数据通过 GeoHash 算法转换成了一个整数,这个整数作为 Sorted Set 的 score(权重参数)使用。
|
||||
|
||||

|
||||

|
||||
|
||||
**获取指定位置范围内的其他元素** :
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ tag:
|
|||
|
||||
举个例子:操作系统为你分配了 32 字节的连续内存空间,而你存储数据实际只需要使用 24 字节内存空间,那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数据的话,就可以被称为内存碎片。
|
||||
|
||||

|
||||

|
||||
|
||||
Redis 内存碎片虽然不会影响 Redis 性能,但是会增加内存消耗。
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ void *zmalloc(size_t size) {
|
|||
|
||||
另外,Redis 可以使用多种内存分配器来分配内存( libc、jemalloc、tcmalloc),默认使用 [jemalloc](https://github.com/jemalloc/jemalloc),而 jemalloc 按照一系列固定的大小(8 字节、16 字节、32 字节......)来分配内存的。jemalloc 划分的内存单元如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
当程序申请的内存最接近某个固定值时,jemalloc 会给它分配相应大小的空间,就比如说程序需要申请 17 字节的内存,jemalloc 会直接给它分配 32 字节的内存,这样会导致有 15 字节内存的浪费。不过,jemalloc 专门针对内存碎片问题做了优化,一般不会存在过度碎片化的问题。
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ void *zmalloc(size_t size) {
|
|||
|
||||
这个在 Redis 官方文档中也有对应的原话:
|
||||
|
||||

|
||||

|
||||
|
||||
文档地址:https://redis.io/topics/memory-optimization 。
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ void *zmalloc(size_t size) {
|
|||
|
||||
使用 `info memory` 命令即可查看 Redis 内存相关的信息。下图中每个参数具体的含义,Redis 官方文档有详细的介绍:https://redis.io/commands/INFO 。
|
||||
|
||||

|
||||

|
||||
|
||||
Redis 内存碎片率的计算公式:`mem_fragmentation_ratio` (内存碎片率)= `used_memory_rss` (操作系统实际分配给 Redis 的物理内存空间大小)/ `used_memory`(Redis 内存分配器为了存储数据实际申请使用的内存空间大小)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Redis 没有外部依赖,Linux 和 OS X 是 Redis 开发和测试最多的两
|
|||
|
||||
个人学习的话,你可以自己本机安装 Redis 或者通过 Redis 官网提供的[在线 Redis 环境](https://try.redis.io/)来实际体验 Redis。
|
||||
|
||||

|
||||

|
||||
|
||||
全世界有非常多的网站使用到了 Redis ,[techstacks.io](https://techstacks.io/) 专门维护了一个[使用 Redis 的热门站点列表](https://techstacks.io/tech/redis) ,感兴趣的话可以看看。
|
||||
|
||||
|
|
@ -246,11 +246,11 @@ Redis 中有一个叫做 `sorted set` 的数据结构经常被用在各种排行
|
|||
|
||||
相关的一些 Redis 命令: `ZRANGE` (从小到大排序) 、 `ZREVRANGE` (从大到小排序)、`ZREVRANK` (指定元素排名)。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) 的「技术面试题篇」就有一篇文章详细介绍如何使用 Sorted Set 来设计制作一个排行榜。
|
||||
|
||||

|
||||

|
||||
|
||||
### 使用 Set 实现抽奖系统需要用到什么命令?
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ Redis 通过 **IO 多路复用程序** 来监听来自客户端的大量连接
|
|||
- 文件事件分派器(将 socket 关联到相应的事件处理器)
|
||||
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
|
||||
|
||||

|
||||

|
||||
|
||||
相关阅读:[Redis 事件机制详解](http://remcarpediem.net/article/1aa2da89/) 。
|
||||
|
||||
|
|
@ -346,7 +346,7 @@ Redis 通过 **IO 多路复用程序** 来监听来自客户端的大量连接
|
|||
|
||||
为此,Redis 4.0 之后新增了`UNLINK`(可以看作是 `DEL` 的异步版本)、`FLUSHALL ASYNC`(清空所有数据库的所有 key,不仅仅是当前 `SELECT` 的数据库)、`FLUSHDB ASYNC`(清空当前 `SELECT` 数据库中的所有 key)等异步命令。
|
||||
|
||||

|
||||

|
||||
|
||||
大体上来说,Redis 6.0 之前主要还是单线程处理。
|
||||
|
||||
|
|
@ -416,7 +416,7 @@ OK
|
|||
|
||||
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
|
||||
|
||||

|
||||

|
||||
|
||||
过期字典是存储在 redisDb 这个结构里的:
|
||||
|
||||
|
|
@ -568,7 +568,7 @@ Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使
|
|||
|
||||
官方文档地址:https://redis.io/topics/persistence
|
||||
|
||||

|
||||

|
||||
|
||||
## 参考
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ QUEUED
|
|||
|
||||
Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io/topics/transactions) 如下:
|
||||
|
||||

|
||||

|
||||
|
||||
### Redis 事务支持原子性吗?
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ Redis 事务在运行错误的情况下,除了执行过程中出现错误的
|
|||
|
||||
Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚,这样更简单便捷并且性能更好。Redis 开发者觉得即使命令执行错误也应该在开发过程中就被发现而不是生产过程中。
|
||||
|
||||

|
||||

|
||||
|
||||
你可以将 Redis 中的事务就理解为 :**Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。**
|
||||
|
||||
|
|
@ -294,7 +294,7 @@ Lua 脚本同样支持批量操作多条命令。一段 Lua 脚本可以视作
|
|||
|
||||
缓存穿透说简单点就是大量请求的 key 是不合理的,**根本不存在于缓存中,也不存在于数据库中** 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
|
||||
|
||||

|
||||

|
||||
|
||||
举个例子:某个黑客故意制造一些非法的 key 发起大量请求,导致大量请求落到数据库,结果数据库上也没有查到对应的数据。也就是说这些请求最终都落到了数据库上,对数据库造成了巨大的压力。
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ public Object getObjectInclNullById(Integer id) {
|
|||
|
||||
加入布隆过滤器之后的缓存处理流程图如下。
|
||||
|
||||

|
||||

|
||||
|
||||
但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: **布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。**
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理
|
|||
|
||||
缓存击穿中,请求的 key 对应的是 **热点数据** ,该数据 **存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)** 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
|
||||
|
||||

|
||||

|
||||
|
||||
举个例子 :秒杀进行过程中,缓存中的某个秒杀商品的数据突然过期,这就导致瞬时大量对该商品的请求直接落到数据库上,对数据库造成了巨大的压力。
|
||||
|
||||
|
|
@ -391,7 +391,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理
|
|||
|
||||
另外,缓存服务宕机也会导致缓存雪崩现象,导致所有的请求都落到了数据库上。
|
||||
|
||||

|
||||

|
||||
|
||||
举个例子 :数据库中的大量数据在同一时间过期,这个时候突然有大量的请求需要访问这些过期的数据。这就导致大量的请求直接落到数据库上,对数据库造成了巨大的压力。
|
||||
|
||||
|
|
|
|||
|
|
@ -1239,7 +1239,7 @@ SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不
|
|||
|
||||
下图展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法。
|
||||
|
||||

|
||||

|
||||
|
||||
如果不加任何修饰词,只写 `JOIN`,那么默认为 `INNER JOIN`
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ icon: "gateway"
|
|||
|
||||
微服务背景下,一个系统被拆分为多个服务,但是像安全认证,流量控制,日志,监控等功能是每个服务都需要的,没有网关的话,我们就需要在每个服务中单独实现,这使得我们做了很多重复的事情并且没有一个全局的视图来统一管理这些功能。
|
||||
|
||||

|
||||

|
||||
|
||||
一般情况下,网关可以为我们提供请求转发、安全认证(身份/权限认证)、流量控制、负载均衡、降级熔断、日志、监控、参数校验、协议转换等功能。
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ icon: "gateway"
|
|||
|
||||
如下图所示,网关服务外层通过 Nginx(其他负载均衡设备/软件也行) 进⾏负载转发以达到⾼可⽤。Nginx 在部署的时候,尽量也要考虑高可用,避免单点风险。
|
||||
|
||||

|
||||

|
||||
|
||||
## 网关能提供哪些功能?
|
||||
|
||||
|
|
@ -51,11 +51,11 @@ Zuul 是 Netflix 开发的一款提供动态路由、监控、弹性、安全的
|
|||
|
||||
Zuul 核心架构如下:
|
||||
|
||||

|
||||

|
||||
|
||||
Zuul 主要通过过滤器(类似于 AOP)来过滤请求,从而实现网关必备的各种功能。
|
||||
|
||||

|
||||

|
||||
|
||||
我们可以自定义过滤器来处理请求,并且,Zuul 生态本身就有很多现成的过滤器供我们使用。就比如限流可以直接用国外朋友写的 [spring-cloud-zuul-ratelimit](https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit) (这里只是举例说明,一般是配合 hystrix 来做限流):
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ SpringCloud Gateway 属于 Spring Cloud 生态系统中的网关,其诞生的
|
|||
|
||||
为了提升网关的性能,SpringCloud Gateway 基于 Spring WebFlux 。Spring WebFlux 使用 Reactor 库来实现响应式编程模型,底层基于 Netty 实现同步非阻塞的 I/O。
|
||||
|
||||

|
||||

|
||||
|
||||
Spring Cloud Gateway 不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,限流。
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ Kong 是一款基于 [OpenResty](https://github.com/openresty/) (Nginx + Lua
|
|||
|
||||
> OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
|
||||
|
||||

|
||||

|
||||
|
||||
Kong 提供了插件机制来扩展其功能,插件在 API 请求响应循环的生命周期中被执行。比如在服务上启用 Zipkin 插件:
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ $ curl -X POST http://kong:8001/services/{service}/plugins \
|
|||
|
||||
> Kong 本身就是一个 Lua 应用程序,并且是在 Openresty 的基础之上做了一层封装的应用。归根结底就是利用 Lua 嵌入 Nginx 的方式,赋予了 Nginx 可编程的能力,这样以插件的形式在 Nginx 这一层能够做到无限想象的事情。例如限流、安全访问策略、路由、负载均衡等等。编写一个 Kong 插件,就是按照 Kong 插件编写规范,写一个自己自定义的 Lua 脚本,然后加载到 Kong 中,最后引用即可。
|
||||
|
||||

|
||||

|
||||
|
||||
- Github 地址: https://github.com/Kong/kong
|
||||
- 官网地址 : https://konghq.com/kong
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@ icon: "configuration"
|
|||
|
||||
|
||||
|
||||

|
||||

|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ icon: "id"
|
|||
|
||||
这个时候就需要生成**分布式 ID**了。
|
||||
|
||||

|
||||

|
||||
|
||||
### 分布式 ID 需要满足哪些要求?
|
||||
|
||||

|
||||

|
||||
|
||||
分布式 ID 作为分布式系统中必不可少的一环,很多地方都要用到分布式 ID。
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ icon: "id"
|
|||
|
||||
这种方式就比较简单直白了,就是通过关系型数据库的自增主键产生来唯一的 ID。
|
||||
|
||||

|
||||

|
||||
|
||||
以 MySQL 举例,我们通过下面的方式即可。
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ CREATE TABLE `sequence_id_generator` (
|
|||
|
||||
`current_max_id` 字段和`step`字段主要用于获取批量 ID,获取的批量 id 为: `current_max_id ~ current_max_id+step`。
|
||||
|
||||

|
||||

|
||||
|
||||
`version` 字段主要用于解决并发问题(乐观锁),`biz_type` 主要用于表示业务类型。
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ id current_max_id step version biz_type
|
|||
|
||||
#### NoSQL
|
||||
|
||||

|
||||

|
||||
|
||||
一般情况下,NoSQL 方案使用 Redis 多一些。我们通过 Redis 的 `incr` 命令即可实现对 id 原子顺序递增。
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ OK
|
|||
|
||||
除了 Redis 之外,MongoDB ObjectId 经常也会被拿来当做分布式 ID 的解决方案。
|
||||
|
||||

|
||||

|
||||
|
||||
MongoDB ObjectId 一共需要 12 个字节存储:
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ UUID.randomUUID()
|
|||
|
||||
[RFC 4122](https://tools.ietf.org/html/rfc4122) 中关于 UUID 的示例是这样的:
|
||||
|
||||

|
||||

|
||||
|
||||
我们这里重点关注一下这个 Version(版本),不同的版本对应的 UUID 的生成规则是不同的。
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ UUID.randomUUID()
|
|||
|
||||
下面是 Version 1 版本下生成的 UUID 的示例:
|
||||
|
||||

|
||||

|
||||
|
||||
JDK 中通过 `UUID` 的 `randomUUID()` 方法生成的 UUID 的版本默认为 4。
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 由 64 bit
|
|||
- **第 42~52 位** :一共 10 位,一般来说,前 5 位表示机房 ID,后 5 位表示机器 ID(实际项目中可以根据实际情况调整)。这样就可以区分不同集群/机房的节点。
|
||||
- **第 53~64 位** :一共 12 位,用来表示序列号。 序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你想要使用 Snowflake 算法的话,一般不需要你自己再造轮子。有很多基于 Snowflake 算法的开源实现比如美团 的 Leaf、百度的 UidGenerator,并且这些开源实现对原有的 Snowflake 算法进行了优化。
|
||||
|
||||
|
|
@ -293,13 +293,13 @@ Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 由 64 bit
|
|||
|
||||
不过,UidGenerator 对 Snowflake(雪花算法)进行了改进,生成的唯一 ID 组成如下。
|
||||
|
||||

|
||||

|
||||
|
||||
可以看出,和原始 Snowflake(雪花算法)生成的唯一 ID 的组成不太一样。并且,上面这些参数我们都可以自定义。
|
||||
|
||||
UidGenerator 官方文档中的介绍如下:
|
||||
|
||||

|
||||

|
||||
|
||||
自 18 年后,UidGenerator 就基本没有再维护了,我这里也不过多介绍。想要进一步了解的朋友,可以看看 [UidGenerator 的官方介绍](https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md)。
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ OK
|
|||
|
||||
对于 Java 开发的小伙伴来说,已经有了现成的解决方案:**[Redisson](https://github.com/redisson/redisson)** 。其他语言的解决方案,可以在 Redis 官方文档中找到,地址:https://redis.io/topics/distlock 。
|
||||
|
||||

|
||||

|
||||
|
||||
Redisson 是一个开源的 Java 语言 Redis 客户端,提供了很多开箱即用的功能,不仅仅包括多种分布式锁的实现。并且,Redisson 还支持 Redis 单机、Redis Sentinel 、Redis Cluster 等多种部署架构。
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ icon: "transanction"
|
|||
|
||||
**分布式事务** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了《Java 面试指北》中。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ icon: "transanction"
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ icon: "transanction"
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ icon: "transanction"
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -48,6 +48,6 @@ icon: "transanction"
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -26,7 +26,7 @@ tag:
|
|||
5. 运行期流量调度。
|
||||
6. 可视化的服务治理与运维。
|
||||
|
||||

|
||||

|
||||
|
||||
简单来说就是: **Dubbo 不光可以帮助我们调用远程服务,还提供了一些其他开箱即用的功能比如智能负载均衡。**
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ Dubbo 目前已经有接近 34.4 k 的 Star 。
|
|||
|
||||
在 **2020 年度 OSC 中国开源项目** 评选活动中,Dubbo 位列开发框架和基础组件类项目的第7名。相比几年前来说,热度和排名有所下降。
|
||||
|
||||

|
||||

|
||||
|
||||
Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出现,才使得越来越多的公司开始使用以及接受分布式架构。
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出
|
|||
|
||||
分布式或者说 SOA 分布式重要的就是面向服务,说简单的分布式就是我们把整个系统拆分成不同的服务然后将这些服务放在不同的服务器上减轻单体服务的压力提高并发量和性能。比如电商系统可以简单地拆分成订单系统、商品系统、登录系统等等,拆分之后的每个服务可以部署在不同的机器上,如果某一个服务的访问量比较大的话也可以将这个服务同时部署在多台机器上。
|
||||
|
||||

|
||||

|
||||
|
||||
### 为什么要分布式?
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出
|
|||
|
||||
[官方文档中的框架设计章节](https://dubbo.apache.org/zh/docs/v2.7/dev/design/) 已经介绍的非常详细了,我这里把一些比较重要的点再提一下。
|
||||
|
||||

|
||||

|
||||
|
||||
上述节点简单介绍以及他们之间的关系:
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出
|
|||
|
||||
简单来说,`Invoker` 就是 Dubbo 对远程调用的抽象。
|
||||
|
||||

|
||||

|
||||
|
||||
按照 Dubbo 官方的话来说,`Invoker` 分为
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出
|
|||
|
||||
> 左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。
|
||||
|
||||

|
||||

|
||||
|
||||
- **config 配置层**:Dubbo相关的配置。支持代码配置,同时也支持基于 Spring 来做配置,以 `ServiceConfig`, `ReferenceConfig` 为中心
|
||||
- **proxy 服务代理层**:调用远程方法像调用本地的方法一样简单的一个关键,真实调用过程依赖代理类,以 `ServiceProxy` 为中心。
|
||||
|
|
@ -182,7 +182,7 @@ Dubbo 采用 微内核(Microkernel) + 插件(Plugin) 模式,简单来
|
|||
|
||||
微内核架构包含两类组件:**核心系统(core system)** 和 **插件模块(plug-in modules)**。
|
||||
|
||||

|
||||

|
||||
|
||||
核心系统提供系统所需核心能力,插件模块可以扩展系统的功能。因此, 基于微内核架构的系统,非常易于扩展功能。
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
|||
|
||||
`AbstractLoadBalance` 的实现类有下面这些:
|
||||
|
||||

|
||||

|
||||
|
||||
官方文档对负载均衡这部分的介绍非常详细,推荐小伙伴们看看,地址:[https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/#m-zhdocsv27devsourceloadbalance](https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/#m-zhdocsv27devsourceloadbalance ) 。
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
|||
|
||||
我们把这些权重值分布在坐标区间会得到:S1->[0, 7) ,S2->[7, 10)。我们生成[0, 10) 之间的随机数,随机数落到对应的区间,我们就选择对应的服务器来处理请求。
|
||||
|
||||

|
||||

|
||||
|
||||
`RandomLoadBalance` 的源码非常简单,简单花几分钟时间看一下。
|
||||
|
||||
|
|
@ -407,13 +407,13 @@ public class RpcStatus {
|
|||
|
||||
`ConsistentHashLoadBalance` 即**一致性Hash负载均衡策略**。 `ConsistentHashLoadBalance` 中没有权重的概念,具体是哪个服务提供者处理请求是由你的请求的参数决定的,也就是说相同参数的请求总是发到同一个服务提供者。
|
||||
|
||||

|
||||

|
||||
|
||||
另外,Dubbo 为了避免数据倾斜问题(节点不够分散,大量请求落到同一节点),还引入了虚拟节点的概念。通过虚拟节点可以让节点更加分散,有效均衡各个节点的请求量。
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
官方有详细的源码分析:[https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/#23-consistenthashloadbalance](https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/#23-consistenthashloadbalance) 。这里还有一个相关的 [PR#5440](https://github.com/apache/dubbo/pull/5440) 来修复老版本中 ConsistentHashLoadBalance 存在的一些Bug。感兴趣的小伙伴,可以多花点时间研究一下。我这里不多分析了,这个作业留给你们!
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ Dubbo 中的 `RoundRobinLoadBalance` 的代码实现被修改重建了好几次
|
|||
|
||||
### Dubbo 支持哪些序列化方式呢?
|
||||
|
||||

|
||||

|
||||
|
||||
Dubbo 支持多种序列化方式:JDK自带的序列化、hessian2、JSON、Kryo、FST、Protostuff,ProtoBuf等等。
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
|
||||
在定义了 socket 之后,我们就可以愉快的对这个 socket 进行操作,比如用`bind()`绑定 IP 端口,用`connect()`发起建连。
|
||||
|
||||

|
||||

|
||||
|
||||
在连接建立之后,我们就可以使用`send()`发送数据,`recv()`接收数据。
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
|
||||
八股文常背,TCP 是有三个特点,**面向连接**、**可靠**、基于**字节流**。
|
||||
|
||||

|
||||

|
||||
|
||||
这三个特点真的概括的 **非常精辟** ,这个八股文我们没白背。
|
||||
|
||||
|
|
@ -53,11 +53,11 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
|
||||
字节流可以理解为一个双向的通道里流淌的二进制数据,也就是 **01 串** 。纯裸 TCP 收发的这些 01 串之间是 **没有任何边界** 的,你根本不知道到哪个地方才算一条完整消息。
|
||||
|
||||

|
||||

|
||||
|
||||
正因为这个没有任何边界的特点,所以当我们选择使用 TCP 发送 **"夏洛"和"特烦恼"** 的时候,接收端收到的就是 **"夏洛特烦恼"** ,这时候接收端没发区分你是想要表达 **"夏洛"+"特烦恼"** 还是 **"夏洛特"+"烦恼"** 。
|
||||
|
||||

|
||||

|
||||
|
||||
这就是所谓的 **粘包问题**,之前也写过一篇专门的[文章](https://mp.weixin.qq.com/s/0-YBxU1cSbDdzcZEZjmQYA)聊过这个问题。
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
|
||||
于是我们会把每条要发送的数据都包装一下,比如加入 **消息头** ,消息头里写清楚一个完整的包长度是多少,根据这个长度可以继续接收数据,截取出来后它们就是我们真正要传输的 **消息体** 。
|
||||
|
||||

|
||||

|
||||
|
||||
而这里头提到的 **消息头** ,还可以放各种东西,比如消息体是否被压缩过和消息体格式之类的,只要上下游都约定好了,互相都认就可以了,这就是所谓的 **协议。**
|
||||
|
||||
|
|
@ -79,13 +79,13 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
|
||||
我们回过头来看网络的分层图。
|
||||
|
||||

|
||||

|
||||
|
||||
**TCP 是传输层的协议** ,而基于 TCP 造出来的 HTTP 和各类 RPC 协议,它们都只是定义了不同消息格式的 **应用层协议** 而已。
|
||||
|
||||
**HTTP**(**H**yper **T**ext **T**ransfer **P**rotocol)协议又叫做 **超文本传输协议** 。我们用的比较多,平时上网在浏览器上敲个网址就能访问网页,这里用到的就是 HTTP 协议。
|
||||
|
||||

|
||||

|
||||
|
||||
而 **RPC**(**R**emote **P**rocedure **C**all)又叫做 **远程过程调用**,它本身并不是一个具体的协议,而是一种 **调用方式** 。
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ fd = socket(AF_INET,SOCK_STREAM,0);
|
|||
res = remoteFunc(req)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
基于这个思路,大佬们造出了非常多款式的 RPC 协议,比如比较有名的`gRPC`,`thrift`。
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ res = remoteFunc(req)
|
|||
|
||||
而 **RPC** 协议,也跟 HTTP 类似,也是通过建立 TCP 长链接进行数据交互,但不同的地方在于,RPC 协议一般还会再建个 **连接池**,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用,可以说非常环保。
|
||||
|
||||

|
||||

|
||||
|
||||
由于连接池有利于提升网络请求性能,所以不少编程语言的网络库里都会给 HTTP 加个连接池,比如 Go 就是这么干的。
|
||||
|
||||
|
|
@ -161,21 +161,21 @@ res = remoteFunc(req)
|
|||
|
||||
这个将结构体转为二进制数组的过程就叫 **序列化** ,反过来将二进制数组复原成结构体的过程叫 **反序列化**。
|
||||
|
||||

|
||||

|
||||
|
||||
对于主流的 HTTP1.1,虽然它现在叫超文本协议,支持音频视频,但 HTTP 设计 初是用于做网页文本展示的,所以它传的内容以字符串为主。Header 和 Body 都是如此。在 Body 这块,它使用 **JSON** 来 **序列化** 结构体数据。
|
||||
|
||||
我们可以随便截个图直观看下。
|
||||
|
||||

|
||||

|
||||
|
||||
可以看到这里面的内容非常多的冗余,显得非常啰嗦。最明显的,像 Header 里的那些信息,其实如果我们约定好头部的第几位是 `Content-Type`,就不需要每次都真的把 `Content-Type` 这个字段都传过来,类似的情况其实在 Body 的 JSON 结构里也特别明显。
|
||||
|
||||
而 RPC,因为它定制化程度更高,可以采用体积更小的 Protobuf 或其他序列化协议去保存结构体数据,同时也不需要像 HTTP 那样考虑各种浏览器行为,比如 302 重定向跳转啥的。**因此性能也会更好一些,这也是在公司内部微服务中抛弃 HTTP,选择使用 RPC 的最主要原因。**
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
当然上面说的 HTTP,其实 **特指的是现在主流使用的 HTTP1.1**,`HTTP2`在前者的基础上做了很多改进,所以 **性能可能比很多 RPC 协议还要好**,甚至连`gRPC`底层都直接用的`HTTP2`。
|
||||
|
||||
|
|
|
|||
|
|
@ -57,14 +57,14 @@ tag:
|
|||
|
||||
### Dubbo
|
||||
|
||||

|
||||

|
||||
|
||||
Apache Dubbo 是一款微服务框架,为大规模微服务实践提供高性能 RPC 通信、流量治理、可观测性等解决方案,
|
||||
涵盖 Java、Golang 等多种语言 SDK 实现。
|
||||
|
||||
Dubbo 提供了从服务定义、服务发现、服务通信到流量管控等几乎所有的服务治理能力,支持 Triple 协议(基于 HTTP/2 之上定义的下一代 RPC 通信协议)、应用级服务发现、Dubbo Mesh (Dubbo3 赋予了很多云原生友好的新特性)等特性。
|
||||
|
||||

|
||||

|
||||
|
||||
Dubbo 是由阿里开源,后来加入了 Apache 。正是由于 Dubbo 的出现,才使得越来越多的公司开始使用以及接受分布式架构。
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ gRPC 是 Google 开源的一个高性能、通用的开源 RPC 框架。其由
|
|||
|
||||
**何谓 ProtoBuf?** [ProtoBuf( Protocol Buffer)](https://github.com/protocolbuffers/protobuf) 是一种更加灵活、高效的数据格式,可用于通讯协议、数据存储等领域,基本支持所有主流编程语言且与平台无关。不过,通过 ProtoBuf 定义接口和数据类型还挺繁琐的,这是一个小问题。
|
||||
|
||||

|
||||

|
||||
|
||||
不得不说,gRPC 的通信层的设计还是非常优秀的,[Dubbo-go 3.0](https://dubbogo.github.io/) 的通信层改进主要借鉴了 gRPC。
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ Dubbo 也是 Spring Cloud Alibaba 里面的一个组件。
|
|||
|
||||
**内容概览** :
|
||||
|
||||

|
||||

|
||||
|
||||
## 既然有了 HTTP 协议,为什么还要有 RPC ?
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ tag:
|
|||
|
||||
**CAP** 也就是 **Consistency(一致性)**、**Availability(可用性)**、**Partition Tolerance(分区容错性)** 这三个单词首字母组合。
|
||||
|
||||

|
||||

|
||||
|
||||
CAP 理论的提出者布鲁尔在提出 CAP 猜想的时候,并没有详细定义 **Consistency**、**Availability**、**Partition Tolerance** 三个单词的明确定义。
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ CAP 理论的提出者布鲁尔在提出 CAP 猜想的时候,并没有详细
|
|||
|
||||
分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络就分成了几块区域,这就叫 **网络分区**。
|
||||
|
||||

|
||||

|
||||
|
||||
### 不是所谓的“3 选 2”
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ CAP 理论的提出者布鲁尔在提出 CAP 猜想的时候,并没有详细
|
|||
|
||||
注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
|
||||
|
||||

|
||||

|
||||
|
||||
常见的可以作为注册中心的组件有:ZooKeeper、Eureka、Nacos...。
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ Gossip 设计了两种可能的消息传播模式:**反熵(Anti-Entropy)**
|
|||
|
||||
伪代码如下:
|
||||
|
||||

|
||||

|
||||
|
||||
谣言传播比较适合节点数量比较多的情况,不过,这种模式下要尽量避免传播的信息包不能太大,避免网络消耗太大。
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ tag:
|
|||
|
||||
共识算法允许一组节点像一个整体一样一起工作,即使其中的一些节点出现故障也能够继续工作下去,其正确性主要是源于复制状态机的性质:一组`Server`的状态机计算相同状态的副本,即使有一部分的`Server`宕机了它们仍然能够继续运行。
|
||||
|
||||

|
||||

|
||||
|
||||
`图-1 复制状态机架构`
|
||||
|
||||
|
|
@ -59,13 +59,13 @@ tag:
|
|||
|
||||
在正常的情况下,只有一个服务器是 Leader,剩下的服务器是 Follower。Follower 是被动的,它们不会发送任何请求,只是响应来自 Leader 和 Candidate 的请求。
|
||||
|
||||

|
||||

|
||||
|
||||
`图-2:服务器的状态`
|
||||
|
||||
### 2.2 任期
|
||||
|
||||

|
||||

|
||||
|
||||
`图-3:任期`
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ category: 高可用
|
|||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ category: 高可用
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ category: 高可用
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ category: 高可用
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -48,7 +48,6 @@ category: 高可用
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ Resilience4j 不仅提供限流,还提供了熔断、负载保护、自动重
|
|||
|
||||
> ShenYu 地址: https://github.com/apache/incubator-shenyu
|
||||
|
||||

|
||||

|
||||
|
||||
## 相关阅读
|
||||
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@ head:
|
|||
|
||||
类似于京东建立的庞大的仓储运输体系,京东物流在全国拥有非常多的仓库,仓储网络几乎覆盖全国所有区县。这样的话,用户下单的第一时间,商品就从距离用户最近的仓库,直接发往对应的配送站,再由京东小哥送到你家。
|
||||
|
||||

|
||||

|
||||
|
||||
你可以将 CDN 看作是服务上一层的特殊缓存服务,分布在全国各地,主要用来处理静态资源的请求。
|
||||
|
||||

|
||||

|
||||
|
||||
我们经常拿全站加速和内容分发网络做对比,不要把两者搞混了!全站加速(不同云服务商叫法不同,腾讯云叫 ECDN、阿里云叫 DCDN)既可以加速静态资源又可以加速动态资源,内容分发网络(CDN)主要针对的是 **静态资源** 。
|
||||
|
||||

|
||||

|
||||
|
||||
绝大部分公司都会在项目开发中交使用 CDN 服务,但很少会有自建 CDN 服务的公司。基于成本、稳定性和易用性考虑,建议直接选择专业的云厂商(比如阿里云、腾讯云、华为云、青云)或者 CDN 厂商(比如网宿、蓝汛)提供的开箱即用的 CDN 服务。
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ CDN 会通过 GSLB 找到最合适的 CDN 节点,更具体点来说是下面
|
|||
3. GSLB 返回性能最好(通常距离请求地址最近)的 CDN 节点(边缘服务器,真正缓存内容的地方)的地址给浏览器;
|
||||
4. 浏览器直接访问指定的 CDN 节点。
|
||||
|
||||

|
||||

|
||||
|
||||
为了方便理解,上图其实做了一点简化。GSLB 内部可以看作是 CDN 专用 DNS 服务器和负载均衡系统组合。CDN 专用 DNS 服务器会返回负载均衡系统 IP 地址给浏览器,浏览器使用 IP 地址请求负载均衡系统进而找到对应的 CDN 节点。
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ CDN 会通过 GSLB 找到最合适的 CDN 节点,更具体点来说是下面
|
|||
|
||||
CDN 服务提供商几乎都提供了这种比较基础的防盗链机制。
|
||||
|
||||

|
||||

|
||||
|
||||
不过,如果站点的防盗链配置允许 Referer 为空的话,通过隐藏 Referer,可以直接绕开防盗链。
|
||||
|
||||
|
|
@ -103,11 +103,11 @@ http://cdn.wangsu.com/4/123.mp3? wsSecret=79aead3bd7b5db4adeffb93a010298b5&wsTim
|
|||
- `wsSecret` :签名字符串。
|
||||
- `wsTime`: 过期时间。
|
||||
|
||||

|
||||

|
||||
|
||||
时间戳防盗链的实现也比较简单,并且可靠性较高,推荐使用。并且,绝大部分 CDN 服务提供商都提供了开箱即用的时间戳防盗链机制。
|
||||
|
||||

|
||||

|
||||
|
||||
除了 Referer 防盗链和时间戳防盗链之外,你还可以 IP 黑白名单配置、IP 访问限频配置等机制来防盗刷。
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ head:
|
|||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -53,6 +53,6 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -51,7 +51,7 @@ Kafka 主要有两大应用场景:
|
|||
|
||||
发布-订阅模型主要是为了解决队列模型存在的问题。
|
||||
|
||||

|
||||

|
||||
|
||||
发布订阅模型(Pub-Sub) 使用**主题(Topic)** 作为消息通信载体,类似于**广播模式**;发布者发布一条消息,该消息通过主题传递给所有的订阅者,**在一条消息广播之后才订阅的用户则是收不到该条消息的**。
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ Kafka 主要有两大应用场景:
|
|||
|
||||
Kafka 将生产者发布的消息发送到 **Topic(主题)** 中,需要这些消息的消费者可以订阅这些 **Topic(主题)**,如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
上面这张图也为我们引出了,Kafka 比较重要的几个概念:
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ tag:
|
|||
|
||||
我们可以把消息队列看作是一个存放消息的容器,当我们需要使用消息的时候,直接从容器中取出消息供自己使用即可。由于队列 Queue 是一种先进先出的数据结构,所以消费消息时也是按照顺序来消费的。
|
||||
|
||||

|
||||

|
||||
|
||||
参与消息传递的双方称为 **生产者** 和 **消费者** ,生产者负责发送消息,消费者负责处理消息。
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ RocketMQ 、 Kafka、Pulsar 、QMQ 都提供了事务相关的功能。事务允
|
|||
|
||||
详细介绍可以查看 [分布式事务详解(付费)](https://javaguide.cn/distributed-system/distributed-transaction.html) 这篇文章。
|
||||
|
||||

|
||||

|
||||
|
||||
## 使用消息队列会带来哪些问题?
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ RPC 和消息队列本质上是网络通讯的两种不同的实现机制,两
|
|||
|
||||
#### Kafka
|
||||
|
||||

|
||||

|
||||
|
||||
Kafka 是 LinkedIn 开源的一个分布式流式处理平台,已经成为 Apache 顶级项目,早期被用来用于处理海量的日志,后面才慢慢发展成了一款功能全面的高性能消息队列。
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ Kafka 是一个分布式系统,由通过高性能 TCP 网络协议进行通信
|
|||
|
||||
不过,要提示一下:**如果要使用 KRaft 模式的话,建议选择较高版本的 Kafka,因为这个功能还在持续完善优化中。Kafka 3.3.1 版本是第一个将 KRaft(Kafka Raft)共识协议标记为生产就绪的版本。**
|
||||
|
||||

|
||||

|
||||
|
||||
Kafka 官网:http://kafka.apache.org/
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ Kafka 更新记录(可以直观看到项目是否还在维护):https://kaf
|
|||
|
||||
#### RocketMQ
|
||||
|
||||

|
||||

|
||||
|
||||
RocketMQ 是阿里开源的一款云原生“消息、事件、流”实时数据处理平台,借鉴了 Kafka,已经成为 Apache 顶级项目。
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ RocketMQ 更新记录(可以直观看到项目是否还在维护):https://
|
|||
|
||||
#### RabbitMQ
|
||||
|
||||

|
||||

|
||||
|
||||
RabbitMQ 是采用 Erlang 语言实现 AMQP(Advanced Message Queuing Protocol,高级消息队列协议)的消息中间件,它最初起源于金融系统,用于在分布式系统中存储转发消息。
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ RabbitMQ 更新记录(可以直观看到项目是否还在维护):https://
|
|||
|
||||
#### Pulsar
|
||||
|
||||

|
||||

|
||||
|
||||
Pulsar 是下一代云原生分布式消息流平台,最初由 Yahoo 开发 ,已经成为 Apache 顶级项目。
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ head:
|
|||
|
||||
我简单画了一张图来帮助不太清楚读写分离的小伙伴理解。
|
||||
|
||||

|
||||

|
||||
|
||||
一般情况下,我们都会选择一主多从,也就是一台主数据库负责写,其他的从数据库负责读。主库和从库之间会进行数据同步,以保证从库中数据的准确性。这样的架构实现起来比较简单,并且也符合系统的写少读多的特点。
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ hintManager.setMasterRouteOnly();
|
|||
|
||||
**1.代理方式**
|
||||
|
||||

|
||||

|
||||
|
||||
我们可以在应用和数据中间加了一个代理层。应用程序所有的数据请求都交给代理层处理,代理层负责分离读写请求,将它们路由到对应的数据库中。
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ MySQL binlog(binary log 即二进制日志文件) 主要记录了 MySQL 数据
|
|||
|
||||
更具体和详细的过程是这个样子的(图片来自于:[《MySQL Master-Slave Replication on the Same Machine》](https://www.toptal.com/mysql/mysql-master-slave-replication-tutorial)):
|
||||
|
||||

|
||||

|
||||
|
||||
1. 主库将数据库中数据的变化写入到 binlog
|
||||
2. 从库连接主库
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ head:
|
|||
|
||||
**常见 SQL 优化手段总结** 相关的内容为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -55,6 +55,6 @@ head:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -36,11 +36,11 @@ tag:
|
|||
|
||||
Brendan Gregg 之前是 Netflix 公司的高级性能架构师,在 Netflix 工作近 7 年。2022 年 4 月,他离开了 Netflix 去了 Intel,担任院士职位。
|
||||
|
||||

|
||||

|
||||
|
||||
总体上,他已经在系统性能领域深耕超过 10 年,[Brendan Gregg 的过往履历](https://www.linkedin.com/in/brendangregg/)可以在 linkedin 上看到。在这 10 年间,除了书籍以外,Brendan Gregg 还产出了超过上百份和系统性能相关的技术文档,演讲视频/ppt,还有各种工具软件,相关内容都整整齐齐地分享在[他的技术博客](http://www.brendangregg.com/)上,可以说他是一个非常高产的技术大牛。
|
||||
|
||||

|
||||

|
||||
|
||||
上图来自 Brendan Gregg 的新书《BPF Performance Tools: Linux System and Application Observability》。从这个图可以看出,Brendan Gregg 对系统性能领域的掌握程度,已经深挖到了硬件、操作系统和应用的每一个角落,可以说是 360 度无死角,整个计算机系统对他来说几乎都是透明的。波波认为,Brendan Gregg 是名副其实的,世界级的,系统性能领域的大神级人物。
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ Brendan Gregg 之前是 Netflix 公司的高级性能架构师,在 Netflix 工
|
|||
|
||||
到 2014 年底,Kafka 在社区已经非常成功,有了一个比较大的用户群,于是 Jay Kreps 就和几个早期作者一起离开了 Linkedin,成立了[Confluent 公司](https://tech.163.com/14/1107/18/AAFG92LD00094ODU.html),开始了 Kafka 和周边产品的企业化服务道路。今年(2020.4 月),Confluent 公司已经获得 E 轮 2.5 亿美金融资,公司估值达到 45 亿美金。从 Kafka 诞生到现在,Jay Kreps 差不多在这个产品和公司上投入了整整 10 年。
|
||||
|
||||

|
||||

|
||||
|
||||
上图是 Confluent 创始人三人组,一个非常有意思的组合,一个中国人(左),一个印度人(右),中间的 Jay Kreps 是美国人。
|
||||
|
||||
|
|
@ -64,11 +64,11 @@ Brendan Gregg 之前是 Netflix 公司的高级性能架构师,在 Netflix 工
|
|||
|
||||
介绍到这里,有些同学可能会反驳说:波波你讲的这些大牛都是学历背景好,功底扎实起点高,所以他们才更能成功。其实不然,这里我再要介绍一位技术媒体界的大 V 叫 Brad Traversy,大家可以看[他的 Linkedin 简历](https://www.linkedin.com/in/bradtraversy/),背景很一般,学历差不多是一个非正规的社区大学(相当于大专),没有正规大厂工作经历,有限几份工作一直是在做网站外包。
|
||||
|
||||

|
||||

|
||||
|
||||
但是!!!Brad Traversy 目前是技术媒体领域的一个大 V,当前[他在 Youtube 上的频道](https://www.youtube.com/c/TraversyMedia)有 138 万多的订阅量,10 年累计输出 Web 开发和编程相关教学视频超过 800 个。Brad Traversy 也是 [Udemy](https://www.udemy.com/user/brad-traversy/) 上的一个成功讲师,目前已经在 Udemy 上累计输出课程 19 门,购课学生数量近 42 万。
|
||||
|
||||

|
||||

|
||||
|
||||
Brad Traversy 目前是自由职业者,他的 Youtube 广告+Udemy 课程的收入相当不错。
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ Brad Traversy 目前是自由职业者,他的 Youtube 广告+Udemy 课程的
|
|||
|
||||
到结婚后的第一个孩子诞生,他才开始担起责任做出改变,然后凭借对技术的一腔热情,开始在 Youtube 平台上持续输出免费课程。从此他找到了适合自己的战略目标,然后人生开始发生各种积极的变化。。。如果大家对 Brad Traversy 的过往经历感兴趣,推荐观看他在 Youtube 上的自述视频[《My Struggles & Success》](https://www.youtube.com/watch?v=zA9krklwADI)。
|
||||
|
||||

|
||||

|
||||
|
||||
我粗略浏览了[Brad Traversy 在 Youtube 上的所有视频](https://www.youtube.com/c/TraversyMedia/videos),10 年总计输出 800+视频,平均每年 80+。第一个视频提交于 2010 年 8 月,刚开始几年几乎没有订阅量,2017 年 1 月订阅量才到 50k,这中间差不多隔了 6 年。2017.10 月订阅量猛增到 200k,2018 年 3 月订阅量到 300k。当前 2021.1 月,订阅量达到 138 万。可以认为从 2017 开始,也就是在积累了 6 ~ 7 年后,他的订阅量开始出现拐点。**如果把这些数据画出来,将会是一条非常漂亮的复利曲线**。
|
||||
|
||||
|
|
@ -108,13 +108,13 @@ Brendan Gregg,Jay Kreps 和 Brad Traversy 三个人走的技术路线各不相
|
|||
|
||||
普通人通常走一步算一步,很少长远规划。牛人通 常是先有远大目标,然后采用倒推法,将大目标细化到每年/月/周的详细落地计划。Brendan Gregg,Jay Kreps 和 Brad Traversy 三人都是以终为始的典型。
|
||||
|
||||

|
||||

|
||||
|
||||
上面总结了几位技术大牛的成长模式,其中一个重点就是:这些大牛的成长都是通过 **持续有价值产出(Persistent Valuable Output)** 来驱动的。持续产出为啥如此重要,这个还要从下面的学习金字塔说起。
|
||||
|
||||
## 三、学习金字塔和刻意训练
|
||||
|
||||

|
||||

|
||||
|
||||
学习金字塔是美国缅因州国家训练实验室的研究成果,它认为:
|
||||
|
||||
|
|
@ -134,11 +134,11 @@ Brendan Gregg,Jay Kreps 和 Brad Traversy 三个人走的技术路线各不相
|
|||
|
||||
明白这个道理之后,心智成熟和自律的人就会对自己进行持续地 **刻意训练** 。这个刻意训练包括对身体的训练,比如波波现在每天坚持跑步 3km,走 3km,每天做 60 个仰卧起坐,5 分钟平板撑等等,每天保持让身体燃烧一定量的卡路里。刻意训练也包括对大脑的训练,比如波波现在每天做项目写代码 coding(训练脑+手),平均每天在 B 站上输出十分钟免费视频(训练脑+口头表达),另外有定期总结输出公众号文章(训练脑+文字表达),还有每天打半小时左右的平衡球(下图)或古墓丽影游戏(训练小脑+手),每天保持让大脑燃烧一定量的卡路里,并保持一定强度(适度不适感)。
|
||||
|
||||

|
||||

|
||||
|
||||
关于刻意训练的专业原理和方法论,推荐看书籍《刻意练习》。
|
||||
|
||||

|
||||

|
||||
|
||||
注意,如果你平时从来不做举重锻炼的,那么某天突然做举重会很不适应甚至受伤。脑部训练也是一样的,如果你从来没有做过视频输出,那么刚开始做会很不适应,做出来的视频质量会很差。不过没有关系,任何训练都是一个循序渐进,不断强化的过程。等大脑相关区域的"肌肉"长出来以后,会逐步进入正循环,后面会越来越顺畅,相关"肌肉"会越来越发达。所以,和健身一样,健脑也不能遇到困难就放弃,需要循序渐进(Incremental)+持续地(Persistent)刻意训练。
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ tag:
|
|||
|
||||
设计一个初始问题,比如说查找算法,然后从这个初始问题出发,串联起各个知识点。比如:
|
||||
|
||||

|
||||

|
||||
|
||||
在每一个技术点上,都可以应用以上发问技巧,导向不同的问题分支。同时考察面试者的深度、广度和应用能力。
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ tag:
|
|||
- 工号是单独的 300 号段,其他供应商员工的工号是 8 开头,或着 WX 开头;
|
||||
- 工卡带是红色的,和自有员工一样,但是工卡内容不同,OD 的明确标注:办公区通行证,并有德科公司的备注:
|
||||
|
||||

|
||||

|
||||
|
||||
还听到一些内部的说法:
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ tag:
|
|||
|
||||
a) 内部发文啥的,还有心声平台的大部分内容,都是无权限看的:
|
||||
|
||||

|
||||

|
||||
|
||||
b) 你的考勤是在租赁人员管理系统里考核,绩效管理也是;
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ OD 同学能拿到 A 吗?不知道,我入职晚,都没有经历一个完
|
|||
|
||||
这个听起来都感觉很玄学。还是那句话,实力和运气到了,应该可以的!成功转正员工图镇楼:
|
||||
|
||||

|
||||

|
||||
|
||||
### 真的感谢 OD,也感谢华为
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ tag:
|
|||
>
|
||||
> **原文地址** :https://www.cnblogs.com/hunternet/p/14675348.html
|
||||
|
||||

|
||||

|
||||
|
||||
一年一度的金三银四跳槽大戏即将落幕,相信很多跳槽的小伙伴们已经找到了心仪的工作,即将或已经有了新的开始。
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ tag:
|
|||
|
||||
新的工作面对着一堆的代码仓库,很多人常常感觉无从下手。但回顾一下自己过往的工作与项目的经验,我们可以发现它们有着异曲同工之处。当开始一个新的项目,一般会经历几个步骤:需求->设计->开发->测试->发布,就这么循环往复,我们完成了一个又一个的项目。
|
||||
|
||||

|
||||

|
||||
|
||||
而在这个过程中主要有四个方面的知识那就是业务、技术、项目与团队贯穿始终。新入职一家公司,我们第一阶段的目标就是要具备能够跟着团队做项目的能力,因此我们所应尽快掌握的知识点也要从这四个方面入手。
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ title: JavaGuide(Java学习&&面试指南)
|
|||
<div align="center">
|
||||
<p>
|
||||
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width="" />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width="" />
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
|
|
@ -31,7 +31,7 @@ title: JavaGuide(Java学习&&面试指南)
|
|||
<div style="text-align:center">
|
||||
<p>
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -240,7 +240,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
|||
|
||||
[Elasticsearch常见面试题总结(付费)](./database/elasticsearch/elasticsearch-questions-01.md)
|
||||
|
||||

|
||||

|
||||
|
||||
## 开发工具
|
||||
|
||||
|
|
@ -432,5 +432,5 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
|||
|
||||
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号“**JavaGuide**”。
|
||||
|
||||

|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -9,21 +9,21 @@ category: 知识星球
|
|||
|
||||
如果你是非科班的同学,也能在这些文章中找到对应的非科班的同学写的面经。
|
||||
|
||||

|
||||

|
||||
|
||||
并且,[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)还有专门分享面经和面试题的专题,里面会分享很多优质的面经和面试题。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
欢迎准备 Java 面试以及学习 Java 的同学加入我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html),干货非常多,学习氛围也很不错!收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。
|
||||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ category: 知识星球
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ category: 知识星球
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ category: 知识星球
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ category: 面试准备
|
|||
|
||||
你可以通过慕课网、哔哩哔哩、拉勾、极客时间、培训机构(比如黑马、尚硅谷)等渠道获取到适合自己的实战项目视频/专栏。
|
||||
|
||||

|
||||

|
||||
|
||||
尽量选择一个适合自己的项目,没必要必须做分布式/微服务项目,对于绝大部分同学来说,能把一个单机项目做好就已经很不错了。
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Github 或者码云上面有很多实战类别项目,你可以选择一个来
|
|||
|
||||
你可以参考 [Java 优质开源实战项目](https://javaguide.cn/open-source-project/practical-project.html "Java 优质开源实战项目") 上面推荐的实战类开源项目,质量都很高,项目类型也比较全面,涵盖博客/论坛系统、考试/刷题系统、商城系统、权限管理系统、快速开发脚手架以及各种轮子。
|
||||
|
||||

|
||||

|
||||
|
||||
一定要记住: **不光要做,还要改进,改善。不论是实战项目视频或者专栏还是实战类开源项目,都一定会有很多可以完善改进的地方。**
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ Github 或者码云上面有很多实战类别项目,你可以选择一个来
|
|||
|
||||
**[《Java 面试指北》](../zhuanlan/java-mian-shi-zhi-bei.md)** 的「面试准备篇」中有一篇文章专门整理了一些比较高质量的实战项目,非常适合用来学习或者作为项目经验。
|
||||
|
||||

|
||||

|
||||
|
||||
这篇文章一共推荐了 15+ 个实战项目,有业务类的,也有轮子类的,有开源项目、也有视频教程。对于参加校招的小伙伴,我更建议做一个业务类项目加上一个轮子类的项目。
|
||||
|
||||
|
|
|
|||
|
|
@ -7,23 +7,23 @@ category: 知识星球
|
|||
|
||||
在 **[《Java 面试指北》](../zhuanlan/java-mian-shi-zhi-bei.md)** 的 **「技术面试题自测篇」** ,我总结了 Java 面试中最重要的知识点的最常见的面试题并按照面试提问的方式展现出来。
|
||||
|
||||

|
||||

|
||||
|
||||
每一道用于自测的面试题我都会给出重要程度,方便大家在时间比较紧张的时候根据自身情况来选择性自测。并且,我还会给出提示,方便你回忆起对应的知识点。
|
||||
|
||||
在面试中如果你实在没有头绪的话,一个好的面试官也是会给你提示的。
|
||||
|
||||

|
||||

|
||||
|
||||
欢迎准备 Java 面试以及学习 Java 的同学加入我的[知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc),干货非常多,学习氛围非常好!收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。
|
||||
|
||||

|
||||

|
||||
|
||||
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
|
||||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -33,6 +33,6 @@ category: 知识星球
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -79,15 +79,15 @@ category: 知识星球
|
|||
|
||||
**1.个人介绍没太多实用的信息。**
|
||||
|
||||

|
||||

|
||||
|
||||
技术博客、Github 以及在校获奖经历的话,能写就尽量写在这里。 你可以参考下面 👇 的模板进行修改:
|
||||
|
||||

|
||||

|
||||
|
||||
**2.项目经历过于简单,完全没有质量可言**
|
||||
|
||||

|
||||

|
||||
|
||||
每一个项目经历真的就一两句话可以描述了么?还是自己不想写?还是说不是自己做的,不敢多写。
|
||||
|
||||
|
|
@ -102,11 +102,11 @@ category: 知识星球
|
|||
|
||||
**3.计算机二级这个证书对于计算机专业完全不用写了,没有含金量的。**
|
||||
|
||||

|
||||

|
||||
|
||||
**4.技能介绍问题太大。**
|
||||
|
||||

|
||||

|
||||
|
||||
- 技术名词最好规范大小写比较好,比如 java->Java ,spring boot -> Spring Boot 。这个虽然有些面试官不会介意,但是很多面试官都会在意这个细节的。
|
||||
- 技能介绍太杂,没有亮点。不需要全才,某个领域做得好就行了!
|
||||
|
|
@ -176,7 +176,7 @@ category: 知识星球
|
|||
- 降级
|
||||
- 熔断
|
||||
|
||||

|
||||

|
||||
|
||||
不同类型的公司对于技能的要求侧重点是不同的比如腾讯、字节可能更重视计算机基础比如网络、操作系统这方面的内容。阿里、美团这种可能更重视你的项目经历、实战能力。
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ System.out.println(a == b);// false
|
|||
|
||||
《阿里巴巴 Java 开发手册》中提到:**浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断。**
|
||||
|
||||

|
||||

|
||||
|
||||
具体原因我们在上面已经详细介绍了,这里就不多提了。
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ System.out.println(x.compareTo(y));// 0
|
|||
|
||||
《阿里巴巴 Java 开发手册》对这部分内容也有提到,如下图所示。
|
||||
|
||||

|
||||

|
||||
|
||||
### 加减乘除
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ System.out.println(n);// 1.255
|
|||
|
||||
《阿里巴巴 Java 开发手册》中提到:
|
||||
|
||||

|
||||

|
||||
|
||||
`BigDecimal` 使用 `equals()` 方法进行等值比较出现问题的代码示例:
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ System.out.println(a.equals(b));//false
|
|||
|
||||
1.0 的 scale 是 1,1 的 scale 是 0,因此 `a.equals(b)` 的结果是 false。
|
||||
|
||||

|
||||

|
||||
|
||||
`compareTo()` 方法可以比较两个 `BigDecimal` 的值,如果相等就返回 0,如果第 1 个数比第 2 个数大则返回 1,反之返回-1。
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ tag:
|
|||
|
||||
[《Java 面试指北》](https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) 的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。
|
||||
|
||||

|
||||

|
||||
|
||||
[《Java 面试指北》](https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7)只是星球内部众多资料中的一个,星球还有很多其他优质资料比如[专属专栏](https://javaguide.cn/zhuanlan/)、Java 编程视频、PDF 资料。
|
||||
|
||||

|
||||

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -35,6 +35,6 @@ tag:
|
|||
|
||||
<div align="center">
|
||||
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
|
||||
<img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -41,7 +41,7 @@ Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不
|
|||
|
||||
除了我们平时最常用的 HotSpot VM 外,还有 J9 VM、Zing VM、JRockit VM 等 JVM 。维基百科上就有常见 JVM 的对比:[Comparison of Java virtual machines](https://en.wikipedia.org/wiki/Comparison_of_Java_virtual_machines) ,感兴趣的可以去看看。并且,你可以在 [Java SE Specifications](https://docs.oracle.com/javase/specs/index.html) 上找到各个版本的 JDK 对应的 JVM 规范。
|
||||
|
||||

|
||||

|
||||
|
||||
#### JDK 和 JRE
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
|
|||
|
||||
**Java 程序从源代码到运行的过程如下图所示:**
|
||||
|
||||

|
||||

|
||||
|
||||
我们需要格外注意的是 `.class->机器码` 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(just-in-time compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 **Java 是编译与解释共存的语言** 。
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ AOT 可以提前编译节省启动时间,那为什么不全部使用这种编
|
|||
- **编译型** :[编译型语言](https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E8%AA%9E%E8%A8%80) 会通过[编译器](https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E5%99%A8)将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。
|
||||
- **解释型** :[解释型语言](https://zh.wikipedia.org/wiki/%E7%9B%B4%E8%AD%AF%E8%AA%9E%E8%A8%80)会通过[解释器](https://zh.wikipedia.org/wiki/直譯器)一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。
|
||||
|
||||

|
||||

|
||||
|
||||
根据维基百科介绍:
|
||||
|
||||
|
|
@ -126,14 +126,14 @@ AOT 可以提前编译节省启动时间,那为什么不全部使用这种编
|
|||
>
|
||||
> 基于以上这些原因,OpenJDK 还是有存在的必要的!
|
||||
|
||||

|
||||

|
||||
|
||||
🌈 拓展一下:
|
||||
|
||||
- BCL 协议(Oracle Binary Code License Agreement): 可以使用 JDK(支持商用),但是不能进行修改。
|
||||
- OTN 协议(Oracle Technology Network License Agreement): 11 及之后新发布的 JDK 用的都是这个协议,可以自己私下用,但是商用需要付费。
|
||||
|
||||

|
||||

|
||||
|
||||
相关阅读 👍:[《Differences Between Oracle JDK and OpenJDK》](https://www.baeldung.com/oracle-jdk-vs-openjdk)
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ Java 中的注释有三种:
|
|||
|
||||
用的比较多的还是单行注释和文档注释,多行注释在实际开发中使用的相对较少。
|
||||
|
||||

|
||||

|
||||
|
||||
在我们编写代码的时候,如果代码量比较少,我们自己或者团队其他成员还可以很轻易地看懂代码,但是当项目结构一旦复杂起来,我们就需要用到注释了。注释并不会执行(编译器在编译代码之前会把代码中的所有注释抹掉,字节码中不保留注释),是我们程序员写给自己看的,注释是你的代码说明书,能够帮助看代码的人快速地理清代码之间的逻辑关系。因此,在写程序的时候随手加上注释是一个非常好的习惯。
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ System.out.println(person1.getAddress() == person1Copy.getAddress());
|
|||
|
||||
我专门画了一张图来描述浅拷贝、深拷贝、引用拷贝:
|
||||
|
||||

|
||||

|
||||
|
||||
## Java 常见类
|
||||
|
||||
|
|
@ -473,7 +473,7 @@ public final class String implements java.io.Serializable, Comparable<String>, C
|
|||
>
|
||||
> JDK 官方就说了绝大部分字符串对象只包含 Latin-1 可表示的字符。
|
||||
>
|
||||
> 
|
||||
> 
|
||||
>
|
||||
> 如果字符串中包含的汉字超过 Latin-1 可表示范围内的字符,`byte` 和 `char` 所占用的空间是一样的。
|
||||
>
|
||||
|
|
@ -492,7 +492,7 @@ String str4 = str1 + str2 + str3;
|
|||
|
||||
上面的代码对应的字节码如下:
|
||||
|
||||

|
||||

|
||||
|
||||
可以看出,字符串对象通过“+”的字符串拼接方式,实际上是通过 `StringBuilder` 调用 `append()` 方法实现的,拼接完成之后调用 `toString()` 得到一个 `String` 对象 。
|
||||
|
||||
|
|
@ -509,7 +509,7 @@ System.out.println(s);
|
|||
|
||||
`StringBuilder` 对象是在循环内部被创建的,这意味着每循环一次就会创建一个 `StringBuilder` 对象。
|
||||
|
||||

|
||||

|
||||
|
||||
如果直接使用 `StringBuilder` 对象进行字符串拼接的话,就不会存在这个问题了。
|
||||
|
||||
|
|
@ -522,7 +522,7 @@ for (String value : arr) {
|
|||
System.out.println(s);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
如果你使用 IDEA 的话,IDEA 自带的代码检查机制也会提示你修改代码。
|
||||
|
||||
|
|
@ -559,7 +559,7 @@ String s1 = new String("abc");
|
|||
|
||||
对应的字节码:
|
||||
|
||||

|
||||

|
||||
|
||||
`ldc` 命令用于判断字符串常量池中是否保存了对应的字符串对象的引用,如果保存了的话直接返回,如果没有保存的话,会在堆中创建对应的字符串对象并将该字符串对象的引用保存到字符串常量池中。
|
||||
|
||||
|
|
@ -576,7 +576,7 @@ String s2 = new String("abc");
|
|||
|
||||
对应的字节码:
|
||||
|
||||

|
||||

|
||||
|
||||
这里就不对上面的字节码进行详细注释了,7 这个位置的 `ldc` 命令不会在堆中创建新的字符串对象“abc”,这是因为 0 这个位置已经执行了一次 `ldc` 命令,已经在堆中创建过一次字符串对象“abc”了。7 这个位置执行 `ldc` 命令会直接返回字符串常量池中字符串对象“abc”对应的引用。
|
||||
|
||||
|
|
@ -624,13 +624,13 @@ System.out.println(str4 == str5);//false
|
|||
|
||||
> **注意** :比较 String 字符串的值是否相等,可以使用 `equals()` 方法。 `String` 中的 `equals` 方法是被重写过的。 `Object` 的 `equals` 方法是比较的对象的内存地址,而 `String` 的 `equals` 方法比较的是字符串的值是否相等。如果你使用 `==` 比较两个字符串是否相等的话,IDEA 还是提示你使用 `equals()` 方法替换。
|
||||
|
||||

|
||||

|
||||
|
||||
**对于编译期可以确定值的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池,这个得益于编译器的优化。**
|
||||
|
||||
在编译过程中,Javac 编译器(下文中统称为编译器)会进行一个叫做 **常量折叠(Constant Folding)** 的代码优化。《深入理解 Java 虚拟机》中是也有介绍到:
|
||||
|
||||

|
||||

|
||||
|
||||
常量折叠会把常量表达式的值求出来作为常量嵌在最终生成的代码中,这是 Javac 编译器会对源代码做的极少量优化措施之一(代码优化几乎都在即时编译器中进行)。
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ head:
|
|||
|
||||
**Java 异常类层次结构图概览** :
|
||||
|
||||

|
||||

|
||||
|
||||
### Exception 和 Error 有什么区别?
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ head:
|
|||
|
||||
比如下面这段 IO 操作的代码:
|
||||
|
||||

|
||||

|
||||
|
||||
除了`RuntimeException`及其子类以外,其他的`Exception`类及其子类都属于受检查异常 。常见的受检查异常有: IO 相关的异常、`ClassNotFoundException` 、`SQLException`...。
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ head:
|
|||
- `UnsupportedOperationException`(不支持的操作错误比如重复创建同一用户)
|
||||
- ......
|
||||
|
||||

|
||||

|
||||
|
||||
### Throwable 类常用方法有哪些?
|
||||
|
||||
|
|
@ -415,7 +415,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
|
||||
很多框架都使用了 Java 的 SPI 机制,比如:Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等。
|
||||
|
||||

|
||||

|
||||
|
||||
### SPI 和 API 有什么区别?
|
||||
|
||||
|
|
@ -423,7 +423,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
|
||||
说到 SPI 就不得不说一下 API 了,从广义上来说它们都属于接口,而且很容易混淆。下面先用一张图说明一下:
|
||||
|
||||

|
||||

|
||||
|
||||
一般模块之间都是通过接口进行通讯,那我们在服务调用方和服务实现方(也称服务提供者)之间引入一个“接口”。
|
||||
|
||||
|
|
@ -481,7 +481,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
3. 网络层
|
||||
4. 网络接口层
|
||||
|
||||

|
||||

|
||||
|
||||
如上图所示,OSI 七层协议模型中,表示层做的事情主要就是对应用层的用户数据进行处理转换为二进制流。反过来的话,就是将二进制流转换成应用层的用户数据。这不就对应的是序列化和反序列化么?
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ tag:
|
|||
|
||||
举个例子:新娘找来了自己的姨妈来代替自己处理新郎的提问,新娘收到的提问都是经过姨妈处理过滤之后的。姨妈在这里就可以看作是代理你的代理对象,代理的行为(方法)是接收和回复新郎的提问。
|
||||
|
||||

|
||||

|
||||
|
||||
<p style="text-align:right;font-size:13px;color:gray">https://medium.com/@mithunsasidharan/understanding-the-proxy-design-pattern-5e63fe38052a</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ tag:
|
|||
3. 网络层
|
||||
4. 网络接口层
|
||||
|
||||

|
||||

|
||||
|
||||
如上图所示,OSI 七层协议模型中,表示层做的事情主要就是对应用层的用户数据进行处理转换为二进制流。反过来的话,就是将二进制流转换成应用层的用户数据。这不就对应的是序列化和反序列化么?
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
|
||||
很多框架都使用了 Java 的 SPI 机制,比如:Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等。
|
||||
|
||||

|
||||

|
||||
|
||||
### SPI 和 API 有什么区别?
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
|
||||
说到 SPI 就不得不说一下 API 了,从广义上来说它们都属于接口,而且很容易混淆。下面先用一张图说明一下:
|
||||
|
||||

|
||||

|
||||
|
||||
一般模块之间都是通过通过接口进行通讯,那我们在服务调用方和服务实现方(也称服务提供者)之间引入一个“接口”。
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ SPI 将服务接口和具体的服务实现分离开来,将服务调用方和
|
|||
|
||||
SLF4J (Simple Logging Facade for Java)是 Java 的一个日志门面(接口),其具体实现有几种,比如:Logback、Log4j、Log4j2 等等,而且还可以切换,在切换日志具体实现的时候我们是不需要更改项目代码的,只需要在 Maven 依赖里面修改一些 pom 依赖就好了。
|
||||
|
||||

|
||||

|
||||
|
||||
这就是依赖 SPI 机制实现的,那我们接下来就实现一个简易版本的日志框架。
|
||||
|
||||
|
|
@ -222,11 +222,11 @@ public class Logback implements Logger {
|
|||
|
||||
新建 lib 目录,然后将 jar 包拷贝过来,再添加到项目中。
|
||||
|
||||

|
||||

|
||||
|
||||
再点击 OK 。
|
||||
|
||||

|
||||

|
||||
|
||||
接下来就可以在项目中导入 jar 包里面的一些类和方法了,就像 JDK 工具类导包一样的。
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ public class Logback implements Logger {
|
|||
|
||||
然后先导入 `Logger` 的接口 jar 包,再导入具体的实现类的 jar 包。
|
||||
|
||||

|
||||

|
||||
|
||||
新建 Main 方法测试:
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ head:
|
|||
|
||||
**语法糖(Syntactic Sugar)** 也称糖衣语法,是英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。简而言之,语法糖让程序更加简洁,有更高的可读性。
|
||||
|
||||

|
||||

|
||||
|
||||
> 有意思的是,在编程领域,除了语法糖,还有语法盐和语法糖精的说法,篇幅有限这里不做扩展了。
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ tag:
|
|||
|
||||
另外,`Unsafe` 提供的这些功能的实现需要依赖本地方法(Native Method)。你可以将本地方法看作是 Java 中使用其他编程语言编写的方法。本地方法使用 **`native`** 关键字修饰,Java 代码中只是声明方法头,具体的实现则交给 **本地代码**。
|
||||
|
||||

|
||||

|
||||
|
||||
**为什么要使用本地方法呢?**
|
||||
|
||||
|
|
@ -163,11 +163,11 @@ addr3: 2433733894944
|
|||
|
||||
你可以通过下图理解这个过程:
|
||||
|
||||

|
||||

|
||||
|
||||
在代码中调用`reallocateMemory`方法重新分配了一块 8 字节长度的内存空间,通过比较`addr`和`addr3`可以看到和之前申请的内存地址是不同的。在代码中的第二个 for 循环里,调用`copyMemory`方法进行了两次内存的拷贝,每次拷贝内存地址`addr`开始的 4 个字节,分别拷贝到以`addr3`和`addr3+4`开始的内存空间上:
|
||||
|
||||

|
||||

|
||||
|
||||
拷贝完成后,使用`getLong`方法一次性读取 8 个字节,得到`long`类型的值为 72340172838076673。
|
||||
|
||||
|
|
@ -283,7 +283,7 @@ main thread end
|
|||
|
||||
而如果删掉上面代码中的`loadFence`方法,那么主线程将无法感知到`flag`发生的变化,会一直在`while`中循环。可以用图来表示上面的过程:
|
||||
|
||||

|
||||

|
||||
|
||||
了解 Java 内存模型(`JMM`)的小伙伴们应该清楚,运行中的线程不是直接读取主内存中的变量的,只能操作自己工作内存中的变量,然后同步到主内存中,并且线程的工作内存是不能共享的。上面的图中的流程就是子线程借助于主内存,将修改后的结果同步给了主线程,进而修改主线程中的工作空间,跳出循环。
|
||||
|
||||
|
|
@ -341,7 +341,7 @@ public native void putOrderedLong(Object o, long offset, long x);
|
|||
|
||||
顺序写入与`volatile`写入的差别在于,在顺序写时加入的内存屏障类型为`StoreStore`类型,而在`volatile`写入时加入的内存屏障是`StoreLoad`类型,如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
在有序写入方法中,使用的是`StoreStore`屏障,该屏障确保`Store1`立刻刷新数据到内存,这一操作先于`Store2`以及后续的存储指令操作。而在`volatile`写入中,使用的是`StoreLoad`屏障,该屏障确保`Store1`立刻刷新数据到内存,这一操作先于`Load2`及后续的装载指令,并且,`StoreLoad`屏障会使该屏障之前的所有内存访问指令,包括存储指令和访问指令全部完成之后,才执行该屏障之后的内存访问指令。
|
||||
|
||||
|
|
@ -398,7 +398,7 @@ public native int arrayIndexScale(Class<?> arrayClass);
|
|||
|
||||
这两个与数据操作相关的方法,在 `java.util.concurrent.atomic` 包下的 `AtomicIntegerArray`(可以实现对 `Integer` 数组中每个元素的原子性操作)中有典型的应用,如下图 `AtomicIntegerArray` 源码所示,通过 `Unsafe` 的 `arrayBaseOffset` 、`arrayIndexScale` 分别获取数组首元素的偏移地址 `base` 及单个元素大小因子 `scale` 。后续相关原子性操作,均依赖于这两个值进行数组中元素的定位,如下图二所示的 `getAndAdd` 方法即通过 `checkedByteOffset` 方法获取某数组元素的偏移地址,而后通过 CAS 实现原子性操作。
|
||||
|
||||

|
||||

|
||||
|
||||
### CAS 操作
|
||||
|
||||
|
|
@ -473,7 +473,7 @@ private void increment(int x){
|
|||
|
||||
在上面的例子中,使用两个线程去修改`int`型属性`a`的值,并且只有在`a`的值等于传入的参数`x`减一时,才会将`a`的值变为`x`,也就是实现对`a`的加一的操作。流程如下所示:
|
||||
|
||||

|
||||

|
||||
|
||||
需要注意的是,在调用`compareAndSwapInt`方法后,会直接返回`true`或`false`的修改结果,因此需要我们在代码中手动添加自旋的逻辑。在`AtomicInteger`类的设计中,也是采用了将`compareAndSwapInt`的结果作为循环条件,直至修改成功才退出死循环的方式来实现的原子性的自增操作。
|
||||
|
||||
|
|
@ -565,7 +565,7 @@ unpark mainThread success
|
|||
|
||||
程序运行的流程也比较容易看懂,子线程开始运行后先进行睡眠,确保主线程能够调用`park`方法阻塞自己,子线程在睡眠 5 秒后,调用`unpark`方法唤醒主线程,使主线程能继续向下执行。整个流程如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
### Class 操作
|
||||
|
||||
|
|
@ -644,7 +644,7 @@ private static void defineTest() {
|
|||
|
||||
在上面的代码中,首先读取了一个`class`文件并通过文件流将它转化为字节数组,之后使用`defineClass`方法动态的创建了一个类,并在后续完成了它的实例化工作,流程如下图所示,并且通过这种方式创建的类,会跳过 JVM 的所有安全检查。
|
||||
|
||||

|
||||

|
||||
|
||||
除了`defineClass`方法外,Unsafe 还提供了一个`defineAnonymousClass`方法:
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ num2 = 20
|
|||
|
||||
在 `swap()` 方法中,`a`、`b` 的值进行交换,并不会影响到 `num1`、`num2`。因为,`a`、`b` 的值,只是从 `num1`、`num2` 的复制过来的。也就是说,a、b 相当于 `num1`、`num2` 的副本,副本的内容无论怎么修改,都不会影响到原件本身。
|
||||
|
||||

|
||||

|
||||
|
||||
通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看案例2。
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ num2 = 20
|
|||
|
||||
解析:
|
||||
|
||||

|
||||

|
||||
|
||||
看了这个案例很多人肯定觉得 Java 对引用类型的参数采用的是引用传递。
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ xiaoLi:小李
|
|||
|
||||
`swap` 方法的参数 `person1` 和 `person2` 只是拷贝的实参 `xiaoZhang` 和 `xiaoLi` 的地址。因此, `person1` 和 `person2` 的互换只是拷贝的两个地址的互换罢了,并不会影响到实参 `xiaoZhang` 和 `xiaoLi` 。
|
||||
|
||||

|
||||

|
||||
|
||||
## 引用传递是怎么样的?
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ tag:
|
|||
|
||||
### 1. 存储结构
|
||||
|
||||

|
||||

|
||||
|
||||
Java 7 中 `ConcurrentHashMap` 的存储结构如上图,`ConcurrnetHashMap` 由很多个 `Segment` 组合,而每一个 `Segment` 是一个类似于 `HashMap` 的结构,所以每一个 `HashMap` 的内部可以进行扩容。但是 `Segment` 的个数一旦**初始化就不能改变**,默认 `Segment` 的个数是 16 个,你也可以认为 `ConcurrentHashMap` 默认支持最多 16 个线程并发。
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ public V get(Object key) {
|
|||
|
||||
### 1. 存储结构
|
||||
|
||||

|
||||

|
||||
|
||||
可以发现 Java8 的 ConcurrentHashMap 相对于 Java7 来说变化比较大,不再是之前的 **Segment 数组 + HashEntry 数组 + 链表**,而是 **Node 数组 + 链表 / 红黑树**。当冲突链表达到一定长度时,链表会转换成红黑树。
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Java 集合, 也叫作容器,主要是由两大接口派生而来:一个
|
|||
|
||||
Java 集合框架如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
注:图中只列举了主要的继承派生关系,并没有列举所有关系。比方省略了`AbstractList`, `NavigableSet`等抽象类以及其他的一些辅助类,如想深入了解,可自行查看源码。
|
||||
|
|
@ -95,7 +95,7 @@ Java 集合框架如下图所示:
|
|||
|
||||
我们在项目中一般是不会使用到 `LinkedList` 的,需要用到 `LinkedList` 的场景几乎都可以使用 `ArrayList` 来代替,并且,性能通常会更好!就连 `LinkedList` 的作者约书亚 · 布洛克(Josh Bloch)自己都说从来不会使用 `LinkedList` 。
|
||||
|
||||

|
||||

|
||||
|
||||
另外,不要下意识地认为 `LinkedList` 作为链表就最适合元素增删的场景。我在上面也说了,`LinkedList` 仅仅在头尾插入或者删除元素的时候时间复杂度近似 O(1),其他情况增删元素的时间复杂度都是 O(n) 。
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ head:
|
|||
|
||||
`TreeMap` 和`HashMap` 都继承自`AbstractMap` ,但是需要注意的是`TreeMap`它还实现了`NavigableMap`接口和`SortedMap` 接口。
|
||||
|
||||

|
||||

|
||||
|
||||
实现 `NavigableMap` 接口让 `TreeMap` 有了对集合内元素的搜索的能力。
|
||||
|
||||
|
|
@ -206,13 +206,13 @@ static int hash(int h) {
|
|||
|
||||
所谓 **“拉链法”** 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
|
||||
|
||||

|
||||

|
||||
|
||||
#### JDK1.8 之后
|
||||
|
||||
相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
|
||||
|
||||

|
||||

|
||||
|
||||
> TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
|
||||
|
||||
|
|
@ -304,13 +304,13 @@ final void treeifyBin(Node<K,V>[] tab, int hash) {
|
|||
|
||||
**Hashtable** :
|
||||
|
||||

|
||||

|
||||
|
||||
<p style="text-align:right;font-size:13px;color:gray">https://www.cnblogs.com/chengxiao/p/6842045.html></p>
|
||||
|
||||
**JDK1.7 的 ConcurrentHashMap** :
|
||||
|
||||

|
||||

|
||||
|
||||
`ConcurrentHashMap` 是由 `Segment` 数组结构和 `HashEntry` 数组结构组成。
|
||||
|
||||
|
|
@ -318,7 +318,7 @@ final void treeifyBin(Node<K,V>[] tab, int hash) {
|
|||
|
||||
**JDK1.8 的 ConcurrentHashMap** :
|
||||
|
||||

|
||||

|
||||
|
||||
JDK1.8 的 `ConcurrentHashMap` 不再是 **Segment 数组 + HashEntry 数组 + 链表**,而是 **Node 数组 + 链表 / 红黑树**。不过,Node 只能用于链表的情况,红黑树的情况需要使用 **`TreeNode`**。当冲突链表达到一定长度时,链表会转换成红黑树。
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ static final class TreeBin<K,V> extends Node<K,V> {
|
|||
|
||||
#### JDK1.8 之前
|
||||
|
||||

|
||||

|
||||
|
||||
首先将数据分为一段一段(这个“段”就是 `Segment`)的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。
|
||||
|
||||
|
|
@ -361,7 +361,7 @@ static class Segment<K,V> extends ReentrantLock implements Serializable {
|
|||
|
||||
#### JDK1.8 之后
|
||||
|
||||

|
||||

|
||||
|
||||
Java 8 几乎完全重写了 `ConcurrentHashMap`,代码量从原来 Java 7 中的 1000 多行,变成了现在的 6000 多行。
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||
}
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
`CompletableFuture` 除了提供了更为好用和强大的 `Future` 特性之外,还提供了函数式编程的能力。
|
||||
|
||||

|
||||

|
||||
|
||||
`Future` 接口有 5 个方法:
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||
|
||||
`CompletionStage` 接口中的方法比较多,`CompletableFuture` 的函数式能力就是这个接口赋予的。从这个接口的方法参数你就可以发现其大量使用了 Java8 引入的函数式编程。
|
||||
|
||||

|
||||

|
||||
|
||||
由于方法众多,所以这里不能一一讲解,下文中我会介绍大部分常见方法的使用。
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public class MultiThread {
|
|||
|
||||
下图是 Java 内存区域,通过下图我们从 JVM 的角度来说一下线程和进程之间的关系。
|
||||
|
||||

|
||||

|
||||
|
||||
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈**。
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种
|
|||
|
||||
Java 线程状态变迁图(图源:[挑错 |《Java 并发编程的艺术》中关于线程状态的三处错误](https://mp.weixin.qq.com/s/UOrXql_LhOD8dhTq_EPI0w)):
|
||||
|
||||

|
||||

|
||||
|
||||
由上图可以看出:线程创建之后它将处于 **NEW(新建)** 状态,调用 `start()` 方法后开始运行,线程这时候处于 **READY(可运行)** 状态。可运行状态的线程获得了 CPU 时间片(timeslice)后就处于 **RUNNING(运行)** 状态。
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ JMM(Java 内存模型)相关的问题比较多,也比较重要,于是我
|
|||
|
||||
在 Java 中,`volatile` 关键字可以保证变量的可见性,如果我们将变量声明为 **`volatile`** ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
`volatile` 关键字其实并非是 Java 语言特有的,在 C 语言里也有,它最原始的意义就是禁用 CPU 缓存。如果我们将一个变量使用 `volatile` 修饰,这就指示 编译器,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。
|
||||
|
||||
|
|
@ -390,11 +390,11 @@ public class SynchronizedDemo {
|
|||
|
||||
在执行`monitorenter`时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。
|
||||
|
||||

|
||||

|
||||
|
||||
对象锁的的拥有者线程才可以执行 `monitorexit` 指令来释放锁。在执行 `monitorexit` 指令后,将锁计数器设为 0,表明锁被释放,其他线程可以尝试获取锁。
|
||||
|
||||

|
||||

|
||||
|
||||
如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ public class ReentrantLock implements Lock, java.io.Serializable {}
|
|||
|
||||
`ReentrantLock` 里面有一个内部类 `Sync`,`Sync` 继承 AQS(`AbstractQueuedSynchronizer`),添加锁和释放锁的大部分操作实际上都是在 `Sync` 中实现的。`Sync` 有公平锁 `FairSync` 和非公平锁 `NonfairSync` 两个子类。
|
||||
|
||||

|
||||

|
||||
|
||||
`ReentrantLock` 默认使用非公平锁,也可以通过构造器来显示的指定使用公平锁。
|
||||
|
||||
|
|
@ -548,7 +548,7 @@ public interface ReadWriteLock {
|
|||
|
||||
和 `ReentrantLock` 一样,`ReentrantReadWriteLock` 底层也是基于 AQS 实现的。
|
||||
|
||||

|
||||

|
||||
|
||||
`ReentrantReadWriteLock` 也支持公平锁和非公平锁,默认使用非公平锁,可以通过构造器来显示的指定。
|
||||
|
||||
|
|
|
|||
|
|
@ -153,11 +153,11 @@ ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
|
|||
|
||||
`ThreadLocal` 数据结构如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
`ThreadLocalMap`是`ThreadLocal`的静态内部类。
|
||||
|
||||

|
||||

|
||||
|
||||
### ThreadLocal 内存泄露问题是怎么导致的?
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ static class Entry extends WeakReference<ThreadLocal<?>> {
|
|||
|
||||
对应 `Executors` 工具类中的方法如图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
### 为什么不推荐使用内置线程池?
|
||||
|
||||
|
|
@ -338,7 +338,7 @@ public ScheduledThreadPoolExecutor(int corePoolSize) {
|
|||
|
||||
### 线程池处理任务的流程了解吗?
|
||||
|
||||

|
||||

|
||||
|
||||
1. 如果当前运行的线程数小于核心线程数,那么就会新建一个线程来执行任务。
|
||||
2. 如果当前运行的线程数等于或大于核心线程数,但是小于最大线程数,那么就把该任务放入到任务队列里等待执行。
|
||||
|
|
@ -451,7 +451,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
|||
|
||||
**如何支持参数动态配置?** 且看 `ThreadPoolExecutor` 提供的下面这些方法。
|
||||
|
||||

|
||||

|
||||
|
||||
格外需要注意的是`corePoolSize`, 程序运行期间的时候,我们调用 `setCorePoolSize()`这个方法的话,线程池会首先判断当前工作线程数是否大于`corePoolSize`,如果大于的话就会回收工作线程。
|
||||
|
||||
|
|
@ -459,7 +459,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
|||
|
||||
最终实现的可动态修改线程池参数效果如下。👏👏👏
|
||||
|
||||

|
||||

|
||||
|
||||
还没看够?推荐 why 神的[如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。](https://mp.weixin.qq.com/s/9HLuPcoWmTqAeFKa1kj-_A)这篇文章,深度剖析,很不错哦!
|
||||
|
||||
|
|
@ -518,7 +518,7 @@ Future<?> submit(Runnable task);
|
|||
|
||||
`FutureTask` 不光实现了 `Future`接口,还实现了`Runnable` 接口,因此可以作为任务直接被线程执行。
|
||||
|
||||

|
||||

|
||||
|
||||
`FutureTask` 有两个构造函数,可传入 `Callable` 或者 `Runnable` 对象。实际上,传入 `Runnable` 对象也会在方法内部转换为`Callable` 对象。
|
||||
|
||||
|
|
@ -553,13 +553,13 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||
|
||||
可以看到,`CompletableFuture` 同时实现了 `Future` 和 `CompletionStage` 接口。
|
||||
|
||||

|
||||

|
||||
|
||||
`CompletionStage` 接口描述了一个异步计算的阶段。很多计算可以分成多个阶段或步骤,此时可以通过它将所有步骤组合起来,形成异步计算的流水线。
|
||||
|
||||
`CompletionStage` 接口中的方法比较多,`CompletableFuture` 的函数式能力就是这个接口赋予的。从这个接口的方法参数你就可以发现其大量使用了 Java8 引入的函数式编程。
|
||||
|
||||

|
||||

|
||||
|
||||
## AQS
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ tag:
|
|||
|
||||
除此之外,我们还可以利用 `ThreadPoolExecutor` 的相关 API 做一个简陋的监控。从下图可以看出, `ThreadPoolExecutor`提供了获取线程池当前的线程数和活跃线程数、已经执行完成的任务数、正在排队中的任务数等等。
|
||||
|
||||

|
||||

|
||||
|
||||
下面是一个简单的 Demo。`printThreadPoolStatus()`会每隔一秒打印出线程池的线程数、活跃线程数、完成的任务数、以及队列中的任务数。
|
||||
|
||||
|
|
@ -61,13 +61,13 @@ public static void printThreadPoolStatus(ThreadPoolExecutor threadPool) {
|
|||
|
||||
**我们再来看一个真实的事故案例!** (本案例来源自:[《线程池运用不当的一次线上事故》](https://club.perfma.com/article/646639) ,很精彩的一个案例)
|
||||
|
||||

|
||||

|
||||
|
||||
上面的代码可能会存在死锁的情况,为什么呢?画个图给大家捋一捋。
|
||||
|
||||
试想这样一种极端情况:假如我们线程池的核心线程数为 **n**,父任务(扣费任务)数量为 **n**,父任务下面有两个子任务(扣费任务下的子任务),其中一个已经执行完成,另外一个被放在了任务队列中。由于父任务把线程池核心线程资源用完,所以子任务因为无法获取到线程资源无法正常执行,一直被阻塞在队列中。父任务等待子任务执行完成,而子任务等待父任务释放线程池资源,这也就造成了 **"死锁"** 。
|
||||
|
||||

|
||||

|
||||
|
||||
解决方法也很简单,就是新增加一个用于执行子任务的线程池专门为其服务。
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
|||
|
||||
**如何支持参数动态配置?** 且看 `ThreadPoolExecutor` 提供的下面这些方法。
|
||||
|
||||

|
||||

|
||||
|
||||
格外需要注意的是`corePoolSize`, 程序运行期间的时候,我们调用 `setCorePoolSize()`这个方法的话,线程池会首先判断当前工作线程数是否大于`corePoolSize`,如果大于的话就会回收工作线程。
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
|||
|
||||
最终实现的可动态修改线程池参数效果如下。👏👏👏
|
||||
|
||||

|
||||

|
||||
|
||||
还没看够?推荐 why 神的[《如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。》](https://mp.weixin.qq.com/s/9HLuPcoWmTqAeFKa1kj-_A)这篇文章,深度剖析,很不错哦!
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ tag:
|
|||
|
||||
如下图所示,包括任务执行机制的核心接口 **`Executor`** ,以及继承自 `Executor` 接口的 **`ExecutorService` 接口。`ThreadPoolExecutor`** 和 **`ScheduledThreadPoolExecutor`** 这两个关键类实现了 **`ExecutorService`** 接口。
|
||||
|
||||

|
||||

|
||||
|
||||
这里提了很多底层的类关系,但是,实际上我们需要更多关注的是 `ThreadPoolExecutor` 这个类,这个类在我们实际使用线程池的过程中,使用频率还是非常高的。
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ Spring 通过 `ThreadPoolTaskExecutor` 或者我们直接通过 `ThreadPoolExecu
|
|||
|
||||
对应 `Executors` 工具类中的方法如图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
《阿里巴巴 Java 开发手册》强制线程池不允许使用 `Executors` 去创建,而是通过 `ThreadPoolExecutor` 构造函数的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ pool-1-thread-2 End. Time = Sun Apr 12 11:14:47 CST 2020
|
|||
|
||||
下图是我为了省事直接从网上找到,原地址不明。
|
||||
|
||||

|
||||

|
||||
|
||||
在 `execute` 方法中,多次调用 `addWorker` 方法。`addWorker` 这个方法主要用来创建新的工作线程,如果返回 true 说明创建和启动工作线程成功,否则的话返回的就是 false。
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ JMM(Java内存模型)主要定义了对于一个共享变量,当另一个线
|
|||
|
||||
> **🐛 修正(参见: [issue#1848](https://github.com/Snailclimb/JavaGuide/issues/1848))**:对 CPU 缓存模型绘图不严谨的地方进行完善。
|
||||
|
||||

|
||||

|
||||
|
||||
现代的 CPU Cache 通常分为三层,分别叫 L1,L2,L3 Cache。有些 CPU 可能还有 L4 Cache,这里不做讨论,并不常见
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ JMM(Java内存模型)主要定义了对于一个共享变量,当另一个线
|
|||
|
||||
**CPU 为了解决内存缓存不一致性问题可以通过制定缓存一致协议(比如 [MESI 协议](https://zh.wikipedia.org/wiki/MESI%E5%8D%8F%E8%AE%AE))或者其他手段来解决。** 这个缓存一致性协议指的是在 CPU 高速缓存与主内存交互的时候需要遵守的原则和规范。不同的 CPU 中,使用的缓存一致性协议通常也会有所不同。
|
||||
|
||||

|
||||

|
||||
|
||||
我们的程序运行在操作系统之上,操作系统屏蔽了底层硬件的操作细节,将各种硬件资源虚拟化。于是,操作系统也就同样需要解决内存缓存不一致性问题。
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ JMM 说白了就是定义了一些规范来解决这些问题,开发者可以
|
|||
|
||||
Java 内存模型的抽象示意图如下:
|
||||
|
||||

|
||||

|
||||
|
||||
从上图来看,线程 1 与线程 2 之间如果要进行通信的话,必须要经历下面 2 个步骤:
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ JSR 133 引入了 happens-before 这个概念来描述两个操作之间的内
|
|||
|
||||
下面这张是 《Java 并发编程的艺术》这本书中的一张 JMM 设计思想的示意图,非常清晰。
|
||||
|
||||

|
||||

|
||||
|
||||
了解了 happens-before 原则的设计思想,我们再来看看 JSR-133 对 happens-before 原则的定义:
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ happens-before 的规则就 8 条,说多不多,重点了解下面列举的 5
|
|||
|
||||
happens-before 与 JMM 的关系用《Java 并发编程的艺术》这本书中的一张图就可以非常好的解释清楚。
|
||||
|
||||

|
||||

|
||||
|
||||
## 再看并发编程三个重要特性
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ public class ThreadLocal<T> {
|
|||
|
||||
从当前节点`staleSlot`向后查找`key`值相等的`Entry`元素,找到后更新`Entry`的值并交换`staleSlot`元素的位置(`staleSlot`位置为过期元素),更新`Entry`数据,然后开始进行过期`Entry`的清理工作,如下图所示:
|
||||
|
||||
向后遍历过程中,如果没有找到相同 key 值的 Entry 数据:
|
||||
向后遍历过程中,如果没有找到相同 key 值的 Entry 数据:
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ try (InputStream fis = new FileInputStream("input.txt")) {
|
|||
|
||||
`input.txt` 文件内容:
|
||||
|
||||

|
||||

|
||||
|
||||
输出:
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ try (FileOutputStream output = new FileOutputStream("output.txt")) {
|
|||
|
||||
运行结果:
|
||||
|
||||

|
||||

|
||||
|
||||
类似于 `FileInputStream`,`FileOutputStream` 通常也会配合 `BufferedOutputStream`(字节缓冲输出流,后文会讲到)来使用。
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ output.writeObject(person);
|
|||
|
||||
乱码问题这个很容易就可以复现,我们只需要将上面提到的 `FileInputStream` 代码示例中的 `input.txt` 文件内容改为中文即可,原代码不需要改动。
|
||||
|
||||

|
||||

|
||||
|
||||
输出:
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ try (FileReader fileReader = new FileReader("input.txt");) {
|
|||
|
||||
`input.txt` 文件内容:
|
||||
|
||||

|
||||

|
||||
|
||||
输出:
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ try (Writer output = new FileWriter("output.txt")) {
|
|||
|
||||
输出结果:
|
||||
|
||||

|
||||

|
||||
|
||||
## 字节缓冲流
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ System.out.println("读取之前的偏移量:" + randomAccessFile.getFilePoint
|
|||
|
||||
`input.txt` 文件内容:
|
||||
|
||||

|
||||

|
||||
|
||||
输出:
|
||||
|
||||
|
|
@ -535,10 +535,10 @@ randomAccessFile.write(new byte[]{'H', 'I', 'J', 'K'});
|
|||
|
||||
`RandomAccessFile` 可以帮助我们合并文件分片,示例代码如下:
|
||||
|
||||

|
||||

|
||||
|
||||
我在[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中详细介绍了大文件的上传问题。
|
||||
|
||||

|
||||

|
||||
|
||||
`RandomAccessFile` 的实现依赖于 `FileDescriptor` (文件描述符) 和 `FileChannel` (内存映射文件)。
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ I/O(**I**nput/**O**utpu) 即**输入/输出** 。
|
|||
|
||||
根据冯.诺依曼结构,计算机结构分为 5 大部分:运算器、控制器、存储器、输入设备、输出设备。
|
||||
|
||||

|
||||

|
||||
|
||||
输入设备(比如键盘)和输出设备(比如显示器)都属于外部设备。网卡、硬盘这种既可以属于输入设备,也可以属于输出设备。
|
||||
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ ClassFile {
|
|||
|
||||
通过分析 `ClassFile` 的内容,我们便可以知道 class 文件的组成。
|
||||
|
||||

|
||||

|
||||
|
||||
下面这张图是通过 IDEA 插件 `jclasslib` 查看的,你可以更直观看到 Class 文件结构。
|
||||
|
||||

|
||||

|
||||
|
||||
使用 `jclasslib` 不光可以直观地查看某个类对应的字节码文件,还可以查看类的基本信息、常量池、接口、属性、函数等信息。
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ Java 类的继承关系由类索引、父类索引和接口索引集合三项确
|
|||
|
||||
**字段的 access_flag 的取值:**
|
||||
|
||||

|
||||

|
||||
|
||||
### 方法表集合(Methods)
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ Class 文件存储格式中对方法的描述与对字段的描述几乎采用
|
|||
|
||||
**方法表的 access_flag 取值:**
|
||||
|
||||

|
||||

|
||||
|
||||
注意:因为`volatile`修饰符和`transient`修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了`synchronized`、`native`、`abstract`等关键字修饰方法,所以也就多了这些关键字对应的标志。
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ tag:
|
|||
|
||||
这 7 个阶段的顺序如下图所示:
|
||||
|
||||

|
||||

|
||||
|
||||
## 类加载过程
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ tag:
|
|||
|
||||
系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。
|
||||
|
||||

|
||||

|
||||
|
||||
详见 [Java Virtual Machine Specification - 5.3. Creation and Loading](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.3 "Java Virtual Machine Specification - 5.3. Creation and Loading")。
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ tag:
|
|||
3. 字节码验证(程序语义检查)
|
||||
4. 符号引用验证(类的正确性检查)
|
||||
|
||||

|
||||

|
||||
|
||||
文件格式验证这一阶段是基于该类的二进制字节流进行的,主要目的是保证输入的字节流能正确地解析并存储于方法区之内,格式上符合描述一个 Java 类型信息的要求。除了这一阶段之外,其余三个验证阶段都是基于方法区的存储结构上进行的,不会再直接读取、操作字节流了。
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ tag:
|
|||
|
||||
《深入理解 Java 虚拟机》7.34 节第三版对符号引用和直接引用的解释如下:
|
||||
|
||||

|
||||

|
||||
|
||||
举个例子:在程序执行方法时,系统需要明确知道这个方法所在的位置。Java 虚拟机为每个类都准备了一张方法表来存放类中所有的方法。当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法了。通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue