1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-08-14 05:21:42 +08:00

Compare commits

...

42 Commits

Author SHA1 Message Date
Guide
9d9b55a2ae Merge branch 'main' of github.com:Snailclimb/JavaGuide 2023-04-28 21:38:36 +08:00
Guide
818ccbca79 [docs add]程序员简历编写指南 2023-04-28 21:38:12 +08:00
Guide
fcdbe12190
Merge pull request #2001 from Erzbir/main
[docs fix]修正 hashCode() 方法的描述错误
2023-04-28 21:19:55 +08:00
Erzbir
f3754a92d4 [docs fix]修正 hashCode() 方法的描述错误 2023-04-28 20:44:18 +08:00
Guide
72019c2b09 [docs fix]url error 2023-04-28 20:32:33 +08:00
Guide
a19b2744b0
Merge pull request #1999 from Snailclimb/dependabot/npm_and_yarn/d3-color-3.1.0
Bump d3-color from 1.4.1 to 3.1.0
2023-04-28 19:31:11 +08:00
Guide
19cb0cd775
Merge pull request #1998 from Snailclimb/dependabot/npm_and_yarn/json5-2.2.3
Bump json5 from 2.2.1 to 2.2.3
2023-04-28 19:31:00 +08:00
Guide
372cb240ca [docs update]exact small-advertisement.snippet.md 2023-04-28 19:27:56 +08:00
dependabot[bot]
954364882e
Bump d3-color from 1.4.1 to 3.1.0
Bumps [d3-color](https://github.com/d3/d3-color) from 1.4.1 to 3.1.0.
- [Release notes](https://github.com/d3/d3-color/releases)
- [Commits](https://github.com/d3/d3-color/compare/v1.4.1...v3.1.0)

---
updated-dependencies:
- dependency-name: d3-color
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-28 10:44:55 +00:00
dependabot[bot]
3f2471340c
Bump json5 from 2.2.1 to 2.2.3
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-28 10:44:55 +00:00
Guide
0d8c0c0fb3
Merge pull request #1997 from Mister-Hope/ci
ci: add test workflow
2023-04-28 18:43:57 +08:00
Guide
f3c36f2916
Merge pull request #1996 from Mister-Hope/font-size
docs: update font-size
2023-04-28 18:43:17 +08:00
Guide
5678155022
Merge pull request #1995 from Mister-Hope/docs
docs: update docs
2023-04-28 18:42:56 +08:00
Mr.Hope
ef93bec410 ci: add test workflow 2023-04-28 18:00:51 +08:00
Mr.Hope
d993af3421 feat: add @ alias for include 2023-04-28 17:56:30 +08:00
Mr.Hope
76b220540b chore: pin deps 2023-04-28 17:53:18 +08:00
Mr.Hope
a13c531f35 chore: add husky and nano-staged 2023-04-28 17:52:53 +08:00
Mr.Hope
881bc5c591 Merge branch 'main' into docs 2023-04-28 17:50:47 +08:00
Mr.Hope
22e3ef1efc docs: add planet snippet 2023-04-28 17:48:34 +08:00
Mr.Hope
9153648dba chore: tweaks 2023-04-28 17:37:42 +08:00
Mr.Hope
4df51f86e9 docs: add linter 2023-04-28 17:35:43 +08:00
Mr.Hope
6bdc809e2f docs: add linter 2023-04-28 17:31:44 +08:00
Mr.Hope
72c52dba3e docs: update font-size 2023-04-28 17:21:21 +08:00
Mr.Hope
893c673f1c chore: update 2023-04-28 17:18:52 +08:00
Mr.Hope
2975f2f244 chore: update 2023-04-28 17:15:49 +08:00
Guide
a788fc300d [docs feat]format specification 2023-04-28 17:15:47 +08:00
Mr.Hope
7f877f8e5f docs: update docs 2023-04-28 17:12:53 +08:00
Guide
8f8d7c102a
Merge pull request #1994 from Mister-Hope/docs
chore: tweaks
2023-04-28 17:09:34 +08:00
Mr.Hope
cf9e96aa6c chore: tweaks 2023-04-28 17:02:11 +08:00
Guide
566c75d5a4
Merge pull request #1993 from Mister-Hope/update
feat: update deps and switch to pnpm
2023-04-28 16:27:35 +08:00
Guide
675d97ce1b
Merge pull request #1990 from Mister-Hope/readme
docs: update readme
2023-04-28 16:27:13 +08:00
Mr.Hope
fac0c7698d feat: add atom and rss feed 2023-04-28 16:22:41 +08:00
Mr.Hope
be1b2f46ce chore: remove iconfont 2023-04-28 16:19:18 +08:00
Mr.Hope
be6c1faa03 chore: update scripts 2023-04-28 16:18:11 +08:00
Mr.Hope
7703240ba3 feat: update deps and use pnpm 2023-04-28 16:17:44 +08:00
Mr.Hope
638181bf70 chore: rm en readme 2023-04-28 16:05:59 +08:00
Mr.Hope
44e5cfa5d2 docs: fix readme align 2023-04-28 16:05:09 +08:00
Mr.Hope
e5d5c357b3 docs: fix broken links in en readme 2023-04-28 16:04:04 +08:00
Guide
db776f0fd2 Delete README.en.md 2023-04-28 16:03:28 +08:00
Guide
dff5130082
Merge pull request #1989 from Mister-Hope/readme
docs: update readme
2023-04-28 15:59:15 +08:00
Mr.Hope
8f2cc4b8b2 docs: update readme 2023-04-28 15:56:23 +08:00
Guide
bc083f989c [docs update]完善Java基础常见面试题总结(上),添加一些代码示例 2023-04-28 15:44:41 +08:00
265 changed files with 35352 additions and 3255 deletions

29
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Docs Test
on:
- push
- pull_request
jobs:
test-docs:
name: Test docs
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
run_install: true
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: pnpm
- name: Build test
env:
NODE_OPTIONS: --max_old_space_size=4096
run: pnpm docs:build

13
.gitignore vendored
View File

@ -1,15 +1,14 @@
/node_modules node_modules/
/package-lock.json
# *.drawio # *.drawio
*.drawio.bkp *.drawio.bkp
.DS_Store .DS_Store
# VS Code Config file # VS Code Config file
.vscode/ .vscode/
# Vuepress Cache # VuePress Cache
.cache/ **/.vuepress/.cache/
# Vuepress Temp # VuePress Temp
.temp/ **/.vuepress/.temp/
# Vuepress Output # VuePress Output
dist/ dist/
# Build files # Build files
packages/*/lib/ packages/*/lib/

4
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm nano-staged

20
.markdownlint.json Normal file
View File

@ -0,0 +1,20 @@
{
"default": true,
"MD003": {
"style": "atx"
},
"MD004": {
"style": "dash"
},
"MD013": false,
"MD024": {
"allow_different_nesting": true
},
"MD035": {
"style": "---"
},
"MD040": false,
"MD045": false,
"MD046": false,
"MD049": false
}

4
.markdownlintignore Normal file
View File

@ -0,0 +1,4 @@
**/node_modules/**
# markdown snippets
*.snippet.md

15
.prettierignore Normal file
View File

@ -0,0 +1,15 @@
# Vuepress Cache
**/.vuepress/.cache/**
# Vuepress Temp
**/.vuepress/.temp/**
# Vuepress Output
dist/
# Node modules
node_modules/
# pnpm lock file
pnpm-lock.yaml
index.html
sw.js

View File

@ -1,375 +0,0 @@
<p style="text-align:center">
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
<img src="https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png" width=""/>
</a>
</p>
<p style="text-align:center">
<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>
<h3 style="text-align:center">Recommended</h3>
<table>
<tbody>
<tr>
<td style="text-align:center" valign="middle">
<a href="https://sourl.cn/e7ee87">
<img src="https://oss.javaguide.cn/xingqiu/xingqiu.png" style="margin: 0 auto;width:850px" /></a>
</td>
</tr>
</tbody>
</table>
## Java
### Basis
**Knowledge points/interview questions**: (Must see:+1: ):
- [Java Basics Knowledge Points/Interview Questions Summary(1)](docs/java/basis/java-basic-questions-01.md)
- [Java Basics Knowledge Points/Interview Questions Summary(2)](docs/java/basis/java-basic-questions-01.md)
- [Java Basics Knowledge Points/Interview Questions Summary(3)](docs/java/basis/java-basic-questions-01.md)
**Important Knowledge Points Explained:**
- [Why only value passing in Java?](docs/java/basis/why-thereis-only-value-passing-in-java.md)
- [What is the reflection mechanism? What are the application scenarios of reflection mechanism?](docs/java/basis/反射机制详解.md)
- (docs/java/basis/proxy-model-detail.md) [proxy-model-detail: static proxy + JDK/CGLIB dynamic proxy practice](docs/java/basis/代理模式详解.md)
- [What are the common IO models and what is the difference between BIO, NIO, AIO in Java?](docs/java/basis/io模型详解.md)
- [BigDecimal solve floating point problem](docs/java/basis/bigdecimal.md)
### Collection
1. **[Java collection FAQ summary](docs/java/collection/java集合框架基础知识&面试题总结.md)** (must see :+1:)
2. [Summary of considerations for using Java containers](docs/java/collection/java集合使用注意事项.md)
3. **source code analysis** : [ArrayList source code + expansion mechanism analysis](docs/java/collection/arraylist-source-code.md),
[HashMap(JDK1.8) source code + underlying data structure analysis](docs/java/collection/ hashmap-source-code.md),
[ConcurrentHashMap source code + underlying data structure analysis](docs/java/collection/concurrent-hash-map-source-code.md)
### Concurrency
**Knowledge/Interview Questions:** (Must see :+1:)
1. **[Java concurrency basic common interview questions summary](docs/java/concurrent/java并发基础常见面试题总结.md)**
2. **[Java concurrency advanced common interview questions summary](docs/java/concurrent/java并发进阶常见面试题总结.md)**
**Important Knowledge Points Explained:**
1. **Thread pool**: [Java thread pool learning summary](./docs/java/concurrent/java-thread-pool-summary.md), [Java thread pooling best practices](./docs/java/concurrent/java-thread-pool-best-practices.md)
2. [ThreadLocal keyword resolution](docs/java/concurrent/threadlocal.md)
3. [Java concurrency container summary](docs/java/concurrent/java-concurrent-collections.md)
4. [Atomic atomic class summary](docs/java/concurrent/atomic-classes.md)
5. [AQS principle and AQS synchronization component summary](docs/java/concurrent/aqs.md)
6. [Getting Started with CompletableFuture](docs/java/concurrent/completablefuture-intro.md)
### JVM (must see :+1:)
This part of JVM mainly refers to [JVM Virtual Machine Specification-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) and Mr. Zhou's [In-depth Understanding of Java Virtual Machine (3rd Edition)](https://book.douban.com/subject/34907497/) (Highly recommended to read more than once!) .
1. **[Java Memory Regions](https://javaguide.cn/java/jvm/jvm-garbage-collection/)**
2. **[JVM Garbage Collection](https://javaguide.cn/java/jvm/jvm-garbage-collection/)**
3. [JDK monitoring and troubleshooting tools](https://javaguide.cn/java/jvm/jdk-monitoring-and-troubleshooting-tools/)
4. [Class file structure](https://javaguide.cn/java/jvm/class-file-structure/)
5. **[Class loading process](https://javaguide.cn/java/jvm/class-loading-process/)**
6. [Class loader](https://javaguide.cn/java/jvm/classloader/)
7. **[[To be completed] Summary of the most important JVM parameters (half of the translation is perfected)](https://javaguide.cn/java/jvm/jvm-parameters-intro/)**
8. **[[Extra Meal] The Big White Word takes you through the JVM](https://javaguide.cn/java/jvm/jvm-intro/)**
### New features
1. **Java 8**: [Java 8 new features summary](docs/java/new-features/Java8新特性总结.md), [Java8 common new features summary](docs/java/new-features/java8-common-new-features.md)
2. **Java9~Java15** : [An article to take you through the important new features of JDK9~15!](./docs/java/new-features/java新特性总结.md)
### Tips
1. [JAD decompile](docs/java/tips/JAD反编译tricks.md)
2. [Handy for locating common Java performance problems](./docs/java/tips/locate-performance-problems/手把手教你定位常见Java性能问题.md)
## Computer Basics
👉 **[Illustrated Computer Fundamentals PDF Download](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100021725&idx=1&sn=2db9664ca25363139a81691043e9fd8f&chksm=4ea19a1679d61300d8990f7e43bfc7f476577a81b712cf0f9c6f6552a8b219bc081efddb5c54#rd)** .
### Operating system
1. [OS FAQ summary!](docs/cs-basics/operating-system/操作系统常见面试题&知识点总结.md)
2. [Backend programmer essential Linux basics summary](docs/cs-basics/operating-system/linux-intro.md)
3. [Introduction to Shell Programming](docs/cs-basics/operating-system/shell-intro.md)
### Networking
1. [Computer Network Common Interview Questions](docs/cs-basics/network/计算机网络常见面试题.md)
2. [Xie Xiren teacher's "computer network" content summary](docs/cs-basics/network/谢希仁老师的《计算机网络》内容总结.md)
### Data Structures
**Diagrammatic Data Structures :**
1. [Linear data structure :array, chain table, stack, queue](docs/cs-basics/data-structure/线性数据结构.md)
2. [diagram](docs/cs-basics/data-structure/图.md)
3. [heap](docs/cs-basics/data-structure/堆.md)
4. [tree](docs/cs-basics/data-structure/树.md) : focus on [red-black-tree](docs/cs-basics/data-structure/红黑树.md), B-, B+, B* tree, LSM tree
Other common data structures : 1.
1. [Bloom filter](docs/cs-basics/data-structure/bloom-filter.md)
### Algorithm
This part of the algorithm is very important, if you do not know how to learn the algorithm, you can look at what I wrote.
- [Recommended Algorithm Learning Books + Resources](https://www.zhihu.com/question/323359308/answer/1545320858) 。
- [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
**Summary of common algorithm problems** :
- [Several Common String Algorithm Questions Summarized ](docs/cs-basics/algorithms/几道常见的字符串算法题.md)
- [Summary of several common algorithm problems of the chain table ](docs/cs-basics/algorithms/几道常见的链表算法题.md)
- [Link offer some programming questions](docs/cs-basics/algorithms/剑指offer部分编程题.md)
In addition[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) This site summarizes the common algorithms, which are more comprehensive and systematic.
## Database
### MySQL
**Summary:**
1. [Database Basics Summary](docs/database/数据库基础知识.md)
2. **[MySQL Knowledge Summary](docs/database/mysql/mysql知识点&面试题总结.md)** (Must see:+1:)
5. [MySQL High Performance Optimization Specification Recommendations](docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md)
**Important knowledge points:**
1. [Transaction isolation level (graphic detail)](docs/database/mysql/transaction-isolation-level.md)
2. [MySQL's Three Major Logs (binlog, redo log and undo log) Explained](docs/database/mysql/mysql-logs.md)
3. [InnoDB storage engine implementation of MVCC](docs/database/mysql/innodb-implementation-of-mvcc.md)
4. [How does a SQL statement get executed in MySQL?](docs/database/mysql/how-sql-executed-in-mysql.md)
5. [Character set details: Why is it not recommended to use utf8 in MySQL?](docs/database/字符集.md)
6. [A little thought on how to store time in the database](docs/database/mysql/some-thoughts-on-database-storage-time.md)
### Redis
1. [Redis FAQ Summary](docs/database/redis/redis-questions-01.md)
2. [3 common cache read and write strategies](docs/database/redis/3-commonly-used-cache-read-and-write-strategies.md)
## Search Engine
It is used to improve search efficiency and functions similarly to browser search engines. The more common search engines are Elasticsearch (recommended) and Solr.
## System design
### System design essential foundation
#### RESTful API
When we do back-end development, our main job is to provide APIs for front-end or other back-end services such as APIs for querying user data. a RESTful API is an API built on REST, and it is an API designed to be better used.
Related reading: [RestFul API Brief Tutorial](docs/system-design/basis/RESTfulAPI.md)
#### Name
During programming, you must pay attention to naming. Because a good naming is a comment, others will know what your variable, method or class does as soon as they see your naming!
Read more about: [Java Naming](docs/system-design/naming.md) 。
### Common frameworks
If you have not touched Java Web development, you can first look at my summary of [J2EE Basics](docs/system-design/J2EE基础知识.md). Although much of the content in this article is now obsolete, it will give you a deeper understanding of Java backend technology development.
#### Spring/SpringBoot (must see :+1:)
**Knowledge/Interview Questions:**
1. **[Spring FAQ Summary](docs/system-design/framework/spring/Spring常见问题总结.md)**
2. **[SpringBoot Getting Started Guide](https://github.com/Snailclimb/springboot-guide)**
**Important Knowledge Points Explained:** 1.
1. **[Spring/Spring Boot common annotations summary! Arrangement!](./docs/system-design/framework/spring/Spring&SpringBoot常用注解总结.md)**
2. **[Spring Transaction Summary](docs/system-design/framework/spring/Spring事务总结.md)**
3. [What design patterns are used in Spring?](docs/system-design/framework/spring/Spring设计模式总结.md)
4. **[SpringBoot auto-assembly principle?"](docs/system-design/framework/spring/SpringBoot自动装配原理.md)**
#### MyBatis
[MyBatis Common Interview Questions Summary](docs/system-design/framework/mybatis/mybatis-interview.md)
### Security
#### Certification Authorization
**[Fundamentals of Certification Authorization](docs/system-design/security/basis-of-authority-certification.md)** In this article I will introduce the common concepts of authentication and authorization: **Authentication**, **Authorization** and **Cookie**, **Session**, Token, **OAuth 2**, **SSO**. If you are not clear about these concepts, we suggest you read this article properly.
- **JWT** : JWT (JSON Web Token) is a form of authentication, where a JWT is essentially a signed piece of data in JSON format. Since it is signed, the recipient can verify its authenticity. Related reading.
- [JWT Pros and Cons Analysis and Solutions to Common Problems](docs/system-design/security/jwt优缺点分析以及常见问题解决方案.md)
- [Demo for beginners to get started with Spring Security With JWT](https://github.com/Snailclimb/spring-security-jwt-guide)
- **SSO(Single Sign On)**: **SSO(Single Sign On)** that is, single sign on means that a user has the right to access other systems related to him/her by logging into one of the multiple subsystems. For example, after we logged into Jingdong Finance, we also successfully logged into Jingdong Supermarket, Jingdong Home Appliances and other subsystems of Jingdong. Related reading: [**SSO Single Sign-On is enough to read this article! **](docs/system-design/security/sso-intro.md)
#### Data Desensitization
Data desensitization means that we deform sensitive information data according to specific rules, for example, we replace certain digits of cell phone numbers and ID numbers with *.
### Timed tasks
Recently, some friends asked about timing task related issues. So, I simply wrote an article to summarize some concepts of timed tasks and some common timed task technology options: ["Java Timed Tasks Revealed"].(./docs/system-design/定时任务.md)
## Distributed
### CAP theory and BASE theory
CAP is also the combination of the initials Consistency, Availability, and Partition Tolerance.
**BASE** is an acronym for **Basically Available**, **Soft-state**, and **Eventually Consistent**. The BASE theory is the result of a trade-off between consistency and availability in the CAP, and is derived from a summary of distributed practices for large-scale Internet systems, evolving from the CAP theorem, which significantly reduces our system requirements.
Related reading: [CAP Theory and BASE Theory Explained](docs/distributed-system/theorem&algorithm&protocol/cap&base-theorem.md)
### Paxos algorithm and Raft algorithm
The **Paxos algorithm** was born in 1990 as a classical algorithm for solving the consistency of distributed systems. However, since the Paxos algorithm was very difficult to understand and implement, there were continuous attempts to simplify it. Only in 2013 was a distributed consistency algorithm born that is easier to understand and implement than the Paxos algorithm - the **Raft algorithm**.
### RPC
RPC makes calling remote service calls as easy as calling local methods.
Dubbo is a home-grown RPC framework , open source by Ali . Related reading.
- [Dubbo FAQ Summary](docs/distributed-system/rpc/dubbo.md)
### API gateway
Gateways are mainly used for request forwarding, security authentication, protocol conversion, and disaster recovery.
Related reading.
- [Why gateways? What common gateway systems do you know of?](docs/distributed-system/api-gateway.md)
- [Design and Implementation of Shepherd, a 10 Billion Dollar API Gateway Service](https://tech.meituan.com/2021/05/20/shepherd-api-gateway.html)
### Distributed IDs
In complex distributed systems, a large amount of data and messages often need to be uniquely identified. For example, after the data volume is too large, it is often necessary to split the data into libraries and tables, and after the splitting of the libraries and tables, a unique ID is needed to identify a piece of data or a message, and the self-incrementing ID of the database obviously cannot meet the demand. Related reading: [Why distributed id? What are the distributed id generation solutions?](docs/distributed-system/distributed-id.md)
### Distributed transactions
** A distributed transaction is one in which the participants of the transaction, the server supporting the transaction, the resource server, and the transaction manager are located on different nodes of different distributed systems. **
Simply put, a large operation consists of different small operations that are distributed across different servers and belong to different applications, and the distributed transaction needs to guarantee that all of these small operations either succeed or fail. Essentially, distributed transactions are about ensuring data consistency across different databases.
### Distributed Orchestration
**ZooKeeper**.
> The first two articles may have content overlapping parts, we recommend reading them both.
1. [[Getting Started] Summary of ZooKeeper-related concepts](docs/distributed-system/分布式协调/zookeeper/zookeeper-intro.md)
2. [[Advanced] Summary of ZooKeeper Related Concepts](docs/distributed-system/分布式协调/zookeeper/zookeeper-plus.md)
3. [[Hands-on] ZooKeeper hands-on](docs/distributed-system/分布式协调/zookeeper/zookeeper-in-action.md)
## High performance
### Message Queues
Message queues are used in distributed systems primarily for decoupling and peak shaving. Related reading: [Message Queues FAQ Summary](docs/high-performance/message-queue/message-queue.md)。
1. **RabbitMQ** : [Getting Started with RabbitMQ](docs/high-performance/message-queue/rabbitmq-intro.md)
2. **RocketMQ** : [Getting Started with RocketMQ](docs/high-performance/message-queue/rocketmq-intro)、[A few simple questions and answers for RocketMQ](docs/high-performance/message-queue/rocketmq-questions.md)
3. **Kafka** : [Kafka FAQ Summary](docs/high-performance/message-queue/kafka知识点&面试题总结.md)
### Read-write separation & split database and split table
Read-write separation is mainly to separate the database read and write operations on different database nodes. The master server is responsible for writes and the slave server is responsible for reads. Alternatively, one master and one slave or one master and multiple slaves can be used.
Read-write separation can substantially improve read performance and marginally improve write performance. Therefore, read-write separation is more suitable for scenarios where there are more concurrent read requests from a single machine.
Library and table separation is to solve the problem of continuous database performance degradation due to the excessive amount of library and table data.
Common library and table splitting tools are: `sharding-jdbc` (Dangdang), `TSharding` (Mushroom Street), `MyCAT` (based on Cobar), `Cobar` (Alibaba).... We recommend using `sharding-jdbc`. Because, `sharding-jdbc` is a lightweight `Java` framework, served as a `jar` package, no extra O&M work for us, and good compatibility.
Related reading: [read-write separation & sharding summary of common problems](docs/high-performance/读写分离&分库分表.md)
### Load Balancing
Load balancing systems are often used to distribute tasks such as user request processing to multiple servers to improve the performance and reliability of a website, application or database.
Common load balancing systems include 3 types.
1. **DNS load balancing**: generally used to achieve geographic level balancing.
2. **Hardware Load Balancing**: Load balancing is achieved through a separate hardware device such as F5 (hardware is usually expensive).
3. **Software load balancing**: Load balancing is achieved by load balancing software such as Nginx.
## High Availability
Highly available describes a system that is available most of the time and can provide services to us. High availability means that the system is available even in the event of a hardware failure or system upgrade.
Related reading: **"[How to design a highly available system? What are the areas to consider?](docs/high-availability/高可用系统设计.md)》** 。
### Flow limiting
Flow limiting considers how to respond to system failures from the perspective of user access pressure.
The purpose of flow limiting is to limit the frequency of requests received by the server-side interface to prevent the service from hanging. For example, if an interface is limited to 100 requests per second, requests that exceed the limit are either dropped or placed in a queue for processing. Limiting the flow can effectively deal with the excessive number of burst requests. Related reading: [What is flow limiting? What are the flow limiting algorithms?](docs/high-availability/limit-request.md)
### Downgrading
Downgrading is the consideration of how to respond to system failures from the perspective of system functional priorities.
Service degradation refers to the strategic downgrading of some services and pages based on the current business situation and traffic when the server is under pressure, in order to free up server resources to ensure the normal operation of core tasks.
### Meltdown
Meltdown and degradation are two concepts that are easily confused and do not have the same meaning.
Downgrades are intended to deal with failures of the system itself, while meltdowns are intended to deal with failures of external systems or third-party systems on which the current system depends.
### Queuing
An alternative type of flow limitation, analogous to real-world queuing. If you've played League of Legends, you'll know that every time there's an event, you have to go through a queue to get into the game.
### Clustering
Deploy multiple copies of the same service to avoid single points of failure.
### Timeout and retry mechanism
** Once a user's request goes beyond a certain time without a response, the request is ended and an exception is thrown. ** Failure to set a timeout may result in slow response times, or even a buildup of requests that prevents the system from processing them.
In addition, the number of retries is generally set to 3. More retries will not be beneficial, but will add pressure to the server (some scenarios may not be suitable to use the failure retry mechanism).
### Disaster recovery design and offsite multi-live
**Disaster recovery** = disaster recovery + backup.
- **Backup** : Backup several copies of all important data generated by the system.
- **Disaster Tolerant** : Create two identical systems in offsite locations. When the system in one place suddenly hangs, the whole application system can be switched to the other one so that the system can provide services normally.
**Offsite Multi-Live** describes the deployment of services offsite and the simultaneous provisioning of services to the outside world. The main difference from traditional disaster recovery design is "multi-live", i.e., all sites are providing services to the public at the same time. Off-site multiplication is designed to deal with unexpected situations such as fires, earthquakes, and other natural or perceived disasters.
Related reading.
- [Read this article to understand off-site multi-live](https://mp.weixin.qq.com/s/T6mMDdtTfBuIiEowCpqu6Q)
- [Four steps to build offsite multi-live](https://mp.weixin.qq.com/s/hMD-IS__4JE5_nQhYPYSTg)
- ["Learning Architecture from Scratch" - 28 | Guarantees for Highly Available Business: Offsite Multi-Live Architecture](http://gk.link/a/10pKZ)
## About the Author
- [Personal Introduction Q & A](https://javaguide.cn/about-the-author/)
- [I used to be an Internet addict too](https://javaguide.cn/about-the-author/internet-addiction-teenager/)
- [Feelings after one month of onboarding](https://javaguide.cn/about-the-author/feelings-after-one-month-of-induction-training/)
- [Feelings from graduation to six months of employment](https://javaguide.cn/about-the-author/feelings-of-half-a-year-from-graduation-to-entry/)
- [A training institution stole my article into a video also on the B station popular](https://javaguide.cn/about-the-author/my-article-was-stolen-and-made-into-video-and-it-became-popular/)
## Public
If you want to follow my updated articles and the dry goods I share in real time, you can follow my public number.
**《Java Interview Blitz》:** A PDF version of "Java Interview Blitz" derived from this document specifically for interviews [Public](#公众号) Reply back to **"Interview Blitz "** and get it for free!
<div align="center">
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
</div>
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a2d826918a44bcbaa8d9272db3ad7d2~tplv-k3u1fbpfcp-watermark.image)

142
README.md
View File

@ -1,46 +1,39 @@
推荐你通过在线阅读网站进行阅读,体验更好,速度更快! 推荐你通过在线阅读网站进行阅读,体验更好,速度更快!
* **[JavaGuide 在线阅读网站(新版,推荐👍)](https://javaguide.cn/)** - **[JavaGuide 在线阅读网站(新版,推荐 👍)](https://javaguide.cn/)**
* [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/) - [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/)
[<img src="https://oss.javaguide.cn/xingqiu/xingqiu.png" style="width:850px;margin: 0 auto" />](https://sourl.cn/e7ee87)
<div align="center"> <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>
[![logo](https://oss.javaguide.cn/github/javaguide/csdn/1c00413c65d1995993bf2b0daf7b4f03.png)](https://github.com/Snailclimb/JavaGuide)
[![阅读](https://img.shields.io/badge/阅读-read-brightgreen.svg)](https://javaguide.cn/)
![Stars](https://img.shields.io/github/stars/Snailclimb/JavaGuide)
![forks](https://img.shields.io/github/forks/Snailclimb/JavaGuide)
![issues](https://img.shields.io/github/issues/Snailclimb/JavaGuide)
[GitHub](https://github.com/Snailclimb/JavaGuide) | [Gitee](https://gitee.com/SnailClimb/JavaGuide)
</div>
> 1. **面试专版** :准备面试的小伙伴可以考虑面试专版:[《Java 面试指北 》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) (质量很高,专为面试打造,配合 JavaGuide 食用)。 > 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)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。 > 1. **知识星球** :专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入 [JavaGuide 知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。
> 2. **转载须知** 以下所有文章如非文首说明为转载皆为我Guide 哥)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境! > 1. **转载须知** 以下所有文章如非文首说明为转载皆为我Guide的原创转载在文首注明出处如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
<div align="center"> <div align="center">
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" /> <img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
</div> </div>
<!-- #region home -->
## 项目相关 ## 项目相关
* [项目介绍](./docs/javaguide/intro.md) - [项目介绍](./docs/javaguide/intro.md)
* [贡献指南](./docs/javaguide/contribution-guideline.md) - [贡献指南](./docs/javaguide/contribution-guideline.md)
* [常见问题](./docs/javaguide/faq.md) - [常见问题](./docs/javaguide/faq.md)
* [项目待办](./docs/javaguide/todo.md) - [项目待办](./docs/javaguide/todo.md)
## Java ## Java
@ -74,15 +67,15 @@
**源码分析** **源码分析**
* [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md) - [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md)
* [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md) - [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md)
* [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md) - [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md)
### IO ### IO
* [IO 基础知识总结](./docs/java/io/io-basis.md) - [IO 基础知识总结](./docs/java/io/io-basis.md)
* [IO 设计模式总结](./docs/java/io/io-design-patterns.md) - [IO 设计模式总结](./docs/java/io/io-design-patterns.md)
* [IO 模型详解](./docs/java/io/io-model.md) - [IO 模型详解](./docs/java/io/io-model.md)
### 并发 ### 并发
@ -100,11 +93,11 @@
- [Java 并发容器总结](./docs/java/concurrent/java-concurrent-collections.md) - [Java 并发容器总结](./docs/java/concurrent/java-concurrent-collections.md)
- [Atomic 原子类总结](./docs/java/concurrent/atomic-classes.md) - [Atomic 原子类总结](./docs/java/concurrent/atomic-classes.md)
- [AQS 详解](./docs/java/concurrent/aqs.md) - [AQS 详解](./docs/java/concurrent/aqs.md)
- [CompletableFuture详解](./docs/java/concurrent/completablefuture-intro.md) - [CompletableFuture 详解](./docs/java/concurrent/completablefuture-intro.md)
### JVM (必看 :+1:) ### JVM (必看 :+1:)
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机第3版》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。 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)** - **[Java 内存区域](./docs/java/jvm/memory-area.md)**
- **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)** - **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)**
@ -117,7 +110,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 新特性 ### 新特性
- **Java 8** [Java 8 新特性总结(翻译)](./docs/java/new-features/java8-tutorial-translate.md)、[Java8常用新特性总结](./docs/java/new-features/java8-common-new-features.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 9 新特性概览](./docs/java/new-features/java9.md)
- [Java 10 新特性概览](./docs/java/new-features/java10.md) - [Java 10 新特性概览](./docs/java/new-features/java10.md)
- [Java 11 新特性概览](./docs/java/new-features/java11.md) - [Java 11 新特性概览](./docs/java/new-features/java11.md)
@ -148,10 +141,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**重要知识点详解** **重要知识点详解**
- [OSI 和 TCP/IP 网络分层模型详解(基础)](./docs/cs-basics/network/osi&tcp-ip-model.md) - [OSI 和 TCP/IP 网络分层模型详解(基础)](./docs/cs-basics/network/osi-and-tcp-ip-model.md)
- [应用层常见协议总结(应用层)](./docs/cs-basics/network/application-layer-protocol.md) - [应用层常见协议总结(应用层)](./docs/cs-basics/network/application-layer-protocol.md)
- [HTTP vs HTTPS应用层](./docs/cs-basics/network/http&https.md) - [HTTP vs HTTPS应用层](./docs/cs-basics/network/http-vs-https.md)
- [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0&http1.1.md) - [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0-vs-http1.1.md)
- [HTTP 常见状态码(应用层)](./docs/cs-basics/network/http-status-codes.md) - [HTTP 常见状态码(应用层)](./docs/cs-basics/network/http-status-codes.md)
- [DNS 域名系统详解(应用层)](./docs/cs-basics/network/dns.md) - [DNS 域名系统详解(应用层)](./docs/cs-basics/network/dns.md)
- [TCP 三次握手和四次挥手(传输层)](./docs/cs-basics/network/tcp-connection-and-disconnection.md) - [TCP 三次握手和四次挥手(传输层)](./docs/cs-basics/network/tcp-connection-and-disconnection.md)
@ -166,7 +159,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
- [线性数据结构 :数组、链表、栈、队列](./docs/cs-basics/data-structure/linear-data-structure.md) - [线性数据结构 :数组、链表、栈、队列](./docs/cs-basics/data-structure/linear-data-structure.md)
- [](./docs/cs-basics/data-structure/graph.md) - [](./docs/cs-basics/data-structure/graph.md)
- [](./docs/cs-basics/data-structure/heap.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/tree.md) :重点关注[红黑树](./docs/cs-basics/data-structure/red-black-tree.md)、B-B+B\*树、LSM
其他常用数据结构 其他常用数据结构
@ -176,17 +169,17 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
算法这部分内容非常重要,如果你不知道如何学习算法的话,可以看下我写的: 算法这部分内容非常重要,如果你不知道如何学习算法的话,可以看下我写的:
* [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。 - [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。
* [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374) - [如何刷 Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
**常见算法问题总结** **常见算法问题总结**
* [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md) - [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md)
* [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md) - [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
* [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md) - [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
* [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md) - [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md)
另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。 另外,[GeeksforGeeks](https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
## 数据库 ## 数据库
@ -196,9 +189,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
- [NoSQL 基础知识总结](./docs/database/nosql.md) - [NoSQL 基础知识总结](./docs/database/nosql.md)
- [字符集详解](./docs/database/character-set.md) - [字符集详解](./docs/database/character-set.md)
- SQL : - SQL :
- [SQL语法基础知识总结](./docs/database/sql/sql-syntax-summary.md) - [SQL 语法基础知识总结](./docs/database/sql/sql-syntax-summary.md)
- [SQL常见面试题总结](./docs/database/sql/sql-questions-01.md) - [SQL 常见面试题总结](./docs/database/sql/sql-questions-01.md)
### MySQL ### MySQL
@ -209,14 +201,14 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**重要知识点:** **重要知识点:**
- [MySQL索引详解](./docs/database/mysql/mysql-index.md) - [MySQL 索引详解](./docs/database/mysql/mysql-index.md)
- [MySQL事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md) - [MySQL 事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md)
- [MySQL三大日志(binlog、redo log和undo log)详解](./docs/database/mysql/mysql-logs.md) - [MySQL 三大日志(binlog、redo log undo log)详解](./docs/database/mysql/mysql-logs.md)
- [InnoDB 存储引擎对 MVCC 的实现](./docs/database/mysql/innodb-implementation-of-mvcc.md) - [InnoDB 存储引擎对 MVCC 的实现](./docs/database/mysql/innodb-implementation-of-mvcc.md)
- [SQL 语句在 MySQL 中的执行过程](./docs/database/mysql/how-sql-executed-in-mysql.md) - [SQL 语句在 MySQL 中的执行过程](./docs/database/mysql/how-sql-executed-in-mysql.md)
- [MySQL 查询缓存详解](./docs/database/mysql/mysql-query-cache.md) - [MySQL 查询缓存详解](./docs/database/mysql/mysql-query-cache.md)
- [MySQL执行计划分析](./docs/database/mysql/mysql-query-execution-plan.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/mysql-auto-increment-primary-key-continuous.md)
- [MySQL 时间类型数据存储建议](./docs/database/mysql/some-thoughts-on-database-storage-time.md) - [MySQL 时间类型数据存储建议](./docs/database/mysql/some-thoughts-on-database-storage-time.md)
- [MySQL 隐式转换造成索引失效](./docs/database/mysql/index-invalidation-caused-by-implicit-conversion.md) - [MySQL 隐式转换造成索引失效](./docs/database/mysql/index-invalidation-caused-by-implicit-conversion.md)
@ -229,7 +221,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**重要知识点:** **重要知识点:**
- [3种常用的缓存读写策略详解](./docs/database/redis/3-commonly-used-cache-read-and-write-strategies.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 5 种基本数据结构详解](./docs/database/redis/redis-data-structures-01.md)
- [Redis 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.md) - [Redis 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.md)
- [Redis 持久化机制详解](./docs/database/redis/redis-persistence.md) - [Redis 持久化机制详解](./docs/database/redis/redis-persistence.md)
@ -244,7 +236,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
## 搜索引擎 ## 搜索引擎
[Elasticsearch常见面试题总结(付费)](./docs/database/elasticsearch/elasticsearch-questions-01.md) [Elasticsearch 常见面试题总结(付费)](./docs/database/elasticsearch/elasticsearch-questions-01.md)
![JavaGuide 官方公众号](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png) ![JavaGuide 官方公众号](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png)
@ -260,13 +252,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### Docker ### Docker
* [Docker 核心概念总结](./docs/tools/docker/docker-intro.md) - [Docker 核心概念总结](./docs/tools/docker/docker-intro.md)
* [Docker 实战](./docs/tools/docker/docker-in-action.md) - [Docker 实战](./docs/tools/docker/docker-in-action.md)
### Git ### Git
* [Git 核心概念总结](./docs/tools/git/git-intro.md) - [Git 核心概念总结](./docs/tools/git/git-intro.md)
* [Github 实用小技巧总结](./docs/tools/git/github-tips.md) - [Github 实用小技巧总结](./docs/tools/git/github-tips.md)
## 系统设计 ## 系统设计
@ -308,14 +300,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
- [认证授权基础概念详解](./docs/system-design/security/basis-of-authority-certification.md) - [认证授权基础概念详解](./docs/system-design/security/basis-of-authority-certification.md)
- [JWT 基础概念详解](./docs/system-design/security/jwt-intro.md) - [JWT 基础概念详解](./docs/system-design/security/jwt-intro.md)
- [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages&disadvantages-of-jwt.md) - [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages-and-disadvantages-of-jwt.md)
- [SSO 单点登录详解](./docs/system-design/security/sso-intro.md) - [SSO 单点登录详解](./docs/system-design/security/sso-intro.md)
- [权限系统设计详解](./docs/system-design/security/design-of-authority-system.md) - [权限系统设计详解](./docs/system-design/security/design-of-authority-system.md)
#### 数据脱敏 #### 数据脱敏
数据脱敏说的就是我们根据特定的规则对敏感信息数据进行变形,比如我们把手机号、身份证号某些位数使用 * 来代替。 数据脱敏说的就是我们根据特定的规则对敏感信息数据进行变形,比如我们把手机号、身份证号某些位数使用 \* 来代替。
#### 敏感词过滤 #### 敏感词过滤
@ -333,10 +324,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 理论&算法&协议 ### 理论&算法&协议
- [CAP 理论和 BASE 理论详解](./docs/distributed-system/theorem&algorithm&protocol/cap&base-theorem.md) - [CAP 理论和 BASE 理论详解](./docs/distributed-system/protocol/cap-and-base-theorem.md)
- [Paxos 算法详解](./docs/distributed-system/theorem&algorithm&protocol/paxos-algorithm.md) - [Paxos 算法详解](./docs/distributed-system/protocol/paxos-algorithm.md)
- [Raft 算法详解](./docs/distributed-system/theorem&algorithm&protocol/raft-algorithm.md) - [Raft 算法详解](./docs/distributed-system/protocol/raft-algorithm.md)
- [Gossip 协议详解](./docs/distributed-system/theorem&algorithm&protocol/gossip-protocl.md) - [Gossip 协议详解](./docs/distributed-system/protocol/gossip-protocl.md)
### API 网关 ### API 网关
@ -360,8 +351,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### RPC ### RPC
* [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md) - [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md)
* [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md) - [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md)
### ZooKeeper ### ZooKeeper
@ -411,7 +402,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 降级&熔断 ### 降级&熔断
[降级&熔断详解](./docs/high-availability/fallback&circuit-breaker.md) [降级&熔断详解](./docs/high-availability/fallback-and-circuit-breaker.md)
### 超时&重试 ### 超时&重试
@ -425,14 +416,14 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**灾备** = 容灾+备份。 **灾备** = 容灾+备份。
* **备份** 将系统所产生的的所有重要数据多备份几份。 - **备份** 将系统所产生的的所有重要数据多备份几份。
* **容灾** 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。 - **容灾** 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
**异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。 **异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。
## Star 趋势 ## Star 趋势
![](https://api.star-history.com/svg?repos=Snailclimb/JavaGuide&type=Date) ![Stars](https://api.star-history.com/svg?repos=Snailclimb/JavaGuide&type=Date)
## 公众号 ## 公众号
@ -440,3 +431,4 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
![JavaGuide 官方公众号](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png) ![JavaGuide 官方公众号](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png)
<!-- #endregion home -->

View File

@ -1,14 +1,15 @@
import { defineUserConfig } from "vuepress"; import { defineUserConfig } from "vuepress";
import { themeConfig } from "./themeConfig"; import { searchProPlugin } from "vuepress-plugin-search-pro";
import { searchPlugin } from "@vuepress/plugin-search";
import theme from "./theme.js";
export default defineUserConfig({ export default defineUserConfig({
dest: "./dist", dest: "./dist",
theme: themeConfig,
shouldPrefetch: false,
title: "JavaGuide(Java面试+学习指南)", title: "JavaGuide(Java面试+学习指南)",
description: description:
"「Java学习指北+Java面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,复习 Java 知识点,首选 JavaGuide ", "「Java学习指北+Java面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,复习 Java 知识点,首选 JavaGuide ",
head: [ head: [
// meta // meta
["meta", { name: "robots", content: "all" }], ["meta", { name: "robots", content: "all" }],
@ -43,28 +44,20 @@ export default defineUserConfig({
s.parentNode.insertBefore(hm, s); s.parentNode.insertBefore(hm, s);
})();`, })();`,
], ],
["link", { rel: "stylesheet", href: "/iconfont/iconfont.css" }],
["link", { rel: "icon", href: "/favicon.ico" }], ["link", { rel: "icon", href: "/favicon.ico" }],
], ],
locales: { locales: {
"/": { "/": {
lang: "zh-CN", lang: "zh-CN",
}, },
}, },
plugins: [
searchPlugin({ theme,
// https://v2.vuepress.vuejs.org/zh/reference/plugin/search.html
// 排除首页 plugins: [searchProPlugin({ indexContent: true })],
isSearchable: (page) => page.path !== "/",
maxSuggestions: 10, pagePatterns: ["**/*.md", "!*.snippet.md", "!.vuepress", "!node_modules"],
hotKeys: ["s", "/"],
// 用于在页面的搜索索引中添加额外字段 shouldPrefetch: false,
getExtraFields: () => [],
locales: {
"/": {
placeholder: "搜索",
},
},
}),
],
}); });

