JAVA常见面试题整理(长期更新)

常见面试题

    • java基础
      • jdk
            • 1、java跨平台原理
            • 2、java中int占几个字节 int和integer的区别
            • 3、==与equals区别 equals和hashcode的区别与联系
            • 4、面向对象的几个特征
            • 5、抽象类和接口的区别
            • 6、什么是字符串常量池?
            • 7、字符串是可变的吗?
            • 8、String、StringBuffer和StringBuilder的区别是什么?
            • 9、访问权限修饰符的区别
            • 10、&和&&的区别
            • 11、是否可以继承String
            • 12、当一个对象作为参数传入一个方法后,这个方法可以改变传入对象的属性值,那么这里对象的传递是值传递还是引用传递
            • 12、重载和重写的区别
            • 13、char类型中能否存入一个中文汉字
            • 14、抽象方法是否可以被static、native、synchronized修饰
            • 15、什么是多态
            • 16、java异常分类
            • 17、error和exception的区别
      • 反射
            • 1、什么是反射?
            • 2、反射的优缺点
            • 3、反射机制的应用场景
            • 4、通过反射获取Clazz的几种方式
            • 5、通过反射创建实例对象几种方式
            • 6、如何通过反射获取私用属性
      • 集合
            • 1 、简述集合体系
            • 2、hashMap和hashTable区别
            • 3、ArrayList和Vector的区别
            • 4、Array和ArrayList有什么区别?什么时候应该用Array而不是ArrayList?
            • 5、HashMap的底层原理
            • 6、set里的元素是不能重复的,那么底层是用什么方法区分重复与否呢?
            • 7、HashSet和TreeSet的区别
            • 8、LinkedHashMap的实现原理
            • 9、ConcurrentHashMap与Hashtable的区别
      • 线程
            • 1、进程、线程的关系与区别
            • 2、创建线程的几种方式
            • 3、什么是守护线程
            • 4、Thread类中的start()和run()方法有什么区别?
            • 5、什么导致线程阻塞
            • 6、wait()与sleep()的区别
            • 7、什么是线程局部变量ThreadLocal
            • 8、什么是乐观锁和悲观锁
            • 9、版本号机制和CAS机制的区别
            • 10、volatile关键字
    • javaEE
            • 1、http get post的区别
            • 2、Servlet生命周期
            • 3、jsp和Servlet的相同点和不同点
            • 4、内置对象和四大作用域
            • 5、Session和Cookie的区别
            • 6、MVC模式和MVC各部分实现
    • JVM虚拟机
            • 1、java类加载过程
            • 2、描述JVM加载Class文件的原理机制
            • 3、java内存分配
            • 4、GC是什么?为什么要有GC?
            • 5、简述java垃圾回收机制
            • 6、如何判断一个对象是否存活
            • 7、垃圾回收的优点以及原理
            • 8、垃圾回收器可以马上回收内存吗?有什么办法可以主动通知JVM进行垃圾回收?
            • 9、java中存在内存泄漏吗?
            • 10、谈谈深copy和浅copy
            • 11、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存
            • 12、对象什么时候可以被垃圾回收
            • 13、简述java内存分配与回收测率以及MinorGC
            • 14、JVM的永久代中会发生垃圾回收吗?
            • 15、什么是类加载器,类加载器有哪些?
    • 框架
      • spring框架
            • 1、什么是spring?spring有哪些主要模块?
            • 2、使用spring框架有什么好处?
            • 3、什么是IoC?什么是DI?
            • 4、spring中的单例Bean是线程安全的吗?
            • 5、spring中都用到了哪些设计模式?
            • 6、IoC容器中Bean的生命周期
            • 7、解释spring支持的几种bean的作用域
            • 8、spring几种属性装配方式
            • 9、什么是AOP?
            • 10、简单说明spring的声明式事务?
            • 11、Spring中BeanFactory和ApplicationContext的区别
      • springMVC框架
            • 1、springMVC运行流程
            • 2、什么是DispatcherServlet
            • 3、Spring MVC的控制器是不是单例模式
            • 4、Spring MVC怎么和AJAX相互调用的
      • Mybatis
            • 1、什么是ORM
            • 2、MyBatis的工作原理
            • 3、为什么需要预编译
            • 4、Mybatis是否支持延迟加载?
            • 5、#{}和${}的区别
            • 6、模糊查询like语句该怎么写
            • 7、mapper中如何对应多个值
            • 8、Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗
            • 9、Mybatis是如何将sql执行结果封装为目标对象并返回的
            • 10、Mybatis动态sql
            • 11、Mybatis的缓存机制
      • springBoot框架
            • 1、为什么要用SpringBoot
            • 2、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
            • 2、SpringBoot事务的使用
      • RabbitMQ
            • 1、 MQ的优点
            • 2、 MQ的几种工作模式
            • 3、消息基于什么传输
    • 数据库
        • mysql
            • 1、数据库分类和常用数据库
            • 2、关系型数据库三大范式
            • 3、事务的三大特征
            • 4、mysql数据库最大连接数
            • 5、MySQL或者Oracle分页语句
            • 6、简单说说jdbc的理解
            • 7、数据库连接池的作用
            • 8、mysql优化
            • 9、什么是索引
            • 10、索引失效的场景
            • 11、 B树和B+树的区别
            • 12、mysql常用的存储引擎
            • 13、主从复制、读写分离
            • 14、主从复制的几种方式
            • 15、主从复制的过程
            • 16、mysql分库分表
            • 17、分库分表策略
            • 18、mysql日志
            • 19、mysql事务隔离级别
            • 20、mysql锁类别
            • 21、什么是游标,存储过程,触发器
            • 22、常用触发器
            • 23、BTree 与 Hash 索引有什么区别
        • Redis
            • 1、Redis的优点
            • 2、Redis为甚么执行效率快
            • 3、redis事务的特征
            • 4、redis同步机制
            • 5、redis持久化机制
            • 5、redis集群搭建
            • 6、redis应用场景
            • 7、redis过期键删除策略
            • 8、redis内存淘汰

java基础

jdk

1、java跨平台原理

java中.java文件在执行编译后,产生.class文件,.class文件是在JVM虚拟机中运行的,而JVM虚拟机可以安装在各个主流系统上,所以编译后的.class文件可以运行在各个系统。

2、java中int占几个字节 int和integer的区别

在java中int是中基本类型的其中一种,占4字节,32位,定义后初始化数据为0。
Integer为int类型的包装类,里面定义了许多关于int类型的方法,同时也可以达到存储int类型数据的目的,拥有自动装箱,自动拆箱功能,定义后初始化数据为null,当存储数据在-128到127时,Integer对象是在IntegerCache.cache产生,会复用已有对象,此时使用==进行判断,两个是同一个对象。当不在这个区间内,则会重新new一个Integer对象,使用==判断后结果为false。

3、==与equals区别 equals和hashcode的区别与联系

