Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c59f765

Browse files
update: Spring 部分内容完善
1 parent e3f51ce commit c59f765

File tree

3 files changed

+72
-30
lines changed

3 files changed

+72
-30
lines changed

‎docs/database/redis/redis-persistence.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ AOF 持久化功能的实现可以简单分为 5 步:
7171

7272
1. **命令追加(append)**:所有的写命令会追加到 AOF 缓冲区中。
7373
2. **文件写入(write)**:将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用`write`函数(系统调用),`write`将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
74-
3. **文件同步(fsync)**:AOF 缓冲区根据对应的持久化方式( `fsync` 策略)向硬盘做同步操作。这一步需要调用 `fsync` 函数(系统调用), `fsync` 针对单个文件操作,对其进行强制硬盘同步,`fsync` 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
74+
3. **文件同步(fsync)**:这一步才是持久化的核心!根据你在 `redis.conf` 文件里 `appendfsync` 配置的策略,Redis 会在不同的时机,调用 `fsync` 函数(系统调用)`fsync` 针对单个文件操作,对其进行强制硬盘同步(文件在内核缓冲区里的数据写到硬盘),`fsync` 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
7575
4. **文件重写(rewrite)**:随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
7676
5. **重启加载(load)**:当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
7777

@@ -90,9 +90,9 @@ AOF 工作流程图如下:
9090

9191
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式( `fsync`策略),它们分别是:
9292

93-
1. `appendfsync always`:主线程调用 `write` 执行写操作后,后台线程( `aof_fsync` 线程)立即会调用 `fsync` 函数同步 AOF 文件(刷盘),`fsync` 完成后线程返回,这样会严重降低 Redis 的性能(`write` + `fsync`)
94-
2. `appendfsync everysec`:主线程调用 `write` 执行写操作后立即返回,由后台线程( `aof_fsync` 线程)每秒钟调用 `fsync` 函数(系统调用)同步一次 AOF 文件(`write`+`fsync`,`fsync`间隔为 1 秒)
95-
3. `appendfsync no`:主线程调用 `write` 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(`write`但不`fsync`,`fsync` 的时机由操作系统决定)。
93+
1. `appendfsync always`:主线程调用 `write` 执行写操作后,会立刻调用 `fsync` 函数同步 AOF 文件(刷盘)。主线程会阻塞,直到 `fsync` 将数据完全刷到磁盘后才会返回。这种方式数据最安全,理论上不会有任何数据丢失。但因为每个写操作都会同步阻塞主线程,所以性能极差
94+
2. `appendfsync everysec`:主线程调用 `write` 执行写操作后立即返回,由后台线程( `aof_fsync` 线程)每秒钟调用 `fsync` 函数(系统调用)同步一次 AOF 文件(`write`+`fsync`,`fsync`间隔为 1 秒)。这种方式主线程的性能基本不受影响。在性能和数据安全之间做出了绝佳的平衡。不过,在 Redis 异常宕机时,最多可能丢失最近 1 秒内的数据。
95+
3. `appendfsync no`:主线程调用 `write` 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(`write`但不`fsync`,`fsync` 的时机由操作系统决定)。 这种方式性能最好,因为避免了 `fsync` 的阻塞。但数据安全性最差,宕机时丢失的数据量不可控,取决于操作系统上一次同步的时间点。
9696

9797
可以看出:**这 3 种持久化方式的主要区别在于 `fsync` 同步 AOF 文件的时机(刷盘)**
9898

‎docs/database/sql/sql-questions-05.md

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,53 @@ tag:
4141
写法 1:
4242

4343
```sql
44-
SELECT exam_id,
45-
count(submit_time IS NULL OR NULL) incomplete_cnt,
46-
ROUND(count(submit_time IS NULL OR NULL) / count(*), 3) complete_rate
47-
FROM exam_record
48-
GROUP BY exam_id
49-
HAVING incomplete_cnt <> 0
44+
SELECT
45+
exam_id,
46+
(COUNT(*) - COUNT(submit_time)) AS incomplete_cnt,
47+
ROUND((COUNT(*) - COUNT(submit_time)) / COUNT(*), 3) AS incomplete_rate
48+
FROM
49+
exam_record
50+
GROUP BY
51+
exam_id
52+
HAVING
53+
(COUNT(*) - COUNT(submit_time)) > 0;
5054
```
5155

56+
利用 `COUNT(*) `统计分组内的总记录数,`COUNT(submit_time)` 只统计 `submit_time` 字段不为 NULL 的记录数(即已完成数)。两者相减,就是未完成数。
57+
5258
写法 2:
5359

