diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts
index 8fa92a8..63869db 100644
--- a/docs/.vuepress/config.ts
+++ b/docs/.vuepress/config.ts
@@ -8,7 +8,7 @@ import { gitPlugin } from '@vuepress/plugin-git'
export default defineUserConfig({
lang: "zh-CN",
- title: "Java学习&面试指南-程序员大彬",
+ title: "大彬",
description: "Java学习、面试指南,涵盖大部分 Java 程序员所需要掌握的核心知识",
base: "/",
dest: './public',
diff --git a/docs/README.md b/docs/README.md
index 4b49ed1..9f8ba39 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -47,26 +47,10 @@ projects:
[
](https://www.zhihu.com/people/dai-shu-bin-13)
[
](https://github.com/Tyson0314/java-books)
-## 秋招提前批信息汇总
-
-[秋招提前批及正式批信息汇总(含内推)](https://docs.qq.com/sheet/DYW9ObnpobXNRTXpq?tab=BB08J2)
-
## 面试手册电子版
本网站所有内容已经汇总成**PDF电子版**,**PDF电子版**在我的[**学习圈**](zsxq/introduce.md)可以获取~
-## 计算机经典书籍PDF
-
-给大家分享**200多本计算机经典书籍PDF电子书**,包括**C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生**等,感兴趣的小伙伴可以自取:
-
-
-
-
-
-**200多本计算机经典书籍PDF电子书**:https://pan.xunlei.com/s/VNlmlh9jBl42w0QH2l4AJaWGA1?pwd=j8eq#
-
-备用链接:https://pan.quark.cn/s/3f1321952a16
-
## 学习路线

diff --git "a/docs/advance/excellent-article/MySQL\344\270\255N\344\270\252\345\206\231SQL\347\232\204\345\245\275\344\271\240\346\203\257.md" "b/docs/advance/excellent-article/MySQL\344\270\255N\344\270\252\345\206\231SQL\347\232\204\345\245\275\344\271\240\346\203\257.md"
new file mode 100644
index 0000000..9a2241a
--- /dev/null
+++ "b/docs/advance/excellent-article/MySQL\344\270\255N\344\270\252\345\206\231SQL\347\232\204\345\245\275\344\271\240\346\203\257.md"
@@ -0,0 +1,91 @@
+MySQL中编写SQL时,遵循良好的习惯能够提高查询性能、保障数据一致性、提升代码可读性和维护性。以下列举了多个编写SQL的好习惯
+
+#### 1.使用EXPLAIN分析查询计划
+
+在编写或优化复杂查询时,先使用EXPLAIN命令查看查询执行计划,理解MySQL如何执行查询、访问哪些表、使用哪种类型的联接以及索引的使用情况。
+
+好处:有助于识别潜在的性能瓶颈,如全表扫描、错误的索引选择、过多的临时表或文件排序等,从而针对性地优化查询或调整索引结构。
+
+#### 2.避免全表扫描
+
+2. 习惯:尽可能利用索引来避免全表扫描,尤其是在处理大表时。确保在WHERE、JOIN条件和ORDER BY、GROUP BY子句中使用的列有适当的索引。
+
+好处:极大地减少数据访问量,提高查询性能,减轻I/O压力。
+
+#### 3. 为表和字段添加注释
+
+3. 习惯:在创建表时,为表和每个字段添加有意义的注释,描述其用途、数据格式、业务规则等信息。
+
+好处:提高代码可读性和可维护性,帮助其他开发人员快速理解表结构和字段含义,减少沟通成本和误解。
+
+#### 4. 明确指定INSERT语句的列名
+
+习惯:在INSERT语句中显式列出要插入数据的列名,即使插入所有列也应如此。
+
+好处:避免因表结构变化导致的插入错误,增强代码的健壮性,同时也提高了语句的清晰度。
+
+#### 5. 格式化SQL语句
+
+习惯:保持SQL语句的格式整洁,使用一致的大小写(如关键词大写、表名和列名小写),合理缩进,避免过长的单行语句。
+
+好处:提高代码可读性,便于审查、调试和团队协作。
+
+#### 6. 使用LIMIT限制结果集大小
+
+习惯:在执行SELECT、DELETE或UPDATE操作时,若不需要处理全部数据,务必使用LIMIT子句限制结果集大小,特别是在生产环境中。
+
+好处:防止因误操作导致大量数据被修改或删除,降低风险,同时也能提高查询性能。
+
+#### 7.使用JOIN语句代替子查询
+
+习惯:在可能的情况下,优先使用JOIN操作代替嵌套的子查询,特别是在处理多表关联查询时。
+
+好处:许多情况下JOIN的执行效率高于子查询,而且JOIN语句通常更易于理解和优化。
+
+#### 8.避免在WHERE子句中对NULL进行比较
+
+习惯:使用IS NULL和IS NOT NULL来检查字段是否为NULL,而不是直接与NULL进行等值或不等值比较。
+
+好处:正确处理NULL值,避免逻辑错误和未预期的结果。
+
+#### 9.避免在查询中使用SELECT
+
+习惯:明确列出需要的列名,而不是使用SELECT *从表中获取所有列。
+
+好处:减少网络传输的数据量,降低I/O开销,提高查询性能,同时也有利于代码的清晰性和可维护性。
+
+#### 10. 数据库对象命名规范
+
+习惯:遵循一致且有意义的命名约定,如使用小写字母、下划线分隔单词,避免使用MySQL保留字,保持表名、列名、索引名等的简洁性和一致性。
+
+好处:提高代码可读性,减少命名冲突,便于团队协作和维护。
+
+#### 11. 事务管理
+
+习惯:对一系列需要保持原子性的操作使用事务管理,确保数据的一致性。
+
+好处:在发生异常时能够回滚未完成的操作,避免数据处于不一致状态。
+
+#### 12.适时使用索引覆盖
+
+习惯:对于只查询索引列且不需要访问数据行的查询(如计数、统计),创建覆盖索引以避免回表操作。
+
+好处:极大提升查询性能,减少I/O开销。
+
+#### 13.遵循第三范式或适当反范式
+
+习惯:根据业务需求和查询模式,合理设计表结构,遵循第三范式以减少数据冗余和更新异常,或适当反范式以优化查询性能。
+
+好处:保持数据一致性,减少数据维护成本,或提高查询效率。
+
+#### 14.使用预编译语句(PreparedStatement)
+
+习惯:在应用程序中使用预编译语句(如Java中的PreparedStatement)执行SQL,特别是对于动态拼接SQL语句的情况。
+
+好处:避免SQL注入攻击,提高查询性能,减少数据库服务器的解析开销。
+
+#### 15.定期分析与优化表和索引
+
+习惯:定期运行ANALYZE TABLE收集统计信息,以便MySQL优化器做出更准确的查询计划决策。根据查询性能监控结果,适时调整索引或重构表结构。
+
+好处:确保数据库持续高效运行,适应不断变化的业务需求和数据分布。
\ No newline at end of file
diff --git a/docs/advance/system-design/README.md b/docs/advance/system-design/README.md
index 515b3d5..15ef840 100644
--- a/docs/advance/system-design/README.md
+++ b/docs/advance/system-design/README.md
@@ -26,8 +26,8 @@
怎么加入[知识星球](https://topjavaer.cn/zsxq/introduce.html)?
-**扫描以下二维码**领取50元的优惠券即可加入。星球定价**218**元,减去**50**元的优惠券,等于说只需要**168**元的价格就可以加入,服务期一年,**每天只要三毛钱**(0.46元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**218**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/campus-recruit/share/2-years-tech-upgrade.md b/docs/campus-recruit/share/2-years-tech-upgrade.md
index b2aa471..5322d98 100644
--- a/docs/campus-recruit/share/2-years-tech-upgrade.md
+++ b/docs/campus-recruit/share/2-years-tech-upgrade.md
@@ -58,4 +58,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券即可加入~
-
+
diff --git a/docs/career-plan/3-years-reflect.md b/docs/career-plan/3-years-reflect.md
index 8c4c12c..21e4cfc 100644
--- a/docs/career-plan/3-years-reflect.md
+++ b/docs/career-plan/3-years-reflect.md
@@ -95,5 +95,5 @@ head:
**加入方式**:**扫描二维码**领取优惠券加入(**即将恢复原价**)~
-
+
diff --git a/docs/career-plan/how-to-prepare-job-hopping.md b/docs/career-plan/how-to-prepare-job-hopping.md
index 0dea290..59aee75 100644
--- a/docs/career-plan/how-to-prepare-job-hopping.md
+++ b/docs/career-plan/how-to-prepare-job-hopping.md
@@ -85,4 +85,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券加入(**即将恢复原价**)~
-
+
diff --git a/docs/career-plan/java-or-bigdata.md b/docs/career-plan/java-or-bigdata.md
index d3bbf32..cf98ec1 100644
--- a/docs/career-plan/java-or-bigdata.md
+++ b/docs/career-plan/java-or-bigdata.md
@@ -59,4 +59,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券加入(**即将恢复原价**)~
-
+
diff --git a/docs/computer-basic/network.md b/docs/computer-basic/network.md
index c407f6d..831488a 100644
--- a/docs/computer-basic/network.md
+++ b/docs/computer-basic/network.md
@@ -41,8 +41,8 @@ head:
怎么加入[知识星球](https://topjavaer.cn/zsxq/introduce.html)?
-**扫描以下二维码**领取50元的优惠券即可加入。星球定价**218**元,减去**50**元的优惠券,等于说只需要**168**元的价格就可以加入,服务期一年,**每天只要三毛钱**(0.46元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**218**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
-
+
diff --git a/docs/database/mysql.md b/docs/database/mysql.md
index b7946d9..c8b0032 100644
--- a/docs/database/mysql.md
+++ b/docs/database/mysql.md
@@ -22,6 +22,8 @@ head:
## 更新记录
+- 2024.06.05,更新[MySQL查询 limit 1000,10 和limit 10 速度一样快吗?](###MySQL查询 limit 1000,10 和limit 10 速度一样快吗?)
+
- 2024.5.15,新增[B树和B+树的区别?](###B树和B+树的区别?)
## 什么是MySQL
diff --git "a/docs/database/\344\270\200\346\235\241 SQL \346\237\245\350\257\242\350\257\255\345\217\245\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md" "b/docs/database/\344\270\200\346\235\241 SQL \346\237\245\350\257\242\350\257\255\345\217\245\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md"
new file mode 100644
index 0000000..94d82b5
--- /dev/null
+++ "b/docs/database/\344\270\200\346\235\241 SQL \346\237\245\350\257\242\350\257\255\345\217\245\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md"
@@ -0,0 +1,67 @@
+一条 SQL 查询语句如何执行的
+
+在平常的开发中,可能很多人都是 CRUD,对 SQL 语句的语法很熟练,但是说起一条 SQL 语句在 MySQL 中是怎么执行的却浑然不知,今天大彬就由浅入深,带大家一点点剖析一条 SQL 语句在 MySQL 中是怎么执行的。
+
+比如你执行下面这个 SQL 语句时,我们看到的只是输入一条语句,返回一个结果,却不知道 MySQL 内部的执行过程:
+
+```mysql
+mysql> select * from T where ID=10;
+```
+
+在剖析这个语句怎么执行之前,我们先看一下 MySQL 的基本架构示意图,能更清楚的看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。
+
+
+
+整体来说,MySQL 可以分为 Server 层和存储引擎两部分。
+
+Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
+
+### 连接器
+
+如果要操作 MySQL 数据库,我们必须使用 MySQL 客户端来连接 MySQL 服务器,这时候就是服务器中的连接器来负责根客户端建立连接、获取权限、维持和管理连接。
+
+在和服务端完成 TCP 连接后,连接器就要认证身份,需要用到用户名和密码,确保用户有足够的权限执行该SQL语句。
+
+### 查询缓存
+
+建立完连接后,就可以执行查询语句了,来到第二步:查询缓存。
+
+MySQL 拿到第一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中,如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。
+
+如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。
+
+### 分析器
+
+如果没有命中缓存,就要开始真正执行语句了,MySQL 首先会对 SQL 语句做解析。
+
+分析器会先做 “词法分析”,MySQL 需要识别出 SQL 里面的字符串分别是什么,代表什么。
+
+做完之后就要做“语法分析”,根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。若果语句不对,就会收到错误提醒。
+
+### 优化器
+
+经过了分析器,MySQL 就知道要做什么了,但是在开始执行之前,要先经过优化器的处理。
+
+比如:优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
+
+MySQL 会帮我去使用他自己认为的最好的方式去优化这条 SQL 语句,并生成一条条的执行计划,比如你创建了多个索引,MySQL 会依据**成本最小原则**来选择使用对应的索引,这里的成本主要包括两个方面, IO 成本和 CPU 成本。
+
+### 执行器
+
+执行优化之后的执行计划,在开始执行之前,先判断一下用户对这个表有没有执行查询的权限,如果没有,就会返回没有权限的错误;如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
+
+### 存储引擎
+
+执行器将查询请求发送给存储引擎组件。
+
+存储引擎组件负责具体的数据存储、检索和修改操作。
+
+存储引擎根据执行器的请求,从磁盘或内存中读取或写入相关数据。
+
+### 返回结果
+
+存储引擎将查询结果返回给执行器。
+
+执行器将结果返回给连接器。
+
+最后,连接器将结果发送回客户端,完成整个执行过程。
\ No newline at end of file
diff --git a/docs/framework/springboot/springboot-cross-domain.md b/docs/framework/springboot/springboot-cross-domain.md
index fa7dac3..b93a909 100644
--- a/docs/framework/springboot/springboot-cross-domain.md
+++ b/docs/framework/springboot/springboot-cross-domain.md
@@ -90,4 +90,4 @@ public class AccountController {
6、打卡学习,**大学自习室的氛围**,一起蜕变成长
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/framework/springmvc.md b/docs/framework/springmvc.md
index f0bc2ae..6bf2369 100644
--- a/docs/framework/springmvc.md
+++ b/docs/framework/springmvc.md
@@ -43,8 +43,8 @@ head:
怎么加入[知识星球](https://topjavaer.cn/zsxq/introduce.html)?
-**扫描以下二维码**领取50元的优惠券即可加入。星球定价**218**元,减去**50**元的优惠券,等于说只需要**168**元的价格就可以加入,服务期一年,**每天只要三毛钱**(0.46元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**218**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/java/java-concurrent.md b/docs/java/java-concurrent.md
index e1c611a..09c408f 100644
--- a/docs/java/java-concurrent.md
+++ b/docs/java/java-concurrent.md
@@ -22,7 +22,9 @@ head:
## 线程池
-线程池:一个管理线程的池子。
+### 什么是线程池,如何使用?为什么要使用线程池?
+
+线程池就是事先将多个线程对象放到一个容器中,使用的时候就不用new线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高了代码执行效率。
### 为什么平时都是使用线程池创建线程,直接new一个线程不好吗?
@@ -35,7 +37,7 @@ head:
系统资源有限,每个人针对不同业务都可以手动创建线程,并且创建线程没有统一标准,比如创建的线程有没有名字等。当系统运行起来,所有线程都在抢占资源,毫无规则,混乱场面可想而知,不好管控。
-**频繁手动创建线程为什么开销会大?跟new Object() 有什么差别?**
+### 频繁手动创建线程为什么开销会大?跟new Object() 有什么差别?
虽然Java中万物皆对象,但是new Thread() 创建一个线程和 new Object()还是有区别的。
@@ -733,9 +735,23 @@ class SeasonThreadTask implements Runnable{
## ThreadLocal
+### ThreadLocal是什么
+
线程本地变量。当使用`ThreadLocal`维护变量时,`ThreadLocal`为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程。
-### ThreadLocal原理
+### 为什么要使用ThreadLocal?
+
+并发场景下,会存在多个线程同时修改一个共享变量的场景。这就可能会出现**线性安全问题**。
+
+为了解决线性安全问题,可以用加锁的方式,比如使用`synchronized` 或者`Lock`。但是加锁的方式,可能会导致系统变慢。
+
+还有另外一种方案,就是使用空间换时间的方式,即使用`ThreadLocal`。使用`ThreadLocal`类访问共享变量时,会在每个线程的本地,都保存一份共享变量的拷贝副本。多线程对共享变量修改时,实际上操作的是这个变量副本,从而保证线性安全。
+
+### Thread和ThreadLocal有什么联系呢?
+
+Thread和ThreadLocal是绑定的, ThreadLocal依赖于Thread去执行, Thread将需要隔离的数据存放到ThreadLocal(准确的讲是ThreadLocalMap)中,来实现多线程处理。
+
+### 说说ThreadLocal的原理?
每个线程都有一个`ThreadLocalMap`(`ThreadLocal`内部类),Map中元素的键为`ThreadLocal`,而值对应线程的变量副本。
diff --git a/docs/java/jvm.md b/docs/java/jvm.md
index 9120ef0..5400aac 100644
--- a/docs/java/jvm.md
+++ b/docs/java/jvm.md
@@ -26,8 +26,8 @@
怎么加入[知识星球](https://topjavaer.cn/zsxq/introduce.html)?
-**扫描以下二维码**领取50元的优惠券即可加入。星球定价**218**元,减去**50**元的优惠券,等于说只需要**168**元的价格就可以加入,服务期一年,**每天只要三毛钱**(0.46元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**218**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/other/site-diary.md b/docs/other/site-diary.md
index 426ce57..477801a 100644
--- a/docs/other/site-diary.md
+++ b/docs/other/site-diary.md
@@ -8,6 +8,14 @@ sidebar: heading
## 更新记录
+- 2024.06.11,更新-Redis大key怎么处理?
+
+- 2024.06.11,新增-聊聊如何用Redis 实现分布式锁?
+
+- 2024.06.07,更新-为什么Redis单线程还这么快?
+
+- 2024.05.21,新增一条SQL是怎么执行的
+
- 2023.12.28,[增加源码解析模块,包含Sprign/SpringMVC/MyBatis(更新中)](/source/mybatis/1-overview.html)。
- 2023.12.28,[遭受黑客攻击,植入木马程序](/zsxq/article/site-hack.html)。
diff --git a/docs/redis/redis.md b/docs/redis/redis.md
index 0f2a11c..0890449 100644
--- a/docs/redis/redis.md
+++ b/docs/redis/redis.md
@@ -824,6 +824,95 @@ Redis 的哈希表使用链地址法(separate chaining)来解决键冲突:
原理跟 Java 的 HashMap 类似,都是数组+链表的结构。当发生 hash 碰撞时将会把元素追加到链表上。
+## Redis实现分布式锁有哪些方案?
+
+在这里分享六种Redis分布式锁的正确使用方式,由易到难。
+
+方案一:SETNX+EXPIRE
+
+方案二:SETNX+value值(系统时间+过期时间)
+
+方案三:使用Lua脚本(包含SETNX+EXPIRE两条指令)
+
+方案四::ET的扩展命令(SETEXPXNX)
+
+方案五:开源框架~Redisson
+
+方案六:多机实现的分布式锁Redlock
+
+**首先什么是分布式锁**?
+
+分布式锁是一种机制,用于确保在分布式系统中,多个节点在同一时刻只能有一个节点对共享资源进行操作。它是解决分布式环境下并发控制和数据一致性问题的关键技术之一。
+
+分布式锁的特征:
+
+1、「互斥性」:任意时刻,只有一个客户端能持有锁。
+
+2、「锁超时释放」:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁。
+
+3、「可重入性」“一个线程如果获取了锁之后,可以再次对其请求加锁。
+
+4、「安全性」:锁只能被持有的客户端删除,不能被其他客户端删除
+
+5、「高性能和高可用」:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效。
+
+
+
+**Redis分布式锁方案一:SETNX+EXPIRE**
+
+提到Redis的分布式锁,很多朋友可能就会想到setnx+expire命令。即先用setnx来抢锁,如果抢到之后,再用expire给锁设置一个过期时间,防止锁忘记了释放。SETNX是SETIF NOT EXISTS的简写。日常命令格式是SETNXkey value,如果 key不存在,则SETNX成功返回1,如果这个key已经存在了,则返回0。假设某电商网站的某商品做秒杀活动,key可以设置为key_resource_id,value设置任意值,伪代码如下:
+
+
+
+缺陷:加锁与设置过期时间是非原子操作,如果加锁后未来得及设置过期时间系统异常等,会导致其他线程永远获取不到锁。
+
+**Redis分布式锁方案二**:SETNX+value值(系统时间+过期时间)
+
+为了解决方案一,「发生异常锁得不到释放的场景」,有小伙伴认为,可以把过期时间放到setnx的value值里面。如果加锁失败,再拿出value值校验一下即可。
+
+这个方案的优点是,避免了expire 单独设置过期时间的操作,把「过期时间放到setnx的value值」里面来。解决了方案一发生异常,锁得不到释放的问题。
+
+但是这个方案有别的缺点:过期时间是客户端自己生成的(System.currentTimeMillis()是当前系统的时间),必须要求分布式环境下,每个客户端的时间必须同步。如果锁过期的时候,并发多个客户端同时请求过来,都执行jedis.get()和set(),最终只能有一个客户端加锁成功,但是该客户端锁的过期时间,可能被别的客户端覆盖。该锁没有保存持有者的唯一标识,可能坡别的客户端释放/解锁
+
+**分布式锁方案三:使用Lua脚本(包含SETNX+EXPIRE两条指令)**
+
+实际上,我们还可以使用Lua脚本来保证原子性(包含setnx和expire两条指令),lua脚本如下:
+
+
+
+加锁代码如下:
+
+
+
+**Redis分布式锁方案四:SET的扩展命令(SET EX PX NX)**
+
+除了使用,使用Lua脚本,保证SETNX+EXPIRE两条指令的原子性,我们还可以巧用Redis的SET指令扩展参数。(`SET key value[EX seconds]`PX milliseconds][NX|XX]`),它也是原子性的
+
+`SET key value[EX seconds][PX milliseconds][NX|XX]`
+
+1. NX:表示key不存在的时候,才能set成功,也即保证只有第一个客户端请求才能获得锁,而其他客户端请求只能等其释放锁, 才能获取。
+2. EXseconds:设定key的过期时间,时间单位是秒。
+3. PX milliseconds:设定key的过期时间,单位为毫秒。
+4. XX:仅当key存在时设置值。
+
+伪代码如下:
+
+
+
+**Redis分布式锁方案五:Redisson框架**
+
+方案四还是可能存在「锁过期释放,业务没执行完」的问题。设想一下,是否可以给获得锁的线程,开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放。当前开源框架Redisson解决了这个问题。一起来看下Redisson底层原理图:
+
+
+
+只要线程一加锁成功,就会启动一个watchdog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。因此,Redisson就是使用Redisson解决了「锁过期释放,业务没执行完」问题。
+
+**分布式锁方案六:多机实现的分布式锁Redlock+Redisson**
+
+前面五种方案都是基于单机版的讨论,那么集群部署该怎么处理?
+
+答案是多机实现的分布式锁Redlock+Redisson
+

diff --git a/docs/system-design/README.md b/docs/system-design/README.md
index 4ea61d7..dac1d6d 100644
--- a/docs/system-design/README.md
+++ b/docs/system-design/README.md
@@ -24,4 +24,4 @@
[知识星球](https://topjavaer.cn/zsxq/introduce.html)**加入方式**:
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/inner-material.md b/docs/zsxq/inner-material.md
index 536c880..613a61e 100644
--- a/docs/zsxq/inner-material.md
+++ b/docs/zsxq/inner-material.md
@@ -22,4 +22,4 @@
[知识星球](https://topjavaer.cn/zsxq/introduce.html)**加入方式**:
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/introduce.md b/docs/zsxq/introduce.md
index 7e2d967..a72a60d 100644
--- a/docs/zsxq/introduce.md
+++ b/docs/zsxq/introduce.md
@@ -73,7 +73,7 @@ APP端页面如下(建议大家**使用APP**,因为APP布局更加美观,
如果你加入了,希望你也能跟像球友们一样**每天坚持打卡学习,为未来奋斗**~
-
+
## 学习圈能提供什么?
@@ -205,10 +205,10 @@ APP端页面如下(建议大家**使用APP**,因为APP布局更加美观,
## 怎么进入星球?
-如果你下定决心要加入的话,可以直接扫下面这个二维码。星球定价**218**元,减去**50**元的优惠券,等于说只需要**168**元(**拒绝割韭菜**)的价格就可以加入,服务期一年,**每天只要三毛钱**(0.46元),相比培训班几万块的学费,非常值了,星球提供的服务**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**218**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
-PS:如果加入学习圈之后觉得不合适,**支持3天内全额退款**~
+PS:如果加入学习圈之后觉得不合适,**支持3天内全额退款**
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/mianshishouce.md b/docs/zsxq/mianshishouce.md
index 287488c..24d1368 100644
--- a/docs/zsxq/mianshishouce.md
+++ b/docs/zsxq/mianshishouce.md
@@ -76,10 +76,10 @@
## 怎么进入星球?
-如果你下定决心要加入的话,可以直接扫下面这个二维码。星球定价**158**元,减去**50**元的优惠券,等于说只需要**108**元(**拒绝割韭菜**)的价格就可以加入,服务期一年,**每天不到三毛钱**(0.29元),相比培训班几万块的学费,非常值了,星球提供的服务**远超**门票价格了。
+**扫描以下二维码**领取50元的优惠券即可加入。星球定价**188**元,减去**50**元的优惠券,等于说只需要**138**元的价格就可以加入,服务期一年,**每天只要4毛钱**(0.37元),相比培训班几万块的学费,非常值了,星球提供的服务可以说**远超**门票价格了。
-随着星球内容不断积累,星球定价也会不断**上涨**,所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
+随着星球内容不断积累,星球定价也会不断**上涨**(最初原价**68**元,现在涨到**188**元了,后面还会持续**上涨**),所以,想提升自己的小伙伴要趁早加入,**早就是优势**(优惠券只有50个名额,用完就恢复**原价**了)。
PS:如果加入学习圈之后觉得不合适,**支持3天内全额退款**~
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/question/2-years-tech-no-upgrade.md b/docs/zsxq/question/2-years-tech-no-upgrade.md
index 3bf789f..b4eccf3 100644
--- a/docs/zsxq/question/2-years-tech-no-upgrade.md
+++ b/docs/zsxq/question/2-years-tech-no-upgrade.md
@@ -58,4 +58,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券即可加入~
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/question/3-years-confusion.md b/docs/zsxq/question/3-years-confusion.md
index 7fde282..1888eda 100644
--- a/docs/zsxq/question/3-years-confusion.md
+++ b/docs/zsxq/question/3-years-confusion.md
@@ -89,5 +89,5 @@ head:
6、打卡学习,**大学自习室的氛围**,一起蜕变成长
-
+
diff --git a/docs/zsxq/question/frontend-or-backend.md b/docs/zsxq/question/frontend-or-backend.md
index b33ccf4..35e6f0c 100644
--- a/docs/zsxq/question/frontend-or-backend.md
+++ b/docs/zsxq/question/frontend-or-backend.md
@@ -31,4 +31,4 @@
最后,给大家送福利啦,限时发放10张[知识星球](https://mp.weixin.qq.com/s/6eAOmYiNhEjIvhhXoXm9QQ)60元的优惠券,先到先得!目前[知识星球](https://mp.weixin.qq.com/s/6eAOmYiNhEjIvhhXoXm9QQ)已经有**300**多位成员了,想加入的小伙伴不要错过这一波优惠活动,**扫描下方二维码**领取优惠券即可加入。
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/zsxq/question/how-to-prepare-job-hopping.md b/docs/zsxq/question/how-to-prepare-job-hopping.md
index 0dea290..59aee75 100644
--- a/docs/zsxq/question/how-to-prepare-job-hopping.md
+++ b/docs/zsxq/question/how-to-prepare-job-hopping.md
@@ -85,4 +85,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券加入(**即将恢复原价**)~
-
+
diff --git a/docs/zsxq/question/java-or-bigdata.md b/docs/zsxq/question/java-or-bigdata.md
index d3bbf32..cf98ec1 100644
--- a/docs/zsxq/question/java-or-bigdata.md
+++ b/docs/zsxq/question/java-or-bigdata.md
@@ -59,4 +59,4 @@ head:
**加入方式**:**扫描二维码**领取优惠券加入(**即将恢复原价**)~
-
+
diff --git "a/docs/zsxq/\347\272\277\344\270\212CPU\351\243\231\345\215\207100%\351\227\256\351\242\230\346\216\222\346\237\245.md" "b/docs/zsxq/\347\272\277\344\270\212CPU\351\243\231\345\215\207100%\351\227\256\351\242\230\346\216\222\346\237\245.md"
new file mode 100644
index 0000000..57a099a
--- /dev/null
+++ "b/docs/zsxq/\347\272\277\344\270\212CPU\351\243\231\345\215\207100%\351\227\256\351\242\230\346\216\222\346\237\245.md"
@@ -0,0 +1,95 @@
+线上CPU飙升100%问题排查
+
+对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),特此整理排查方法一篇,供大家参考讨论提高。
+
+## 二、问题复现
+
+线上系统突然运行缓慢,CPU飙升,甚至到100%,以及Full GC次数过多,接着就是各种报警:例如接口超时报警等。此时急需快速线上排查问题。
+
+## 三、问题排查
+
+不管什么问题,既然是CPU飙升,肯定是查一下耗CPU的线程,然后看看GC。
+
+### 3.1 核心排查步骤
+
+1.执行“top”命令``:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。``
+
+2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。
+
+3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
+
+4.执行 “jstack 进程号 | grep 线程ID” 查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
+
+5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
+
+6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多
+
+### 3.2 原因分析
+
+#### 1.内存消耗过大,导致Full GC次数过多
+
+执行步骤1-5:
+
+- 多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
+- 通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
+
+确定是Full GC,接下来找到**具体原因**:
+
+- 生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
+- 内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。
+
+#### 2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;
+
+执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。
+
+#### 3.由于锁使用不当,导致死锁。
+
+执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。
+
+造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
+
+#### 4.随机出现大量线程访问接口缓慢。
+
+代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
+
+思路:
+
+首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
+
+执行步骤1-4:
+
+```
+"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]
+
+ java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待
+
+ at java.lang.Thread.sleep(Native Method)
+
+ at java.lang.Thread.sleep(Thread.java:340)
+
+ at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
+
+ at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
+```
+
+如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。
+
+#### 5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
+
+执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS->LockSupport.park()。
+
+```
+"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]
+java.lang.Thread.State: WAITING (parking) ->无期限等待
+at sun.misc.Unsafe.park(Native Method)
+at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
+at com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点
+at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)
+at java.lang.Thread.run(Thread.java:748)
+```
+
+
+
+## 四、总结
+
+按照3.1节的6个步骤走下来,基本都能找到问题所在。
\ No newline at end of file