实际上equals方法的底层是==去实现的,当比较的数据类型为基本类型时则不能使用基本类型.equals,需要使用==才能进行比较。
使用equals或==对类型为String的数据进行判断时比较的是字符串内容,当使用equals或==对引用数据进行判断时,比较的是地址在内存中的地址值,当重写equals后可以自己指定比较内容,同时也可以使用hashcode作为比较值。当需要比较大量数据时,使用重写equals方法并结合hashcode进行查找效率最高。

4、面向对象的几个特征

抽象: 将一类对象的共同特征总结出来构造类的过程,抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
封装: 把一个对象的属性私有化,但是同时也提供一些可以被外界访问的属性的方法,如果不希望外界访问,则也不必提供方法给外界。
继承: 使用已存在的类的定义作为基础,建立新类的技术,继承父类的子类可以增加自己独有的属性和方法,同时也可以使用父类的属性和功能,但不能选择性的继承父类,通过继承可以减少代码冗余,增加代码复用。要注意的是java是单继承多实现。
子类拥有父类非private的属性和方法。
子类可以拥有自己的属性和方法,可以在父类的基础上进行扩展。
子类可以用自己的方式实现父类的方法,也就是方法重写。
多态: 指程序中定义的引用变量所指向的具体类型在编程时不确定,而是在运行期间才确定,即一个引用变量到底指向哪个实例对象,该引用变量发出的方法调用到底是那个类中的实现方法,必须由程序运行期间才能决定。

5、抽象类和接口的区别

抽象类是定义要被继承的子类的通用特性的,接口只能定义方法。
抽象类是对类的抽象,是一种模板,接口是对行为的抽象,是对行为的规范。
相同点:
接口和抽象类都不能实例化,只能被继承或实现。
都包含抽象方法,并且子类必须重写这些方法。(1.8以后接口引入默认方法和静态方法,默认方法不用被强制实现)
不同点:
声明关键字不同。
实现关键字不同。
抽象类可以有构造器,接口没有。
抽象类的方法可以有各种访问修饰符,接口访问修饰符必须是public
一个类最多继承一个抽象类,但是可以实现多个接口

6、什么是字符串常量池?

字符串常量池位于堆内存,专门存放字符串常量,可以提高内存使用率,避免多块空间存储相同字符串。在初始化字符串时会在内存中检查字符串常量池,如果常量池已存在该字符串,则返回它的引用,如果不存在,则实例化一个字符串放入池中,并返回其引用。

7、字符串是可变的吗?

字符串是不可变的,java中String类是用final修饰的一个常量char数组,所以不可修改。表面看上去的可以修改实际上是在字符串常量池中新建了一个字符串,并返回了该字符串的引用。

8、String、StringBuffer和StringBuilder的区别是什么?

String底层是被final修饰过的所以是不可变的,StringBuffer和StringBuilder虽然也是用char数组实现,但是没有用final修饰,所以是可变的,并且拥有一些独有的字符串处理方法
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以它是线程安全的,而StringBuilder没有加锁,所以它不是安全的。
StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并引用,相同情况下使用StringBuilder要比StringBuffer效率要高。

9、访问权限修饰符的区别
修饰符 当前类 同包 子类 其他包
public
producted
default
private
10、&和&&的区别

&和&&都是逻辑运算符,从某种意义上来讲,两个效果是相同的,但是&&拥有短路特性,当有多个逻辑表达式进行运算时,如果第一个逻辑表达式就是false,那么不管后面是否正确,都不在执行。同理 | 和 || 也是一样的,只要第一个为true那么后面都不在执行了。

11、是否可以继承String

不可以,String类是被final修饰过的,并且继承String本身就是一种错误的行为。

12、当一个对象作为参数传入一个方法后,这个方法可以改变传入对象的属性值,那么这里对象的传递是值传递还是引用传递

是值传递,因为java中不存在引用传递,当一个对象实例被传入方法中,参数的值是该对象的引用,对象的属性可能会被改变,但是对象引用的改变是不会影响到调用者的。

12、重载和重写的区别

重载是相同的方法名,参数列表的类型、数量、顺序不同,并且与返回值无关,可以有不同修饰符。
重写是将继承的父类方法重写覆盖掉父类方法,所以要求,方法名,参数列表都与父类方法名和参数列表相同
注:构造方法不能被重写,被final修饰的方法不能被重写,声明为static的方法不能被重写,但是可以被再次声明

13、char类型中能否存入一个中文汉字

可以,因为java使用的默认编码为Unicode,直接使用字符在字符集的编号,一个charl类型占两字节,所以放一个中文汉字是没问题的。

14、抽象方法是否可以被static、native、synchronized修饰

都不可以
首先抽象方法是要被子类重写的,而static方法无法被重写,这是相互矛盾的。
native是有本地方法实现的,而抽象方法是没有实现的,所以也不可以。
synchronized和实现的细节有关,而抽象方法不设计实现细节,因此也是矛盾的。

15、什么是多态

多态是父类或接口定义的引用变量可以指向子类实现,而程序调用的方法在执行期间才会动态绑定,就是引用变量所指向的具体实例对象的方法,也就是对象内存中正在运行的那个对象,而不是引用变量的类型中定义的那个方法。

16、java异常分类

java异常分为运行时异常和编译时异常
编译时异常是可以被手动处理掉的,大部分是可以预见性的异常,如果是=提前知道怎么处理异常,则可以使用try…cache捕获并处理异常,如果不知道如何处理,则定义该方法是声明时抛出该异常。
运行时异常则是只有在代码运行时才发出的异常,比如类转换异常,数组下标越界异常、除数为0数学异常等,这种异常在出现时会被系统自动捕获,可以手动try…cache进行处理,或者直接交给程序自动处理。

17、error和exception的区别

error和exception都继承于throwable类
error一般是虚拟机相关的问题,如系统崩溃,内存空间不足,方法调用栈溢出等,这种问题一旦出现,就代表这无法修复的错误,是非常严重的。
exception表示程序可处理的异常,遇见这种问题,应该尽可能的解决异常,使程序恢复运行。
exception又分为运行时异常和编译时异常,编译时异常表示语法都没用办法通过,运行时异常表示的是只有在程序运行时,才会出现的异常,比如数组下标越界,没找到类异常等。遇见异常时,尽量使用try…cache进行异常捕获并处理,保证程序的正常运行。

反射

1、什么是反射?

在程序运行状态时,都能够知道任何一个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性,这种动态获取对象类或对象信息,并动态调用对象的方法被称为反射。

2、反射的优缺点

优点:可以在运行期间就对类或对象进行判断,动态加载,提高代码灵活度。
缺点:相当于手动操作JVM进行操作,不如JVM自动操作效率高。

3、反射机制的应用场景

在平时的项目开发过程中,很少直接使用反射,但是在框架设计、模块化开发等都是通过反射调用相对应的字节码,在spring的动态代理中就使用到了反射机制,spring就是通过读取配置文件后,通过全限定类名和反射获得对象实例。

4、通过反射获取Clazz的几种方式
  1. 使用 Class.forName 静态方法,传入类的全限定类名
  2. 通过类使用.class方法
  3. 通过实例对象的.getClass()方法获取
