Compare commits
42 Commits
c1fc5ac09c
...
9d9b55a2ae
Author | SHA1 | Date | |
---|---|---|---|
|
9d9b55a2ae | ||
|
818ccbca79 | ||
|
fcdbe12190 | ||
|
f3754a92d4 | ||
|
72019c2b09 | ||
|
a19b2744b0 | ||
|
19cb0cd775 | ||
|
372cb240ca | ||
|
954364882e | ||
|
3f2471340c | ||
|
0d8c0c0fb3 | ||
|
f3c36f2916 | ||
|
5678155022 | ||
|
ef93bec410 | ||
|
d993af3421 | ||
|
76b220540b | ||
|
a13c531f35 | ||
|
881bc5c591 | ||
|
22e3ef1efc | ||
|
9153648dba | ||
|
4df51f86e9 | ||
|
6bdc809e2f | ||
|
72c52dba3e | ||
|
893c673f1c | ||
|
2975f2f244 | ||
|
a788fc300d | ||
|
7f877f8e5f | ||
|
8f8d7c102a | ||
|
cf9e96aa6c | ||
|
566c75d5a4 | ||
|
675d97ce1b | ||
|
fac0c7698d | ||
|
be1b2f46ce | ||
|
be6c1faa03 | ||
|
7703240ba3 | ||
|
638181bf70 | ||
|
44e5cfa5d2 | ||
|
e5d5c357b3 | ||
|
db776f0fd2 | ||
|
dff5130082 | ||
|
8f2cc4b8b2 | ||
|
bc083f989c |
29
.github/workflows/test.yml
vendored
Normal 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
@ -1,15 +1,14 @@
|
||||
/node_modules
|
||||
/package-lock.json
|
||||
node_modules/
|
||||
# *.drawio
|
||||
*.drawio.bkp
|
||||
.DS_Store
|
||||
# VS Code Config file
|
||||
.vscode/
|
||||
# Vuepress Cache
|
||||
.cache/
|
||||
# Vuepress Temp
|
||||
.temp/
|
||||
# Vuepress Output
|
||||
# VuePress Cache
|
||||
**/.vuepress/.cache/
|
||||
# VuePress Temp
|
||||
**/.vuepress/.temp/
|
||||
# VuePress Output
|
||||
dist/
|
||||
# Build files
|
||||
packages/*/lib/
|
||||
|
4
.husky/pre-commit
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm nano-staged
|
20
.markdownlint.json
Normal 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
@ -0,0 +1,4 @@
|
||||
**/node_modules/**
|
||||
|
||||
# markdown snippets
|
||||
*.snippet.md
|
15
.prettierignore
Normal 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
|
375
README.en.md
@ -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>
|
||||
|
||||

|
150
README.md
@ -1,46 +1,39 @@
|
||||
推荐你通过在线阅读网站进行阅读,体验更好,速度更快!
|
||||
|
||||
* **[JavaGuide 在线阅读网站(新版,推荐👍)](https://javaguide.cn/)**
|
||||
* [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/)
|
||||
- **[JavaGuide 在线阅读网站(新版,推荐 👍)](https://javaguide.cn/)**
|
||||
- [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">
|
||||
<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>
|
||||
|
||||
[](https://github.com/Snailclimb/JavaGuide)
|
||||
|
||||
[](https://javaguide.cn/)
|
||||

|
||||

|
||||

|
||||
|
||||
[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. **知识星球** :专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入 [JavaGuide 知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。
|
||||
> 2. **转载须知** :以下所有文章如非文首说明为转载皆为我(Guide 哥)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
> 1. **转载须知** :以下所有文章如非文首说明为转载皆为我(Guide)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
|
||||
<div align="center">
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
<div align="center">
|
||||
<img src="https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png" style="margin: 0 auto;" />
|
||||
</div>
|
||||
|
||||
<!-- #region home -->
|
||||
|
||||
## 项目相关
|
||||
|
||||
* [项目介绍](./docs/javaguide/intro.md)
|
||||
* [贡献指南](./docs/javaguide/contribution-guideline.md)
|
||||
* [常见问题](./docs/javaguide/faq.md)
|
||||
* [项目待办](./docs/javaguide/todo.md)
|
||||
- [项目介绍](./docs/javaguide/intro.md)
|
||||
- [贡献指南](./docs/javaguide/contribution-guideline.md)
|
||||
- [常见问题](./docs/javaguide/faq.md)
|
||||
- [项目待办](./docs/javaguide/todo.md)
|
||||
|
||||
## Java
|
||||
|
||||
@ -74,15 +67,15 @@
|
||||
|
||||
**源码分析** :
|
||||
|
||||
* [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md)
|
||||
* [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md)
|
||||
* [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md)
|
||||
- [ArrayList 源码+扩容机制分析](./docs/java/collection/arraylist-source-code.md)
|
||||
- [HashMap(JDK1.8)源码+底层数据结构分析](./docs/java/collection/hashmap-source-code.md)
|
||||
- [ConcurrentHashMap 源码+底层数据结构分析](./docs/java/collection/concurrent-hash-map-source-code.md)
|
||||
|
||||
### IO
|
||||
|
||||
* [IO 基础知识总结](./docs/java/io/io-basis.md)
|
||||
* [IO 设计模式总结](./docs/java/io/io-design-patterns.md)
|
||||
* [IO 模型详解](./docs/java/io/io-model.md)
|
||||
- [IO 基础知识总结](./docs/java/io/io-basis.md)
|
||||
- [IO 设计模式总结](./docs/java/io/io-design-patterns.md)
|
||||
- [IO 模型详解](./docs/java/io/io-model.md)
|
||||
|
||||
### 并发
|
||||
|
||||
@ -100,11 +93,11 @@
|
||||
- [Java 并发容器总结](./docs/java/concurrent/java-concurrent-collections.md)
|
||||
- [Atomic 原子类总结](./docs/java/concurrent/atomic-classes.md)
|
||||
- [AQS 详解](./docs/java/concurrent/aqs.md)
|
||||
- [CompletableFuture详解](./docs/java/concurrent/completablefuture-intro.md)
|
||||
- [CompletableFuture 详解](./docs/java/concurrent/completablefuture-intro.md)
|
||||
|
||||
### JVM (必看 :+1:)
|
||||
|
||||
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机(第3版)》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
|
||||
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解 Java 虚拟机(第 3 版)》](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
|
||||
|
||||
- **[Java 内存区域](./docs/java/jvm/memory-area.md)**
|
||||
- **[JVM 垃圾回收](./docs/java/jvm/jvm-garbage-collection.md)**
|
||||
@ -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 10 新特性概览](./docs/java/new-features/java10.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)
|
||||
- [HTTP vs HTTPS(应用层)](./docs/cs-basics/network/http&https.md)
|
||||
- [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0&http1.1.md)
|
||||
- [HTTP vs HTTPS(应用层)](./docs/cs-basics/network/http-vs-https.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)
|
||||
- [DNS 域名系统详解(应用层)](./docs/cs-basics/network/dns.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/graph.md)
|
||||
- [堆](./docs/cs-basics/data-structure/heap.md)
|
||||
- [树](./docs/cs-basics/data-structure/tree.md) :重点关注[红黑树](./docs/cs-basics/data-structure/red-black-tree.md)、B-,B+,B*树、LSM树
|
||||
- [树](./docs/cs-basics/data-structure/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) 。
|
||||
* [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
|
||||
- [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。
|
||||
- [如何刷 Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
|
||||
|
||||
**常见算法问题总结** :
|
||||
|
||||
* [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md)
|
||||
* [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
|
||||
* [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
|
||||
* [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md)
|
||||
- [几道常见的字符串算法题总结 ](./docs/cs-basics/algorithms/string-algorithm-problems.md)
|
||||
- [几道常见的链表算法题总结 ](./docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
|
||||
- [剑指 offer 部分编程题](./docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
|
||||
- [十大经典排序算法](./docs/cs-basics/algorithms/10-classical-sorting-algorithms.md)
|
||||
|
||||
另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
|
||||
另外,[GeeksforGeeks](https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
|
||||
|
||||
## 数据库
|
||||
|
||||
@ -196,9 +189,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
- [NoSQL 基础知识总结](./docs/database/nosql.md)
|
||||
- [字符集详解](./docs/database/character-set.md)
|
||||
- SQL :
|
||||
- [SQL语法基础知识总结](./docs/database/sql/sql-syntax-summary.md)
|
||||
- [SQL常见面试题总结](./docs/database/sql/sql-questions-01.md)
|
||||
|
||||
- [SQL 语法基础知识总结](./docs/database/sql/sql-syntax-summary.md)
|
||||
- [SQL 常见面试题总结](./docs/database/sql/sql-questions-01.md)
|
||||
|
||||
### MySQL
|
||||
|
||||
@ -209,14 +201,14 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
**重要知识点:**
|
||||
|
||||
- [MySQL索引详解](./docs/database/mysql/mysql-index.md)
|
||||
- [MySQL事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md)
|
||||
- [MySQL三大日志(binlog、redo log和undo log)详解](./docs/database/mysql/mysql-logs.md)
|
||||
- [MySQL 索引详解](./docs/database/mysql/mysql-index.md)
|
||||
- [MySQL 事务隔离级别图文详解)](./docs/database/mysql/transaction-isolation-level.md)
|
||||
- [MySQL 三大日志(binlog、redo log 和 undo log)详解](./docs/database/mysql/mysql-logs.md)
|
||||
- [InnoDB 存储引擎对 MVCC 的实现](./docs/database/mysql/innodb-implementation-of-mvcc.md)
|
||||
- [SQL 语句在 MySQL 中的执行过程](./docs/database/mysql/how-sql-executed-in-mysql.md)
|
||||
- [MySQL 查询缓存详解](./docs/database/mysql/mysql-query-cache.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-query-execution-plan.md)
|
||||
- [MySQL 自增主键一定是连续的吗](./docs/database/mysql/mysql-auto-increment-primary-key-continuous.md)
|
||||
- [MySQL 时间类型数据存储建议](./docs/database/mysql/some-thoughts-on-database-storage-time.md)
|
||||
- [MySQL 隐式转换造成索引失效](./docs/database/mysql/index-invalidation-caused-by-implicit-conversion.md)
|
||||
|
||||
@ -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 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.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)
|
||||
|
||||

|
||||
|
||||
@ -260,13 +252,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
### Docker
|
||||
|
||||
* [Docker 核心概念总结](./docs/tools/docker/docker-intro.md)
|
||||
* [Docker 实战](./docs/tools/docker/docker-in-action.md)
|
||||
- [Docker 核心概念总结](./docs/tools/docker/docker-intro.md)
|
||||
- [Docker 实战](./docs/tools/docker/docker-in-action.md)
|
||||
|
||||
### Git
|
||||
|
||||
* [Git 核心概念总结](./docs/tools/git/git-intro.md)
|
||||
* [Github 实用小技巧总结](./docs/tools/git/github-tips.md)
|
||||
- [Git 核心概念总结](./docs/tools/git/git-intro.md)
|
||||
- [Github 实用小技巧总结](./docs/tools/git/github-tips.md)
|
||||
|
||||
## 系统设计
|
||||
|
||||
@ -277,7 +269,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
- [RestFul API 简明教程](./docs/system-design/basis/RESTfulAPI.md)
|
||||
- [软件工程简明教程简明教程](./docs/system-design/basis/software-engineering.md)
|
||||
- [代码命名指南](./docs/system-design/basis/naming.md)
|
||||
- [代码命名指南](./docs/system-design/basis/naming.md)
|
||||
- [代码重构指南](./docs/system-design/basis/refactoring.md)
|
||||
- [单元测试指南](./docs/system-design/basis/unit-test.md)
|
||||
|
||||
@ -308,14 +300,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
- [认证授权基础概念详解](./docs/system-design/security/basis-of-authority-certification.md)
|
||||
- [JWT 基础概念详解](./docs/system-design/security/jwt-intro.md)
|
||||
- [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages&disadvantages-of-jwt.md)
|
||||
- [JWT 优缺点分析以及常见问题解决方案](./docs/system-design/security/advantages-and-disadvantages-of-jwt.md)
|
||||
- [SSO 单点登录详解](./docs/system-design/security/sso-intro.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)
|
||||
- [Paxos 算法详解](./docs/distributed-system/theorem&algorithm&protocol/paxos-algorithm.md)
|
||||
- [Raft 算法详解](./docs/distributed-system/theorem&algorithm&protocol/raft-algorithm.md)
|
||||
- [Gossip 协议详解](./docs/distributed-system/theorem&algorithm&protocol/gossip-protocl.md)
|
||||
- [CAP 理论和 BASE 理论详解](./docs/distributed-system/protocol/cap-and-base-theorem.md)
|
||||
- [Paxos 算法详解](./docs/distributed-system/protocol/paxos-algorithm.md)
|
||||
- [Raft 算法详解](./docs/distributed-system/protocol/raft-algorithm.md)
|
||||
- [Gossip 协议详解](./docs/distributed-system/protocol/gossip-protocl.md)
|
||||
|
||||
### API 网关
|
||||
|
||||
@ -360,8 +351,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
### RPC
|
||||
|
||||
* [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md)
|
||||
* [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md)
|
||||
- [RPC 基础常见知识点&面试题总结](./docs/distributed-system/rpc/rpc-intro.md)
|
||||
- [Dubbo 常见知识点&面试题总结](./docs/distributed-system/rpc/dubbo.md)
|
||||
|
||||
### 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)
|
||||
|
||||
### 超时&重试
|
||||
|
||||
@ -423,16 +414,16 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||
### 灾备设计和异地多活
|
||||
|
||||
**灾备** = 容灾+备份。
|
||||
**灾备** = 容灾+备份。
|
||||
|
||||
* **备份** : 将系统所产生的的所有重要数据多备份几份。
|
||||
* **容灾** : 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
|
||||
- **备份** : 将系统所产生的的所有重要数据多备份几份。
|
||||
- **容灾** : 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
|
||||
|
||||
**异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。
|
||||
|
||||
## Star 趋势
|
||||
|
||||

|
||||

|
||||
|
||||
## 公众号
|
||||
|
||||
@ -440,3 +431,4 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
|
||||
|
||||

|
||||
|
||||
<!-- #endregion home -->
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { defineUserConfig } from "vuepress";
|
||||
import { themeConfig } from "./themeConfig";
|
||||
import { searchPlugin } from "@vuepress/plugin-search";
|
||||
import { searchProPlugin } from "vuepress-plugin-search-pro";
|
||||
|
||||
import theme from "./theme.js";
|
||||
|
||||
export default defineUserConfig({
|
||||
dest: "./dist",
|
||||
theme: themeConfig,
|
||||
shouldPrefetch: false,
|
||||
|
||||
title: "JavaGuide(Java面试+学习指南)",
|
||||
description:
|
||||
"「Java学习指北+Java面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,复习 Java 知识点,首选 JavaGuide! ",
|
||||
|
||||
head: [
|
||||
// meta
|
||||
["meta", { name: "robots", content: "all" }],
|
||||
@ -43,28 +44,20 @@ export default defineUserConfig({
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();`,
|
||||
],
|
||||
["link", { rel: "stylesheet", href: "/iconfont/iconfont.css" }],
|
||||
["link", { rel: "icon", href: "/favicon.ico" }],
|
||||
],
|
||||
|
||||
locales: {
|
||||
"/": {
|
||||
lang: "zh-CN",
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
searchPlugin({
|
||||
// https://v2.vuepress.vuejs.org/zh/reference/plugin/search.html
|
||||
// 排除首页
|
||||
isSearchable: (page) => page.path !== "/",
|
||||
maxSuggestions: 10,
|
||||
hotKeys: ["s", "/"],
|
||||
// 用于在页面的搜索索引中添加额外字段
|
||||
getExtraFields: () => [],
|
||||
locales: {
|
||||
"/": {
|
||||
placeholder: "搜索",
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
theme,
|
||||
|
||||
plugins: [searchProPlugin({ indexContent: true })],
|
||||
|
||||
pagePatterns: ["**/*.md", "!*.snippet.md", "!.vuepress", "!node_modules"],
|
||||
|
||||
shouldPrefetch: false,
|
||||
});
|
||||
|
@ -1,10 +1,19 @@
|
||||
import { navbar } from "vuepress-theme-hope";
|
||||
|
||||
export const navbarConfig = navbar([
|
||||
export default navbar([
|
||||
{ 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: "book", link: "/books/" },
|
||||
{ text: "程序人生", icon: "article", link: "/high-quality-technical-articles/" },
|
||||
{
|
||||
text: "程序人生",
|
||||
icon: "article",
|
||||
link: "/high-quality-technical-articles/",
|
||||
},
|
||||
{
|
||||
text: "网站相关",
|
||||
icon: "about",
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
export const aboutTheAuthor = [
|
||||
import { arraySidebar } from "vuepress-theme-hope";
|
||||
|
||||
export const aboutTheAuthor = arraySidebar([
|
||||
{
|
||||
text: "个人经历",
|
||||
icon: "zuozhe",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"internet-addiction-teenager",
|
||||
"my-college-life",
|
||||
@ -14,7 +16,7 @@ export const aboutTheAuthor = [
|
||||
{
|
||||
text: "杂谈",
|
||||
icon: "chat",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"writing-technology-blog-six-years",
|
||||
"my-article-was-stolen-and-made-into-video-and-it-became-popular",
|
||||
@ -22,4 +24,4 @@ export const aboutTheAuthor = [
|
||||
"zhishixingqiu-two-years",
|
||||
],
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
@ -1,4 +1,6 @@
|
||||
export const books = [
|
||||
import { arraySidebar } from "vuepress-theme-hope";
|
||||
|
||||
export const books = arraySidebar([
|
||||
{
|
||||
text: "计算机基础",
|
||||
link: "cs-basics",
|
||||
@ -30,4 +32,4 @@ export const books = [
|
||||
link: "distributed-system",
|
||||
icon: "distributed-network",
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
@ -1,9 +1,11 @@
|
||||
export const highQualityTechnicalArticles = [
|
||||
import { arraySidebar } from "vuepress-theme-hope";
|
||||
|
||||
export const highQualityTechnicalArticles = arraySidebar([
|
||||
{
|
||||
text: "练级攻略",
|
||||
icon: "et-performance",
|
||||
prefix: "advanced-programmer/",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"the-growth-strategy-of-the-technological-giant",
|
||||
"seven-tips-for-becoming-an-advanced-programmer",
|
||||
@ -14,10 +16,10 @@ export const highQualityTechnicalArticles = [
|
||||
text: "个人经历",
|
||||
icon: "experience",
|
||||
prefix: "personal-experience/",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"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",
|
||||
"huawei-od-275-days",
|
||||
],
|
||||
@ -26,7 +28,7 @@ export const highQualityTechnicalArticles = [
|
||||
text: "程序员",
|
||||
icon: "code",
|
||||
prefix: "programmer/",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"how-do-programmers-publish-a-technical-book",
|
||||
"efficient-book-publishing-and-practice-guide",
|
||||
@ -36,7 +38,7 @@ export const highQualityTechnicalArticles = [
|
||||
text: "面试",
|
||||
icon: "interview",
|
||||
prefix: "interview/",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"the-experience-of-get-offer-from-over-20-big-companies",
|
||||
"the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer",
|
||||
@ -52,10 +54,10 @@ export const highQualityTechnicalArticles = [
|
||||
text: "工作",
|
||||
icon: "work",
|
||||
prefix: "work/",
|
||||
collapsable: false,
|
||||
collapsible: false,
|
||||
children: [
|
||||
"get-into-work-mode-quickly-when-you-join-a-company",
|
||||
"employee-performance",
|
||||
],
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
@ -1,10 +1,11 @@
|
||||
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,
|
||||
"/books/": books,
|
||||
@ -25,6 +26,7 @@ export const sidebarConfig = sidebar({
|
||||
prefix: "interview-preparation/",
|
||||
children: [
|
||||
"teach-you-how-to-prepare-for-the-interview-hand-in-hand",
|
||||
"resume-guide",
|
||||
"key-points-of-interview",
|
||||
"project-experience-guide",
|
||||
"interview-experience",
|
||||
@ -173,10 +175,10 @@ export const sidebarConfig = sidebar({
|
||||
icon: "star",
|
||||
collapsible: true,
|
||||
children: [
|
||||
"osi&tcp-ip-model",
|
||||
"osi-and-tcp-ip-model",
|
||||
"application-layer-protocol",
|
||||
"http&https",
|
||||
"http1.0&http1.1",
|
||||
"http-vs-https",
|
||||
"http1.0-vs-http1.1",
|
||||
"http-status-codes",
|
||||
"dns",
|
||||
"tcp-connection-and-disconnection",
|
||||
@ -198,10 +200,7 @@ export const sidebarConfig = sidebar({
|
||||
text: "Linux",
|
||||
collapsible: true,
|
||||
icon: "linux",
|
||||
children: [
|
||||
"linux-intro",
|
||||
"shell-intro",
|
||||
],
|
||||
children: ["linux-intro", "shell-intro"],
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -420,7 +419,7 @@ export const sidebarConfig = sidebar({
|
||||
children: [
|
||||
"basis-of-authority-certification",
|
||||
"jwt-intro",
|
||||
"advantages&disadvantages-of-jwt",
|
||||
"advantages-and-disadvantages-of-jwt",
|
||||
"sso-intro",
|
||||
"design-of-authority-system",
|
||||
"sentive-words-filter",
|
||||
@ -442,9 +441,9 @@ export const sidebarConfig = sidebar({
|
||||
{
|
||||
text: "理论&算法&协议",
|
||||
icon: "suanfaku",
|
||||
prefix: "theorem&algorithm&protocol/",
|
||||
prefix: "protocol/",
|
||||
children: [
|
||||
"cap&base-theorem",
|
||||
"cap-and-base-theorem",
|
||||
"paxos-algorithm",
|
||||
"raft-algorithm",
|
||||
"gossip-protocl",
|
||||
@ -510,7 +509,7 @@ export const sidebarConfig = sidebar({
|
||||
"high-availability-system-design",
|
||||
"redundancy",
|
||||
"limit-request",
|
||||
"fallback&circuit-breaker",
|
||||
"fallback-and-circuit-breaker",
|
||||
"timeout-and-retry",
|
||||
"performance-test",
|
||||
],
|
@ -1,4 +1,6 @@
|
||||
export const openSourceProject = [
|
||||
import { arraySidebar } from "vuepress-theme-hope";
|
||||
|
||||
export const openSourceProject = arraySidebar([
|
||||
{
|
||||
text: "技术教程",
|
||||
link: "tutorial",
|
||||
@ -34,4 +36,4 @@ export const openSourceProject = [
|
||||
link: "big-data",
|
||||
icon: "big-data",
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
5
docs/.vuepress/styles/index.scss
Normal file
@ -0,0 +1,5 @@
|
||||
body {
|
||||
@media (min-width: 1440px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
$theme-color: #2980B9;
|
||||
$sidebar-width: 20rem;
|
||||
$sidebar-mobile-width: 16rem;
|
||||
$content-width: 60em;
|
||||
$theme-color: #2980b9;
|
||||
// $sidebar-width: 20rem;
|
||||
// $sidebar-mobile-width: 16rem;
|
||||
|
@ -1,19 +1,31 @@
|
||||
import { getDirname, path } from "@vuepress/utils";
|
||||
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",
|
||||
hostname: "https://javaguide.cn/",
|
||||
|
||||
iconAssets: "//at.alicdn.com/t/c/font_2922463_9aayheyb3v7.css",
|
||||
|
||||
author: {
|
||||
name: "Guide",
|
||||
url: "https://javaguide.cn/article/",
|
||||
},
|
||||
|
||||
repo: "https://github.com/Snailclimb/JavaGuide",
|
||||
docsDir: "docs",
|
||||
iconAssets: "//at.alicdn.com/t/c/font_2922463_9aayheyb3v7.css",
|
||||
navbar: navbarConfig,
|
||||
sidebar: sidebarConfig,
|
||||
|
||||
navbar,
|
||||
sidebar,
|
||||
footer:
|
||||
'<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
|
||||
displayFooter: true,
|
||||
|
||||
pageInfo: [
|
||||
"Author",
|
||||
"Category",
|
||||
@ -23,6 +35,7 @@ export const themeConfig = hopeTheme({
|
||||
"Word",
|
||||
"ReadingTime",
|
||||
],
|
||||
|
||||
blog: {
|
||||
intro: "/about-the-author/",
|
||||
sidebarDisplay: "mobile",
|
||||
@ -32,19 +45,33 @@ export const themeConfig = hopeTheme({
|
||||
Gitee: "https://gitee.com/SnailClimb",
|
||||
},
|
||||
},
|
||||
footer:
|
||||
'<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
|
||||
displayFooter: true,
|
||||
|
||||
plugins: {
|
||||
blog: true,
|
||||
copyright: true,
|
||||
mdEnhance: {
|
||||
align: true,
|
||||
codetabs: 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,
|
||||
},
|
||||
feed: {
|
||||
atom: true,
|
||||
json: true,
|
||||
rss: true,
|
||||
},
|
||||
},
|
||||
});
|
@ -31,7 +31,7 @@ tag:
|
||||
|
||||
CSDN 我就不想多说了,就一大型文章垃圾场,都是各种不规范转载,各种收费下载的垃圾资源。这号称国内流量最大的技术网站贼恶心,吃香太难看,能不用就不要用吧!
|
||||
|
||||
像我自己平时用 Google 搜索的时候,都是直接屏蔽掉 CSDN 这个站点的。只需要下载一个叫做 Personal Blocklist 的 Chrome 插件,然后将 blog.csdn.net 添加进黑名单就可以了。
|
||||
像我自己平时用 Google 搜索的时候,都是直接屏蔽掉 CSDN 这个站点的。只需要下载一个叫做 Personal Blocklist 的 Chrome 插件,然后将 blog.csdn.net 添加进黑名单就可以了。
|
||||
|
||||

|
||||
|
||||
|
@ -7,18 +7,18 @@ tag:
|
||||
|
||||
不知不觉已经入职一个多月了,在入职之前我没有在某个公司实习过或者工作过,所以很多东西刚入职工作的我来说还是比较新颖的。学校到职场的转变,带来了角色的转变,其中的差别因人而异。对我而言,在学校的时候课堂上老师课堂上教的东西,自己会根据自己的兴趣选择性接受,甚至很多课程你不想去上的话,还可以逃掉。到了公司就不一样了,公司要求你会的技能你不得不学,除非你不想干了。在学校的时候大部分人编程的目的都是为了通过考试或者找到一份好工作,真正靠自己兴趣支撑起来的很少,到了工作岗位之后我们编程更多的是因为工作的要求,相比于学校的来说会一般会更有挑战而且压力更大。在学校的时候,我们最重要的就是对自己负责,我们不断学习知识去武装自己,但是到了公司之后我们不光要对自己负责,更要对公司负责,毕竟公司出钱请你过来,不是让你一直 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( 反馈) 文化的公司,反馈是告诉人们我们对他们的表现的看法以及他们应该如何更好地做到这一点。刚开始我并没有太在意,慢慢地自己确实感觉到正确的进行反馈对他人会有很大的帮助。因为人在做很多事情的时候,会很难发现别人很容易看到的一些小问题。就比如一个很有趣的现象一样,假如我们在做项目的时候没有测试这个角色,如果你完成了自己的模块,并且自己对这个模块测试了很多遍,你发现已经没啥问题了。但是,到了实际使用的时候会很大概率出现你之前从来没有注意的问题。解释这个问题的说法是:每个人的视野或多或少都是有盲点的,这与我们的关注点息息相关。对于自己做的东西,很多地方自己测试很多遍都不会发现,但是如果让其他人帮你进行测试的话,就很大可能会发现很多显而易见的问题。
|
||||
|
||||

|
||||
|
||||
工作之后,平时更新公众号、专栏还有维护 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 以上的轮子。我相信以这位同事的能力一定会达成目标的,在这里祝福这位同事,希望他可以尽快实现这个目标。
|
||||
|
||||
这是我入职一个多月之后的个人感受,很多地方都是一带而过,后面我会抽时间分享自己在公司或者业余学到的比较有用的知识给各位,希望看过的人都能有所收获。
|
||||
这是我入职一个多月之后的个人感受,很多地方都是一带而过,后面我会抽时间分享自己在公司或者业余学到的比较有用的知识给各位,希望看过的人都能有所收获。
|
||||
|
@ -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)
|
||||
- [JWT 身份认证优缺点分析以及常见问题解决方案](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485655&idx=1&sn=583eeeb081ea21a8ec6347c72aa223d6&chksm=cea2471cf9d5ce0aa135f2fb9aa32d98ebb3338292beaccc1aae43d1178b16c0125eb4139ca4&token=1737409938&lang=zh_CN#rd)
|
||||
@ -53,4 +53,4 @@ tag:
|
||||
|
||||
**所以,我觉得技术的积累和沉淀很大程度在乎工作之外的时间(大佬和一些本身就特别厉害的除外)。**
|
||||
|
||||
**未来还有很长的路要走,即使再有精力也学不完你想学的所有技术,适当取舍、适当妥协,适当娱乐。**
|
||||
**未来还有很长的路要走,即使再有精力也学不完你想学的所有技术,适当取舍、适当妥协,适当娱乐。**
|
||||
|
@ -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。
|
||||
|
||||
@ -15,7 +15,7 @@ tag:
|
||||
|
||||

|
||||
|
||||
维护这个项目的过程中,也被某些人 diss 过:“md项目,没啥含金量,给国人丢脸!”。
|
||||
维护这个项目的过程中,也被某些人 diss 过:“md 项目,没啥含金量,给国人丢脸!”。
|
||||
|
||||
对于说这类话的人,我觉得对我没啥影响,就持续完善,把 JavaGuide 做的更好吧!其实,国外的很多项目也是纯 MD 啊!就比如外国的朋友发起的 awesome 系列、求职面试系列。无需多说,行动自证!凎!
|
||||
|
||||
@ -23,20 +23,20 @@ tag:
|
||||
|
||||
我的公号的小伙伴都是通过这个项目关注我的,趁着午休,简单复盘一下,也算是对关注这个项目的小伙伴负责。
|
||||
|
||||
我在大三开始准备秋招面试的时候,创建了 JavaGuide 这个项目,**2018-05-07** 这一天我提交了**第 1 个 commit**。
|
||||
我在大三开始准备秋招面试的时候,创建了 JavaGuide 这个项目,**2018-05-07** 这一天我提交了**第 1 个 commit**。
|
||||
|
||||
到今天(2021-03-23)为止,这个仓库已经累计有 **2933** 次 commit,累计有 **207** 位朋友参与到了项目中来。
|
||||
|
||||

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

|
||||
|
||||
其实,相比于 star 数量,你看看仓库的 issue 和 pr 更能说明你的项目是否有价值。
|
||||
|
||||
那些到处骗 star 甚至是 刷 star 的行为,我就不多说了,有点丢人。人家觉得你的项目还不错,能提供价值,自然就给你点 star 了。
|
||||
那些到处骗 star 甚至是 刷 star 的行为,我就不多说了,有点丢人。人家觉得你的项目还不错,能提供价值,自然就给你点 star 了。
|
||||
|
||||
**未来几年,我还是会持续完善 JavaGuide。**
|
||||
|
||||
**希望自己以后能开源一些有价值的轮子吧!继续加油!**
|
||||
**希望自己以后能开源一些有价值的轮子吧!继续加油!**
|
||||
|
@ -5,7 +5,7 @@ tag:
|
||||
- 杂谈
|
||||
---
|
||||
|
||||
时间回到 2021-02-25,我在刷哔哩哔哩的时候发现,哔哩哔哩某UP主(某培训机构),擅自将我在知乎的一个回答做成了视频。
|
||||
时间回到 2021-02-25,我在刷哔哩哔哩的时候发现,哔哩哔哩某 UP 主(某培训机构),擅自将我在知乎的一个回答做成了视频。
|
||||
|
||||
原滋原味啊!我艹。甚至,连我开头的自我调侃还加上了!真的牛皮!
|
||||
|
||||
@ -31,7 +31,7 @@ tag:
|
||||
|
||||
其他的视频就不用多看了,是否还是剽窃别人的原创,原封不动地做成视频,大家心里应该有数。
|
||||
|
||||
他们这样做的目的就是一个:**引流到自己的QQ群,然后忽悠你买课程。**
|
||||
他们这样做的目的就是一个:**引流到自己的 QQ 群,然后忽悠你买课程。**
|
||||
|
||||
我并不认为是这完全都是培训机构的问题。培训机构的员工为了流量而做这种恶心的事情,也导致了现在这种事情被越来越频繁地发生。
|
||||
|
||||
@ -69,4 +69,4 @@ tag:
|
||||
|
||||
大家不用担心,这都是小事,我女朋友就是学法律的,国内的某法学双一流学校。
|
||||
|
||||
咱不怕事!凎!!!
|
||||
咱不怕事!凎!!!
|
||||
|
@ -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 年。趁着高考以及应届生毕业之际,简单聊聊自己的大学生活。
|
||||
|
||||
@ -384,4 +384,4 @@ tag:
|
||||
|
||||
我身边专科、三本毕业就进大厂的人也比比皆是。我这句话真不是鸡汤,为了鼓励一些学校出身不太好的朋友。
|
||||
|
||||
**多行动,少抱怨。**
|
||||
**多行动,少抱怨。**
|
||||
|
@ -3,6 +3,8 @@ title: 个人介绍 Q&A
|
||||
category: 走近作者
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
这篇文章我会通过 Q&A 的形式简单介绍一下我自己。
|
||||
|
||||
## 我是什么时候毕业的?
|
||||
@ -45,13 +47,13 @@ category: 走近作者
|
||||
|
||||

|
||||
|
||||
## 为什么自称 Guide哥?
|
||||
## 为什么自称 Guide?
|
||||
|
||||
可能是因为我的项目名字叫做 JavaGuide , 所以导致有很多人称呼我为 **Guide哥**。
|
||||
|
||||
后面,为了读者更方便称呼,我就将自己的笔名改成了 **Guide哥**。
|
||||
后面,为了读者更方便称呼,我就将自己的笔名改成了 **Guide**。
|
||||
|
||||
我早期写文章用的笔名是 SnailClimb 。很多人不知道这个名字是啥意思,给大家拆解一下就清楚了。SnailClimb=Snail(蜗牛)+Climb(攀登)。我从小就非常喜欢听周杰伦的歌曲,特别是他的《蜗牛》🐌 这首歌曲,另外,当年我高考发挥的算是比较失常,上了大学之后还算是比较“奋青”,所以,我就给自己起的笔名叫做 SnailClimb ,寓意自己要不断向上攀登,嘿嘿😁
|
||||
我早期写文章用的笔名是 SnailClimb 。很多人不知道这个名字是啥意思,给大家拆解一下就清楚了。SnailClimb=Snail(蜗牛)+Climb(攀登)。我从小就非常喜欢听周杰伦的歌曲,特别是他的《蜗牛》🐌 这首歌曲,另外,当年我高考发挥的算是比较失常,上了大学之后还算是比较“奋青”,所以,我就给自己起的笔名叫做 SnailClimb ,寓意自己要不断向上攀登,嘿嘿 😁
|
||||
|
||||

|
||||
|
||||
|
@ -122,7 +122,7 @@ tag:
|
||||
|
||||
最重要的是一定要重视 Markdown 规范,不然内容再好也会显得不专业。
|
||||
|
||||
Markdown 规范请参考:**https://javaguide.cn/javaguide/contribution-guideline.html** (很重要,尽量按照规范来,对你工作中写文档会非常有帮助)
|
||||
Markdown 规范请参考:**<https://javaguide.cn/javaguide/contribution-guideline.html>** (很重要,尽量按照规范来,对你工作中写文档会非常有帮助)
|
||||
|
||||
## 有没有什么写作技巧分享?
|
||||
|
||||
@ -170,4 +170,4 @@ Markdown 规范请参考:**https://javaguide.cn/javaguide/contribution-guideli
|
||||
|
||||
## 总结
|
||||
|
||||
总的来说,写技术博客是一件利己利彼的事情。你可能会从中收获到很多东西,你写的东西也可能对别人也有很大的帮助。但是,写技术博客还是比较耗费自己时间的,你需要和工作以及生活做好权衡。
|
||||
总的来说,写技术博客是一件利己利彼的事情。你可能会从中收获到很多东西,你写的东西也可能对别人也有很大的帮助。但是,写技术博客还是比较耗费自己时间的,你需要和工作以及生活做好权衡。
|
||||
|
@ -4,6 +4,8 @@ category: 知识星球
|
||||
star: 2
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
时间过的真快,知识星球我已经平稳运行了 3 年有余了!
|
||||
|
||||
在 2019 年 12 月 29 号,经过了大概一年左右的犹豫期,我正式确定要开始做一个自己的星球。
|
||||
@ -121,14 +123,18 @@ star: 2
|
||||
|
||||
## 如何加入?
|
||||
|
||||

|
||||

|
||||
|
||||
如果你想要进知识星球的话,建议你添加我的微信(guidege666)领取一个星球专属优惠券(一定要备注“优惠卷”),可以优惠 **30** 元,无任何套路,无任何潜在收费项。收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。
|
||||
你可以扫描上方的二维码原价加入(续费半价)。不过,我更建议你添加我的个人微信领取一个 **30** 元的星球专属优惠券(一定要备注“优惠卷”)。
|
||||
|
||||
**无任何套路,无任何潜在收费项。收费虽然是白菜价,但星球里的内容或许比你参加上万的培训班质量还要高。用心做内容,不割韭菜!**
|
||||
|
||||
**一定要备注“优惠卷”**,不然通过不了。
|
||||
|
||||

|
||||
|
||||
进入星球之后,记得查看[星球使用指南](https://t.zsxq.com/0d18KSarv)(一定要看!) 。
|
||||
|
||||
随着时间推移,星球积累的干货资源越来越多,我花在星球上的时间也越来越多,星球的价格会逐步向上调整,想要加入的同学一定要尽早。
|
||||
|
||||
不过, **一定要确定需要再进** 。并且, **三天之内觉得内容不满意可以全额退款** 。
|
||||
|
@ -271,4 +271,4 @@ Github 上就有一些名校的计算机网络试验/Project:
|
||||
|
||||
我上面推荐的书籍的难度还是比较高的,真心很难坚持看完。这里强烈推荐[哈工大的编译原理视频课程](https://www.icourse163.org/course/HIT-1002123007),真心不错,还是国家精品课程,关键还是又漂亮有温柔的美女老师讲的!
|
||||
|
||||

|
||||

|
||||
|
@ -16,13 +16,11 @@ head:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
如果你比较喜欢动手,对于理论知识比较抵触的话,推荐你看看[《如何开发一个简单的数据库》](https://cstack.github.io/db_tutorial/) ,这个 project 会手把手教你编写一个简单的数据库。
|
||||
|
||||

|
||||
|
||||
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 语言写的,朋友们也可以去瞅瞅。
|
||||
|
||||
@ -44,7 +42,7 @@ Github上也已经有大佬用 Java 实现过一个简易的数据库,介绍
|
||||
|
||||

|
||||
|
||||
不管是 MySQL 还是Oracle ,它们总体的架子是差不多的,不同的是其内部的实现比如数据库索引的数据结构、存储引擎的实现方式等等。
|
||||
不管是 MySQL 还是 Oracle ,它们总体的架子是差不多的,不同的是其内部的实现比如数据库索引的数据结构、存储引擎的实现方式等等。
|
||||
|
||||
这本书有些地方还是翻译的比较蹩脚,有能力看英文版的还是建议上手英文版。
|
||||
|
||||
|
@ -18,9 +18,9 @@ icon: "distributed-network"
|
||||
|
||||

|
||||
|
||||
作者专门写了一篇文章来介绍这本书的背后的故事,感兴趣的小伙伴可以自行查阅: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)。
|
||||
|
||||
@ -40,7 +40,7 @@ icon: "distributed-network"
|
||||
|
||||

|
||||
|
||||
**[《深入理解分布式事务》](https://book.douban.com/subject/35626925/)** 这本书是的其中一位作者是 Apache ShenYu(incubating)网关创始人、Hmily、RainCat、Myth等分布式事务框架的创始人。
|
||||
**[《深入理解分布式事务》](https://book.douban.com/subject/35626925/)** 这本书是的其中一位作者是 Apache ShenYu(incubating)网关创始人、Hmily、RainCat、Myth 等分布式事务框架的创始人。
|
||||
|
||||
学习分布式事务的时候,可以参考一下这本书。虽有一些小错误以及逻辑不通顺的地方,但对于各种分布式事务解决方案的介绍,总体来说还是不错的。
|
||||
|
||||
|
@ -6,7 +6,7 @@ icon: "java"
|
||||
|
||||
## Java 基础
|
||||
|
||||
**[《Head First Java》](https://book.douban.com/subject/2000732/)**
|
||||
**[《Head First Java》](https://book.douban.com/subject/2000732/)**
|
||||
|
||||

|
||||
|
||||
@ -18,7 +18,7 @@ icon: "java"
|
||||
|
||||
我个人觉得这本书还是挺适合编程新手阅读的,毕竟是 “Head First” 系列。
|
||||
|
||||
**[《Java 核心技术卷 1+卷 2》](https://book.douban.com/subject/34898994/)**
|
||||
**[《Java 核心技术卷 1+卷 2》](https://book.douban.com/subject/34898994/)**
|
||||
|
||||

|
||||
|
||||
@ -26,7 +26,7 @@ icon: "java"
|
||||
|
||||
我当时在大学的时候就买了两本放在寝室,没事的时候就翻翻。建议有点 Java 基础之后再读,介绍的还是比较深入和全面的,非常推荐。
|
||||
|
||||
**[《Java 编程思想》](https://book.douban.com/subject/2130190/)**
|
||||
**[《Java 编程思想》](https://book.douban.com/subject/2130190/)**
|
||||
|
||||

|
||||
|
||||
@ -34,7 +34,7 @@ icon: "java"
|
||||
|
||||
我第一次看的时候还觉得有点枯燥,那时候还在上大二,看了 1/3 就没看下去了。
|
||||
|
||||
**[《Java 8实战》](https://book.douban.com/subject/26772632/)**
|
||||
**[《Java 8 实战》](https://book.douban.com/subject/26772632/)**
|
||||
|
||||

|
||||
|
||||
@ -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/)**
|
||||
|
||||
@ -78,7 +78,7 @@ _这本书还是非常适合我们用来学习 Java 多线程的。这本书的
|
||||
|
||||
## JVM
|
||||
|
||||
**[《深入理解 Java 虚拟机》](https://book.douban.com/subject/34907497/)**
|
||||
**[《深入理解 Java 虚拟机》](https://book.douban.com/subject/34907497/)**
|
||||
|
||||

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

|
||||

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

|
||||
|
||||
@ -24,4 +24,4 @@ Elasticsearch 在 Apache Lucene 的基础上开发而成,学习 ES 之前,
|
||||
|
||||
如果你想进一步深入研究 Elasticsearch 原理的话,可以看看张超老师的 **[《Elasticsearch 源码解析与优化实战》](https://book.douban.com/subject/30386800/)** 这本书。这是市面上唯一一本写 Elasticsearch 源码的书。
|
||||
|
||||

|
||||

|
||||
|
@ -32,7 +32,7 @@ head:
|
||||
|
||||
Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓是对后生的一大馈赠。
|
||||
|
||||
**[《Effective Java 》](https://book.douban.com/subject/30412517/)**
|
||||
**[《Effective Java 》](https://book.douban.com/subject/30412517/)**
|
||||
|
||||

|
||||
|
||||
@ -127,5 +127,5 @@ Bob 大叔将自己对整洁代码的理解浓缩在了这本书中,真可谓
|
||||
|
||||
最后再推荐两个相关的文档:
|
||||
|
||||
- **阿里巴巴 Java 开发手册** :https://github.com/alibaba/p3c
|
||||
- **Google Java 编程风格指南:** http://www.hawstein.com/posts/google-java-style.html
|
||||
- **阿里巴巴 Java 开发手册** :<https://github.com/alibaba/p3c>
|
||||
- **Google Java 编程风格指南**: <http://www.hawstein.com/posts/google-java-style.html>
|
||||
|
@ -11,7 +11,7 @@ tag:
|
||||
|
||||
> 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
|
||||
|
||||
**我们首先从最低有效位也就是列表 l1和 l2 的表头开始相加。注意需要考虑到进位的情况!**
|
||||
**我们首先从最低有效位也就是列表 l1 和 l2 的表头开始相加。注意需要考虑到进位的情况!**
|
||||
|
||||
```java
|
||||
/**
|
||||
@ -76,8 +76,8 @@ public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
|
||||
|
||||
## 2. 翻转链表
|
||||
|
||||
|
||||
### 题目描述
|
||||
|
||||
> 剑指 offer:输入一个链表,反转链表后,输出链表的所有元素。
|
||||
|
||||

|
||||
@ -88,7 +88,6 @@ public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
|
||||
|
||||
### Solution
|
||||
|
||||
|
||||
```java
|
||||
public class ListNode {
|
||||
int val;
|
||||
@ -102,7 +101,7 @@ public class ListNode {
|
||||
|
||||
```java
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Snailclimb
|
||||
* @date 2018年9月19日
|
||||
* @Description: TODO
|
||||
@ -162,18 +161,17 @@ public class Solution {
|
||||
1
|
||||
```
|
||||
|
||||
## 3. 链表中倒数第k个节点
|
||||
## 3. 链表中倒数第 k 个节点
|
||||
|
||||
### 题目描述
|
||||
|
||||
> 剑指offer: 输入一个链表,输出该链表中倒数第k个结点。
|
||||
> 剑指 offer: 输入一个链表,输出该链表中倒数第 k 个结点。
|
||||
|
||||
### 问题分析
|
||||
|
||||
> **链表中倒数第k个节点也就是正数第(L-K+1)个节点,知道了只一点,这一题基本就没问题!**
|
||||
|
||||
首先两个节点/指针,一个节点 node1 先开始跑,指针 node1 跑到 k-1 个节点后,另一个节点 node2 开始跑,当 node1 跑到最后时,node2 所指的节点就是倒数第k个节点也就是正数第(L-K+1)个节点。
|
||||
> **链表中倒数第 k 个节点也就是正数第(L-K+1)个节点,知道了只一点,这一题基本就没问题!**
|
||||
|
||||
首先两个节点/指针,一个节点 node1 先开始跑,指针 node1 跑到 k-1 个节点后,另一个节点 node2 开始跑,当 node1 跑到最后时,node2 所指的节点就是倒数第 k 个节点也就是正数第(L-K+1)个节点。
|
||||
|
||||
### Solution
|
||||
|
||||
@ -221,9 +219,7 @@ public class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 4. 删除链表的倒数第N个节点
|
||||
|
||||
## 4. 删除链表的倒数第 N 个节点
|
||||
|
||||
> Leetcode:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
|
||||
|
||||
@ -248,8 +244,7 @@ public class Solution {
|
||||
|
||||
### 问题分析
|
||||
|
||||
|
||||
我们注意到这个问题可以容易地简化成另一个问题:删除从列表开头数起的第 (L - n + 1)个结点,其中 L是列表的长度。只要我们找到列表的长度 L,这个问题就很容易解决。
|
||||
我们注意到这个问题可以容易地简化成另一个问题:删除从列表开头数起的第 (L - n + 1)个结点,其中 L 是列表的长度。只要我们找到列表的长度 L,这个问题就很容易解决。
|
||||
|
||||

|
||||
|
||||
@ -299,16 +294,13 @@ public class Solution {
|
||||
**复杂度分析:**
|
||||
|
||||
- **时间复杂度 O(L)** :该算法对列表进行了两次遍历,首先计算了列表的长度 LL 其次找到第 (L - n)(L−n) 个结点。 操作执行了 2L-n2L−n 步,时间复杂度为 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
|
||||
/**
|
||||
@ -345,25 +337,21 @@ public class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 5. 合并两个排序的链表
|
||||
|
||||
### 题目描述
|
||||
|
||||
> 剑指offer:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
|
||||
> 剑指 offer:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
|
||||
|
||||
### 问题分析
|
||||
|
||||
我们可以这样分析:
|
||||
我们可以这样分析:
|
||||
|
||||
1. 假设我们有两个链表 A,B;
|
||||
2. A的头节点A1的值与B的头结点B1的值比较,假设A1小,则A1为头节点;
|
||||
3. A2再和B1比较,假设B1小,则,A1指向B1;
|
||||
4. A2再和B2比较
|
||||
就这样循环往复就行了,应该还算好理解。
|
||||
1. 假设我们有两个链表 A,B;
|
||||
2. A 的头节点 A1 的值与 B 的头结点 B1 的值比较,假设 A1 小,则 A1 为头节点;
|
||||
3. A2 再和 B1 比较,假设 B1 小,则,A1 指向 B1;
|
||||
4. A2 再和 B2 比较
|
||||
就这样循环往复就行了,应该还算好理解。
|
||||
|
||||
考虑通过递归的方式实现!
|
||||
|
||||
@ -396,8 +384,7 @@ public ListNode Merge(ListNode list1,ListNode list2) {
|
||||
}else{
|
||||
list2.next = Merge(list1, list2.next);
|
||||
return list2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7,14 +7,14 @@ tag:
|
||||
|
||||
## 斐波那契数列
|
||||
|
||||
**题目描述:**
|
||||
**题目描述:**
|
||||
|
||||
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
|
||||
大家都知道斐波那契数列,现在要求输入一个整数 n,请你输出斐波那契数列的第 n 项。
|
||||
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);
|
||||
> b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
|
||||
> c.由a,b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
|
||||
> a.如果两种跳法,1 阶或者 2 阶,那么假定第一次跳的是一阶,那么剩下的是 n-1 个台阶,跳法是 f(n-1);
|
||||
> b.假定第一次跳的是 2 阶,那么剩下的是 n-2 个台阶,跳法是 f(n-2)
|
||||
> c.由 a,b 假设可以得出总跳法为: f(n) = f(n-1) + f(n-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级
|
||||
跳1级,剩下n-1级,则剩下跳法是f(n-1)
|
||||
跳2级,剩下n-2级,则剩下跳法是f(n-2)
|
||||
假设 n>=2,第一步有 n 种跳法:跳 1 级、跳 2 级、到跳 n 级
|
||||
跳 1 级,剩下 n-1 级,则剩下跳法是 f(n-1)
|
||||
跳 2 级,剩下 n-2 级,则剩下跳法是 f(n-2)
|
||||
......
|
||||
跳n-1级,剩下1级,则剩下跳法是f(1)
|
||||
跳n级,剩下0级,则剩下跳法是f(0)
|
||||
所以在n>=2的情况下:
|
||||
跳 n-1 级,剩下 1 级,则剩下跳法是 f(1)
|
||||
跳 n 级,剩下 0 级,则剩下跳法是 f(0)
|
||||
所以在 n>=2 的情况下:
|
||||
f(n)=f(n-1)+f(n-2)+...+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-1)=f(n-2)+f(n-3)+...+f(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次方
|
||||
2. “>>”: **右移运算符**,等同于除2的n次方
|
||||
3. “>>>” : **无符号右移运算符**,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。与>>类似。
|
||||
1. “<<” : **左移运算符**,等同于乘 2 的 n 次方
|
||||
2. “>>”: **右移运算符**,等同于除 2 的 n 次方
|
||||
3. “>>>” : **无符号右移运算符**,不管移动前最高位是 0 还是 1,右移后左侧产生的空位部分都以 0 来填充。与>>类似。
|
||||
|
||||
```java
|
||||
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
|
||||
```
|
||||
|
||||
|
||||
## 二维数组查找
|
||||
|
||||
**题目描述:**
|
||||
@ -152,8 +151,8 @@ 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)方法了,一行代码就可以解决。
|
||||
|
||||
@ -203,7 +202,7 @@ public String replaceSpace(StringBuffer str) {
|
||||
out.append(b);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
return out.toString();
|
||||
}
|
||||
```
|
||||
|
||||
@ -213,7 +212,7 @@ public String replaceSpace(StringBuffer str) {
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
//return str.toString().replaceAll(" ", "%20");
|
||||
//public String replaceAll(String regex,String replacement)
|
||||
//用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串。
|
||||
//用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串。
|
||||
//\ 转义字符. 如果你要使用 "\" 本身, 则应该使用 "\\". String类型中的空格用“\s”表示,所以我这里猜测"\\s"就是代表空格的意思
|
||||
return str.toString().replaceAll("\\s", "%20");
|
||||
}
|
||||
@ -223,25 +222,22 @@ public String replaceSpace(StringBuffer str) {
|
||||
|
||||
**题目描述:**
|
||||
|
||||
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
|
||||
给定一个 double 类型的浮点数 base 和 int 类型的整数 exponent。求 base 的 exponent 次方。
|
||||
|
||||
**问题解析:**
|
||||
|
||||
这道题算是比较麻烦和难一点的一个了。我这里采用的是**二分幂**思想,当然也可以采用**快速幂**。
|
||||
更具剑指offer书中细节,该题的解题思路如下:
|
||||
1.当底数为0且指数<0时,会出现对0求倒数的情况,需进行错误处理,设置一个全局变量;
|
||||
2.判断底数是否等于0,由于base为double型,所以不能直接用==判断
|
||||
3.优化求幂函数(二分幂)。
|
||||
当n为偶数,a^n =(a^n/2)*(a^n/2);
|
||||
当n为奇数,a^n = a^[(n-1)/2] * a^[(n-1)/2] * a。时间复杂度O(logn)
|
||||
更具剑指 offer 书中细节,该题的解题思路如下: 1.当底数为 0 且指数<0 时,会出现对 0 求倒数的情况,需进行错误处理,设置一个全局变量; 2.判断底数是否等于 0,由于 base 为 double 型,所以不能直接用==判断 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)
|
||||
|
||||
**示例代码:**
|
||||
|
||||
```java
|
||||
public class Solution {
|
||||
boolean invalidInput=false;
|
||||
public class Solution {
|
||||
boolean invalidInput=false;
|
||||
public double Power(double base, int exponent) {
|
||||
//如果底数等于0并且指数小于0
|
||||
//由于base为double型,不能直接用==判断
|
||||
@ -286,7 +282,7 @@ public class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
当然这一题也可以采用笨方法:累乘。不过这种方法的时间复杂度为O(n),这样没有前一种方法效率高。
|
||||
当然这一题也可以采用笨方法:累乘。不过这种方法的时间复杂度为 O(n),这样没有前一种方法效率高。
|
||||
|
||||
```java
|
||||
// 使用累乘
|
||||
@ -311,17 +307,17 @@ public double powerAnother(double base, int exponent) {
|
||||
**问题解析:**
|
||||
|
||||
这道题有挺多种解法的,给大家介绍一种我觉得挺好理解的方法:
|
||||
我们首先统计奇数的个数假设为n,然后新建一个等长数组,然后通过循环判断原数组中的元素为偶数还是奇数。如果是则从数组下标0的元素开始,把该奇数添加到新数组;如果是偶数则从数组下标为n的元素开始把该偶数添加到新数组中。
|
||||
我们首先统计奇数的个数假设为 n,然后新建一个等长数组,然后通过循环判断原数组中的元素为偶数还是奇数。如果是则从数组下标 0 的元素开始,把该奇数添加到新数组;如果是偶数则从数组下标为 n 的元素开始把该偶数添加到新数组中。
|
||||
|
||||
**示例代码:**
|
||||
|
||||
时间复杂度为O(n),空间复杂度为O(n)的算法
|
||||
时间复杂度为 O(n),空间复杂度为 O(n)的算法
|
||||
|
||||
```java
|
||||
public class Solution {
|
||||
public void reOrderArray(int [] array) {
|
||||
//如果数组长度等于0或者等于1,什么都不做直接返回
|
||||
if(array.length==0||array.length==1)
|
||||
if(array.length==0||array.length==1)
|
||||
return;
|
||||
//oddCount:保存奇数个数
|
||||
//oddBegin:奇数从数组头部开始添加
|
||||
@ -335,7 +331,7 @@ public class Solution {
|
||||
for(int i=0;i<array.length;i++){
|
||||
//如果数为基数新数组从头开始添加元素
|
||||
//如果为偶数就从oddCount(数组中的奇数个数)开始添加元素
|
||||
if((array[i]&1)==1)
|
||||
if((array[i]&1)==1)
|
||||
newArray[oddBegin++]=array[i];
|
||||
else newArray[oddCount++]=array[i];
|
||||
}
|
||||
@ -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。
|
||||
规律一:要找到倒数第k个结点,需要向前走多少步呢?比如倒数第一个结点,需要走n步,那倒数第二个结点呢?很明显是向前走了n-1步,所以可以找到规律是找到倒数第k个结点,需要向前走n-k+1步。
|
||||
前提假设:链表的结点个数(长度)为 n。
|
||||
规律一:要找到倒数第 k 个结点,需要向前走多少步呢?比如倒数第一个结点,需要走 n 步,那倒数第二个结点呢?很明显是向前走了 n-1 步,所以可以找到规律是找到倒数第 k 个结点,需要向前走 n-k+1 步。
|
||||
|
||||
**算法开始:**
|
||||
|
||||
1. 设两个都指向head的指针p1和p2,当p1走了k-1步的时候,停下来。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个结点处。
|
||||
1. 设两个都指向 head 的指针 p1 和 p2,当 p1 走了 k-1 步的时候,停下来。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 个结点处。
|
||||
这样是不是很好理解了呢?
|
||||
|
||||
**考察内容:**
|
||||
@ -410,7 +406,7 @@ public class Solution {
|
||||
//如果节点个数小于所求的倒数第k个节点,则返回空
|
||||
if(count<a) return null;
|
||||
return pre;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -425,7 +421,7 @@ public class Solution {
|
||||
|
||||
链表的很常规的一道题,这一道题思路不算难,但自己实现起来真的可能会感觉无从下手,我是参考了别人的代码。
|
||||
思路就是我们根据链表的特点,前一个节点指向下一个节点的特点,把后面的节点移到前面来。
|
||||
就比如下图:我们把1节点和2节点互换位置,然后再将3节点指向2节点,4节点指向3节点,这样以来下面的链表就被反转了。
|
||||
就比如下图:我们把 1 节点和 2 节点互换位置,然后再将 3 节点指向 2 节点,4 节点指向 3 节点,这样以来下面的链表就被反转了。
|
||||
|
||||

|
||||
|
||||
@ -475,9 +471,9 @@ public class Solution {
|
||||
我们可以这样分析:
|
||||
|
||||
1. 假设我们有两个链表 A,B;
|
||||
2. A的头节点A1的值与B的头结点B1的值比较,假设A1小,则A1为头节点;
|
||||
3. A2再和B1比较,假设B1小,则,A1指向B1;
|
||||
4. A2再和B2比较。。。。。。。
|
||||
2. A 的头节点 A1 的值与 B 的头结点 B1 的值比较,假设 A1 小,则 A1 为头节点;
|
||||
3. A2 再和 B1 比较,假设 B1 小,则,A1 指向 B1;
|
||||
4. A2 再和 B2 比较。。。。。。。
|
||||
就这样循环往复就行了,应该还算好理解。
|
||||
|
||||
**考察内容:**
|
||||
@ -509,10 +505,10 @@ public class Solution {
|
||||
return list1;
|
||||
}
|
||||
ListNode mergeHead = null;
|
||||
ListNode current = null;
|
||||
ListNode current = null;
|
||||
//当list1和list2不为空时
|
||||
while(list1!=null && list2!=null){
|
||||
//取较小值作头结点
|
||||
//取较小值作头结点
|
||||
if(list1.val <= list2.val){
|
||||
if(mergeHead == null){
|
||||
mergeHead = current = list1;
|
||||
@ -561,7 +557,7 @@ public ListNode Merge(ListNode list1,ListNode list2) {
|
||||
}else{
|
||||
list2.next = Merge(list1, list2.next);
|
||||
return list2;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -569,17 +565,17 @@ public ListNode Merge(ListNode list1,ListNode list2) {
|
||||
|
||||
**题目描述:**
|
||||
|
||||
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
|
||||
用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。 队列中的元素为 int 类型。
|
||||
|
||||
**问题分析:**
|
||||
|
||||
先来回顾一下栈和队列的基本特点:
|
||||
**栈:**后进先出(LIFO)
|
||||
**队列:** 先进先出
|
||||
很明显我们需要根据JDK给我们提供的栈的一些基本方法来实现。先来看一下Stack类的一些基本方法:
|
||||
很明显我们需要根据 JDK 给我们提供的栈的一些基本方法来实现。先来看一下 Stack 类的一些基本方法:
|
||||

|
||||
|
||||
既然题目给了我们两个栈,我们可以这样考虑当push的时候将元素push进stack1,pop的时候我们先把stack1的元素pop到stack2,然后再对stack2执行pop操作,这样就可以保证是先进先出的。(负[pop]负[pop]得正[先进先出])
|
||||
既然题目给了我们两个栈,我们可以这样考虑当 push 的时候将元素 push 进 stack1,pop 的时候我们先把 stack1 的元素 pop 到 stack2,然后再对 stack2 执行 pop 操作,这样就可以保证是先进先出的。(负[pop]负[pop]得正[先进先出])
|
||||
|
||||
**考察内容:**
|
||||
|
||||
@ -590,16 +586,16 @@ public ListNode Merge(ListNode list1,ListNode list2) {
|
||||
```java
|
||||
//左程云的《程序员代码面试指南》的答案
|
||||
import java.util.Stack;
|
||||
|
||||
|
||||
public class Solution {
|
||||
Stack<Integer> stack1 = new Stack<Integer>();
|
||||
Stack<Integer> stack2 = new Stack<Integer>();
|
||||
|
||||
|
||||
//当执行push操作时,将元素添加到stack1
|
||||
public void push(int node) {
|
||||
stack1.push(node);
|
||||
}
|
||||
|
||||
|
||||
public int pop() {
|
||||
//如果两个队列都为空则抛出异常,说明用户没有push进任何元素
|
||||
if(stack1.empty()&&stack2.empty()){
|
||||
@ -621,37 +617,37 @@ public class Solution {
|
||||
|
||||
**题目描述:**
|
||||
|
||||
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
|
||||
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 是该压栈序列对应的一个弹出序列,但 4,3,5,1,2 就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
|
||||
|
||||
**题目分析:**
|
||||
|
||||
这道题想了半天没有思路,参考了Alias的答案,他的思路写的也很详细应该很容易看懂。
|
||||
这道题想了半天没有思路,参考了 Alias 的答案,他的思路写的也很详细应该很容易看懂。
|
||||
作者:Alias
|
||||
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
|
||||
|
||||
此时栈顶4=4,出栈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
|
||||
|
||||
….
|
||||
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
|
||||
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
|
||||
|
||||
**考察内容:**
|
||||
|
||||
@ -683,4 +679,4 @@ public class Solution {
|
||||
return s.empty();
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
@ -57,7 +57,6 @@ tag:
|
||||
1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
|
||||
2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。
|
||||
|
||||
|
||||
## 编码实战
|
||||
|
||||
### 通过 Java 编程手动实现布隆过滤器
|
||||
@ -242,12 +241,12 @@ System.out.println(filter.mightContain(2));
|
||||
|
||||
Redis v4.0 之后有了 Module(模块/插件) 功能,Redis Modules 让 Redis 可以使用外部模块扩展其功能 。布隆过滤器就是其中的 Module。详情可以查看 Redis 官方对 Redis Modules 的介绍 :https://redis.io/modules
|
||||
|
||||
另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom
|
||||
另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom
|
||||
其他还有:
|
||||
|
||||
* redis-lua-scaling-bloom-filter(lua 脚本实现):https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
|
||||
* pyreBloom(Python 中的快速 Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom
|
||||
* ......
|
||||
- redis-lua-scaling-bloom-filter(lua 脚本实现):https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
|
||||
- pyreBloom(Python 中的快速 Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom
|
||||
- ......
|
||||
|
||||
RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、JavaScript 和 PHP。
|
||||
|
||||
@ -287,7 +286,7 @@ root@21396d02c252:/data# redis-cli
|
||||
|
||||
可选参数:
|
||||
|
||||
* expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。
|
||||
- expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。
|
||||
|
||||
### 实际使用
|
||||
|
||||
|
@ -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关注B,B不一定关注A。在这种情况下,我们就用带箭头的边表示二者的关系,这样的图就是有向图。
|
||||
边表示的是顶点之间的关系,有的关系是双向的,比如同学关系,A 是 B 的同学,那么 B 也肯定是 A 的同学,那么在表示 A 和 B 的关系时,就不用关注方向,用不带箭头的边表示,这样的图就是无向图。
|
||||
|
||||
有的关系是有方向的,比如父子关系,师生关系,微博的关注关系,A 是 B 的爸爸,但 B 肯定不是 A 的爸爸,A 关注 B,B 不一定关注 A。在这种情况下,我们就用带箭头的边表示二者的关系,这样的图就是有向图。
|
||||
|
||||
### 无权图和带权图
|
||||
|
||||
@ -55,16 +59,18 @@ tag:
|
||||

|
||||
|
||||
## 图的存储
|
||||
|
||||
### 邻接矩阵存储
|
||||
|
||||
邻接矩阵将图用二维矩阵存储,是一种较为直观的表示方式。
|
||||
|
||||
如果第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。如下图所示:
|
||||
|
||||

|
||||
|
||||
值得注意的是:**无向图的邻接矩阵是一个对称矩阵,因为在无向图中,顶点i和顶点j有关系,则顶点j和顶点i必有关系。**
|
||||
值得注意的是:**无向图的邻接矩阵是一个对称矩阵,因为在无向图中,顶点 i 和顶点 j 有关系,则顶点 j 和顶点 i 必有关系。**
|
||||
|
||||

|
||||
|
||||
@ -74,7 +80,7 @@ tag:
|
||||
|
||||
针对上面邻接矩阵比较浪费内存空间的问题,诞生了图的另外一种存储方法—**邻接表** 。
|
||||
|
||||
邻接链表使用一个链表来存储某个顶点的所有后继相邻顶点。对于图中每个顶点Vi,把所有邻接于Vi的顶点Vj链成一个单链表,这个单链表称为顶点Vi的 **邻接表**。如下图所示:
|
||||
邻接链表使用一个链表来存储某个顶点的所有后继相邻顶点。对于图中每个顶点 Vi,把所有邻接于 Vi 的顶点 Vj 链成一个单链表,这个单链表称为顶点 Vi 的 **邻接表**。如下图所示:
|
||||
|
||||

|
||||
|
||||
@ -82,38 +88,40 @@ tag:
|
||||
|
||||
大家可以数一数邻接表中所存储的元素的个数以及图中边的条数,你会发现:
|
||||
|
||||
- 在无向图中,邻接表元素个数等于边的条数的两倍,如左图所示的无向图中,边的条数为7,邻接表存储的元素个数为14。
|
||||
- 在有向图中,邻接表元素个数等于边的条数,如右图所示的有向图中,边的条数为8,邻接表存储的元素个数为8。
|
||||
- 在无向图中,邻接表元素个数等于边的条数的两倍,如左图所示的无向图中,边的条数为 7,邻接表存储的元素个数为 14。
|
||||
- 在有向图中,邻接表元素个数等于边的条数,如右图所示的有向图中,边的条数为 8,邻接表存储的元素个数为 8。
|
||||
|
||||
## 图的搜索
|
||||
|
||||
### 广度优先搜索
|
||||
|
||||
广度优先搜索就像水面上的波纹一样一层一层向外扩展,如下图所示:
|
||||
|
||||

|
||||
|
||||
**广度优先搜索的具体实现方式用到了之前所学过的线性数据结构——队列** 。具体过程如下图所示:
|
||||
|
||||
**第1步:**
|
||||
**第 1 步:**
|
||||
|
||||

|
||||
|
||||
**第2步:**
|
||||
**第 2 步:**
|
||||
|
||||

|
||||
|
||||
**第3步:**
|
||||
**第 3 步:**
|
||||
|
||||

|
||||
|
||||
**第4步:**
|
||||
**第 4 步:**
|
||||
|
||||

|
||||
|
||||
**第5步:**
|
||||
**第 5 步:**
|
||||
|
||||

|
||||
|
||||
**第6步:**
|
||||
**第 6 步:**
|
||||
|
||||

|
||||
|
||||
@ -123,30 +131,28 @@ tag:
|
||||
|
||||

|
||||
|
||||
|
||||
**和广度优先搜索类似,深度优先搜索的具体实现用到了另一种线性数据结构——栈** 。具体过程如下图所示:
|
||||
|
||||
**第1步:**
|
||||
**第 1 步:**
|
||||
|
||||

|
||||
|
||||
**第2步:**
|
||||
**第 2 步:**
|
||||
|
||||

|
||||
|
||||
**第3步:**
|
||||
**第 3 步:**
|
||||
|
||||

|
||||
|
||||
**第4步:**
|
||||
**第 4 步:**
|
||||
|
||||

|
||||
|
||||
**第5步:**
|
||||
**第 5 步:**
|
||||
|
||||

|
||||
|
||||
**第6步:**
|
||||
**第 6 步:**
|
||||
|
||||

|
||||
|
||||
|
@ -23,11 +23,12 @@ tag:
|
||||
|
||||

|
||||
|
||||
第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)` 的时间复杂度。
|
||||
@ -39,25 +40,30 @@ tag:
|
||||
## 堆的分类
|
||||
|
||||
堆分为 **最大堆** 和 **最小堆**。二者的区别在于节点的排序方式。
|
||||
|
||||
- **最大堆** :堆中的每一个节点的值都大于等于子树中所有节点的值
|
||||
- **最小堆** :堆中的每一个节点的值都小于等于子树中所有节点的值
|
||||
|
||||
如下图所示,图1是最大堆,图2是最小堆
|
||||
如下图所示,图 1 是最大堆,图 2 是最小堆
|
||||
|
||||

|
||||
|
||||
|
||||
## 堆的存储
|
||||
之前介绍树的时候说过,由于完全二叉树的优秀性质,利用数组存储二叉树即节省空间,又方便索引(若根结点的序号为1,那么对于树中任意节点i,其左子节点序号为 `2*i`,右子节点序号为 `2*i+1`)。
|
||||
|
||||
之前介绍树的时候说过,由于完全二叉树的优秀性质,利用数组存储二叉树即节省空间,又方便索引(若根结点的序号为 1,那么对于树中任意节点 i,其左子节点序号为 `2*i`,右子节点序号为 `2*i+1`)。
|
||||
|
||||
为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示:
|
||||
|
||||

|
||||
|
||||
## 堆的操作
|
||||
堆的更新操作主要包括两种 : **插入元素** 和 **删除堆顶元素**。操作过程需要着重掌握和理解。
|
||||
|
||||
堆的更新操作主要包括两种 : **插入元素** 和 **删除堆顶元素**。操作过程需要着重掌握和理解。
|
||||
|
||||
> 在进入正题之前,再重申一遍,堆是一个公平的公司,有能力的人自然会走到与他能力所匹配的位置
|
||||
|
||||
### 插入元素
|
||||
|
||||
> 插入元素,作为一个新入职的员工,初来乍到,这个员工需要从基层做起
|
||||
|
||||
**1.将要插入的元素放到最后**
|
||||
@ -85,20 +91,16 @@ tag:
|
||||
|
||||
> 在堆这个公司中,会出现老大离职的现象,老大离职之后,他的位置就空出来了
|
||||
|
||||
首先删除堆顶元素,使得数组中下标为1的位置空出。
|
||||
|
||||
|
||||
首先删除堆顶元素,使得数组中下标为 1 的位置空出。
|
||||
|
||||

|
||||
|
||||
|
||||
> 那么他的位置由谁来接替呢,当然是他的直接下属了,谁能力强就让谁上呗
|
||||
|
||||
比较根结点的左子节点和右子节点,也就是下标为2,3的数组元素,将较大的元素填充到根结点(下标为1)的位置。
|
||||
比较根结点的左子节点和右子节点,也就是下标为 2,3 的数组元素,将较大的元素填充到根结点(下标为 1)的位置。
|
||||
|
||||

|
||||
|
||||
|
||||
> 这个时候又空出一个位置了,老规矩,谁有能力谁上
|
||||
|
||||
一直循环比较空出位置的左右子节点,并将较大者移至空位,直到堆的最底部
|
||||
@ -108,6 +110,7 @@ tag:
|
||||
这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了“气泡”,这会导致存储空间的浪费。接下来我们试试自顶向下堆化。
|
||||
|
||||
#### 自顶向下堆化
|
||||
|
||||
自顶向下的堆化用一个词形容就是“石沉大海”,那么第一件事情,就是把石头抬起来,从海面扔下去。这个石头就是堆的最后一个元素,我们将最后一个元素移动到堆顶。
|
||||
|
||||

|
||||
@ -118,14 +121,11 @@ tag:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 堆的操作总结
|
||||
|
||||
- **插入元素** :先将元素放至数组末尾,再自底向上堆化,将末尾元素上浮
|
||||
- **删除堆顶元素** :删除堆顶元素,将末尾元素放至堆顶,再自顶向下堆化,将堆顶元素下沉。也可以自底向上堆化,只是会产生“气泡”,浪费存储空间。最好采用自顶向下堆化的方式。
|
||||
|
||||
|
||||
## 堆排序
|
||||
|
||||
堆排序的过程分为两步:
|
||||
@ -137,22 +137,22 @@ tag:
|
||||
|
||||
如果你已经足够了解堆化的过程,那么建堆的过程掌握起来就比较容易了。建堆的过程就是一个对所有非叶节点的自顶向下堆化过程。
|
||||
|
||||
首先要了解哪些是非叶节点,最后一个节点的父结点及它之前的元素,都是非叶节点。也就是说,如果节点个数为n,那么我们需要对n/2到1的节点进行自顶向下(沉底)堆化。
|
||||
首先要了解哪些是非叶节点,最后一个节点的父结点及它之前的元素,都是非叶节点。也就是说,如果节点个数为 n,那么我们需要对 n/2 到 1 的节点进行自顶向下(沉底)堆化。
|
||||
|
||||
具体过程如下图:
|
||||
|
||||

|
||||
|
||||
将初始的无序数组抽象为一棵树,图中的节点个数为6,所以4,5,6节点为叶节点,1,2,3节点为非叶节点,所以要对1-3号节点进行自顶向下(沉底)堆化,注意,顺序是从后往前堆化,从3号节点开始,一直到1号节点。
|
||||
3号节点堆化结果:
|
||||
将初始的无序数组抽象为一棵树,图中的节点个数为 6,所以 4,5,6 节点为叶节点,1,2,3 节点为非叶节点,所以要对 1-3 号节点进行自顶向下(沉底)堆化,注意,顺序是从后往前堆化,从 3 号节点开始,一直到 1 号节点。
|
||||
3 号节点堆化结果:
|
||||
|
||||

|
||||
|
||||
2号节点堆化结果:
|
||||
2 号节点堆化结果:
|
||||
|
||||

|
||||
|
||||
1号节点堆化结果:
|
||||
1 号节点堆化结果:
|
||||
|
||||

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

|
||||
|
||||
@ -48,8 +48,6 @@ tag:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 完全二叉树
|
||||
|
||||
除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则这个二叉树就是 **完全二叉树** 。
|
||||
|
@ -5,8 +5,6 @@ tag:
|
||||
- 计算机网络
|
||||
---
|
||||
|
||||
|
||||
|
||||
## HTTP:超文本传输协议
|
||||
|
||||
**超文本传输协议(HTTP,HyperText Transfer Protocol)** 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
|
||||
@ -112,4 +110,4 @@ DNS(Domain Name System,域名管理系统)基于 UDP 协议,用于解决
|
||||
## 参考
|
||||
|
||||
- 《计算机网络自顶向下方法》(第七版)
|
||||
- RTP 协议介绍:https://mthli.xyz/rtp-introduction/
|
||||
- RTP 协议介绍:https://mthli.xyz/rtp-introduction/
|
||||
|
@ -100,4 +100,4 @@ ARP 的工作原理将分两种场景讨论:
|
||||
|
||||
7. 路由器接口将对 IP 数据报重新封装成链路层帧,目标 MAC 地址为主机 B 的 MAC 地址,单播发送,直到目的地。
|
||||
|
||||

|
||||

|
||||
|
@ -5,12 +5,11 @@ 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.zhihu.com/question/327872966) 。
|
||||
相关问题:[如何评价谢希仁的计算机网络(第七版)? - 知乎](https://www.zhihu.com/question/327872966) 。
|
||||
|
||||
## 1. 计算机网络概述
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: DNS 域名系统详解(应用层)
|
||||
title: DNS 域名系统详解(应用层)
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 计算机网络
|
||||
@ -99,4 +99,4 @@ foo.example.com. A 192.0.2.23
|
||||
|
||||
- DNS 服务器类型:https://www.cloudflare.com/zh-cn/learning/dns/dns-server-types/
|
||||
- DNS Message Resource Record Field Formats:http://www.tcpipguide.com/free/t_DNSMessageResourceRecordFieldFormats-2.htm
|
||||
- Understanding Different Types of Record in DNS Server:https://www.mustbegeek.com/understanding-different-types-of-record-in-dns-server/
|
||||
- Understanding Different Types of Record in DNS Server:https://www.mustbegeek.com/understanding-different-types-of-record-in-dns-server/
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: HTTP 常见状态码总结(应用层)
|
||||
title: HTTP 常见状态码总结(应用层)
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 计算机网络
|
||||
---
|
||||
|
||||
HTTP 状态码用于描述 HTTP 请求的结果,比如2xx 就代表请求被成功处理。
|
||||
HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被成功处理。
|
||||
|
||||

|
||||
|
||||
@ -15,32 +15,32 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如2xx 就代表请求被
|
||||
|
||||
### 2xx Success(成功状态码)
|
||||
|
||||
- **200 OK** :请求被成功处理。比如我们发送一个查询用户数据的HTTP 请求到服务端,服务端正确返回了用户数据。这个是我们平时最常见的一个 HTTP 状态码。
|
||||
- **200 OK** :请求被成功处理。比如我们发送一个查询用户数据的 HTTP 请求到服务端,服务端正确返回了用户数据。这个是我们平时最常见的一个 HTTP 状态码。
|
||||
- **201 Created** :请求被成功处理并且在服务端创建了一个新的资源。比如我们通过 POST 请求创建一个新的用户。
|
||||
- **202 Accepted** :服务端已经接收到了请求,但是还未处理。
|
||||
- **204 No Content** : 服务端已经成功处理了请求,但是没有返回任何内容。
|
||||
- **204 No Content** : 服务端已经成功处理了请求,但是没有返回任何内容。
|
||||
|
||||
这里格外提一下 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
|
||||
> entity-body, and might want to return updated metainformation. The
|
||||
> response MAY include new or updated metainformation in the form of
|
||||
> entity-headers, which if present SHOULD be associated with the
|
||||
> requested variant.
|
||||
> The server has fulfilled the request but does not need to return an
|
||||
> entity-body, and might want to return updated metainformation. The
|
||||
> response MAY include new or updated metainformation in the form of
|
||||
> entity-headers, which if present SHOULD be associated with the
|
||||
> requested variant.
|
||||
>
|
||||
> If the client is a user agent, it SHOULD NOT change its document view
|
||||
> from that which caused the request to be sent. This response is
|
||||
> primarily intended to allow input for actions to take place without
|
||||
> causing a change to the user agent's active document view, although
|
||||
> any new or updated metainformation SHOULD be applied to the document
|
||||
> currently in the user agent's active view.
|
||||
> If the client is a user agent, it SHOULD NOT change its document view
|
||||
> from that which caused the request to be sent. This response is
|
||||
> primarily intended to allow input for actions to take place without
|
||||
> causing a change to the user agent's active document view, although
|
||||
> any new or updated metainformation SHOULD be applied to the document
|
||||
> currently in the user agent's active view.
|
||||
>
|
||||
> The 204 response MUST NOT include a message-body, and thus is always
|
||||
> terminated by the first empty line after the header fields.
|
||||
> The 204 response MUST NOT include a message-body, and thus is always
|
||||
> terminated by the first empty line after the header fields.
|
||||
|
||||
简单来说,204状态码描述的是我们向服务端发送 HTTP 请求之后,只关注处理结果是否成功的场景。也就是说我们需要的就是一个结果:true/false。
|
||||
简单来说,204 状态码描述的是我们向服务端发送 HTTP 请求之后,只关注处理结果是否成功的场景。也就是说我们需要的就是一个结果:true/false。
|
||||
|
||||
举个例子:你要追一个女孩子,你问女孩子:“我能追你吗?”,女孩子回答:“好!”。我们把这个女孩子当做是服务端就很好理解 204 状态码了。
|
||||
|
||||
@ -51,15 +51,15 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如2xx 就代表请求被
|
||||
|
||||
### 4xx Client Error(客户端错误状态码)
|
||||
|
||||
- **400 Bad Request** : 发送的HTTP请求存在问题。比如请求参数不合法、请求方法错误。
|
||||
- **400 Bad Request** : 发送的 HTTP 请求存在问题。比如请求参数不合法、请求方法错误。
|
||||
- **401 Unauthorized** : 未认证却请求需要认证之后才能访问的资源。
|
||||
- **403 Forbidden** :直接拒绝HTTP请求,不处理。一般用来针对非法请求。
|
||||
- **403 Forbidden** :直接拒绝 HTTP 请求,不处理。一般用来针对非法请求。
|
||||
- **404 Not Found** : 你请求的资源未在服务端找到。比如你请求某个用户的信息,服务端并没有找到指定的用户。
|
||||
- **409 Conflict** : 表示请求的资源与服务端当前的状态存在冲突,请求无法被处理。
|
||||
|
||||
### 5xx Server Error(服务端错误状态码)
|
||||
|
||||
- **500 Internal Server Error** : 服务端出问题了(通常是服务端出Bug了)。比如你服务端处理请求的时候突然抛出异常,但是异常并未在服务端被正确处理。
|
||||
- **500 Internal Server Error** : 服务端出问题了(通常是服务端出 Bug 了)。比如你服务端处理请求的时候突然抛出异常,但是异常并未在服务端被正确处理。
|
||||
- **502 Bad Gateway** :我们的网关将请求转发到服务端,但是服务端返回的却是一个错误的响应。
|
||||
|
||||
### 参考
|
||||
@ -68,4 +68,3 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如2xx 就代表请求被
|
||||
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
|
||||
- https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
|
||||
- https://segmentfault.com/a/1190000018264501
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: HTTP vs HTTPS(应用层)
|
||||
title: HTTP vs HTTPS(应用层)
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 计算机网络
|
||||
@ -39,7 +39,7 @@ HTTPS 协议中,SSL 通道通常使用基于密钥的加密算法,密钥长
|
||||
|
||||
保密性好、信任度高。
|
||||
|
||||
## HTTPS 的核心—SSL/TLS协议
|
||||
## HTTPS 的核心—SSL/TLS 协议
|
||||
|
||||
HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。
|
||||
|
||||
@ -61,7 +61,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
|
||||
>
|
||||
> 这样,通信信息就不会被其他人截获了,这依赖于私钥的保密性。
|
||||
|
||||

|
||||

|
||||
|
||||
非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数。
|
||||
|
||||
@ -69,7 +69,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
|
||||
>
|
||||
> 单向陷门函数:一个较弱的单向函数。已知单向陷门函数 f,陷门 h,给定任意一个输入 x,易计算出输出 y=f(x;h);而给定一个输出 y,假设存在 f(x;h)=y,很难根据 f 来计算出 x,但可以根据 f 和 h 来推导出 x。
|
||||
|
||||

|
||||

|
||||
|
||||
上图就是一个单向函数(不是单项陷门函数),假设有一个绝世秘籍,任何知道了这个秘籍的人都可以把苹果汁榨成苹果,那么这个秘籍就是“陷门”了吧。
|
||||
|
||||
@ -81,7 +81,7 @@ SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密
|
||||
|
||||
> 对称加密:通信双方共享唯一密钥 k,加解密算法已知,加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。
|
||||
|
||||

|
||||

|
||||
|
||||
对称加密的密钥生成代价比公私钥对的生成代价低得多,那么有的人会问了,为什么 SSL/TLS 还需要使用非对称加密呢?因为对称加密的保密性完全依赖于密钥的保密性。在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。
|
||||
|
||||
@ -99,7 +99,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
>
|
||||
> 同样的,S 公钥即使做加密,也难以避免这种信任性问题,C 被 AS 拐跑了!
|
||||
|
||||

|
||||

|
||||
|
||||
为了公钥传输的信赖性问题,第三方机构应运而生——证书颁发机构(CA,Certificate Authority)。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的**电子签名**(见下节)。
|
||||
|
||||
@ -117,7 +117,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
>
|
||||
> 客户端对证书数据(包含服务器的公钥)做相同的散列处理,得到摘要,并将该摘要与之前从签名中解码出的摘要做对比,如果相同,则身份验证成功;否则验证失败。
|
||||
|
||||

|
||||

|
||||
|
||||
总结来说,带有证书的公钥传输机制如下:
|
||||
|
||||
@ -127,7 +127,7 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
|
||||
5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。
|
||||
|
||||

|
||||

|
||||
|
||||
对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看[数字签名及数字证书原理](https://www.bilibili.com/video/BV18N411X7ty/)这个视频,这是我看过最清晰的讲解。
|
||||
|
||||
@ -138,6 +138,3 @@ SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐
|
||||
- **端口号** :HTTP 默认是 80,HTTPS 默认是 443。
|
||||
- **URL 前缀** :HTTP 的 URL 前缀是 `http://`,HTTPS 的 URL 前缀是 `https://`。
|
||||
- **安全性和资源消耗** : HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
|
||||
|
||||
|
||||
|
@ -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`的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 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.html,HTTP/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`可以作为指示请求是否会被正常响应,过程如下图:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
然而在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 tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
|
||||
1. **带宽优化及网络连接的使用** :HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial 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)
|
105
docs/cs-basics/network/http1.0-vs-http1.1.md
Normal 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`的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 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.html,HTTP/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`可以作为指示请求是否会被正常响应,过程如下图:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
然而在 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 tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
|
||||
1. **带宽优化及网络连接的使用** :HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial 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)
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -1,13 +1,13 @@
|
||||
---
|
||||
title: 网络攻击常见手段总结
|
||||
title: 网络攻击常见手段总结
|
||||
category: 计算机基础
|
||||
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 欺骗
|
||||
|
||||
@ -153,15 +153,15 @@ HTTP 洪水攻击有两种:
|
||||
|
||||
### 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 的攻击原理是什么?
|
||||
|
||||

|
||||
|
||||
域名系统的功能是将易于记忆的名称(例如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?
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: OSI 和 TCP/IP 网络分层模型详解(基础)
|
||||
title: OSI 和 TCP/IP 网络分层模型详解(基础)
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 计算机网络
|
@ -5,6 +5,8 @@ tag:
|
||||
- 计算机网络
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
上篇主要是计算机网络基础和应用层相关的内容。
|
||||
|
||||
## 计算机网络基础
|
||||
@ -38,7 +40,7 @@ tag:
|
||||
|
||||

|
||||
|
||||
关于每一层作用的详细介绍,请看 [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) 这篇文章。
|
||||
|
||||
#### 为什么网络要分层?
|
||||
|
||||
@ -132,51 +134,51 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
|
||||
|
||||
### HTTP Header 中常见的字段有哪些?
|
||||
|
||||
| 请求头字段名 | 说明 | 示例 |
|
||||
| :------------------ | :----------------------------------------------------------- | :----------------------------------------------------------- |
|
||||
| Accept | 能够接受的回应内容类型(Content-Types)。 | Accept: text/plain |
|
||||
| Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 |
|
||||
| Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT |
|
||||
| Accept-Encoding | 能够接受的编码方式列表。参考 HTTP 压缩。 | Accept-Encoding: gzip, deflate |
|
||||
| Accept-Language | 能够接受的回应内容的自然语言列表。 | Accept-Language: en-US |
|
||||
| Authorization | 用于超文本传输协议的认证的认证信息 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
||||
| Cache-Control | 用来指定在这次的请求/响应链中的所有缓存机制 都必须 遵守的指令 | Cache-Control: no-cache |
|
||||
| Connection | 该浏览器想要优先使用的连接类型 | Connection: keep-alive Connection: Upgrade |
|
||||
| Content-Length | 以 八位字节数组 (8 位的字节)表示的请求体的长度 | Content-Length: 348 |
|
||||
| Content-MD5 | 请求体的内容的二进制 MD5 散列值,以 Base64 编码的结果 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
|
||||
| Content-Type | 请求体的 多媒体类型 (用于 POST 和 PUT 请求中) | Content-Type: application/x-www-form-urlencoded |
|
||||
| Cookie | 之前由服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议 Cookie | Cookie: \$Version=1; Skin=new; |
|
||||
| Date | 发送该消息的日期和时间(按照 RFC 7231 中定义的"超文本传输协议日期"格式来发送) | Date: Tue, 15 Nov 1994 08:12:31 GMT |
|
||||
| Expect | 表明客户端要求服务器做出特定的行为 | Expect: 100-continue |
|
||||
| From | 发起此请求的用户的邮件地址 | From: [user@example.com](mailto:user@example.com) |
|
||||
| Host | 服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。 | Host: en.wikipedia.org:80 |
|
||||
| If-Match | 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Modified-Since | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
|
||||
| If-None-Match | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Range | 如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体 | If-Range: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Unmodified-Since | 仅当该实体自某个特定时间已来未被修改的情况下,才发送回应。 | If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
|
||||
| Max-Forwards | 限制该消息可被代理及网关转发的次数。 | Max-Forwards: 10 |
|
||||
| Origin | 发起一个针对 跨来源资源共享 的请求。 | Origin: [http://www.example-social-network.com](http://www.example-social-network.com/) |
|
||||
| Pragma | 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 | Pragma: no-cache |
|
||||
| Proxy-Authorization | 用来向代理进行认证的认证信息。 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
||||
| Range | 仅请求某个实体的一部分。字节偏移以 0 开始。参见字节服务。 | Range: bytes=500-999 |
|
||||
| Referer | 表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。 | Referer: [http://en.wikipedia.org/wiki/Main_Page](https://en.wikipedia.org/wiki/Main_Page) |
|
||||
| TE | 浏览器预期接受的传输编码方式:可使用回应协议头 Transfer-Encoding 字段中的值; | TE: trailers, deflate |
|
||||
| Upgrade | 要求服务器升级到另一个协议。 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
|
||||
| User-Agent | 浏览器的浏览器身份标识字符串 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0 |
|
||||
| Via | 向服务器告知,这个请求是由哪些代理发出的。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
|
||||
| Warning | 一个一般性的警告,告知,在实体内容体中可能存在错误。 | Warning: 199 Miscellaneous warning |
|
||||
| 请求头字段名 | 说明 | 示例 |
|
||||
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------- |
|
||||
| Accept | 能够接受的回应内容类型(Content-Types)。 | Accept: text/plain |
|
||||
| Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 |
|
||||
| Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT |
|
||||
| Accept-Encoding | 能够接受的编码方式列表。参考 HTTP 压缩。 | Accept-Encoding: gzip, deflate |
|
||||
| Accept-Language | 能够接受的回应内容的自然语言列表。 | Accept-Language: en-US |
|
||||
| Authorization | 用于超文本传输协议的认证的认证信息 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
||||
| Cache-Control | 用来指定在这次的请求/响应链中的所有缓存机制 都必须 遵守的指令 | Cache-Control: no-cache |
|
||||
| Connection | 该浏览器想要优先使用的连接类型 | Connection: keep-alive Connection: Upgrade |
|
||||
| Content-Length | 以 八位字节数组 (8 位的字节)表示的请求体的长度 | Content-Length: 348 |
|
||||
| Content-MD5 | 请求体的内容的二进制 MD5 散列值,以 Base64 编码的结果 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
|
||||
| Content-Type | 请求体的 多媒体类型 (用于 POST 和 PUT 请求中) | Content-Type: application/x-www-form-urlencoded |
|
||||
| Cookie | 之前由服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议 Cookie | Cookie: \$Version=1; Skin=new; |
|
||||
| Date | 发送该消息的日期和时间(按照 RFC 7231 中定义的"超文本传输协议日期"格式来发送) | Date: Tue, 15 Nov 1994 08:12:31 GMT |
|
||||
| Expect | 表明客户端要求服务器做出特定的行为 | Expect: 100-continue |
|
||||
| From | 发起此请求的用户的邮件地址 | From: [user@example.com](mailto:user@example.com) |
|
||||
| Host | 服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。 | Host: en.wikipedia.org:80 |
|
||||
| If-Match | 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Modified-Since | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
|
||||
| If-None-Match | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Range | 如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体 | If-Range: “737060cd8c284d8af7ad3082f209582d” |
|
||||
| If-Unmodified-Since | 仅当该实体自某个特定时间已来未被修改的情况下,才发送回应。 | If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
|
||||
| Max-Forwards | 限制该消息可被代理及网关转发的次数。 | Max-Forwards: 10 |
|
||||
| Origin | 发起一个针对 跨来源资源共享 的请求。 | Origin: [http://www.example-social-network.com](http://www.example-social-network.com/) |
|
||||
| Pragma | 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 | Pragma: no-cache |
|
||||
| Proxy-Authorization | 用来向代理进行认证的认证信息。 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
||||
| Range | 仅请求某个实体的一部分。字节偏移以 0 开始。参见字节服务。 | Range: bytes=500-999 |
|
||||
| Referer | 表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。 | Referer: [http://en.wikipedia.org/wiki/Main_Page](https://en.wikipedia.org/wiki/Main_Page) |
|
||||
| TE | 浏览器预期接受的传输编码方式:可使用回应协议头 Transfer-Encoding 字段中的值; | TE: trailers, deflate |
|
||||
| Upgrade | 要求服务器升级到另一个协议。 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
|
||||
| User-Agent | 浏览器的浏览器身份标识字符串 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0 |
|
||||
| Via | 向服务器告知,这个请求是由哪些代理发出的。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
|
||||
| Warning | 一个一般性的警告,告知,在实体内容体中可能存在错误。 | Warning: 199 Miscellaneous warning |
|
||||
|
||||
### HTTP 和 HTTPS 有什么区别?(重要)
|
||||
|
||||

|
||||

|
||||
|
||||
- **端口号** :HTTP 默认是 80,HTTPS 默认是 443。
|
||||
- **URL 前缀** :HTTP 的 URL 前缀是 `http://`,HTTPS 的 URL 前缀是 `https://`。
|
||||
- **安全性和资源消耗** : HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
|
||||
- **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 有什么区别?
|
||||
|
||||
@ -188,7 +190,7 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
|
||||
- **带宽** :HTTP/1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
|
||||
- **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 有什么区别?
|
||||
|
||||
|
@ -96,21 +96,19 @@ tag:
|
||||
|
||||
每个连入互联网的设备或域(如计算机、服务器、路由器等)都被分配一个 **IP 地址(Internet Protocol address)**,作为唯一标识符。每个 IP 地址都是一个字符序列,如 192.168.1.1(IPv4)、2001:0db8:85a3:0000:0000:8a2e:0370:7334(IPv6) 。
|
||||
|
||||
当网络设备发送IP数据包时,数据包中包含了 **源IP地址** 和 **目的IP地址** 。源IP地址用于标识数据包的发送方设备或域,而目的IP地址则用于标识数据包的接收方设备或域。这类似于一封邮件中同时包含了目的地地址和回邮地址。
|
||||
当网络设备发送 IP 数据包时,数据包中包含了 **源 IP 地址** 和 **目的 IP 地址** 。源 IP 地址用于标识数据包的发送方设备或域,而目的 IP 地址则用于标识数据包的接收方设备或域。这类似于一封邮件中同时包含了目的地地址和回邮地址。
|
||||
|
||||
网络设备根据目的IP地址来判断数据包的目的地,并将数据包转发到正确的目的地网络或子网络,从而实现了设备间的通信。
|
||||
网络设备根据目的 IP 地址来判断数据包的目的地,并将数据包转发到正确的目的地网络或子网络,从而实现了设备间的通信。
|
||||
|
||||
这种基于IP地址的寻址方式是互联网通信的基础,它允许数据包在不同的网络之间传递,从而实现了全球范围内的网络互联互通。IP地址的唯一性和全局性保证了网络中的每个设备都可以通过其独特的IP地址进行标识和寻址。
|
||||
这种基于 IP 地址的寻址方式是互联网通信的基础,它允许数据包在不同的网络之间传递,从而实现了全球范围内的网络互联互通。IP 地址的唯一性和全局性保证了网络中的每个设备都可以通过其独特的 IP 地址进行标识和寻址。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 什么是 IP 地址过滤?
|
||||
|
||||
**IP 地址过滤(IP Address Filtering)** 简单来说就是限制或阻止特定IP地址或IP地址范围的访问。例如,你有一个图片服务突然被某一个 IP 地址攻击,那我们就可以禁止这个 IP 地址访问图片服务。
|
||||
**IP 地址过滤(IP Address Filtering)** 简单来说就是限制或阻止特定 IP 地址或 IP 地址范围的访问。例如,你有一个图片服务突然被某一个 IP 地址攻击,那我们就可以禁止这个 IP 地址访问图片服务。
|
||||
|
||||
IP地址过滤是一种简单的网络安全措施,实际应用中一般会结合其他网络安全措施,如认证、授权、加密等一起使用。单独使用 IP地址过滤并不能完全保证网络的安全。
|
||||
IP 地址过滤是一种简单的网络安全措施,实际应用中一般会结合其他网络安全措施,如认证、授权、加密等一起使用。单独使用 IP 地址过滤并不能完全保证网络的安全。
|
||||
|
||||
### IPv4 和 IPv6 有什么区别?
|
||||
|
||||
@ -174,4 +172,4 @@ ARP 协议,全称 **地址解析协议(Address Resolution Protocol)**,
|
||||
- 《图解 HTTP》
|
||||
- 《计算机网络自顶向下方法》(第七版)
|
||||
- 什么是 Internet 协议(IP)?:https://www.cloudflare.com/zh-cn/learning/network-layer/internet-protocol/
|
||||
- What Is NAT and What Are the Benefits of NAT Firewalls?:https://community.fs.com/blog/what-is-nat-and-what-are-the-benefits-of-nat-firewalls.html
|
||||
- What Is NAT and What Are the Benefits of NAT Firewalls?:https://community.fs.com/blog/what-is-nat-and-what-are-the-benefits-of-nat-firewalls.html
|
||||
|
@ -5,40 +5,39 @@ tag:
|
||||
- 计算机网络
|
||||
---
|
||||
|
||||
|
||||
为了准确无误地把数据送达目标处,TCP 协议采用了三次握手策略。
|
||||
|
||||
## 建立连接-TCP 三次握手
|
||||
## 建立连接-TCP 三次握手
|
||||
|
||||

|
||||
|
||||
建立一个 TCP 连接需要“三次握手”,缺一不可 :
|
||||
|
||||
|
||||
- **一次握手**:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 **SYN_SEND** 状态,等待服务器的确认;
|
||||
- **二次握手**:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 **SYN_RECV** 状态
|
||||
- **三次握手**:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入**ESTABLISHED** 状态,完成TCP三次握手。
|
||||
- **三次握手**:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入**ESTABLISHED** 状态,完成 TCP 三次握手。
|
||||
|
||||
**当建立了 3 次握手之后,客户端和服务端就可以传输数据啦!**
|
||||
|
||||
### 为什么要三次握手?
|
||||
### 为什么要三次握手?
|
||||
|
||||
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
|
||||
|
||||
1. **第一次握手** :Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
|
||||
2. **第二次握手** :Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常
|
||||
3. **第三次握手** :Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
|
||||
|
||||
三次握手就能确认双方收发功能都正常,缺一不可。
|
||||
|
||||
更详细的解答可以看这个:[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 则是为了建立并确认从服务端到客户端的通信。
|
||||
|
||||
> SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement)消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
|
||||
|
||||
## 断开连接-TCP 四次挥手
|
||||
## 断开连接-TCP 四次挥手
|
||||
|
||||

|
||||
|
||||
@ -51,9 +50,9 @@ tag:
|
||||
|
||||
**只要四次挥手没有结束,客户端和服务端就可以继续传输数据!**
|
||||
|
||||
### 为什么要四次挥手?
|
||||
### 为什么要四次挥手?
|
||||
|
||||
TCP是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
|
||||
TCP 是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
|
||||
|
||||
举个例子:A 和 B 打电话,通话即将结束后。
|
||||
|
||||
@ -62,30 +61,24 @@ TCP是全双工通信,可以双向传输数据。任何一方都可以在数
|
||||
3. **第三次挥手** :于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”
|
||||
4. **第四次挥手** :A 回答“知道了”,这样通话才算结束。
|
||||
|
||||
### 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
|
||||
|
||||
### 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
|
||||
|
||||
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK,表示接收到了断开连接的请求。等到数据发完之后再发 FIN,断开服务器到客户端的数据传送。
|
||||
|
||||
### 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
|
||||
|
||||
### 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
|
||||
|
||||
客户端没有收到 ACK 确认,会重新发送 FIN 请求。
|
||||
|
||||
### 为什么第四次挥手客户端需要等待 2\*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?
|
||||
|
||||
### 为什么第四次挥手客户端需要等待 2\*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?
|
||||
|
||||
第四次挥手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端在 2\*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN。
|
||||
|
||||
> **MSL(Maximum Segment Lifetime)** : 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接。
|
||||
|
||||
## 参考
|
||||
|
||||
## 参考
|
||||
|
||||
- 《计算机网络(第 7 版)》
|
||||
|
||||
- 《图解 HTTP》
|
||||
|
||||
- TCP and UDP Tutorial:https://www.9tut.com/tcp-and-udp-tutorial
|
||||
|
||||
|
||||
|
@ -5,16 +5,16 @@ tag:
|
||||
- 计算机网络
|
||||
---
|
||||
|
||||
## TCP 如何保证传输的可靠性?
|
||||
## TCP 如何保证传输的可靠性?
|
||||
|
||||
1. **基于数据块传输** :应用数据被分割成 TCP 认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段。
|
||||
2. **对失序数据包重新排序以及去重**: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 利用滑动窗口实现流量控制)。
|
||||
6. **拥塞控制** : 当网络拥塞时,减少数据的发送。
|
||||
|
||||
## TCP 如何实现流量控制?
|
||||
## TCP 如何实现流量控制?
|
||||
|
||||
**TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。** 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。
|
||||
|
||||
@ -25,16 +25,16 @@ tag:
|
||||
- 发送端不等同于客户端
|
||||
- 接收端不等同于服务端
|
||||
|
||||
TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客户端和服务端既可能是发送端又可能是服务端。因此,两端各有一个发送缓冲区与接收缓冲区,两端都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。通信双方的发送窗口和接收窗口的要求相同
|
||||
TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客户端和服务端既可能是发送端又可能是服务端。因此,两端各有一个发送缓冲区与接收缓冲区,两端都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制(TCP 传输速率不能大于应用的数据处理速率)。通信双方的发送窗口和接收窗口的要求相同
|
||||
|
||||
**TCP 发送窗口可以划分成四个部分** :
|
||||
|
||||
1. 已经发送并且确认的TCP段(已经发送并确认);
|
||||
2. 已经发送但是没有确认的TCP段(已经发送未确认);
|
||||
3. 未发送但是接收方准备接收的TCP段(可以发送);
|
||||
4. 未发送并且接收方也并未准备接受的TCP段(不可发送)。
|
||||
1. 已经发送并且确认的 TCP 段(已经发送并确认);
|
||||
2. 已经发送但是没有确认的 TCP 段(已经发送未确认);
|
||||
3. 未发送但是接收方准备接收的 TCP 段(可以发送);
|
||||
4. 未发送并且接收方也并未准备接受的 TCP 段(不可发送)。
|
||||
|
||||
**TCP发送窗口结构图示** :
|
||||
**TCP 发送窗口结构图示** :
|
||||
|
||||

|
||||
|
||||
@ -42,13 +42,13 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
|
||||
- **SND.UNA**:Send Unacknowledged 指针,指向发送窗口的第一个字节。
|
||||
- **SND.NXT**:Send Next 指针,指向可用窗口的第一个字节。
|
||||
|
||||
**可用窗口大小** = `SND.UNA + SND.WND - SND.NXT` 。
|
||||
**可用窗口大小** = `SND.UNA + SND.WND - SND.NXT` 。
|
||||
|
||||
**TCP 接收窗口可以划分成三个部分** :
|
||||
|
||||
1. 已经接收并且已经确认的 TCP 段(已经接收并确认);
|
||||
2. 等待接收且允许发送方发送 TCP 段(可以接收未确认);
|
||||
3. 不可接收且不允许发送方发送TCP段(不可接收)。
|
||||
3. 不可接收且不允许发送方发送 TCP 段(不可接收)。
|
||||
|
||||
**TCP 接收窗口结构图示** :
|
||||
|
||||
@ -58,8 +58,7 @@ TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客
|
||||
|
||||
另外,这里的滑动窗口大小只是为了演示使用,实际窗口大小通常会远远大于这个值。
|
||||
|
||||
## TCP 的拥塞控制是怎么实现的?
|
||||
|
||||
## TCP 的拥塞控制是怎么实现的?
|
||||
|
||||
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
|
||||
|
||||
@ -73,13 +72,13 @@ TCP 的拥塞控制采用了四种算法,即 **慢开始** 、 **拥塞避免*
|
||||
- **拥塞避免:** 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送方的 cwnd 加 1.
|
||||
- **快重传与快恢复:** 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
|
||||
|
||||
## ARQ 协议了解吗?
|
||||
## ARQ 协议了解吗?
|
||||
|
||||
**自动重传请求**(Automatic Repeat-reQuest,ARQ)是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认信息(Acknowledgements,就是我们常说的 ACK),它通常会重新发送,直到收到确认或者重试超过一定的次数。
|
||||
|
||||
ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
|
||||
|
||||
### 停止等待 ARQ 协议
|
||||
### 停止等待 ARQ 协议
|
||||
|
||||
停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认(回复 ACK)。如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组;
|
||||
|
||||
@ -98,8 +97,7 @@ ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
|
||||
- **确认丢失** :确认消息在传输过程丢失。当 A 发送 M1 消息,B 收到后,B 向 A 发送了一个 M1 确认消息,但却在传输过程中丢失。而 A 并不知道,在超时计时过后,A 重传 M1 消息,B 再次收到该消息后采取以下两点措施:1. 丢弃这个重复的 M1 消息,不向上层交付。 2. 向 A 发送确认消息。(不会认为已经发送过了,就不再发送。A 能重传,就证明 B 的确认消息丢失)。
|
||||
- **确认迟到** :确认消息在传输过程中迟到。A 发送 M1 消息,B 收到并发送确认。在超时时间内没有收到确认消息,A 重传 M1 消息,B 仍然收到并继续发送确认消息(B 收到了 2 份 M1)。此时 A 收到了 B 第二次发送的确认消息。接着发送其他数据。过了一会,A 收到了 B 第一次发送的对 M1 的确认消息(A 也收到了 2 份确认消息)。处理如下:1. A 收到重复的确认后,直接丢弃。2. B 收到重复的 M1 后,也直接丢弃重复的 M1。
|
||||
|
||||
### 连续 ARQ 协议
|
||||
|
||||
### 连续 ARQ 协议
|
||||
|
||||
连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。
|
||||
|
||||
@ -107,13 +105,12 @@ ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
|
||||
|
||||
**缺点:** 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息,中间第三条丢失(3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。
|
||||
|
||||
## Reference
|
||||
|
||||
## Reference
|
||||
|
||||
1. 《计算机网络(第 7 版)》
|
||||
2. 《图解 HTTP》
|
||||
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 )
|
||||
5. TCP Flow Control—[https://www.brianstorti.com/tcp-flow-control/](https://www.brianstorti.com/tcp-flow-control/ )
|
||||
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)
|
||||
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
|
||||
7. TCP之滑动窗口原理 : https://cloud.tencent.com/developer/article/1857363
|
||||
7. TCP 之滑动窗口原理 : https://cloud.tencent.com/developer/article/1857363
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Linux 基础知识总结
|
||||
title: Linux 基础知识总结
|
||||
category: 计算机基础
|
||||
tag:
|
||||
- 操作系统
|
||||
@ -339,7 +339,7 @@ Linux 系统是一个多用户多任务的分时操作系统,任何一个要
|
||||
- `top [选项]`:用于实时查看系统的 CPU 使用率、内存使用率、进程信息等。
|
||||
- `htop [选项]`:类似于 `top`,但提供了更加交互式和友好的界面,可让用户交互式操作,支持颜色主题,可横向或纵向滚动浏览进程列表,并支持鼠标操作。
|
||||
- `uptime [选项]`:用于查看系统总共运行了多长时间、系统的平均负载等信息。
|
||||
- `vmstat [间隔时间] [重复次数]` :vmstat (Virtual Memory Statistics) 的含义为显示虚拟内存状态,但是它可以报告关于进程、内存、I/O等系统整体运行状态。
|
||||
- `vmstat [间隔时间] [重复次数]` :vmstat (Virtual Memory Statistics) 的含义为显示虚拟内存状态,但是它可以报告关于进程、内存、I/O 等系统整体运行状态。
|
||||
- `free [选项]`:用于查看系统的内存使用情况,包括已用内存、可用内存、缓冲区和缓存等。
|
||||
- `df [选项] [文件系统]`:用于查看系统的磁盘空间使用情况,包括磁盘空间的总量、已使用量和可用量等,可以指定文件系统上。例如:`df -a`,查看全部文件系统。
|
||||
- `du [选项] [文件]`:用于查看指定目录或文件的磁盘空间使用情况,可以指定不同的选项来控制输出格式和单位。
|
||||
|
@ -12,6 +12,8 @@ head:
|
||||
content: 很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如进程管理、内存管理、虚拟内存等等。
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如 **用户态和内核态、系统调用、进程和线程、死锁、内存管理、虚拟内存、文件系统**等等。
|
||||
|
||||
这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。
|
||||
@ -45,8 +47,6 @@ head:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 操作系统主要有哪些功能?
|
||||
|
||||
从资源管理的角度来看,操作系统有 6 大功能:
|
||||
|
@ -408,4 +408,4 @@ LRU 算法是实际使用中应用的比较多,也被认为是最接近 OPT
|
||||
- 内存管理之伙伴系统与 SLAB:https://blog.csdn.net/qq_44272681/article/details/124199068
|
||||
- 为什么 Linux 需要虚拟内存:https://draveness.me/whys-the-design-os-virtual-memory/
|
||||
- 程序员的自我修养(七):内存缺页错误:https://liam.page/2017/09/01/page-fault/
|
||||
- 虚拟内存的那点事儿:https://juejin.cn/post/6844903507594575886
|
||||
- 虚拟内存的那点事儿:https://juejin.cn/post/6844903507594575886
|
||||
|
@ -115,7 +115,7 @@ ER 图由下面 3 个要素组成:
|
||||
- `truncate` (清空数据) : `truncate table 表名` ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。
|
||||
- `delete`(删除数据) : `delete from 表名 where 列名=值`,删除某一行的数据,如果不加 `where` 子句和`truncate table 表名`作用类似。
|
||||
|
||||
`truncate` 和不带 where``子句的 `delete`、以及 `drop` 都会删除表内的数据,但是 **`truncate` 和 `delete` 只删除数据不删除表的结构(定义),执行 `drop` 语句,此表的结构也会删除,也就是执行 `drop` 之后对应的表不复存在。**
|
||||
`truncate` 和不带 `where`子句的 `delete`、以及 `drop` 都会删除表内的数据,但是 **`truncate` 和 `delete` 只删除数据不删除表的结构(定义),执行 `drop` 语句,此表的结构也会删除,也就是执行`drop` 之后对应的表不复存在。**
|
||||
|
||||
### 属于不同的数据库语言
|
||||
|
||||
|
@ -5,10 +5,9 @@ tag:
|
||||
- 数据库基础
|
||||
---
|
||||
|
||||
|
||||
MySQL 字符编码集中有两套 UTF-8 编码实现:**`utf8`** 和 **`utf8mb4`**。
|
||||
|
||||
如果使用 **`utf8`** 的话,存储emoji 符号和一些比较复杂的汉字、繁体字就会出错。
|
||||
如果使用 **`utf8`** 的话,存储 emoji 符号和一些比较复杂的汉字、繁体字就会出错。
|
||||
|
||||
为什么会这样呢?这篇文章可以从源头给你解答。
|
||||
|
||||
@ -65,7 +64,7 @@ GB18030 完全兼容 GB2312 和 GBK 字符集,纳入中国国内少数民族
|
||||
|
||||
BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
|
||||
|
||||
### Unicode & UTF-8编码
|
||||
### Unicode & UTF-8 编码
|
||||
|
||||
为了更加适合本国语言,诞生了很多种字符集。
|
||||
|
||||
@ -73,7 +72,7 @@ BIG5 主要针对的是繁体中文,收录了 13000 多个汉字。
|
||||
|
||||
就比如说你使用 UTF-8 编码方式打开 GB2312 编码格式的文件就会出现乱码。示例:“牛”这个汉字 GB2312 编码后的十六进制数值为 “C5A3”,而 “C5A3” 用 UTF-8 解码之后得到的却是 “ţ”。
|
||||
|
||||
你可以通过这个网站在线进行编码和解码:https://www.haomeili.net/HanZi/ZiFuBianMaZhuanHuan
|
||||
你可以通过这个网站在线进行编码和解码:<https://www.haomeili.net/HanZi/ZiFuBianMaZhuanHuan>
|
||||
|
||||

|
||||
|
||||
@ -140,7 +139,7 @@ CREATE TABLE `user` (
|
||||
```sql
|
||||
INSERT INTO `user` (`id`, `name`, `phone`, `password`)
|
||||
VALUES
|
||||
('A00003', 'guide哥😘😘😘', '181631312312', '123456');
|
||||
('A00003', 'guide哥😘😘😘', '181631312312', '123456');
|
||||
|
||||
```
|
||||
|
||||
@ -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
|
||||
- 十分钟搞清字符集和字符编码:http://cenalulu.github.io/linux/character-encoding/
|
||||
- Unicode-维基百科:https://zh.wikipedia.org/wiki/Unicode
|
||||
- GB2312-维基百科:https://zh.wikipedia.org/wiki/GB_2312
|
||||
- UTF-8-维基百科:https://zh.wikipedia.org/wiki/UTF-8
|
||||
- GB18030-维基百科: https://zh.wikipedia.org/wiki/GB_18030
|
||||
- 字符集和字符编码(Charset & Encoding): <https://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html>
|
||||
- 十分钟搞清字符集和字符编码:<http://cenalulu.github.io/linux/character-encoding/>
|
||||
- Unicode-维基百科:<https://zh.wikipedia.org/wiki/Unicode>
|
||||
- GB2312-维基百科:<https://zh.wikipedia.org/wiki/GB_2312>
|
||||
- UTF-8-维基百科:<https://zh.wikipedia.org/wiki/UTF-8>
|
||||
- GB18030-维基百科: <https://zh.wikipedia.org/wiki/GB_18030>
|
||||
|
@ -10,46 +10,4 @@ tag:
|
||||
|
||||

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

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
为了帮助更多同学准备 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>
|
||||
<!-- @include: @planet.snippet.md -->
|
@ -28,15 +28,15 @@ MongoDB 的存储结构区别于传统的关系型数据库,主要由如下三
|
||||
|
||||
**SQL 与 MongoDB 常见术语对比** :
|
||||
|
||||
| SQL | MongoDB |
|
||||
| ----------------------- | ------------------------------ |
|
||||
| 表(Table) | 集合(Collection) |
|
||||
| 行(Row) | 文档(Document) |
|
||||
| 列(Col) | 字段(Field) |
|
||||
| 主键(Primary Key) | 对象 ID(Objectid) |
|
||||
| 索引(Index) | 索引(Index) |
|
||||
| SQL | MongoDB |
|
||||
| ------------------------ | ------------------------------- |
|
||||
| 表(Table) | 集合(Collection) |
|
||||
| 行(Row) | 文档(Document) |
|
||||
| 列(Col) | 字段(Field) |
|
||||
| 主键(Primary Key) | 对象 ID(Objectid) |
|
||||
| 索引(Index) | 索引(Index) |
|
||||
| 嵌套表(Embedded Table) | 嵌入式文档(Embedded Document) |
|
||||
| 数组(Array) | 数组(Array) |
|
||||
| 数组(Array) | 数组(Array) |
|
||||
|
||||
#### 文档
|
||||
|
||||
@ -126,7 +126,7 @@ MongoDB 预留了几个特殊的数据库。
|
||||
|
||||
与 MySQL 一样,MongoDB 采用的也是 **插件式的存储引擎架构** ,支持不同类型的存储引擎,不同的存储引擎解决不同场景的问题。在创建数据库或集合时,可以指定存储引擎。
|
||||
|
||||
> 插件式的存储引擎架构可以实现 Server 层和存储引擎层的解耦,可以支持多种存储引擎,如MySQL既可以支持B-Tree结构的InnoDB存储引擎,还可以支持LSM结构的RocksDB存储引擎。
|
||||
> 插件式的存储引擎架构可以实现 Server 层和存储引擎层的解耦,可以支持多种存储引擎,如 MySQL 既可以支持 B-Tree 结构的 InnoDB 存储引擎,还可以支持 LSM 结构的 RocksDB 存储引擎。
|
||||
|
||||
在存储引擎刚出来的时候,默认是使用 MMAPV1 存储引擎,MongoDB4.x 版本不再支持 MMAPv1 存储引擎。
|
||||
|
||||
@ -141,13 +141,13 @@ 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 还支持 [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)。
|
||||
|
||||
@ -155,13 +155,13 @@ WiredTiger maintains a table's data in memory using a data structure called a B-
|
||||
|
||||
- **root page(根节点)** : B+ 树的根节点。
|
||||
- **internal page(内部节点)** :不实际存储数据的中间索引节点。
|
||||
- **leaf page(叶子节点)**:真正存储数据的叶子节点,包含一个页头(page header)、块头(block header)和真正的数据(key/value),其中页头定义了页的类型、页中实际载荷数据的大小、页中记录条数等信息;块头定义了此页的checksum、块在磁盘上的寻址位置等信息。
|
||||
- **leaf page(叶子节点)**:真正存储数据的叶子节点,包含一个页头(page header)、块头(block header)和真正的数据(key/value),其中页头定义了页的类型、页中实际载荷数据的大小、页中记录条数等信息;块头定义了此页的 checksum、块在磁盘上的寻址位置等信息。
|
||||
|
||||
其整体结构如下图所示:
|
||||
|
||||

|
||||
|
||||
如果想要深入研究学习 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 聚合
|
||||
|
||||
@ -196,17 +196,17 @@ MongoDB 聚合管道由多个阶段组成,每个阶段在文档通过管道时
|
||||
|
||||
**常用阶段操作符** :
|
||||
|
||||
| 操作符 | 简述 |
|
||||
| --------- | ------------------------------------------------------------ |
|
||||
| \$match | 匹配操作符,用于对文档集合进行筛选 |
|
||||
| 操作符 | 简述 |
|
||||
| --------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| \$match | 匹配操作符,用于对文档集合进行筛选 |
|
||||
| \$project | 投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段 |
|
||||
| \$sort | 排序操作符,用于根据一个或多个字段对文档进行排序 |
|
||||
| \$limit | 限制操作符,用于限制返回文档的数量 |
|
||||
| \$skip | 跳过操作符,用于跳过指定数量的文档 |
|
||||
| \$count | 统计操作符,用于统计文档的数量 |
|
||||
| \$group | 分组操作符,用于对文档集合进行分组 |
|
||||
| \$unwind | 拆分操作符,用于将数组中的每一个值拆分为单独的文档 |
|
||||
| \$lookup | 连接操作符,用于连接同一个数据库中另一个集合,并获取指定的文档,类似于 populate |
|
||||
| \$sort | 排序操作符,用于根据一个或多个字段对文档进行排序 |
|
||||
| \$limit | 限制操作符,用于限制返回文档的数量 |
|
||||
| \$skip | 跳过操作符,用于跳过指定数量的文档 |
|
||||
| \$count | 统计操作符,用于统计文档的数量 |
|
||||
| \$group | 分组操作符,用于对文档集合进行分组 |
|
||||
| \$unwind | 拆分操作符,用于将数组中的每一个值拆分为单独的文档 |
|
||||
| \$lookup | 连接操作符,用于连接同一个数据库中另一个集合,并获取指定的文档,类似于 populate |
|
||||
|
||||
更多操作符介绍详见官方文档:https://docs.mongodb.com/manual/reference/operator/aggregation/
|
||||
|
||||
@ -246,7 +246,7 @@ db.orders.aggregate([
|
||||
- **隔离性**(`Isolation`): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的。WiredTiger 存储引擎支持读未提交( read-uncommitted )、读已提交( read-committed )和快照( snapshot )隔离,MongoDB 启动时默认选快照隔离。在不同隔离级别下,一个事务的生命周期内,可能出现脏读、不可重复读、幻读等现象。
|
||||
- **持久性**(`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 引入了 **分布式事务** ,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
|
||||
|
||||
@ -258,8 +258,8 @@ MongoDB 单文档原生支持原子性,也具备事务的特性。当谈论 Mo
|
||||
|
||||
**注意** :
|
||||
|
||||
- 从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 开始,多文档事务支持副本集和分片集群,其中:主节点使用 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 数据压缩
|
||||
|
||||
@ -281,4 +281,4 @@ WiredTiger 日志也会被压缩,默认使用的也是 Snappy 压缩算法。
|
||||
- 技术干货| MongoDB 事务原理 - MongoDB 中文社区:https://mongoing.com/archives/82187
|
||||
- Transactions - MongoDB 官方文档:https://www.mongodb.com/docs/manual/core/transactions/
|
||||
- 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
|
||||
|
@ -166,7 +166,7 @@ MongoDB 的分片集群由如下三个部分组成(下图来源于[官方文
|
||||
|
||||
- **Config Servers**:配置服务器,本质上是一个 MongoDB 的副本集,负责存储集群的各种元数据和配置,如分片地址、Chunks 等
|
||||
- **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)):
|
||||
|
||||
- **取值基数** 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如:选择年龄做一个基数,范围最多只有100个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk,从而无法迁移,导致数据分布不均匀,性能瓶颈。
|
||||
- **取值基数** 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如:选择年龄做一个基数,范围最多只有 100 个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk,从而无法迁移,导致数据分布不均匀,性能瓶颈。
|
||||
- **取值分布** 取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
|
||||
- **查询带分片** 查询时建议带上分片,使用分片键进行条件查询时,mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。
|
||||
- **避免单调递增或递减** 单调递增的 sharding key,数据文件挪动小,但写入会集中,导致最后一篇的数据量持续增大,不断发生迁移,递减同理。
|
||||
|
||||
综上,在选择片键时要考虑以上4个条件,尽可能满足更多的条件,才能降低 MoveChunks 对性能的影响,从而获得最优的性能体验。
|
||||
综上,在选择片键时要考虑以上 4 个条件,尽可能满足更多的条件,才能降低 MoveChunks 对性能的影响,从而获得最优的性能体验。
|
||||
|
||||
#### 分片策略有哪些?
|
||||
|
||||
@ -270,4 +270,4 @@ Rebalance 操作是比较耗费系统资源的,我们可以通过在业务低
|
||||
- MongoDB - 索引: https://www.cnblogs.com/Neeo/articles/14325130.html
|
||||
- Sharding - MongoDB 官方文档:https://www.mongodb.com/docs/manual/sharding/
|
||||
- MongoDB 分片集群介绍 - 阿里云文档:https://help.aliyun.com/document_detail/64561.html
|
||||
- 分片集群使用注意事项 - - 腾讯云文档:https://cloud.tencent.com/document/product/240/44611
|
||||
- 分片集群使用注意事项 - - 腾讯云文档:https://cloud.tencent.com/document/product/240/44611
|
||||
|
@ -50,7 +50,7 @@ tag:
|
||||
同时删除该数据库相关的目录及其目录内容
|
||||
```
|
||||
|
||||
### 表的操作
|
||||
### 表的操作
|
||||
|
||||
```sql
|
||||
/* 表的操作 */
|
||||
@ -353,7 +353,7 @@ set(val1, val2, val3...)
|
||||
将一个实体信息的数据放在一个表内实现。
|
||||
```
|
||||
|
||||
### SELECT
|
||||
### SELECT
|
||||
|
||||
```sql
|
||||
/* SELECT */ ------------------
|
||||
@ -418,7 +418,7 @@ h. DISTINCT, ALL 选项
|
||||
默认为 all, 全部记录
|
||||
```
|
||||
|
||||
### UNION
|
||||
### UNION
|
||||
|
||||
```sql
|
||||
/* UNION */ ------------------
|
||||
@ -494,7 +494,7 @@ h. DISTINCT, ALL 选项
|
||||
select info.id, info.name, info.stu_num, extra_info.hobby, extra_info.sex from info, extra_info where info.stu_num = extra_info.stu_id;
|
||||
```
|
||||
|
||||
### TRUNCATE
|
||||
### TRUNCATE
|
||||
|
||||
```sql
|
||||
/* TRUNCATE */ ------------------
|
||||
@ -568,7 +568,7 @@ CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name
|
||||
UNDEFINED 未定义(默认),指的是MySQL自主去选择相应的算法。
|
||||
```
|
||||
|
||||
### 事务(transaction)
|
||||
### 事务(transaction)
|
||||
|
||||
```sql
|
||||
事务是指逻辑上的一组操作,组成这组操作的各个单元,要不全成功要不全失败。
|
||||
@ -684,7 +684,7 @@ end
|
||||
3. Replace 语法 如果有记录,则执行 before insert, before delete, after delete, after insert
|
||||
```
|
||||
|
||||
### SQL编程
|
||||
### SQL 编程
|
||||
|
||||
```mysql
|
||||
/* SQL编程 */ ------------------
|
||||
@ -713,7 +713,7 @@ select into 可以将表中查询获得的数据赋给变量。
|
||||
--// 控制结构 ----------
|
||||
-- if语句
|
||||
if search_condition then
|
||||
statement_list
|
||||
statement_list
|
||||
[elseif search_condition then
|
||||
statement_list]
|
||||
...
|
||||
@ -953,4 +953,3 @@ OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
|
||||
6. SQL对大小写不敏感
|
||||
7. 清除已有语句:\c
|
||||
```
|
||||
|
||||
|
@ -15,7 +15,7 @@ tag:
|
||||
|
||||
### 1.1 MySQL 基本架构概览
|
||||
|
||||
下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。
|
||||
下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。
|
||||
|
||||
先简单介绍一下下图涉及的一些组件的基本作用帮助大家理解这幅图,在 1.2 节中会详细介绍到这些组件的作用。
|
||||
|
||||
@ -27,7 +27,7 @@ tag:
|
||||
|
||||

|
||||
|
||||
简单来说 MySQL 主要分为 Server 层和存储引擎层:
|
||||
简单来说 MySQL 主要分为 Server 层和存储引擎层:
|
||||
|
||||
- **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binlog 日志模块。
|
||||
- **存储引擎**: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。**现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5 版本开始就被当做默认存储引擎了。**
|
||||
@ -62,7 +62,7 @@ MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用
|
||||
|
||||
完成这 2 步之后,MySQL 就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。
|
||||
|
||||
#### 4) 优化器
|
||||
#### 4) 优化器
|
||||
|
||||
优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优,这篇文章涉及对这部分知识的深入讲解),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
|
||||
|
||||
@ -72,7 +72,7 @@ MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用
|
||||
|
||||
当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。
|
||||
|
||||
## 二 语句分析
|
||||
## 二 语句分析
|
||||
|
||||
### 2.1 查询语句
|
||||
|
||||
@ -84,15 +84,16 @@ select * from tb_student A where A.age='18' and A.name=' 张三 ';
|
||||
|
||||
结合上面的说明,我们分析下这个语句的执行流程:
|
||||
|
||||
* 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 SQL 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
|
||||
* 通过分析器进行词法分析,提取 SQL 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id='1'。然后判断这个 SQL 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
|
||||
* 接下来就是优化器进行确定执行方案,上面的 SQL 语句,可以有两种执行方案:
|
||||
|
||||
- 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 SQL 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
|
||||
- 通过分析器进行词法分析,提取 SQL 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id='1'。然后判断这个 SQL 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
|
||||
- 接下来就是优化器进行确定执行方案,上面的 SQL 语句,可以有两种执行方案:
|
||||
|
||||
a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。
|
||||
b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
|
||||
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
|
||||
|
||||
* 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
|
||||
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
|
||||
|
||||
- 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
|
||||
|
||||
### 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=' 张三 ';
|
||||
```
|
||||
|
||||
我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实这条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块是 **binlog(归档日志)** ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 **redo log(重做日志)**,我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:
|
||||
|
||||
* 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
|
||||
* 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
|
||||
* 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
|
||||
* 更新完成。
|
||||
- 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
|
||||
- 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
|
||||
- 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
|
||||
- 更新完成。
|
||||
|
||||
**这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?**
|
||||
|
||||
@ -114,25 +116,25 @@ update tb_student A set A.age='19' where A.name=' 张三 ';
|
||||
|
||||
并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做?
|
||||
|
||||
* **先写 redo log 直接提交,然后写 binlog**,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
|
||||
* **先写 binlog,然后写 redo log**,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
|
||||
- **先写 redo log 直接提交,然后写 binlog**,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
|
||||
- **先写 binlog,然后写 redo log**,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
|
||||
|
||||
如果采用 redo log 两阶段提交的方式就不一样了,写完 binlog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设 redo log 处于预提交状态,binlog 也已经写完了,这个时候发生了异常重启会怎么样呢?
|
||||
这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:
|
||||
|
||||
* 判断 redo log 是否完整,如果判断是完整的,就立即提交。
|
||||
* 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
|
||||
- 判断 redo log 是否完整,如果判断是完整的,就立即提交。
|
||||
- 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
|
||||
|
||||
这样就解决了数据一致性的问题。
|
||||
|
||||
## 三 总结
|
||||
|
||||
* MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。
|
||||
* 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
|
||||
* 查询语句的执行流程如下:权限校验(如果命中缓存)--->查询缓存--->分析器--->优化器--->权限校验--->执行器--->引擎
|
||||
* 更新语句执行流程如下:分析器---->权限校验---->执行器--->引擎---redo log(prepare 状态)--->binlog--->redo log(commit状态)
|
||||
- MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。
|
||||
- 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
|
||||
- 查询语句的执行流程如下:权限校验(如果命中缓存)--->查询缓存--->分析器--->优化器--->权限校验--->执行器--->引擎
|
||||
- 更新语句执行流程如下:分析器---->权限校验---->执行器--->引擎---redo log(prepare 状态)--->binlog--->redo log(commit 状态)
|
||||
|
||||
## 四 参考
|
||||
|
||||
* 《MySQL 实战45讲》
|
||||
* MySQL 5.6参考手册:<https://dev.MySQL.com/doc/refman/5.6/en/>
|
||||
- 《MySQL 实战 45 讲》
|
||||
- MySQL 5.6 参考手册:<https://dev.MySQL.com/doc/refman/5.6/en/>
|
||||
|
@ -157,4 +157,4 @@ INSERT INTO `test1` (`id`, `num1`, `num2`, `type1`, `type2`, `str1`, `str2`) VAL
|
||||
3. 当 where 查询操作符**左边为字符类型**时发生了隐式转换,那么会导致索引失效,造成全表扫描效率极低。
|
||||
4. 字符串转换为数值类型时,非数字开头的字符串会转化为`0`,以数字开头的字符串会截取从第一个字符到第一个非数字内容为止的值为转化结果。
|
||||
|
||||
所以,我们在写 SQL 时一定要养成良好的习惯,查询的字段是什么类型,等号右边的条件就写成对应的类型。特别当查询的字段是字符串时,等号右边的条件一定要用引号引起来标明这是一个字符串,否则会造成索引失效触发全表扫描。
|
||||
所以,我们在写 SQL 时一定要养成良好的习惯,查询的字段是什么类型,等号右边的条件就写成对应的类型。特别当查询的字段是字符串时,等号右边的条件一定要用引号引起来标明这是一个字符串,否则会造成索引失效触发全表扫描。
|
||||
|
@ -40,13 +40,13 @@ tag:
|
||||
|
||||

|
||||
|
||||
但如果马上重启 MySQL 实例,重启后这个表的 AUTO_INCREMENT 就会变成 1。也就是说,MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。
|
||||
但如果马上重启 MySQL 实例,重启后这个表的 AUTO_INCREMENT 就会变成 1。 也就是说,MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
以上,是在我本地 MySQL 5.x 版本的实验,实际上,**到了 MySQL 8.0 版本后,自增值的变更记录被放在了 redo log 中,提供了自增值持久化的能力** ,也就是实现了“如果发生重启,表的自增值可以根据 redo log 恢复为 MySQL 重启前的值”
|
||||
以上,是在我本地 MySQL 5.x 版本的实验,实际上,**到了 MySQL 8.0 版本后,自增值的变更记录被放在了 redo log 中,提供了自增值持久化的能力** ,也就是实现了“如果发生重启,表的自增值可以根据 redo log 恢复为 MySQL 重启前的值”
|
||||
|
||||
也就是说对于上面这个例子来说,重启实例后这个表的 AUTO_INCREMENT 仍然是 2。
|
||||
|
||||
@ -76,7 +76,7 @@ tag:
|
||||
|
||||
这个奇数偶数其实是通过 `auto_increment_offset` 和 `auto_increment_increment` 这两个参数来决定的,这俩分别用来表示自增的初始值和步长,默认值都是 1。
|
||||
|
||||
所以,上面的例子中生成新的自增值的步骤实际是这样的:从 `auto_increment_offset` 开始,以 `auto_increment_increment` 为步长,持续叠加,直到找到第一个大于 100 的值,作为新的自增值。
|
||||
所以,上面的例子中生成新的自增值的步骤实际是这样的:从 `auto_increment_offset` 开始,以 `auto_increment_increment` 为步长,持续叠加,直到找到第一个大于 100 的值,作为新的自增值。
|
||||
|
||||
所以,这种情况下,自增值可能会是 102,103 等等之类的,就会导致不连续的主键 id。
|
||||
|
||||
@ -149,7 +149,7 @@ tag:
|
||||
|
||||
现在有两个并行执行的事务 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。
|
||||
3. 接下来,继续执行的其他事务就会申请到 id=2。这时,就会出现插入语句报错“主键冲突”。
|
||||
|
||||
@ -216,4 +216,4 @@ tag:
|
||||
1. 自增初始值和自增步长设置不为 1
|
||||
2. 唯一键冲突
|
||||
3. 事务回滚
|
||||
4. 批量插入(如 `insert...select` 语句)
|
||||
4. 批量插入(如 `insert...select` 语句)
|
||||
|
@ -9,12 +9,12 @@ head:
|
||||
content: MySQL查询缓存,MySQL缓存机制中的内存管理
|
||||
- - meta
|
||||
- name: description
|
||||
content: 为了提高完全相同的查询语句的响应速度,MySQL Server 会对查询语句进行 Hash 计算得到一个 Hash 值。MySQL Server 不会对 SQL 做任何处理,SQL 必须完全一致 Hash 值才会一样。得到 Hash 值之后,通过该 Hash 值到查询缓存中匹配该查询的结果。MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查询同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。
|
||||
content: 为了提高完全相同的查询语句的响应速度,MySQL Server 会对查询语句进行 Hash 计算得到一个 Hash 值。MySQL Server 不会对 SQL 做任何处理,SQL 必须完全一致 Hash 值才会一样。得到 Hash 值之后,通过该 Hash 值到查询缓存中匹配该查询的结果。MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查询同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。
|
||||
---
|
||||
|
||||
缓存是一个有效且实用的系统性能优化的手段,不论是操作系统还是各种软件和网站或多或少都用到了缓存。
|
||||
|
||||
然而,有经验的 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 体系架构如下图所示:
|
||||
|
||||

|
||||
|
||||
@ -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 生效。
|
||||
|
||||
8.0 版本之前,`my.cnf` 加入以下配置,重启 MySQL 开启查询缓存
|
||||
8.0 版本之前,`my.cnf` 加入以下配置,重启 MySQL 开启查询缓存
|
||||
|
||||
```properties
|
||||
query_cache_type=1
|
||||
@ -151,7 +151,7 @@ MySQL 查询缓存使用内存池技术,自己管理内存释放和分配,
|
||||
|
||||
## MySQL 查询缓存的优缺点
|
||||
|
||||
**优点:**
|
||||
**优点:**
|
||||
|
||||
- 查询缓存的查询,发生在 MySQL 接收到客户端的查询请求、查询权限验证之后和查询 SQL 解析之前。也就是说,当 MySQL 接收到客户端的查询 SQL 之后,仅仅只需要对其进行相应的权限验证之后,就会通过查询缓存来查找结果,甚至都不需要经过 Optimizer 模块进行执行计划的分析优化,更不需要发生任何存储引擎的交互。
|
||||
- 由于查询缓存是基于内存的,直接从内存中返回相应的查询结果,因此减少了大量的磁盘 I/O 和 CPU 计算,导致效率非常高。
|
||||
@ -174,7 +174,7 @@ MySQL 查询缓存使用内存池技术,自己管理内存释放和分配,
|
||||
|
||||
## 总结
|
||||
|
||||
MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查询同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。
|
||||
MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查询同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。
|
||||
|
||||
查询缓存是一个适用较少情况的缓存机制。如果你的应用对数据库的更新很少,那么查询缓存将会作用显著。比较典型的如博客系统,一般博客更新相对较慢,数据表相对稳定不变,这时候查询缓存的作用会比较明显。
|
||||
|
||||
@ -196,11 +196,11 @@ MySQL 中的查询缓存虽然能够提升数据库的查询性能,但是查
|
||||
|
||||
> 根据我们的经验,在高并发压力环境中查询缓存会导致系统性能的下降,甚至僵死。如果你一 定要使用查询缓存,那么不要设置太大内存,而且只有在明确收益的时候才使用(数据库内容修改次数较少)。
|
||||
|
||||
**确实是这样的!实际项目中,更建议使用本地缓存(比如 Caffeine)或者分布式缓存(比如Redis) ,性能更好,更通用一些。**
|
||||
**确实是这样的!实际项目中,更建议使用本地缓存(比如 Caffeine)或者分布式缓存(比如 Redis) ,性能更好,更通用一些。**
|
||||
|
||||
## 参考
|
||||
|
||||
- 《高性能 MySQL》
|
||||
- MySQL缓存机制:https://zhuanlan.zhihu.com/p/55947158
|
||||
- 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
|
||||
- MySQL 缓存机制:https://zhuanlan.zhihu.com/p/55947158
|
||||
- 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
|
||||
|
@ -12,9 +12,9 @@ head:
|
||||
content: 执行计划是指一条 SQL 语句在经过MySQL 查询优化器的优化会后,具体的执行方式。优化 SQL 的第一步应该是读懂 SQL 的执行计划。
|
||||
---
|
||||
|
||||
> 本文来自公号 MySQL 技术,JavaGuide 对其做了补充完善。原文地址:https://mp.weixin.qq.com/s/d5OowNLtXBGEAbT31sSH4g
|
||||
> 本文来自公号 MySQL 技术,JavaGuide 对其做了补充完善。原文地址:https://mp.weixin.qq.com/s/d5OowNLtXBGEAbT31sSH4g
|
||||
|
||||
优化 SQL 的第一步应该是读懂 SQL 的执行计划。本篇文章,我们一起来学习下 MySQL `EXPLAIN` 执行计划相关知识。
|
||||
优化 SQL 的第一步应该是读懂 SQL 的执行计划。本篇文章,我们一起来学习下 MySQL `EXPLAIN` 执行计划相关知识。
|
||||
|
||||
## 什么是执行计划?
|
||||
|
||||
@ -24,7 +24,7 @@ head:
|
||||
|
||||
## 如何获取执行计划?
|
||||
|
||||
MySQL 为我们提供了 `EXPLAIN` 命令,来获取执行计划的相关信息。
|
||||
MySQL 为我们提供了 `EXPLAIN` 命令,来获取执行计划的相关信息。
|
||||
|
||||
需要注意的是,`EXPLAIN` 语句并不会真的去执行相关的语句,而是通过查询优化器对语句进行分析,找出最优的查询方案,并显示对应的信息。
|
||||
|
||||
@ -50,8 +50,8 @@ mysql> explain SELECT * FROM dept_emp WHERE emp_no IN (SELECT emp_no FROM dept_e
|
||||
|
||||
| **列名** | **含义** |
|
||||
| ------------- | -------------------------------------------- |
|
||||
| id | SELECT查询的序列标识符 |
|
||||
| select_type | SELECT关键字对应的查询类型 |
|
||||
| id | SELECT 查询的序列标识符 |
|
||||
| select_type | SELECT 关键字对应的查询类型 |
|
||||
| table | 用到的表名 |
|
||||
| partitions | 匹配的分区,对于未分区的表,值为 NULL |
|
||||
| type | 表的访问方法 |
|
||||
@ -89,8 +89,7 @@ id 如果相同,从上往下依次执行。id 不同,id 值越大,执行
|
||||
查询用到的表名,每行都有对应的表名,表名除了正常的表之外,也可能是以下列出的值:
|
||||
|
||||
- **`<unionM,N>`** : 本行引用了 id 为 M 和 N 的行的 UNION 结果;
|
||||
- **`<derivedN>`** : 本行引用了 id 为 N 的表所产生的的派生表结果。派生表有可能产生自 FROM 语句中的子查询。
|
||||
-**`<subqueryN>`** : 本行引用了 id 为 N 的表所产生的的物化子查询结果。
|
||||
- **`<derivedN>`** : 本行引用了 id 为 N 的表所产生的的派生表结果。派生表有可能产生自 FROM 语句中的子查询。 -**`<subqueryN>`** : 本行引用了 id 为 N 的表所产生的的物化子查询结果。
|
||||
|
||||
### type(重要)
|
||||
|
||||
@ -139,4 +138,4 @@ rows 列表示根据表统计信息及选用情况,大致估算出找到所需
|
||||
## 参考
|
||||
|
||||
- https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
|
||||
- https://juejin.cn/post/6953444668973514789
|
||||
- https://juejin.cn/post/6953444668973514789
|
||||
|
@ -13,6 +13,8 @@ head:
|
||||
content: 一篇文章总结MySQL常见的知识点和面试题,涵盖MySQL基础、MySQL基础架构、MySQL存储引擎、MySQL查询缓存、MySQL事务、MySQL锁等内容。
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
## 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)
|
||||
- [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)
|
||||
- [MySQL 的自增主键一定是连续的吗? - 飞天小牛肉 - 2022](https://mp.weixin.qq.com/s/qci10h9rJx_COZbHV3aygQ)
|
||||
- [深入理解 MySQL 索引底层原理 - 腾讯技术工程 - 2020](https://zhuanlan.zhihu.com/p/113917726)
|
||||
|
@ -157,4 +157,4 @@ MySQL 中时间到底怎么存储才好?Datetime?Timestamp? 数值保存的时
|
||||
|
||||
每种方式都有各自的优势,根据实际场景才是王道。下面再对这三种方式做一个简单的对比,以供大家实际开发中选择正确的存放时间的数据类型:
|
||||
|
||||

|
||||

|
||||
|
@ -73,7 +73,7 @@ SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTE
|
||||
|
||||
### 脏读(读未提交)
|
||||
|
||||
%E5%AE%9E%E4%BE%8B.jpg)
|
||||
%E5%AE%9E%E4%BE%8B.jpg>)
|
||||
|
||||
### 避免脏读(读已提交)
|
||||
|
||||
|
@ -19,16 +19,16 @@ NoSQL 数据库代表:HBase 、Cassandra、MongoDB、Redis。
|
||||
|
||||
## SQL 和 NoSQL 有什么区别?
|
||||
|
||||
| | SQL 数据库 | NoSQL 数据库 |
|
||||
| :----------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| 数据存储模型 | 结构化存储,具有固定行和列的表格 | 非结构化存储。文档:JSON 文档,键值:键值对,宽列:包含行和动态列的表,图:节点和边 |
|
||||
| 发展历程 | 开发于 1970 年代,重点是减少数据重复 | 开发于 2000 年代后期,重点是提升可扩展性,减少大规模数据的存储成本 |
|
||||
| 例子 | Oracle、MySQL、Microsoft SQL Server 、PostgreSQL | 文档:MongoDB、CouchDB,键值:Redis 、DynamoDB,宽列:Cassandra 、 HBase,图表:Neo4j 、 Amazon Neptune、Giraph |
|
||||
| ACID 属性 | 提供原子性、一致性、隔离性和持久性 (ACID) 属性 | 通常不支持 ACID 事务,为了可扩展、高性能进行了权衡,少部分支持比如 MongoDB 。不过,MongoDB 对 ACID 事务 的支持和 MySQL 还是有所区别的。 |
|
||||
| 性能 | 性能通常取决于磁盘子系统。要获得最佳性能,通常需要优化查询、索引和表结构。 | 性能通常由底层硬件集群大小、网络延迟以及调用应用程序来决定。 |
|
||||
| 扩展 | 垂直(使用性能更强大的服务器进行扩展)、读写分离、分库分表 | 横向(增加服务器的方式横向扩展,通常是基于分片机制) |
|
||||
| 用途 | 普通企业级的项目的数据存储 | 用途广泛比如图数据库支持分析和遍历连接数据之间的关系、键值数据库可以处理大量数据扩展和极高的状态变化 |
|
||||
| 查询语法 | 结构化查询语言 (SQL) | 数据访问语法可能因数据库而异 |
|
||||
| | SQL 数据库 | NoSQL 数据库 |
|
||||
| :----------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 数据存储模型 | 结构化存储,具有固定行和列的表格 | 非结构化存储。文档:JSON 文档,键值:键值对,宽列:包含行和动态列的表,图:节点和边 |
|
||||
| 发展历程 | 开发于 1970 年代,重点是减少数据重复 | 开发于 2000 年代后期,重点是提升可扩展性,减少大规模数据的存储成本 |
|
||||
| 例子 | Oracle、MySQL、Microsoft SQL Server 、PostgreSQL | 文档:MongoDB、CouchDB,键值:Redis 、DynamoDB,宽列:Cassandra 、 HBase,图表:Neo4j 、 Amazon Neptune、Giraph |
|
||||
| ACID 属性 | 提供原子性、一致性、隔离性和持久性 (ACID) 属性 | 通常不支持 ACID 事务,为了可扩展、高性能进行了权衡,少部分支持比如 MongoDB 。不过,MongoDB 对 ACID 事务 的支持和 MySQL 还是有所区别的。 |
|
||||
| 性能 | 性能通常取决于磁盘子系统。要获得最佳性能,通常需要优化查询、索引和表结构。 | 性能通常由底层硬件集群大小、网络延迟以及调用应用程序来决定。 |
|
||||
| 扩展 | 垂直(使用性能更强大的服务器进行扩展)、读写分离、分库分表 | 横向(增加服务器的方式横向扩展,通常是基于分片机制) |
|
||||
| 用途 | 普通企业级的项目的数据存储 | 用途广泛比如图数据库支持分析和遍历连接数据之间的关系、键值数据库可以处理大量数据扩展和极高的状态变化 |
|
||||
| 查询语法 | 结构化查询语言 (SQL) | 数据访问语法可能因数据库而异 |
|
||||
|
||||
## NoSQL 数据库有什么优势?
|
||||
|
||||
@ -54,6 +54,6 @@ NoSQL 数据库主要可以分为下面四种类型:
|
||||
|
||||
## 参考
|
||||
|
||||
- NoSQL 是什么?- MongoDB 官方文档:https://www.mongodb.com/zh-cn/nosql-explained
|
||||
- 什么是 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 是什么?- MongoDB 官方文档:<https://www.mongodb.com/zh-cn/nosql-explained>
|
||||
- 什么是 NoSQL? - AWS:<https://aws.amazon.com/cn/nosql/>
|
||||
- NoSQL vs. SQL Databases - MongoDB 官方文档:<https://www.mongodb.com/zh-cn/nosql-explained/nosql-vs-sql>
|
||||
|
@ -5,12 +5,11 @@ tag:
|
||||
- Redis
|
||||
---
|
||||
|
||||
|
||||
看到很多小伙伴简历上写了“**熟练使用缓存**”,但是被我问到“**缓存常用的3种读写策略**”的时候却一脸懵逼。
|
||||
看到很多小伙伴简历上写了“**熟练使用缓存**”,但是被我问到“**缓存常用的 3 种读写策略**”的时候却一脸懵逼。
|
||||
|
||||
在我看来,造成这个问题的原因是我们在学习 Redis 的时候,可能只是简单了写一些 Demo,并没有去关注缓存的读写策略,或者说压根不知道这回事。
|
||||
|
||||
但是,搞懂3种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
|
||||
但是,搞懂 3 种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
|
||||
|
||||
**下面介绍到的三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式。**
|
||||
|
||||
|
@ -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)中。
|
||||
|
||||

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

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
为了帮助更多同学准备 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>
|
||||
<!-- @include: @planet.snippet.md -->
|
@ -9,47 +9,4 @@ tag:
|
||||
|
||||

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

|
||||
|
||||
最近几年,市面上有越来越多的“技术大佬”开始办培训班/训练营,动辄成千上万的学费,却并没有什么干货,单纯的就是割韭菜。
|
||||
|
||||
为了帮助更多同学准备 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>
|
||||
<!-- @include: @planet.snippet.md -->
|
@ -5,7 +5,7 @@ tag:
|
||||
- Redis
|
||||
---
|
||||
|
||||
> 本文整理完善自:https://mp.weixin.qq.com/s/0Nqfq_eQrUb12QH6eBbHXA ,作者:阿Q说代码
|
||||
> 本文整理完善自:https://mp.weixin.qq.com/s/0Nqfq_eQrUb12QH6eBbHXA ,作者:阿 Q 说代码
|
||||
|
||||
这篇文章会详细总结一下可能导致 Redis 阻塞的情况,这些情况也是影响 Redis 性能的关键因素,使用 Redis 的时候应该格外注意!
|
||||
|
||||
@ -54,7 +54,7 @@ Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关
|
||||
|
||||
当后台线程( `aof_fsync` 线程)调用 `fsync` 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,会导致 `fsync` 操作发生阻塞,主线程调用 `write` 函数时也会被阻塞。`fsync` 完成后,主线程执行 `write` 才能成功返回。
|
||||
|
||||
关于 AOF 工作流程的详细介绍可以查看:[Redis持久化机制详解](./redis-persistence.md),有助于理解 AOF 刷盘阻塞。
|
||||
关于 AOF 工作流程的详细介绍可以查看:[Redis 持久化机制详解](./redis-persistence.md),有助于理解 AOF 刷盘阻塞。
|
||||
|
||||
### AOF 重写阻塞
|
||||
|
||||
@ -64,7 +64,7 @@ Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关
|
||||
|
||||
阻塞就是出现在第 2 步的过程中,将缓冲区中新数据写到新文件的过程中会产生**阻塞**。
|
||||
|
||||
相关阅读:[Redis AOF重写阻塞问题分析](https://cloud.tencent.com/developer/article/1633077)。
|
||||
相关阅读:[Redis AOF 重写阻塞问题分析](https://cloud.tencent.com/developer/article/1633077)。
|
||||
|
||||
## 大 Key
|
||||
|
||||
@ -111,13 +111,13 @@ Redis 集群可以进行节点的动态扩容缩容,这一过程目前还处
|
||||
|
||||
## Swap(内存交换)
|
||||
|
||||
什么是 Swap?Swap 直译过来是交换的意思,Linux中的Swap常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。因此,Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。
|
||||
什么是 Swap?Swap 直译过来是交换的意思,Linux 中的 Swap 常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。因此,Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。
|
||||
|
||||
Swap 对于Redis来说是非常致命的,Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出硬盘,由于内存与硬盘读写的速度并几个数量级,会导致发生交换后的Redis性能急剧下降。
|
||||
Swap 对于 Redis 来说是非常致命的,Redis 保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把 Redis 使用的部分内存换出硬盘,由于内存与硬盘读写的速度并几个数量级,会导致发生交换后的 Redis 性能急剧下降。
|
||||
|
||||
识别 Redis 发生 Swap 的检查方法如下:
|
||||
|
||||
1、查询Redis进程号
|
||||
1、查询 Redis 进程号
|
||||
|
||||
```bash
|
||||
reids-cli -p 6383 info server | grep process_id
|
||||
@ -136,19 +136,19 @@ Swap: 0kB
|
||||
.....
|
||||
```
|
||||
|
||||
如果交换量都是0KB或者个别的是4KB,则正常。
|
||||
如果交换量都是 0KB 或者个别的是 4KB,则正常。
|
||||
|
||||
预防内存交换的方法:
|
||||
|
||||
- 保证机器充足的可用内存
|
||||
- 确保所有Redis实例设置最大可用内存(maxmemory),防止极端情况Redis内存不可控的增长
|
||||
- 降低系统使用swap优先级,如`echo 10 > /proc/sys/vm/swappiness`
|
||||
- 确保所有 Redis 实例设置最大可用内存(maxmemory),防止极端情况 Redis 内存不可控的增长
|
||||
- 降低系统使用 swap 优先级,如`echo 10 > /proc/sys/vm/swappiness`
|
||||
|
||||
## 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开发与运维笔记-Redis的噩梦-阻塞:https://mp.weixin.qq.com/s/TDbpz9oLH6ifVv6ewqgSgA
|
||||
- Redis 阻塞的 6 大类场景分析与总结:https://mp.weixin.qq.com/s/eaZCEtTjTuEmXfUubVHjew
|
||||
- Redis 开发与运维笔记-Redis 的噩梦-阻塞:https://mp.weixin.qq.com/s/TDbpz9oLH6ifVv6ewqgSgA
|
||||
|
@ -387,17 +387,17 @@ Sorted Set 类似于 Set,但和 Set 相比,Sorted Set 增加了一个权重
|
||||
|
||||
### 常用命令
|
||||
|
||||
| 命令 | 介绍 |
|
||||
| --------------------------------------------- | ------------------------------------------------------------ |
|
||||
| ZADD key score1 member1 score2 member2 ... | 向指定有序集合添加一个或多个元素 |
|
||||
| ZCARD KEY | 获取指定有序集合的元素数量 |
|
||||
| ZSCORE key member | 获取指定有序集合中指定元素的 score 值 |
|
||||
| 命令 | 介绍 |
|
||||
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| ZADD key score1 member1 score2 member2 ... | 向指定有序集合添加一个或多个元素 |
|
||||
| ZCARD KEY | 获取指定有序集合的元素数量 |
|
||||
| ZSCORE key member | 获取指定有序集合中指定元素的 score 值 |
|
||||
| ZINTERSTORE destination numkeys key1 key2 ... | 将给定所有有序集合的交集存储在 destination 中,对相同元素对应的 score 值进行 SUM 聚合操作,numkeys 为集合数量 |
|
||||
| ZUNIONSTORE destination numkeys key1 key2 ... | 求并集,其它和 ZINTERSTORE 类似 |
|
||||
| ZDIFFSTORE destination numkeys key1 key2 ... | 求差集,其它和 ZINTERSTORE 类似 |
|
||||
| ZRANGE key start end | 获取指定有序集合 start 和 end 之间的元素(score 从低到高) |
|
||||
| ZREVRANGE key start end | 获取指定有序集合 start 和 end 之间的元素(score 从高到底) |
|
||||
| ZREVRANK key member | 获取指定有序集合中指定元素的排名(score 从大到小排序) |
|
||||
| ZUNIONSTORE destination numkeys key1 key2 ... | 求并集,其它和 ZINTERSTORE 类似 |
|
||||
| ZDIFFSTORE destination numkeys key1 key2 ... | 求差集,其它和 ZINTERSTORE 类似 |
|
||||
| ZRANGE key start end | 获取指定有序集合 start 和 end 之间的元素(score 从低到高) |
|
||||
| ZREVRANGE key start end | 获取指定有序集合 start 和 end 之间的元素(score 从高到底) |
|
||||
| ZREVRANK key member | 获取指定有序集合中指定元素的排名(score 从大到小排序) |
|
||||
|
||||
更多 Redis Sorted Set 命令以及详细使用指南,请查看 Redis 官网对应的介绍:https://redis.io/commands/?group=sorted-set 。
|
||||
|
||||
|
@ -26,11 +26,11 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
|
||||
|
||||
### 常用命令
|
||||
|
||||
| 命令 | 介绍 |
|
||||
| ------------------------------------- | ------------------------------------------------------------ |
|
||||
| SETBIT key offset value | 设置指定 offset 位置的值 |
|
||||
| GETBIT key offset | 获取指定 offset 位置的值 |
|
||||
| BITCOUNT key start end | 获取 start 和 end 之前值为 1 的元素个数 |
|
||||
| 命令 | 介绍 |
|
||||
| ------------------------------------- | ---------------------------------------------------------------- |
|
||||
| SETBIT key offset value | 设置指定 offset 位置的值 |
|
||||
| GETBIT key offset | 获取指定 offset 位置的值 |
|
||||
| BITCOUNT key start end | 获取 start 和 end 之前值为 1 的元素个数 |
|
||||
| BITOP operation destkey key1 key2 ... | 对一个或多个 Bitmap 进行运算,可用运算符有 AND, OR, XOR 以及 NOT |
|
||||
|
||||
**Bitmap 基本操作演示** :
|
||||
@ -86,10 +86,10 @@ HyperLogLog 的使用非常简单,但原理非常复杂。HyperLogLog 的原
|
||||
|
||||
HyperLogLog 相关的命令非常少,最常用的也就 3 个。
|
||||
|
||||
| 命令 | 介绍 |
|
||||
| ----------------------------------------- | ------------------------------------------------------------ |
|
||||
| PFADD key element1 element2 ... | 添加一个或多个元素到 HyperLogLog 中 |
|
||||
| PFCOUNT key1 key2 | 获取一个或者多个 HyperLogLog 的唯一计数。 |
|
||||
| 命令 | 介绍 |
|
||||
| ----------------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| PFADD key element1 element2 ... | 添加一个或多个元素到 HyperLogLog 中 |
|
||||
| PFCOUNT key1 key2 | 获取一个或者多个 HyperLogLog 的唯一计数。 |
|
||||
| PFMERGE destkey sourcekey1 sourcekey2 ... | 将多个 HyperLogLog 合并到 destkey 中,destkey 会结合多个源,算出对应的唯一计数。 |
|
||||
|
||||
**HyperLogLog 基本操作演示** :
|
||||
@ -132,13 +132,13 @@ Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理
|
||||
|
||||
### 常用命令
|
||||
|
||||
| 命令 | 介绍 |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| GEOADD key longitude1 latitude1 member1 ... | 添加一个或多个元素对应的经纬度信息到 GEO 中 |
|
||||
| GEOPOS key member1 member2 ... | 返回给定元素的经纬度信息 |
|
||||
| GEODIST key member1 member2 M/KM/FT/MI | 返回两个给定元素之间的距离 |
|
||||
| 命令 | 介绍 |
|
||||
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
|
||||
| GEOADD key longitude1 latitude1 member1 ... | 添加一个或多个元素对应的经纬度信息到 GEO 中 |
|
||||
| GEOPOS key member1 member2 ... | 返回给定元素的经纬度信息 |
|
||||
| GEODIST key member1 member2 M/KM/FT/MI | 返回两个给定元素之间的距离 |
|
||||
| GEORADIUS key longitude latitude radius distance | 获取指定位置附近 distance 范围内的其他元素,支持 ASC(由近到远)、DESC(由远到近)、Count(数量) 等参数 |
|
||||
| GEORADIUSBYMEMBER key member radius distance | 类似于 GEORADIUS 命令,只是参照的中心点是 GEO 中的元素 |
|
||||
| GEORADIUSBYMEMBER key member radius distance | 类似于 GEORADIUS 命令,只是参照的中心点是 GEO 中的元素 |
|
||||
|
||||
**基本操作** :
|
||||
|
||||
@ -205,4 +205,4 @@ user2
|
||||
|
||||
- Redis Data Structures :https://redis.com/redis-enterprise/data-structures/ 。
|
||||
- 《Redis 深度历险:核心原理与应用实践》1.6 四两拨千斤——HyperLogLog
|
||||
- 布隆过滤器,位图,HyperLogLog:https://hogwartsrico.github.io/2020/06/08/BloomFilter-HyperLogLog-BitMap/index.html
|
||||
- 布隆过滤器,位图,HyperLogLog:https://hogwartsrico.github.io/2020/06/08/BloomFilter-HyperLogLog-BitMap/index.html
|
||||
|
@ -119,4 +119,4 @@ config set active-defrag-cycle-max 50
|
||||
|
||||
- Redis 官方文档:https://redis.io/topics/memory-optimization
|
||||
- Redis 核心技术与实战 - 极客时间 - 删除数据后,为什么内存占用率还是很高?:https://time.geekbang.org/column/article/289140
|
||||
- Redis 源码解析——内存分配:<https://shinerio.cc/2020/05/17/redis/Redis源码解析——内存管理>
|
||||
- Redis 源码解析——内存分配:<https://shinerio.cc/2020/05/17/redis/Redis源码解析——内存管理>
|
||||
|
@ -12,6 +12,8 @@ head:
|
||||
content: 一篇文章总结Redis常见的知识点和面试题,涵盖Redis基础、Redis常见数据结构、Redis线程模型、Redis内存管理、Redis事务、Redis性能优化等内容。
|
||||
---
|
||||
|
||||
<!-- @include: @small-advertisement.snippet.md -->
|
||||
|
||||
## Redis 基础
|
||||
|
||||
### 什么是 Redis?
|
||||
@ -247,13 +249,13 @@ struct __attribute__ ((__packed__)) sdshdr64 {
|
||||
|
||||
通过源码可以看出,SDS 共有五种实现方式 SDS_TYPE_5(并未用到)、SDS_TYPE_8、SDS_TYPE_16、SDS_TYPE_32、SDS_TYPE_64,其中只有后四种实际用到。Redis 会根据初始化的长度决定使用哪种类型,从而减少内存的使用。
|
||||
|
||||
| 类型 | 字节 | 位 |
|
||||
| -------- | ---- | ---- |
|
||||
| sdshdr5 | < 1 | <8 |
|
||||
| sdshdr8 | 1 | 8 |
|
||||
| sdshdr16 | 2 | 16 |
|
||||
| sdshdr32 | 4 | 32 |
|
||||
| sdshdr64 | 8 | 64 |
|
||||
| 类型 | 字节 | 位 |
|
||||
| -------- | ---- | --- |
|
||||
| sdshdr5 | < 1 | <8 |
|
||||
| sdshdr8 | 1 | 8 |
|
||||
| sdshdr16 | 2 | 16 |
|
||||
| sdshdr32 | 4 | 32 |
|
||||
| sdshdr64 | 8 | 64 |
|
||||
|
||||
对于后四种实现都包含了下面这 4 个属性:
|
||||
|
||||
@ -371,7 +373,7 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
|
||||
|
||||
### 使用 HyperLogLog 统计页面 UV 怎么做?
|
||||
|
||||
使用 HyperLogLog 统计页面 UV主要需要用到下面这两个命令:
|
||||
使用 HyperLogLog 统计页面 UV 主要需要用到下面这两个命令:
|
||||
|
||||
- `PFADD key element1 element2 ...`:添加一个或多个元素到 HyperLogLog 中。
|
||||
- `PFCOUNT key1 key2`:获取一个或者多个 HyperLogLog 的唯一计数。
|
||||
@ -444,7 +446,7 @@ Redis 通过 **IO 多路复用程序** 来监听来自客户端的大量连接
|
||||
- Redis 的性能瓶颈不在 CPU ,主要在内存和网络;
|
||||
- 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
|
||||
|
||||
相关阅读:[为什么 Redis 选择单线程模型?](https://draveness.me/whys-the-design-redis-single-thread/) 。
|
||||
相关阅读:[为什么 Redis 选择单线程模型?](https://draveness.me/whys-the-design-redis-single-thread/) 。
|
||||
|
||||
### Redis6.0 之后为何引入了多线程?
|
||||
|
||||
@ -593,4 +595,3 @@ Redis 提供 6 种数据淘汰策略:
|
||||
- 《Redis 设计与实现》
|
||||
- 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)
|
||||
|
||||
|
@ -518,5 +518,5 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删
|
||||
|
||||
- 《Redis 开发与运维》
|
||||
- 《Redis 设计与实现》
|
||||
- Redis Transactions : https://redis.io/docs/manual/transactions/
|
||||
- What is Redis Pipeline:https://buildatscale.tech/what-is-redis-pipeline/
|
||||
- Redis Transactions : https://redis.io/docs/manual/transactions/
|
||||
- What is Redis Pipeline:https://buildatscale.tech/what-is-redis-pipeline/
|
||||
|
@ -102,8 +102,8 @@ FROM Customers
|
||||
答案:
|
||||
|
||||
```sql
|
||||
SELECT cust_name
|
||||
FROM Customers
|
||||
SELECT cust_name
|
||||
FROM Customers
|
||||
ORDER BY cust_name DESC
|
||||
```
|
||||
|
||||
@ -617,15 +617,15 @@ ORDER BY order_date
|
||||
| `DATE()` | 返回日期时间的日期部分 |
|
||||
| `DATEDIFF` | 计算两个日期之差 |
|
||||
| `DATE_FORMAT()` | 返回一个格式化的日期或时间串 |
|
||||
| `DAY()` | 返回一个日期的天数部分 |
|
||||
| `DAYOFWEEK()` | 对于一个日期,返回对应的星期几 |
|
||||
| `HOUR()` | 返回一个时间的小时部分 |
|
||||
| `MINUTE()` | 返回一个时间的分钟部分 |
|
||||
| `MONTH()` | 返回一个日期的月份部分 |
|
||||
| `NOW()` | 返回当前日期和时间 |
|
||||
| `SECOND()` | 返回一个时间的秒部分 |
|
||||
| `TIME()` | 返回一个日期时间的时间部分 |
|
||||
| `YEAR()` | 返回一个日期的年份部分 |
|
||||
| `DAY()` | 返回一个日期的天数部分 |
|
||||
| `DAYOFWEEK()` | 对于一个日期,返回对应的星期几 |
|
||||
| `HOUR()` | 返回一个时间的小时部分 |
|
||||
| `MINUTE()` | 返回一个时间的分钟部分 |
|
||||
| `MONTH()` | 返回一个日期的月份部分 |
|
||||
| `NOW()` | 返回当前日期和时间 |
|
||||
| `SECOND()` | 返回一个时间的秒部分 |
|
||||
| `TIME()` | 返回一个日期时间的时间部分 |
|
||||
| `YEAR()` | 返回一个日期的年份部分 |
|
||||
|
||||
## 汇总数据
|
||||
|
||||
@ -1181,8 +1181,8 @@ ON table1.common_column1 = table2.common_column2;
|
||||
```sql
|
||||
# join....on
|
||||
SELECT c.cust_name, o.order_num
|
||||
FROM Customers c
|
||||
INNER JOIN Orders o
|
||||
FROM Customers c
|
||||
INNER JOIN Orders o
|
||||
ON c.cust_id = o.cust_id
|
||||
ORDER BY c.cust_name
|
||||
|
||||
@ -1203,14 +1203,14 @@ ORDER BY c.cust_name
|
||||
|
||||
SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示:
|
||||
|
||||
| 连接类型 | 说明 |
|
||||
| ---------------------------------------- | ------------------------------------------------------------ |
|
||||
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
|
||||
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
|
||||
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |
|
||||
| FULL JOIN / FULL OUTER JOIN 全(外)连接 | 只要其中有一个表存在满足条件的记录,就返回行。 |
|
||||
| 连接类型 | 说明 |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
|
||||
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
|
||||
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |
|
||||
| FULL JOIN / FULL OUTER JOIN 全(外)连接 | 只要其中有一个表存在满足条件的记录,就返回行。 |
|
||||
| SELF JOIN | 将一个表连接到自身,就像该表是两个表一样。为了区分两个表,在 SQL 语句中需要至少重命名一个表。 |
|
||||
| CROSS JOIN | 交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。 |
|
||||
| CROSS JOIN | 交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。 |
|
||||
|
||||
下图展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法。
|
||||
|
||||
@ -1229,7 +1229,7 @@ ORDER BY c.cust_name
|
||||
|
||||
# 显式内连接
|
||||
SELECT c.cust_name, o.order_num
|
||||
FROM Customers c
|
||||
FROM Customers c
|
||||
INNER JOIN Orders o
|
||||
USING(cust_id)
|
||||
ORDER BY c.cust_name;
|
||||
@ -1272,7 +1272,7 @@ ORDER BY c.cust_name,o.order_num
|
||||
|
||||
# 显式内连接
|
||||
SELECT c.cust_name, o.order_num
|
||||
FROM Customers c
|
||||
FROM Customers c
|
||||
INNER JOIN Orders o
|
||||
USING(cust_id)
|
||||
ORDER BY c.cust_name,o.order_num;
|
||||
|
@ -489,14 +489,14 @@ order by c.cust_name;
|
||||
|
||||
SQL 允许在 `JOIN` 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示:
|
||||
|
||||
| 连接类型 | 说明 |
|
||||
| ---------------------------------------- | ------------------------------------------------------------ |
|
||||
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
|
||||
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
|
||||
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |
|
||||
| FULL JOIN / FULL OUTER JOIN 全(外)连接 | 只要其中有一个表存在满足条件的记录,就返回行。 |
|
||||
| 连接类型 | 说明 |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| INNER JOIN 内连接 | (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。 |
|
||||
| LEFT JOIN / LEFT OUTER JOIN 左(外)连接 | 返回左表中的所有行,即使右表中没有满足条件的行也是如此。 |
|
||||
| RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 | 返回右表中的所有行,即使左表中没有满足条件的行也是如此。 |
|
||||
| FULL JOIN / FULL OUTER JOIN 全(外)连接 | 只要其中有一个表存在满足条件的记录,就返回行。 |
|
||||
| SELF JOIN | 将一个表连接到自身,就像该表是两个表一样。为了区分两个表,在 SQL 语句中需要至少重命名一个表。 |
|
||||
| CROSS JOIN | 交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。 |
|
||||
| CROSS JOIN | 交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。 |
|
||||
|
||||
下图展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法。
|
||||
|
||||
@ -555,7 +555,7 @@ SELECT column_name(s) FROM table2;
|
||||
| -------------------- | ---------------------- |
|
||||
| `LEFT()`、`RIGHT()` | 左边或者右边的字符 |
|
||||
| `LOWER()`、`UPPER()` | 转换为小写或者大写 |
|
||||
| `LTRIM()`、`RTRIM()` | 去除左边或者右边的空格 |
|
||||
| `LTRIM()`、`RTRIM()` | 去除左边或者右边的空格 |
|
||||
| `LENGTH()` | 长度 |
|
||||
| `SOUNDEX()` | 转换为语音值 |
|
||||
|
||||
@ -918,41 +918,41 @@ SELECT user FROM user;
|
||||
|
||||
下表说明了可用于`GRANT`和`REVOKE`语句的所有允许权限:
|
||||
|
||||
| **特权** | **说明** | **级别** | | | | | |
|
||||
| ----------------------- | ------------------------------------------------------------ | -------- | ------ | -------- | -------- | ---- | ---- |
|
||||
| **全局** | 数据库 | **表** | **列** | **程序** | **代理** | | |
|
||||
| ALL [PRIVILEGES] | 授予除 GRANT OPTION 之外的指定访问级别的所有权限 | | | | | | |
|
||||
| ALTER | 允许用户使用 ALTER TABLE 语句 | X | X | X | | | |
|
||||
| ALTER ROUTINE | 允许用户更改或删除存储的例程 | X | X | | | X | |
|
||||
| CREATE | 允许用户创建数据库和表 | X | X | X | | | |
|
||||
| CREATE ROUTINE | 允许用户创建存储的例程 | X | X | | | | |
|
||||
| CREATE TABLESPACE | 允许用户创建,更改或删除表空间和日志文件组 | X | | | | | |
|
||||
| CREATE TEMPORARY TABLES | 允许用户使用 CREATE TEMPORARY TABLE 创建临时表 | X | X | | | | |
|
||||
| CREATE USER | 允许用户使用 CREATE USER,DROP USER,RENAME USER 和 REVOKE ALL PRIVILEGES 语句。 | X | | | | | |
|
||||
| CREATE VIEW | 允许用户创建或修改视图。 | X | X | X | | | |
|
||||
| DELETE | 允许用户使用 DELETE | X | X | X | | | |
|
||||
| DROP | 允许用户删除数据库,表和视图 | X | X | X | | | |
|
||||
| EVENT | 启用事件计划程序的事件使用。 | X | X | | | | |
|
||||
| EXECUTE | 允许用户执行存储的例程 | X | X | X | | | |
|
||||
| FILE | 允许用户读取数据库目录中的任何文件。 | X | | | | | |
|
||||
| GRANT OPTION | 允许用户拥有授予或撤消其他帐户权限的权限。 | X | X | X | | X | X |
|
||||
| INDEX | 允许用户创建或删除索引。 | X | X | X | | | |
|
||||
| INSERT | 允许用户使用 INSERT 语句 | X | X | X | X | | |
|
||||
| LOCK TABLES | 允许用户对具有 SELECT 权限的表使用 LOCK TABLES | X | X | | | | |
|
||||
| PROCESS | 允许用户使用 SHOW PROCESSLIST 语句查看所有进程。 | X | | | | | |
|
||||
| PROXY | 启用用户代理。 | | | | | | |
|
||||
| REFERENCES | 允许用户创建外键 | X | X | X | X | | |
|
||||
| RELOAD | 允许用户使用 FLUSH 操作 | X | | | | | |
|
||||
| REPLICATION CLIENT | 允许用户查询以查看主服务器或从属服务器的位置 | X | | | | | |
|
||||
| REPLICATION SLAVE | 允许用户使用复制从属从主服务器读取二进制日志事件。 | X | | | | | |
|
||||
| SELECT | 允许用户使用 SELECT 语句 | X | X | X | X | | |
|
||||
| SHOW DATABASES | 允许用户显示所有数据库 | X | | | | | |
|
||||
| SHOW VIEW | 允许用户使用 SHOW CREATE VIEW 语句 | X | X | X | | | |
|
||||
| SHUTDOWN | 允许用户使用 mysqladmin shutdown 命令 | X | | | | | |
|
||||
| SUPER | 允许用户使用其他管理操作,例如 CHANGE MASTER TO,KILL,PURGE BINARY LOGS,SET GLOBAL 和 mysqladmin 命令 | X | | | | | |
|
||||
| TRIGGER | 允许用户使用 TRIGGER 操作。 | X | X | X | | | |
|
||||
| UPDATE | 允许用户使用 UPDATE 语句 | X | X | X | X | | |
|
||||
| USAGE | 相当于“没有特权” | | | | | | |
|
||||
| **特权** | **说明** | **级别** | | | | | |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------------- | -------- | ------ | -------- | -------- | --- | --- |
|
||||
| **全局** | 数据库 | **表** | **列** | **程序** | **代理** | | |
|
||||
| ALL [PRIVILEGES] | 授予除 GRANT OPTION 之外的指定访问级别的所有权限 | | | | | | |
|
||||
| ALTER | 允许用户使用 ALTER TABLE 语句 | X | X | X | | | |
|
||||
| ALTER ROUTINE | 允许用户更改或删除存储的例程 | X | X | | | X | |
|
||||
| CREATE | 允许用户创建数据库和表 | X | X | X | | | |
|
||||
| CREATE ROUTINE | 允许用户创建存储的例程 | X | X | | | | |
|
||||
| CREATE TABLESPACE | 允许用户创建,更改或删除表空间和日志文件组 | X | | | | | |
|
||||
| CREATE TEMPORARY TABLES | 允许用户使用 CREATE TEMPORARY TABLE 创建临时表 | X | X | | | | |
|
||||
| CREATE USER | 允许用户使用 CREATE USER,DROP USER,RENAME USER 和 REVOKE ALL PRIVILEGES 语句。 | X | | | | | |
|
||||
| CREATE VIEW | 允许用户创建或修改视图。 | X | X | X | | | |
|
||||
| DELETE | 允许用户使用 DELETE | X | X | X | | | |
|
||||
| DROP | 允许用户删除数据库,表和视图 | X | X | X | | | |
|
||||
| EVENT | 启用事件计划程序的事件使用。 | X | X | | | | |
|
||||
| EXECUTE | 允许用户执行存储的例程 | X | X | X | | | |
|
||||
| FILE | 允许用户读取数据库目录中的任何文件。 | X | | | | | |
|
||||
| GRANT OPTION | 允许用户拥有授予或撤消其他帐户权限的权限。 | X | X | X | | X | X |
|
||||
| INDEX | 允许用户创建或删除索引。 | X | X | X | | | |
|
||||
| INSERT | 允许用户使用 INSERT 语句 | X | X | X | X | | |
|
||||
| LOCK TABLES | 允许用户对具有 SELECT 权限的表使用 LOCK TABLES | X | X | | | | |
|
||||
| PROCESS | 允许用户使用 SHOW PROCESSLIST 语句查看所有进程。 | X | | | | | |
|
||||
| PROXY | 启用用户代理。 | | | | | | |
|
||||
| REFERENCES | 允许用户创建外键 | X | X | X | X | | |
|
||||
| RELOAD | 允许用户使用 FLUSH 操作 | X | | | | | |
|
||||
| REPLICATION CLIENT | 允许用户查询以查看主服务器或从属服务器的位置 | X | | | | | |
|
||||
| REPLICATION SLAVE | 允许用户使用复制从属从主服务器读取二进制日志事件。 | X | | | | | |
|
||||
| SELECT | 允许用户使用 SELECT 语句 | X | X | X | X | | |
|
||||
| SHOW DATABASES | 允许用户显示所有数据库 | X | | | | | |
|
||||
| SHOW VIEW | 允许用户使用 SHOW CREATE VIEW 语句 | X | X | X | | | |
|
||||
| SHUTDOWN | 允许用户使用 mysqladmin shutdown 命令 | X | | | | | |
|
||||
| SUPER | 允许用户使用其他管理操作,例如 CHANGE MASTER TO,KILL,PURGE BINARY LOGS,SET GLOBAL 和 mysqladmin 命令 | X | | | | | |
|
||||
| TRIGGER | 允许用户使用 TRIGGER 操作。 | X | X | X | | | |
|
||||
| UPDATE | 允许用户使用 UPDATE 语句 | X | X | X | X | | |
|
||||
| USAGE | 相当于“没有特权” | | | | | | |
|
||||
|
||||
### 创建账户
|
||||
|
||||
@ -1206,5 +1206,5 @@ DROP TRIGGER IF EXISTS trigger_insert_user;
|
||||
|
||||
## 文章推荐
|
||||
|
||||
- [后端程序员必备: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 高性能优化指南!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)
|
||||
|
@ -75,12 +75,12 @@ Zuul 主要通过过滤器(类似于 AOP)来过滤请求,从而实现网
|
||||
|
||||

|
||||
|
||||
- Github 地址 : https://github.com/Netflix/zuul
|
||||
- 官方 Wiki : https://github.com/Netflix/zuul/wiki
|
||||
- Github 地址 : <https://github.com/Netflix/zuul>
|
||||
- 官方 Wiki : <https://github.com/Netflix/zuul/wiki>
|
||||
|
||||
### 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。
|
||||
|
||||
@ -90,8 +90,8 @@ Spring Cloud Gateway 不仅提供统一的路由方式,并且基于 Filter 链
|
||||
|
||||
Spring Cloud Gateway 和 Zuul 2.x 的差别不大,也是通过过滤器来处理请求。不过,目前更加推荐使用 Spring Cloud Gateway 而非 Zuul,Spring Cloud 生态对其支持更加友好。
|
||||
|
||||
- Github 地址 : https://github.com/spring-cloud/spring-cloud-gateway
|
||||
- 官网 : https://spring.io/projects/spring-cloud-gateway
|
||||
- Github 地址 : <https://github.com/spring-cloud/spring-cloud-gateway>
|
||||
- 官网 : <https://spring.io/projects/spring-cloud-gateway>
|
||||
|
||||
### Kong
|
||||
|
||||
@ -118,8 +118,8 @@ $ curl -X POST http://kong:8001/services/{service}/plugins \
|
||||
|
||||

|
||||
|
||||
- Github 地址: https://github.com/Kong/kong
|
||||
- 官网地址 : https://konghq.com/kong
|
||||
- Github 地址: <https://github.com/Kong/kong>
|
||||
- 官网地址 : <https://konghq.com/kong>
|
||||
|
||||
### APISIX
|
||||
|
||||
@ -144,8 +144,8 @@ APISIX 同样支持定制化的插件开发。开发者除了能够使用 Lua
|
||||
|
||||

|
||||
|
||||
- Github 地址 :https://github.com/apache/apisix
|
||||
- 官网地址: https://apisix.apache.org/zh/
|
||||
- Github 地址 :<https://github.com/apache/apisix>
|
||||
- 官网地址: <https://apisix.apache.org/zh/>
|
||||
|
||||
相关阅读:
|
||||
|
||||
@ -162,11 +162,11 @@ Shenyu 是一款基于 WebFlux 的可扩展、高性能、响应式网关,Apac
|
||||
|
||||
Shenyu 通过插件扩展功能,插件是 ShenYu 的灵魂,并且插件也是可扩展和热插拔的。不同的插件实现不同的功能。Shenyu 自带了诸如限流、熔断、转发 、重写、重定向、和路由监控等插件。
|
||||
|
||||
- Github 地址: https://github.com/apache/incubator-shenyu
|
||||
- 官网地址 : https://shenyu.apache.org/
|
||||
- Github 地址: <https://github.com/apache/incubator-shenyu>
|
||||
- 官网地址 : <https://shenyu.apache.org/>
|
||||
|
||||
## 参考
|
||||
|
||||
- Kong 插件开发教程[通俗易懂]:https://cloud.tencent.com/developer/article/2104299
|
||||
- API 网关 Kong 实战:https://xie.infoq.cn/article/10e4dab2de0bdb6f2c3c93da6
|
||||
- Spring Cloud Gateway 原理介绍和应用:https://blog.fintopia.tech/60e27b0e2078082a378ec5ed/
|
||||
- Kong 插件开发教程[通俗易懂]:<https://cloud.tencent.com/developer/article/2104299>
|
||||
- API 网关 Kong 实战:<https://xie.infoq.cn/article/10e4dab2de0bdb6f2c3c93da6>
|
||||
- Spring Cloud Gateway 原理介绍和应用:<https://blog.fintopia.tech/60e27b0e2078082a378ec5ed/>
|
||||
|