Skip to content

Commit

Permalink
add: SpringMVC
Browse files Browse the repository at this point in the history
  • Loading branch information
lbwanga committed Sep 27, 2024
1 parent 6a50c90 commit 1788fb4
Show file tree
Hide file tree
Showing 17 changed files with 1,315 additions and 11 deletions.
10 changes: 9 additions & 1 deletion docs/JUC/JUC.md
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@ ThreadLocal,即线程变量,是一个以 ThreadLocal 对象为键、任意

队列同步器 AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架,它使用了一个 int 成员变量表示同步状态,通过内置的 FIFO 队列来完成资源获取线程的排队工作。

AQS核心思想是,如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配,将暂时获取不到锁的线程加入到队列中。

```java
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer{
// 指向同步队列的头部
Expand Down Expand Up @@ -2285,7 +2287,13 @@ Java8 中的 `ConcurrentHashMap` 使用的 `Synchronized` 锁加 CAS 的机制

### CAS

CAS 的全称是 Compare-And-Swap,依赖于CPU的原子性指令实现。在 Java 中,实现 CAS 操作的一个关键类是`Unsafe`
CAS 的全称是 Compare-And-Swap,依赖于CPU的原子性指令实现。在 Java 中,实现 CAS 操作的一个关键类是`Unsafe`。它包含三个操作数:

1. 变量内存地址,V表示
2. 旧的预期值,A表示
3. 准备设置的新值,B表示

当执行CAS指令时,只有当V等于A时,才会用B去更新V的值,否则就不会执行更新操作。



Expand Down
11 changes: 10 additions & 1 deletion docs/MySQL/MySQL.md
Original file line number Diff line number Diff line change
Expand Up @@ -1442,12 +1442,21 @@ show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里

EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中,表如何连接和连接的顺序。

`EXPLAIN` 并不会真的去执行相关的语句,而是通过 查询优化器 对语句进行分析,找出最优的查询方案,并显示对应的信息。
`EXPLAIN` 并不会真的去执行相关的语句,而是通过查询优化器对语句进行分析,找出最优的查询方案,并显示对应的信息。

语法 :直接在 select 语句之前加上关键字 explain/desc;

![](MySQL\explain.webp)

type 字段就是描述了找到所需数据时使用的扫描方式是什么,常见扫描类型的执行效率从低到高的顺序为:

- All(全表扫描):在这些情况里,all 是最坏的情况,因为采用了全表扫描的方式。
- index(全索引扫描):index 和 all 差不多,只不过 index 对索引表进行全扫描,这样做的好处是不再需要对数据进行排序,但是开销依然很大。所以,要尽量避免全表扫描和全索引扫描。
- range(索引范围扫描):range 表示采用了索引范围扫描,一般在 where 子句中使用 < 、>、in、between 等关键词,只检索给定范围的行,属于范围查找。**从这一级别开始,索引的作用会越来越明显,因此我们需要尽量让 SQL 查询可以使用到 range 这一级别及以上的 type 访问方式**
- ref(非唯一索引扫描):ref 类型表示采用了非唯一索引,或者是唯一索引的非唯一性前缀,返回数据返回可能是多条。因为虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。
- eq_ref(唯一索引扫描):eq_ref 类型是使用主键或唯一索引时产生的访问方式,通常使用在多表联查中。比如,对两张表进行联查,关联条件是两张表的 user_id 相等,且 user_id 是唯一索引,那么使用 EXPLAIN 进行执行计划查看的时候,type 就会显示 eq_ref。
- const(结果只有一条的主键或唯一索引扫描):const 类型表示使用了主键或者唯一索引与常量值进行比较,比如 select name from product where id=1。需要说明的是 const 类型和 eq_ref 都使用了主键或唯一索引,不过这两个类型有所区别,**const 是与常量进行比较,查询效率会更快,而 eq_ref 通常用于多表联查中**

extra 几个重要的参考指标:

- Using filesort :当查询语句中包含 group by 操作,而且无法利用索引完成排序操作的时候, 这时不得不选择相应的排序算法进行,甚至可能会通过文件排序,效率是很低的,所以要避免这种问题的出现。
Expand Down
12 changes: 6 additions & 6 deletions docs/Redis/Redis基础.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ RDB保存的是dump.rdb文件。
**优势**
1. 适合大规模的数据恢复
2. 按照业务定时备份
3. 父进程不会执行磁盘I/О或类似操作,会fork一个子进程完成持久化工作,性能高
4. RDB文件在内存中的加载速度要比AOF快很多
1. RDB通过快照的形式保存某一时刻的数据状态,文件体积小
2. 备份和恢复的速度非常快
3. RDB是在主线程之外通过fork子进程来进行的,不会阻塞服务器处理命令请求
4. RDB文件通常比AOF文件小得多
**劣势**
Expand Down Expand Up @@ -355,8 +355,8 @@ AOF保存的是 appendonly.aof 文件
2. AOF缓冲会根据AOF缓冲区同步文件的三种写回策略将命令写入磁盘上的AOF文件。
1. **ALways**:同步写回,每个写命令执行完立刻同步地将日志写回磁盘。
2. **everysec**(默认):每秒写回,每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔1秒把缓冲区中的内容写入到磁盘
3. **no**:操作系统控制的写回,每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
2. **everysec**(默认):每秒写回,每个写命令执行完,只是先把日志写到AOF文件的内核缓冲区,每隔1秒把缓冲区中的内容写入到磁盘
3. **no**:操作系统控制的写回,每个写命令执行完,只是先把日志写到AOF文件的内核缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
3. 随着写入AOF内容的增加为避免文件膨胀,会根据规则进行命令的合并(**AOF重写**),从而起到AOF文件压缩的目的。
Expand Down
6 changes: 3 additions & 3 deletions docs/Redis/Redis高级.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

### Redis单线程

redis单线程主要是指Redis的**网络IO和键值对读写是由一个线程来完成**的,Redis在处理客户端的请求时包括**获取 (socket 读)、解析、执行、内容返回 (socket 写**) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程
**Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的**

但Redis的其他功能,比如**关闭文件、AOF 刷盘、释放内存**等,其实是由额外的线程执行的。
但Redis的其他功能,比如**关闭文件、AOF 刷盘、释放内存**等,其实是由额外的线程执行的。例如执行 unlink key / flushdb async/ flushall async 等命令,会把这些删除操作交给后台线程来执行,好处是不会导致 Redis 主线程卡顿。

**Redis命令工作线程是单线程的,但是,整个Redis来说,是多线程的;**

Expand All @@ -21,7 +21,7 @@ redis单线程主要是指Redis的**网络IO和键值对读写是由一个线程
1. **基于内存操作**: Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的,所以他的性能比较高;
2. **数据结构简单**: Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是 0(1),因此性能比较高;
3. Redis **采用单线程模型可以避免了多线程之间的竞争**,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
4. **多路复用和非阻塞 I/O**: Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作;
4. **多路复用和非阻塞 I/O**: Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程来检查多个 Socket 的就绪状态,在单个线程中通过记录跟踪每一个 socket(I/O流)的状态来管理处理多个 I/O 流,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作;



Expand Down
19 changes: 19 additions & 0 deletions docs/Spring/Spring6.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
hide:
- navigation
---

## IoC、DI和AOP思想提出

**IoC 控制反转思想的提出**
Expand Down Expand Up @@ -1742,3 +1747,17 @@ public class ApplicationContextConfig {
5. spring的事务在抛异常的时候会回滚,如果是catch捕获了,事务无效。可以在catch里面加上throw new RuntimeException();

6. 和锁同时使用需要注意:由于Spring事务是通过AOP实现的,所以在方法执行之前会有开启事务,之后会有提交事务逻辑。而synchronized代码块执行是在事务之内执行的,可以推断在synchronized代码块执行完时,事务还未提交,其他线程进入synchronized代码块后,读取的数据不是最新的。 所以必须使synchronized锁的范围大于事务控制的范围,把synchronized加到Controller层或者大于事务边界的调用层!



**Spring事务如果没有回滚可能是什么原因?**

1.public 修饰的方法中的事务不自动回滚,解决方案是将方法的权限修饰符改为 public 即可。

2.@Transactional 遇上 try/catch 事务不自动回滚,解决方案有两种:一种是在 catch 中将异常重新抛出去,另一种是使用代码手动将事务回滚。

3. 调用类内部的 @Transactional 方法事务不自动回滚,解决方案是给调用的方法上也加上 @Transactional

4. 抛出检查异常时事务不自动回滚,解决方案是给 @Transactional 注解上,添加 rollbackFor 参数并设置 Exception.class 值即可

5. 数据库不支持事务,事务也不会自动回滚,比如 MySQL 中设置了使用 MyISAM 引擎,因为它本身是不支持事务的,这种情况下,即使在程序中添加了 @Transactional 注解,那么依然不会有事务的行为,也就不会执行事务的自动回滚了。解决方式就是将 MySQL 的存储引擎设置为 InnoDBInnoDB支持事务。
Loading

0 comments on commit 1788fb4

Please sign in to comment.