5、通过反射创建实例对象几种方式
  1. 首先获取类的字节码文件,其次调用clazz.newInstance()获取实例
  2. 首先获取类的字节码文件,其次获取构造方法clazz.getConstructor(),通过constroctor.newInstance()创建实例对象
6、如何通过反射获取私用属性

首先通过反射获取class对象
通过class对象获取属性 getDeclaredField(filedName)
给属性设置可以访问 field.setAccessible(true);

集合

1 、简述集合体系

JAVA常见面试题整理(长期更新)_第1张图片

Collection接口 和 Map接口继承于Iterator接口
set接口 和 List接口继承于Collection接口
set接口下有HashSet、TreeSet和LinkedHashSet

 - HashSet:无序,集合内元素不可重复,线程不安全
 - TreeSet:指定排序算法后可以进行排序,线程不安全
 - LinkedHashSet:有序并且保证排序,线程不安全

List接口下有ArrayList、LinkedList

 - ArrayList:查、改快,线程不安全,初始长度没有指定默认长度的时候,长度为0,并在第一次添加元素时初始化,初始长度为10,再次扩容会先copy数组,并扩容为原数组的1.5倍。
 - LinkedList:增、删快,线程不安全,插入元素是将元素置于链表末尾,属于尾插法。

Map接口下有HashMap、TreeMap、LinkedHashMap和HashTable

 - HashMap:无序双列集合,线程不安全
 - TreeMap:可排序双列集合,线程不安全
 - LinkedHashMap:有序并且保证排序的双列集合,线程不安全
 - HashTable:无序双列集合,线程安全
2、hashMap和hashTable区别

HashMap和HashTable都继承于Map接口,都是双列集合,两者的区别在于:

  1. HashMap线程不安全,hashTable线程安全
  2. HashMap的键和值允许为null值,而HashTable键和值都不允许为null。
  3. 解决hash冲突的方式不同
3、ArrayList和Vector的区别

两个类都继承了List接口,都属于单列有序集合。
Vector是Java出现的时候就存在的类,而ArrayList是后面更新后才出现的。java也推荐我们优先使用ArrayList,但是在使用前要考虑线程安全问题,因为ArrayList是线程不安全的,而Vector是线程安全的,如果没有多线程问题则选择ArrayList,这样效率高于Vector。
ArrayList和Vector在创建时都有一个初始容量大小,当存储的数据超过初始容量时,会自动对集合进行扩容,Vector默认每次增长为原来的2倍,ArrayList是增长为原来的1.5倍,但是Vector可以手动设置增长的空间大小,ArrayList不能手动设置增长空间大小。

4、Array和ArrayList有什么区别?什么时候应该用Array而不是ArrayList?

Array大小是固定的,ArrayList大小是动态变化的。
ArrayList处理固定大小的基本数据类型时,这种方式效率较慢。
在实际应用场景中,如果提前知道需要存储的数量,并且后期不会在改变大小的时候可以使用数组,如果后期对存储容量有动态变化的时候则使用ArrayList。

5、HashMap的底层原理

在jdk1.7之前HashMap的底层原理是由数组+链表实现的,当创建出来HashMap时,是一个数组,数组中的每一个元素是一个单向链表的头指针,指向一个entry键值对,当一个键值对放入hashMap时会根据键的hashcode选择放入哪一个数组元素,也就是选择放入哪一个单向链表中,如果出现两个entry的hash值一样,这样就产生了hash冲突,那么新放入的entry键值对则使用头插法,插入在表头。
jdk1.8之后采用数组+链表+红黑树实现,在基础思想上添加了红黑树进行优化,当链表长度大于等于阈值(8)时,链表转化为红黑树,利用红黑树的自平衡在查找性能上得到提升。当链表长度小于于等于阈值(6)时,红黑树转化为链表。HashMap的初始长度是16,每次自动扩展或手动扩展时,长度必须是2的幂,1.8之后遇到hash冲突后是尾插法。

6、set里的元素是不能重复的,那么底层是用什么方法区分重复与否呢?

set底层先使用hashcode值和将要加入的hashcode值进行比较,如果相同则继续使用equals方法进行比较。

7、HashSet和TreeSet的区别

HashSet底层是有HashMap实现的,在HashSet的构造方法中初始化了一个HashMap,利用HashMap的键值不唯一,使用HashMap的键来存储值,因此当存储的值重复时会返回false。
TreeSet是有树形结构,基于TreeMap实现的,所以存储是有序的,但是同样是线程不安全的。

8、LinkedHashMap的实现原理

LinkedHashMap也是基于HashMap实现的,只是它额外定义了一个Entry header,这个header是独立出来的一个链表头指针。每个entry添加了两个属性,before和after和header结合起来形成了一个双向链表,由此就实现了插入顺序或访问顺序排序。默认排序即插入的顺序。

9、ConcurrentHashMap与Hashtable的区别

两者都是线程安全的,但是底层对于线程安全实现方式不同,Hashtable是对表结构进行上锁,其他操作需要等待执行完毕后才能访问,1.8之前ConcurrentHashMap是采用分离锁形式,没有对整表进行锁定,而是对局部进行锁定,不影响其他线程对表的其他地方操作。1.8之后ConcurrentHashMap采用CAS算法进行安全实现线程安全。

线程

1、进程、线程的关系与区别

进程是包含多个线程的集合,每一个程序在执行时都是一个进程。
线程是进程中最小的数据单位,每个指令都是一个线程。

进程可以没有线程,但是线程必须要存在于进程,即线程依赖于进程。

2、创建线程的几种方式
  1. 继承Thread类,重写run方法,实例化线程,调用start执行。
  2. 实现Runable接口,实现run方法,实例化线程(需要借助Thread),调用start执行。
  3. 实现Callable接口,实例化FutureTask对象包装Callable的实例化对象,使用实例化FutureTask对象作为Thread对象的target创建并启动新线程。
3、什么是守护线程

守护线程是为了服务用户线程的存在,比如jvm虚拟机会等待用户线程执行完成后关闭,但是不会等待GC线程执行完再关闭。

4、Thread类中的start()和run()方法有什么区别?

start()方法用来创建线程,底层也是调用了run()方法,这和直接调用run()方法不一样,当你调用run()方法时,是在当前线程调用,使用start()方法是启动一个新线程。

5、什么导致线程阻塞

导致线程阻塞的原因大体上来说是因为需要的资源没有就绪,所以会陷入阻塞状态,需要等待资源就绪后才会继续执行。常见的阻塞原因有以下几种

  • sleep():sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞 状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。
  • wait()和notify():两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。
6、wait()与sleep()的区别
  1. sleep()来自Thread类,和wait()来自Object类
  2. sleep()睡眠后不让出系统资源,wait()让其他线程可以占用CPU
  3. sleep需要指定一个睡眠时间,时间一到会自动唤醒.而wait()需要配合notify()使用
7、什么是线程局部变量ThreadLocal

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享,是一种实现线程安全的方式