5460
```sql
55-
SELECT exam_id,
56-
count(submit_time IS NULL OR NULL) incomplete_cnt,
57-
ROUND(count(submit_time IS NULL OR NULL) / count(*), 3) complete_rate
58-
FROM exam_record
59-
GROUP BY exam_id
60-
HAVING incomplete_cnt <> 0
61+
SELECT
62+
exam_id,
63+
COUNT(CASE WHEN submit_time IS NULL THEN 1 END) AS incomplete_cnt,
64+
ROUND(COUNT(CASE WHEN submit_time IS NULL THEN 1 END) / COUNT(*), 3) AS incomplete_rate
65+
FROM
66+
exam_record
67+
GROUP BY
68+
exam_id
69+
HAVING
70+
COUNT(CASE WHEN submit_time IS NULL THEN 1 END) > 0;
71+
```
72+
73+
使用 `CASE` 表达式,当条件满足时返回一个非 `NULL` 值(例如 1),否则返回 `NULL`。然后用 `COUNT` 函数来统计非 `NULL` 值的数量。
74+
75+
写法 3:
76+
77+
```sql
78+
SELECT
79+
exam_id,
80+
SUM(submit_time IS NULL) AS incomplete_cnt,
81+
ROUND(SUM(submit_time IS NULL) / COUNT(*), 3) AS incomplete_rate
82+
FROM
83+
exam_record
84+
GROUP BY
85+
exam_id
86+
HAVING
87+
incomplete_cnt > 0;
6188
```
6289

63-
两种写法都可以,只有中间的写法不一样,一个是对符合条件的才`COUNT`,一个是直接上`IF`,后者更为直观,最后这个`having`解释一下, 无论是 `complete_rate` 还是 `incomplete_cnt`,只要不为 0 即可,不为 0 就意味着有未完成的
90+
利用 `SUM` 函数对一个表达式求和。当 `submit_time``NULL` 时,表达式 `(submit_time IS NULL)` 的值为 1 (TRUE),否则为 0 (FALSE)。将这些 1 和 0 加起来,就得到了未完成的数量
6491

6592
### 0 级用户高难度试卷的平均用时和平均得分
6693

‎docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,29 +110,44 @@ Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程
110110

111111
## Spring IoC
112112

113-
### 谈谈自己对于 Spring IoC 的了解
113+
### 什么是 IoC?
114114

115-
**IoC(Inversion of Control:控制反转)** 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用
115+
IoC(Inversion of Control )即控制反转/反转控制。它是一种思想不是一个技术实现。描述的是:Java 开发领域对象的创建以及管理的问题
116116

117-
**为什么叫控制反转?**
117+
例如:现有类 A 依赖于类 B
118118

119-
- **控制**:指的是对象创建(实例化、管理)的权力
120-
- **反转**:控制权交给外部环境(Spring 框架IoC 容器)
119+
- **传统的开发方式** :往往是在类 A 中手动通过 new 关键字来 new 一个 B 的对象出来
120+
- **使用 IoC 思想的开发方式** :不通过 new 关键字来创建对象,而是通过 IoC 容器(Spring 框架) 来帮助我们实例化对象。我们需要哪个对象,直接从 IoC 容器里面去取即可。
121121

122-
![IoC 图解](https://oss.javaguide.cn/java-guide-blog/frc-365faceb5697f04f31399937c059c162.png)
122+
从以上两种开发方式的对比来看:我们 "丧失了一个权力" (创建、管理对象的权力),从而也得到了一个好处(不用再考虑对象的创建、管理等一系列的事情)
123123

124-
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
124+
**为什么叫控制反转?**
125125

126-
在实际项目中一个 Service 类可能依赖了很多其他的类,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
126+
- **控制** :指的是对象创建(实例化、管理)的权力
127+
- **反转** :控制权交给外部环境(IoC 容器)
127128

128-
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
129+
![IoC 图解](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration.png)
129130

130-
Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。
131+
### IoC 解决了什么问题?
131132

132-
相关阅读:
133+
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?
133134

134-
- [IoC 源码阅读](https://javadoop.com/post/spring-ioc)
135-
- [IoC & AOP 详解(快速搞懂)](./ioc-and-aop.md)
135+
1. 对象之间的耦合度或者说依赖程度降低;
136+
2. 资源变的容易管理;比如你用 Spring 容器提供的话很容易就可以实现一个单例。
137+
138+
例如:现有一个针对 User 的操作,利用 Service 和 Dao 两层结构进行开发
139+
140+
在没有使用 IoC 思想的情况下,Service 层想要使用 Dao 层的具体实现的话,需要通过 new 关键字在`UserServiceImpl` 中手动 new 出 `IUserDao` 的具体实现类 `UserDaoImpl`(不能直接 new 接口类)。
141+
142+
很完美,这种方式也是可以实现的,但是我们想象一下如下场景:
143+
144+
开发过程中突然接到一个新的需求,针对`IUserDao` 接口开发出另一个具体实现类。因为 Server 层依赖了`IUserDao`的具体实现,所以我们需要修改`UserServiceImpl`中 new 的对象。如果只有一个类引用了`IUserDao`的具体实现,可能觉得还好,修改起来也不是很费力气,但是如果有许许多多的地方都引用了`IUserDao`的具体实现的话,一旦需要更换`IUserDao` 的实现方式,那修改起来将会非常的头疼。
145+
146+
![IoC&Aop-ioc-illustration-dao-service](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration-dao-service.png)
147+
148+
使用 IoC 的思想,我们将对象的控制权(创建、管理)交由 IoC 容器去管理,我们在使用的时候直接向 IoC 容器 "要" 就可以了
149+
150+
![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration-dao.png)
136151

137152
### 什么是 Spring Bean?
138153

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /