【面试总结大纲】

面试

1. spring

Spring AOP的具体实现

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP 就是基于动态代理的,
有实现接口的对象,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,
而对于没有实现接口的对象, Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理

开发有两种方式,XML 和注解

核心概念分别指的是什么?

Spring的AOP是对一个类的方法在不进行任何修改的前提下实现增强,这些方法我们给起了一个名字叫连接点
需要增强的方法我们给起了一个名字叫切入点
存放共性功能的方法,我们给起了个名字叫通知
通知和切入点之间的关系描述,我们给起了个名字叫切面
方法不能独立存在需要被写在一个类中,这个类我们也给起了个名字叫通知类

基于注解的切面实现主要包括以下几个步骤:

  1. 定义切面类:在切面类上使用 @Aspect 注解来标识该类为切面类,同时在该类中定义切点和通知等信息。
  2. 定义切点:在切面类中使用 @Pointcut 注解来定义切点,切点是一个表达式,用于描述哪些连接点应该被拦截。
  3. 定义通知:在切面类中定义通知方法,通知方法使用 @Before、@After、@AfterReturning、@AfterThrowing 或@Around 等注解来标识通知类型,同时可以使用 JoinPoint 参数来获取连接点的信息。
  4. 在Spring配置类中开启AOP支持。@EnableAspectJAutoProxy

两个切面,它们之间的顺序是怎么控制的

(1) 通常使用@Order 注解直接定义切面顺序
(2) 实现Ordered 接口重写 getOrder 方法。返回值越小优先级越高

springmvc的工作流程

在这里插入图片描述

执行前;当一个请求发来时先进服务器(Tomcat),在服务器中会有拦截器,过滤器啊,等这些功能走完之后,才真正的进入了框架中。

1.用户发来一个请求,首先进入的是前端控制器DispatcherServlet
2.前端控制器将(DispacherServlet)用户发来的请求发送给处理器映射器(HandlerMapping)
3.处理器映射器根据前端控制器发来的用户的请求找到对应符合的控制器(Handler),并且将其封装成处理器执行链,返回给前端控制器。
4.前端控制器DispatcherServlet调用处理适配器(HandlerAdapter)来调用的具体的控制器
5.控制器执行完成后,会返回一个
ModelAndView对象
给处理器适配器
6.处理器适配器将返回来的ModelAndView对象返回给前端控制器(到这里所有的业务处理过程就要完了,接下就是将结果以页面的的形式相应给用户)
7.前端控制器将返回回来的ModelAndView对象交给视图解析器(ViewResolver),视图解析器根据传过里的View对象解析成对应的页面对象,然后将页面对象和Model对象返回给前端控制器。
8.前端控制器再将返回回来的对象交给视图(View),视图根据传过来的Model对象再一次的对页面进行渲染,然后在返回给前端控制器。
9.前端控制器将完成的结果响应给浏览器,然后浏览器在展现给用户。

设计模式和面向对象的五大原则

在这里插入图片描述

创建型模式,5 (将对象的创建与使用分离)⼯⼚/抽象⼯⼚/单例/建造者/原型模式
结构型模式,7 关注类和对象的组织 适配器/桥接模式/过滤器/组合/装饰器/外观/享元/代理模式
行为型模式,11 关注对象之间的相互交互 任链/命名/解释器/迭代器/中介者/备忘录/观察者/状态/策略/模板/访问者模式

原则

接一(依)单,开里迪

  • 接口隔离原则:将不同功能定义在不同接⼝中实现接⼝隔离
  • 依赖倒置原则:程序应该依赖于抽象类或接⼝,⽽不是具体的实现类。
  • 单一原则:一个类只负责一项职责
  • 开闭原则:对扩展开放,对修改关闭。通过扩展来实现变化,而不是通过修改原来的代码来实现变化
  • ⾥⽒替换原则:子类除了新增功能外,尽量不要重写父类的方法。
  • 迪⽶特原则:每个模块对其他模块都要尽可能少地了解和依赖,降低代码耦合度。