8、什么是乐观锁和悲观锁
  • 乐观锁:认为不是每一次操作都需要上锁,但是在执行操作之前会判断是否会对数据执行修改,一般会使用版本号机制或者CAS机制实现
  • 悲观锁,认为每一次操作都需要上锁,比如synchronized,不管三七二十一就给加上锁了
9、版本号机制和CAS机制的区别
  • 版本号机制会在取出记录时携带版本号,在修改版本号时会与版本号对比,如果版本号不一致,则说明出现问题,抛出异常。如果更新操作执行成功则版本号自增。
  • CAS机制在更新前先取出值作为一个缓存,在更新时,会对更新的值做比较 ,如果更新前的值和更新后的值相同则执行更新,否则抛出异常。
10、volatile关键字

被volatile修饰的共享变量保证了不同线程对该变量操作的内存可见性,禁止指令重排序。
就是当你写一个 volatile 变量之前,会插入一个写屏障,读一个 volatile 变量之前,会插入一个读屏障。在你写一个 volatile 变量时,能保证任何线程都能看到你写的值,在写之前,也能保证任何数值的更新对所有线程是可见的

javaEE

1、http get post的区别

http是超文本传输协议,它规定通过浏览器访问服务器时要遵循请求发送的规则,要求请求的格式要有请求行,请求头,请求体。get方法没有请求体

get和post则是发送请求的两种不同的方法

get请求可以被缓存,可以保存在历史浏览记录中,可以被收藏为书签,响应速度比post快,但是缺乏安全性,请求的数据会在地址栏中显示,请求长度限制最大4k。

post请求不可以被缓存,不会保留在历史浏览记录中,不能被收藏为书签,请求长度没有限制,请求数据不会显示在地址栏上,请求头比get更大。

2、Servlet生命周期

servlet包含四个生命周期

  1. 加载和实例化:当Servlet容器监听到有请求时,会实例化相应的servlet。
  2. 初始化:当示例化后,将会调用init()方法对servlet对象进行一定的初始化处理
  3. 处理请求:当成功初始化后,开始处理用户的请求,并返回给用户
  4. 销毁服务:当Servlet容器检测到已经执行完,就会调用destory()方法释放这个Servlet实例对象。
3、jsp和Servlet的相同点和不同点

jsp是servlet的技术加强,所有的jsp文件都会被解析成一个继成HttpServlet的类,这个类可以对外访问,并且可以动态的生成HTML,XML,或其他格式的web文档返回给用户。

servlet是应用在java文件中,处理用户请求,以HTML,XML,或其他格式返回给用户。

jsp多侧重于页面展示,servlet侧重处理业务逻辑。

4、内置对象和四大作用域

jsp拥有9个内置对象,4个作用域

内置对象

  1. request: 代表对象的请求对象,包含form表单的数据,浏览器信息等。
  2. response: 代表对客户端的相应对象,封装返回给用户的数据,发送重定向编码。
  3. session: 代表用户的一个连接对象,用于追踪用户会话,同时可以将用户的一些数据放入session域中,只要用户不断开此次连接,就可以一直读取session域中的数据。
  4. pageContext: 代表当前页面的一切属性,同时可以通过这个对象获取其他8个对象。。
  5. application: 提供了关于服务器版本,应用参数等和资源的绝对路径等。
  6. out: 代表输出流对象,用作向浏览器返回文本一级的数据,可以直接动态生成html文件。
  7. config: 代表servlet的配置信息对象,可以获取servlet的配置信息。
  8. page: 代表当前页面自身对象。
  9. exception: 代表jsp运行期间产生的异常对象。

作用域

  1. application: web程序的全局范围 自启动就存在,直到服务器关闭才销毁。
  2. session: 用作同一个会话中使用,会话关闭后,session域销毁。
  3. request: 只能在同一个一个请求中转发。
  4. pageContext: 只能在当前jsp页面中使用的数据。
5、Session和Cookie的区别

两者同是追踪回话的一种方式,最直观的区别就在于Session是在服务器端存储用户的登录信息,Cookie是在客户端浏览器存储用户的登录信息。

Seesion的机制决定了用户只能获取自己的session,其他用户的seesion不可见,各客户的session相互独立不可见。seesion的使用比cookie要方便,但是会对服务器产生一定的压力。

6、MVC模式和MVC各部分实现

MVC是目前B/S架构中最常见的设计思想,利用分层思想将程序的整个运行流程分为三层,方便开发中的逻辑处理,实现每一层处理不同的业务。
M: 用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
V: view代表向用户展示的页面数据。
C: 是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

JVM虚拟机

1、java类加载过程

Java类的生命周期为:加载、验证、准备、解析、初始化、使用、卸载七个生命周期,其中,加载、验证、准备、解析、初始化可以称之为类的加载过程。

首先将class文件转为二进制流,接着验证是否为class文件和文件的正确性,验证完毕后在内存中生成该类对象,接着对类中的属性进行预定义,在局部变量表中进行分配存储。解析主要完成符号引用到直接引用的转换动作,有可能在初始化之后开始解析。初始化是对类中的变量进行初始化,加载构造方法,剩余的都又jvm进行初始,之后才开始执行类中定义的java程序代码。开始使用,最后卸载。

2、描述JVM加载Class文件的原理机制

当运行指定程序时JVM会按照一定规则编译并加载class文件,组织成为一个完整的java应用程序,这个过程由类加载器完成。一般有隐式加载(使用new的方式创建对象)和显示加载(利用class.forName()创建对象)两种方式。
类的加载是动态的,它不会一次性将所有的类加载完后再执行,而是保证基础类的加载,至于其他类则在需要时加载。

3、java内存分配

JAVA常见面试题整理(长期更新)_第2张图片
java内存分为以下5个区域:

  1. 堆:是jvm中最大的一块内存区域,用于存放对象实例,数组等。
    堆中内存又分为新生代老年代,内存分配占比为 1:2。
    新生代又分为Eden区和两块Survior区,内存占比为 8:1:1
  2. 栈:也叫虚拟机栈,可以理解为一个线程,在这个线程里执行的每个方法都是一个栈帧,而一个栈帧又包含了【局部变量表,操作数栈,动态链接,返回地址】。
  3. 方法区 :方法区中又分为静态方法区和非静态方法区。静态方法区用来存储已经被JVM加载的常量,静态变量等,是可以被多个线程共享的。非静态方法区是用于存储需要实体对象调用的方法。
  4. 本地方法栈:非Java语言实现的本地方法的堆栈,提供jvm和本机操作系统的功能接口。
  5. 程序计数器:保存有当前正在执行的JVM指令的地址。
4、GC是什么?为什么要有GC?

GC是JVM虚拟机中的垃圾回收器,可以自动监测堆内存中是否存在垃圾对象,从而达到自动回收内存的目的,尽量避免内存溢出。Java 语言没有提供释放已分配内存的显示操作方法。

5、简述java垃圾回收机制

在 Java 中垃圾回收由虚拟机自行执行。JVM 有一个垃圾回收线程,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描垃圾对象,将他们回收。

6、如何判断一个对象是否存活

判断一个对象是否存活有两种方法:
引用计数法:给每一个对象设置一个引用计数器,当有一个地方引用这个对象时,计数器加一,引用失效时,计数器减一。当一个对象的引用计数器为零时,说明此对象没有被引用,也就是“死对象”,将会被垃圾回收。
引用计数法有一个缺陷就是无法解决循环引用问题,所以主流的虚拟机都没有采用这种算法。
可达性算法:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到 GC Roots 没有任何引用链相连时,则说明此对象不可用。当一个对象不可达 GC Root 时,这个对象并不会立马被回收,若要被真正的回收需要经历两次标记。当经历两次标记后该对象将被移除” 即将回收”集合,等待回收。

7、垃圾回收的优点以及原理

在程序开发过程中,最让人头疼的就是内存回收,但是java引入了垃圾回收机制,使此类为题迎刃而解,使开发人员在开发中不用再考虑内存管理。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。不可预知的情况下对内存中已经死亡的或者长时间没有使用的对象进行清除和回收,开发者不能手动的调用垃圾回收器对某个对象进行垃圾回收。
回收机制有分代复制垃圾回收标记垃圾回收增量垃圾回收

8、垃圾回收器可以马上回收内存吗?有什么办法可以主动通知JVM进行垃圾回收?

当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式判断是不是不可引用的垃圾对象,当确定是垃圾对象后GC会回收这些内存空间。而程序员虽然可以手动执行System.gc()但是java不能保证一定会销毁对象。

9、java中存在内存泄漏吗?

内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。Java 中有垃圾回收机制,它可以保证一个对象不再被引用的时候,对象将被垃圾回收器从内存中清除。
而java中使用有向图进行垃圾回收管理,可以消除引用循环的问题。
当然java也存在内存泄漏的可能,比如创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是 java中可能出现内存泄露的情况。

10、谈谈深copy和浅copy

深拷贝就是更改copy后的对象数据,原对象数据不变。浅拷贝就是更改copy后的对象数据原对象数据也跟着改变。简单来说就是深拷贝复制对象的值,浅拷贝是复制对象的地址。

11、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存

如果对象的引用被置为null,只是断开了当前线程栈帧中对该对象的引用关系,而垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize方法中恢复引用 )。只有确定了对象无法恢复引用的时候才会清除对象内存。

12、对象什么时候可以被垃圾回收

当对象没有变量引用的时候,这个对象就可以被回收了。

13、简述java内存分配与回收测率以及MinorGC

• 对象优先在堆的 Eden 区分配
• 大对象直接进入老年代
• 长期存活的对象将直接进入老年代
当 Eden 区没有足够的空间进行分配时,虚拟机会执行一次Minor GC 。Eden 区的对象生存期短,所以可能会频繁触发MinorGC,触发MinorGC后会将未被释放掉的对象放入S0或S1内存,如果要放入对象大于S0或S1内存的50%,则跳过S1或S0直接放入老年代。

14、JVM的永久代中会发生垃圾回收吗?

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发Full GC
注:Java 8 中已经移除了永久代,新加了一个叫做元数据区的native内存区。

15、什么是类加载器,类加载器有哪些?

类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM执行加载后的字节码。类加载器负责加载文件系统、网络或其他来源的类文件。

加载器 说明
启动类加载器(BootstrapClassLoader) 用来加载 Java 核心类库,无法被 Java 程序直接引用。
扩展类加载器(ExtensionsClassLoader) 用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
系统类加载器(SystemClassLoader) 根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java应用的类都是由它来完成加载的。
用户自定义类加载器 通过继承 java.lang.ClassLoader 类的方式实现。

框架

spring框架

1、什么是spring?spring有哪些主要模块?

spring框架是一个轻量级,一站式的开源java框架,它提供了综合广泛的基础性支持平台。拥有简单性,可测试性,松耦合性,任何java程序都能从中收益。
spring中已经集成了20多个模块,比如常用的web,jdbc,aop,tx等。

2、使用spring框架有什么好处?

spring框架提供了IoC(控制翻转)和DI(依赖注入)实现了松耦合的依赖关系
spring框架提供了AOP切面编程,对指定功能进行增强,减少冗余代码,提高代码复用性。
spring框架提供了简单的声明式事务,使开发中能够专注逻辑代码而不用花费过多心思管理事务。
spring框架是按照模块的形式来进行组装的,使用的时候一目了然,直接导入使用的模块即可。

3、什么是IoC?什么是DI?

IoC(控制翻转)将对象交给spring进行创建、初始化、管理、销毁,并存放在IoC容器中。
DI(依赖注入)在程序使用IoC容器中的某个对象时,从容器中获取对象。有三种注入方式:set方法注入,构造方法注入,工厂方法注入,静态方法注入,接口注入。

4、spring中的单例Bean是线程安全的吗?

spring框架没有对单例Bean进行任何的线程封装处理,关于单例Bean的线程安全问题需要开发者自己解决。但是在实际开发中,大部分bean都没有可变状态,所以从某种情况上考虑,spring的单例是安全的,如果bean有多种状态的话,就需要自己保证线程安全。最常用的办法就是将bean的作用域由singleton变更为prototype。

5、spring中都用到了哪些设计模式?

spring中用到了大量的设计模式具体如下:

  • 代理模式:在AOP中使用,使用jdk的动态代理和cglib动态代理。
  • 单例模式:在spring配置文件中定义的bean默认是单例模式。
  • 工厂模式:BeanFactory用来创建对象的实例。
  • 模板模式:用来解决代码重复的问题,比如RestTemplate,JDBCTemplate。
6、IoC容器中Bean的生命周期
  1. 通过构造器或工厂方法创建bean实例。
  2. 为bean的属性设置值和对其他bean的引用。
  3. 将bean实例传递给bean后置处理器的postProcessBeforeInitialization方法
  4. 调用bean的初始化方法。
  5. 将bean实例传递给bean后置处理器的postProcessAfterInitialization方法
  6. bean可以使用了。
  7. 当容器关闭时,调用bean的销毁方法(destroy-method)。
7、解释spring支持的几种bean的作用域
作用域 说明
singleton bean在每个spring ioc容器中只有一个实例,配置文件配置后默认是单例
prototype 一个bean的定义可以有多个实例
request 每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效
session 在一个HTTP Session中,一个bean定义对应一个实例,该作用域仅在基于web的Spring ApplicationContext情形下有效
global-session 在一个HTTP Session中,一个bean定义对应一个实例,该作用域仅在基于web的Spring ApplicationContext情形下有效,缺省的Spring bean的作用域是Singleton
8、spring几种属性装配方式
  1. no:默认的方式是不进行自动装配,通过显示的ref属性进行装配。
  2. byName:通过配置的id进行自动装配,如果在配置文件中bean的autowire属性被设置为byname,那么在进行匹配时,装配和该bean的属性具有相同名字的bean。
  3. byType:通过参数类型自动装配,如果再配置文件中bean的的autowire设置为bytype,在进行匹配时,装配和该bean的属性具有相同类型的bean,如果有多个bean符合条件则抛出异常。
  4. constructor:这个方式类似于byType,但是要提供构造器参数,如果没有确定的带参数的构造器,则会抛出异常。
  5. autodetect:首先尝试使用constructor来自动装配,如果无法工作,则用byType。
9、什么是AOP?

AOP是面向切面编程,是一种编程技术,允许对功能做横向切割,对目标方法做增强,可以有效的增加代码复用性,减少冗余代码。
AOP底层是以jdk动态代理和cglib动态代理技术实现的,jdk的动态代理是对接口方法进行增强,所以要求切入点至少要实现一个接口,否则spring会使用另一个cglib动态代理进行增强,而cglib是在程序运行期间找到继承的父类,并生成代理后的子类。
切面是我们要织入的功能,可以是一个类中的一个方法,也可以是一个类中的多个方法。
切入点是我们要对哪个功能进行增强,在开发中,我们通常理解为一个切入点就是一个方法。
增强的方式也有前置增强,返回前增强,返回后增强,异常增强,环绕增强,总共5中方式,具体使用哪种方法还要参考具体业务逻辑需求。

10、简单说明spring的声明式事务?

spring有自己的一套事务管理机制,一般使用TransactionMananger进行管理,可以通过配置文件进行注入来完成此功能,通过配置可以实现对事务级别和传播性的控制。而底层也是使用到了spring的AOP思想。

11、Spring中BeanFactory和ApplicationContext的区别

ApplicationContext是BeanFactory的子类,两者都有getBean这个核心方法
Beanfactory只用基本只有跟Bean相关的功能,而ApplicationContext则在此基础上有增加了很多bean的细节,且进行了一定程度的封装。

springMVC框架

1、springMVC运行流程
  1. 用户请求发送给DispatcherServlet,DispatcherServlet调用HandlerMapping处理器映射器;

  2. HandlerMapping根据xml或注解找到对应的处理器,生成处理器对象返回给DispatcherServlet;

  3. DispatcherServlet会调用相应的HandlerAdapter;

  4. HandlerAdapter经过适配调用具体的处理器去处理请求,生成ModelAndView返回给DispatcherServlet

  5. DispatcherServlet将ModelAndView传给ViewReslover解析生成View返回给DispatcherServlet;

  6. DispatcherServlet根据View进行渲染视图;

2、什么是DispatcherServlet

Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。

3、Spring MVC的控制器是不是单例模式

是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。

4、Spring MVC怎么和AJAX相互调用的

通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。
这样就可以直接返回一个json字符串形式的json对象,但是要注意方法上要加上@ResponseBody注解,或者类上加@RestController注解。

Mybatis

1、什么是ORM

是对象关系映射,是一种为了解决关系型数据库与java对象的映射技术,ORM是通过使用描述对象和数据库之间的映射关系,将程序中的对象自动持久化到关系型数据库中。

2、MyBatis的工作原理
  1. 读取mybatis配置文件
  2. 加载映射文件
  3. 创建SqlessionFactory(构造会话工厂)
  4. 创建会话对象(SqlSession)
  5. 调用sql执行器
  6. 输入参数映射
  7. 输出结果映射
3、为什么需要预编译
  1. 预编译是指在发送sql语句进行执行之前,对sql语句先进行编译,这样数据库在执行时就不需要再次编译
  2. 还可以预防sql注入
4、Mybatis是否支持延迟加载?

mybatis支持一对一、一对多的延迟加载
当调用方法进行查询时,进入拦截器方法,当判断到关联查询的值为null时,会去查找相对应的sql语句进行二次查询,然后在赋予值。

5、#{}和${}的区别
  1. #{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
  2. Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
  3. #{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入
  4. #{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外
6、模糊查询like语句该怎么写
  1. '%${question}%' 可能引起SQL注入,不推荐
  2. "%"#{question}"%"
  3. CONCAT(’%’,#{question},’%’)
7、mapper中如何对应多个值
  1. 顺序传参法:#{}里的数字代表接口形参中的传入顺序
  2. @Param注解:在接口参数前使用@Param注解指定,#{}中传入的变量名
  3. map传参:#{}中的内容是map中的key值
  4. 对象传参:将传递的参数封装成一个java对象,#{}中传入的是对象的属性
8、Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗

dao接口工作原理是JDK动态代理,在运行时会通过动态代理产生代理对象,代理对象会拦截接口方法,执行所对应的sql语句,随后返回执行结果。

dao接口方法是不能重载的,因为要靠全限定名和方法名去进行拦截处理

9、Mybatis是如何将sql执行结果封装为目标对象并返回的

首先判断返回结果是resultType还是resultMap,如果是ResultType会根据全限定类名查找实体类通过反射创建对象,调用set方法给对象赋值。如果是ResultMap则会直接根据配置的名称和数据库查询后的别名进行映射处理。

10、Mybatis动态sql

Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能
比如

11、Mybatis的缓存机制

mybatis拥有一级和二级缓存

  1. 一级缓存:在操作数据库时需要创建SqlSession对象,在内存中有一个hashMap缓存数据,每一个SqlSession的缓存互不影响,当同一个SqlSession两次执行相同的sql,则会直接去缓存中获取数据,当SqlSession关闭时,缓存清除。
  2. 二级缓存:首先二级缓存是跨session的,多个session可以共享二级缓存,当一个namespace下执行两次同一个语句,并传递相同的参数,则不在从数据库进行查询,直接从二级缓存中获取,mybatis默认开启一级缓存,但是二级缓存默认关闭。

springBoot框架

1、为什么要用SpringBoot

快速开发,快速整合,配置简化、内嵌服务容器

2、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是核心注解,主要包含以下三个注解

  1. @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
  2. EnableAutoConfiguration:打开自动配置的功能
  3. @ComponentScan:Spring组件扫描。
2、SpringBoot事务的使用

首先使用注解EnableTransactionManagement开启事物之后,然后在Service方法上添加注解Transactional便可。

RabbitMQ

1、 MQ的优点
  1. 异步处理,提高了系统吞吐量
  2. 解耦:系统间通过消息通信,不用关心其他系统的处理。
  3. 削峰填谷:可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求.
2、 MQ的几种工作模式
  1. 最简单的收发模式:最简单的发送消息到队列,从队列取出消息并消费
  2. 工作模式:一个队列下挂多个消费者,两者为竞争关系
  3. 广播模式:引入交换机概念,将消息发送至交换机,随后交换机将消息转发至所有绑定该交换机的队列
  4. 路由模式:将消息发送至交换机,并携带一个路由key,交换机通过指定的路由key发送至对应的队列中,由绑定的消费者消费。
  5. 通配符模式:类似路由模式,通过通配符方法,使交换机更加灵活的选择绑定的队列
3、消息基于什么传输

RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制

数据库

mysql

1、数据库分类和常用数据库

数据库分为关系型数据库和非关系型数据库
关系型数据库:
Mysql,Oracle,sqlServer,DB2等

因为关系型数据库的原因,各表之间可以有关联,方便对用户请求数据的分模块、分功能管理,可以使用简单的sql语句就可以做非常复杂的数据查询。

非关系型数据库:
NoSql,Redis,MongoDB

非关系型数据库利用键值对的方式存储数据,不便于存储用户的大量数据,也正是因为这个机制,非关系型数据库经常被用做关系型数据库的缓存,以此减少关系型数据库的压力和资源消耗。

2、关系型数据库三大范式

第一范式: 数据表中的每个字段都具有不可拆分性。也是数据设计中最基本的要求。
第二范式: 在满足第一范式的基础上,消除了部分依赖,解决了删除异常,插入异常和修改异常。
第三范式: 在满足第二范式的基础上,消除了传递依赖。

3、事务的三大特征
  1. 原子性:保证事务中包含的操作为一个独立的数据单元。
  2. 隔离性:保证事务与事务之间不存在相互干扰,保证事务之间的相互独立性
  3. 一致性:保证事务执行结束后数据的一致状态,所有操作要么全部成功,要么全部失败。
4、mysql数据库最大连接数

mysql的最大值是16384,默认值是100,最大连接数同时也根据当前系统的内存、tcp连接数相关,但是一般不建议设置为最大值,这样很容易导致数据库崩溃,一般情况下我们会设置一个最大连接数,用来限制数据库的最大连接,防止访问量过大导致数据库崩溃。

5、MySQL或者Oracle分页语句

select * from table limit 0,5;
0代表开始查找的索引值,5代表查找数量。

6、简单说说jdbc的理解

jdbc是java执行访问数据库的桥梁,它提供了多种主流关系数据库的统一接口。

7、数据库连接池的作用

连接池极大的提高了数据库的性能,极大的节省了数据库资源。
提高获取数据库连接的速度,避免了频繁创建和销毁连接。
方便对数据库连接的管理,方便对数据库连接的调优。

8、mysql优化
  • 为搜索字段建立索引可以提高效率,但是要注意的是建立索引不一定会提高效率,当数据库数据比较少时,通过索引进行查找反而会降低效率,因为查找索引本身也是要消耗资源的。
  • MySQL集群、负载均衡、读写分离
  • 根据需要指定不同的存储引擎
  • 查询时避免多个范围条件
  • 优化关联查询,确保关联的列要有索引,确保group by分组是的列有索引
9、什么是索引
  • 索引也是一种文件,它包含着数据库中所有记录的指针
  • 索引是一种排序数据结构,为了实现快速查找,更新表数据,底层使用B+树进行实现
  • 索引也可以理解为目录,通过查找目录快速定位目标位置,索引本身也是需要占用磁盘空间的
  • 索引的原理是将内容进行排序,并生成倒排表,在倒排表上拼上地址链,在查询时先拿到倒排表,根据地址链指向的地址拿到具体数据。
10、索引失效的场景
  1. 如果条件中有or,即使其中有条件带索引也不会使用,如果想使用or又想使用索引,就需要在条件的每个列上都添加索引
  2. like查询以%开头
  3. 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
  4. 使用联合索引的时候要遵循最左匹配原则,否则索引会失效
11、 B树和B+树的区别

首先B树上,内容节点可以存放键和值,但是B+树的内容节点都是键,所有的值都在叶子节点上
其次B树的每个叶子节点相互独立,B+树的叶子节点有一条链相连

B树可以将经常查询的热点数据放入内容节点中,有利于缩小查找范围,方便快速查找。
B+树因为在叶子节点上有一条链相连,所以查找时会根据链进行顺序查找,也更适合于范围查找。

12、mysql常用的存储引擎
  • MyISAM:MyISAM表是独立于操作系统的,可以轻松的从windows服务器移植到linux服务器,但是MyISAM引擎无法处理事务,这也意味着当需要处理和事务有关的表时,不能使用MyISAM引擎
  • InnoDB:InnoDB是一个强大的支持事务的引擎,并且有较高的并发读取频率,所以Mysql中默认的存储引擎就是InnoDB
  • MEMORY:从名字就可以知道是一个基于内存的存储引擎,为了得到最快的响应时间而在内存中存储表数据,以此达到很高的性能,但是当守护进程崩溃时,所有Memory数据会全部丢失。所以一般用于数据较小的热点数据存储,或者数据是临时的,可以使用该引擎。
13、主从复制、读写分离

当写操作影响数据库查询效率时,这时候就要用到读写分离。
读写分离的基本的原理是让主数据库处理事务性增、改、删操作,而从数据库处理查询操作。我们可以通过主从复制实现数据同步,通过读写分离提升并发负载能力。

14、主从复制的几种方式
  1. 基于语句的复制:在主数据库上执行sql语句,在从数据库上执行同样的语句,而mysql默认采用基于语句复制,并且执行效率高。
  2. 基于行的复制:将改变的内容复制到从服务器,不在进行语句的执行。
  3. 混合类型的复制:属于以上两种方法的合体,平时采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
15、主从复制的过程

首先在主数据库执行完事务操作后,将执行操作写入binlog日志文件,随后通知从数据库进行同步。从数据库会建立一个I/O线程,随后从主数据库中读取事件放入中继日志,如果已经将事件读取完毕,则陷入阻塞状态,等待新的事件到来。随后从数据库从中继日志读取事件进行数据的同步更新。

16、mysql分库分表

当读操作频繁时,我们可以增加从数据库进行读写分离来降低数据库压力,但是当从数据库也变多的时候,我们就要考虑分库。同样当写操作压力很大时,我们也要进行分库操作。

垂直分库:
我们可以按照业务进行拆分,将不同业务的表放在不同的库中,这样就可以减轻单库的操作压力。但是随着数据的增大同样会让数据库的能力达到瓶颈,服务器磁盘、内存也会受到影响,这时候就要将其拆分到多个服务器上。
垂直分表:
一般就是将大表拆成小表,将不常用的字段拆分出来放到扩展表中,避免查询的时候数据量太大造成跨页问题。

水平分表
类似于垂直分库,只是将表的内容做了一定限制,可以减少单表数据量,达到查询效率的提升。
水平分库分表
在水平分表的基础上将数据切片部署在多个服务器中,每个服务器具有相对应的库和表,但是表的数据不同,这样做可以有效缓解数据库的大部分压力。

17、分库分表策略
策略 介绍
哈希取模 根据用户的id进行取模,按照取模后的结果放入不同的数据库
范围分片 比如根据id进行划分,1-10000划入表1,10001-20000划入表2
地理位置分片 按照地理位置进行分片,华东区一个表,华北区一个表
时间分片 按照时间进行分片,比如按年或者月进行分片
18、mysql日志

mysql总共有4种日志类型

日志类型 介绍
Error Log(错误日志) 用于几率sql错误信息
General Query Log(一般查询日志) 记录目前sql正在做的事情
Binary Log(二进制日志) 记录数据库的建表,改动等,可以通过该日志进行数据回滚和主从复制的数据同步
Slow Query Log(慢查询日志) 记录查询时间超过阈值的sql语句,常用于数据库调优
19、mysql事务隔离级别

mysql拥有4种事务隔离界别从低到高分别是
读未提交、读已提交(解决脏读)、可重复读(解决不可重复读)、序列化(解决幻读)

20、mysql锁类别
  • 共享锁: 也叫读锁,在执行查询操作时,对数据上锁,同时可以多个线程拿到这把锁
  • 排它锁: 也叫写锁,在执行事务操作时,对数据上锁,但是只可有一个线程获取这把锁,别的线程必须等待释放锁后才可执行事务操作。
  • 行级锁:是mysql中锁粒度最细的一种锁,只对当前操作行进行加锁,执行事务操作时不会影响其他行的操作,所以能减少数据库操作的冲突,但是加锁的开销也是最大的。同时用可能出现死锁
  • 表级锁:是mysql中锁粒度最大的一种锁,表示对整张表加锁,相比行锁消耗资源较少,并且被大部分mysql引擎支持。
  • 页级锁:是mysql中锁粒度介于行锁和表锁中间的一种锁,因为行锁消耗大,页锁锁定太多,所以折中了这两个锁形成页锁,一次锁定相邻的一组记录。但是同样会出现死锁,锁定粒度介于行锁和表锁之间。
    在innoDB下的行锁是基于索引进行行锁,而主键自带索引,但是如果主键没有索引,那么也无法进行行锁,直接升级为表锁。
21、什么是游标,存储过程,触发器
  • 游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理

  • 存储过程是一个预编译的SQL语句,允许模块化的设计,只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。

  • 触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。

22、常用触发器
  • Before Insert
  • After Insert
  • Before Update
  • After Update
  • Before Delete
  • After Delete
23、BTree 与 Hash 索引有什么区别

Hash索引是通过hash函数计算出hash值在表中查找对应的数据,所以在精确查找上hash索引要快

BTree索引底层使用B+树实现,要多次使用折半查找来找到对应的数据,所有数据都存放在叶子节点上,并且每个叶子节点之间都有链相连,所以BTree索引支持范围查找,模糊查询。

Redis

1、Redis的优点
  • 读写性能优异
  • 支持数据持久化
  • 支持事务
  • 数据结构丰富
  • 支持主从复制,读写分离,分片,集群
2、Redis为甚么执行效率快
  1. 单线程操作,不存在多线程切换小号cpu,不用考虑锁的问题,所以不会出现死锁
  2. 是基于内存实现的,避免大量的访问数据库,减少直接读取磁盘的数据
  3. 采用了非阻塞IO多路复用机制
3、redis事务的特征
  1. 开启事务后所有命令都将变为串行化进行执行,在执行期间,redis不再为其他客户端的请求提供服务,从而保证事务的原子性。
  2. 在执行期间如果出现某一条命令执行失败,后面的命令仍会继续执行。
4、redis同步机制

全量同步

  1. 从节点第一次连接主节点时,主节点会生成rdb文件,期间所有写命令被放入缓存区,生成rdb后发送给从节点
  2. 从节点抛弃旧数据,执行rdb文件,随后执行主节点缓存区的命令
  3. 之后主节点的每一条写命令都会发送给从节点去执行。

增量同步
4. 如果出现网络问题导致的数据丢失情况,从节点自身已经保存了已复制的偏移量和主节点id
5. 主节点根据偏移量将缓存区的数据发送给从节点,保证主从复制状态的正常。

5、redis持久化机制

有RDB和AOF两种方式做持久化,RDB做快照持久,AOF做增量持久

RDB根据快照保存当前数据库中的信息,随后开启一个线程创建RDB文件,但是RDB机制依旧会存在一定问题,因为它是每隔一段时间进行快照,这种方式会造成上次快照时间到这一秒中的数据丢失。

AOF是遵循redis协议对执行的命令进行持久化,redis会记录下所有变更数据库状态的命令,redis在载入AOF文件的时候,把AOF中每一条命令都执行一遍,最终还原回数据库的状态,它的载入也是自动的。在RDB和AOF文件都有的情况下,redis会优先载入AOF文件

5、redis集群搭建
  1. 使用主从复制,达到一个主节点下挂多个从节点,使数据冗余,同时还可以实现读写分离,减轻redis压力,但是也存在一定问题,当主节点挂掉以后,相当于整个redis集群还是都挂掉了,并没有提升高可用,所以我们要引入哨兵机制。
  2. 利用哨兵对主节点和从节点进行监控,为了防止哨兵存在挂掉的情况,哨兵也是可以搭建集群的。而监控的方式是乒乓机制,每隔一段固定时间就会向所监控的节点发送ping,节点会回复pang,如果监控的节点没有进行回复,则哨兵会将此节点判定为下线状态,并通过投票选举出一个新的主节点。但是这样依旧存在一个问题,redis的容量受限于单机配置。
  3. cluster解决了redis分布式存储,也就是每个节点存储的不通的内容来解决在线扩容的问题,对数据进行分片处理,所有的在redis的节点上有个哈希槽,取值为0-16383,当存取key时会g恩局CRC16算法和取模运算得出一个余数,随后会放到对应的哈希槽中,这样每个值都对应一个槽,通过这个值可以去不同节点对相应的key值进行操作。同样为了保证高可用也可以引用主从和哨兵,集群搭建最少要配置6个节点,3主3从,主节点实现读写操作,从节点作为备份节点,同样哨兵也可以搭建集群避免哨兵宕机。
6、redis应用场景
  1. 缓存:将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。
  2. 排行榜:ZSet 可以实现有序性操作,从而实现排行榜等功能。
  3. 计数器:可以对string进行自增自减运算,因为是内存型数据库,所以读写效率非常高,很适合频繁的读写
7、redis过期键删除策略
  1. 定时删除:每个key设定一个时间,到达时间后自动删除,可以达到实时删除的目的,对内存友好,但是需要占用cpu大量资源去监控定时器。
  2. 惰性删除:只有在访问一个key时,才回去判断是否过期,如果过期则删除,相比定时删除,对cpu友好,但是可能存在一个key一直不被访问,所以也没办法删除,导致占用内存。
  3. 定期删除:上面两种的这种方案,每隔一段时间会扫描一定数量的key,并清除中间已经过期的key值,这样达到了内存和cpu的最优平衡效果,
8、redis内存淘汰

全局的键空间选择删除策略:

  1. 当内存不足容纳新数据时,会执行失败
  2. 当内存不足容纳新数据时,会删除最近最少使用的key
  3. 当内存不足容纳新数据时,会随机删除某个key

设置过期时间的键空间选择性的删除:

  1. 当内存不足容纳新数据时,在设置了过期时间中,移除最少使用的key
  2. 当内存不足容纳新数据时,在设置了过期时间中,随机移除某个key
  3. 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

你可能感兴趣的:(面试,面试)