Skip to content

Commit

Permalink
文章更新
Browse files Browse the repository at this point in the history
  • Loading branch information
lizhifuabc committed May 10, 2024
1 parent e3ab334 commit c1107ed
Show file tree
Hide file tree
Showing 29 changed files with 3,856 additions and 3,546 deletions.
17 changes: 12 additions & 5 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { defaultTheme } from 'vuepress'
import { defaultTheme } from '@vuepress/theme-default'
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'

export default {
import { defineUserConfig } from 'vuepress'
import type { DefaultThemeOptions } from 'vuepress'
import { viteBundler } from '@vuepress/bundler-vite'


export default defineUserConfig({
lang: 'zh-CN',
title: '拔土豆的程序员',
description: '没进过大厂|技术一般|创业被坑|普普通通程序员',
// markdown设置
markdown:{
lineNumbers: true, // 代码块行号
},
theme : defaultTheme( {
bundler: viteBundler(),
theme : defaultTheme({
logo: '/images/logo.png',
// 添加导航栏
navbar: [
Expand Down Expand Up @@ -55,9 +61,10 @@ export default {
{ text: '支付系统', link: '/pay/' },
{ text: '工具集',
children: [
{text: 'Docker',link:'/tools/Docker/'},
{text: 'Arthas',link:'/tools/arthas/'},
{text: 'Mac软件',link:'/tools/mac/'},
{text: 'Maven',link:'/tools/maven/'},
{text: 'Docker',link:'/tools/Docker/'},
{text: 'Git',link:'/tools/git/'},
{text: 'IntelliJ IDEA',link:'/tools/idea/'},
{text: '效率工具',link:'/tools/help/'},
Expand All @@ -75,4 +82,4 @@ export default {
appId: '78IVUHUF7Z',
}),
],
}
})
69 changes: 69 additions & 0 deletions docs/Interview/2024年05月08日.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 2024年05月08日



- kafka如何保证顺序消费,假如:一个房间ID1001,产成大量的数据,如何顺序存储到kafka,如何保证消费端多线程消费的时候也是保证顺序的

kafka没用过,主要是使用的rabbitmq,对于需要保证顺序消费的业务,可以只部署一个消费者实例,然后设置 RabbitMQ 每次只推送一个消息,再开启手动 ack 即可。多个消费者实例,我不会。

- Redis中用set数据结构,存储了10w左右的数据,如何合理的获取出来

bigKey 数量太多了所以不能用命令全部取出 可以用sscan命令一点点去读取。京东有个开源的 bigKey 探测系统。

- A,B,C三个字段,创建联合索引,说一下可能走索引的所有情况的sql,越多越好

abc ,ab,a,ac(abc字段都在,无论顺序如何都会走索引,ab,ac,a会部分走索引,其他情况不走索引)

- 区分度高的字段放在前面,区分度低的字段放后面
- 最左前缀,联合索引遇到范围匹配会停止,不会再匹配后面的索引字段
- MySQL优化器为了适应索引,会调整条件的顺序。
- 怎么判断是用到了3个字段的索引,而不是只用到前两个字段的索引呢?有个非常简单的方法,看执行计划的索引长度。

- 线上有什么问题的处理令你很深刻吗,介绍一下

随便编了一个:正则表达式回溯的问题。

- Redisson的watchDog,底层的源码有了解吗,说下抢到锁的线程执行流程,以及没有抢到锁的线程如何进行处理的

watchdog 就是jdk会起一个定时任务 每10s(没记错的话)会去执行:看下key还存在吗 存在的话进行一个续签。因为redisson在进行lock的时候 如果你没有设置超时时间 它会默认设置30s的过期(为了让你的服务挂了之后 锁能释放掉)watchdog就是为了让这个30s能不断的续签下去(如果你的服务挂了 watchdog自然就不会执行了)

如果抢到锁,整个lock就结束了。如果没有抢到锁的话。首先会注册监听一个redis的一个释放锁的事件并将自己阻塞掉(目的是为了不占用cpu,阻塞自己让出cpu给别的线程执行)。当收到锁释放消息的时候 就会进入一个while 进行自选尝试去获取锁(如果设置了过期时间的话 还会判断是否已经超时 超时也会直接结束)。获取获取到 就结束 还是没获取到 自己会根据获取的到ttl跟waitime 进行比较取一个较小值用于创建有一个信号量 再将自己阻塞掉。等时间到了 在在这个while循环里面在进行上面的步骤 直到获取锁 或者 超时(如果有设置waitTime的话)

- b树,b+树的特点,以及优缺点

B树的特点的 非叶子节点也会有数据存储。而B+树的话 数据只会在叶子节点上。如此的话所以 B+树的层级会小点而且数据都在叶子节点所以查询的所要经过的层级都一样所以查询的速度更文档。还有叶子节点都同一层,相互之间有关联形成了链表结果 对范围查找的速度会更快

- 处理过线上的内存泄露的情况吗,说下你的应急方案以及处理方法

确定是内存泄漏还是内存溢出啊,泄漏的话 你应该感觉不出来,只有内存泄漏导致了内存溢出了 你去查原因 才会发现内存泄漏的问题。如果是溢出的话。简单点 你可以先用 jstat -gcutil 看下fgc的情况 如果很频繁的话 用 jmap -histo:live 看下前几个存活的对象有多少 如果有个对象占比很多的话 就是这个对象内存溢出了 可能是哪里list或者map存储着 要看下代码 这个对象的引用。如果看不出来的话 只能打印内存快照生产 hprof文件 在用mat之类的工具分析

- 线上CPU100%问题的排查,如何处理和定位

- top 查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。
- top -Hp 进程号 查看java进程下的所有线程占CPU的情况。
- printf "%x\n 10 后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
- jstack 进程号 | grep 线程ID 线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
- jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
- jmap -dump:format=b,file=filename 进程ID导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多。

- java中的锁默认是什么模式,java设计者为什么设计锁的默认方式为非公平锁

- 恢复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU空闲状态时间
- 使用多线程很重要的考量点是线程切换的开销,当采用非公平锁时,当1个线程请求锁获取同步状态,然后释放同步状态,因为不需要考虑是否还有前驱节点,所以刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销
- 为了更高的吞吐量,非公平锁是比较合适的,因为节省很多线程切换时间,吞吐量自然就上去了; 否则那就用公平锁,大家公平使用。

- 线程池的核心参数有哪些,如果提交一个任务到线程池,创建的线程数是多少,如何保证线程池的线程进行存活的机制,结合源码讲一下

- MVCC机制实现原理,数据结构以及实现

mysql表中每行列都有2个隐藏列 分别保存了 对应的事务id和redo log日志的索引。每当对数据进行修改时 修改后redo log日志的索引会指向老的数据。这样才形成了 redo日志的版本链, 版本链和readview 才实现了mvcc。才实现了mysql的可重复读和读已提交2个事务隔离级别。readview的话 有几个重要的结构:当前事务、事务id数组(包含目前活跃的事务id)最小事务id、最大事务id。然后还要说清楚readview的运行逻辑。 其实这个还是八股 就是之前我提到的 mysql的ACID是如何实现的中的事务相关内容。可以多背背

- 说下零拷贝的原理,零拷贝的实现方式有那些,那些系统运用到了零拷贝

零拷贝就是没有把数据从一个存储区域拷贝到另一个存储区域。

- DDD

- 说下DDD的核心思想是什么,你们落地是采用的那种模式,战略方式,战术方式了解吗,说下俩种方式的区别
- 你们DDD架构的包结构以及每个包的职能划分,调用如何设计得
- DDD设计过程中,你们如何设计核心领域,子领域,领域边界的
5 changes: 5 additions & 0 deletions docs/Interview/2024年05月10日.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 2024年05月10日

- HashMap 的经典设计有什么


1 change: 1 addition & 0 deletions docs/Interview/HashMap扫盲.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# HashMap扫盲
9 changes: 9 additions & 0 deletions docs/Interview/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 记录自己遇到过的面试题

随便记录自己在面试过程中遇到的一些题目。

[HashMap扫盲](./HashMap扫盲.md)

[2024年05月08日](./2024年05月08日.md)

[2024年05月10日](./2024年05月10日.md)
11 changes: 7 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ home: true
# Public 文件路径
heroImage: /images/logo.png
actions:
- text: 写点什么
link: /started/
- text: ← 面试遇到的题
link: /Interview/
type: primary
- text: 几个项目 →
- text: ← 写点什么 →
link: /started/
type: se
- text: ← 几个项目 →
link: /guide/
type: secondary
type: primary
features:
- title: 宗旨
details: 三天打鱼,两天晒网。
Expand Down
6 changes: 6 additions & 0 deletions docs/database/mysql/MySQL-FOR-UPDATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# select for update

总结:

1. select for update 除了有查询的作用外,还会加一个悲观锁。
2. 没用索引/主键的话就是表锁,否则就是是行锁。
170 changes: 170 additions & 0 deletions docs/database/mysql/MySQL-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# MySQL-explain

EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。

![image-20240418203448169](./image/image-20240418203448169.png)

## 常见优化方案

- 索引失效,没有充分利用到索引:创建索引
- 关联查询太多JOIN(尽量减少此类操作):SQL优化
- 数据过多:分库分表
- 服务器调/优及各个参数设置(缓冲、线程数等):调整my.cnf

## 回表

- 索引的列在 select 所需获得的列中(因为在 mysql 中索引是根据索引列的值进行排序的,所以索引节点中存在该列中的部分值)或者根据一次索引查询就能获得记录就不需要回表
- select 所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表。

![image-20240419101435362](./image/image-20240419101435362.png)

## 索引覆盖

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。explain的输出结果Extra字段为Using index时,能够触发索引覆盖。将被查询的字段,建立到联合索引里去。

## id

select 的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的。

MySQL将 select 查询分为简单查询(SIMPLE)和复杂查询(PRIMARY)。

复杂查询:

- 简单子查询、派生表(from语句中的子查询)、union 查询。
- id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

## select_type

select_type 表示对应行是简单还是复杂的查询,如果是复杂的查询,又是上述三种复杂查询中的哪一种。

1. simple简单查询。查询不包含子查询和union

2. primary:复杂查询中最外层的 select
3. subquery:包含在 select 中的子查询(不在 from 子句中)
4. derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)。
5. union:在 union 中的第二个和随后的 select
6. union result:从 union 临时表检索结果的 select

## table

单表:显示这一行的数据是关于哪张表的。

```
explain select * from practice_history where id = 1780924119466397697;
```

![image-20240419100034086](./image/image-20240419100034086.png)

多表关联:驱动表和被驱动表。(内连接时,MySQL性能优化器会自动判断哪个表是驱动表,哪个表示被驱动表,和书写的顺序无关)

![image-20240419100213996](./image/image-20240419100213996.png)

子查询时:table列是格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。

当有 union 时,UNION RESULT 的 table 列的值为`<union1,2>`,1和2表示参与 union 的 select 行id。

## type

表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。

最优到最差分别为:system > const > eq_ref > ref > range > index > ALL 一般来说,得保证查询达到range级别,最好达到ref

- NULL值:

mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表。

- const(system):

mysql能对查询的某部分进行优化并将其转化成一个常量(可以看show warnings 的结果)。用于 primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。

system是const的特例,表里只有一条元组匹配时为system。

- eq_ref:

primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。

这可能是在 const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。

- ref:

相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。

简单 select 查询:普通索引(非唯一索引)

关联表查询:联合索引

- range:

范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

- index:

扫描全表索引,这通常比ALL快一些。(index是从索引中读取的,而all是从硬盘中读取)

- ALL:全表扫描,mysql需要从头到尾去查找所需要的行。**需要增加索引来进行优化**

![image-20240419100936159](./image/image-20240419100936159.png)

![image-20240419101231932](./image/image-20240419101231932.png)

## possible_keys

这一列显示查询可能使用哪些索引来查找。

explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。

## key

这一列显示mysql实际采用哪个索引来优化对该表的访问。

如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。

## key_len

这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

## Extra 额外信息

- Using index:查询的列被索引覆盖,并且where筛选条件是索引的前导列,是性能高的表现。一般是使用了覆盖索引(索引包含了所有查询的字段)。对于innodb来说,如果是辅助索引性能会有不少提高

- Using where:查询的列未被索引覆盖,where筛选条件非索引的前导列

- Using where Using index:查询的列被索引覆盖,并且where筛选条件是索引列之一但是不是索引的前导列,意味着无法直接通过索引查找来查询到符合条件的数据

- NULL:查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引

```sql
explain
select *
from biphon_exam.practice_history where question_bank_id in(select id from biphon_exam.question_bank t2 where t2.id = 1745688198517374978);

explain
select t1.id
from biphon_exam.practice_history t1 where question_bank_id in(select id from biphon_exam.question_bank t2 where t2.id = 1745688198517374978);
```

![image-20240419101435362](./image/image-20240419101435362.png)

![image-20240419101454389](./image/image-20240419101454389.png)

- Using index condition:与Using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围;

- Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。

- Using filesort:mysql 会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时mysql会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化的。

- Using join buffer (hash join):使用了连接缓冲(哈希连接)。

- no matching row in const table:使用唯一索引查询不到记录。

![image-20240419100557344](./image/image-20240419100557344.png)







> https://juejin.cn/post/7305235970285305867?utm_source=gold_browser_extension#heading-3
6 changes: 6 additions & 0 deletions docs/database/mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

## 小技巧

[MySQL-explain](./MySQL-explain.md)

[MySQL-limit优化](./MySQL-limit优化.md)

[MySQL-count用法分析](./MySQL-count用法分析.md)
Expand All @@ -27,3 +29,7 @@
[MySQL更新优化](./MySQL更新优化.md)

[MySQL主键](./MySQL主键.md)

## 面经

[select for update](./MySQL-FOR-UPDATE.md)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions docs/database/nosql/击穿穿透雪崩.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# 击穿、穿透、雪崩
# 缓存穿透、缓存击穿、缓存雪崩

使用缓存的过程中会存在各种各样的问题,以下简单介绍几种常见的问题。

## 缓存雪崩

缓存机器意外发生了全盘宕机,所有并发流量就会直接到达数据库,此时就算重启数据库,也会被流量给打死。
某个时间点,大量缓存同时失效或被清空,导致大量请求直接打到数据库或后端系统,造成系统负载激增,甚至引发系统崩溃,此时就算重启数据库,也会被流量给打死。

![image-20230910171726917](image/image-20230910171726917.png)

简单解决方案
Redis 故障

- 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
- 事中:本地 ehcache 缓存 + 限流&降级,避免 MySQL 被打死。
Expand All @@ -19,6 +19,13 @@
- 限流组件确保了每秒只有多少个请求能通过,保障数据库的安全。
- 用户的请求不会被完全处理。

缓存键同时失效:

- 过期时间随机化:设置缓存的过期时间,加上一个随机值,避免同一时间大量缓存失效。
- 使用多级缓存:引入多级缓存机制,如本地缓存和分布式缓存相结合,减少单点故障风险。
- 缓存预热:系统启动时提前加载缓存数据,避免大量请求落到冷启动状态下的数据库。
- 加互斥锁:保证同一时间只有一个请求来构建缓存,别的只能等它构建完成再从缓存中读取。

## 缓存穿透

1. 查询某个Key对应的数据,Redis缓存中没有相应的数据
Expand Down
Loading

0 comments on commit c1107ed

Please sign in to comment.