View File

@ -1,10 +1,19 @@
import { navbar } from "vuepress-theme-hope"; import { navbar } from "vuepress-theme-hope";
export const navbarConfig = navbar([ export default navbar([
{ text: "面试指南", icon: "java", link: "/home.md" }, { text: "面试指南", icon: "java", link: "/home.md" },
{
text: "知识星球",
icon: "code",
link: "/about-the-author/zhishixingqiu-two-years.md",
},
{ text: "开源项目", icon: "github", link: "/open-source-project/" }, { text: "开源项目", icon: "github", link: "/open-source-project/" },
{ text: "技术书籍", icon: "book", link: "/books/" }, { text: "技术书籍", icon: "book", link: "/books/" },
{ text: "程序人生", icon: "article", link: "/high-quality-technical-articles/" }, {
text: "程序人生",
icon: "article",
link: "/high-quality-technical-articles/",
},
{ {
text: "网站相关", text: "网站相关",
icon: "about", icon: "about",

View File

@ -1,223 +0,0 @@
@font-face {
font-family: "iconfont"; /* Project id 2922463 */
src: url('iconfont.woff2?t=1660530571134') format('woff2'),
url('iconfont.woff?t=1660530571134') format('woff'),
url('iconfont.ttf?t=1660530571134') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-history:before {
content: "\e752";
}
.icon-experience:before {
content: "\e72b";
}
.icon-code:before {
content: "\e7fc";
}
.icon-interview:before {
content: "\e65d";
}
.icon-about:before {
content: "\e6e5";
}
.icon-search:before {
content: "\e7de";
}
.icon-featured:before {
content: "\e633";
}
.icon-codelibrary-fill:before {
content: "\e84b";
}
.icon-tool:before {
content: "\e70c";
}
.icon-highavailable:before {
content: "\ea23";
}
.icon-big-data:before {
content: "\e632";
}
.icon-work:before {
content: "\e8d7";
}
.icon-project:before {
content: "\e702";
}
.icon-article:before {
content: "\e672";
}
.icon-a-MachineLearning:before {
content: "\e617";
}
.icon-github:before {
content: "\e673";
}
.icon-rss:before {
content: "\e768";
}
.icon-mianshi:before {
content: "\e614";
}
.icon-et-performance:before {
content: "\e623";
}
.icon-virtual_machine:before {
content: "\e73f";
}
.icon-basic:before {
content: "\e67b";
}
.icon-container:before {
content: "\e641";
}
.icon-MQ:before {
content: "\e684";
}
.icon-redis:before {
content: "\e619";
}
.icon-mysql:before {
content: "\e613";
}
.icon-recommend:before {
content: "\e639";
}
.icon-chat:before {
content: "\e66a";
}
.icon-tips:before {
content: "\e62a";
}
.icon-chajian1:before {
content: "\e69d";
}
.icon-star:before {
content: "\e61d";
}
.icon-docker1:before {
content: "\e659";
}
.icon-zuozhe:before {
content: "\e688";
}
.icon-pdf:before {
content: "\e740";
}
.icon-suanfaku:before {
content: "\e63a";
}
.icon-jichushuju:before {
content: "\e60c";
}
.icon-people-network-full:before {
content: "\e865";
}
.icon-git:before {
content: "\e708";
}
.icon-luxianchaxun:before {
content: "\e622";
}
.icon-computer:before {
content: "\e601";
}
.icon-framework:before {
content: "\e69e";
}
.icon-Tools:before {
content: "\ed5f";
}
.icon-xitongsheji:before {
content: "\e63e";
}
.icon-database:before {
content: "\e8e4";
}
.icon-security-fill:before {
content: "\e78b";
}
.icon-docker:before {
content: "\e616";
}
.icon-java:before {
content: "\e6e0";
}
.icon-book:before {
content: "\e7c7";
}
.icon-network:before {
content: "\e67a";
}
.icon-caozuoxitong:before {
content: "\e686";
}
.icon-gaojixiaozuzhibeifen:before {
content: "\e756";
}
.icon-distributed-network:before {
content: "\e8d5";
}
.icon-intellijidea:before {
content: "\ebd1";
}

View File

@ -1,8 +1,10 @@
export const aboutTheAuthor = [ import { arraySidebar } from "vuepress-theme-hope";
export const aboutTheAuthor = arraySidebar([
{ {
text: "个人经历", text: "个人经历",
icon: "zuozhe", icon: "zuozhe",
collapsable: false, collapsible: false,
children: [ children: [
"internet-addiction-teenager", "internet-addiction-teenager",
"my-college-life", "my-college-life",
@ -14,7 +16,7 @@ export const aboutTheAuthor = [
{ {
text: "杂谈", text: "杂谈",
icon: "chat", icon: "chat",
collapsable: false, collapsible: false,
children: [ children: [
"writing-technology-blog-six-years", "writing-technology-blog-six-years",
"my-article-was-stolen-and-made-into-video-and-it-became-popular", "my-article-was-stolen-and-made-into-video-and-it-became-popular",
@ -22,4 +24,4 @@ export const aboutTheAuthor = [
"zhishixingqiu-two-years", "zhishixingqiu-two-years",
], ],
}, },
]; ]);

View File

@ -1,4 +1,6 @@
export const books = [ import { arraySidebar } from "vuepress-theme-hope";
export const books = arraySidebar([
{ {
text: "计算机基础", text: "计算机基础",
link: "cs-basics", link: "cs-basics",
@ -30,4 +32,4 @@ export const books = [
link: "distributed-system", link: "distributed-system",
icon: "distributed-network", icon: "distributed-network",
}, },
]; ]);

View File

@ -1,9 +1,11 @@
export const highQualityTechnicalArticles = [ import { arraySidebar } from "vuepress-theme-hope";
export const highQualityTechnicalArticles = arraySidebar([
{ {
text: "练级攻略", text: "练级攻略",
icon: "et-performance", icon: "et-performance",
prefix: "advanced-programmer/", prefix: "advanced-programmer/",
collapsable: false, collapsible: false,
children: [ children: [
"the-growth-strategy-of-the-technological-giant", "the-growth-strategy-of-the-technological-giant",
"seven-tips-for-becoming-an-advanced-programmer", "seven-tips-for-becoming-an-advanced-programmer",
@ -14,10 +16,10 @@ export const highQualityTechnicalArticles = [
text: "个人经历", text: "个人经历",
icon: "experience", icon: "experience",
prefix: "personal-experience/", prefix: "personal-experience/",
collapsable: false, collapsible: false,
children: [ children: [
"four-year-work-in-tencent-summary", "four-year-work-in-tencent-summary",
"two-years-of-back-end-develop--experience-in-didi&toutiao", "two-years-of-back-end-develop--experience-in-didi-and-toutiao",
"8-years-programmer-work-summary", "8-years-programmer-work-summary",
"huawei-od-275-days", "huawei-od-275-days",
], ],
@ -26,7 +28,7 @@ export const highQualityTechnicalArticles = [
text: "程序员", text: "程序员",
icon: "code", icon: "code",
prefix: "programmer/", prefix: "programmer/",
collapsable: false, collapsible: false,
children: [ children: [
"how-do-programmers-publish-a-technical-book", "how-do-programmers-publish-a-technical-book",
"efficient-book-publishing-and-practice-guide", "efficient-book-publishing-and-practice-guide",
@ -36,7 +38,7 @@ export const highQualityTechnicalArticles = [
text: "面试", text: "面试",
icon: "interview", icon: "interview",
prefix: "interview/", prefix: "interview/",
collapsable: false, collapsible: false,
children: [ children: [
"the-experience-of-get-offer-from-over-20-big-companies", "the-experience-of-get-offer-from-over-20-big-companies",
"the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer", "the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer",
@ -52,10 +54,10 @@ export const highQualityTechnicalArticles = [
text: "工作", text: "工作",
icon: "work", icon: "work",
prefix: "work/", prefix: "work/",
collapsable: false, collapsible: false,
children: [ children: [
"get-into-work-mode-quickly-when-you-join-a-company", "get-into-work-mode-quickly-when-you-join-a-company",
"employee-performance", "employee-performance",
], ],
}, },
]; ]);

View File

@ -1,10 +1,11 @@
import { sidebar } from "vuepress-theme-hope"; import { sidebar } from "vuepress-theme-hope";
import { highQualityTechnicalArticles } from "./sidebar/high-quality-technical-articles";
import { aboutTheAuthor } from "./sidebar/about-the-author";
import { books } from "./sidebar/books";
import { openSourceProject } from "./sidebar/open-source-project";
export const sidebarConfig = sidebar({ import { aboutTheAuthor } from "./about-the-author.js";
import { books } from "./books.js";
import { highQualityTechnicalArticles } from "./high-quality-technical-articles.js";
import { openSourceProject } from "./open-source-project.js";
export default sidebar({
// 应该把更精确的路径放置在前边 // 应该把更精确的路径放置在前边
"/open-source-project/": openSourceProject, "/open-source-project/": openSourceProject,
"/books/": books, "/books/": books,
@ -25,6 +26,7 @@ export const sidebarConfig = sidebar({
prefix: "interview-preparation/", prefix: "interview-preparation/",
children: [ children: [
"teach-you-how-to-prepare-for-the-interview-hand-in-hand", "teach-you-how-to-prepare-for-the-interview-hand-in-hand",
"resume-guide",
"key-points-of-interview", "key-points-of-interview",
"project-experience-guide", "project-experience-guide",
"interview-experience", "interview-experience",
@ -173,10 +175,10 @@ export const sidebarConfig = sidebar({
icon: "star", icon: "star",
collapsible: true, collapsible: true,
children: [ children: [
"osi&tcp-ip-model", "osi-and-tcp-ip-model",
"application-layer-protocol", "application-layer-protocol",
"http&https", "http-vs-https",
"http1.0&http1.1", "http1.0-vs-http1.1",
"http-status-codes", "http-status-codes",
"dns", "dns",
"tcp-connection-and-disconnection", "tcp-connection-and-disconnection",
@ -198,10 +200,7 @@ export const sidebarConfig = sidebar({
text: "Linux", text: "Linux",
collapsible: true, collapsible: true,
icon: "linux", icon: "linux",
children: [ children: ["linux-intro", "shell-intro"],
"linux-intro",
"shell-intro",
],
}, },
], ],
}, },
@ -420,7 +419,7 @@ export const sidebarConfig = sidebar({
children: [ children: [
"basis-of-authority-certification", "basis-of-authority-certification",
"jwt-intro", "jwt-intro",
"advantages&disadvantages-of-jwt", "advantages-and-disadvantages-of-jwt",
"sso-intro", "sso-intro",
"design-of-authority-system", "design-of-authority-system",
"sentive-words-filter", "sentive-words-filter",
@ -442,9 +441,9 @@ export const sidebarConfig = sidebar({
{ {
text: "理论&算法&协议", text: "理论&算法&协议",
icon: "suanfaku", icon: "suanfaku",
prefix: "theorem&algorithm&protocol/", prefix: "protocol/",
children: [ children: [
"cap&base-theorem", "cap-and-base-theorem",
"paxos-algorithm", "paxos-algorithm",
"raft-algorithm", "raft-algorithm",
"gossip-protocl", "gossip-protocl",
@ -510,7 +509,7 @@ export const sidebarConfig = sidebar({
"high-availability-system-design", "high-availability-system-design",
"redundancy", "redundancy",
"limit-request", "limit-request",
"fallback&circuit-breaker", "fallback-and-circuit-breaker",
"timeout-and-retry", "timeout-and-retry",
"performance-test", "performance-test",
], ],

View File

@ -1,4 +1,6 @@
export const openSourceProject = [ import { arraySidebar } from "vuepress-theme-hope";
export const openSourceProject = arraySidebar([
{ {
text: "技术教程", text: "技术教程",
link: "tutorial", link: "tutorial",
@ -34,4 +36,4 @@ export const openSourceProject = [
link: "big-data", link: "big-data",
icon: "big-data", icon: "big-data",
}, },
]; ]);

View File

@ -0,0 +1,5 @@
body {
@media (min-width: 1440px) {
font-size: 16px;
}
}

View File

@ -1,4 +1,3 @@
$theme-color: #2980B9; $theme-color: #2980b9;
$sidebar-width: 20rem; // $sidebar-width: 20rem;
$sidebar-mobile-width: 16rem; // $sidebar-mobile-width: 16rem;
$content-width: 60em;

View File

@ -1,19 +1,31 @@
import { getDirname, path } from "@vuepress/utils";
import { hopeTheme } from "vuepress-theme-hope"; import { hopeTheme } from "vuepress-theme-hope";
import { navbarConfig } from "./navbar";
import { sidebarConfig } from "./sidebar";
export const themeConfig = hopeTheme({ import navbar from "./navbar.js";
import sidebar from "./sidebar/index.js";
const __dirname = getDirname(import.meta.url);
export default hopeTheme({
logo: "/logo.png", logo: "/logo.png",
hostname: "https://javaguide.cn/", hostname: "https://javaguide.cn/",
iconAssets: "//at.alicdn.com/t/c/font_2922463_9aayheyb3v7.css",
author: { author: {
name: "Guide", name: "Guide",
url: "https://javaguide.cn/article/", url: "https://javaguide.cn/article/",
}, },
repo: "https://github.com/Snailclimb/JavaGuide", repo: "https://github.com/Snailclimb/JavaGuide",
docsDir: "docs", docsDir: "docs",
iconAssets: "//at.alicdn.com/t/c/font_2922463_9aayheyb3v7.css",
navbar: navbarConfig, navbar,
sidebar: sidebarConfig, sidebar,
footer:
'<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
displayFooter: true,
pageInfo: [ pageInfo: [
"Author", "Author",
"Category", "Category",
@ -23,6 +35,7 @@ export const themeConfig = hopeTheme({
"Word", "Word",
"ReadingTime", "ReadingTime",
], ],
blog: { blog: {
intro: "/about-the-author/", intro: "/about-the-author/",
sidebarDisplay: "mobile", sidebarDisplay: "mobile",
@ -32,19 +45,33 @@ export const themeConfig = hopeTheme({
Gitee: "https://gitee.com/SnailClimb", Gitee: "https://gitee.com/SnailClimb",
}, },
}, },
footer:
'<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
displayFooter: true,
plugins: { plugins: {
blog: true, blog: true,
copyright: true, copyright: true,
mdEnhance: { mdEnhance: {
align: true,
codetabs: true, codetabs: true,
container: true, container: true,
figure: true,
include: {
resolvePath: (file, cwd) => {
if (file.startsWith("@"))
return path.resolve(
__dirname,
"../snippets",
file.replace("@", "./")
);
return path.resolve(cwd, file);
},
},
tasklist: true, tasklist: true,
}, },
feed: { feed: {
atom: true,
json: true, json: true,
rss: true,
}, },
}, },
}); });

View File

@ -7,18 +7,18 @@ tag:
不知不觉已经入职一个多月了,在入职之前我没有在某个公司实习过或者工作过,所以很多东西刚入职工作的我来说还是比较新颖的。学校到职场的转变,带来了角色的转变,其中的差别因人而异。对我而言,在学校的时候课堂上老师课堂上教的东西,自己会根据自己的兴趣选择性接受,甚至很多课程你不想去上的话,还可以逃掉。到了公司就不一样了,公司要求你会的技能你不得不学,除非你不想干了。在学校的时候大部分人编程的目的都是为了通过考试或者找到一份好工作,真正靠自己兴趣支撑起来的很少,到了工作岗位之后我们编程更多的是因为工作的要求,相比于学校的来说会一般会更有挑战而且压力更大。在学校的时候,我们最重要的就是对自己负责,我们不断学习知识去武装自己,但是到了公司之后我们不光要对自己负责,更要对公司负责,毕竟公司出钱请你过来,不是让你一直 on beach 的。 不知不觉已经入职一个多月了,在入职之前我没有在某个公司实习过或者工作过,所以很多东西刚入职工作的我来说还是比较新颖的。学校到职场的转变,带来了角色的转变,其中的差别因人而异。对我而言,在学校的时候课堂上老师课堂上教的东西,自己会根据自己的兴趣选择性接受,甚至很多课程你不想去上的话,还可以逃掉。到了公司就不一样了,公司要求你会的技能你不得不学,除非你不想干了。在学校的时候大部分人编程的目的都是为了通过考试或者找到一份好工作,真正靠自己兴趣支撑起来的很少,到了工作岗位之后我们编程更多的是因为工作的要求,相比于学校的来说会一般会更有挑战而且压力更大。在学校的时候,我们最重要的就是对自己负责,我们不断学习知识去武装自己,但是到了公司之后我们不光要对自己负责,更要对公司负责,毕竟公司出钱请你过来,不是让你一直 on beach 的。
刚来公司的时候,因为公司要求,我换上了 Mac 电脑。由于之前一直用的是 Windows 系统,所以非常不习惯。刚开始用 Mac 系统的时候笨手笨脚,自己会很明显的感觉自己的编程效率降低了至少 3 成。当时内心还是挺不爽的,心里也总是抱怨为什么不直接用 Windows 系统或者 Linux 系统。不过也挺奇怪,大概一个星期之后,自己就开始慢慢适应使用 Mac 进行编程,甚至非常喜欢。我这里不想对比 Mac 和 Windows 编程体验哪一个更好,我觉得还是因人而异,相同价位的 Mac 的配置相比于 Windows确实要被甩几条街。不过 Mac 的编程和使用体验确实不错,当然你也可以选择使用 Linux 进行日常开发,相信一定很不错。 另外Mac 不能玩一些主流网络游戏,对于一些克制不住自己想玩游戏的朋友是一个不错的选择。 刚来公司的时候,因为公司要求,我换上了 Mac 电脑。由于之前一直用的是 Windows 系统,所以非常不习惯。刚开始用 Mac 系统的时候笨手笨脚,自己会很明显的感觉自己的编程效率降低了至少 3 成。当时内心还是挺不爽的,心里也总是抱怨为什么不直接用 Windows 系统或者 Linux 系统。不过也挺奇怪,大概一个星期之后,自己就开始慢慢适应使用 Mac 进行编程,甚至非常喜欢。我这里不想对比 Mac 和 Windows 编程体验哪一个更好,我觉得还是因人而异,相同价位的 Mac 的配置相比于 Windows 确实要被甩几条街。不过 Mac 的编程和使用体验确实不错,当然你也可以选择使用 Linux 进行日常开发,相信一定很不错。 另外Mac 不能玩一些主流网络游戏,对于一些克制不住自己想玩游戏的朋友是一个不错的选择。
不得不说 ThoughtWorks 的培训机制还是很不错的。应届生入职之后一般都会安排培训与往年不同的是今年的培训多了中国本地班TWU-C。作为本地班的第一期学员说句心里话还是很不错。8周的培训除了工作需要用到的基本技术比如ES6、SpringBoot等等之外还会增加一些新员工基本技能的培训比如如何高效开会、如何给别人正确的提 Feedback、如何对代码进行重构、如何进行 TDD 等等。培训期间不定期的有活动比如Weekend Trip、 City Tour、Cake time等等。最后三周还会有一个实际的模拟项目这个项目基本和我们正式工作的实际项目差不多我个人感觉很不错。目前这个项目已经正式完成了一个迭代我觉得在做项目的过程中收获最大的不是项目中使用的技术而是如何进行团队合作、如何正确使用 Git 团队协同开发、一个完成的迭代是什么样子的、做项目的过程中可能遇到那些问题、一个项目运作的完整流程等等。 不得不说 ThoughtWorks 的培训机制还是很不错的。应届生入职之后一般都会安排培训与往年不同的是今年的培训多了中国本地班TWU-C。作为本地班的第一期学员说句心里话还是很不错。8 周的培训,除了工作需要用到的基本技术比如 ES6、SpringBoot 等等之外,还会增加一些新员工基本技能的培训比如如何高效开会、如何给别人正确的提 Feedback、如何对代码进行重构、如何进行 TDD 等等。培训期间不定期的有活动,比如 Weekend Trip、 City Tour、Cake time 等等。最后三周还会有一个实际的模拟项目,这个项目基本和我们正式工作的实际项目差不多,我个人感觉很不错。目前这个项目已经正式完成了一个迭代,我觉得在做项目的过程中,收获最大的不是项目中使用的技术,而是如何进行团队合作、如何正确使用 Git 团队协同开发、一个完成的迭代是什么样子的、做项目的过程中可能遇到那些问题、一个项目运作的完整流程等等。
ThoughtWorks 非常提倡分享、提倡帮助他人成长,这一点在公司的这段时间深有感触。培训期间,我们每个人会有一个 Trainer 负责Trainer 就是日常带我们上课和做项目的同事,一个 Trainer 大概会负责5-6个人。Trainer不定期都会给我们最近表现的 Feedback( 反馈) 我个人觉得这个并不是这是走走形式Trainer 们都很负责,很多时候都是在下班之后找我们聊天。同事们也都很热心,如果你遇到问题,向别人询问,其他人如果知道的话一般都会毫无保留的告诉你,如果遇到大部分都不懂的问题,甚至会组织一次技术 Session 分享。上周五我在我们小组内进行了一次关于 Feign 远程调用的技术分享,因为 team 里面大家对这部分知识都不太熟悉,但是后面的项目进展大概率会用到这部分知识。我刚好研究了这部分内容,所以就分享给了组内的其他同事,以便于项目更好的进行。 ThoughtWorks 非常提倡分享、提倡帮助他人成长,这一点在公司的这段时间深有感触。培训期间,我们每个人会有一个 Trainer 负责Trainer 就是日常带我们上课和做项目的同事,一个 Trainer 大概会负责 5-6 个人。Trainer 不定期都会给我们最近表现的 Feedback( 反馈) 我个人觉得这个并不是这是走走形式Trainer 们都很负责,很多时候都是在下班之后找我们聊天。同事们也都很热心,如果你遇到问题,向别人询问,其他人如果知道的话一般都会毫无保留的告诉你,如果遇到大部分都不懂的问题,甚至会组织一次技术 Session 分享。上周五我在我们小组内进行了一次关于 Feign 远程调用的技术分享,因为 team 里面大家对这部分知识都不太熟悉,但是后面的项目进展大概率会用到这部分知识。我刚好研究了这部分内容,所以就分享给了组内的其他同事,以便于项目更好的进行。
另外ThoughtWorks 也是一家非常提倡 Feedback( 反馈) 文化的公司,反馈是告诉人们我们对他们的表现的看法以及他们应该如何更好地做到这一点。刚开始我并没有太在意,慢慢地自己确实感觉到正确的进行反馈对他人会有很大的帮助。因为人在做很多事情的时候,会很难发现别人很容易看到的一些小问题。就比如一个很有趣的现象一样,假如我们在做项目的时候没有测试这个角色,如果你完成了自己的模块,并且自己对这个模块测试了很多遍,你发现已经没啥问题了。但是,到了实际使用的时候会很大概率出现你之前从来没有注意的问题。解释这个问题的说法是:每个人的视野或多或少都是有盲点的,这与我们的关注点息息相关。对于自己做的东西,很多地方自己测试很多遍都不会发现,但是如果让其他人帮你进行测试的话,就很大可能会发现很多显而易见的问题。 另外ThoughtWorks 也是一家非常提倡 Feedback( 反馈) 文化的公司,反馈是告诉人们我们对他们的表现的看法以及他们应该如何更好地做到这一点。刚开始我并没有太在意,慢慢地自己确实感觉到正确的进行反馈对他人会有很大的帮助。因为人在做很多事情的时候,会很难发现别人很容易看到的一些小问题。就比如一个很有趣的现象一样,假如我们在做项目的时候没有测试这个角色,如果你完成了自己的模块,并且自己对这个模块测试了很多遍,你发现已经没啥问题了。但是,到了实际使用的时候会很大概率出现你之前从来没有注意的问题。解释这个问题的说法是:每个人的视野或多或少都是有盲点的,这与我们的关注点息息相关。对于自己做的东西,很多地方自己测试很多遍都不会发现,但是如果让其他人帮你进行测试的话,就很大可能会发现很多显而易见的问题。
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/feedback.png) ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/feedback.png)
工作之后,平时更新公众号、专栏还有维护 Github 的时间变少了。实际上,很多时候下班回来后,都有自己的时间来干自己的事情,但是自己也总是找工作太累或者时间比较零散的接口来推掉了。到了今天,翻看 Github 突然发现 14 天前别人在 Github 上给我提的 pr 我还没有处理。这一点确实是自己没有做好的地方,没有合理安排好自己的时间。实际上自己有很多想写的东西,后面会慢慢将他们提上日程。工作之后,更加发现下班后的几个小时如何度过确实很重要 ,如果你觉得自己没有完成好自己白天该做的工作的话,下班后你可以继续忙白天没有忙完的工作,如果白天的工作对于你游刃有余的话,下班回来之后,你大可去干自己感兴趣的事情,学习自己感兴趣的技术。做任何事情都要基于自身的基础,切不可好高骛远。 工作之后,平时更新公众号、专栏还有维护 Github 的时间变少了。实际上,很多时候下班回来后,都有自己的时间来干自己的事情,但是自己也总是找工作太累或者时间比较零散的接口来推掉了。到了今天,翻看 Github 突然发现 14 天前别人在 Github 上给我提的 pr 我还没有处理。这一点确实是自己没有做好的地方,没有合理安排好自己的时间。实际上自己有很多想写的东西,后面会慢慢将他们提上日程。工作之后,更加发现下班后的几个小时如何度过确实很重要 ,如果你觉得自己没有完成好自己白天该做的工作的话,下班后你可以继续忙白天没有忙完的工作,如果白天的工作对于你游刃有余的话,下班回来之后,你大可去干自己感兴趣的事情,学习自己感兴趣的技术。做任何事情都要基于自身的基础,切不可好高骛远。
工作之后身边也会有很多厉害的人,多从他人身上学习我觉得是每个职场人都应该做的。这一届和我们一起培训的同事中,有一些技术很厉害的,也有一些技术虽然不是那么厉害,但是组织能力以及团队协作能力特别厉害的。有一个特别厉害的同事,在我们还在学 SpringBoot 各种语法的时候,他自己利用业余时间写了一个简化版的 SpringBoot ,涵盖了 Spring 的一些常用注解比如 `@RestController``@Autowried``@Pathvairable``@RestquestParam`等等(已经联系这位同事,想让他开源一下,后面会第一时间同步到公众号,期待一下吧!)。我觉得这位同事对于编程是真的有兴趣,他好像从初中就开始接触编程了,对于各种底层知识也非常感兴趣,自己写过实现过很多比较底层的东西。他的梦想是在 Github 上造一个 20k Star 以上的轮子。我相信以这位同事的能力一定会达成目标的,在这里祝福这位同事,希望他可以尽快实现这个目标。 工作之后身边也会有很多厉害的人,多从他人身上学习我觉得是每个职场人都应该做的。这一届和我们一起培训的同事中,有一些技术很厉害的,也有一些技术虽然不是那么厉害,但是组织能力以及团队协作能力特别厉害的。有一个特别厉害的同事,在我们还在学 SpringBoot 各种语法的时候,他自己利用业余时间写了一个简化版的 SpringBoot ,涵盖了 Spring 的一些常用注解比如 `@RestController``@Autowried``@Pathvairable``@RestquestParam`等等(已经联系这位同事,想让他开源一下,后面会第一时间同步到公众号,期待一下吧!)。我觉得这位同事对于编程是真的有兴趣,他好像从初中就开始接触编程了,对于各种底层知识也非常感兴趣,自己写过实现过很多比较底层的东西。他的梦想是在 Github  上造一个 20k Star 以上的轮子。我相信以这位同事的能力一定会达成目标的,在这里祝福这位同事,希望他可以尽快实现这个目标。
这是我入职一个多月之后的个人感受,很多地方都是一带而过,后面我会抽时间分享自己在公司或者业余学到的比较有用的知识给各位,希望看过的人都能有所收获。 这是我入职一个多月之后的个人感受,很多地方都是一带而过,后面我会抽时间分享自己在公司或者业余学到的比较有用的知识给各位,希望看过的人都能有所收获。

View File

@ -31,7 +31,7 @@ tag:
不知道其他公司的程序员是怎么样的?我感觉技术积累很大程度在乎平时,单纯依靠工作绝大部分情况只会加快自己做需求的熟练度,当然,写多了之后或多或少也会提升你对代码质量的认识(前提是你有这个意识)。 不知道其他公司的程序员是怎么样的?我感觉技术积累很大程度在乎平时,单纯依靠工作绝大部分情况只会加快自己做需求的熟练度,当然,写多了之后或多或少也会提升你对代码质量的认识(前提是你有这个意识)。
工作之余,我会利用业余时间来学习自己想学的东西。工作中的例子就是我刚进公司的第一个项目用到了 Spring Security+JWT ,因为当时自己对于这个技术不太了解,然后就在工作之外大概花了一周的时间学习写了一个 Demo 分享了出来,Github 地址https://github.com/Snailclimb/spring-security-jwt-guide 。以次为契机,我还分享了 工作之余,我会利用业余时间来学习自己想学的东西。工作中的例子就是我刚进公司的第一个项目用到了 Spring Security+JWT ,因为当时自己对于这个技术不太了解,然后就在工作之外大概花了一周的时间学习写了一个 Demo 分享了出来,Github 地址:<https://github.com/Snailclimb/spring-security-jwt-guide> 。以次为契机,我还分享了
- [《一问带你区分清楚 Authentication,Authorization 以及 Cookie、Session、Token》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485626&idx=1&sn=3247aa9000693dd692de8a04ccffeec1&chksm=cea24771f9d5ce675ea0203633a95b68bfe412dc6a9d05f22d221161147b76161d1b470d54b3&token=684071313&lang=zh_CN&scene=21#wechat_redirect) - [《一问带你区分清楚 Authentication,Authorization 以及 Cookie、Session、Token》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485626&idx=1&sn=3247aa9000693dd692de8a04ccffeec1&chksm=cea24771f9d5ce675ea0203633a95b68bfe412dc6a9d05f22d221161147b76161d1b470d54b3&token=684071313&lang=zh_CN&scene=21#wechat_redirect)
- [JWT 身份认证优缺点分析以及常见问题解决方案](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485655&idx=1&sn=583eeeb081ea21a8ec6347c72aa223d6&chksm=cea2471cf9d5ce0aa135f2fb9aa32d98ebb3338292beaccc1aae43d1178b16c0125eb4139ca4&token=1737409938&lang=zh_CN#rd) - [JWT 身份认证优缺点分析以及常见问题解决方案](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485655&idx=1&sn=583eeeb081ea21a8ec6347c72aa223d6&chksm=cea2471cf9d5ce0aa135f2fb9aa32d98ebb3338292beaccc1aae43d1178b16c0125eb4139ca4&token=1737409938&lang=zh_CN#rd)

View File

@ -5,7 +5,7 @@ tag:
- 个人经历 - 个人经历
--- ---
2021-03-21晚上12点肝完了我正在做的一个项目的前端的某块功能我随手打开了[我的 Github 主页](https://github.com/Snailclimb)。 2021-03-21晚上 12 点,肝完了我正在做的一个项目的前端的某块功能,我随手打开了[我的 Github 主页](https://github.com/Snailclimb)。
好家伙!几天没注意,[JavaGuide](https://github.com/Snailclimb/JavaGuide) 这个项目直接上了 100K star。 好家伙!几天没注意,[JavaGuide](https://github.com/Snailclimb/JavaGuide) 这个项目直接上了 100K star。
@ -15,7 +15,7 @@ tag:
![](https://oss.javaguide.cn/github/javaguide/about-the-author/20210323132635635.png) ![](https://oss.javaguide.cn/github/javaguide/about-the-author/20210323132635635.png)
维护这个项目的过程中,也被某些人 diss 过“md项目没啥含金量给国人丢脸”。 维护这个项目的过程中,也被某些人 diss 过“md 项目,没啥含金量,给国人丢脸!”。
对于说这类话的人,我觉得对我没啥影响,就持续完善,把 JavaGuide 做的更好吧!其实,国外的很多项目也是纯 MD 啊!就比如外国的朋友发起的 awesome 系列、求职面试系列。无需多说,行动自证!凎! 对于说这类话的人,我觉得对我没啥影响,就持续完善,把 JavaGuide 做的更好吧!其实,国外的很多项目也是纯 MD 啊!就比如外国的朋友发起的 awesome 系列、求职面试系列。无需多说,行动自证!凎!
@ -29,7 +29,7 @@ tag:
![](https://oss.javaguide.cn/github/javaguide/about-the-author/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70.png) ![](https://oss.javaguide.cn/github/javaguide/about-the-author/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70.png)
累计有 **511****issue****575****pr**。所有的 pr 都已经被处理仅有15 个左右的 issue 我还未抽出时间处理。 累计有 **511****issue****575****pr**。所有的 pr 都已经被处理,仅有 15 个左右的 issue 我还未抽出时间处理。
![](https://oss.javaguide.cn/github/javaguide/about-the-author/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70-20230309224044850.png) ![](https://oss.javaguide.cn/github/javaguide/about-the-author/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70-20230309224044850.png)

View File

@ -5,7 +5,7 @@ tag:
- 杂谈 - 杂谈
--- ---
时间回到 2021-02-25我在刷哔哩哔哩的时候发现哔哩哔哩某UP主某培训机构擅自将我在知乎的一个回答做成了视频。 时间回到 2021-02-25我在刷哔哩哔哩的时候发现哔哩哔哩某 UP 主(某培训机构),擅自将我在知乎的一个回答做成了视频。
原滋原味啊!我艹。甚至,连我开头的自我调侃还加上了!真的牛皮! 原滋原味啊!我艹。甚至,连我开头的自我调侃还加上了!真的牛皮!
@ -31,7 +31,7 @@ tag:
其他的视频就不用多看了,是否还是剽窃别人的原创,原封不动地做成视频,大家心里应该有数。 其他的视频就不用多看了,是否还是剽窃别人的原创,原封不动地做成视频,大家心里应该有数。
他们这样做的目的就是一个:**引流到自己的QQ群然后忽悠你买课程。** 他们这样做的目的就是一个:**引流到自己的 QQ 群,然后忽悠你买课程。**
我并不认为是这完全都是培训机构的问题。培训机构的员工为了流量而做这种恶心的事情,也导致了现在这种事情被越来越频繁地发生。 我并不认为是这完全都是培训机构的问题。培训机构的员工为了流量而做这种恶心的事情,也导致了现在这种事情被越来越频繁地发生。

View File

@ -6,7 +6,7 @@ tag:
- 个人经历 - 个人经历
--- ---
> 关于初高中的生活,可以看 2020年我写的[我曾经也是网瘾少年](https://javaguide.cn/about-the-author/internet-addiction-teenager.html)这篇文章。 > 关于初高中的生活,可以看 2020 年我写的[我曾经也是网瘾少年](https://javaguide.cn/about-the-author/internet-addiction-teenager.html)这篇文章。
2019 年 6 月份毕业,距今已经过去了 3 年。趁着高考以及应届生毕业之际,简单聊聊自己的大学生活。 2019 年 6 月份毕业,距今已经过去了 3 年。趁着高考以及应届生毕业之际,简单聊聊自己的大学生活。

View File

@ -3,6 +3,8 @@ title: 个人介绍 Q&A
category: 走近作者 category: 走近作者
--- ---
<!-- @include: @small-advertisement.snippet.md -->
这篇文章我会通过 Q&A 的形式简单介绍一下我自己。 这篇文章我会通过 Q&A 的形式简单介绍一下我自己。
## 我是什么时候毕业的? ## 我是什么时候毕业的?
@ -45,13 +47,13 @@ category: 走近作者
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2020-8/1d38ea3b-da2a-41df-9ac4-087356e9b5b4-20200802185910087.png) ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2020-8/1d38ea3b-da2a-41df-9ac4-087356e9b5b4-20200802185910087.png)
## 为什么自称 Guide ## 为什么自称 Guide
可能是因为我的项目名字叫做 JavaGuide , 所以导致有很多人称呼我为 **Guide哥** 可能是因为我的项目名字叫做 JavaGuide , 所以导致有很多人称呼我为 **Guide哥**
后面,为了读者更方便称呼,我就将自己的笔名改成了 **Guide**。 后面,为了读者更方便称呼,我就将自己的笔名改成了 **Guide**。
我早期写文章用的笔名是 SnailClimb 。很多人不知道这个名字是啥意思给大家拆解一下就清楚了。SnailClimb=Snail蜗牛+Climb(攀登)。我从小就非常喜欢听周杰伦的歌曲,特别是他的《蜗牛》🐌 这首歌曲,另外,当年我高考发挥的算是比较失常,上了大学之后还算是比较“奋青”,所以,我就给自己起的笔名叫做 SnailClimb ,寓意自己要不断向上攀登,嘿嘿😁 我早期写文章用的笔名是 SnailClimb 。很多人不知道这个名字是啥意思给大家拆解一下就清楚了。SnailClimb=Snail蜗牛+Climb(攀登)。我从小就非常喜欢听周杰伦的歌曲,特别是他的《蜗牛》🐌 这首歌曲,另外,当年我高考发挥的算是比较失常,上了大学之后还算是比较“奋青”,所以,我就给自己起的笔名叫做 SnailClimb ,寓意自己要不断向上攀登,嘿嘿 😁
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/37599546f3b34b92a32db579a225aa45~tplv-k3u1fbpfcp-watermark.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/37599546f3b34b92a32db579a225aa45~tplv-k3u1fbpfcp-watermark.image)

View File

@ -122,7 +122,7 @@ tag:
最重要的是一定要重视 Markdown 规范,不然内容再好也会显得不专业。 最重要的是一定要重视 Markdown 规范,不然内容再好也会显得不专业。
Markdown 规范请参考:**https://javaguide.cn/javaguide/contribution-guideline.html** (很重要,尽量按照规范来,对你工作中写文档会非常有帮助) Markdown 规范请参考:**<https://javaguide.cn/javaguide/contribution-guideline.html>** (很重要,尽量按照规范来,对你工作中写文档会非常有帮助)
## 有没有什么写作技巧分享? ## 有没有什么写作技巧分享?

View File

@ -4,6 +4,8 @@ category: 知识星球
star: 2 star: 2
--- ---
<!-- @include: @small-advertisement.snippet.md -->
时间过的真快,知识星球我已经平稳运行了 3 年有余了! 时间过的真快,知识星球我已经平稳运行了 3 年有余了!
在 2019 年 12 月 29 号,经过了大概一年左右的犹豫期,我正式确定要开始做一个自己的星球。 在 2019 年 12 月 29 号,经过了大概一年左右的犹豫期,我正式确定要开始做一个自己的星球。
@ -121,14 +123,18 @@ star: 2
## 如何加入? ## 如何加入?
![](https://oss.javaguide.cn/xingqiu/image-20220311203414600.png) ![知识星球](https://oss.javaguide.cn/xingqiu/image-20220311203414600.png)
如果你想要进知识星球的话建议你添加我的微信guidege666领取一个星球专属优惠券一定要备注“优惠卷”可以优惠 **30** 元,无任何套路,无任何潜在收费项。收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。 你可以扫描上方的二维码原价加入(续费半价)。不过,我更建议你添加我的个人微信领取一个 **30** 元的星球专属优惠券(一定要备注“优惠卷”)。
**无任何套路,无任何潜在收费项。收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。用心做内容,不割韭菜!**
**一定要备注“优惠卷”**,不然通过不了。 **一定要备注“优惠卷”**,不然通过不了。
![个人微信](https://oss.javaguide.cn/xingqiu/weixin-guidege666.jpeg) ![个人微信](https://oss.javaguide.cn/xingqiu/weixin-guidege666.jpeg)
进入星球之后,记得查看[星球使用指南](https://t.zsxq.com/0d18KSarv)(一定要看!) 。
随着时间推移,星球积累的干货资源越来越多,我花在星球上的时间也越来越多,星球的价格会逐步向上调整,想要加入的同学一定要尽早。 随着时间推移,星球积累的干货资源越来越多,我花在星球上的时间也越来越多,星球的价格会逐步向上调整,想要加入的同学一定要尽早。
不过, **一定要确定需要再进** 。并且, **三天之内觉得内容不满意可以全额退款** 不过, **一定要确定需要再进** 。并且, **三天之内觉得内容不满意可以全额退款**

View File

@ -16,13 +16,11 @@ head:
![](https://oscimg.oschina.net/oscnet/up-e113c726a41874ef5fb19f7ac14e38e16ce.png) ![](https://oscimg.oschina.net/oscnet/up-e113c726a41874ef5fb19f7ac14e38e16ce.png)
如果你比较喜欢动手,对于理论知识比较抵触的话,推荐你看看[《如何开发一个简单的数据库》](https://cstack.github.io/db_tutorial/) ,这个 project 会手把手教你编写一个简单的数据库。 如果你比较喜欢动手,对于理论知识比较抵触的话,推荐你看看[《如何开发一个简单的数据库》](https://cstack.github.io/db_tutorial/) ,这个 project 会手把手教你编写一个简单的数据库。
![](https://oscimg.oschina.net/oscnet/up-11de8cb239aa7201cc8d78fa28928b9ec7d.png) ![](https://oscimg.oschina.net/oscnet/up-11de8cb239aa7201cc8d78fa28928b9ec7d.png)
Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍的挺详细的,感兴趣的朋友可以去看看。地址:[https://github.com/alchemystar/Freedom](https://github.com/alchemystar/Freedom) 。 Github 上也已经有大佬用 Java 实现过一个简易的数据库,介绍的挺详细的,感兴趣的朋友可以去看看。地址:[https://github.com/alchemystar/Freedom](https://github.com/alchemystar/Freedom) 。
除了这个用 Java 写的之外,**[db_tutorial](https://github.com/cstack/db_tutorial)** 这个项目是国外的一个大佬用 C 语言写的,朋友们也可以去瞅瞅。 除了这个用 Java 写的之外,**[db_tutorial](https://github.com/cstack/db_tutorial)** 这个项目是国外的一个大佬用 C 语言写的,朋友们也可以去瞅瞅。
@ -44,7 +42,7 @@ Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍
![](https://oss.javaguide.cn/github/javaguide/books/database-system-implementation.png) ![](https://oss.javaguide.cn/github/javaguide/books/database-system-implementation.png)
不管是 MySQL 还是Oracle ,它们总体的架子是差不多的,不同的是其内部的实现比如数据库索引的数据结构、存储引擎的实现方式等等。 不管是 MySQL 还是 Oracle ,它们总体的架子是差不多的,不同的是其内部的实现比如数据库索引的数据结构、存储引擎的实现方式等等。
这本书有些地方还是翻译的比较蹩脚,有能力看英文版的还是建议上手英文版。 这本书有些地方还是翻译的比较蹩脚,有能力看英文版的还是建议上手英文版。

View File

@ -18,9 +18,9 @@ icon: "distributed-network"
![](https://oss.javaguide.cn/github/javaguide/books/image-20220706121952258.png) ![](https://oss.javaguide.cn/github/javaguide/books/image-20220706121952258.png)
作者专门写了一篇文章来介绍这本书的背后的故事感兴趣的小伙伴可以自行查阅https://zhuanlan.zhihu.com/p/487534882 。 作者专门写了一篇文章来介绍这本书的背后的故事,感兴趣的小伙伴可以自行查阅:<https://zhuanlan.zhihu.com/p/487534882>
最后放上这本书的代码仓库和勘误地址https://github.com/tangwz/DistSysDeepDive 。 最后,放上这本书的代码仓库和勘误地址:<https://github.com/tangwz/DistSysDeepDive>
## 《数据密集型应用系统设计》 ## 《数据密集型应用系统设计》
@ -32,7 +32,7 @@ icon: "distributed-network"
书中介绍的大部分概念你可能之前都听过,但是在看了书中的内容之后,你可能会豁然开朗:“哇塞!原来是这样的啊!这不是某技术的原理么?”。 书中介绍的大部分概念你可能之前都听过,但是在看了书中的内容之后,你可能会豁然开朗:“哇塞!原来是这样的啊!这不是某技术的原理么?”。
这本书我之前专门写过知乎回答介绍和推荐,没看过的朋友可以看看:[有哪些你看了以后大呼过瘾的编程书? ](https://www.zhihu.com/question/50408698/answer/2278198495) 。 这本书我之前专门写过知乎回答介绍和推荐,没看过的朋友可以看看:[有哪些你看了以后大呼过瘾的编程书?](https://www.zhihu.com/question/50408698/answer/2278198495) 。
另外,如果你在阅读这本书的时候感觉难度比较大,很多地方读不懂的话,我这里推荐一下《深入理解分布式系统》作者写的[《DDIA 逐章精读》小册](https://ddia.qtmuniao.com)。 另外,如果你在阅读这本书的时候感觉难度比较大,很多地方读不懂的话,我这里推荐一下《深入理解分布式系统》作者写的[《DDIA 逐章精读》小册](https://ddia.qtmuniao.com)。
@ -40,7 +40,7 @@ icon: "distributed-network"
![](https://oss.javaguide.cn/github/javaguide/books/In-depth-understanding-of-distributed-transactions-xiaoyu.png) ![](https://oss.javaguide.cn/github/javaguide/books/In-depth-understanding-of-distributed-transactions-xiaoyu.png)
**[《深入理解分布式事务》](https://book.douban.com/subject/35626925/)** 这本书是的其中一位作者是 Apache ShenYuincubating网关创始人、Hmily、RainCat、Myth等分布式事务框架的创始人。 **[《深入理解分布式事务》](https://book.douban.com/subject/35626925/)** 这本书是的其中一位作者是 Apache ShenYuincubating网关创始人、Hmily、RainCat、Myth 等分布式事务框架的创始人。
学习分布式事务的时候,可以参考一下这本书。虽有一些小错误以及逻辑不通顺的地方,但对于各种分布式事务解决方案的介绍,总体来说还是不错的。 学习分布式事务的时候,可以参考一下这本书。虽有一些小错误以及逻辑不通顺的地方,但对于各种分布式事务解决方案的介绍,总体来说还是不错的。

View File

@ -34,7 +34,7 @@ icon: "java"
我第一次看的时候还觉得有点枯燥,那时候还在上大二,看了 1/3 就没看下去了。 我第一次看的时候还觉得有点枯燥,那时候还在上大二,看了 1/3 就没看下去了。
**[《Java 8实战》](https://book.douban.com/subject/26772632/)** **[《Java 8 实战》](https://book.douban.com/subject/26772632/)**
![《Java 8实战》-豆瓣](https://oss.javaguide.cn/github/javaguide/books/image-20220424103202625.png) ![《Java 8实战》-豆瓣](https://oss.javaguide.cn/github/javaguide/books/image-20220424103202625.png)
@ -64,7 +64,7 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
这本书的质量也是非常过硬!给作者们点个赞!这本书有统一的排版规则和语言风格、清晰的表达方式和逻辑。并且每篇文章初稿写完后,作者们就会互相审校,合并到主分支时所有成员会再次审校,最后再通篇修订了三遍。 这本书的质量也是非常过硬!给作者们点个赞!这本书有统一的排版规则和语言风格、清晰的表达方式和逻辑。并且每篇文章初稿写完后,作者们就会互相审校,合并到主分支时所有成员会再次审校,最后再通篇修订了三遍。
在线阅读:[https://redspider.gitbook.io/concurrent/](https://redspider.gitbook.io/concurrent/ ) 。 在线阅读:[https://redspider.gitbook.io/concurrent/](https://redspider.gitbook.io/concurrent/) 。
**[《Java 并发实现原理JDK 源码剖析》](https://book.douban.com/subject/35013531/)** **[《Java 并发实现原理JDK 源码剖析》](https://book.douban.com/subject/35013531/)**

View File

@ -3,11 +3,7 @@ title: 技术书籍精选
category: 计算机书籍 category: 计算机书籍
--- ---
::: tip 这是一则或许对你有用的小广告 <!-- @include: @small-advertisement.snippet.md -->
👉 欢迎准备 Java 面试以及学习 Java 的同学加入我的[知识星球](./../about-the-author/zhishixingqiu-two-years.md),干货很多!收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。
👉 [《Java 面试指北》](./../zhuanlan/java-mian-shi-zhi-bei.md)持续更新完善中!这是一份教你如何更高效地准备面试的小册,涵盖常见八股文(系统设计、常见框架、分布式、高并发 ......)、优质面经等内容。
:::
精选优质计算机书籍。 精选优质计算机书籍。
@ -18,6 +14,6 @@ category: 计算机书籍
如果内容对你有帮助的话,欢迎给本项目点个 Star。我会用我的业余时间持续完善这份书单感谢 如果内容对你有帮助的话,欢迎给本项目点个 Star。我会用我的业余时间持续完善这份书单感谢
本项目推荐的大部分书籍的 PDF 版本我已经整理到了云盘里,你可以在公众号“**Github掘金计划**” 后台回复“**书籍**”获取到。 本项目推荐的大部分书籍的 PDF 版本我已经整理到了云盘里,你可以在公众号“**Github 掘金计划**” 后台回复“**书籍**”获取到。
![](https://oss.javaguide.cn/github/javaguide/booksimage-20220409153638398.png) ![](https://oss.javaguide.cn/github/javaguide/booksimage-20220409153638398.png)

View File

@ -8,7 +8,7 @@ icon: "search"
Elasticsearch 在 Apache Lucene 的基础上开发而成,学习 ES 之前,建议简单了解一下 Lucene 的相关概念。 Elasticsearch 在 Apache Lucene 的基础上开发而成,学习 ES 之前,建议简单了解一下 Lucene 的相关概念。
**[《Lucene实战》](https://book.douban.com/subject/6440615/)** 是国内为数不多的中文版本讲 Lucene 的书籍,适合用来学习和了解 Lucene 相关的概念和常见操作。 **[《Lucene 实战》](https://book.douban.com/subject/6440615/)** 是国内为数不多的中文版本讲 Lucene 的书籍,适合用来学习和了解 Lucene 相关的概念和常见操作。
![《Lucene实战》-实战](https://oss.javaguide.cn/github/javaguide/books/vAJkdYEyol4e6Nr.png) ![《Lucene实战》-实战](https://oss.javaguide.cn/github/javaguide/books/vAJkdYEyol4e6Nr.png)

View File

@ -127,5 +127,5 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
最后再推荐两个相关的文档: 最后再推荐两个相关的文档:
- **阿里巴巴 Java 开发手册** https://github.com/alibaba/p3c - **阿里巴巴 Java 开发手册** <https://github.com/alibaba/p3c>
- **Google Java 编程风格指南** http://www.hawstein.com/posts/google-java-style.html - **Google Java 编程风格指南** <http://www.hawstein.com/posts/google-java-style.html>

View File

@ -11,7 +11,7 @@ tag:
> Leetcode:给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。 > Leetcode:给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
> >
>你可以假设除了数字 0 之外,这两个数字都不会以零开头。 > 你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例: 示例:
@ -23,11 +23,11 @@ tag:
### 问题分析 ### 问题分析
Leetcode官方详细解答地址 Leetcode 官方详细解答地址:
https://leetcode-cn.com/problems/add-two-numbers/solution/ https://leetcode-cn.com/problems/add-two-numbers/solution/
> 要对头结点进行操作时考虑创建哑节点dummy使用dummy->next表示真正的头节点。这样可以避免处理头节点为空的边界问题。 > 要对头结点进行操作时,考虑创建哑节点 dummy使用 dummy->next 表示真正的头节点。这样可以避免处理头节点为空的边界问题。
我们使用变量来跟踪进位,并从包含最低有效位的表头开始模拟逐 我们使用变量来跟踪进位,并从包含最低有效位的表头开始模拟逐
位相加的过程。 位相加的过程。
@ -36,7 +36,7 @@ Leetcode官方详细解答地址
### Solution ### Solution
**我们首先从最低有效位也就是列表 l1和 l2 的表头开始相加。注意需要考虑到进位的情况!** **我们首先从最低有效位也就是列表 l1 和 l2 的表头开始相加。注意需要考虑到进位的情况!**
```java ```java
/** /**
@ -76,8 +76,8 @@ public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
## 2. 翻转链表 ## 2. 翻转链表
### 题目描述 ### 题目描述
> 剑指 offer:输入一个链表,反转链表后,输出链表的所有元素。 > 剑指 offer:输入一个链表,反转链表后,输出链表的所有元素。
![翻转链表](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-20/81431871.jpg) ![翻转链表](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-20/81431871.jpg)
@ -88,7 +88,6 @@ public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
### Solution ### Solution
```java ```java
public class ListNode { public class ListNode {
int val; int val;
@ -162,18 +161,17 @@ public class Solution {
1 1
``` ```
## 3. 链表中倒数第k个节点 ## 3. 链表中倒数第 k 个节点
### 题目描述 ### 题目描述
> 剑指offer: 输入一个链表输出该链表中倒数第k个结点。 > 剑指 offer: 输入一个链表,输出该链表中倒数第 k 个结点。
### 问题分析 ### 问题分析
> **链表中倒数第k个节点也就是正数第(L-K+1)个节点,知道了只一点,这一题基本就没问题!** > **链表中倒数第 k 个节点也就是正数第(L-K+1)个节点,知道了只一点,这一题基本就没问题!**
首先两个节点/指针,一个节点 node1 先开始跑,指针 node1 跑到 k-1 个节点后,另一个节点 node2 开始跑,当 node1 跑到最后时node2 所指的节点就是倒数第k个节点也就是正数第(L-K+1)个节点。
首先两个节点/指针,一个节点 node1 先开始跑,指针 node1 跑到 k-1 个节点后,另一个节点 node2 开始跑,当 node1 跑到最后时node2 所指的节点就是倒数第 k 个节点也就是正数第(L-K+1)个节点。
### Solution ### Solution
@ -221,9 +219,7 @@ public class Solution {
} }
``` ```
## 4. 删除链表的倒数第 N 个节点
## 4. 删除链表的倒数第N个节点
> Leetcode:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 > Leetcode:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
@ -248,8 +244,7 @@ public class Solution {
### 问题分析 ### 问题分析
我们注意到这个问题可以容易地简化成另一个问题:删除从列表开头数起的第 (L - n + 1)个结点,其中 L 是列表的长度。只要我们找到列表的长度 L这个问题就很容易解决。
我们注意到这个问题可以容易地简化成另一个问题:删除从列表开头数起的第 (L - n + 1)个结点,其中 L是列表的长度。只要我们找到列表的长度 L这个问题就很容易解决。
![图 1. 删除列表中的第 L - n + 1 个元素](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-20/94354387.jpg) ![图 1. 删除列表中的第 L - n + 1 个元素](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-20/94354387.jpg)
@ -301,14 +296,11 @@ public class Solution {
- **时间复杂度 O(L)** :该算法对列表进行了两次遍历,首先计算了列表的长度 LL 其次找到第 (L - n)(Ln) 个结点。 操作执行了 2L-n2Ln 步,时间复杂度为 O(L)O(L)。 - **时间复杂度 O(L)** :该算法对列表进行了两次遍历,首先计算了列表的长度 LL 其次找到第 (L - n)(Ln) 个结点。 操作执行了 2L-n2Ln 步,时间复杂度为 O(L)O(L)。
- **空间复杂度 O(1)** :我们只用了常量级的额外空间。 - **空间复杂度 O(1)** :我们只用了常量级的额外空间。
**进阶——一次遍历法:** **进阶——一次遍历法:**
> 链表中倒数第 N 个节点也就是正数第(L-N+1)个节点。
> 链表中倒数第N个节点也就是正数第(L-N+1)个节点。 其实这种方法就和我们上面第四题找“链表中倒数第 k 个节点”所用的思想是一样的。**基本思路就是:** 定义两个节点 node1、node2;node1 节点先跑node1 节点 跑到第 n+1 个节点的时候,node2 节点开始跑.当 node1 节点跑到最后一个节点时node2 节点所在的位置就是第 L-n 个节点L 代表总链表长度,也就是倒数第 n+1 个节点)
其实这种方法就和我们上面第四题找“链表中倒数第k个节点”所用的思想是一样的。**基本思路就是:** 定义两个节点 node1、node2;node1 节点先跑node1节点 跑到第 n+1 个节点的时候,node2 节点开始跑.当node1 节点跑到最后一个节点时node2 节点所在的位置就是第 L-n 个节点L代表总链表长度也就是倒数第 n+1 个节点)
```java ```java
/** /**
@ -345,25 +337,21 @@ public class Solution {
} }
``` ```
## 5. 合并两个排序的链表 ## 5. 合并两个排序的链表
### 题目描述 ### 题目描述
> 剑指offer:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 > 剑指 offer:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
### 问题分析 ### 问题分析
我们可以这样分析: 我们可以这样分析:
1. 假设我们有两个链表 A,B 1. 假设我们有两个链表 A,B
2. A的头节点A1的值与B的头结点B1的值比较假设A1小则A1为头节点 2. A 的头节点 A1 的值与 B 的头结点 B1 的值比较,假设 A1 小,则 A1 为头节点;
3. A2再和B1比较假设B1小,则A1指向B1 3. A2 再和 B1 比较,假设 B1 小,则A1 指向 B1
4. A2再和B2比较 4. A2 再和 B2 比较
就这样循环往复就行了,应该还算好理解。 就这样循环往复就行了,应该还算好理解。
考虑通过递归的方式实现! 考虑通过递归的方式实现!
@ -400,4 +388,3 @@ public ListNode Merge(ListNode list1,ListNode list2) {
} }
} }
``` ```

View File

@ -9,12 +9,12 @@ tag:
**题目描述:** **题目描述:**
大家都知道斐波那契数列现在要求输入一个整数n请你输出斐波那契数列的第n项。 大家都知道斐波那契数列,现在要求输入一个整数 n请你输出斐波那契数列的第 n 项。
n<=39 n<=39
**问题分析:** **问题分析:**
可以肯定的是这一题通过递归的方式是肯定能做出来但是这样会有一个很大的问题那就是递归大量的重复计算会导致内存溢出。另外可以使用迭代法用fn1和fn2保存计算过程中的结果并复用起来。下面我会把两个方法示例代码都给出来并给出两个方法的运行时间对比。 可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有一个很大的问题,那就是递归大量的重复计算会导致内存溢出。另外可以使用迭代法,用 fn1 fn2 保存计算过程中的结果,并复用起来。下面我会把两个方法示例代码都给出来并给出两个方法的运行时间对比。
**示例代码:** **示例代码:**
@ -57,24 +57,24 @@ public int Fibonacci(int n) {
**题目描述:** **题目描述:**
一只青蛙一次可以跳上1级台阶也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
**问题分析:** **问题分析:**
正常分析法: 正常分析法:
> a.如果两种跳法1阶或者2阶那么假定第一次跳的是一阶那么剩下的是n-1个台阶跳法是f(n-1); > a.如果两种跳法1 阶或者 2 阶,那么假定第一次跳的是一阶,那么剩下的是 n-1 个台阶,跳法是 f(n-1);
> b.假定第一次跳的是2阶那么剩下的是n-2个台阶跳法是f(n-2) > b.假定第一次跳的是 2 阶,那么剩下的是 n-2 个台阶,跳法是 f(n-2)
> c.由ab假设可以得出总跳法为: f(n) = f(n-1) + f(n-2) > c.由 ab 假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
> d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2 > d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
找规律分析法: 找规律分析法:
> f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5 可以总结出f(n) = f(n-1) + f(n-2)的规律。但是为什么会出现这样的规律呢假设现在6个台阶我们可以从第5跳一步到6这样的话有多少种方案跳到5就有多少种方案跳到6另外我们也可以从4跳两步跳到6跳到4有多少种方案的话就有多少种方案跳到6其他的不能从3跳到6什么的啦所以最后就是f(6) = f(5) + f(4);这样子也很好理解变态跳台阶的问题了。 > f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5 可以总结出 f(n) = f(n-1) + f(n-2)的规律。但是为什么会出现这样的规律呢?假设现在 6 个台阶,我们可以从第 5 跳一步到 6这样的话有多少种方案跳到 5 就有多少种方案跳到 6另外我们也可以从 4 跳两步跳到 6跳到 4 有多少种方案的话,就有多少种方案跳到 6其他的不能从 3 跳到 6 什么的啦,所以最后就是 f(6) = f(5) + f(4);这样子也很好理解变态跳台阶的问题了。
**所以这道题其实就是斐波那契数列的问题。** **所以这道题其实就是斐波那契数列的问题。**
代码只需要在上一题的代码稍做修改即可。和上一题唯一不同的就是这一题的初始元素变为 1 2 3 5 8.....而上一题为1 1 2 3 5 .......。另外这一题也可以用递归做,但是递归效率太低,所以我这里只给出了迭代方式的代码。 代码只需要在上一题的代码稍做修改即可。和上一题唯一不同的就是这一题的初始元素变为 1 2 3 5 8.....而上一题为 1 1 2 3 5 .......。另外这一题也可以用递归做,但是递归效率太低,所以我这里只给出了迭代方式的代码。
**示例代码:** **示例代码:**
@ -103,20 +103,20 @@ int jumpFloor(int number) {
**题目描述:** **题目描述:**
一只青蛙一次可以跳上1级台阶也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级……它也可以跳上 n 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
**问题分析:** **问题分析:**
假设n>=2第一步有n种跳法跳1级、跳2级、到跳n级 假设 n>=2第一步有 n 种跳法:跳 1 级、跳 2 级、到跳 n
跳1级剩下n-1级则剩下跳法是f(n-1) 1 级,剩下 n-1 级,则剩下跳法是 f(n-1)
跳2级剩下n-2级则剩下跳法是f(n-2) 2 级,剩下 n-2 级,则剩下跳法是 f(n-2)
...... ......
跳n-1级剩下1级则剩下跳法是f(1) n-1 级,剩下 1 级,则剩下跳法是 f(1)
跳n级剩下0级则剩下跳法是f(0) n 级,剩下 0 级,则剩下跳法是 f(0)
所以在n>=2的情况下 所以在 n>=2 的情况下:
f(n)=f(n-1)+f(n-2)+...+f(1) f(n)=f(n-1)+f(n-2)+...+f(1)
因为f(n-1)=f(n-2)+f(n-3)+...+f(1) 因为 f(n-1)=f(n-2)+f(n-3)+...+f(1)
所以f(n)=2*f(n-1) 又f(1)=1,所以可得**f(n)=2^(number-1)** 所以 f(n)=2\*f(n-1) 又 f(1)=1,所以可得**f(n)=2^(number-1)**
**示例代码:** **示例代码:**
@ -128,11 +128,11 @@ int JumpFloorII(int number) {
**补充:** **补充:**
java中有三种移位运算符 java 中有三种移位运算符:
1. “<<” : **左移运算符**等同于乘2的n次方 1. “<<” : **左移运算符**,等同于乘 2 n 次方
2. “>>”: **右移运算符**等同于除2的n次方 2. “>>”: **右移运算符**,等同于除 2 n 次方
3. “>>>” : **无符号右移运算符**不管移动前最高位是0还是1右移后左侧产生的空位部分都以0来填充。与>>类似。 3. “>>>” : **无符号右移运算符**,不管移动前最高位是 0 还是 1右移后左侧产生的空位部分都以 0 来填充。与>>类似。
```java ```java
int a = 16; int a = 16;
@ -140,7 +140,6 @@ int b = a << 2;//左移2等同于16 * 2的2次方也就是16 * 4
int c = a >> 2;//右移2等同于16 / 2的2次方也就是16 / 4 int c = a >> 2;//右移2等同于16 / 2的2次方也就是16 / 4
``` ```
## 二维数组查找 ## 二维数组查找
**题目描述:** **题目描述:**
@ -180,11 +179,11 @@ public boolean Find(int target, int [][] array) {
**题目描述:** **题目描述:**
请实现一个函数,将一个字符串中的空格替换成“%20”。例如当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 请实现一个函数,将一个字符串中的空格替换成“%20”。例如当字符串为 We Are Happy.则经过替换之后的字符串为 We%20Are%20Happy。
**问题分析:** **问题分析:**
这道题不难我们可以通过循环判断字符串的字符是否为空格是的话就利用append()方法添加追加“%20”否则还是追加原字符。 这道题不难,我们可以通过循环判断字符串的字符是否为空格,是的话就利用 append()方法添加追加“%20”否则还是追加原字符。
或者最简单的方法就是利用replaceAll(String regex,String replacement)方法了,一行代码就可以解决。 或者最简单的方法就是利用replaceAll(String regex,String replacement)方法了,一行代码就可以解决。
@ -223,17 +222,14 @@ public String replaceSpace(StringBuffer str) {
**题目描述:** **题目描述:**
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 给定一个 double 类型的浮点数 base int 类型的整数 exponent。求 base exponent 次方。
**问题解析:** **问题解析:**
这道题算是比较麻烦和难一点的一个了。我这里采用的是**二分幂**思想,当然也可以采用**快速幂**。 这道题算是比较麻烦和难一点的一个了。我这里采用的是**二分幂**思想,当然也可以采用**快速幂**。
更具剑指offer书中细节该题的解题思路如下 更具剑指 offer 书中细节,该题的解题思路如下: 1.当底数为 0 且指数<0 会出现对 0 求倒数的情况需进行错误处理设置一个全局变量 2.判断底数是否等于 0由于 base double 所以不能直接用==判断 3.优化求幂函数二分幂
1.当底数为0且指数<0时会出现对0求倒数的情况需进行错误处理设置一个全局变量 当 n 为偶数a^n =a^n/2_a^n/2
2.判断底数是否等于0由于base为double型所以不能直接用==判断 当 n 为奇数a^n = a^[(n-1)/2] _ a^[(n-1)/2] \* a。时间复杂度 O(logn)
3.优化求幂函数(二分幂)。
当n为偶数a^n =a^n/2*a^n/2
当n为奇数a^n = a^[(n-1)/2] * a^[(n-1)/2] * a。时间复杂度O(logn)
**时间复杂度**O(logn) **时间复杂度**O(logn)
@ -286,7 +282,7 @@ public class Solution {
} }
``` ```
当然这一题也可以采用笨方法累乘。不过这种方法的时间复杂度为On这样没有前一种方法效率高。 当然这一题也可以采用笨方法:累乘。不过这种方法的时间复杂度为 On这样没有前一种方法效率高。
```java ```java
// 使用累乘 // 使用累乘
@ -311,11 +307,11 @@ public double powerAnother(double base, int exponent) {
**问题解析:** **问题解析:**
这道题有挺多种解法的,给大家介绍一种我觉得挺好理解的方法: 这道题有挺多种解法的,给大家介绍一种我觉得挺好理解的方法:
我们首先统计奇数的个数假设为n,然后新建一个等长数组然后通过循环判断原数组中的元素为偶数还是奇数。如果是则从数组下标0的元素开始把该奇数添加到新数组如果是偶数则从数组下标为n的元素开始把该偶数添加到新数组中。 我们首先统计奇数的个数假设为 n,然后新建一个等长数组,然后通过循环判断原数组中的元素为偶数还是奇数。如果是则从数组下标 0 的元素开始,把该奇数添加到新数组;如果是偶数则从数组下标为 n 的元素开始把该偶数添加到新数组中。
**示例代码:** **示例代码:**
时间复杂度为On空间复杂度为On的算法 时间复杂度为 On空间复杂度为 On的算法
```java ```java
public class Solution { public class Solution {
@ -346,26 +342,26 @@ public class Solution {
} }
``` ```
## 链表中倒数第k个节点 ## 链表中倒数第 k 个节点
**题目描述:** **题目描述:**
输入一个链表输出该链表中倒数第k个结点 输入一个链表,输出该链表中倒数第 k 个结点
**问题分析:** **问题分析:**
**一句话概括:** **一句话概括:**
两个指针一个指针p1先开始跑指针p1跑到k-1个节点后另一个节点p2开始跑当p1跑到最后时p2所指的指针就是倒数第k个节点。 两个指针一个指针 p1 先开始跑,指针 p1 跑到 k-1 个节点后,另一个节点 p2 开始跑,当 p1 跑到最后时p2 所指的指针就是倒数第 k 个节点。
**思想的简单理解:** **思想的简单理解:**
前提假设:链表的结点个数(长度)为n。 前提假设:链表的结点个数(长度)为 n。
规律一要找到倒数第k个结点需要向前走多少步呢比如倒数第一个结点需要走n步那倒数第二个结点呢很明显是向前走了n-1步所以可以找到规律是找到倒数第k个结点需要向前走n-k+1步。 规律一:要找到倒数第 k 个结点,需要向前走多少步呢?比如倒数第一个结点,需要走 n 步,那倒数第二个结点呢?很明显是向前走了 n-1 步,所以可以找到规律是找到倒数第 k 个结点,需要向前走 n-k+1 步。
**算法开始:** **算法开始:**
1. 设两个都指向head的指针p1和p2当p1走了k-1步的时候停下来。p2之前一直不动。 1. 设两个都指向 head 的指针 p1 p2 p1 走了 k-1 步的时候停下来。p2 之前一直不动。
2. p1的下一步是走第k步这个时候p2开始一起动了。至于为什么p2这个时候动呢看下面的分析。 2. p1 的下一步是走第 k 这个时候p2 开始一起动了。至于为什么 p2 这个时候动呢?看下面的分析。
3. 当p1走到链表的尾部时即p1走了n步。由于我们知道p2是在p1走了k-1步才开始动的也就是说p1和p2永远差k-1步。所以当p1走了n步时p2走的应该是在n-(k-1)步。即p2走了n-k+1步此时巧妙的是p2正好指向的是规律一的倒数第k个结点处。 3. 当 p1 走到链表的尾部时,即 p1 走了 n 步。由于我们知道 p2 是在 p1 走了 k-1 步才开始动的,也就是说 p1 p2 永远差 k-1 步。所以当 p1 走了 n 步时p2 走的应该是在 n-(k-1)步。即 p2 走了 n-k+1 步,此时巧妙的是 p2 正好指向的是规律一的倒数第 k 个结点处。
这样是不是很好理解了呢? 这样是不是很好理解了呢?
**考察内容:** **考察内容:**
@ -425,7 +421,7 @@ public class Solution {
链表的很常规的一道题,这一道题思路不算难,但自己实现起来真的可能会感觉无从下手,我是参考了别人的代码。 链表的很常规的一道题,这一道题思路不算难,但自己实现起来真的可能会感觉无从下手,我是参考了别人的代码。
思路就是我们根据链表的特点,前一个节点指向下一个节点的特点,把后面的节点移到前面来。 思路就是我们根据链表的特点,前一个节点指向下一个节点的特点,把后面的节点移到前面来。
就比如下图我们把1节点和2节点互换位置然后再将3节点指向2节点4节点指向3节点这样以来下面的链表就被反转了。 就比如下图:我们把 1 节点和 2 节点互换位置,然后再将 3 节点指向 2 节点4 节点指向 3 节点,这样以来下面的链表就被反转了。
![链表](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/844773c7300e4373922bb1a6ae2a55a3~tplv-k3u1fbpfcp-zoom-1.image) ![链表](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/844773c7300e4373922bb1a6ae2a55a3~tplv-k3u1fbpfcp-zoom-1.image)
@ -475,9 +471,9 @@ public class Solution {
我们可以这样分析: 我们可以这样分析:
1. 假设我们有两个链表 A,B 1. 假设我们有两个链表 A,B
2. A的头节点A1的值与B的头结点B1的值比较假设A1小则A1为头节点 2. A 的头节点 A1 的值与 B 的头结点 B1 的值比较,假设 A1 小,则 A1 为头节点;
3. A2再和B1比较假设B1小,则A1指向B1 3. A2 再和 B1 比较,假设 B1 小,则A1 指向 B1
4. A2再和B2比较。。。。。。。 4. A2 再和 B2 比较。。。。。。。
就这样循环往复就行了,应该还算好理解。 就这样循环往复就行了,应该还算好理解。
**考察内容:** **考察内容:**
@ -569,17 +565,17 @@ public ListNode Merge(ListNode list1,ListNode list2) {
**题目描述:** **题目描述:**
用两个栈来实现一个队列完成队列的Push和Pop操作。 队列中的元素为int类型。 用两个栈来实现一个队列,完成队列的 Push Pop 操作。 队列中的元素为 int 类型。
**问题分析:** **问题分析:**
先来回顾一下栈和队列的基本特点: 先来回顾一下栈和队列的基本特点:
**栈:**后进先出LIFO **栈:**后进先出LIFO
**队列:** 先进先出 **队列:** 先进先出
很明显我们需要根据JDK给我们提供的栈的一些基本方法来实现。先来看一下Stack类的一些基本方法 很明显我们需要根据 JDK 给我们提供的栈的一些基本方法来实现。先来看一下 Stack 类的一些基本方法:
![Stack类的一些常见方法](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-4-4/5985000.jpg) ![Stack类的一些常见方法](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-4-4/5985000.jpg)
既然题目给了我们两个栈我们可以这样考虑当push的时候将元素push进stack1pop的时候我们先把stack1的元素pop到stack2然后再对stack2执行pop操作这样就可以保证是先进先出的。负[pop]负[pop]得正[先进先出] 既然题目给了我们两个栈,我们可以这样考虑当 push 的时候将元素 push stack1pop 的时候我们先把 stack1 的元素 pop stack2然后再对 stack2 执行 pop 操作,这样就可以保证是先进先出的。(负[pop]负[pop]得正[先进先出]
**考察内容:** **考察内容:**
@ -621,34 +617,34 @@ public class Solution {
**题目描述:** **题目描述:**
输入两个整数序列第一个序列表示栈的压入顺序请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序序列45,3,2,1是该压栈序列对应的一个弹出序列但4,3,5,1,2就不可能是该压栈序列的弹出序列。注意这两个序列的长度是相等的 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列 1,2,3,4,5 是某栈的压入顺序,序列 45,3,2,1 是该压栈序列对应的一个弹出序列,但 4,3,5,1,2 就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
**题目分析:** **题目分析:**
这道题想了半天没有思路参考了Alias的答案他的思路写的也很详细应该很容易看懂。 这道题想了半天没有思路,参考了 Alias 的答案,他的思路写的也很详细应该很容易看懂。
作者Alias 作者Alias
https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106 https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
来源:牛客网 来源:牛客网
【思路】借用一个辅助的栈遍历压栈顺序先讲第一个放入栈中这里是1然后判断栈顶元素是不是出栈顺序的第一个元素这里是4很显然1≠4所以我们继续压栈直到相等以后开始出栈出栈一个元素则将出栈顺序向后移动一位直到不相等这样循环等压栈顺序遍历完成如果辅助栈还不为空说明弹出序列不是该栈的弹出顺序。 【思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是 1然后判断栈顶元素是不是出栈顺序的第一个元素这里是 4很显然 1≠4所以我们继续压栈直到相等以后开始出栈出栈一个元素则将出栈顺序向后移动一位直到不相等这样循环等压栈顺序遍历完成如果辅助栈还不为空说明弹出序列不是该栈的弹出顺序。
举例: 举例:
入栈1,2,3,4,5 入栈 1,2,3,4,5
出栈4,5,3,2,1 出栈 4,5,3,2,1
首先1入辅助栈此时栈顶1≠4继续入栈2 首先 1 入辅助栈,此时栈顶 1≠4继续入栈 2
此时栈顶2≠4继续入栈3 此时栈顶 2≠4继续入栈 3
此时栈顶3≠4继续入栈4 此时栈顶 3≠4继续入栈 4
此时栈顶44出栈4弹出序列向后一位此时为5,辅助栈里面是1,2,3 此时栈顶 4 4出栈 4弹出序列向后一位此时为 5,辅助栈里面是 1,2,3
此时栈顶3≠5继续入栈5 此时栈顶 3≠5继续入栈 5
此时栈顶5=5出栈5,弹出序列向后一位此时为3,辅助栈里面是1,2,3 此时栈顶 5=5出栈 5,弹出序列向后一位,此时为 3,辅助栈里面是 1,2,3
…. ….
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。 依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。

View File

@ -57,7 +57,6 @@ tag:
1. 判断给定数据是否存在比如判断一个数字是否存在于包含大量数字的数字集中数字集很大5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。 1. 判断给定数据是否存在比如判断一个数字是否存在于包含大量数字的数字集中数字集很大5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。 2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。
## 编码实战 ## 编码实战
### 通过 Java 编程手动实现布隆过滤器 ### 通过 Java 编程手动实现布隆过滤器
@ -245,9 +244,9 @@ Redis v4.0 之后有了 Module模块/插件) 功能Redis Modules 让 Red
另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module地址https://github.com/RedisBloom/RedisBloom 另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module地址https://github.com/RedisBloom/RedisBloom
其他还有: 其他还有:
* redis-lua-scaling-bloom-filterlua 脚本实现https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter - redis-lua-scaling-bloom-filterlua 脚本实现https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
* pyreBloomPython 中的快速 Redis 布隆过滤器) https://github.com/seomoz/pyreBloom - pyreBloomPython 中的快速 Redis 布隆过滤器) https://github.com/seomoz/pyreBloom
* ...... - ......
RedisBloom 提供了多种语言的客户端支持包括Python、Java、JavaScript 和 PHP。 RedisBloom 提供了多种语言的客户端支持包括Python、Java、JavaScript 和 PHP。
@ -287,7 +286,7 @@ root@21396d02c252:/data# redis-cli
可选参数: 可选参数:
* expansion如果创建了一个新的子过滤器则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。 - expansion如果创建了一个新的子过滤器则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。
### 实际使用 ### 实际使用

View File

@ -14,7 +14,7 @@ tag:
但是,图形结构的元素之间的关系是任意的。 但是,图形结构的元素之间的关系是任意的。
**何为图呢?** 简单来说,图就是由顶点的有穷非空集合和顶点之间的边组成的集合。通常表示为:**G(V,E)**其中G表示一个图V表示顶点的集合E表示边的集合。 **何为图呢?** 简单来说,图就是由顶点的有穷非空集合和顶点之间的边组成的集合。通常表示为:**G(V,E)**其中G 表示一个图V 表示顶点的集合E 表示边的集合。
下图所展示的就是图这种数据结构,并且还是一张有向图。 下图所展示的就是图这种数据结构,并且还是一张有向图。
@ -25,24 +25,28 @@ tag:
## 图的基本概念 ## 图的基本概念
### 顶点 ### 顶点
图中的数据元素,我们称之为顶点,图至少有一个顶点(非空有穷集合) 图中的数据元素,我们称之为顶点,图至少有一个顶点(非空有穷集合)
对应到好友关系图,每一个用户就代表一个顶点。 对应到好友关系图,每一个用户就代表一个顶点。
### 边 ### 边
顶点之间的关系用边表示。 顶点之间的关系用边表示。
对应到好友关系图,两个用户是好友的话,那两者之间就存在一条边。 对应到好友关系图,两个用户是好友的话,那两者之间就存在一条边。
### 度 ### 度
度表示一个顶点包含多少条边,在有向图中,还分为出度和入度,出度表示从该顶点出去的边的条数,入度表示进入该顶点的边的条数。 度表示一个顶点包含多少条边,在有向图中,还分为出度和入度,出度表示从该顶点出去的边的条数,入度表示进入该顶点的边的条数。
对应到好友关系图,度就代表了某个人的好友数量。 对应到好友关系图,度就代表了某个人的好友数量。
### 无向图和有向图 ### 无向图和有向图
边表示的是顶点之间的关系有的关系是双向的比如同学关系A是B的同学那么B也肯定是A的同学那么在表示A和B的关系时就不用关注方向用不带箭头的边表示这样的图就是无向图。
有的关系是有方向的比如父子关系师生关系微博的关注关系A是B的爸爸但B肯定不是A的爸爸A关注BB不一定关注A。在这种情况下我们就用带箭头的边表示二者的关系这样的图就是有向图。 边表示的是顶点之间的关系有的关系是双向的比如同学关系A 是 B 的同学,那么 B 也肯定是 A 的同学,那么在表示 A 和 B 的关系时,就不用关注方向,用不带箭头的边表示,这样的图就是无向图。
有的关系是有方向的比如父子关系师生关系微博的关注关系A 是 B 的爸爸,但 B 肯定不是 A 的爸爸A 关注 BB 不一定关注 A。在这种情况下我们就用带箭头的边表示二者的关系这样的图就是有向图。
### 无权图和带权图 ### 无权图和带权图
@ -55,16 +59,18 @@ tag:
![带权有向图](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/weighted-directed-graph.png) ![带权有向图](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/weighted-directed-graph.png)
## 图的存储 ## 图的存储
### 邻接矩阵存储 ### 邻接矩阵存储
邻接矩阵将图用二维矩阵存储,是一种较为直观的表示方式。 邻接矩阵将图用二维矩阵存储,是一种较为直观的表示方式。
如果第i个顶点和第j个顶点之间有关系且关系权值为n`A[i][j]=n` 如果第 i 个顶点和第 j 个顶点之间有关系,且关系权值为 n`A[i][j]=n`
在无向图中我们只关心关系的有无所以当顶点i和顶点j有关系时`A[i][j]`=1当顶点i和顶点j没有关系时`A[i][j]`=0。如下图所示 在无向图中,我们只关心关系的有无,所以当顶点 i 和顶点 j 有关系时,`A[i][j]`=1当顶点 i 和顶点 j 没有关系时,`A[i][j]`=0。如下图所示
![无向图的邻接矩阵存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-matrix-representation-of-undirected-graph.png) ![无向图的邻接矩阵存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-matrix-representation-of-undirected-graph.png)
值得注意的是:**无向图的邻接矩阵是一个对称矩阵因为在无向图中顶点i和顶点j有关系则顶点j和顶点i必有关系。** 值得注意的是:**无向图的邻接矩阵是一个对称矩阵,因为在无向图中,顶点 i 和顶点 j 有关系,则顶点 j 和顶点 i 必有关系。**
![有向图的邻接矩阵存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-matrix-representation-of-directed-graph.png) ![有向图的邻接矩阵存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-matrix-representation-of-directed-graph.png)
@ -74,7 +80,7 @@ tag:
针对上面邻接矩阵比较浪费内存空间的问题,诞生了图的另外一种存储方法—**邻接表** 。 针对上面邻接矩阵比较浪费内存空间的问题,诞生了图的另外一种存储方法—**邻接表** 。
邻接链表使用一个链表来存储某个顶点的所有后继相邻顶点。对于图中每个顶点Vi把所有邻接于Vi的顶点Vj链成一个单链表这个单链表称为顶点Vi的 **邻接表**。如下图所示: 邻接链表使用一个链表来存储某个顶点的所有后继相邻顶点。对于图中每个顶点 Vi把所有邻接于 Vi 的顶点 Vj 链成一个单链表,这个单链表称为顶点 Vi **邻接表**。如下图所示:
![无向图的邻接表存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-list-representation-of-undirected-graph.png) ![无向图的邻接表存储](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/adjacency-list-representation-of-undirected-graph.png)
@ -82,38 +88,40 @@ tag:
大家可以数一数邻接表中所存储的元素的个数以及图中边的条数,你会发现: 大家可以数一数邻接表中所存储的元素的个数以及图中边的条数,你会发现:
- 在无向图中邻接表元素个数等于边的条数的两倍如左图所示的无向图中边的条数为7邻接表存储的元素个数为14。 - 在无向图中,邻接表元素个数等于边的条数的两倍,如左图所示的无向图中,边的条数为 7邻接表存储的元素个数为 14。
- 在有向图中邻接表元素个数等于边的条数如右图所示的有向图中边的条数为8邻接表存储的元素个数为8。 - 在有向图中,邻接表元素个数等于边的条数,如右图所示的有向图中,边的条数为 8邻接表存储的元素个数为 8。
## 图的搜索 ## 图的搜索
### 广度优先搜索 ### 广度优先搜索
广度优先搜索就像水面上的波纹一样一层一层向外扩展,如下图所示: 广度优先搜索就像水面上的波纹一样一层一层向外扩展,如下图所示:
![广度优先搜索图示](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search.png) ![广度优先搜索图示](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search.png)
**广度优先搜索的具体实现方式用到了之前所学过的线性数据结构——队列** 。具体过程如下图所示: **广度优先搜索的具体实现方式用到了之前所学过的线性数据结构——队列** 。具体过程如下图所示:
**第1步** **第 1 步:**
![广度优先搜索1](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search1.png) ![广度优先搜索1](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search1.png)
**第2步** **第 2 步:**
![广度优先搜索2](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search2.png) ![广度优先搜索2](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search2.png)
**第3步** **第 3 步:**
![广度优先搜索3](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search3.png) ![广度优先搜索3](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search3.png)
**第4步** **第 4 步:**
![广度优先搜索4](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search4.png) ![广度优先搜索4](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search4.png)
**第5步** **第 5 步:**
![广度优先搜索5](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search5.png) ![广度优先搜索5](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search5.png)
**第6步** **第 6 步:**
![广度优先搜索6](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search6.png) ![广度优先搜索6](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/breadth-first-search6.png)
@ -123,30 +131,28 @@ tag:
![深度优先搜索图示](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search.png) ![深度优先搜索图示](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search.png)
**和广度优先搜索类似,深度优先搜索的具体实现用到了另一种线性数据结构——栈** 。具体过程如下图所示: **和广度优先搜索类似,深度优先搜索的具体实现用到了另一种线性数据结构——栈** 。具体过程如下图所示:
**第1步** **第 1 步:**
![深度优先搜索1](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search1.png) ![深度优先搜索1](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search1.png)
**第2步** **第 2 步:**
![深度优先搜索2](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search2.png) ![深度优先搜索2](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search2.png)
**第3步** **第 3 步:**
![深度优先搜索3](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search3.png) ![深度优先搜索3](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search3.png)
**第4步** **第 4 步:**
![深度优先搜索4](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search4.png) ![深度优先搜索4](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search4.png)
**第5步** **第 5 步:**
![深度优先搜索5](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search5.png) ![深度优先搜索5](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search5.png)
**第6步** **第 6 步:**
![深度优先搜索6](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search6.png) ![深度优先搜索6](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/depth-first-search6.png)

View File

@ -23,11 +23,12 @@ tag:
![](./pictures/堆/堆1.png) ![](./pictures/堆/堆1.png)
第1个和第2个是堆。第1个是最大堆每个节点都比子树中所有节点大。第2个是最小堆每个节点都比子树中所有节点小。 1 个和第 2 个是堆。第 1 个是最大堆,每个节点都比子树中所有节点大。第 2 个是最小堆,每个节点都比子树中所有节点小。
第3个不是第三个中根结点1比2和15小而15却比3大19比5大不满足堆的性质。 3 个不是,第三个中,根结点 1 2 15 小,而 15 却比 3 19 5 大,不满足堆的性质。
## 堆的用途 ## 堆的用途
当我们只关心所有数据中的最大值或者最小值,存在多次获取最大值或者最小值,多次插入或删除数据时,就可以使用堆。 当我们只关心所有数据中的最大值或者最小值,存在多次获取最大值或者最小值,多次插入或删除数据时,就可以使用堆。
有小伙伴可能会想到用有序数组,初始化一个有序数组时间复杂度是 `O(nlog(n))`,查找最大值或者最小值时间复杂度都是 `O(1)`,但是,涉及到更新(插入或删除)数据时,时间复杂度为 `O(n)`,即使是使用复杂度为 `O(log(n))` 的二分法找到要插入或者删除的数据,在移动数据时也需要 `O(n)` 的时间复杂度。 有小伙伴可能会想到用有序数组,初始化一个有序数组时间复杂度是 `O(nlog(n))`,查找最大值或者最小值时间复杂度都是 `O(1)`,但是,涉及到更新(插入或删除)数据时,时间复杂度为 `O(n)`,即使是使用复杂度为 `O(log(n))` 的二分法找到要插入或者删除的数据,在移动数据时也需要 `O(n)` 的时间复杂度。
@ -39,25 +40,30 @@ tag:
## 堆的分类 ## 堆的分类
堆分为 **最大堆****最小堆**。二者的区别在于节点的排序方式。 堆分为 **最大堆****最小堆**。二者的区别在于节点的排序方式。
- **最大堆** :堆中的每一个节点的值都大于等于子树中所有节点的值 - **最大堆** :堆中的每一个节点的值都大于等于子树中所有节点的值
- **最小堆** :堆中的每一个节点的值都小于等于子树中所有节点的值 - **最小堆** :堆中的每一个节点的值都小于等于子树中所有节点的值
如下图所示图1是最大堆图2是最小堆 如下图所示,图 1 是最大堆,图 2 是最小堆
![](./pictures/堆/堆2.png) ![](./pictures/堆/堆2.png)
## 堆的存储 ## 堆的存储
之前介绍树的时候说过由于完全二叉树的优秀性质利用数组存储二叉树即节省空间又方便索引若根结点的序号为1那么对于树中任意节点i其左子节点序号为 `2*i`,右子节点序号为 `2*i+1`)。
之前介绍树的时候说过,由于完全二叉树的优秀性质,利用数组存储二叉树即节省空间,又方便索引(若根结点的序号为 1那么对于树中任意节点 i其左子节点序号为 `2*i`,右子节点序号为 `2*i+1`)。
为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示: 为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示:
![堆的存储](./pictures/堆/堆的存储.png) ![堆的存储](./pictures/堆/堆的存储.png)
## 堆的操作 ## 堆的操作
堆的更新操作主要包括两种 : **插入元素****删除堆顶元素**。操作过程需要着重掌握和理解。 堆的更新操作主要包括两种 : **插入元素****删除堆顶元素**。操作过程需要着重掌握和理解。
> 在进入正题之前,再重申一遍,堆是一个公平的公司,有能力的人自然会走到与他能力所匹配的位置 > 在进入正题之前,再重申一遍,堆是一个公平的公司,有能力的人自然会走到与他能力所匹配的位置
### 插入元素 ### 插入元素
> 插入元素,作为一个新入职的员工,初来乍到,这个员工需要从基层做起 > 插入元素,作为一个新入职的员工,初来乍到,这个员工需要从基层做起
**1.将要插入的元素放到最后** **1.将要插入的元素放到最后**
@ -85,20 +91,16 @@ tag:
> 在堆这个公司中,会出现老大离职的现象,老大离职之后,他的位置就空出来了 > 在堆这个公司中,会出现老大离职的现象,老大离职之后,他的位置就空出来了
首先删除堆顶元素使得数组中下标为1的位置空出。 首先删除堆顶元素,使得数组中下标为 1 的位置空出。
![删除堆顶元素1](./pictures/堆/删除堆顶元素1.png) ![删除堆顶元素1](./pictures/堆/删除堆顶元素1.png)
> 那么他的位置由谁来接替呢,当然是他的直接下属了,谁能力强就让谁上呗 > 那么他的位置由谁来接替呢,当然是他的直接下属了,谁能力强就让谁上呗
比较根结点的左子节点和右子节点也就是下标为2,3的数组元素将较大的元素填充到根结点(下标为1)的位置。 比较根结点的左子节点和右子节点,也就是下标为 2,3 的数组元素,将较大的元素填充到根结点(下标为 1)的位置。
![删除堆顶元素2](./pictures/堆/删除堆顶元素2.png) ![删除堆顶元素2](./pictures/堆/删除堆顶元素2.png)
> 这个时候又空出一个位置了,老规矩,谁有能力谁上 > 这个时候又空出一个位置了,老规矩,谁有能力谁上
一直循环比较空出位置的左右子节点,并将较大者移至空位,直到堆的最底部 一直循环比较空出位置的左右子节点,并将较大者移至空位,直到堆的最底部
@ -108,6 +110,7 @@ tag:
这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了“气泡”,这会导致存储空间的浪费。接下来我们试试自顶向下堆化。 这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了“气泡”,这会导致存储空间的浪费。接下来我们试试自顶向下堆化。
#### 自顶向下堆化 #### 自顶向下堆化
自顶向下的堆化用一个词形容就是“石沉大海”,那么第一件事情,就是把石头抬起来,从海面扔下去。这个石头就是堆的最后一个元素,我们将最后一个元素移动到堆顶。 自顶向下的堆化用一个词形容就是“石沉大海”,那么第一件事情,就是把石头抬起来,从海面扔下去。这个石头就是堆的最后一个元素,我们将最后一个元素移动到堆顶。
![删除堆顶元素4](./pictures/堆/删除堆顶元素4.png) ![删除堆顶元素4](./pictures/堆/删除堆顶元素4.png)
@ -118,14 +121,11 @@ tag:
![删除堆顶元素6](./pictures/堆/删除堆顶元素6.png) ![删除堆顶元素6](./pictures/堆/删除堆顶元素6.png)
### 堆的操作总结 ### 堆的操作总结
- **插入元素** :先将元素放至数组末尾,再自底向上堆化,将末尾元素上浮 - **插入元素** :先将元素放至数组末尾,再自底向上堆化,将末尾元素上浮
- **删除堆顶元素** :删除堆顶元素,将末尾元素放至堆顶,再自顶向下堆化,将堆顶元素下沉。也可以自底向上堆化,只是会产生“气泡”,浪费存储空间。最好采用自顶向下堆化的方式。 - **删除堆顶元素** :删除堆顶元素,将末尾元素放至堆顶,再自顶向下堆化,将堆顶元素下沉。也可以自底向上堆化,只是会产生“气泡”,浪费存储空间。最好采用自顶向下堆化的方式。
## 堆排序 ## 堆排序
堆排序的过程分为两步: 堆排序的过程分为两步:
@ -137,22 +137,22 @@ tag:
如果你已经足够了解堆化的过程,那么建堆的过程掌握起来就比较容易了。建堆的过程就是一个对所有非叶节点的自顶向下堆化过程。 如果你已经足够了解堆化的过程,那么建堆的过程掌握起来就比较容易了。建堆的过程就是一个对所有非叶节点的自顶向下堆化过程。
首先要了解哪些是非叶节点最后一个节点的父结点及它之前的元素都是非叶节点。也就是说如果节点个数为n那么我们需要对n/2到1的节点进行自顶向下沉底堆化。 首先要了解哪些是非叶节点,最后一个节点的父结点及它之前的元素,都是非叶节点。也就是说,如果节点个数为 n那么我们需要对 n/2 1 的节点进行自顶向下(沉底)堆化。
具体过程如下图: 具体过程如下图:
![建堆1](./pictures/堆/建堆1.png) ![建堆1](./pictures/堆/建堆1.png)
将初始的无序数组抽象为一棵树图中的节点个数为6所以4,5,6节点为叶节点1,2,3节点为非叶节点所以要对1-3号节点进行自顶向下沉底堆化注意顺序是从后往前堆化从3号节点开始一直到1号节点。 将初始的无序数组抽象为一棵树,图中的节点个数为 6所以 4,5,6 节点为叶节点1,2,3 节点为非叶节点,所以要对 1-3 号节点进行自顶向下(沉底)堆化,注意,顺序是从后往前堆化,从 3 号节点开始,一直到 1 号节点。
3号节点堆化结果 3 号节点堆化结果:
![建堆1](./pictures/堆/建堆2.png) ![建堆1](./pictures/堆/建堆2.png)
2号节点堆化结果 2 号节点堆化结果:
![建堆1](./pictures/堆/建堆3.png) ![建堆1](./pictures/堆/建堆3.png)
1号节点堆化结果 1 号节点堆化结果:
![建堆1](./pictures/堆/建堆4.png) ![建堆1](./pictures/堆/建堆4.png)

View File

@ -10,13 +10,12 @@ tag:
1. 每个节点非红即黑; 1. 每个节点非红即黑;
2. 根节点总是黑色的; 2. 根节点总是黑色的;
3. 每个叶子节点都是黑色的空节点NIL节点 3. 每个叶子节点都是黑色的空节点NIL 节点);
4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定); 4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定);
5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。 5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。
**红黑树的应用** TreeMap、TreeSet以及JDK1.8的HashMap底层都用到了红黑树。 **红黑树的应用** TreeMap、TreeSet 以及 JDK1.8 HashMap 底层都用到了红黑树。
**为什么要用红黑树?** 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。详细了解可以查看 [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐) **为什么要用红黑树?** 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。详细了解可以查看 [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐)
**相关阅读** [《红黑树深入剖析及Java实现》](https://zhuanlan.zhihu.com/p/24367771)(美团点评技术团队) **相关阅读** [《红黑树深入剖析及 Java 实现》](https://zhuanlan.zhihu.com/p/24367771)(美团点评技术团队)

View File

@ -38,7 +38,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))。 **二叉树** 的第 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>))。
![危机百科对节点深度的定义](https://oss.javaguide.cn/github/javaguide/image-20220119112736158.png) ![危机百科对节点深度的定义](https://oss.javaguide.cn/github/javaguide/image-20220119112736158.png)
@ -48,8 +48,6 @@ tag:
![满二叉树](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/full-binary-tree.png) ![满二叉树](https://oss.javaguide.cn/github/javaguide/cs-basics/data-structure/full-binary-tree.png)
### 完全二叉树 ### 完全二叉树
除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则这个二叉树就是 **完全二叉树** 除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则这个二叉树就是 **完全二叉树**

View File

@ -5,8 +5,6 @@ tag:
- 计算机网络 - 计算机网络
--- ---
## HTTP:超文本传输协议 ## HTTP:超文本传输协议
**超文本传输协议HTTPHyperText Transfer Protocol)** 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。 **超文本传输协议HTTPHyperText Transfer Protocol)** 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。

View File

@ -5,7 +5,6 @@ tag:
- 计算机网络 - 计算机网络
--- ---
本文是我在大二学习计算机网络期间整理, 大部分内容都来自于谢希仁老师的[《计算机网络》第七版 ](https://www.elias.ltd/usr/local/etc/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%EF%BC%88%E7%AC%AC7%E7%89%88%EF%BC%89%E8%B0%A2%E5%B8%8C%E4%BB%81.pdf)这本书。为了内容更容易理解,我对之前的整理进行了一波重构,并配上了一些相关的示意图便于理解。 本文是我在大二学习计算机网络期间整理, 大部分内容都来自于谢希仁老师的[《计算机网络》第七版 ](https://www.elias.ltd/usr/local/etc/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%EF%BC%88%E7%AC%AC7%E7%89%88%EF%BC%89%E8%B0%A2%E5%B8%8C%E4%BB%81.pdf)这本书。为了内容更容易理解,我对之前的整理进行了一波重构,并配上了一些相关的示意图便于理解。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fb5d8645cd55484ab0177f25a13e97db~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fb5d8645cd55484ab0177f25a13e97db~tplv-k3u1fbpfcp-zoom-1.image)

View File

@ -5,7 +5,7 @@ tag:
- 计算机网络 - 计算机网络
--- ---
HTTP 状态码用于描述 HTTP 请求的结果比如2xx 就代表请求被成功处理。 HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被成功处理。
![常见 HTTP 状态码](https://oss.javaguide.cn/github/javaguide/cs-basics/network/http-status-code.png) ![常见 HTTP 状态码](https://oss.javaguide.cn/github/javaguide/cs-basics/network/http-status-code.png)
@ -15,14 +15,14 @@ HTTP 状态码用于描述 HTTP 请求的结果比如2xx 就代表请求被
### 2xx Success成功状态码 ### 2xx Success成功状态码
- **200 OK** 请求被成功处理。比如我们发送一个查询用户数据的HTTP 请求到服务端,服务端正确返回了用户数据。这个是我们平时最常见的一个 HTTP 状态码。 - **200 OK** :请求被成功处理。比如我们发送一个查询用户数据的 HTTP 请求到服务端,服务端正确返回了用户数据。这个是我们平时最常见的一个 HTTP 状态码。
- **201 Created** :请求被成功处理并且在服务端创建了一个新的资源。比如我们通过 POST 请求创建一个新的用户。 - **201 Created** :请求被成功处理并且在服务端创建了一个新的资源。比如我们通过 POST 请求创建一个新的用户。
- **202 Accepted** :服务端已经接收到了请求,但是还未处理。 - **202 Accepted** :服务端已经接收到了请求,但是还未处理。
- **204 No Content** 服务端已经成功处理了请求,但是没有返回任何内容。 - **204 No Content** 服务端已经成功处理了请求,但是没有返回任何内容。
这里格外提一下 204 状态码,平时学习/工作中见到的次数并不多。 这里格外提一下 204 状态码,平时学习/工作中见到的次数并不多。
[HTTP RFC 2616对204状态码的描述](https://tools.ietf.org/html/rfc2616#section-10.2.5)如下: [HTTP RFC 2616 204 状态码的描述](https://tools.ietf.org/html/rfc2616#section-10.2.5)如下:
> The server has fulfilled the request but does not need to return an > The server has fulfilled the request but does not need to return an
> entity-body, and might want to return updated metainformation. The > entity-body, and might want to return updated metainformation. The
@ -40,7 +40,7 @@ HTTP 状态码用于描述 HTTP 请求的结果比如2xx 就代表请求被
> The 204 response MUST NOT include a message-body, and thus is always > The 204 response MUST NOT include a message-body, and thus is always
> terminated by the first empty line after the header fields. > terminated by the first empty line after the header fields.
简单来说204状态码描述的是我们向服务端发送 HTTP 请求之后只关注处理结果是否成功的场景。也就是说我们需要的就是一个结果true/false。 简单来说204 状态码描述的是我们向服务端发送 HTTP 请求之后只关注处理结果是否成功的场景。也就是说我们需要的就是一个结果true/false。
举个例子:你要追一个女孩子,你问女孩子:“我能追你吗?”,女孩子回答:“好!”。我们把这个女孩子当做是服务端就很好理解 204 状态码了。 举个例子:你要追一个女孩子,你问女孩子:“我能追你吗?”,女孩子回答:“好!”。我们把这个女孩子当做是服务端就很好理解 204 状态码了。
@ -51,15 +51,15 @@ HTTP 状态码用于描述 HTTP 请求的结果比如2xx 就代表请求被
### 4xx Client Error客户端错误状态码 ### 4xx Client Error客户端错误状态码
- **400 Bad Request** 发送的HTTP请求存在问题。比如请求参数不合法、请求方法错误。 - **400 Bad Request** 发送的 HTTP 请求存在问题。比如请求参数不合法、请求方法错误。
- **401 Unauthorized** 未认证却请求需要认证之后才能访问的资源。 - **401 Unauthorized** 未认证却请求需要认证之后才能访问的资源。
- **403 Forbidden** 直接拒绝HTTP请求不处理。一般用来针对非法请求。 - **403 Forbidden** :直接拒绝 HTTP 请求,不处理。一般用来针对非法请求。
- **404 Not Found** 你请求的资源未在服务端找到。比如你请求某个用户的信息,服务端并没有找到指定的用户。 - **404 Not Found** 你请求的资源未在服务端找到。比如你请求某个用户的信息,服务端并没有找到指定的用户。
- **409 Conflict** 表示请求的资源与服务端当前的状态存在冲突,请求无法被处理。 - **409 Conflict** 表示请求的资源与服务端当前的状态存在冲突,请求无法被处理。
### 5xx Server Error服务端错误状态码 ### 5xx Server Error服务端错误状态码
- **500 Internal Server Error** 服务端出问题了通常是服务端出Bug了。比如你服务端处理请求的时候突然抛出异常但是异常并未在服务端被正确处理。 - **500 Internal Server Error** 服务端出问题了(通常是服务端出 Bug 了)。比如你服务端处理请求的时候突然抛出异常,但是异常并未在服务端被正确处理。
- **502 Bad Gateway** :我们的网关将请求转发到服务端,但是服务端返回的却是一个错误的响应。 - **502 Bad Gateway** :我们的网关将请求转发到服务端,但是服务端返回的却是一个错误的响应。
### 参考 ### 参考
@ -68,4 +68,3 @@ HTTP 状态码用于描述 HTTP 请求的结果比如2xx 就代表请求被
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status - https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
- https://en.wikipedia.org/wiki/List_of_HTTP_status_codes - https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
- https://segmentfault.com/a/1190000018264501 - https://segmentfault.com/a/1190000018264501

View File

@ -39,7 +39,7 @@ HTTPS 协议中SSL 通道通常使用基于密钥的加密算法,密钥长
保密性好、信任度高。 保密性好、信任度高。
## HTTPS 的核心—SSL/TLS协议 ## HTTPS 的核心—SSL/TLS 协议
HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。 HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。
@ -61,7 +61,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
> >
> 这样,通信信息就不会被其他人截获了,这依赖于私钥的保密性。 > 这样,通信信息就不会被其他人截获了,这依赖于私钥的保密性。
![](./images/http&https/public-key-cryptography.png) ![](./images/http-vs-https/public-key-cryptography.png)
非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数。 非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数。
@ -69,7 +69,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
> >
> 单向陷门函数:一个较弱的单向函数。已知单向陷门函数 f陷门 h给定任意一个输入 x易计算出输出 y=f(x;h);而给定一个输出 y假设存在 f(x;h)=y很难根据 f 来计算出 x但可以根据 f 和 h 来推导出 x。 > 单向陷门函数:一个较弱的单向函数。已知单向陷门函数 f陷门 h给定任意一个输入 x易计算出输出 y=f(x;h);而给定一个输出 y假设存在 f(x;h)=y很难根据 f 来计算出 x但可以根据 f 和 h 来推导出 x。
![单向函数](./images/http&https/OWF.png) ![单向函数](./images/http-vs-https/OWF.png)
上图就是一个单向函数(不是单项陷门函数),假设有一个绝世秘籍,任何知道了这个秘籍的人都可以把苹果汁榨成苹果,那么这个秘籍就是“陷门”了吧。 上图就是一个单向函数(不是单项陷门函数),假设有一个绝世秘籍,任何知道了这个秘籍的人都可以把苹果汁榨成苹果,那么这个秘籍就是“陷门”了吧。
@ -81,7 +81,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
> 对称加密:通信双方共享唯一密钥 k加解密算法已知加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。 > 对称加密:通信双方共享唯一密钥 k加解密算法已知加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。
![](./images/http&https/symmetric-encryption.png) ![](./images/http-vs-https/symmetric-encryption.png)
对称加密的密钥生成代价比公私钥对的生成代价低得多,那么有的人会问了,为什么 SSL/TLS 还需要使用非对称加密呢?因为对称加密的保密性完全依赖于密钥的保密性。在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。 对称加密的密钥生成代价比公私钥对的生成代价低得多,那么有的人会问了,为什么 SSL/TLS 还需要使用非对称加密呢?因为对称加密的保密性完全依赖于密钥的保密性。在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。
@ -99,7 +99,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
> >
> 同样的S 公钥即使做加密也难以避免这种信任性问题C 被 AS 拐跑了! > 同样的S 公钥即使做加密也难以避免这种信任性问题C 被 AS 拐跑了!
![](./images/http&https/attack1.png) ![](./images/http-vs-https/attack1.png)
为了公钥传输的信赖性问题第三方机构应运而生——证书颁发机构CACertificate Authority。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的**电子签名**(见下节)。 为了公钥传输的信赖性问题第三方机构应运而生——证书颁发机构CACertificate Authority。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的**电子签名**(见下节)。
@ -117,7 +117,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
> >
> 客户端对证书数据(包含服务器的公钥)做相同的散列处理,得到摘要,并将该摘要与之前从签名中解码出的摘要做对比,如果相同,则身份验证成功;否则验证失败。 > 客户端对证书数据(包含服务器的公钥)做相同的散列处理,得到摘要,并将该摘要与之前从签名中解码出的摘要做对比,如果相同,则身份验证成功;否则验证失败。
![](./images/http&https/digital-signature.png) ![](./images/http-vs-https/digital-signature.png)
总结来说,带有证书的公钥传输机制如下: 总结来说,带有证书的公钥传输机制如下:
@ -127,7 +127,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。 4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。 5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。
![](./images/http&https/public-key-transmission.png) ![](./images/http-vs-https/public-key-transmission.png)
对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看[数字签名及数字证书原理](https://www.bilibili.com/video/BV18N411X7ty/)这个视频,这是我看过最清晰的讲解。 对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看[数字签名及数字证书原理](https://www.bilibili.com/video/BV18N411X7ty/)这个视频,这是我看过最清晰的讲解。
@ -138,6 +138,3 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
- **端口号** HTTP 默认是 80HTTPS 默认是 443。 - **端口号** HTTP 默认是 80HTTPS 默认是 443。
- **URL 前缀** HTTP 的 URL 前缀是 `http://`HTTPS 的 URL 前缀是 `https://` - **URL 前缀** HTTP 的 URL 前缀是 `http://`HTTPS 的 URL 前缀是 `https://`
- **安全性和资源消耗** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。 - **安全性和资源消耗** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。

View File

@ -1,105 +0,0 @@
---
title: HTTP 1.0 vs HTTP 1.1(应用层)
category: 计算机基础
tag:
- 计算机网络
---
这篇文章会从下面几个维度来对比 HTTP 1.0 和 HTTP 1.1
- 响应状态码
- 缓存处理
- 连接方式
- Host头处理
- 带宽优化
## 响应状态码
HTTP/1.0仅定义了16种状态码。HTTP/1.1中新加入了大量的状态码光是错误响应状态码就新增了24种。比如说`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
## 缓存处理
缓存技术通过避免用户与源服务器的频繁交互,节约了大量的网络带宽,降低了用户接收信息的延迟。
### HTTP/1.0
HTTP/1.0提供的缓存机制非常简单。服务器端使用`Expires`标签来标志(时间)一个响应体,在`Expires`标志时间内的请求,都会获得该响应体缓存。服务器端在初次返回给客户端的响应体中,有一个`Last-Modified`标签,该标签标记了被请求资源在服务器端的最后一次修改。在请求头中,使用`If-Modified-Since`标签,该标签标志一个时间,意为客户端向服务器进行问询:“该时间之后,我要请求的资源是否有被修改过?”通常情况下,请求头中的`If-Modified-Since`的值即为上一次获得该资源时,响应体中的`Last-Modified`的值。
如果服务器接收到了请求头,并判断`If-Modified-Since`时间后,资源确实没有修改过,则返回给客户端一个`304 not modified`响应头,表示”缓冲可用,你从浏览器里拿吧!”。
如果服务器判断`If-Modified-Since`时间后,资源被修改过,则返回给客户端一个`200 OK`的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
![HTTP1.0cache1](./images/http&https/HTTP1.0cache1.png)
![HTTP1.0cache2](./images/http&https/HTTP1.0cache2.png)
### HTTP/1.1
HTTP/1.1的缓存机制在HTTP/1.0的基础上大大增加了灵活性和扩展性。基本工作原理和HTTP/1.0保持不变,而是增加了更多细致的特性。其中,请求头中最常见的特性就是`Cache-Control`详见MDN Web文档 [Cache-Control](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control).
## 连接方式
**HTTP/1.0 默认使用短连接** ,也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源浏览器就会重新建立一个TCP连接这样就会导致有大量的“握手报文”和“挥手报文”占用了带宽。
**为了解决 HTTP/1.0 存在的资源浪费的问题, HTTP/1.1 优化为默认长连接模式 。** 采用长连接模式的请求报文会通知服务端“我向你请求连接并且连接成功建立后请不要关闭”。因此该TCP连接将持续打开为后续的客户端-服务端的数据交互服务。也就是说在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。
如果 TCP 连接一直保持的话也是对资源的浪费,因此,一些服务器软件(如 Apache还会支持超时时间的时间。在超时时间之内没有新的请求达到TCP 连接才会被关闭。
有必要说明的是HTTP/1.0仍提供了长连接选项,即在请求头中加入`Connection: Keep-alive`。同样的在HTTP/1.1中,如果不希望使用长连接选项,也可以在请求头中加入`Connection: close`,这样会通知服务器端:“我不需要长连接,连接成功后即可关闭”。
**HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。**
**实现长连接需要客户端和服务端都支持长连接。**
## Host头处理
域名系统DNS允许多个主机名绑定到同一个IP地址上但是HTTP/1.0并没有考虑这个问题假设我们有一个资源URL是http://example1.org/home.htmlHTTP/1.0的请求报文中,将会请求的是`GET /home.html HTTP/1.0`.也就是不会加入主机名。这样的报文送到服务器端,服务器是理解不了客户端想请求的真正网址。
因此HTTP/1.1在请求头中加入了`Host`字段。加入`Host`字段的报文头部将会是:
```
GET /home.html HTTP/1.1
Host: example1.org
```
这样,服务器端就可以确定客户端想要请求的真正的网址了。
## 带宽优化
### 范围请求
HTTP/1.1引入了范围请求range request机制以避免带宽的浪费。当客户端想请求一个文件的一部分或者需要继续下载一个已经下载了部分但被终止的文件HTTP/1.1可以在请求中加入`Range`头部,以请求(并只能请求字节型数据)数据的一部分。服务器端可以忽略`Range`头部,也可以返回若干`Range`响应。
如果一个响应包含部分数据的话,那么将带有`206 (Partial Content)`状态码。该状态码的意义在于避免了HTTP/1.0代理缓存错误地把该响应认为是一个完整的数据响应,从而把他当作为一个请求的响应缓存。
在范围响应中,`Content-Range`头部标志指示出了该数据块的偏移量和数据块的长度。
### 状态码100
HTTP/1.1中新加入了状态码`100`。该状态码的使用场景为,存在某些较大的文件请求,服务器可能不愿意响应这种请求,此时状态码`100`可以作为指示请求是否会被正常响应,过程如下图:
![HTTP1.1continue1](./images/http&https/HTTP1.1continue1.png)
![HTTP1.1continue2](./images/http&https/HTTP1.1continue2.png)
然而在HTTP/1.0中,并没有`100 (Continue)`状态码,要想触发这一机制,可以发送一个`Expect`头部,其中包含一个`100-continue`的值。
### 压缩
许多格式的数据在传输时都会做预压缩处理。数据的压缩可以大幅优化带宽的利用。然而HTTP/1.0对数据压缩的选项提供的不多不支持压缩细节的选择也无法区分端到端end-to-end压缩或者是逐跳hop-by-hop压缩。
HTTP/1.1则对内容编码content-codings和传输编码transfer-codings做了区分。内容编码总是端到端的传输编码总是逐跳的。
HTTP/1.0包含了`Content-Encoding`头部对消息进行端到端编码。HTTP/1.1加入了`Transfer-Encoding`头部可以对消息进行逐跳传输编码。HTTP/1.1还加入了`Accept-Encoding`头部,是客户端用来指示他能处理什么样的内容编码。
## 总结
1. **连接方式** : HTTP 1.0 为短连接HTTP 1.1 支持长连接。
1. **状态响应码** : HTTP/1.1中新加入了大量的状态码光是错误响应状态码就新增了24种。比如说`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
1. **缓存处理** : 在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准HTTP1.1 则引入了更多的缓存控制策略例如 Entity tagIf-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
1. **带宽优化及网络连接的使用** :HTTP1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。
1. **Host头处理** : HTTP/1.1在请求头中加入了`Host`字段。
## 参考资料
[Key differences between HTTP/1.0 and HTTP/1.1](http://www.ra.ethz.ch/cdstore/www8/data/2136/pdf/pd1.pdf)

View File

@ -0,0 +1,105 @@
---
title: HTTP 1.0 vs HTTP 1.1(应用层)
category: 计算机基础
tag:
- 计算机网络
---
这篇文章会从下面几个维度来对比 HTTP 1.0 和 HTTP 1.1
- 响应状态码
- 缓存处理
- 连接方式
- Host 头处理
- 带宽优化
## 响应状态码
HTTP/1.0 仅定义了 16 种状态码。HTTP/1.1 中新加入了大量的状态码,光是错误响应状态码就新增了 24 种。比如说,`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
## 缓存处理
缓存技术通过避免用户与源服务器的频繁交互,节约了大量的网络带宽,降低了用户接收信息的延迟。
### HTTP/1.0
HTTP/1.0 提供的缓存机制非常简单。服务器端使用`Expires`标签来标志(时间)一个响应体,在`Expires`标志时间内的请求,都会获得该响应体缓存。服务器端在初次返回给客户端的响应体中,有一个`Last-Modified`标签,该标签标记了被请求资源在服务器端的最后一次修改。在请求头中,使用`If-Modified-Since`标签,该标签标志一个时间,意为客户端向服务器进行问询:“该时间之后,我要请求的资源是否有被修改过?”通常情况下,请求头中的`If-Modified-Since`的值即为上一次获得该资源时,响应体中的`Last-Modified`的值。
如果服务器接收到了请求头,并判断`If-Modified-Since`时间后,资源确实没有修改过,则返回给客户端一个`304 not modified`响应头,表示”缓冲可用,你从浏览器里拿吧!”。
如果服务器判断`If-Modified-Since`时间后,资源被修改过,则返回给客户端一个`200 OK`的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
![HTTP1.0cache1](./images/http-vs-https/HTTP1.0cache1.png)
![HTTP1.0cache2](./images/http-vs-https/HTTP1.0cache2.png)
### HTTP/1.1
HTTP/1.1 的缓存机制在 HTTP/1.0 的基础上,大大增加了灵活性和扩展性。基本工作原理和 HTTP/1.0 保持不变,而是增加了更多细致的特性。其中,请求头中最常见的特性就是`Cache-Control`,详见 MDN Web 文档 [Cache-Control](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control).
## 连接方式
**HTTP/1.0 默认使用短连接** ,也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 TCP 连接,这样就会导致有大量的“握手报文”和“挥手报文”占用了带宽。
**为了解决 HTTP/1.0 存在的资源浪费的问题, HTTP/1.1 优化为默认长连接模式 。** 采用长连接模式的请求报文会通知服务端:“我向你请求连接,并且连接成功建立后,请不要关闭”。因此,该 TCP 连接将持续打开,为后续的客户端-服务端的数据交互服务。也就是说在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。
如果 TCP 连接一直保持的话也是对资源的浪费,因此,一些服务器软件(如 Apache还会支持超时时间的时间。在超时时间之内没有新的请求达到TCP 连接才会被关闭。
有必要说明的是HTTP/1.0 仍提供了长连接选项,即在请求头中加入`Connection: Keep-alive`。同样的,在 HTTP/1.1 中,如果不希望使用长连接选项,也可以在请求头中加入`Connection: close`,这样会通知服务器端:“我不需要长连接,连接成功后即可关闭”。
**HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。**
**实现长连接需要客户端和服务端都支持长连接。**
## Host 头处理
域名系统DNS允许多个主机名绑定到同一个 IP 地址上,但是 HTTP/1.0 并没有考虑这个问题,假设我们有一个资源 URL 是http://example1.org/home.htmlHTTP/1.0的请求报文中,将会请求的是`GET /home.html HTTP/1.0`.也就是不会加入主机名。这样的报文送到服务器端,服务器是理解不了客户端想请求的真正网址。
因此HTTP/1.1 在请求头中加入了`Host`字段。加入`Host`字段的报文头部将会是:
```
GET /home.html HTTP/1.1
Host: example1.org
```
这样,服务器端就可以确定客户端想要请求的真正的网址了。
## 带宽优化
### 范围请求
HTTP/1.1 引入了范围请求range request机制以避免带宽的浪费。当客户端想请求一个文件的一部分或者需要继续下载一个已经下载了部分但被终止的文件HTTP/1.1 可以在请求中加入`Range`头部,以请求(并只能请求字节型数据)数据的一部分。服务器端可以忽略`Range`头部,也可以返回若干`Range`响应。
如果一个响应包含部分数据的话,那么将带有`206 (Partial Content)`状态码。该状态码的意义在于避免了 HTTP/1.0 代理缓存错误地把该响应认为是一个完整的数据响应,从而把他当作为一个请求的响应缓存。
在范围响应中,`Content-Range`头部标志指示出了该数据块的偏移量和数据块的长度。
### 状态码 100
HTTP/1.1 中新加入了状态码`100`。该状态码的使用场景为,存在某些较大的文件请求,服务器可能不愿意响应这种请求,此时状态码`100`可以作为指示请求是否会被正常响应,过程如下图:
![HTTP1.1continue1](./images/http-vs-https/HTTP1.1continue1.png)
![HTTP1.1continue2](./images/http-vs-https/HTTP1.1continue2.png)
然而在 HTTP/1.0 中,并没有`100 (Continue)`状态码,要想触发这一机制,可以发送一个`Expect`头部,其中包含一个`100-continue`的值。
### 压缩
许多格式的数据在传输时都会做预压缩处理。数据的压缩可以大幅优化带宽的利用。然而HTTP/1.0 对数据压缩的选项提供的不多不支持压缩细节的选择也无法区分端到端end-to-end压缩或者是逐跳hop-by-hop压缩。
HTTP/1.1 则对内容编码content-codings和传输编码transfer-codings做了区分。内容编码总是端到端的传输编码总是逐跳的。
HTTP/1.0 包含了`Content-Encoding`头部对消息进行端到端编码。HTTP/1.1 加入了`Transfer-Encoding`头部可以对消息进行逐跳传输编码。HTTP/1.1 还加入了`Accept-Encoding`头部,是客户端用来指示他能处理什么样的内容编码。
## 总结
1. **连接方式** : HTTP 1.0 为短连接HTTP 1.1 支持长连接。
1. **状态响应码** : HTTP/1.1 中新加入了大量的状态码,光是错误响应状态码就新增了 24 种。比如说,`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
1. **缓存处理** : 在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准HTTP1.1 则引入了更多的缓存控制策略例如 Entity tagIf-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
1. **带宽优化及网络连接的使用** :HTTP1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。
1. **Host 头处理** : HTTP/1.1 在请求头中加入了`Host`字段。
## 参考资料
[Key differences between HTTP/1.0 and HTTP/1.1](http://www.ra.ethz.ch/cdstore/www8/data/2136/pdf/pd1.pdf)

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -5,9 +5,9 @@ tag:
- 计算机网络 - 计算机网络
--- ---
> 本文整理完善自[TCP/IP常见攻击手段 - 暖蓝笔记 - 2021](https://mp.weixin.qq.com/s/AZwWrOlLxRSSi-ywBgZ0fA)这篇文章。 > 本文整理完善自[TCP/IP 常见攻击手段 - 暖蓝笔记 - 2021](https://mp.weixin.qq.com/s/AZwWrOlLxRSSi-ywBgZ0fA)这篇文章。
这篇文章的内容主要是介绍 TCP/IP常见攻击手段尤其是 DDoS 攻击,也会补充一些其他的常见网络攻击手段。 这篇文章的内容主要是介绍 TCP/IP 常见攻击手段,尤其是 DDoS 攻击,也会补充一些其他的常见网络攻击手段。
## IP 欺骗 ## IP 欺骗
@ -153,15 +153,15 @@ HTTP 洪水攻击有两种:
### DNS Flood 是什么? ### DNS Flood 是什么?
域名系统DNS服务器是互联网的“电话簿“互联网设备通过这些服务器来查找特定 Web 服务器以便访问互联网内容。DNS Flood攻击是一种分布式拒绝服务DDoS攻击攻击者用大量流量淹没某个域的 DNS 服务器,以尝试中断该域的 DNS 解析。如果用户无法找到电话簿,就无法查找到用于调用特定资源的地址。通过中断 DNS 解析DNS Flood攻击将破坏网站、API 或 Web 应用程序响应合法流量的能力。很难将 DNS Flood攻击与正常的大流量区分开来因为这些大规模流量往往来自多个唯一地址查询该域的真实记录模仿合法流量。 域名系统DNS服务器是互联网的“电话簿“互联网设备通过这些服务器来查找特定 Web 服务器以便访问互联网内容。DNS Flood 攻击是一种分布式拒绝服务DDoS攻击攻击者用大量流量淹没某个域的 DNS 服务器,以尝试中断该域的 DNS 解析。如果用户无法找到电话簿,就无法查找到用于调用特定资源的地址。通过中断 DNS 解析DNS Flood 攻击将破坏网站、API 或 Web 应用程序响应合法流量的能力。很难将 DNS Flood 攻击与正常的大流量区分开来,因为这些大规模流量往往来自多个唯一地址,查询该域的真实记录,模仿合法流量。
### DNS Flood 的攻击原理是什么? ### DNS Flood 的攻击原理是什么?
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/97ea11a212924900b10d159226783887~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/97ea11a212924900b10d159226783887~tplv-k3u1fbpfcp-zoom-1.image)
域名系统的功能是将易于记忆的名称例如example.com转换成难以记住的网站服务器地址例如192.168.0.1),因此成功攻击 DNS 基础设施将导致大多数人无法使用互联网。DNS Flood攻击是一种相对较新的基于 DNS 的攻击,这种攻击是在高带宽[物联网IoT](https://www.cloudflare.com/learning/ddos/glossary/internet-of-things-iot/)[僵尸网络](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-botnet/)(如 [Mirai](https://www.cloudflare.com/learning/ddos/glossary/mirai-botnet/)兴起后激增的。DNS Flood攻击使用 IP 摄像头、DVR 盒和其他 IoT 设备的高带宽连接直接淹没主要提供商的 DNS 服务器。来自 IoT 设备的大量请求淹没 DNS 提供商的服务,阻止合法用户访问提供商的 DNS 服务器。 域名系统的功能是将易于记忆的名称(例如 example.com转换成难以记住的网站服务器地址例如 192.168.0.1),因此成功攻击 DNS 基础设施将导致大多数人无法使用互联网。DNS Flood 攻击是一种相对较新的基于 DNS 的攻击,这种攻击是在高带宽[物联网IoT](https://www.cloudflare.com/learning/ddos/glossary/internet-of-things-iot/)[僵尸网络](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-botnet/)(如 [Mirai](https://www.cloudflare.com/learning/ddos/glossary/mirai-botnet/)兴起后激增的。DNS Flood 攻击使用 IP 摄像头、DVR 盒和其他 IoT 设备的高带宽连接直接淹没主要提供商的 DNS 服务器。来自 IoT 设备的大量请求淹没 DNS 提供商的服务,阻止合法用户访问提供商的 DNS 服务器。
DNS Flood攻击不同于 [DNS 放大攻击](https://www.cloudflare.com/zh-cn/learning/ddos/dns-amplification-ddos-attack/)。与 DNS Flood攻击不同DNS 放大攻击反射并放大不安全 DNS 服务器的流量以便隐藏攻击的源头并提高攻击的有效性。DNS 放大攻击使用连接带宽较小的设备向不安全的 DNS 服务器发送无数请求。这些设备对非常大的 DNS 记录发出小型请求,但在发出请求时,攻击者伪造返回地址为目标受害者。这种放大效果让攻击者能借助有限的攻击资源来破坏较大的目标。 DNS Flood 攻击不同于 [DNS 放大攻击](https://www.cloudflare.com/zh-cn/learning/ddos/dns-amplification-ddos-attack/)。与 DNS Flood 攻击不同DNS 放大攻击反射并放大不安全 DNS 服务器的流量以便隐藏攻击的源头并提高攻击的有效性。DNS 放大攻击使用连接带宽较小的设备向不安全的 DNS 服务器发送无数请求。这些设备对非常大的 DNS 记录发出小型请求,但在发出请求时,攻击者伪造返回地址为目标受害者。这种放大效果让攻击者能借助有限的攻击资源来破坏较大的目标。
### 如何防护 DNS Flood? ### 如何防护 DNS Flood?

View File

@ -5,6 +5,8 @@ tag:
- 计算机网络 - 计算机网络
--- ---
<!-- @include: @small-advertisement.snippet.md -->
上篇主要是计算机网络基础和应用层相关的内容。 上篇主要是计算机网络基础和应用层相关的内容。
## 计算机网络基础 ## 计算机网络基础
@ -38,7 +40,7 @@ tag:
![TCP/IP 四层模型](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-ip-4-model.png) ![TCP/IP 四层模型](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-ip-4-model.png)
关于每一层作用的详细介绍,请看 [OSI 和 TCP/IP 网络分层模型详解(基础)](https://javaguide.cn/cs-basics/network/osi&tcp-ip-model.html) 这篇文章。 关于每一层作用的详细介绍,请看 [OSI 和 TCP/IP 网络分层模型详解(基础)](https://javaguide.cn/cs-basics/network/osi-and-tcp-ip-model.html) 这篇文章。
#### 为什么网络要分层? #### 为什么网络要分层?
@ -133,7 +135,7 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
### HTTP Header 中常见的字段有哪些? ### HTTP Header 中常见的字段有哪些?
| 请求头字段名 | 说明 | 示例 | | 请求头字段名 | 说明 | 示例 |
| :------------------ | :----------------------------------------------------------- | :----------------------------------------------------------- | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------- |
| Accept | 能够接受的回应内容类型Content-Types。 | Accept: text/plain | | Accept | 能够接受的回应内容类型Content-Types。 | Accept: text/plain |
| Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 | | Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 |
| Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT | | Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT |
@ -169,14 +171,14 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
### HTTP 和 HTTPS 有什么区别?(重要) ### HTTP 和 HTTPS 有什么区别?(重要)
![HTTP 和 HTTPS 对比](https://oss.javaguide.cn/github/javaguide/cs-basics/network/http-vs-https.png) ![HTTP 和 HTTPS 对比](https://oss.javaguide.cn/github/javaguide/cs-basics/network/http1.0-vs-http1.1.png)
- **端口号** HTTP 默认是 80HTTPS 默认是 443。 - **端口号** HTTP 默认是 80HTTPS 默认是 443。
- **URL 前缀** HTTP 的 URL 前缀是 `http://`HTTPS 的 URL 前缀是 `https://` - **URL 前缀** HTTP 的 URL 前缀是 `http://`HTTPS 的 URL 前缀是 `https://`
- **安全性和资源消耗** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。 - **安全性和资源消耗** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
- **SEO搜索引擎优化** :搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。 - **SEO搜索引擎优化** :搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。
关于 HTTP 和 HTTPS 更详细的对比总结,可以看我写的这篇文章:[HTTP vs HTTPS应用层](./http&https.md) 。 关于 HTTP 和 HTTPS 更详细的对比总结,可以看我写的这篇文章:[HTTP vs HTTPS应用层](./http-vs-https.md) 。
### HTTP/1.0 和 HTTP/1.1 有什么区别? ### HTTP/1.0 和 HTTP/1.1 有什么区别?
@ -188,7 +190,7 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
- **带宽** HTTP/1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。 - **带宽** HTTP/1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。
- **Host 头Host Header处理** :HTTP/1.1 引入了 Host 头字段,允许在同一 IP 地址上托管多个域名,从而支持虚拟主机的功能。而 HTTP/1.0 没有 Host 头字段,无法实现虚拟主机。 - **Host 头Host Header处理** :HTTP/1.1 引入了 Host 头字段,允许在同一 IP 地址上托管多个域名,从而支持虚拟主机的功能。而 HTTP/1.0 没有 Host 头字段,无法实现虚拟主机。
关于 HTTP/1.0 和 HTTP/1.1 更详细的对比总结,可以看我写的这篇文章:[HTTP/1.0 vs HTTP/1.1(应用层)](./http1.0&http1.1.md) 。 关于 HTTP/1.0 和 HTTP/1.1 更详细的对比总结,可以看我写的这篇文章:[HTTP/1.0 vs HTTP/1.1(应用层)](./http1.0-vs-http1.1.md) 。
### HTTP/1.1 和 HTTP/2.0 有什么区别? ### HTTP/1.1 和 HTTP/2.0 有什么区别?

View File

@ -96,21 +96,19 @@ tag:
每个连入互联网的设备或域(如计算机、服务器、路由器等)都被分配一个 **IP 地址Internet Protocol address**,作为唯一标识符。每个 IP 地址都是一个字符序列,如 192.168.1.1IPv4、2001:0db8:85a3:0000:0000:8a2e:0370:7334IPv6 每个连入互联网的设备或域(如计算机、服务器、路由器等)都被分配一个 **IP 地址Internet Protocol address**,作为唯一标识符。每个 IP 地址都是一个字符序列,如 192.168.1.1IPv4、2001:0db8:85a3:0000:0000:8a2e:0370:7334IPv6
当网络设备发送IP数据包时数据包中包含了 **源IP地址** 和 **目的IP地址** 。源IP地址用于标识数据包的发送方设备或域而目的IP地址则用于标识数据包的接收方设备或域。这类似于一封邮件中同时包含了目的地地址和回邮地址。 当网络设备发送 IP 数据包时,数据包中包含了 **源 IP 地址** 和 **目的 IP 地址** 。源 IP 地址用于标识数据包的发送方设备或域,而目的 IP 地址则用于标识数据包的接收方设备或域。这类似于一封邮件中同时包含了目的地地址和回邮地址。
网络设备根据目的IP地址来判断数据包的目的地并将数据包转发到正确的目的地网络或子网络从而实现了设备间的通信。 网络设备根据目的 IP 地址来判断数据包的目的地,并将数据包转发到正确的目的地网络或子网络,从而实现了设备间的通信。
这种基于IP地址的寻址方式是互联网通信的基础它允许数据包在不同的网络之间传递从而实现了全球范围内的网络互联互通。IP地址的唯一性和全局性保证了网络中的每个设备都可以通过其独特的IP地址进行标识和寻址。 这种基于 IP 地址的寻址方式是互联网通信的基础它允许数据包在不同的网络之间传递从而实现了全球范围内的网络互联互通。IP 地址的唯一性和全局性保证了网络中的每个设备都可以通过其独特的 IP 地址进行标识和寻址。
![IP 地址使数据包到达其目的地](https://oss.javaguide.cn/github/javaguide/cs-basics/network/internet_protocol_ip_address_diagram.png) ![IP 地址使数据包到达其目的地](https://oss.javaguide.cn/github/javaguide/cs-basics/network/internet_protocol_ip_address_diagram.png)
### 什么是 IP 地址过滤? ### 什么是 IP 地址过滤?
**IP 地址过滤IP Address Filtering** 简单来说就是限制或阻止特定IP地址或IP地址范围的访问。例如你有一个图片服务突然被某一个 IP 地址攻击,那我们就可以禁止这个 IP 地址访问图片服务。 **IP 地址过滤IP Address Filtering** 简单来说就是限制或阻止特定 IP 地址或 IP 地址范围的访问。例如,你有一个图片服务突然被某一个 IP 地址攻击,那我们就可以禁止这个 IP 地址访问图片服务。
IP地址过滤是一种简单的网络安全措施实际应用中一般会结合其他网络安全措施如认证、授权、加密等一起使用。单独使用 IP地址过滤并不能完全保证网络的安全。 IP 地址过滤是一种简单的网络安全措施,实际应用中一般会结合其他网络安全措施,如认证、授权、加密等一起使用。单独使用 IP 地址过滤并不能完全保证网络的安全。
### IPv4 和 IPv6 有什么区别? ### IPv4 和 IPv6 有什么区别?

View File

@ -5,7 +5,6 @@ tag:
- 计算机网络 - 计算机网络
--- ---
为了准确无误地把数据送达目标处TCP 协议采用了三次握手策略。 为了准确无误地把数据送达目标处TCP 协议采用了三次握手策略。
## 建立连接-TCP 三次握手 ## 建立连接-TCP 三次握手
@ -14,16 +13,16 @@ tag:
建立一个 TCP 连接需要“三次握手”,缺一不可 建立一个 TCP 连接需要“三次握手”,缺一不可
- **一次握手**:客户端发送带有 SYNSEQ=x 标志的数据包 -> 服务端,然后客户端进入 **SYN_SEND** 状态,等待服务器的确认; - **一次握手**:客户端发送带有 SYNSEQ=x 标志的数据包 -> 服务端,然后客户端进入 **SYN_SEND** 状态,等待服务器的确认;
- **二次握手**:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 > 客户端,然后服务端进入 **SYN_RECV** 状态 - **二次握手**:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 > 客户端,然后服务端进入 **SYN_RECV** 状态
- **三次握手**:客户端发送带有 ACK(ACK=y+1) 标志的数据包 > 服务端,然后客户端和服务器端都进入**ESTABLISHED** 状态完成TCP三次握手。 - **三次握手**:客户端发送带有 ACK(ACK=y+1) 标志的数据包 > 服务端,然后客户端和服务器端都进入**ESTABLISHED** 状态,完成 TCP 三次握手。
**当建立了 3 次握手之后,客户端和服务端就可以传输数据啦!** **当建立了 3 次握手之后,客户端和服务端就可以传输数据啦!**
### 为什么要三次握手? ### 为什么要三次握手?
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。 三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
1. **第一次握手** Client 什么都不能确认Server 确认了对方发送正常,自己接收正常 1. **第一次握手** Client 什么都不能确认Server 确认了对方发送正常,自己接收正常
2. **第二次握手** Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:对方发送正常,自己接收正常 2. **第二次握手** Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:对方发送正常,自己接收正常
3. **第三次握手** Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:自己发送、接收正常,对方发送、接收正常 3. **第三次握手** Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:自己发送、接收正常,对方发送、接收正常
@ -32,7 +31,7 @@ tag:
更详细的解答可以看这个:[TCP 为什么是三次握手,而不是两次或四次? - 车小胖的回答 - 知乎](https://www.zhihu.com/question/24853633/answer/115173386) 。 更详细的解答可以看这个:[TCP 为什么是三次握手,而不是两次或四次? - 车小胖的回答 - 知乎](https://www.zhihu.com/question/24853633/answer/115173386) 。
### 第2次握手传回了ACK为什么还要传回SYN ### 第 2 次握手传回了 ACK为什么还要传回 SYN
服务端传回发送端所发送的 ACK 是为了告诉客户端:“我接收到的信息确实就是你所发送的信号了”,这表明从客户端到服务端的通信是正常的。回传 SYN 则是为了建立并确认从服务端到客户端的通信。 服务端传回发送端所发送的 ACK 是为了告诉客户端:“我接收到的信息确实就是你所发送的信号了”,这表明从客户端到服务端的通信是正常的。回传 SYN 则是为了建立并确认从服务端到客户端的通信。
@ -53,7 +52,7 @@ tag:
### 为什么要四次挥手? ### 为什么要四次挥手?
TCP是全双工通信可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候则发出连接释放通知对方确认后就完全关闭了 TCP 连接。 TCP 是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
举个例子A 和 B 打电话,通话即将结束后。 举个例子A 和 B 打电话,通话即将结束后。
@ -64,28 +63,22 @@ TCP是全双工通信可以双向传输数据。任何一方都可以在数
### 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手? ### 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK表示接收到了断开连接的请求。等到数据发完之后再发 FIN断开服务器到客户端的数据传送。 因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK表示接收到了断开连接的请求。等到数据发完之后再发 FIN断开服务器到客户端的数据传送。
### 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样? ### 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
客户端没有收到 ACK 确认,会重新发送 FIN 请求。 客户端没有收到 ACK 确认,会重新发送 FIN 请求。
### 为什么第四次挥手客户端需要等待 2\*MSL报文段最长寿命时间后才进入 CLOSED 状态? ### 为什么第四次挥手客户端需要等待 2\*MSL报文段最长寿命时间后才进入 CLOSED 状态?
第四次挥手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN如果客户端在 2\*MSL 的时间内收到了 FIN就会重新发送 ACK 并再次等待 2MSL防止 Server 没有收到 ACK 而不断重发 FIN。 第四次挥手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN如果客户端在 2\*MSL 的时间内收到了 FIN就会重新发送 ACK 并再次等待 2MSL防止 Server 没有收到 ACK 而不断重发 FIN。
> **MSL(Maximum Segment Lifetime)** : 一个片段在网络中最大的存活时间2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSLClient 都没有再次收到 FIN那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接。 > **MSL(Maximum Segment Lifetime)** : 一个片段在网络中最大的存活时间2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSLClient 都没有再次收到 FIN那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接。
## 参考 ## 参考
- 《计算机网络(第 7 版)》 - 《计算机网络(第 7 版)》
- 《图解 HTTP》 - 《图解 HTTP》
- TCP and UDP Tutorialhttps://www.9tut.com/tcp-and-udp-tutorial - TCP and UDP Tutorialhttps://www.9tut.com/tcp-and-udp-tutorial

View File

@ -10,7 +10,7 @@ tag:
1. **基于数据块传输** :应用数据被分割成 TCP 认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段。 1. **基于数据块传输** :应用数据被分割成 TCP 认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段。
2. **对失序数据包重新排序以及去重**TCP 为了保证不发生丢包,就给每个包一个序列号,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。 2. **对失序数据包重新排序以及去重**TCP 为了保证不发生丢包,就给每个包一个序列号,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。
3. **校验和** : TCP 将保持它首部和数据的检验和。这是一个端到端的检验和目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错TCP 将丢弃这个报文段和不确认收到此报文段。 3. **校验和** : TCP 将保持它首部和数据的检验和。这是一个端到端的检验和目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错TCP 将丢弃这个报文段和不确认收到此报文段。
4. **超时重传** : 当发送方发送数据之后它启动一个定时器等待目的端确认收到这个报文段。接收端实体对已成功收到的包发回一个相应的确认信息ACK。如果发送端实体在合理的往返时延RTT内未收到确认消息那么对应的数据包就被假设为[已丢失](https://zh.wikipedia.org/wiki/丢包 )并进行重传。 4. **超时重传** : 当发送方发送数据之后它启动一个定时器等待目的端确认收到这个报文段。接收端实体对已成功收到的包发回一个相应的确认信息ACK。如果发送端实体在合理的往返时延RTT内未收到确认消息那么对应的数据包就被假设为[已丢失](https://zh.wikipedia.org/wiki/丢包)并进行重传。
5. **流量控制** : TCP 连接的每一方都有固定大小的缓冲空间TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据能提示发送方降低发送的速率防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议TCP 利用滑动窗口实现流量控制)。 5. **流量控制** : TCP 连接的每一方都有固定大小的缓冲空间TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据能提示发送方降低发送的速率防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议TCP 利用滑动窗口实现流量控制)。
6. **拥塞控制** : 当网络拥塞时,减少数据的发送。 6. **拥塞控制** : 当网络拥塞时,减少数据的发送。
@ -25,16 +25,16 @@ tag:
- 发送端不等同于客户端 - 发送端不等同于客户端
- 接收端不等同于服务端 - 接收端不等同于服务端
TCP 为全双工(Full-Duplex, FDX)通信双方可以进行双向通信客户端和服务端既可能是发送端又可能是服务端。因此两端各有一个发送缓冲区与接收缓冲区两端都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制TCP传输速率不能大于应用的数据处理速率。通信双方的发送窗口和接收窗口的要求相同 TCP 为全双工(Full-Duplex, FDX)通信双方可以进行双向通信客户端和服务端既可能是发送端又可能是服务端。因此两端各有一个发送缓冲区与接收缓冲区两端都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制TCP 传输速率不能大于应用的数据处理速率)。通信双方的发送窗口和接收窗口的要求相同
**TCP 发送窗口可以划分成四个部分** **TCP 发送窗口可以划分成四个部分**
1. 已经发送并且确认的TCP段已经发送并确认 1. 已经发送并且确认的 TCP 段(已经发送并确认);
2. 已经发送但是没有确认的TCP段已经发送未确认 2. 已经发送但是没有确认的 TCP 段(已经发送未确认);
3. 未发送但是接收方准备接收的TCP段可以发送 3. 未发送但是接收方准备接收的 TCP 段(可以发送);
4. 未发送并且接收方也并未准备接受的TCP段不可发送 4. 未发送并且接收方也并未准备接受的 TCP 段(不可发送)。
**TCP发送窗口结构图示** **TCP 发送窗口结构图示**
![TCP发送窗口结构](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-send-window.png) ![TCP发送窗口结构](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-send-window.png)
@ -48,7 +48,7 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
1. 已经接收并且已经确认的 TCP 段(已经接收并确认); 1. 已经接收并且已经确认的 TCP 段(已经接收并确认);
2. 等待接收且允许发送方发送 TCP 段(可以接收未确认); 2. 等待接收且允许发送方发送 TCP 段(可以接收未确认);
3. 不可接收且不允许发送方发送TCP段不可接收 3. 不可接收且不允许发送方发送 TCP 段(不可接收)。
**TCP 接收窗口结构图示** **TCP 接收窗口结构图示**
@ -60,7 +60,6 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
## TCP 的拥塞控制是怎么实现的? ## TCP 的拥塞控制是怎么实现的?
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。 在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
![TCP的拥塞控制](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-congestion-control.png) ![TCP的拥塞控制](https://oss.javaguide.cn/github/javaguide/cs-basics/network/tcp-congestion-control.png)
@ -100,7 +99,6 @@ ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
### 连续 ARQ 协议 ### 连续 ARQ 协议
连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。 连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。
**优点:** 信道利用率高,容易实现,即使确认丢失,也不必重传。 **优点:** 信道利用率高,容易实现,即使确认丢失,也不必重传。
@ -109,11 +107,10 @@ ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
## Reference ## Reference
1. 《计算机网络(第 7 版)》 1. 《计算机网络(第 7 版)》
2. 《图解 HTTP》 2. 《图解 HTTP》
3. [https://www.9tut.com/tcp-and-udp-tutorial](https://www.9tut.com/tcp-and-udp-tutorial ) 3. [https://www.9tut.com/tcp-and-udp-tutorial](https://www.9tut.com/tcp-and-udp-tutorial)
4. [https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md](https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md ) 4. [https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md](https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md)
5. TCP Flow Control—[https://www.brianstorti.com/tcp-flow-control/](https://www.brianstorti.com/tcp-flow-control/ ) 5. TCP Flow Control—[https://www.brianstorti.com/tcp-flow-control/](https://www.brianstorti.com/tcp-flow-control/)
6. TCP 流量控制(Flow Control)https://notfalse.net/24/tcp-flow-control 6. TCP 流量控制(Flow Control)https://notfalse.net/24/tcp-flow-control
7. TCP之滑动窗口原理 : https://cloud.tencent.com/developer/article/1857363 7. TCP 之滑动窗口原理 : https://cloud.tencent.com/developer/article/1857363

View File

@ -339,7 +339,7 @@ Linux 系统是一个多用户多任务的分时操作系统,任何一个要
- `top [选项]`:用于实时查看系统的 CPU 使用率、内存使用率、进程信息等。 - `top [选项]`:用于实时查看系统的 CPU 使用率、内存使用率、进程信息等。
- `htop [选项]`:类似于 `top`,但提供了更加交互式和友好的界面,可让用户交互式操作,支持颜色主题,可横向或纵向滚动浏览进程列表,并支持鼠标操作。 - `htop [选项]`:类似于 `top`,但提供了更加交互式和友好的界面,可让用户交互式操作,支持颜色主题,可横向或纵向滚动浏览进程列表,并支持鼠标操作。
- `uptime [选项]`:用于查看系统总共运行了多长时间、系统的平均负载等信息。 - `uptime [选项]`:用于查看系统总共运行了多长时间、系统的平均负载等信息。
- `vmstat [间隔时间] [重复次数]` vmstat Virtual Memory Statistics 的含义为显示虚拟内存状态但是它可以报告关于进程、内存、I/O等系统整体运行状态。 - `vmstat [间隔时间] [重复次数]` vmstat Virtual Memory Statistics 的含义为显示虚拟内存状态但是它可以报告关于进程、内存、I/O 等系统整体运行状态。
- `free [选项]`:用于查看系统的内存使用情况,包括已用内存、可用内存、缓冲区和缓存等。 - `free [选项]`:用于查看系统的内存使用情况,包括已用内存、可用内存、缓冲区和缓存等。
- `df [选项] [文件系统]`:用于查看系统的磁盘空间使用情况,包括磁盘空间的总量、已使用量和可用量等,可以指定文件系统上。例如:`df -a`,查看全部文件系统。 - `df [选项] [文件系统]`:用于查看系统的磁盘空间使用情况,包括磁盘空间的总量、已使用量和可用量等,可以指定文件系统上。例如:`df -a`,查看全部文件系统。
- `du [选项] [文件]`:用于查看指定目录或文件的磁盘空间使用情况,可以指定不同的选项来控制输出格式和单位。 - `du [选项] [文件]`:用于查看指定目录或文件的磁盘空间使用情况,可以指定不同的选项来控制输出格式和单位。

View File

@ -12,6 +12,8 @@ head:
content: 很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如进程管理、内存管理、虚拟内存等等。 content: 很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如进程管理、内存管理、虚拟内存等等。
--- ---
<!-- @include: @small-advertisement.snippet.md -->
很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如 **用户态和内核态、系统调用、进程和线程、死锁、内存管理、虚拟内存、文件系统**等等。 很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如 **用户态和内核态、系统调用、进程和线程、死锁、内存管理、虚拟内存、文件系统**等等。
这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。 这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。
@ -45,8 +47,6 @@ head:
![Kernel_Layout](https://oss.javaguide.cn/2020-8/Kernel_Layout.png) ![Kernel_Layout](https://oss.javaguide.cn/2020-8/Kernel_Layout.png)
### 操作系统主要有哪些功能? ### 操作系统主要有哪些功能?
从资源管理的角度来看,操作系统有 6 大功能: 从资源管理的角度来看,操作系统有 6 大功能:

View File

@ -115,7 +115,7 @@ ER 图由下面 3 个要素组成:
- `truncate` (清空数据) : `truncate table 表名` ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。 - `truncate` (清空数据) : `truncate table 表名` ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。
- `delete`(删除数据) : `delete from 表名 where 列名=值`,删除某一行的数据,如果不加 `where` 子句和`truncate table 表名`作用类似。 - `delete`(删除数据) : `delete from 表名 where 列名=值`,删除某一行的数据,如果不加 `where` 子句和`truncate table 表名`作用类似。
`truncate` 和不带 where``子句的 `delete`、以及 `drop` 都会删除表内的数据,但是 **`truncate` 和 `delete` 只删除数据不删除表的结构(定义),执行 `drop` 语句,此表的结构也会删除,也就是执行 `drop` 之后对应的表不复存在。** `truncate` 和不带 `where`子句的 `delete`、以及 `drop` 都会删除表内的数据,但是 **`truncate``delete` 只删除数据不删除表的结构(定义),执行 `drop` 语句,此表的结构也会删除,也就是执行`drop` 之后对应的表不复存在。**
### 属于不同的数据库语言 ### 属于不同的数据库语言

View File

@ -5,10 +5,9 @@ tag:
- 数据库基础 - 数据库基础
--- ---
MySQL 字符编码集中有两套 UTF-8 编码实现:**`utf8`** 和 **`utf8mb4`**。 MySQL 字符编码集中有两套 UTF-8 编码实现:**`utf8`** 和 **`utf8mb4`**。
如果使用 **`utf8`** 的话存储emoji 符号和一些比较复杂的汉字、繁体字就会出错。 如果使用 **`utf8`** 的话,存储 emoji 符号和一些比较复杂的汉字、繁体字就会出错。
为什么会这样呢?这篇文章可以从源头给你解答。 为什么会这样呢?这篇文章可以从源头给你解答。
@ -65,7 +64,7 @@ GB18030 完全兼容 GB2312 和 GBK 字符集,纳入中国国内少数民族
BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。 BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
### Unicode & UTF-8编码 ### Unicode & UTF-8 编码
为了更加适合本国语言,诞生了很多种字符集。 为了更加适合本国语言,诞生了很多种字符集。
@ -73,7 +72,7 @@ BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
就比如说你使用 UTF-8 编码方式打开 GB2312 编码格式的文件就会出现乱码。示例:“牛”这个汉字 GB2312 编码后的十六进制数值为 “C5A3”而 “C5A3” 用 UTF-8 解码之后得到的却是 “ţ”。 就比如说你使用 UTF-8 编码方式打开 GB2312 编码格式的文件就会出现乱码。示例:“牛”这个汉字 GB2312 编码后的十六进制数值为 “C5A3”而 “C5A3” 用 UTF-8 解码之后得到的却是 “ţ”。
你可以通过这个网站在线进行编码和解码https://www.haomeili.net/HanZi/ZiFuBianMaZhuanHuan 你可以通过这个网站在线进行编码和解码:<https://www.haomeili.net/HanZi/ZiFuBianMaZhuanHuan>
![](https://oss.javaguide.cn/github/javaguide/csdn/836c49b117ee4408871b0020b74c991d.png) ![](https://oss.javaguide.cn/github/javaguide/csdn/836c49b117ee4408871b0020b74c991d.png)
@ -152,9 +151,9 @@ Incorrect string value: '\xF0\x9F\x98\x98\xF0\x9F...' for column 'name' at row 1
## 参考 ## 参考
- 字符集和字符编码Charset & Encoding https://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html - 字符集和字符编码Charset & Encoding <https://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html>
- 十分钟搞清字符集和字符编码http://cenalulu.github.io/linux/character-encoding/ - 十分钟搞清字符集和字符编码:<http://cenalulu.github.io/linux/character-encoding/>
- Unicode-维基百科https://zh.wikipedia.org/wiki/Unicode - Unicode-维基百科:<https://zh.wikipedia.org/wiki/Unicode>
- GB2312-维基百科https://zh.wikipedia.org/wiki/GB_2312 - GB2312-维基百科:<https://zh.wikipedia.org/wiki/GB_2312>
- UTF-8-维基百科https://zh.wikipedia.org/wiki/UTF-8 - UTF-8-维基百科:<https://zh.wikipedia.org/wiki/UTF-8>
- GB18030-维基百科: https://zh.wikipedia.org/wiki/GB_18030 - GB18030-维基百科: <https://zh.wikipedia.org/wiki/GB_18030>

View File

@ -10,46 +10,4 @@ tag:
![](https://oss.javaguide.cn/javamianshizhibei/elasticsearch-questions.png) ![](https://oss.javaguide.cn/javamianshizhibei/elasticsearch-questions.png)
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。 <!-- @include: @planet.snippet.md -->
![](https://oss.javaguide.cn/xingqiu/image-20220304102536445.png)
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
为了帮助更多同学准备 Java 面试以及学习 Java ,我创建了一个纯粹的知识星球。虽然收费只有培训班/训练营的百分之一,但是知识星球里的内容质量更高,提供的服务也更全面。
欢迎准备 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://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
</a>
</div>
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
</a>
</div>
**我有自己的原则,不割韭菜,用心做内容,真心希望帮助到你!**
如果你感兴趣的话,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)。
这里再送一个 30 元的新人优惠券(续费半价)。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
</a>
</div>
进入星球之后,记得添加微信,我会发你详细的星球使用指南。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
</a>
</div>

View File

@ -29,7 +29,7 @@ MongoDB 的存储结构区别于传统的关系型数据库,主要由如下三
**SQL 与 MongoDB 常见术语对比** **SQL 与 MongoDB 常见术语对比**
| SQL | MongoDB | | SQL | MongoDB |
| ----------------------- | ------------------------------ | | ------------------------ | ------------------------------- |
| 表Table | 集合Collection | | 表Table | 集合Collection |
| 行Row | 文档Document | | 行Row | 文档Document |
| 列Col | 字段Field | | 列Col | 字段Field |
@ -126,7 +126,7 @@ MongoDB 预留了几个特殊的数据库。
与 MySQL 一样MongoDB 采用的也是 **插件式的存储引擎架构** ,支持不同类型的存储引擎,不同的存储引擎解决不同场景的问题。在创建数据库或集合时,可以指定存储引擎。 与 MySQL 一样MongoDB 采用的也是 **插件式的存储引擎架构** ,支持不同类型的存储引擎,不同的存储引擎解决不同场景的问题。在创建数据库或集合时,可以指定存储引擎。
> 插件式的存储引擎架构可以实现 Server 层和存储引擎层的解耦可以支持多种存储引擎如MySQL既可以支持B-Tree结构的InnoDB存储引擎还可以支持LSM结构的RocksDB存储引擎。 > 插件式的存储引擎架构可以实现 Server 层和存储引擎层的解耦,可以支持多种存储引擎,如 MySQL 既可以支持 B-Tree 结构的 InnoDB 存储引擎,还可以支持 LSM 结构的 RocksDB 存储引擎。
在存储引擎刚出来的时候,默认是使用 MMAPV1 存储引擎MongoDB4.x 版本不再支持 MMAPv1 存储引擎。 在存储引擎刚出来的时候,默认是使用 MMAPV1 存储引擎MongoDB4.x 版本不再支持 MMAPv1 存储引擎。
@ -141,13 +141,13 @@ MongoDB 预留了几个特殊的数据库。
目前绝大部分流行的数据库存储引擎都是基于 B/B+ Tree 或者 LSM(Log Structured Merge) Tree 来实现的。对于 NoSQL 数据库来说,绝大部分(比如 HBase、Cassandra、RocksDB都是基于 LSM 树MongoDB 不太一样。 目前绝大部分流行的数据库存储引擎都是基于 B/B+ Tree 或者 LSM(Log Structured Merge) Tree 来实现的。对于 NoSQL 数据库来说,绝大部分(比如 HBase、Cassandra、RocksDB都是基于 LSM 树MongoDB 不太一样。
上面也说了,自 MongoDB 3.2 以后默认的存储引擎为WiredTiger 存储引擎。在 WiredTiger 引擎官网上,我们发现 WiredTiger 使用的是 B+ 树作为其存储结构: 上面也说了,自 MongoDB 3.2 以后,默认的存储引擎为 WiredTiger 存储引擎。在 WiredTiger 引擎官网上,我们发现 WiredTiger 使用的是 B+ 树作为其存储结构:
``` ```
WiredTiger maintains a table's data in memory using a data structure called a B-Tree ( B+ Tree to be specific), referring to the nodes of a B-Tree as pages. Internal pages carry only keys. The leaf pages store both keys and values. WiredTiger maintains a table's data in memory using a data structure called a B-Tree ( B+ Tree to be specific), referring to the nodes of a B-Tree as pages. Internal pages carry only keys. The leaf pages store both keys and values.
``` ```
此外WiredTiger 还支持 [LSM(Log Structured Merge)](https://source.wiredtiger.com/3.1.0/lsm.html) 树作为存储结构MongoDB 在使用WiredTiger 作为存储引擎时,默认使用的是 B+ 树。 此外WiredTiger 还支持 [LSM(Log Structured Merge)](https://source.wiredtiger.com/3.1.0/lsm.html) 树作为存储结构MongoDB 在使用 WiredTiger 作为存储引擎时,默认使用的是 B+ 树。
如果想要了解 MongoDB 使用 B 树的原因,可以看看这篇文章:[为什么 MongoDB 使用 B 树?](https://mp.weixin.qq.com/s/mMWdpbYRiT6LQcdaj4hgXQ)。 如果想要了解 MongoDB 使用 B 树的原因,可以看看这篇文章:[为什么 MongoDB 使用 B 树?](https://mp.weixin.qq.com/s/mMWdpbYRiT6LQcdaj4hgXQ)。
@ -155,13 +155,13 @@ WiredTiger maintains a table's data in memory using a data structure called a B-
- **root page根节点** B+ 树的根节点。 - **root page根节点** B+ 树的根节点。
- **internal page内部节点** :不实际存储数据的中间索引节点。 - **internal page内部节点** :不实际存储数据的中间索引节点。
- **leaf page叶子节点**真正存储数据的叶子节点包含一个页头page header、块头block header和真正的数据key/value其中页头定义了页的类型、页中实际载荷数据的大小、页中记录条数等信息块头定义了此页的checksum、块在磁盘上的寻址位置等信息。 - **leaf page叶子节点**真正存储数据的叶子节点包含一个页头page header、块头block header和真正的数据key/value其中页头定义了页的类型、页中实际载荷数据的大小、页中记录条数等信息块头定义了此页的 checksum、块在磁盘上的寻址位置等信息。
其整体结构如下图所示: 其整体结构如下图所示:
![WiredTiger B+树整体结构](https://oss.javaguide.cn/github/javaguide/database/mongodb/mongodb-b-plus-tree-integral-structure.png) ![WiredTiger B+树整体结构](https://oss.javaguide.cn/github/javaguide/database/mongodb/mongodb-b-plus-tree-integral-structure.png)
如果想要深入研究学习 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)。 如果想要深入研究学习 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)。
## MongoDB 聚合 ## MongoDB 聚合
@ -197,7 +197,7 @@ MongoDB 聚合管道由多个阶段组成,每个阶段在文档通过管道时
**常用阶段操作符** **常用阶段操作符**
| 操作符 | 简述 | | 操作符 | 简述 |
| --------- | ------------------------------------------------------------ | | --------- | ---------------------------------------------------------------------------------------------------- |
| \$match | 匹配操作符,用于对文档集合进行筛选 | | \$match | 匹配操作符,用于对文档集合进行筛选 |
| \$project | 投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段 | | \$project | 投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段 |
| \$sort | 排序操作符,用于根据一个或多个字段对文档进行排序 | | \$sort | 排序操作符,用于根据一个或多个字段对文档进行排序 |
@ -246,7 +246,7 @@ db.orders.aggregate([
- **隔离性**`Isolation` 并发访问数据库时一个用户的事务不被其他事务所干扰各并发事务之间数据库是独立的。WiredTiger 存储引擎支持读未提交( read-uncommitted )、读已提交( read-committed )和快照( snapshot 隔离MongoDB 启动时默认选快照隔离。在不同隔离级别下,一个事务的生命周期内,可能出现脏读、不可重复读、幻读等现象。 - **隔离性**`Isolation` 并发访问数据库时一个用户的事务不被其他事务所干扰各并发事务之间数据库是独立的。WiredTiger 存储引擎支持读未提交( read-uncommitted )、读已提交( read-committed )和快照( snapshot 隔离MongoDB 启动时默认选快照隔离。在不同隔离级别下,一个事务的生命周期内,可能出现脏读、不可重复读、幻读等现象。
- **持久性**`Durability` 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。 - **持久性**`Durability` 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
关于事务的详细介绍这篇文章就不多说了,感兴趣的可以看看我写的[MySQL常见面试题总结](https://javaguide.cn/database/mysql/mysql-questions-01.html)这篇文章,里面有详细介绍到。 关于事务的详细介绍这篇文章就不多说了,感兴趣的可以看看我写的[MySQL 常见面试题总结](https://javaguide.cn/database/mysql/mysql-questions-01.html)这篇文章,里面有详细介绍到。
MongoDB 单文档原生支持原子性,也具备事务的特性。当谈论 MongoDB 事务的时候,通常指的是 **多文档** 。MongoDB 4.0 加入了对多文档 ACID 事务的支持,但只支持复制集部署模式下的 ACID 事务也就是说事务的作用域限制为一个副本集内。MongoDB 4.2 引入了 **分布式事务** ,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。 MongoDB 单文档原生支持原子性,也具备事务的特性。当谈论 MongoDB 事务的时候,通常指的是 **多文档** 。MongoDB 4.0 加入了对多文档 ACID 事务的支持,但只支持复制集部署模式下的 ACID 事务也就是说事务的作用域限制为一个副本集内。MongoDB 4.2 引入了 **分布式事务** ,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
@ -258,8 +258,8 @@ MongoDB 单文档原生支持原子性,也具备事务的特性。当谈论 Mo
**注意** **注意**
- 从MongoDB 4.2开始多文档事务支持副本集和分片集群其中主节点使用WiredTiger存储引擎同时从节点使用WiredTiger存储引擎或In-Memory存储引擎。在MongoDB 4.0中只有使用WiredTiger存储引擎的副本集支持事务。 - 从 MongoDB 4.2 开始,多文档事务支持副本集和分片集群,其中:主节点使用 WiredTiger 存储引擎,同时从节点使用 WiredTiger 存储引擎或 In-Memory 存储引擎。在 MongoDB 4.0 中,只有使用 WiredTiger 存储引擎的副本集支持事务。
- 在MongoDB 4.2及更早版本中,你无法在事务中创建集合。从 MongoDB 4.4 开始,您可以在事务中创建集合和索引。有关详细信息,请参阅 [在事务中创建集合和索引](https://www.mongodb.com/docs/upcoming/core/transactions/#std-label-transactions-create-collections-indexes)。 - 在 MongoDB 4.2 及更早版本中,你无法在事务中创建集合。从 MongoDB 4.4 开始,您可以在事务中创建集合和索引。有关详细信息,请参阅 [在事务中创建集合和索引](https://www.mongodb.com/docs/upcoming/core/transactions/#std-label-transactions-create-collections-indexes)。
## MongoDB 数据压缩 ## MongoDB 数据压缩
@ -281,4 +281,4 @@ WiredTiger 日志也会被压缩,默认使用的也是 Snappy 压缩算法。
- 技术干货| MongoDB 事务原理 - MongoDB 中文社区https://mongoing.com/archives/82187 - 技术干货| MongoDB 事务原理 - MongoDB 中文社区https://mongoing.com/archives/82187
- Transactions - MongoDB 官方文档https://www.mongodb.com/docs/manual/core/transactions/ - Transactions - MongoDB 官方文档https://www.mongodb.com/docs/manual/core/transactions/
- WiredTiger Storage Engine - MongoDB 官方文档https://www.mongodb.com/docs/manual/core/wiredtiger/ - WiredTiger Storage Engine - MongoDB 官方文档https://www.mongodb.com/docs/manual/core/wiredtiger/
- WiredTiger存储引擎之一基础数据结构分析https://mongoing.com/topic/archives-35143 - WiredTiger 存储引擎之一基础数据结构分析https://mongoing.com/topic/archives-35143

View File

@ -166,7 +166,7 @@ MongoDB 的分片集群由如下三个部分组成(下图来源于[官方文
- **Config Servers**:配置服务器,本质上是一个 MongoDB 的副本集负责存储集群的各种元数据和配置如分片地址、Chunks 等 - **Config Servers**:配置服务器,本质上是一个 MongoDB 的副本集负责存储集群的各种元数据和配置如分片地址、Chunks 等
- **Mongos**:路由服务,不存具体数据,从 Config 获取集群配置讲请求转发到特定的分片,并且整合分片结果返回给客户端。 - **Mongos**:路由服务,不存具体数据,从 Config 获取集群配置讲请求转发到特定的分片,并且整合分片结果返回给客户端。
- **Shard**每个分片是整体数据的一部分子集从MongoDB3.6版本开始每个Shard必须部署为副本集replica set架构 - **Shard**:每个分片是整体数据的一部分子集,从 MongoDB3.6 版本开始,每个 Shard 必须部署为副本集replica set架构
#### 为什么要用分片集群? #### 为什么要用分片集群?
@ -196,12 +196,12 @@ MongoDB 的分片集群由如下三个部分组成(下图来源于[官方文
选择合适的片键对 sharding 效率影响很大,主要基于如下四个因素(摘自[分片集群使用注意事项 - - 腾讯云文档](https://cloud.tencent.com/document/product/240/44611) 选择合适的片键对 sharding 效率影响很大,主要基于如下四个因素(摘自[分片集群使用注意事项 - - 腾讯云文档](https://cloud.tencent.com/document/product/240/44611)
- **取值基数** 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如选择年龄做一个基数范围最多只有100个随着数据量增多同一个值分布过多时导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk从而无法迁移导致数据分布不均匀性能瓶颈。 - **取值基数** 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如:选择年龄做一个基数,范围最多只有 100 个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk从而无法迁移导致数据分布不均匀性能瓶颈。
- **取值分布** 取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。 - **取值分布** 取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
- **查询带分片** 查询时建议带上分片使用分片键进行条件查询时mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。 - **查询带分片** 查询时建议带上分片使用分片键进行条件查询时mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。
- **避免单调递增或递减** 单调递增的 sharding key数据文件挪动小但写入会集中导致最后一篇的数据量持续增大不断发生迁移递减同理。 - **避免单调递增或递减** 单调递增的 sharding key数据文件挪动小但写入会集中导致最后一篇的数据量持续增大不断发生迁移递减同理。
综上在选择片键时要考虑以上4个条件尽可能满足更多的条件才能降低 MoveChunks 对性能的影响,从而获得最优的性能体验。 综上,在选择片键时要考虑以上 4 个条件,尽可能满足更多的条件,才能降低 MoveChunks 对性能的影响,从而获得最优的性能体验。
#### 分片策略有哪些? #### 分片策略有哪些?

View File

@ -684,7 +684,7 @@ end
3. Replace 语法 如果有记录,则执行 before insert, before delete, after delete, after insert 3. Replace 语法 如果有记录,则执行 before insert, before delete, after delete, after insert
``` ```
### SQL编程 ### SQL 编程
```mysql ```mysql
/* SQL编程 */ ------------------ /* SQL编程 */ ------------------
@ -953,4 +953,3 @@ OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
6. SQL对大小写不敏感 6. SQL对大小写不敏感
7. 清除已有语句:\c 7. 清除已有语句:\c
``` ```

View File

@ -84,15 +84,16 @@ select * from tb_student A where A.age='18' and A.name=' 张三 ';
结合上面的说明,我们分析下这个语句的执行流程: 结合上面的说明,我们分析下这个语句的执行流程:
* 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 SQL 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。 - 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 SQL 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
* 通过分析器进行词法分析,提取 SQL 语句的关键元素,比如提取上面这个语句是查询 select提取需要查询的表名为 tb_student需要查询所有的列查询条件是这个表的 id='1'。然后判断这个 SQL 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。 - 通过分析器进行词法分析,提取 SQL 语句的关键元素,比如提取上面这个语句是查询 select提取需要查询的表名为 tb_student需要查询所有的列查询条件是这个表的 id='1'。然后判断这个 SQL 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
* 接下来就是优化器进行确定执行方案,上面的 SQL 语句,可以有两种执行方案: - 接下来就是优化器进行确定执行方案,上面的 SQL 语句,可以有两种执行方案:
a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。 a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。
b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。 b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。 那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
* 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。 - 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
### 2.2 更新语句 ### 2.2 更新语句
@ -101,12 +102,13 @@ select * from tb_student A where A.age='18' and A.name=' 张三 ';
``` ```
update tb_student A set A.age='19' where A.name=' 张三 '; update tb_student A set A.age='19' where A.name=' 张三 ';
``` ```
我们来给张三修改下年龄在实际数据库肯定不会设置年龄这个字段的不然要被技术负责人打的。其实这条语句也基本上会沿着上一个查询的流程走只不过执行更新的时候肯定要记录日志啦这就会引入日志模块了MySQL 自带的日志模块是 **binlog归档日志** ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 **redo log重做日志**,我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下: 我们来给张三修改下年龄在实际数据库肯定不会设置年龄这个字段的不然要被技术负责人打的。其实这条语句也基本上会沿着上一个查询的流程走只不过执行更新的时候肯定要记录日志啦这就会引入日志模块了MySQL 自带的日志模块是 **binlog归档日志** ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 **redo log重做日志**,我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:
* 先查询到张三这一条数据,如果有缓存,也是会用到缓存。 - 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
* 然后拿到查询的语句,把 age 改为 19然后调用引擎 API 接口写入这一行数据InnoDB 引擎把数据保存在内存中,同时记录 redo log此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。 - 然后拿到查询的语句,把 age 改为 19然后调用引擎 API 接口写入这一行数据InnoDB 引擎把数据保存在内存中,同时记录 redo log此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
* 执行器收到通知后记录 binlog然后调用引擎接口提交 redo log 为提交状态。 - 执行器收到通知后记录 binlog然后调用引擎接口提交 redo log 为提交状态。
* 更新完成。 - 更新完成。
**这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?** **这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?**
@ -114,25 +116,25 @@ update tb_student A set A.age='19' where A.name=' 张三 ';
并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做? 并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做?
* **先写 redo log 直接提交,然后写 binlog**,假设写完 redo log 后机器挂了binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。 - **先写 redo log 直接提交,然后写 binlog**,假设写完 redo log 后机器挂了binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
* **先写 binlog然后写 redo log**,假设写完了 binlog机器异常重启了由于没有 redo log本机是无法恢复这一条记录的但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。 - **先写 binlog然后写 redo log**,假设写完了 binlog机器异常重启了由于没有 redo log本机是无法恢复这一条记录的但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
如果采用 redo log 两阶段提交的方式就不一样了,写完 binlog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设 redo log 处于预提交状态binlog 也已经写完了,这个时候发生了异常重启会怎么样呢? 如果采用 redo log 两阶段提交的方式就不一样了,写完 binlog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设 redo log 处于预提交状态binlog 也已经写完了,这个时候发生了异常重启会怎么样呢?
这个就要依赖于 MySQL 的处理机制了MySQL 的处理过程如下: 这个就要依赖于 MySQL 的处理机制了MySQL 的处理过程如下:
* 判断 redo log 是否完整,如果判断是完整的,就立即提交。 - 判断 redo log 是否完整,如果判断是完整的,就立即提交。
* 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。 - 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
这样就解决了数据一致性的问题。 这样就解决了数据一致性的问题。
## 三 总结 ## 三 总结
* MySQL 主要分为 Server 层和引擎层Server 层主要包括连接器、查询缓存、分析器、优化器、执行器同时还有一个日志模块binlog这个日志模块所有执行引擎都可以共用redolog 只有 InnoDB 有。 - MySQL 主要分为 Server 层和引擎层Server 层主要包括连接器、查询缓存、分析器、优化器、执行器同时还有一个日志模块binlog这个日志模块所有执行引擎都可以共用redolog 只有 InnoDB 有。
* 引擎层是插件式的目前主要包括MyISAM,InnoDB,Memory 等。 - 引擎层是插件式的目前主要包括MyISAM,InnoDB,Memory 等。
* 查询语句的执行流程如下:权限校验(如果命中缓存)--->查询缓存--->分析器--->优化器--->权限校验--->执行器--->引擎 - 查询语句的执行流程如下:权限校验(如果命中缓存)--->查询缓存--->分析器--->优化器--->权限校验--->执行器--->引擎
* 更新语句执行流程如下:分析器---->权限校验---->执行器--->引擎---redo log(prepare 状态)--->binlog--->redo log(commit状态) - 更新语句执行流程如下:分析器---->权限校验---->执行器--->引擎---redo log(prepare 状态)--->binlog--->redo log(commit 状态)
## 四 参考 ## 四 参考
* 《MySQL 实战45讲》 - 《MySQL 实战 45 讲》
* MySQL 5.6参考手册:<https://dev.MySQL.com/doc/refman/5.6/en/> - MySQL 5.6 参考手册:<https://dev.MySQL.com/doc/refman/5.6/en/>

View File

@ -40,7 +40,7 @@ tag:
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/61b8dc9155624044a86d91c368b20059~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/61b8dc9155624044a86d91c368b20059~tplv-k3u1fbpfcp-zoom-1.image)
但如果马上重启 MySQL 实例,重启后这个表的 AUTO_INCREMENT 就会变成 1。也就是说MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。 但如果马上重启 MySQL 实例,重启后这个表的 AUTO_INCREMENT 就会变成 1。 也就是说MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27fdb15375664249a31f88b64e6e5e66~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27fdb15375664249a31f88b64e6e5e66~tplv-k3u1fbpfcp-zoom-1.image)
@ -149,7 +149,7 @@ tag:
现在有两个并行执行的事务 A 和 B在申请自增值的时候为了避免两个事务申请到相同的自增 id肯定要加锁然后顺序申请对吧。 现在有两个并行执行的事务 A 和 B在申请自增值的时候为了避免两个事务申请到相同的自增 id肯定要加锁然后顺序申请对吧。
1. 假设事务 A 申请到了 id = 1 事务 B 申请到 id=2那么这时候表 t 的自增值是3之后继续执行。 1. 假设事务 A 申请到了 id = 1 事务 B 申请到 id=2那么这时候表 t 的自增值是 3之后继续执行。
2. 事务 B 正确提交了,但事务 A 出现了唯一键冲突,也就是 id = 1 的那行记录插入失败了,那如果允许事务 A 把自增 id 回退,也就是把表的当前自增值改回 1那么就会出现这样的情况表里面已经有 id = 2 的行,而当前的自增 id 值是 1。 2. 事务 B 正确提交了,但事务 A 出现了唯一键冲突,也就是 id = 1 的那行记录插入失败了,那如果允许事务 A 把自增 id 回退,也就是把表的当前自增值改回 1那么就会出现这样的情况表里面已经有 id = 2 的行,而当前的自增 id 值是 1。
3. 接下来,继续执行的其他事务就会申请到 id=2。这时就会出现插入语句报错“主键冲突”。 3. 接下来,继续执行的其他事务就会申请到 id=2。这时就会出现插入语句报错“主键冲突”。

View File

@ -14,7 +14,7 @@ head:
缓存是一个有效且实用的系统性能优化的手段,不论是操作系统还是各种软件和网站或多或少都用到了缓存。 缓存是一个有效且实用的系统性能优化的手段,不论是操作系统还是各种软件和网站或多或少都用到了缓存。
然而,有经验的 DBA 都建议生产环境中把 MySQL 自带的 Query Cache查询缓存给关掉。而且从 MySQL 5.7.20 开始,就已经默认弃用查询缓存了。在 MySQL 8.0及之后,更是直接删除了查询缓存的功能。 然而,有经验的 DBA 都建议生产环境中把 MySQL 自带的 Query Cache查询缓存给关掉。而且从 MySQL 5.7.20 开始,就已经默认弃用查询缓存了。在 MySQL 8.0 及之后,更是直接删除了查询缓存的功能。
这又是为什么呢?查询缓存真就这么鸡肋么? 这又是为什么呢?查询缓存真就这么鸡肋么?
@ -27,7 +27,7 @@ head:
## MySQL 查询缓存介绍 ## MySQL 查询缓存介绍
MySQL体系架构如下图所示 MySQL 体系架构如下图所示:
![](https://oss.javaguide.cn/github/javaguide/mysql/mysql-architecture.png) ![](https://oss.javaguide.cn/github/javaguide/mysql/mysql-architecture.png)
@ -90,10 +90,10 @@ mysql> show variables like '%query_cache%';
**建议** **建议**
- `query_cache_size`不建议设置的过大。过大的空间不但挤占实例其他内存结构的空间而且会增加在缓存中搜索的开销。建议根据实例规格初始值设置为10MB到100MB之间的值而后根据运行使用情况调整。 - `query_cache_size`不建议设置的过大。过大的空间不但挤占实例其他内存结构的空间,而且会增加在缓存中搜索的开销。建议根据实例规格,初始值设置为 10MB 100MB 之间的值,而后根据运行使用情况调整。
- 建议通过调整 `query_cache_size` 的值来开启、关闭查询缓存,因为修改`query_cache_type` 参数需要重启 MySQL Server 生效。 - 建议通过调整 `query_cache_size` 的值来开启、关闭查询缓存,因为修改`query_cache_type` 参数需要重启 MySQL Server 生效。
8.0 版本之前,`my.cnf` 加入以下配置,重启 MySQL 开启查询缓存 8.0 版本之前,`my.cnf` 加入以下配置,重启 MySQL 开启查询缓存
```properties ```properties
query_cache_type=1 query_cache_type=1
@ -196,11 +196,11 @@ MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查
> 根据我们的经验,在高并发压力环境中查询缓存会导致系统性能的下降,甚至僵死。如果你一 定要使用查询缓存,那么不要设置太大内存,而且只有在明确收益的时候才使用(数据库内容修改次数较少)。 > 根据我们的经验,在高并发压力环境中查询缓存会导致系统性能的下降,甚至僵死。如果你一 定要使用查询缓存,那么不要设置太大内存,而且只有在明确收益的时候才使用(数据库内容修改次数较少)。
**确实是这样的!实际项目中,更建议使用本地缓存(比如 Caffeine或者分布式缓存比如Redis ,性能更好,更通用一些。** **确实是这样的!实际项目中,更建议使用本地缓存(比如 Caffeine或者分布式缓存比如 Redis ,性能更好,更通用一些。**
## 参考 ## 参考
- 《高性能 MySQL》 - 《高性能 MySQL》
- MySQL缓存机制https://zhuanlan.zhihu.com/p/55947158 - MySQL 缓存机制https://zhuanlan.zhihu.com/p/55947158
- RDS MySQL查询缓存Query Cache的设置和使用 - 阿里元云数据库 RDS 文档:https://help.aliyun.com/document_detail/41717.html - RDS MySQL 查询缓存Query Cache的设置和使用 - 阿里元云数据库 RDS 文档:https://help.aliyun.com/document_detail/41717.html
- 8.10.3 The MySQL Query Cache - MySQL 官方文档https://dev.mysql.com/doc/refman/5.7/en/query-cache.html - 8.10.3 The MySQL Query Cache - MySQL 官方文档https://dev.mysql.com/doc/refman/5.7/en/query-cache.html

View File

@ -50,8 +50,8 @@ mysql> explain SELECT * FROM dept_emp WHERE emp_no IN (SELECT emp_no FROM dept_e
| **列名** | **含义** | | **列名** | **含义** |
| ------------- | -------------------------------------------- | | ------------- | -------------------------------------------- |
| id | SELECT查询的序列标识符 | | id | SELECT 查询的序列标识符 |
| select_type | SELECT关键字对应的查询类型 | | select_type | SELECT 关键字对应的查询类型 |
| table | 用到的表名 | | table | 用到的表名 |
| partitions | 匹配的分区,对于未分区的表,值为 NULL | | partitions | 匹配的分区,对于未分区的表,值为 NULL |
| type | 表的访问方法 | | type | 表的访问方法 |
@ -89,8 +89,7 @@ id 如果相同从上往下依次执行。id 不同id 值越大,执行
查询用到的表名,每行都有对应的表名,表名除了正常的表之外,也可能是以下列出的值: 查询用到的表名,每行都有对应的表名,表名除了正常的表之外,也可能是以下列出的值:
- **`<unionM,N>`** : 本行引用了 id 为 M 和 N 的行的 UNION 结果; - **`<unionM,N>`** : 本行引用了 id 为 M 和 N 的行的 UNION 结果;
- **`<derivedN>`** : 本行引用了 id 为 N 的表所产生的的派生表结果。派生表有可能产生自 FROM 语句中的子查询。 - **`<derivedN>`** : 本行引用了 id 为 N 的表所产生的的派生表结果。派生表有可能产生自 FROM 语句中的子查询。 -**`<subqueryN>`** : 本行引用了 id 为 N 的表所产生的的物化子查询结果。
-**`<subqueryN>`** : 本行引用了 id 为 N 的表所产生的的物化子查询结果。
### type重要 ### type重要

View File

@ -13,6 +13,8 @@ head:
content: 一篇文章总结MySQL常见的知识点和面试题涵盖MySQL基础、MySQL基础架构、MySQL存储引擎、MySQL查询缓存、MySQL事务、MySQL锁等内容。 content: 一篇文章总结MySQL常见的知识点和面试题涵盖MySQL基础、MySQL基础架构、MySQL存储引擎、MySQL查询缓存、MySQL事务、MySQL锁等内容。
--- ---
<!-- @include: @small-advertisement.snippet.md -->
## MySQL 基础 ## MySQL 基础
### 什么是关系型数据库? ### 什么是关系型数据库?
@ -700,7 +702,7 @@ mysql> EXPLAIN SELECT `score`,`name` FROM `cus_order` ORDER BY `score` DESC;
- [一树一溪的 MySQL 系列教程](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg3NTc3NjM4Nw==&action=getalbum&album_id=2372043523518300162&scene=173&from_msgid=2247484308&from_itemidx=1&count=3&nolastread=1#wechat_redirect) - [一树一溪的 MySQL 系列教程](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg3NTc3NjM4Nw==&action=getalbum&album_id=2372043523518300162&scene=173&from_msgid=2247484308&from_itemidx=1&count=3&nolastread=1#wechat_redirect)
- [Yes 的 MySQL 系列教程](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNTE3NjQ3MA==&action=getalbum&album_id=1903249596194095112&scene=173&from_msgid=2247490365&from_itemidx=1&count=3&nolastread=1#wechat_redirect) - [Yes 的 MySQL 系列教程](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNTE3NjQ3MA==&action=getalbum&album_id=1903249596194095112&scene=173&from_msgid=2247490365&from_itemidx=1&count=3&nolastread=1#wechat_redirect)
- [写完这篇 我的SQL优化能力直接进入新层次 - 变成派大星 - 2022](https://juejin.cn/post/7161964571853815822) - [写完这篇 我的 SQL 优化能力直接进入新层次 - 变成派大星 - 2022](https://juejin.cn/post/7161964571853815822)
- [两万字详解InnoDB 锁专题! - 捡田螺的小男孩 - 2022](https://juejin.cn/post/7094049650428084232) - [两万字详解InnoDB 锁专题! - 捡田螺的小男孩 - 2022](https://juejin.cn/post/7094049650428084232)
- [MySQL 的自增主键一定是连续的吗? - 飞天小牛肉 - 2022](https://mp.weixin.qq.com/s/qci10h9rJx_COZbHV3aygQ) - [MySQL 的自增主键一定是连续的吗? - 飞天小牛肉 - 2022](https://mp.weixin.qq.com/s/qci10h9rJx_COZbHV3aygQ)
- [深入理解 MySQL 索引底层原理 - 腾讯技术工程 - 2020](https://zhuanlan.zhihu.com/p/113917726) - [深入理解 MySQL 索引底层原理 - 腾讯技术工程 - 2020](https://zhuanlan.zhihu.com/p/113917726)

View File

@ -73,7 +73,7 @@ SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTE
### 脏读(读未提交) ### 脏读(读未提交)
![](https://oss.javaguide.cn/github/javaguide/2019-31-1%E8%84%8F%E8%AF%BB(%E8%AF%BB%E6%9C%AA%E6%8F%90%E4%BA%A4)%E5%AE%9E%E4%BE%8B.jpg) ![](<https://oss.javaguide.cn/github/javaguide/2019-31-1%E8%84%8F%E8%AF%BB(%E8%AF%BB%E6%9C%AA%E6%8F%90%E4%BA%A4)%E5%AE%9E%E4%BE%8B.jpg>)
### 避免脏读(读已提交) ### 避免脏读(读已提交)

View File

@ -20,7 +20,7 @@ NoSQL 数据库代表HBase 、Cassandra、MongoDB、Redis。
## SQL 和 NoSQL 有什么区别? ## SQL 和 NoSQL 有什么区别?
| | SQL 数据库 | NoSQL 数据库 | | | SQL 数据库 | NoSQL 数据库 |
| :----------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | :----------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| 数据存储模型 | 结构化存储,具有固定行和列的表格 | 非结构化存储。文档JSON 文档,键值:键值对,宽列:包含行和动态列的表,图:节点和边 | | 数据存储模型 | 结构化存储,具有固定行和列的表格 | 非结构化存储。文档JSON 文档,键值:键值对,宽列:包含行和动态列的表,图:节点和边 |
| 发展历程 | 开发于 1970 年代,重点是减少数据重复 | 开发于 2000 年代后期,重点是提升可扩展性,减少大规模数据的存储成本 | | 发展历程 | 开发于 1970 年代,重点是减少数据重复 | 开发于 2000 年代后期,重点是提升可扩展性,减少大规模数据的存储成本 |
| 例子 | Oracle、MySQL、Microsoft SQL Server 、PostgreSQL | 文档MongoDB、CouchDB键值Redis 、DynamoDB宽列Cassandra 、 HBase图表Neo4j 、 Amazon Neptune、Giraph | | 例子 | Oracle、MySQL、Microsoft SQL Server 、PostgreSQL | 文档MongoDB、CouchDB键值Redis 、DynamoDB宽列Cassandra 、 HBase图表Neo4j 、 Amazon Neptune、Giraph |
@ -54,6 +54,6 @@ NoSQL 数据库主要可以分为下面四种类型:
## 参考 ## 参考
- NoSQL 是什么?- MongoDB 官方文档https://www.mongodb.com/zh-cn/nosql-explained - NoSQL 是什么?- MongoDB 官方文档:<https://www.mongodb.com/zh-cn/nosql-explained>
- 什么是 NoSQL? - AWShttps://aws.amazon.com/cn/nosql/ - 什么是 NoSQL? - AWS<https://aws.amazon.com/cn/nosql/>
- NoSQL vs. SQL Databases - MongoDB 官方文档https://www.mongodb.com/zh-cn/nosql-explained/nosql-vs-sql - NoSQL vs. SQL Databases - MongoDB 官方文档:<https://www.mongodb.com/zh-cn/nosql-explained/nosql-vs-sql>

View File

@ -5,12 +5,11 @@ tag:
- Redis - Redis
--- ---
看到很多小伙伴简历上写了“**熟练使用缓存**”,但是被我问到“**缓存常用的 3 种读写策略**”的时候却一脸懵逼。
看到很多小伙伴简历上写了“**熟练使用缓存**”,但是被我问到“**缓存常用的3种读写策略**”的时候却一脸懵逼。
在我看来,造成这个问题的原因是我们在学习 Redis 的时候,可能只是简单了写一些 Demo并没有去关注缓存的读写策略或者说压根不知道这回事。 在我看来,造成这个问题的原因是我们在学习 Redis 的时候,可能只是简单了写一些 Demo并没有去关注缓存的读写策略或者说压根不知道这回事。
但是搞懂3种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的 但是,搞懂 3 种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
**下面介绍到的三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式。** **下面介绍到的三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式。**

View File

@ -6,49 +6,6 @@ tag:
--- ---
**缓存基础** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。 **缓存基础** 相关的面试题为我的[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)中。
![](https://oss.javaguide.cn/javamianshizhibei/database-questions.png) ![](https://oss.javaguide.cn/javamianshizhibei/database-questions.png)
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。 <!-- @include: @planet.snippet.md -->
![](https://oss.javaguide.cn/xingqiu/image-20220304102536445.png)
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
为了帮助更多同学准备 Java 面试以及学习 Java ,我创建了一个纯粹的知识星球。虽然收费只有培训班/训练营的百分之一,但是知识星球里的内容质量更高,提供的服务也更全面。
欢迎准备 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://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
</a>
</div>
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
</a>
</div>
**我有自己的原则,不割韭菜,用心做内容,真心希望帮助到你!**
如果你感兴趣的话,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)。
这里再送一个 30 元的新人优惠券(续费半价)。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
</a>
</div>
进入星球之后,记得添加微信,我会发你详细的星球使用指南。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
</a>
</div>

View File

@ -9,47 +9,4 @@ tag:
![](https://oss.javaguide.cn/github/javaguide/database/redis/redis-cluster-javamianshizhibei.png) ![](https://oss.javaguide.cn/github/javaguide/database/redis/redis-cluster-javamianshizhibei.png)
<!-- @include: @planet.snippet.md -->
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn) 的补充完善,两者可以配合使用。
![](https://oss.javaguide.cn/xingqiu/image-20220304102536445.png)
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
为了帮助更多同学准备 Java 面试以及学习 Java ,我创建了一个纯粹的知识星球。虽然收费只有培训班/训练营的百分之一,但是知识星球里的内容质量更高,提供的服务也更全面。
欢迎准备 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://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
</a>
</div>
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
</a>
</div>
**我有自己的原则,不割韭菜,用心做内容,真心希望帮助到你!**
如果你感兴趣的话,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)。
这里再送一个 30 元的新人优惠券(续费半价)。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
</a>
</div>
进入星球之后,记得添加微信,我会发你详细的星球使用指南。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
</a>
</div>

View File

@ -5,7 +5,7 @@ tag:
- Redis - Redis
--- ---
> 本文整理完善自https://mp.weixin.qq.com/s/0Nqfq_eQrUb12QH6eBbHXA 作者阿Q说代码 > 本文整理完善自https://mp.weixin.qq.com/s/0Nqfq_eQrUb12QH6eBbHXA ,作者:阿 Q 说代码
这篇文章会详细总结一下可能导致 Redis 阻塞的情况,这些情况也是影响 Redis 性能的关键因素,使用 Redis 的时候应该格外注意! 这篇文章会详细总结一下可能导致 Redis 阻塞的情况,这些情况也是影响 Redis 性能的关键因素,使用 Redis 的时候应该格外注意!
@ -54,7 +54,7 @@ Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关
当后台线程( `aof_fsync` 线程)调用 `fsync` 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,会导致 `fsync` 操作发生阻塞,主线程调用 `write` 函数时也会被阻塞。`fsync` 完成后,主线程执行 `write` 才能成功返回。 当后台线程( `aof_fsync` 线程)调用 `fsync` 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,会导致 `fsync` 操作发生阻塞,主线程调用 `write` 函数时也会被阻塞。`fsync` 完成后,主线程执行 `write` 才能成功返回。
关于 AOF 工作流程的详细介绍可以查看:[Redis持久化机制详解](./redis-persistence.md),有助于理解 AOF 刷盘阻塞。 关于 AOF 工作流程的详细介绍可以查看:[Redis 持久化机制详解](./redis-persistence.md),有助于理解 AOF 刷盘阻塞。
### AOF 重写阻塞 ### AOF 重写阻塞
@ -64,7 +64,7 @@ Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关
阻塞就是出现在第 2 步的过程中,将缓冲区中新数据写到新文件的过程中会产生**阻塞**。 阻塞就是出现在第 2 步的过程中,将缓冲区中新数据写到新文件的过程中会产生**阻塞**。
相关阅读:[Redis AOF重写阻塞问题分析](https://cloud.tencent.com/developer/article/1633077)。 相关阅读:[Redis AOF 重写阻塞问题分析](https://cloud.tencent.com/developer/article/1633077)。
## 大 Key ## 大 Key
@ -111,13 +111,13 @@ Redis 集群可以进行节点的动态扩容缩容,这一过程目前还处
## Swap内存交换 ## Swap内存交换
什么是 SwapSwap 直译过来是交换的意思Linux中的Swap常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存就是当内存不足的时候把一部分硬盘空间虚拟成内存使用从而解决内存容量不足的情况。因此Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。 什么是 SwapSwap 直译过来是交换的意思Linux 中的 Swap 常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存就是当内存不足的时候把一部分硬盘空间虚拟成内存使用从而解决内存容量不足的情况。因此Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。
Swap 对于Redis来说是非常致命的Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出硬盘由于内存与硬盘读写的速度并几个数量级会导致发生交换后的Redis性能急剧下降。 Swap 对于 Redis 来说是非常致命的Redis 保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把 Redis 使用的部分内存换出硬盘,由于内存与硬盘读写的速度并几个数量级,会导致发生交换后的 Redis 性能急剧下降。
识别 Redis 发生 Swap 的检查方法如下: 识别 Redis 发生 Swap 的检查方法如下:
1、查询Redis进程号 1、查询 Redis 进程号
```bash ```bash
reids-cli -p 6383 info server | grep process_id reids-cli -p 6383 info server | grep process_id
@ -136,19 +136,19 @@ Swap: 0kB
..... .....
``` ```
如果交换量都是0KB或者个别的是4KB则正常。 如果交换量都是 0KB 或者个别的是 4KB则正常。
预防内存交换的方法: 预防内存交换的方法:
- 保证机器充足的可用内存 - 保证机器充足的可用内存
- 确保所有Redis实例设置最大可用内存(maxmemory)防止极端情况Redis内存不可控的增长 - 确保所有 Redis 实例设置最大可用内存(maxmemory),防止极端情况 Redis 内存不可控的增长
- 降低系统使用swap优先级`echo 10 > /proc/sys/vm/swappiness` - 降低系统使用 swap 优先级,如`echo 10 > /proc/sys/vm/swappiness`
## CPU 竞争 ## CPU 竞争
Redis是典型的CPU密集型应用不建议和其他多核CPU密集型服务部署在一起。当其他进程过度消耗CPU时将严重影响Redis的吞吐量。 Redis 是典型的 CPU 密集型应用,不建议和其他多核 CPU 密集型服务部署在一起。当其他进程过度消耗 CPU 时,将严重影响 Redis 的吞吐量。
可以通过`reids-cli --stat`获取当前Redis使用情况。通过`top`命令获取进程对CPU的利用率等信息 通过`info commandstats`统计信息分析出命令不合理开销时间,查看是否是因为高算法复杂度或者过度的内存优化问题。 可以通过`reids-cli --stat`获取当前 Redis 使用情况。通过`top`命令获取进程对 CPU 的利用率等信息 通过`info commandstats`统计信息分析出命令不合理开销时间,查看是否是因为高算法复杂度或者过度的内存优化问题。
## 网络问题 ## 网络问题
@ -156,5 +156,5 @@ Redis是典型的CPU密集型应用不建议和其他多核CPU密集型服务
## 参考 ## 参考
- Redis阻塞的6大类场景分析与总结https://mp.weixin.qq.com/s/eaZCEtTjTuEmXfUubVHjew - Redis 阻塞的 6 大类场景分析与总结https://mp.weixin.qq.com/s/eaZCEtTjTuEmXfUubVHjew
- Redis开发与运维笔记-Redis的噩梦-阻塞https://mp.weixin.qq.com/s/TDbpz9oLH6ifVv6ewqgSgA - Redis 开发与运维笔记-Redis 的噩梦-阻塞https://mp.weixin.qq.com/s/TDbpz9oLH6ifVv6ewqgSgA

View File

@ -388,7 +388,7 @@ Sorted Set 类似于 Set但和 Set 相比Sorted Set 增加了一个权重
### 常用命令 ### 常用命令
| 命令 | 介绍 | | 命令 | 介绍 |
| --------------------------------------------- | ------------------------------------------------------------ | | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| ZADD key score1 member1 score2 member2 ... | 向指定有序集合添加一个或多个元素 | | ZADD key score1 member1 score2 member2 ... | 向指定有序集合添加一个或多个元素 |
| ZCARD KEY | 获取指定有序集合的元素数量 | | ZCARD KEY | 获取指定有序集合的元素数量 |
| ZSCORE key member | 获取指定有序集合中指定元素的 score 值 | | ZSCORE key member | 获取指定有序集合中指定元素的 score 值 |

View File

@ -27,7 +27,7 @@ Bitmap 存储的是连续的二进制数字0 和 1通过 Bitmap, 只需
### 常用命令 ### 常用命令
| 命令 | 介绍 | | 命令 | 介绍 |
| ------------------------------------- | ------------------------------------------------------------ | | ------------------------------------- | ---------------------------------------------------------------- |
| SETBIT key offset value | 设置指定 offset 位置的值 | | SETBIT key offset value | 设置指定 offset 位置的值 |
| GETBIT key offset | 获取指定 offset 位置的值 | | GETBIT key offset | 获取指定 offset 位置的值 |
| BITCOUNT key start end | 获取 start 和 end 之前值为 1 的元素个数 | | BITCOUNT key start end | 获取 start 和 end 之前值为 1 的元素个数 |
@ -87,7 +87,7 @@ HyperLogLog 的使用非常简单但原理非常复杂。HyperLogLog 的原
HyperLogLog 相关的命令非常少,最常用的也就 3 个。 HyperLogLog 相关的命令非常少,最常用的也就 3 个。
| 命令 | 介绍 | | 命令 | 介绍 |
| ----------------------------------------- | ------------------------------------------------------------ | | ----------------------------------------- | -------------------------------------------------------------------------------- |
| PFADD key element1 element2 ... | 添加一个或多个元素到 HyperLogLog 中 | | PFADD key element1 element2 ... | 添加一个或多个元素到 HyperLogLog 中 |
| PFCOUNT key1 key2 | 获取一个或者多个 HyperLogLog 的唯一计数。 | | PFCOUNT key1 key2 | 获取一个或者多个 HyperLogLog 的唯一计数。 |
| PFMERGE destkey sourcekey1 sourcekey2 ... | 将多个 HyperLogLog 合并到 destkey 中destkey 会结合多个源,算出对应的唯一计数。 | | PFMERGE destkey sourcekey1 sourcekey2 ... | 将多个 HyperLogLog 合并到 destkey 中destkey 会结合多个源,算出对应的唯一计数。 |
@ -133,7 +133,7 @@ Geospatial index地理空间索引简称 GEO 主要用于存储地理
### 常用命令 ### 常用命令
| 命令 | 介绍 | | 命令 | 介绍 |
| ------------------------------------------------ | ------------------------------------------------------------ | | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| GEOADD key longitude1 latitude1 member1 ... | 添加一个或多个元素对应的经纬度信息到 GEO 中 | | GEOADD key longitude1 latitude1 member1 ... | 添加一个或多个元素对应的经纬度信息到 GEO 中 |
| GEOPOS key member1 member2 ... | 返回给定元素的经纬度信息 | | GEOPOS key member1 member2 ... | 返回给定元素的经纬度信息 |
| GEODIST key member1 member2 M/KM/FT/MI | 返回两个给定元素之间的距离 | | GEODIST key member1 member2 M/KM/FT/MI | 返回两个给定元素之间的距离 |

View File

@ -12,6 +12,8 @@ head:
content: 一篇文章总结Redis常见的知识点和面试题涵盖Redis基础、Redis常见数据结构、Redis线程模型、Redis内存管理、Redis事务、Redis性能优化等内容。 content: 一篇文章总结Redis常见的知识点和面试题涵盖Redis基础、Redis常见数据结构、Redis线程模型、Redis内存管理、Redis事务、Redis性能优化等内容。
--- ---
<!-- @include: @small-advertisement.snippet.md -->
## Redis 基础 ## Redis 基础
### 什么是 Redis ### 什么是 Redis
@ -248,7 +250,7 @@ struct __attribute__ ((__packed__)) sdshdr64 {
通过源码可以看出SDS 共有五种实现方式 SDS_TYPE_5并未用到、SDS_TYPE_8、SDS_TYPE_16、SDS_TYPE_32、SDS_TYPE_64其中只有后四种实际用到。Redis 会根据初始化的长度决定使用哪种类型,从而减少内存的使用。 通过源码可以看出SDS 共有五种实现方式 SDS_TYPE_5并未用到、SDS_TYPE_8、SDS_TYPE_16、SDS_TYPE_32、SDS_TYPE_64其中只有后四种实际用到。Redis 会根据初始化的长度决定使用哪种类型,从而减少内存的使用。
| 类型 | 字节 | 位 | | 类型 | 字节 | 位 |
| -------- | ---- | ---- | | -------- | ---- | --- |
| sdshdr5 | < 1 | <8 | | sdshdr5 | < 1 | <8 |
| sdshdr8 | 1 | 8 | | sdshdr8 | 1 | 8 |
| sdshdr16 | 2 | 16 | | sdshdr16 | 2 | 16 |
@ -371,7 +373,7 @@ Bitmap 存储的是连续的二进制数字0 和 1通过 Bitmap, 只需
### 使用 HyperLogLog 统计页面 UV 怎么做? ### 使用 HyperLogLog 统计页面 UV 怎么做?
使用 HyperLogLog 统计页面 UV主要需要用到下面这两个命令 使用 HyperLogLog 统计页面 UV 主要需要用到下面这两个命令:
- `PFADD key element1 element2 ...`:添加一个或多个元素到 HyperLogLog 中。 - `PFADD key element1 element2 ...`:添加一个或多个元素到 HyperLogLog 中。
- `PFCOUNT key1 key2`:获取一个或者多个 HyperLogLog 的唯一计数。 - `PFCOUNT key1 key2`:获取一个或者多个 HyperLogLog 的唯一计数。
@ -593,4 +595,3 @@ Redis 提供 6 种数据淘汰策略:
- 《Redis 设计与实现》 - 《Redis 设计与实现》
- Redis 命令手册https://www.redis.com.cn/commands.html - Redis 命令手册https://www.redis.com.cn/commands.html
- WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153) - WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153)

View File

@ -1204,7 +1204,7 @@ ORDER BY c.cust_name
SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示: SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示:
| 连接类型 | 说明 | | 连接类型 | 说明 |
| ---------------------------------------- | ------------------------------------------------------------ | | ---------------------------------------- | --------------------------------------------------------------------------------------------- |
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 | | INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 | | LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 | | RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |

View File

@ -490,7 +490,7 @@ order by c.cust_name;
SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示: SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示:
| 连接类型 | 说明 | | 连接类型 | 说明 |
| ---------------------------------------- | ------------------------------------------------------------ | | ---------------------------------------- | --------------------------------------------------------------------------------------------- |
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 | | INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 | | LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 | | RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |
@ -919,7 +919,7 @@ SELECT user FROM user;
下表说明了可用于`GRANT``REVOKE`语句的所有允许权限: 下表说明了可用于`GRANT``REVOKE`语句的所有允许权限:
| **特权** | **说明** | **级别** | | | | | | | **特权** | **说明** | **级别** | | | | | |
| ----------------------- | ------------------------------------------------------------ | -------- | ------ | -------- | -------- | ---- | ---- | | ----------------------- | ------------------------------------------------------------------------------------------------------- | -------- | ------ | -------- | -------- | --- | --- |
| **全局** | 数据库 | **表** | **列** | **程序** | **代理** | | | | **全局** | 数据库 | **表** | **列** | **程序** | **代理** | | |
| ALL [PRIVILEGES] | 授予除 GRANT OPTION 之外的指定访问级别的所有权限 | | | | | | | | ALL [PRIVILEGES] | 授予除 GRANT OPTION 之外的指定访问级别的所有权限 | | | | | | |
| ALTER | 允许用户使用 ALTER TABLE 语句 | X | X | X | | | | | ALTER | 允许用户使用 ALTER TABLE 语句 | X | X | X | | | |
@ -1206,5 +1206,5 @@ DROP TRIGGER IF EXISTS trigger_insert_user;
## 文章推荐 ## 文章推荐
- [后端程序员必备SQL高性能优化指南35+条优化建议立马GET!](https://mp.weixin.qq.com/s/I-ZT3zGTNBZ6egS7T09jyQ) - [后端程序员必备SQL 高性能优化指南35+条优化建议立马 GET!](https://mp.weixin.qq.com/s/I-ZT3zGTNBZ6egS7T09jyQ)
- [后端程序员必备:书写高质量SQL的30条建议](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486461&idx=1&sn=60a22279196d084cc398936fe3b37772&chksm=cea24436f9d5cd20a4fa0e907590f3e700d7378b3f608d7b33bb52cfb96f503b7ccb65a1deed&token=1987003517&lang=zh_CN#rd) - [后端程序员必备:书写高质量 SQL 30 条建议](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486461&idx=1&sn=60a22279196d084cc398936fe3b37772&chksm=cea24436f9d5cd20a4fa0e907590f3e700d7378b3f608d7b33bb52cfb96f503b7ccb65a1deed&token=1987003517&lang=zh_CN#rd)

View File

@ -75,12 +75,12 @@ Zuul 主要通过过滤器(类似于 AOP来过滤请求从而实现网
![Zuul2 架构](https://oscimg.oschina.net/oscnet/up-4f9047dc9109e27f9fced1b365e2b976e9d.png) ![Zuul2 架构](https://oscimg.oschina.net/oscnet/up-4f9047dc9109e27f9fced1b365e2b976e9d.png)
- Github 地址 https://github.com/Netflix/zuul - Github 地址 <https://github.com/Netflix/zuul>
- 官方 Wiki https://github.com/Netflix/zuul/wiki - 官方 Wiki <https://github.com/Netflix/zuul/wiki>
### Spring Cloud Gateway ### Spring Cloud Gateway
SpringCloud Gateway 属于 Spring Cloud 生态系统中的网关,其诞生的目标是为了替代老牌网关 **Zuul **。准确点来说,应该是 Zuul 1.x。SpringCloud Gateway 起步要比 Zuul 2.x 更早。 SpringCloud Gateway 属于 Spring Cloud 生态系统中的网关,其诞生的目标是为了替代老牌网关 **Zuul**。准确点来说,应该是 Zuul 1.x。SpringCloud Gateway 起步要比 Zuul 2.x 更早。
为了提升网关的性能SpringCloud Gateway 基于 Spring WebFlux 。Spring WebFlux 使用 Reactor 库来实现响应式编程模型,底层基于 Netty 实现同步非阻塞的 I/O。 为了提升网关的性能SpringCloud Gateway 基于 Spring WebFlux 。Spring WebFlux 使用 Reactor 库来实现响应式编程模型,底层基于 Netty 实现同步非阻塞的 I/O。
@ -90,8 +90,8 @@ Spring Cloud Gateway 不仅提供统一的路由方式,并且基于 Filter 链
Spring Cloud Gateway 和 Zuul 2.x 的差别不大,也是通过过滤器来处理请求。不过,目前更加推荐使用 Spring Cloud Gateway 而非 ZuulSpring Cloud 生态对其支持更加友好。 Spring Cloud Gateway 和 Zuul 2.x 的差别不大,也是通过过滤器来处理请求。不过,目前更加推荐使用 Spring Cloud Gateway 而非 ZuulSpring Cloud 生态对其支持更加友好。
- Github 地址 https://github.com/spring-cloud/spring-cloud-gateway - Github 地址 <https://github.com/spring-cloud/spring-cloud-gateway>
- 官网 https://spring.io/projects/spring-cloud-gateway - 官网 <https://spring.io/projects/spring-cloud-gateway>
### Kong ### Kong
@ -118,8 +118,8 @@ $ curl -X POST http://kong:8001/services/{service}/plugins \
![](https://oss.javaguide.cn/github/javaguide/system-design/distributed-system/api-gateway/kong-gateway-overview.png) ![](https://oss.javaguide.cn/github/javaguide/system-design/distributed-system/api-gateway/kong-gateway-overview.png)
- Github 地址: https://github.com/Kong/kong - Github 地址: <https://github.com/Kong/kong>
- 官网地址 https://konghq.com/kong - 官网地址 <https://konghq.com/kong>
### APISIX ### APISIX
@ -144,8 +144,8 @@ APISIX 同样支持定制化的插件开发。开发者除了能够使用 Lua
![](https://oscimg.oschina.net/oscnet/up-a240d3b113cde647f5850f4c7cc55d4ff5c.png) ![](https://oscimg.oschina.net/oscnet/up-a240d3b113cde647f5850f4c7cc55d4ff5c.png)
- Github 地址 https://github.com/apache/apisix - Github 地址 <https://github.com/apache/apisix>
- 官网地址: https://apisix.apache.org/zh/ - 官网地址: <https://apisix.apache.org/zh/>
相关阅读: 相关阅读:
@ -162,11 +162,11 @@ Shenyu 是一款基于 WebFlux 的可扩展、高性能、响应式网关Apac
Shenyu 通过插件扩展功能,插件是 ShenYu 的灵魂并且插件也是可扩展和热插拔的。不同的插件实现不同的功能。Shenyu 自带了诸如限流、熔断、转发 、重写、重定向、和路由监控等插件。 Shenyu 通过插件扩展功能,插件是 ShenYu 的灵魂并且插件也是可扩展和热插拔的。不同的插件实现不同的功能。Shenyu 自带了诸如限流、熔断、转发 、重写、重定向、和路由监控等插件。
- Github 地址: https://github.com/apache/incubator-shenyu - Github 地址: <https://github.com/apache/incubator-shenyu>
- 官网地址 https://shenyu.apache.org/ - 官网地址 <https://shenyu.apache.org/>
## 参考 ## 参考
- Kong 插件开发教程[通俗易懂]https://cloud.tencent.com/developer/article/2104299 - Kong 插件开发教程[通俗易懂]<https://cloud.tencent.com/developer/article/2104299>
- API 网关 Kong 实战https://xie.infoq.cn/article/10e4dab2de0bdb6f2c3c93da6 - API 网关 Kong 实战:<https://xie.infoq.cn/article/10e4dab2de0bdb6f2c3c93da6>
- Spring Cloud Gateway 原理介绍和应用https://blog.fintopia.tech/60e27b0e2078082a378ec5ed/ - Spring Cloud Gateway 原理介绍和应用:<https://blog.fintopia.tech/60e27b0e2078082a378ec5ed/>

View File

@ -8,49 +8,4 @@ icon: "configuration"
![](https://oss.javaguide.cn/javamianshizhibei/distributed-system.png) ![](https://oss.javaguide.cn/javamianshizhibei/distributed-system.png)
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。 <!-- @include: @planet.snippet.md -->
![](https://oss.javaguide.cn/xingqiu/image-20220304102536445.png)
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
为了帮助更多同学准备 Java 面试以及学习 Java ,我创建了一个纯粹的知识星球。虽然收费只有培训班/训练营的百分之一,但是知识星球里的内容质量更高,提供的服务也更全面。
欢迎准备 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://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
</a>
</div>
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
</a>
</div>
**我有自己的原则,不割韭菜,用心做内容,真心希望帮助到你!**
如果你感兴趣的话,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)。
这里再送一个 30 元的新人优惠券(续费半价)。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
</a>
</div>
进入星球之后,记得添加微信,我会发你详细的星球使用指南。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
</a>
</div>

View File

@ -84,9 +84,9 @@ COMMIT;
插入数据这里,我们没有使用 `insert into` 而是使用 `replace into` 来插入数据,具体步骤是这样的: 插入数据这里,我们没有使用 `insert into` 而是使用 `replace into` 来插入数据,具体步骤是这样的:
1)第一步: 尝试把数据插入到表中。 - 第一步: 尝试把数据插入到表中。
2)第二步: 如果主键或唯一索引字段出现重复数据错误而插入失败时,先从表中删除含有重复关键字值的冲突行,然后再次尝试把数据插入到表中。 - 第二步: 如果主键或唯一索引字段出现重复数据错误而插入失败时,先从表中删除含有重复关键字值的冲突行,然后再次尝试把数据插入到表中。
这种方式的优缺点也比较明显: 这种方式的优缺点也比较明显:
@ -103,7 +103,7 @@ COMMIT;
以 MySQL 举例,我们通过下面的方式即可。 以 MySQL 举例,我们通过下面的方式即可。
**1.创建一个数据库表。** **1. 创建一个数据库表。**
```sql ```sql
CREATE TABLE `sequence_id_generator` ( CREATE TABLE `sequence_id_generator` (
@ -122,7 +122,7 @@ CREATE TABLE `sequence_id_generator` (
`version` 字段主要用于解决并发问题(乐观锁),`biz_type` 主要用于表示业务类型。 `version` 字段主要用于解决并发问题(乐观锁),`biz_type` 主要用于表示业务类型。
**2.先插入一行数据。** **2. 先插入一行数据。**
```sql ```sql
INSERT INTO `sequence_id_generator` (`id`, `current_max_id`, `step`, `version`, `biz_type`) INSERT INTO `sequence_id_generator` (`id`, `current_max_id`, `step`, `version`, `biz_type`)
@ -130,7 +130,7 @@ VALUES
(1, 0, 100, 0, 101); (1, 0, 100, 0, 101);
``` ```
**3.通过 SELECT 获取指定业务下的批量唯一 ID** **3. 通过 SELECT 获取指定业务下的批量唯一 ID**
```sql ```sql
SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where `biz_type` = 101 SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where `biz_type` = 101
@ -143,7 +143,7 @@ id current_max_id step version biz_type
1 0 100 0 101 1 0 100 0 101
``` ```
**4.不够用的话,更新之后重新 SELECT 即可。** **4. 不够用的话,更新之后重新 SELECT 即可。**
```sql ```sql
UPDATE sequence_id_generator SET current_max_id = 0+100, version=version+1 WHERE version = 0 AND `biz_type` = 101 UPDATE sequence_id_generator SET current_max_id = 0+100, version=version+1 WHERE version = 0 AND `biz_type` = 101

View File

@ -95,7 +95,7 @@ OK
### 如何实现锁的优雅续期? ### 如何实现锁的优雅续期?
对于 Java 开发的小伙伴来说,已经有了现成的解决方案:**[Redisson](https://github.com/redisson/redisson)** 。其他语言的解决方案,可以在 Redis 官方文档中找到地址https://redis.io/topics/distlock 。 对于 Java 开发的小伙伴来说,已经有了现成的解决方案:**[Redisson](https://github.com/redisson/redisson)** 。其他语言的解决方案,可以在 Redis 官方文档中找到,地址:<https://redis.io/topics/distlock>
![Distributed locks with Redis](https://oss.javaguide.cn/github/javaguide/redis-distributed-lock.png) ![Distributed locks with Redis](https://oss.javaguide.cn/github/javaguide/redis-distributed-lock.png)
@ -394,6 +394,3 @@ private static class LockData
## 总结 ## 总结
这篇文章我们介绍了分布式锁的基本概念以及实现分布式锁的两种常见方式。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要看业务的具体需求。如果对性能要求比较高的话,建议使用 Redis 实现分布式锁。如果对可靠性要求比较高的话,建议使用 ZooKeeper 实现分布式锁。 这篇文章我们介绍了分布式锁的基本概念以及实现分布式锁的两种常见方式。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要看业务的具体需求。如果对性能要求比较高的话,建议使用 Redis 实现分布式锁。如果对可靠性要求比较高的话,建议使用 ZooKeeper 实现分布式锁。

View File

@ -5,13 +5,13 @@ tag:
- ZooKeeper - ZooKeeper
--- ---
这篇文章简单给演示一下 ZooKeeper 常见命令的使用以及 ZooKeeper Java客户端 Curator 的基本使用。介绍到的内容都是最基本的操作,能满足日常工作的基本需要。 这篇文章简单给演示一下 ZooKeeper 常见命令的使用以及 ZooKeeper Java 客户端 Curator 的基本使用。介绍到的内容都是最基本的操作,能满足日常工作的基本需要。
如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步! 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步!
## ZooKeeper 安装 ## ZooKeeper 安装
### 使用Docker 安装 zookeeper ### 使用 Docker 安装 zookeeper
**a.使用 Docker 下载 ZooKeeper** **a.使用 Docker 下载 ZooKeeper**
@ -27,11 +27,11 @@ docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5.8
### 连接 ZooKeeper 服务 ### 连接 ZooKeeper 服务
**a.进入ZooKeeper容器中** **a.进入 ZooKeeper 容器中**
先使用 `docker ps` 查看 ZooKeeper 的 ContainerID然后使用 `docker exec -it ContainerID /bin/bash` 命令进入容器中。 先使用 `docker ps` 查看 ZooKeeper 的 ContainerID然后使用 `docker exec -it ContainerID /bin/bash` 命令进入容器中。
**b.先进入 bin 目录,然后通过 `./zkCli.sh -server 127.0.0.1:2181`命令连接ZooKeeper 服务** **b.先进入 bin 目录,然后通过 `./zkCli.sh -server 127.0.0.1:2181`命令连接 ZooKeeper 服务**
```bash ```bash
root@eaf70fc620cb:/apache-zookeeper-3.5.8-bin# cd bin root@eaf70fc620cb:/apache-zookeeper-3.5.8-bin# cd bin
@ -162,15 +162,15 @@ numChildren = 1
在后面我会介绍到 Java 客户端 API 的使用以及开源 ZooKeeper 客户端 ZkClient 和 Curator 的使用。 在后面我会介绍到 Java 客户端 API 的使用以及开源 ZooKeeper 客户端 ZkClient 和 Curator 的使用。
## ZooKeeper Java客户端 Curator简单使用 ## ZooKeeper Java 客户端 Curator 简单使用
Curator 是Netflix公司开源的一套 ZooKeeper Java客户端框架相比于 Zookeeper 自带的客户端 zookeeper 来说Curator 的封装更加完善,各种 API 都可以比较方便地使用。 Curator 是 Netflix 公司开源的一套 ZooKeeper Java 客户端框架,相比于 Zookeeper 自带的客户端 zookeeper 来说Curator 的封装更加完善,各种 API 都可以比较方便地使用。
![](https://oss.javaguide.cn/github/javaguide/distributed-system/zookeeper/curator.png) ![](https://oss.javaguide.cn/github/javaguide/distributed-system/zookeeper/curator.png)
下面我们就来简单地演示一下 Curator 的使用吧! 下面我们就来简单地演示一下 Curator 的使用吧!
Curator4.0+版本对ZooKeeper 3.5.x支持比较好。开始之前请先将下面的依赖添加进你的项目。 Curator4.0+版本对 ZooKeeper 3.5.x 支持比较好。开始之前,请先将下面的依赖添加进你的项目。
```xml ```xml
<dependency> <dependency>
@ -214,14 +214,14 @@ zkClient.start();
#### 创建节点 #### 创建节点
我们在 [ZooKeeper常见概念解读](./zookeeper-intro.md) 中介绍到,我们通常是将 znode 分为 4 大类: 我们在 [ZooKeeper 常见概念解读](./zookeeper-intro.md) 中介绍到,我们通常是将 znode 分为 4 大类:
- **持久PERSISTENT节点** :一旦创建就一直存在即使 ZooKeeper 集群宕机,直到将其删除。 - **持久PERSISTENT节点** :一旦创建就一直存在即使 ZooKeeper 集群宕机,直到将其删除。
- **临时EPHEMERAL节点** :临时节点的生命周期是与 **客户端会话session** 绑定的,**会话消失则节点消失** 。并且,临时节点 **只能做叶子节点** ,不能创建子节点。 - **临时EPHEMERAL节点** :临时节点的生命周期是与 **客户端会话session** 绑定的,**会话消失则节点消失** 。并且,临时节点 **只能做叶子节点** ,不能创建子节点。
- **持久顺序PERSISTENT_SEQUENTIAL节点** 除了具有持久PERSISTENT节点的特性之外 子节点的名称还具有顺序性。比如 `/node1/app0000000001``/node1/app0000000002` - **持久顺序PERSISTENT_SEQUENTIAL节点** 除了具有持久PERSISTENT节点的特性之外 子节点的名称还具有顺序性。比如 `/node1/app0000000001``/node1/app0000000002`
- **临时顺序EPHEMERAL_SEQUENTIAL节点** 除了具备临时EPHEMERAL节点的特性之外子节点的名称还具有顺序性。 - **临时顺序EPHEMERAL_SEQUENTIAL节点** 除了具备临时EPHEMERAL节点的特性之外子节点的名称还具有顺序性。
你在使用的ZooKeeper 的时候,会发现 `CreateMode` 类中实际有 7种 znode 类型 ,但是用的最多的还是上面介绍的 4 种。 你在使用的 ZooKeeper 的时候,会发现 `CreateMode` 类中实际有 7 种 znode 类型 ,但是用的最多的还是上面介绍的 4 种。
**a.创建持久化节点** **a.创建持久化节点**
@ -293,8 +293,3 @@ zkClient.setData().forPath("/node1/00001","c++".getBytes());//更新节点数据
```java ```java
List<String> childrenPaths = zkClient.getChildren().forPath("/node1"); List<String> childrenPaths = zkClient.getChildren().forPath("/node1");
``` ```

View File

@ -125,7 +125,7 @@ Stat 类中包含了一个数据节点的所有状态信息的字段,包括事
下面我们来看一下每个 znode 状态信息究竟代表的是什么吧!(下面的内容来源于《从 Paxos 到 ZooKeeper 分布式一致性原理与实践》,因为 Guide 确实也不是特别清楚,要学会参考资料的嘛! 下面我们来看一下每个 znode 状态信息究竟代表的是什么吧!(下面的内容来源于《从 Paxos 到 ZooKeeper 分布式一致性原理与实践》,因为 Guide 确实也不是特别清楚,要学会参考资料的嘛!
| znode 状态信息 | 解释 | | znode 状态信息 | 解释 |
| -------------- | ------------------------------------------------------------ | | -------------- | --------------------------------------------------------------------------------------------------- |
| cZxid | create ZXID即该数据节点被创建时的事务 id | | cZxid | create ZXID即该数据节点被创建时的事务 id |
| ctime | create time即该节点的创建时间 | | ctime | create time即该节点的创建时间 |
| mZxid | modified ZXID即该节点最终一次更新时的事务 id | | mZxid | modified ZXID即该节点最终一次更新时的事务 id |
@ -202,7 +202,7 @@ Session 有一个属性叫做:`sessionTimeout` `sessionTimeout` 代表会
ZooKeeper 集群中的所有机器通过一个 **Leader 选举过程** 来选定一台称为 “**Leader**” 的机器Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,**Follower** 和 **Observer** 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。 ZooKeeper 集群中的所有机器通过一个 **Leader 选举过程** 来选定一台称为 “**Leader**” 的机器Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,**Follower** 和 **Observer** 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。
| 角色 | 说明 | | 角色 | 说明 |
| -------- | ------------------------------------------------------------ | | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Leader | 为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。 | | Leader | 为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。 |
| Follower | 为客户端提供读服务,如果是写服务则转发给 Leader。参与选举过程中的投票。 | | Follower | 为客户端提供读服务,如果是写服务则转发给 Leader。参与选举过程中的投票。 |
| Observer | 为客户端提供读服务,如果是写服务则转发给 Leader。不参与选举过程中的投票也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于 ZooKeeper3.3 系列新增的角色。 | | Observer | 为客户端提供读服务,如果是写服务则转发给 Leader。不参与选举过程中的投票也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于 ZooKeeper3.3 系列新增的角色。 |
@ -263,9 +263,9 @@ ZAB 协议包括两种基本的模式,分别是
关于 **ZAB 协议&Paxos 算法** 需要讲和理解的东西太多了,具体可以看下面这几篇文章: 关于 **ZAB 协议&Paxos 算法** 需要讲和理解的东西太多了,具体可以看下面这几篇文章:
- [Paxos 算法详解](https://javaguide.cn/distributed-system/theorem&algorithm&protocol/paxos-algorithm.html) - [Paxos 算法详解](https://javaguide.cn/distributed-system/protocol/paxos-algorithm.html)
- [Zookeeper ZAB 协议分析](https://dbaplus.cn/news-141-1875-1.html) - [Zookeeper ZAB 协议分析](https://dbaplus.cn/news-141-1875-1.html)
- [Raft 算法详解](https://javaguide.cn/distributed-system/theorem&algorithm&protocol/raft-algorithm.html) - [Raft 算法详解](https://javaguide.cn/distributed-system/protocol/raft-algorithm.html)
## 总结 ## 总结

View File

@ -7,7 +7,7 @@ tag:
> [FrancisQ](https://juejin.im/user/5c33853851882525ea106810) 投稿。 > [FrancisQ](https://juejin.im/user/5c33853851882525ea106810) 投稿。
## 什么是ZooKeeper ## 什么是 ZooKeeper
`ZooKeeper``Yahoo` 开发,后来捐赠给了 `Apache` ,现已成为 `Apache` 顶级项目。`ZooKeeper` 是一个开源的分布式应用程序协调服务器,其为分布式系统提供一致性服务。其一致性是通过基于 `Paxos` 算法的 `ZAB` 协议完成的。其主要功能包括:配置维护、分布式同步、集群管理、分布式事务等。 `ZooKeeper``Yahoo` 开发,后来捐赠给了 `Apache` ,现已成为 `Apache` 顶级项目。`ZooKeeper` 是一个开源的分布式应用程序协调服务器,其为分布式系统提供一致性服务。其一致性是通过基于 `Paxos` 算法的 `ZAB` 协议完成的。其主要功能包括:配置维护、分布式同步、集群管理、分布式事务等。
@ -39,11 +39,11 @@ tag:
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/38b9ff4b193e4487afe32c9710c6d644~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/38b9ff4b193e4487afe32c9710c6d644~tplv-k3u1fbpfcp-zoom-1.image)
而上述前者就是 `Eureka` 的处理方式它保证了AP可用性后者就是我们今天所要讲的 `ZooKeeper` 的处理方式它保证了CP数据一致性 而上述前者就是 `Eureka` 的处理方式,它保证了 AP可用性后者就是我们今天所要讲的 `ZooKeeper` 的处理方式,它保证了 CP数据一致性
## 一致性协议和算法 ## 一致性协议和算法
而为了解决数据一致性问题,在科学家和程序员的不断探索中,就出现了很多的一致性协议和算法。比如 2PC两阶段提交3PC三阶段提交Paxos算法等等。 而为了解决数据一致性问题,在科学家和程序员的不断探索中,就出现了很多的一致性协议和算法。比如 2PC两阶段提交3PC三阶段提交Paxos 算法等等。
这时候请你思考一个问题,同学之间如果采用传纸条的方式去传播消息,那么就会出现一个问题——我咋知道我的小纸条有没有传到我想要传递的那个人手中呢?万一被哪个小家伙给劫持篡改了呢,对吧? 这时候请你思考一个问题,同学之间如果采用传纸条的方式去传播消息,那么就会出现一个问题——我咋知道我的小纸条有没有传到我想要传递的那个人手中呢?万一被哪个小家伙给劫持篡改了呢,对吧?
@ -57,9 +57,9 @@ tag:
两阶段提交是一种保证分布式系统数据一致性的协议,现在很多数据库都是采用的两阶段提交协议来完成 **分布式事务** 的处理。 两阶段提交是一种保证分布式系统数据一致性的协议,现在很多数据库都是采用的两阶段提交协议来完成 **分布式事务** 的处理。
在介绍2PC之前我们先来想想分布式事务到底有什么问题呢 在介绍 2PC 之前,我们先来想想分布式事务到底有什么问题呢?
还拿秒杀系统的下订单和加积分两个系统来举例吧(我想你们可能都吐了🤮🤮🤮),我们此时下完订单会发个消息给积分系统告诉它下面该增加积分了。如果我们仅仅是发送一个消息也不收回复,那么我们的订单系统怎么能知道积分系统的收到消息的情况呢?如果我们增加一个收回复的过程,那么当积分系统收到消息后返回给订单系统一个 `Response` ,但在中间出现了网络波动,那个回复消息没有发送成功,订单系统是不是以为积分系统消息接收失败了?它是不是会回滚事务?但此时积分系统是成功收到消息的,它就会去处理消息然后给用户增加积分,这个时候就会出现积分加了但是订单没下成功。 还拿秒杀系统的下订单和加积分两个系统来举例吧(我想你们可能都吐了 🤮🤮🤮),我们此时下完订单会发个消息给积分系统告诉它下面该增加积分了。如果我们仅仅是发送一个消息也不收回复,那么我们的订单系统怎么能知道积分系统的收到消息的情况呢?如果我们增加一个收回复的过程,那么当积分系统收到消息后返回给订单系统一个 `Response` ,但在中间出现了网络波动,那个回复消息没有发送成功,订单系统是不是以为积分系统消息接收失败了?它是不是会回滚事务?但此时积分系统是成功收到消息的,它就会去处理消息然后给用户增加积分,这个时候就会出现积分加了但是订单没下成功。
所以我们所需要解决的是在分布式系统中,整个调用链中,我们所有服务的数据处理要么都成功要么都失败,即所有服务的 **原子性问题** 所以我们所需要解决的是在分布式系统中,整个调用链中,我们所有服务的数据处理要么都成功要么都失败,即所有服务的 **原子性问题**
@ -79,19 +79,19 @@ tag:
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cc534022c7184770b9b82b2d0008432a~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cc534022c7184770b9b82b2d0008432a~tplv-k3u1fbpfcp-zoom-1.image)
* **单点故障问题**,如果协调者挂了那么整个系统都处于不可用的状态了。 - **单点故障问题**,如果协调者挂了那么整个系统都处于不可用的状态了。
* **阻塞问题**,即当协调者发送 `prepare` 请求,参与者收到之后如果能处理那么它将会进行事务的处理但并不提交,这个时候会一直占用着资源不释放,如果此时协调者挂了,那么这些资源都不会再释放了,这会极大影响性能。 - **阻塞问题**,即当协调者发送 `prepare` 请求,参与者收到之后如果能处理那么它将会进行事务的处理但并不提交,这个时候会一直占用着资源不释放,如果此时协调者挂了,那么这些资源都不会再释放了,这会极大影响性能。
* **数据不一致问题**,比如当第二阶段,协调者只发送了一部分的 `commit` 请求就挂了,那么也就意味着,收到消息的参与者会进行事务的提交,而后面没收到的则不会进行事务提交,那么这时候就会产生数据不一致性问题。 - **数据不一致问题**,比如当第二阶段,协调者只发送了一部分的 `commit` 请求就挂了,那么也就意味着,收到消息的参与者会进行事务的提交,而后面没收到的则不会进行事务提交,那么这时候就会产生数据不一致性问题。
### 3PC三阶段提交 ### 3PC三阶段提交
因为2PC存在的一系列问题比如单点容错机制缺陷等等从而产生了 **3PC三阶段提交** 。那么这三阶段又分别是什么呢? 因为 2PC 存在的一系列问题,比如单点,容错机制缺陷等等,从而产生了 **3PC三阶段提交** 。那么这三阶段又分别是什么呢?
> 千万不要吧PC理解成个人电脑了其实他们是 phase-commit 的缩写,即阶段提交。 > 千万不要吧 PC 理解成个人电脑了,其实他们是 phase-commit 的缩写,即阶段提交。
1. **CanCommit阶段**:协调者向所有参与者发送 `CanCommit` 请求,参与者收到请求后会根据自身情况查看是否能执行事务,如果可以则返回 YES 响应并进入预备状态,否则返回 NO 。 1. **CanCommit 阶段**:协调者向所有参与者发送 `CanCommit` 请求,参与者收到请求后会根据自身情况查看是否能执行事务,如果可以则返回 YES 响应并进入预备状态,否则返回 NO 。
2. **PreCommit阶段**:协调者根据参与者返回的响应来决定是否可以进行下面的 `PreCommit` 操作。如果上面参与者返回的都是 YES那么协调者将向所有参与者发送 `PreCommit` 预提交请求,**参与者收到预提交请求后,会进行事务的执行操作,并将 `Undo``Redo` 信息写入事务日志中** ,最后如果参与者顺利执行了事务则给协调者返回成功的响应。如果在第一阶段协调者收到了 **任何一个 NO** 的信息,或者 **在一定时间内** 并没有收到全部的参与者的响应那么就会中断事务它会向所有参与者发送中断请求abort参与者收到中断请求之后会立即中断事务或者在一定时间内没有收到协调者的请求它也会中断事务。 2. **PreCommit 阶段**:协调者根据参与者返回的响应来决定是否可以进行下面的 `PreCommit` 操作。如果上面参与者返回的都是 YES那么协调者将向所有参与者发送 `PreCommit` 预提交请求,**参与者收到预提交请求后,会进行事务的执行操作,并将 `Undo``Redo` 信息写入事务日志中** ,最后如果参与者顺利执行了事务则给协调者返回成功的响应。如果在第一阶段协调者收到了 **任何一个 NO** 的信息,或者 **在一定时间内** 并没有收到全部的参与者的响应那么就会中断事务它会向所有参与者发送中断请求abort参与者收到中断请求之后会立即中断事务或者在一定时间内没有收到协调者的请求它也会中断事务。
3. **DoCommit阶段**:这个阶段其实和 `2PC` 的第二阶段差不多,如果协调者收到了所有参与者在 `PreCommit` 阶段的 YES 响应,那么协调者将会给所有参与者发送 `DoCommit` 请求,**参与者收到 `DoCommit` 请求后则会进行事务的提交工作**,完成后则会给协调者返回响应,协调者收到所有参与者返回的事务提交成功的响应之后则完成事务。若协调者在 `PreCommit` 阶段 **收到了任何一个 NO 或者在一定时间内没有收到所有参与者的响应** ,那么就会进行中断请求的发送,参与者收到中断请求后则会 **通过上面记录的回滚日志** 来进行事务的回滚操作,并向协调者反馈回滚状况,协调者收到参与者返回的消息后,中断事务。 3. **DoCommit 阶段**:这个阶段其实和 `2PC` 的第二阶段差不多,如果协调者收到了所有参与者在 `PreCommit` 阶段的 YES 响应,那么协调者将会给所有参与者发送 `DoCommit` 请求,**参与者收到 `DoCommit` 请求后则会进行事务的提交工作**,完成后则会给协调者返回响应,协调者收到所有参与者返回的事务提交成功的响应之后则完成事务。若协调者在 `PreCommit` 阶段 **收到了任何一个 NO 或者在一定时间内没有收到所有参与者的响应** ,那么就会进行中断请求的发送,参与者收到中断请求后则会 **通过上面记录的回滚日志** 来进行事务的回滚操作,并向协调者反馈回滚状况,协调者收到参与者返回的消息后,中断事务。
![3PC流程](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/80854635d48c42d896dbaa066abf5c26~tplv-k3u1fbpfcp-zoom-1.image) ![3PC流程](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/80854635d48c42d896dbaa066abf5c26~tplv-k3u1fbpfcp-zoom-1.image)
@ -99,7 +99,7 @@ tag:
总之,`3PC` 通过一系列的超时机制很好的缓解了阻塞问题,但是最重要的一致性并没有得到根本的解决,比如在 `PreCommit` 阶段,当一个参与者收到了请求之后其他参与者和协调者挂了或者出现了网络分区,这个时候收到消息的参与者都会进行事务提交,这就会出现数据不一致性问题。 总之,`3PC` 通过一系列的超时机制很好的缓解了阻塞问题,但是最重要的一致性并没有得到根本的解决,比如在 `PreCommit` 阶段,当一个参与者收到了请求之后其他参与者和协调者挂了或者出现了网络分区,这个时候收到消息的参与者都会进行事务提交,这就会出现数据不一致性问题。
所以,要解决一致性问题还需要靠 `Paxos` 算法⭐️ ⭐️ ⭐️ 。 所以,要解决一致性问题还需要靠 `Paxos` 算法 ⭐️ ⭐️ ⭐️ 。
### `Paxos` 算法 ### `Paxos` 算法
@ -109,8 +109,8 @@ tag:
#### prepare 阶段 #### prepare 阶段
* `Proposer提案者`:负责提出 `proposal`,每个提案者在提出提案时都会首先获取到一个 **具有全局唯一性的、递增的提案编号N**,即在整个集群中是唯一的编号 N然后将该编号赋予其要提出的提案在**第一阶段是只将提案编号发送给所有的表决者**。 - `Proposer提案者`:负责提出 `proposal`,每个提案者在提出提案时都会首先获取到一个 **具有全局唯一性的、递增的提案编号 N**,即在整个集群中是唯一的编号 N然后将该编号赋予其要提出的提案在**第一阶段是只将提案编号发送给所有的表决者**。
* `Acceptor表决者`:每个表决者在 `accept` 某提案后会将该提案编号N记录在本地这样每个表决者中保存的已经被 accept 的提案中会存在一个**编号最大的提案**,其编号假设为 `maxN`。每个表决者仅会 `accept` 编号大于自己本地 `maxN` 的提案,在批准提案时表决者会将以前接受过的最大编号的提案作为响应反馈给 `Proposer` - `Acceptor表决者`:每个表决者在 `accept` 某提案后,会将该提案编号 N 记录在本地,这样每个表决者中保存的已经被 accept 的提案中会存在一个**编号最大的提案**,其编号假设为 `maxN`。每个表决者仅会 `accept` 编号大于自己本地 `maxN` 的提案,在批准提案时表决者会将以前接受过的最大编号的提案作为响应反馈给 `Proposer`
> 下面是 `prepare` 阶段的流程图,你可以对照着参考一下。 > 下面是 `prepare` 阶段的流程图,你可以对照着参考一下。
@ -134,7 +134,7 @@ tag:
#### paxos 算法的死循环问题 #### paxos 算法的死循环问题
其实就有点类似于两个人吵架,小明说我是对的,小红说我才是对的,两个人据理力争的谁也不让谁🤬🤬。 其实就有点类似于两个人吵架,小明说我是对的,小红说我才是对的,两个人据理力争的谁也不让谁 🤬🤬。
比如说,此时提案者 P1 提出一个方案 M1完成了 `Prepare` 阶段的工作,这个时候 `acceptor` 则批准了 M1但是此时提案者 P2 同时也提出了一个方案 M2它也完成了 `Prepare` 阶段的工作。然后 P1 的方案已经不能在第二阶段被批准了(因为 `acceptor` 已经批准了比 M1 更大的 M2所以 P1 自增方案变为 M3 重新进入 `Prepare` 阶段,然后 `acceptor` ,又批准了新的 M3 方案,它又不能批准 M2 了,这个时候 M2 又自增进入 `Prepare` 阶段。。。 比如说,此时提案者 P1 提出一个方案 M1完成了 `Prepare` 阶段的工作,这个时候 `acceptor` 则批准了 M1但是此时提案者 P2 同时也提出了一个方案 M2它也完成了 `Prepare` 阶段的工作。然后 P1 的方案已经不能在第二阶段被批准了(因为 `acceptor` 已经批准了比 M1 更大的 M2所以 P1 自增方案变为 M3 重新进入 `Prepare` 阶段,然后 `acceptor` ,又批准了新的 M3 方案,它又不能批准 M2 了,这个时候 M2 又自增进入 `Prepare` 阶段。。。
@ -156,9 +156,9 @@ tag:
和介绍 `Paxos` 一样,在介绍 `ZAB` 协议之前,我们首先来了解一下在 `ZAB` 中三个主要的角色,`Leader 领导者``Follower跟随者``Observer观察者` 和介绍 `Paxos` 一样,在介绍 `ZAB` 协议之前,我们首先来了解一下在 `ZAB` 中三个主要的角色,`Leader 领导者``Follower跟随者``Observer观察者`
* `Leader` :集群中 **唯一的写请求处理者** ,能够发起投票(投票也是为了进行写请求)。 - `Leader` :集群中 **唯一的写请求处理者** ,能够发起投票(投票也是为了进行写请求)。
* `Follower`:能够接收客户端的请求,如果是读请求则可以自己处理,**如果是写请求则要转发给 `Leader`** 。在选举过程中会参与投票,**有选举权和被选举权** 。 - `Follower`:能够接收客户端的请求,如果是读请求则可以自己处理,**如果是写请求则要转发给 `Leader`** 。在选举过程中会参与投票,**有选举权和被选举权** 。
* `Observer` :就是没有选举权和被选举权的 `Follower` - `Observer` :就是没有选举权和被选举权的 `Follower`
`ZAB` 协议中对 `zkServer`(即上面我们说的三个角色的总称) 还有两种模式的定义,分别是 **消息广播****崩溃恢复** `ZAB` 协议中对 `zkServer`(即上面我们说的三个角色的总称) 还有两种模式的定义,分别是 **消息广播****崩溃恢复**
@ -174,11 +174,11 @@ tag:
![消息广播](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b64c7f25a5d24766889da14260005e31~tplv-k3u1fbpfcp-zoom-1.image) ![消息广播](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b64c7f25a5d24766889da14260005e31~tplv-k3u1fbpfcp-zoom-1.image)
嗯。。。看起来很简单,貌似懂了🤥🤥🤥。这两个 `Queue` 哪冒出来的?答案是 **`ZAB` 需要让 `Follower``Observer` 保证顺序性** 。何为顺序性比如我现在有一个写请求A此时 `Leader` 将请求A广播出去因为只需要半数同意就行所以可能这个时候有一个 `Follower` F1因为网络原因没有收到`Leader` 又广播了一个请求B因为网络原因F1竟然先收到了请求B然后才收到了请求A这个时候请求处理的顺序不同就会导致数据的不同从而 **产生数据不一致问题** 嗯。。。看起来很简单,貌似懂了 🤥🤥🤥。这两个 `Queue` 哪冒出来的?答案是 **`ZAB` 需要让 `Follower``Observer` 保证顺序性** 。何为顺序性,比如我现在有一个写请求 A此时 `Leader` 将请求 A 广播出去,因为只需要半数同意就行,所以可能这个时候有一个 `Follower` F1 因为网络原因没有收到,而 `Leader` 又广播了一个请求 B因为网络原因F1 竟然先收到了请求 B 然后才收到了请求 A这个时候请求处理的顺序不同就会导致数据的不同从而 **产生数据不一致问题**
所以在 `Leader` 这端,它为每个其他的 `zkServer` 准备了一个 **队列** ,采用先进先出的方式发送消息。由于协议是 **通过 `TCP`** 来进行网络通信的,保证了消息的发送顺序性,接受顺序性也得到了保证。 所以在 `Leader` 这端,它为每个其他的 `zkServer` 准备了一个 **队列** ,采用先进先出的方式发送消息。由于协议是 **通过 `TCP`** 来进行网络通信的,保证了消息的发送顺序性,接受顺序性也得到了保证。
除此之外,在 `ZAB` 中还定义了一个 **全局单调递增的事务ID `ZXID`** 它是一个64位long型其中高32位表示 `epoch` 年代低32位表示事务id。`epoch` 是会根据 `Leader` 的变化而变化的,当一个 `Leader` 挂了,新的 `Leader` 上位的时候,年代(`epoch`就变了。而低32位可以简单理解为递增的事务id。 除此之外,在 `ZAB` 中还定义了一个 **全局单调递增的事务 ID `ZXID`** ,它是一个 64 long 型,其中高 32 位表示 `epoch` 年代,低 32 位表示事务 id。`epoch` 是会根据 `Leader` 的变化而变化的,当一个 `Leader` 挂了,新的 `Leader` 上位的时候,年代(`epoch`)就变了。而低 32 位可以简单理解为递增的事务 id。
定义这个的原因也是为了顺序性,每个 `proposal``Leader` 中生成后需要 **通过其 `ZXID` 来进行排序** ,才能得到处理。 定义这个的原因也是为了顺序性,每个 `proposal``Leader` 中生成后需要 **通过其 `ZXID` 来进行排序** ,才能得到处理。
@ -188,7 +188,7 @@ tag:
`Leader` 选举可以分为两个不同的阶段,第一个是我们提到的 `Leader` 宕机需要重新选举,第二则是当 `Zookeeper` 启动时需要进行系统的 `Leader` 初始化选举。下面我先来介绍一下 `ZAB` 是如何进行初始化选举的。 `Leader` 选举可以分为两个不同的阶段,第一个是我们提到的 `Leader` 宕机需要重新选举,第二则是当 `Zookeeper` 启动时需要进行系统的 `Leader` 初始化选举。下面我先来介绍一下 `ZAB` 是如何进行初始化选举的。
假设我们集群中有3台机器那也就意味着我们需要两台以上同意超过半数。比如这个时候我们启动了 `server1` ,它会首先 **投票给自己** ,投票内容为服务器的 `myid``ZXID` ,因为初始化所以 `ZXID` 都为0此时 `server1` 发出的投票为 (1,0)。但此时 `server1` 的投票仅为1所以不能作为 `Leader` ,此时还在选举阶段所以整个集群处于 **`Looking` 状态**。 假设我们集群中有 3 台机器,那也就意味着我们需要两台以上同意(超过半数)。比如这个时候我们启动了 `server1` ,它会首先 **投票给自己** ,投票内容为服务器的 `myid``ZXID` ,因为初始化所以 `ZXID` 都为 0此时 `server1` 发出的投票为 (1,0)。但此时 `server1` 的投票仅为 1所以不能作为 `Leader` ,此时还在选举阶段所以整个集群处于 **`Looking` 状态**。
接着 `server2` 启动了,它首先也会将投票选给自己(2,0),并将投票信息广播出去(`server1`也会,只是它那时没有其他的服务器了),`server1` 在收到 `server2` 的投票信息后会将投票信息与自己的作比较。**首先它会比较 `ZXID` `ZXID` 大的优先为 `Leader`,如果相同则比较 `myid``myid` 大的优先作为 `Leader`**。所以此时`server1` 发现 `server2` 更适合做 `Leader`,它就会将自己的投票信息更改为(2,0)然后再广播出去,之后`server2` 收到之后发现和自己的一样无需做更改,并且自己的 **投票已经超过半数** ,则 **确定 `server2` 为 `Leader`**`server1` 也会将自己服务器设置为 `Following` 变为 `Follower`。整个服务器就从 `Looking` 变为了正常状态。 接着 `server2` 启动了,它首先也会将投票选给自己(2,0),并将投票信息广播出去(`server1`也会,只是它那时没有其他的服务器了),`server1` 在收到 `server2` 的投票信息后会将投票信息与自己的作比较。**首先它会比较 `ZXID` `ZXID` 大的优先为 `Leader`,如果相同则比较 `myid``myid` 大的优先作为 `Leader`**。所以此时`server1` 发现 `server2` 更适合做 `Leader`,它就会将自己的投票信息更改为(2,0)然后再广播出去,之后`server2` 收到之后发现和自己的一样无需做更改,并且自己的 **投票已经超过半数** ,则 **确定 `server2` 为 `Leader`**`server1` 也会将自己服务器设置为 `Following` 变为 `Follower`。整个服务器就从 `Looking` 变为了正常状态。
@ -196,7 +196,7 @@ tag:
还是前面三个 `server` 的例子,如果在整个集群运行的过程中 `server2` 挂了,那么整个集群会如何重新选举 `Leader` 呢?其实和初始化选举差不多。 还是前面三个 `server` 的例子,如果在整个集群运行的过程中 `server2` 挂了,那么整个集群会如何重新选举 `Leader` 呢?其实和初始化选举差不多。
首先毫无疑问的是剩下的两个 `Follower` 会将自己的状态 **从 `Following` 变为 `Looking` 状态** ,然后每个 `server` 会向初始化投票一样首先给自己投票(这不过这里的 `zxid` 可能不是0了这里为了方便随便取个数字 首先毫无疑问的是剩下的两个 `Follower` 会将自己的状态 **从 `Following` 变为 `Looking` 状态** ,然后每个 `server` 会向初始化投票一样首先给自己投票(这不过这里的 `zxid` 可能不是 0 了,这里为了方便随便取个数字)。
假设 `server1` 给自己投票为(1,99),然后广播给其他 `server``server3` 首先也会给自己投票(3,95),然后也广播给其他 `server``server1``server3` 此时会收到彼此的投票信息,和一开始选举一样,他们也会比较自己的投票和收到的投票(`zxid` 大的优先,如果相同那么就 `myid` 大的优先)。这个时候 `server1` 收到了 `server3` 的投票发现没自己的合适故不变,`server3` 收到 `server1` 的投票结果后发现比自己的合适于是更改投票为(1,99)然后广播出去,最后 `server1` 收到了发现自己的投票已经超过半数就把自己设为 `Leader``server3` 也随之变为 `Follower` 假设 `server1` 给自己投票为(1,99),然后广播给其他 `server``server3` 首先也会给自己投票(3,95),然后也广播给其他 `server``server1``server3` 此时会收到彼此的投票信息,和一开始选举一样,他们也会比较自己的投票和收到的投票(`zxid` 大的优先,如果相同那么就 `myid` 大的优先)。这个时候 `server1` 收到了 `server3` 的投票发现没自己的合适故不变,`server3` 收到 `server1` 的投票结果后发现比自己的合适于是更改投票为(1,99)然后广播出去,最后 `server1` 收到了发现自己的投票已经超过半数就把自己设为 `Leader``server3` 也随之变为 `Follower`
@ -208,9 +208,9 @@ tag:
如果只是 `Follower` 挂了,而且挂的没超过半数的时候,因为我们一开始讲了在 `Leader` 中会维护队列,所以不用担心后面的数据没接收到导致数据不一致性。 如果只是 `Follower` 挂了,而且挂的没超过半数的时候,因为我们一开始讲了在 `Leader` 中会维护队列,所以不用担心后面的数据没接收到导致数据不一致性。
如果 `Leader` 挂了那就麻烦了,我们肯定需要先暂停服务变为 `Looking` 状态然后进行 `Leader` 的重新选举(上面我讲过了),但这个就要分为两种情况了,分别是 **确保已经被Leader提交的提案最终能够被所有的Follower提交** 和 **跳过那些已经被丢弃的提案** 如果 `Leader` 挂了那就麻烦了,我们肯定需要先暂停服务变为 `Looking` 状态然后进行 `Leader` 的重新选举(上面我讲过了),但这个就要分为两种情况了,分别是 **确保已经被 Leader 提交的提案最终能够被所有的 Follower 提交** 和 **跳过那些已经被丢弃的提案**
确保已经被Leader提交的提案最终能够被所有的Follower提交是什么意思呢 确保已经被 Leader 提交的提案最终能够被所有的 Follower 提交是什么意思呢?
假设 `Leader (server2)` 发送 `commit` 请求(忘了请看上面的消息广播模式),他发送给了 `server3`,然后要发给 `server1` 的时候突然挂了。这个时候重新选举的时候我们如果把 `server1` 作为 `Leader` 的话,那么肯定会产生数据不一致性,因为 `server3` 肯定会提交刚刚 `server2` 发送的 `commit` 请求的提案,而 `server1` 根本没收到所以会丢弃。 假设 `Leader (server2)` 发送 `commit` 请求(忘了请看上面的消息广播模式),他发送给了 `server3`,然后要发给 `server1` 的时候突然挂了。这个时候重新选举的时候我们如果把 `server1` 作为 `Leader` 的话,那么肯定会产生数据不一致性,因为 `server3` 肯定会提交刚刚 `server2` 发送的 `commit` 请求的提案,而 `server1` 根本没收到所以会丢弃。
@ -222,15 +222,15 @@ tag:
那么跳过那些已经被丢弃的提案又是什么意思呢? 那么跳过那些已经被丢弃的提案又是什么意思呢?
假设 `Leader (server2)` 此时同意了提案N1自身提交了这个事务并且要发送给所有 `Follower``commit` 的请求,却在这个时候挂了,此时肯定要重新进行 `Leader` 的选举,比如说此时选 `server1``Leader` (这无所谓)。但是过了一会,这个 **挂掉的 `Leader` 又重新恢复了** ,此时它肯定会作为 `Follower` 的身份进入集群中,需要注意的是刚刚 `server2` 已经同意提交了提案N1但其他 `server` 并没有收到它的 `commit` 信息,所以其他 `server` 不可能再提交这个提案N1了这样就会出现数据不一致性问题了所以 **该提案N1最终需要被抛弃掉** 。 假设 `Leader (server2)` 此时同意了提案 N1自身提交了这个事务并且要发送给所有 `Follower``commit` 的请求,却在这个时候挂了,此时肯定要重新进行 `Leader` 的选举,比如说此时选 `server1``Leader` (这无所谓)。但是过了一会,这个 **挂掉的 `Leader` 又重新恢复了** ,此时它肯定会作为 `Follower` 的身份进入集群中,需要注意的是刚刚 `server2` 已经同意提交了提案 N1但其他 `server` 并没有收到它的 `commit` 信息,所以其他 `server` 不可能再提交这个提案 N1 了,这样就会出现数据不一致性问题了,所以 **该提案 N1 最终需要被抛弃掉** 。
![崩溃恢复](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/99cdca39ad6340ae8b77e8befe94e36e~tplv-k3u1fbpfcp-zoom-1.image) ![崩溃恢复](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/99cdca39ad6340ae8b77e8befe94e36e~tplv-k3u1fbpfcp-zoom-1.image)
## Zookeeper的几个理论知识 ## Zookeeper 的几个理论知识
了解了 `ZAB` 协议还不够,它仅仅是 `Zookeeper` 内部实现的一种方式,而我们如何通过 `Zookeeper` 去做一些典型的应用场景呢?比如说集群管理,分布式锁,`Master` 选举等等。 了解了 `ZAB` 协议还不够,它仅仅是 `Zookeeper` 内部实现的一种方式,而我们如何通过 `Zookeeper` 去做一些典型的应用场景呢?比如说集群管理,分布式锁,`Master` 选举等等。
这就涉及到如何使用 `Zookeeper` 了,但在使用之前我们还需要掌握几个概念。比如 `Zookeeper`**数据模型** 、**会话机制**、**ACL**、**Watcher机制** 等等。 这就涉及到如何使用 `Zookeeper` 了,但在使用之前我们还需要掌握几个概念。比如 `Zookeeper`**数据模型** 、**会话机制**、**ACL**、**Watcher 机制** 等等。
### 数据模型 ### 数据模型
@ -242,24 +242,24 @@ tag:
其中节点类型可以分为 **持久节点**、**持久顺序节点**、**临时节点** 和 **临时顺序节点** 其中节点类型可以分为 **持久节点**、**持久顺序节点**、**临时节点** 和 **临时顺序节点**
* 持久节点:一旦创建就一直存在,直到将其删除。 - 持久节点:一旦创建就一直存在,直到将其删除。
* 持久顺序节点:一个父节点可以为其子节点 **维护一个创建的先后顺序** ,这个顺序体现在 **节点名称** 上,是节点名称后自动添加一个由 10 位数字组成的数字串,从 0 开始计数。 - 持久顺序节点:一个父节点可以为其子节点 **维护一个创建的先后顺序** ,这个顺序体现在 **节点名称** 上,是节点名称后自动添加一个由 10 位数字组成的数字串,从 0 开始计数。
* 临时节点:临时节点的生命周期是与 **客户端会话** 绑定的,**会话消失则节点消失** 。临时节点 **只能做叶子节点** ,不能创建子节点。 - 临时节点:临时节点的生命周期是与 **客户端会话** 绑定的,**会话消失则节点消失** 。临时节点 **只能做叶子节点** ,不能创建子节点。
* 临时顺序节点:父节点可以创建一个维持了顺序的临时节点(和前面的持久顺序性节点一样)。 - 临时顺序节点:父节点可以创建一个维持了顺序的临时节点(和前面的持久顺序性节点一样)。
节点状态中包含了很多节点的属性比如 `czxid``mzxid` 等等,在 `zookeeper` 中是使用 `Stat` 这个类来维护的。下面我列举一些属性解释。 节点状态中包含了很多节点的属性比如 `czxid``mzxid` 等等,在 `zookeeper` 中是使用 `Stat` 这个类来维护的。下面我列举一些属性解释。
* `czxid``Created ZXID`,该数据节点被 **创建** 时的事务ID。 - `czxid``Created ZXID`,该数据节点被 **创建** 时的事务 ID。
* `mzxid``Modified ZXID`,节点 **最后一次被更新时** 的事务ID。 - `mzxid``Modified ZXID`,节点 **最后一次被更新时** 的事务 ID。
* `ctime``Created Time`,该节点被创建的时间。 - `ctime``Created Time`,该节点被创建的时间。
* `mtime` `Modified Time`,该节点最后一次被修改的时间。 - `mtime` `Modified Time`,该节点最后一次被修改的时间。
* `version`:节点的版本号。 - `version`:节点的版本号。
* `cversion`**子节点** 的版本号。 - `cversion`**子节点** 的版本号。
* `aversion`:节点的 `ACL` 版本号。 - `aversion`:节点的 `ACL` 版本号。
* `ephemeralOwner`:创建该节点的会话的 `sessionID` 如果该节点为持久节点该值为0。 - `ephemeralOwner`:创建该节点的会话的 `sessionID` ,如果该节点为持久节点,该值为 0。
* `dataLength`:节点数据内容的长度。 - `dataLength`:节点数据内容的长度。
* `numChildre`该节点的子节点个数如果为临时节点为0。 - `numChildre`:该节点的子节点个数,如果为临时节点为 0。
* `pzxid`该节点子节点列表最后一次被修改时的事务ID注意是子节点的 **列表** ,不是内容。 - `pzxid`:该节点子节点列表最后一次被修改时的事务 ID注意是子节点的 **列表** ,不是内容。
### 会话 ### 会话
@ -269,21 +269,21 @@ tag:
### ACL ### ACL
`ACL``Access Control Lists` ,它是一种权限控制。在 `zookeeper` 中定义了5种权限它们分别为 `ACL``Access Control Lists` ,它是一种权限控制。在 `zookeeper` 中定义了 5 种权限,它们分别为:
* `CREATE` :创建子节点的权限。 - `CREATE` :创建子节点的权限。
* `READ`:获取节点数据和子节点列表的权限。 - `READ`:获取节点数据和子节点列表的权限。
* `WRITE`:更新节点数据的权限。 - `WRITE`:更新节点数据的权限。
* `DELETE`:删除子节点的权限。 - `DELETE`:删除子节点的权限。
* `ADMIN`:设置节点 ACL 的权限。 - `ADMIN`:设置节点 ACL 的权限。
### Watcher机制 ### Watcher 机制
`Watcher` 为事件监听器,是 `zk` 非常重要的一个特性,很多功能都依赖于它,它有点类似于订阅的方式,即客户端向服务端 **注册** 指定的 `watcher` ,当服务端符合了 `watcher` 的某些事件或要求则会 **向客户端发送事件通知** ,客户端收到通知后找到自己定义的 `Watcher` 然后 **执行相应的回调方法** `Watcher` 为事件监听器,是 `zk` 非常重要的一个特性,很多功能都依赖于它,它有点类似于订阅的方式,即客户端向服务端 **注册** 指定的 `watcher` ,当服务端符合了 `watcher` 的某些事件或要求则会 **向客户端发送事件通知** ,客户端收到通知后找到自己定义的 `Watcher` 然后 **执行相应的回调方法**
![watcher机制](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac87b7cff7b44c63997ff0f6a7b6d2eb~tplv-k3u1fbpfcp-zoom-1.image) ![watcher机制](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac87b7cff7b44c63997ff0f6a7b6d2eb~tplv-k3u1fbpfcp-zoom-1.image)
## Zookeeper的几个典型应用场景 ## Zookeeper 的几个典型应用场景
前面说了这么多的理论知识,你可能听得一头雾水,这些玩意有啥用?能干啥事?别急,听我慢慢道来。 前面说了这么多的理论知识,你可能听得一头雾水,这些玩意有啥用?能干啥事?别急,听我慢慢道来。
@ -307,7 +307,7 @@ tag:
分布式锁的实现方式有很多种,比如 `Redis` 、数据库 、`zookeeper` 等。个人认为 `zookeeper` 在实现分布式锁这方面是非常非常简单的。 分布式锁的实现方式有很多种,比如 `Redis` 、数据库 、`zookeeper` 等。个人认为 `zookeeper` 在实现分布式锁这方面是非常非常简单的。
上面我们已经提到过了 **zk在高并发的情况下保证节点创建的全局唯一性**,这玩意一看就知道能干啥了。实现互斥锁呗,又因为能在分布式的情况下,所以能实现分布式锁呗。 上面我们已经提到过了 **zk 在高并发的情况下保证节点创建的全局唯一性**,这玩意一看就知道能干啥了。实现互斥锁呗,又因为能在分布式的情况下,所以能实现分布式锁呗。
如何实现呢?这玩意其实跟选主基本一样,我们也可以利用临时节点的创建来实现。 如何实现呢?这玩意其实跟选主基本一样,我们也可以利用临时节点的创建来实现。
@ -329,9 +329,9 @@ tag:
### 命名服务 ### 命名服务
如何给一个对象设置ID大家可能都会想到 `UUID`,但是 `UUID` 最大的问题就在于它太长了。。。(太长不一定是好事,嘿嘿嘿)。那么在条件允许的情况下,我们能不能使用 `zookeeper` 来实现呢? 如何给一个对象设置 ID大家可能都会想到 `UUID`,但是 `UUID` 最大的问题就在于它太长了。。。(太长不一定是好事,嘿嘿嘿)。那么在条件允许的情况下,我们能不能使用 `zookeeper` 来实现呢?
我们之前提到过 `zookeeper` 是通过 **树形结构** 来存储数据节点的,那也就是说,对于每个节点的 **全路径**它必定是唯一的我们可以使用节点的全路径作为命名方式了。而且更重要的是路径是我们可以自己定义的这对于我们对有些有语意的对象的ID设置可以更加便于理解。 我们之前提到过 `zookeeper` 是通过 **树形结构** 来存储数据节点的,那也就是说,对于每个节点的 **全路径**,它必定是唯一的,我们可以使用节点的全路径作为命名方式了。而且更重要的是,路径是我们可以自己定义的,这对于我们对有些有语意的对象的 ID 设置可以更加便于理解。
### 集群管理和注册中心 ### 集群管理和注册中心
@ -343,7 +343,7 @@ tag:
![集群管理](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3d70709f10f4fa6b09125a56a976fda~tplv-k3u1fbpfcp-zoom-1.image) ![集群管理](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3d70709f10f4fa6b09125a56a976fda~tplv-k3u1fbpfcp-zoom-1.image)
至于注册中心也很简单,我们同样也是让 **服务提供者**`zookeeper` 中创建一个临时节点并且将自己的 `ip、port、调用方式` 写入节点,当 **服务消费者** 需要进行调用的时候会 **通过注册中心找到相应的服务的地址列表(IP端口什么的)** ,并缓存到本地(方便以后调用),当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从地址列表中取一个服务提供者的服务器调用服务。 至于注册中心也很简单,我们同样也是让 **服务提供者**`zookeeper` 中创建一个临时节点并且将自己的 `ip、port、调用方式` 写入节点,当 **服务消费者** 需要进行调用的时候会 **通过注册中心找到相应的服务的地址列表(IP 端口什么的)** ,并缓存到本地(方便以后调用),当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从地址列表中取一个服务提供者的服务器调用服务。
当服务提供者的某台服务器宕机或下线时,相应的地址会从服务提供者地址列表中移除。同时,注册中心会将新的服务地址列表发送给服务消费者的机器并缓存在消费者本机(当然你可以让消费者进行节点监听,我记得 `Eureka` 会先试错,然后再更新)。 当服务提供者的某台服务器宕机或下线时,相应的地址会从服务提供者地址列表中移除。同时,注册中心会将新的服务地址列表发送给服务消费者的机器并缓存在消费者本机(当然你可以让消费者进行节点监听,我记得 `Eureka` 会先试错,然后再更新)。
@ -351,20 +351,20 @@ tag:
## 总结 ## 总结
看到这里的同学实在是太有耐心了👍👍👍不知道大家是否还记得我讲了什么😒。 看到这里的同学实在是太有耐心了 👍👍👍 不知道大家是否还记得我讲了什么 😒。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/912c1aa6b7794d4aac8ebe6a14832cae~tplv-k3u1fbpfcp-zoom-1.image) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/912c1aa6b7794d4aac8ebe6a14832cae~tplv-k3u1fbpfcp-zoom-1.image)
这篇文章中我带大家入门了 `zookeeper` 这个强大的分布式协调框架。现在我们来简单梳理一下整篇文章的内容。 这篇文章中我带大家入门了 `zookeeper` 这个强大的分布式协调框架。现在我们来简单梳理一下整篇文章的内容。
* 分布式与集群的区别 - 分布式与集群的区别
* `2PC``3PC` 以及 `paxos` 算法这些一致性框架的原理和实现。 - `2PC``3PC` 以及 `paxos` 算法这些一致性框架的原理和实现。
* `zookeeper` 专门的一致性算法 `ZAB` 原子广播协议的内容(`Leader` 选举、崩溃恢复、消息广播)。 - `zookeeper` 专门的一致性算法 `ZAB` 原子广播协议的内容(`Leader` 选举、崩溃恢复、消息广播)。
* `zookeeper` 中的一些基本概念,比如 `ACL`,数据节点,会话,`watcher`机制等等。 - `zookeeper` 中的一些基本概念,比如 `ACL`,数据节点,会话,`watcher`机制等等。
* `zookeeper` 的典型应用场景,比如选主,注册中心等等。 - `zookeeper` 的典型应用场景,比如选主,注册中心等等。
如果忘了可以回去看看再次理解一下,如果有疑问和建议欢迎提出🤝🤝🤝。 如果忘了可以回去看看再次理解一下,如果有疑问和建议欢迎提出 🤝🤝🤝。

View File

@ -8,46 +8,4 @@ icon: "transanction"
![](https://oss.javaguide.cn/javamianshizhibei/distributed-system.png) ![](https://oss.javaguide.cn/javamianshizhibei/distributed-system.png)
[《Java 面试指北》](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html)(点击链接即可查看详细介绍)的部分内容展示如下,你可以将其看作是 [JavaGuide](https://javaguide.cn/#/) 的补充完善,两者可以配合使用。 <!-- @include: @planet.snippet.md -->
![](https://oss.javaguide.cn/xingqiu/image-20220304102536445.png)
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
为了帮助更多同学准备 Java 面试以及学习 Java ,我创建了一个纯粹的知识星球。虽然收费只有培训班/训练营的百分之一,但是知识星球里的内容质量更高,提供的服务也更全面。
欢迎准备 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://oss.javaguide.cn/xingqiu/image-20220311203414600.png" style="margin: 0 auto; " />
</a>
</div>
下面是星球提供的部分服务(点击下方图片即可获取知识星球的详细介绍):
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiufuwu.png" style="margin: 0 auto; " />
</a>
</div>
**我有自己的原则,不割韭菜,用心做内容,真心希望帮助到你!**
如果你感兴趣的话,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)。
这里再送一个 30 元的新人优惠券(续费半价)。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/xingqiu/xingqiuyouhuijuanheyi.png" style="margin: 0 auto; " />
</a>
</div>
进入星球之后,记得添加微信,我会发你详细的星球使用指南。
<div align="center">
<a href="https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html">
<img src="https://oss.javaguide.cn/github/javaguide/IMG_3007.jpg" style="margin: 0 auto; " />
</a>
</div>

Some files were not shown because too many files have changed in this diff Show More