八股
MQ怎么保证消费者顺序的?
Redis为什么这么快
- 内存数据库
- c语言实现
- 优化过的数据结构
- 单线程,避免多线切换的开销
- I/O多路复用 一个线程处理多个I/O
Redis大key问题
大key是value过大
造成的问题:会造成堵塞
解决方案:拆分大key,删除大key(不能用del,在redis6.0之后可以用unlock)
Redis基本数据结构
string
list
hash
set
zset
Bitmaps
HyperLogLog
Geospatial
跳表
删除、插入、查找都是logN
相比平衡树、红黑树效率差不多,但是红黑树实现更复杂。跳表不稳定。
项目中Redis如何更新的?怎么保证缓存一致性
雪崩、击穿、穿透
给缓存业务添加降级限流策略。
缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key ,击穿是某一个 key 缓存。
解决方案主要是可以将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
雪崩:大量的key同时过期或者redis宕机。
穿透无中生有 key ,布隆过滤 null 隔离
缓存击穿过期 key ,锁与非期解难题。
雪崩大量过期 key ,过期时间要随机。
面试必考三兄弟,可用限流来保底。
Mysql
索引失效场景
使用like 左模糊匹配 左右模糊匹配
条件查询中,对索引列进行表达式计算
条件查询中,对索引列使用函数 length(name)
对索引列进行字符串=数字比较
联合索引,遵循最左原则
where子句中,or前是索引列,or后不是索引列
储存引擎
InnoDB,会默认为主键建立索引,称为聚簇索引,其他的索引叫做二级索引。
都是B+树。
聚簇索引:叶子节点 实际数字
二级索引:叶子节点 主键
MyISAM:不支持事务,也不支持行级锁和外键约束。
Memery:就是将数据放在内存中,数据处理速度很快,但是安全性不高。
日志文件:
binlog:
redolog:
undolog
relaylog
事务隔离级别
脏读
不可重复度
幻读
隔离级别:
读未提交:指一个事务还没提交时,它做的变更就能被其他事务看到
读提交:指一个事务提交之后,它做的变更才能被其他事务看到
可重复读:指一个事务执行级别过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,Mysql InnoDB引擎的默认隔离级别
串行化:会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
JAVA
HashMap的结构
HashMap数据结构是数组和链表,HashMap通过哈希算法将元素的键(key)映射到数组中的槽位(Bucket)。如果多个键映射到同一个槽位,他们会以链表的形式存储在同一个槽位上。
当一个链表长度超过8的时候,就转成红黑树。因为链表查询是O(n)。
ArrayList LinkeList:
ArrayList 适用于频繁访问集合元素的场景,基于数组实现。
LinkedList适用于频繁插入删除和删除的场景,大小经常改变。
ArrayList扩容 1.5倍
计算新的容量、创建新的数组、复制、更新引用、完成扩容。
Linux 常用命令
文件和目录操作
ls
:列出目录内容。
ls -l
:以长格式显示文件详细信息,包括文件权限、所有者、大小、修改时间等。例如ls -l /home/user/Documents
会详细列出/home/user/Documents
目录下的文件信息。ls -a
:显示所有文件,包括隐藏文件(以 “.” 开头的文件)。
cd:切换目录。例如
cd /home/user/Downloads
会将当前工作目录切换到/home/user/Downloads
。pwd:显示当前工作目录的绝对路径。
mkdir:创建目录。如
mkdir new_folder
会在当前目录下创建一个名为new_folder
的新目录。rmdir:删除空目录。若目录非空,需要先删除目录中的文件。
rm:删除文件或目录。
rm -r
用于递归删除目录及其内容。例如rm -r old_folder
会删除old_folder
目录及其内部的所有文件和子目录。
文件查看和编辑
- cat:查看文件内容。如
cat file.txt
会将file.txt
的内容输出到终端。 - less:分页查看文件内容,按空格键翻页,按 “q” 键退出。适合查看大型文件。例如
less big_file.log
。 - vim或nano:文本编辑器。在
vim
中,按 “i” 键进入插入模式进行编辑,按 “Esc” 键退出插入模式,然后输入 “:wq” 保存并退出,“:q!” 强制退出不保存。nano
相对更简单,编辑后按 “Ctrl + O” 保存,按 “Ctrl + X” 退出。
- cat:查看文件内容。如
系统信息查看
- uname:显示系统信息。
uname -a
会输出内核名称、主机名、内核版本等详细信息。 - top:实时查看系统资源使用情况,包括 CPU、内存、进程等的使用信息。按 “q” 键退出。
- df:查看磁盘空间使用情况。
df -h
以人类可读的方式(如 KB、MB、GB)显示磁盘使用量。
- uname:显示系统信息。
进程管理
- ps:查看进程状态。
ps -ef
显示所有进程的详细信息,包括 UID、PID、PPID 等。 - kill:终止进程。例如
kill PID
(将 “PID” 替换为要终止的进程 ID)可以终止指定的进程,kill -9 PID
是强制终止进程。
- ps:查看进程状态。
文件权限管理
- chmod:改变文件或目录的权限模式。例如
chmod 755 file.txt
会将file.txt
的权限设置为所有者有读、写、执行权限,所属组和其他用户有读、执行权限。 - chown:改变文件或目录的所有者。如
chown user:group file.txt
将file.txt
的所有者设置为 “user”,所属组设置为 “group”。
- chmod:改变文件或目录的权限模式。例如
Git 常用命令
- 仓库初始化和克隆
- git init:在当前目录初始化一个新的 Git 仓库。例如在一个新的项目文件夹中执行
git init
,就可以开始使用 Git 管理该项目的版本。 - git clone [repository URL]:克隆远程仓库到本地。比如
git clone https://github.com/user/repository.git
会将远程仓库https://github.com/user/repository.git
克隆到本地。
- git init:在当前目录初始化一个新的 Git 仓库。例如在一个新的项目文件夹中执行
- 文件操作
- git add [file or directory]:将文件或目录添加到暂存区。例如
git add file.txt
将file.txt
添加到暂存区,准备提交;git add.
会将当前目录下的所有文件(除了被忽略的文件)添加到暂存区。 - git commit -m “[commit message]”:提交暂存区的文件到本地仓库,并附上提交信息。如
git commit -m "Initial commit"
是进行初次提交并附上提交说明 “Initial commit”。
- git add [file or directory]:将文件或目录添加到暂存区。例如
- 分支操作
- git branch:查看本地分支。带参数
git branch [branch - name]
可以创建新分支。例如git branch new - branch
创建一个名为new - branch
的新分支。 - git checkout [branch - name]:切换分支。比如
git checkout master
会切换到master
分支。 - git merge [branch - name]:合并分支。假设在
feature - branch
上完成了功能开发,在master
分支执行git merge feature - branch
可以将feature - branch
的内容合并到master
分支。
- git branch:查看本地分支。带参数
- 远程仓库操作
- git remote add [remote - name] [remote - repository - URL]:添加远程仓库。例如
git remote add origin https://github.com/user/repository.git
添加一个名为origin
的远程仓库。 - git push [remote - name] [branch - name]:将本地分支推送到远程仓库。如
git push origin master
将本地master
分支推送到名为origin
的远程仓库。 - git pull [remote - name] [branch - name]:从远程仓库拉取更新并合并到本地分支。例如
git pull origin master
从origin
远程仓库的master
分支拉取更新。
- git remote add [remote - name] [remote - repository - URL]:添加远程仓库。例如
Docker 常用命令
- 镜像操作
- docker pull [image - name]:从镜像仓库拉取镜像。例如
docker pull ubuntu:latest
会拉取最新版本的 Ubuntu 镜像。 - docker images:列出本地所有的 Docker 镜像,显示镜像的仓库名、标签、镜像 ID、创建时间和大小等信息。
- docker rmi [image - ID or image - name]:删除本地镜像。例如
docker rmi ubuntu:latest
删除本地的ubuntu:latest
镜像;也可以通过镜像 ID 来删除。
- docker pull [image - name]:从镜像仓库拉取镜像。例如
- 容器操作
- docker run -it [image - name] [command]:创建并运行一个容器。
-i
表示保持标准输入打开,-t
分配一个伪终端。例如docker run -it ubuntu:latest /bin/bash
会创建一个基于ubuntu:latest
镜像的容器,并在容器中运行/bin/bash
命令,让用户可以在容器内进行交互操作。 - docker ps:查看正在运行的容器,
docker ps -a
查看所有容器(包括已停止的)。显示容器的 ID、名称、创建时间、状态等信息。 - docker stop [container - ID or container - name]:停止运行中的容器。例如
docker stop my_container
停止名为my_container
的容器。 - docker start [container - ID or container - name]:启动已停止的容器。
- docker exec -it [container - ID or container - name] [command]:在运行的容器中执行命令。如
docker exec -it my_container /bin/bash
可以进入名为my_container
的容器并打开一个新的bash
终端。 - docker rm [container - ID or container - name]:删除容器。注意,只能删除已停止的容器,除非使用
docker rm -f
强制删除正在运行的容器。
- docker run -it [image - name] [command]:创建并运行一个容器。
Tmux 常用命令
会话管理
- tmux:启动
Tmux
并创建一个新的会话。 - tmux new-session - s [session - name]:创建一个名为
[session - name]
的新会话。例如tmux new - session - s my_session
。 - tmux ls:列出所有的
Tmux
会话。 - tmux attach-session - t [session - name]:连接到指定名称的会话。如
tmux attach - session - t my_session
连接到my_session
会话。 - tmux kill - session - t [session - name]:杀死指定名称的会话。例如
tmux kill - session - t unused_session
删除unused_session
会话。
- tmux:启动
窗口和窗格操作
- Ctrl + b c:在当前会话中创建一个新窗口。
- Ctrl + b n:切换到下一个窗口。
- Ctrl + b p:切换到上一个窗口。
- Ctrl + b &:关闭当前窗口。
- Ctrl + b “:垂直分割窗格。
- Ctrl + b %:水平分割窗格。
- Ctrl + b o:在窗格之间切换。
- Ctrl + b x:关闭当前窗格。
设置鼠标上下滚动:
tmux set -g mouse on
- 粘贴:
左键选中,然后ctrl+shift+c
HashMap的数据结构,线程安全么,有没有什么并发安全的HashMap。
volatitle关键字原理。
volatitle 是 Java 提供的一种轻量级的同步机制。 Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于 synchronized (synchronized*称为重量级锁), volatile 更轻量级,因为它不会引起线程上下文的切换和调度。但是 volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。
并发安全
创建线程的方式
继承Thread类
实现runnable接口
实现callable接口
线程池创建线程
Runable和Callable有什么区别
Runnable
接口的run
方法无返回值且不能抛出受检异常
Callable
接口的call
方法有返回值且能抛出异常
使用Runable实现Callable功能
使用 FutureTask 包装 Runnable
- 原理:
FutureTask
类实现了RunnableFuture
接口,而RunnableFuture
接口继承了Runnable
和Future
接口。通过将Runnable
任务包装在FutureTask
中,可以获得一个具有返回值的Future
对象,从而模拟Callable
的功能
自定义实现类
- 原理:创建一个自定义类实现
Runnable
接口,并在类中定义一个成员变量来存储任务的结果,通过在run
方法中执行任务逻辑并将结果存储到成员变量中,然后提供一个方法来获取该结果,以此实现类似Callable
的功能。
常见的阻塞队列
ArrayBlockingQueue:基于数组的有界阻塞队列。
LinkedBlockingQueue:基于链表的可选有界阻塞队列。
PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
DelayQueue:一个使用优先级队列实现的无界阻塞队列
SynchronousQueue:一个不存储元素的阻塞队列
保证线程原子性:
使用 synchronized 关键字
保证可见性的方法
使用 volatile 关键字
Synchronize和Volatile关键字原理
线程池
核心线程数
线程池种类
ThreadLocal
单例模式
package com.wyj.singleton;
class SingleObject {
//创建一个SingleObject对象
// 用static 关键字修饰 表示该变量为静态变量 该类所有对象所共享的一个变量
//下方static方法中 不能调用非Static属性
private static SingleObject getInstance = new SingleObject();
private String name;
//让其构造函数为private,那么他不会被实例化
private SingleObject (){
}
//获取唯一可用的对象
// 这里用static关键字修饰的话, 当该静态方法被调用时该类就会被类加载
public static SingleObject getSingleObject() {
return getInstance;
}
void say() {
System.out.println("hello");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class singleDemo {
public static void main(String[] args) {
// 我们并没有去new一个实例,而是调用了该实例的 自己建造实例的方法
SingleObject object = SingleObject.getSingleObject();
SingleObject object2 = SingleObject.getSingleObject();
object.setName("wyj");
object2.setName("www");
System.out.println(object.getName());
}
}