Spring 框架中用到了哪些设计模式?

  • 工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。

  • 单例设计模式 : Spring 中的 Bean 默认都是单例的。
    Spring 中 bean 的默认作用域就是 singleton(单例)的 ,这一类对象只能有一个实例
    对于频繁使用的对象,可以省略创建对象所花费的时间
    由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,

  • 代理设计模式 : Spring AOP 功能的实现。

  • 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  • 包装器设计模式 - : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。

spring 控制反转(IOC)和依赖注入(DI)

在这里插入图片描述
@Autowired是按照类型注入的,如果有多个实现类,@Qualifier来指定注入哪个名称的bean对象。
在这里插入图片描述

@component 和@Bean

用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中
如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现
@Component 注解作用于类,而@Bean注解作用于方法。

springBean 的生命周期

在这里插入图片描述

2. Java-锁

2.1锁的分类

JAVA里面主要有ReentrantLock ,synchronized,Lock三种

Synchronized 的锁升级流程是这样:无锁 ----> 偏向锁 ----> 轻量级锁----> 锁自旋 ----> 重量级锁

可重入锁和不可重入锁

可重入锁:当前线程获取到A锁,在获取之后尝试再次获取A锁是可以直接拿到的

java中提供的synchronized,ReentrantLock,ReentrantReadWriteLock都是可重入锁
不可重入:当前线程获取到A锁,在获取之后尝试再次获取A锁,无法获取到的,因为A锁被当前线
程占用着,需要等待自己释放锁再获取锁。

乐观锁和悲观锁

乐观锁:为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了。适合于读操作多的,乐观思想就是认为:当前环境读数据的多,写数据的少,并发读多,并发写少。
悲观锁
Java中提供的synchronized,ReentrantLock,ReentrantReadWriteLock都是悲观锁
一个共享数据加了悲观锁,那线程每次想操作这个数据前都会假设其他线程也可能会操作这个数据,所以每次操作前都会上锁,这样其他线程想操作这个数据拿不到锁只能阻塞了。
synchronized 引入了大量的优化如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销

公平锁和非公平锁

Java中提供的synchronized只能是非公平锁。
Java中提供的ReentrantLock,ReentrantReadWriteLock可以实现公平锁和非公平锁
公平锁:线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,锁被A持有,同时线
程B在排队。直接排到B的后面,等待B拿到锁资源或者是B取消后,才可以尝试去竞争锁资源。
非公平锁:线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,先尝试竞争

互斥锁和共享锁

Java中提供的synchronized、ReentrantLock是互斥锁。
Java中提供的ReentrantReadWriteLock,有互斥锁也有共享锁。
互斥锁:同一时间点,只会有一个线程持有者当前互斥锁。
共享锁:同一时间点,当前共享锁可以被多个线程同时持有。

知乎连接讲得很好:
在这里插入图片描述
偏向锁:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现这个线程 ID
是自己的就表示没有竞争,不用重新 CAS

如何避免死锁

在这里插入图片描述

在这里插入图片描述

要避免死锁问题

  • 一般方法是打破循环等待条件,让两个线程之间获取资源的顺序不要穿插在一起,可以让一个线程先获得两个资源,使用完毕后释放,另一个线程再获取这两个资源,就可以保证两个线程都能正常执行。
  • 线程 A 和 线程 B 获取资源的顺序要一样,

2.2 Java中synchronized 和 ReentrantLock 有什么不同?

(1)功能区别
Synchronized是java语言的关键字,
ReentrantLock 是JDK1.5之后提供的API层面的互斥锁,需要lock和unlock()方法配合try/finally代码块来完成。

相对于 synchronized 它具备如下特点
不同

  • 可中断 :持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待
  • 可以设置超时时间
  • 锁的细粒度和灵活性:ReentrantLock强于Synchronized;
  • 可以设置为公平锁
  • 支持多个条件变量
    ReentrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像Synchronized要么随机唤醒一个线程,要么唤醒全部线程。

相同

  • 与 synchronized 一样,都支持可重入
    可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
  • 都是阻塞式的同步,也就是说一个线程获得了对象锁,进入代码块,其它访问该同步块的线程都必须阻塞在同步代码块外面等待
    在这里插入图片描述
    6、锁绑定多个条件Condition:synchronized没有。
    ReentrantLock可用来分组唤醒需要唤醒的线程。而不是像synchronized要么随机唤醒一个线程,要么唤醒所有线程。

2.3 volatile(可见性),不能保障原子性

一个线程对共享变量的修改,另外一个线程能够立刻看到,称为变量的可见性。
读取 volatile 修饰的变量时,线程将不会从所在CPU的缓存,而是直接从系统的主存中读取变量值,读取 volatile 修饰的变量时,线程将不会从所在CPU的缓存,而是直接从系统的主存中读取变量值
不能保障原子性
原子性是拒绝多线程交叉操作的,对于volitile i;**i++**操作,就不能保证它的原子性

2.3 ThreadLocal和线程隔离

文本链接:
为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题,不同的线程之间不会相互干扰

线程隔离
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.3 如何创建线程?你比较推荐哪一种方式?为什么?

在这里插入图片描述
优先选择:实现Runnable 接口的

1.实现的方式没有类的单继承性的局限性
2.实现的方式更适合来处理多个线程有共享数据的情况,代码和线程独立。
实现多个 Thread共用一个Runnable
在这里插入图片描述在这里插入图片描述

2.4 Java 线程的状态有哪几种?

在这里插入图片描述

3.JVM

里面包含了很多可能会被问到的JVM的知识
对象的内存分布:视频讲解
在这里插入图片描述

3.1 JVM常用参数

根据JVM参数开头可以区分参数类型,共三类:“-”、“-X”、“-XX”,

标准参数(-):所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
非标准参数(-X):默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
非Stable参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;

-Xms 初始堆大小,-Xmx 最大堆大小
-XX:NewSize=n 设置年轻代大小-XX:NewRatio=n 设置年轻代和年老代的比值。

-Xss:栈空间大小,栈是线程独占的,所以是一个线程使用栈空间的大小。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.2 类的加载过程和类加载器

系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析

  • 加载
    3 件事情:
    通过全类名获取定义此类的二进制字节流。
    将字节流所代表的静态存储结构转换为方法区的运行时数据结构。
    在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口。

  • 验证
    确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,
    保证这些信息被当作代码运行后不会危害虚拟机自身的安全。(文件格式验证,元数据验证,字节码验证,符号引用验证)

  • 准备
    为 static 变量分配空间,设置默认值
    如果 static 变量是 final 的基本类型,以及字符串常量,那么编译阶段值就确定了,赋值在准备阶
    段完成

  • 解析
    解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。

  • 初始化阶段
    初始化即调用 ()V ,虚拟机会保证这个类的『构造方法』的线程安全
    会触发初始化的情况
    (1)当遇到 new 、 getstatic、putstatic 或 invokestatic ,这 4 条直接码指令
    new (创建一个类的实例对象)。
    getstatic(程序访问类的静态变量)。
    putstatic(给类的静态变量赋值)。
    invokestatic (调用类的静态方法)。

(2)反射 Class.forName
(3)子类初始化,如果父类还没初始化,会引发
(4)main 方法所在的类,总会被首先初始化
(5)子类访问父类的静态变量,只会触发父类的初始化

在这里插入图片描述

类加载器
JVM 中内置了三个重要的类加载器:
BootstrapClassLoader(启动类加载器),ExtensionClassLoader(扩展类加载器),AppClassLoader(应用程序类加载器)
除了 BootstrapClassLoader 是 JVM 自身的一部分之外,由 C++ 实现,过getParent()获取其父 ClassLoader,为null
其他所有的类加载器都是在 JVM 外部实现的

在这里插入图片描述

双亲委派

执行流程:
(1)在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载(每个父类加载器都会走一遍这个流程)。
(2) 进行类加载的时候,它首先进行类加载的时候,调用父加载器 loadClass()方法来加载类,调用父加载器 loadClass()方法来加载类。
(3)只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载(调用自己的 findClass() 方法来加载类)。
(4)如果子类加载器也无法加载这个类,那么它会抛出一个 ClassNotFoundException 异常。

在这里插入图片描述

3.3 原子性, 可见性

在这里插入图片描述
原子性

synchronized( 对象 ) {
要作为原子操作代码
}

可见性

main 线程对 run 变量的修改对于 t 线程不可见,它保证的是在多个线程之间,一个线程对 volatile 变量的修改对另一
个线程可见, 不能保证原子性,仅用在一个写线程,多个读线程的情况

synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。但缺点是
synchronized是属于重量级操作,性能相对更低在这里插入图片描述
有序性-指令重排
在 Java 中,volatile 关键字除了可以保证变量的可见性,还有一个重要的作用就是防止 JVM 的指令重排序。
满老师讲的单例模式-指令重排添加链接描述
在这里插入图片描述
在这里插入图片描述

3.4 synchronized底层实现原理

  1. synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置( 修饰代码块:指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

当一个线程想要访问某个对象的 synchronized 代码块,首先需要获取该对象的 Monitor。如果锁的计数器为 0 则表示锁可以被获取,否则,该 Monitor 已经被其他线程持有,则当前线程将会被阻塞,直至 Monitor 变为可用状态。

在这里插入图片描述

  1. JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法
    修饰普通方法:作用于当前对象实例,进入同步代码前要获得当前对象实例的锁

  2. synchronized 修饰静态方法,相比普通方法,ACC_SYNCHRONIZED,只是多了个 ACC_STATIC 标识,
    修饰静态方法:作用于当前类,进入同步代码前要获得当前类对象的锁

3.5 jvm运行原理?

3.6 查看堆内存的情况(常用指令)

操作系统工具

top:显示系统整体资源使用情况   
vmstat:监控内存和CPU
iostat:监控IO使用
netstat:监控网络使用

jmap可以查看当前Java进程的内存占用,把内存快照dump出来,jmap -heap pid
jstack可以查看线程运行情况,是否有死锁,cpu过高问题, jstack -l pid 生成虚拟机当前时刻的线程快照,deadlock:死锁,blocked:线程被阻塞,
jstat命令来查看垃圾回收的情况,full gc比价频繁,那么就得进行调优
在这里插入图片描述

3.7JVm内存溢出定位方法?

摘抄于这篇知乎
step1:通过top命令各个进程的资源占用情况。
step2:通过打印出进程的所有线程信息和进程pid查看gc情况,jstat -gcutil pid 1000
step3:通过jmap查看是哪个对象占用了内存。
step4:使用visualVM对dump文件进行离线分析,找到占用内存高的对象,从代码和业务场景中定位具体问题。
在这里插入图片描述

4.网络

4.1 三次握手

在这里插入图片描述
一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN状态
第一次握手:
客户端会随机初始化序号(client_isn)置于TCP中,TCP报文首部的同步位SYN=1.向服务器发送连接请求报文段,这时客户端进入SYN_SENT(同步已发送)状态,等待服务器的确认
第二次握手:
服务端回复客户端发送的TCP连接请求报文,服务端也随机初始化自己的序号(server_isn),填入 TCP 首部的「序号」字段中, TCP 首部的「确认应答号」字段填入 client_isn + 1, SYN 和 ACK 标志位置为 1,服务端处于SYN-RCVD 状态
第三次握手:
客户端收到服务端报文后,回应最后一个应答报文,
TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 **server_isn + 1 **,客户端处于== ESTABLISHED ==状态。服务端收到客户端的应答报文后,也进入 ESTABLISHED 状态

为什么是三次握手?不是两次、四次?

原因一:避免历史连接
我们考虑一个场景,客户端先发送了 SYN(seq = 90)报文,然后客户端宕机了,重启后,发送了 SYN(seq = 100)报文
正常的三次握手,服务端在第二次握手,ack 确认号实际是90+1,因为旧的报文比新的先返回给客户端,客户端收到此 ACK 报文时,发现自己期望收到的确认号应该是 101,而不是 91,于是就会回 RST 报文。就会释放连接。
在两次握手的情况下,服务端在收到 SYN 报文后,就进入 ESTABLISHED 状态,只有等到客户端判断到此次连接为历史连接,那么就会回 RST 报文来断开连接。

两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。

4.2 四次挥手状态变化

在这里插入图片描述
F12 TC 服务端:clc
客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入FIN_WAIT_1 状态。
服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT状态。
客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。
客户端在经过 2MSL 一段时间后,自动进入CLOSE 状态,至此客户端也完成连接的关闭。

为什么四次挥手

  • 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据
  • 服务端收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接

为什么四次挥手的报文要等2sml才能释放TCP连接?

  • 1.为了保证客户端发送的最后一个ACK报文段能够到达服务器。
    假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
  • 2.在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器。客户端在发送最后一个ACK之后,再经过经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失
    在这里插入图片描述

TCP/IP模型?以及每一层对应七层模型哪个

在这里插入图片描述
应表会 传网 数物
------传网–

5.SQL

  • B+ 树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数。
  • SQL 标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化serializable 。

5.1MySQL索引

根据叶子节点的内容,索引类型分为主键索引和非主键索引。
主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。
非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。
区别
在这里插入图片描述
从性能和存储空间方面考量,自增主键往往是更合理的选择。

  • 自增主键的插入数据模式,递增插入,每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。
  • 主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。

覆盖索引:如果一个索引包含(或者说覆盖)所有需要查询的字段的值,不做回表操作,我们就称之为“覆盖索引”
最左匹配原则:在通过联合索引检索数据时,从索引中最左边的列开始,一直向右匹配,如果遇到范围查询(>、<、between、like等),就停止后边的匹配。
(或者比如直接使用第三个位置上的索引而忽略第一二个位置上的索引时,则会进行全表查询)

索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
在这里插入图片描述

5.2 MySQL索引失效

  • like以%开头,模糊匹配,如果放在开头则不走索引。
  • 联合索引没遵循最左前缀原则
  • where中索引列有运算,索引列使用了函数,使用 or 来连接条件数据少)
  • 需要类型转换(varchar不加单引号的话可能会自动转换为int型, name = 123 和 WHERE name = ‘123’)
  • 如果mysql觉得全表扫描更快时

5.3 MySQL索引为什么采用B+树

索引的出现其实就是为了提高数据查询的效率
在这里插入图片描述
-树的查询时间跟树的高度有关,B+树是一棵多路搜索树可以降低树的高度,提高查找效率,为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。

  • hash表:等值查询是很快的,但是不满足常用的范围查找且相邻的两个值之间没有关系,而且hash比较消耗内存。
  • 二叉树/平衡二叉树/红黑树等都是有且仅有2个分支,共性就是数据量大的时候树的深度变深,增加IO的次数。
  • B树会在节点上存储数据,这样一页存放的key的数量就会减少,增加树的深度。
  • B+树 中非叶子节点去除了数据,这样就会增加一页中key的数量,而且叶子节点之间是通过链表相连,有利于范围查找和分页。

5.4 MySQL日志有哪些,具体什么功能,保存什么数据

一条SQL更新语句
当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log(粉板)里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面(先写日志,再写磁盘
在这里插入图片描述
依赖redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe

redo log

  • 是 InnoDB 引擎特有的日志,InnoDB 依赖redo log 来实现 crash-safe 能力,
  • redo log 是循环写的,空间固定会用完
  • 是物理日志,记录的是“在某个数据页上做了什么修改”;

binlog:

  • binlog 是 归档日志,MySQL 的 Server 层实现的,所有引擎都可以使用。
  • 逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
  • inlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

undo log

  • 撤销日志,用于回滚事务,MySQL事务中原子性就是使用Undo Log实现的
  • undo log主要记录了数据的逻辑变化,比如一条INSERT语句,对应一条DELETE的undo log
  • 实现 MVCC(多版本并发控制,Multi-Version Concurrency Control) 。

执行顺序

from -> on -> join -> where -> group by -> having -> count(聚合函数 avg、max、min、sum) 
-> select -> distinct -> union -> order by -> limit 

分页查询

limit — 随着查询偏移的增大,查询时间急剧增加。
优化1-- 通过id:id是连续递增的,利用索引据查询的页数和查询的记录数可以算出查询的id的范围
优化2-- 子查询 :首先定位偏移量的id,根据获取的id值向后查询

Explain

当Explain 与 SQL语句一起使用时,MySQL 会显示来自优化器关于SQL执行的信息。
在这里插入图片描述select子句或者操作表的顺序,id的值越大,代表优先级越高,越先执行
表示 select 查询的类型,主要是用于区分各种复杂的查询,例如:普通查询、联合查询、子查询等。
type:查询使用了何种类型,它在 SQL优化中是一个非常重要的指标,以下性能从好到坏依次是:
system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
index:Index 与ALL 其实都是读全表,区别在于index是遍历索引树读取,而ALL是从硬盘中读取。

在这里插入图片描述

6.java

6.1 抽象类和接口区别?

在这里插入图片描述
接口:
在这里插入图片描述
区别:

  • 定义关键字不同,接口使用关键字 interface 来定义。 抽象类使用关键字 abstract 来定义。
  • 子类继承或实现关键字不同。
  • 抽象类是单继承,而接口是多继承。抽象类的子类,只能继承一个抽象类
  • 属性访问控制符不同,接口中属性的访问控制符只能是 public,抽象类中的可为任意控制符
  • 方法控制符不同,接口中方法的默认控制符是 public,其中抽象方法不能使用 private 修饰,其余无限制
  • 方法实现,接口中普通方法不能有具体的方法实现(除static 和 default 方法必须有方法实现),抽象类中普通方法可以有方法实现,抽象方法不能有方法实现
  • 抽象类中可以使用静态代码块,接口中不能

6.2 Java8 的新特性

  • 接口的默认方法,在接口中新增了default方法和static方法,这两种方法可以有方法体
  • 有且只有一个抽象方法的接口被称为函数式接口,@FunctionalInterface 注解,Lambda表达式可以看成是匿名内部类,使用Lambda表达式时,接口必须是函数式接口
  • 方法引用:方法引用是一种简化Lambda表达式的语法。它允许直接引用已经存在的方法,可以提高代码的可读性。 Math::max 表示引用Math类的静态方法max
  • Steam API:流的操作包含如下三个部分:创建流、中间流、关闭流,筛选、去重、映射、排序属于流的中间操作,收集属于终止操作
  • 日期时间API:本地日期和时间类:LocalDateTime,LocalDate,LocalTime;带时区的日期和时间类:ZonedDateTime;
  • Java 8引入了元空间(Metaspace)的概念,用于替代Java 7及之前版本中的永久代(PermGen)。
    在这里插入图片描述
    在这里插入图片描述

6.3 讲一下动态代理?动态代理有几种方式?

如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,代理类需要实现InvocationHandler接口,通过proxy类创建代理对象,并且会调用InvocationHandler接口的invoke方法来处理具体的逻辑。
而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,会调用MethodInterceptor接口的intercept方法来处理具体的逻辑。

6.4 反射

Java的反射是指在程序运行时,对于任意一个类,都可以获取到这个类的所有属性和方法,并能够对其进行操作。
应用场景了解么?

  • 动态代理的实现也依赖反射。
  • 许多框架(如Spring)利用反射获取类的信息和属性,来实现依赖注入、控制反转等功能。
    在这里插入图片描述
    在这里插入图片描述

6.5 所有异常的共同祖先是?运行时异常有哪几个?

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7.Redis

7.1 Redis 数据类型有哪些

Redis是一种存储key-value的内存型数据库,它的key都是字符串类型,value支持存储5种类型的数据:String(字符串类型)、List(列表类型)、Hash(哈希表类型、即key-value类型)、Set(无序集合类型,元素不可重复)、Zset(有序集合类型,元素不可重复)。

7.2 String 的应用场景有哪些?

  • 缓存,使用MySQL作为数据库,Redis作为缓存。由于Redis具有支撑高并发的特性,通常能起到加速读写和降低后端压力的作用
  • 共享Session.用户重新刷新一次界面,使用redis集中管理这些session,将session存入redis,使用的时候直接从redis中获取
  • 计数器,Redis中有一个字符串相关的命令,incr key,同时将这些数据异步存储到数据库中达到持久化的目的。

在这里插入图片描述

7.3 String 还是 Hash 存储对象数据更好呢?

在这里插入图片描述

7.4 一致性哈希

视频连接:
文字描述:

7.5 Redis怎么实现分布式事物?怎么加锁?加锁为什么要设置过期时间?作用?怎么释放锁?

分布式系统下,不同的服务/客户端通常运行在独立的 JVM 进程上。如果多个 JVM 进程共享同一份资源的话,使用本地锁就没办法实现资源的互斥访问了。

在这里插入图片描述在这里插入图片描述

7.6 消息队列怎么保证顺序消费?

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值