首页 > 基础资料 博客日记
java经典面试题—2023
2023-07-24 14:54:23基础资料围观222次
java经典面试题—2023
一、Java基础
Java基础知识
1、&和&&的区别?
&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。
2、final, finally, finalize的区别?
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖 此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
3、"= ="和 equals 方法究竟有什么区别?
答:== 操作符: 专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储 的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
equals: 方法是用于比较两个引用对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。
4、String 和StringBuffer的区别?
String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
5、StringBuffer与StringBuilder的区别?
StringBuffer和StringBuilder类都表示内容可以被修改的字符串,**StringBuilder是线程不安全的,运行效率高,**如果一个字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder。如果要在类里面定义成员变量,并且这个类的实例对象会在多线程环
境下使用,那么最好用StringBuffer。
6、Overload(重载)和Override(重写)的区别?
两者都是多态的表现
1)重写(Override):
1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同
1.2)遵循"运行期绑定",根据对象的类型来调用方法
2) 重载(Overload):
2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同
2.2)遵循"编译期绑定",根据引用的类型来绑定调用方法
7、接口和抽象类的区别是什么?
1).抽象类可以有构造方法,接口中不能有构造方法。
2).抽象类中可以有普通成员变量,接口中没有普通成员变量
3). 一个类可以实现多个接口,但只能继承一个抽象类
4). 抽象类中可以包含静态方法,接口中不能包含静态方法
5).抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普 通方法。
8、java中实现多态的机制是什么?
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
9、面向对象的三大特征:
1.封装:
1)类:封装的是对象的属性和行为
2)方法:封装的是特定的业务逻辑实现
3)访问控制修饰符:封装的是访问的权限
2.继承:
1)作用:代码复用
2)超类:所有派生类所共有的属性和行为
接口:部分派生类所共有的行为
派生类:派生类所特有的属性和行为
3)传递性、单一继承,多接口实现
3.多态:
1)意义:行为多态(抽象方法都是多态的)
对象多态(所有对象都是多态的)
2)向上造型、强制类型转换、instanceof判断
3)多态的表现形式:
3.1)重写:根据对象的不同来表现多态
3.2)重载:根据参数的不同来表现多态
10、字节流和字符流的区别?
答:字节流读取的时候,读到一个字节就返回一个字节;字符流使用了字节流读到一个或多个字 节时。先去查指定的编码表,将查到的字符返回。
字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。
只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
11、Java 中有几种类型的流?
(1)按照流的方向:输入流(inputStream)和输出流(outputStream);
(2)按照实现功能分:节点流(可以从或向一个特定的地方(节点)读写数据。
(3)按照处理数据的单位: 字节流和字符流。字节流继承于 InputStream 和 OutputStrea,字符 流继承于InputStreamReader 和 OutputStreamWriter 。
12、字节流如何转为字符流?
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。
13、什么是Java的反射?
在运行状态中,对于任意一个类,都能够知道这个类的属性和方法;
14、反射的作用?
如果给定一个类名,就可以通过反射机制来获取类的所有信息,也可以动态的创建对象和编译;
15、反射的原理?
Java语言在编译之后会生成一个class文件,反射就是通过字节码文件找到其类中的方法和属性等;
反射的实现主要借助以下四个类:
1、Class:类的对象;
2、Constructor:类的构造方法
3、Field:类中的属性对象
4、Method:类中的方法对象
16、什么是反射机制?
答:通过类(Class对象),可以当前类的filed,method,contrutor,interfqce,superClass
,modified等,同是可以通过类实例化一个类,设置属性,唤醒方法。在Spring中一切都是反射。
17、浅克隆和深克隆的区别
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原 有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
18、什么是java序列化,如何实现java序列化?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
19、java有23中设计模式
设计模式分为三大类:
创建型模式,共五种:
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:
策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、
备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
20、单例模式:
什么叫单例模式?
指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪 费,或出现各个窗口显示内容的不一致等错误。
在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对 象、打印机的后台处理服务都是单例模式
单例模式有什么特点?
1.单例类只有一个实例对象;
2. 该单例对象必须由单例类自行创建;
3. 单例类对外提供一个访问该单例的全局访问点;
主要:
饿汉式(线程安全,调用效率高,但是不能延时加载)
懒汉式(线程安全,调用效率不高,但是可以延时加载)
其他:
双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
静态内部类式(线程安全,调用效率高。但是可以延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
饿汉模式和懒汉模式相关代码实现
1.饿汉模式,线程安全
public class Singleton {
private Singleton(){};
private static Singleton instance = new Singleton();
public static Singleton get Instance(){
return instance;
}
}
将需要获取的 instance 实例在类加载的时候就实例化完毕,由于类的加载机制,此时静态变量的实例化只会执行一遍,所以可以保证此实例变量的唯一性。但是此时不具有延迟加载的特性。
2.面试官又问:线程安全还有其他写法吗?
懒汉模式,线程不安全 用Synchronized 修饰表示线程安全
public class Singleton {
private Singleton(){};
private static Singleton instance;
public static Singleton get Instance(){
//public synchronized static Singleton get Instance(){Synchronized 修饰表示安全
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
原来:懒汉模式指的是这个单例类在用的时候会延迟加载,但是这个单例类是线程不安全的,在多线程环境下很容易出现多个实例的情况。
懒汉模式,线程安全
原理:只要在上面的线程不安全模式下进行简单的修改就可以编程线程安全的,将 getInstance 方法 用 Synchronized 修饰,确保同一个时刻只能有一个线程访问此方法。
21、工厂模式:
简单工厂模式:用来生产同一等级结构中的任意产品(对已有产品新增功能,需要修改源代码)
虽然能通过工厂来创建对象,但是违反了开闭原则。一旦增加功能需要在原有基础上修改代码。
工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品,不用修改源代码)
将工厂类调整为工厂接口,需要什么类型的工厂就使用该类实现该工厂,创建相应的产品。
22、观察者模式:
也叫(发布-订阅模式)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题 对象,这个主题对象在状态发生变化时,会通知所有观察者对象。使它们能够自动更新自己。
例如:发广播,游戏中大喇叭,群聊
jdk中提供了抽象主题和抽象观察者的接口,我们可以使用这两个接口来方便的定义自己的观察者模式。
23、代理模式:
代理模式分类:
- 静态代理(静态定义代理类,我们自己静态定义的代理类。比如我们自己定义一个明星的经纪人类)
- 动态代理(通过程序动态生成代理类,该代理类不是我们自己定义的。而是由程序自动生成)比较 重要!!
24、Java中有那些集合?
Set,list,map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。
list和set都继承自collection接口。
Set的实现类主要有HashSet,TreeSet和LinkedHashSet:
List的实现类主要有ArrayList,
Map的实现类主要有HashMap和TreeMap。
25、List,Set和Map的区别?
List: 有序集合,元素可重复
Set: 不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序
Map: map集合是以键值对方式存储;Key无序,唯一;value 不要求有序,允许重复。
26、HashMap和Hashtable有什么区别?
1、HashMap是非线程安全的,HashTable是线程安全的。
2、HashMap的键和值都允许有null值存在,而HashTable则不行。
3、因为线程安全的问题,HashMap效率比HashTable的要高。
4、Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
一般现在不建议用HashTable, ①是HashTable是遗留类,内部实现很多没优化和冗余。②即 使在多线程环境下,现在也有同步的ConcurrentHashMap替代,没有必要因为是多线程而用 HashTable。
27、Java中的HashMap的工作原理是什么?
我们知道在Java中最常用的两种结构是数组和模拟指针(引用),几乎所有的数据结构都可以利用这两种来组合实现,HashMap也是如此。实际上HashMap是一个“链表散列”,如下是它数据结构:最左侧是一个数组,数组中的每一个元素都是一个链表,链表的每一个元素都是entry。
HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。
28、Array和ArrayList有什么区别?什么时候应该使用Array而不是ArrayList?
Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
Array大小是固定的,ArrayList的大小是动态变化的。
ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类 型的时候,这种方式相对比较慢。
29、ArrayList和LinkedList有什么区别?
ArrayList和LinkedList都实现了List接口,他们有以下的不同点:
• ArrayList是基于索引的数据接口**,它的底层是数组**。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素链表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
• 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
• LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
也可以参考ArrayList vs. LinkedList。
30、说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而 Linke dList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
List的子类特点:
ArrayList:
底层数据结构是数组,查询快,增删慢,线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢,线程安全,效率低。
LinkedList:
底层数据结构是链表,查询慢,增删快,线程不安全,效率高。
31、HashSet和TreeSet有什么区别?
HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。
32、HashSet实现原理?
1、基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
2、当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode()方法,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。
通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
3、HashSet的其他操作都是基于HashMap的。
33、在JAVA中Map和HashMap有什么区别?
Map集合的特点:
1、Map集合一次存储两个对象,一个键对象,一个值对象
2、键对象在集合中是唯一的,可以通过键来查找值
HashMap特点:
1、使用哈希算法对键去重复,效率高,但无序
2、HashMap是Map接口的主要实现类
34、什么是HashMap
HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许重复的键。Map接口有两个基本的实现,HashMap和TreeMap。TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null。HashMap是非synchronized的,但collection框架提供方法能保证HashMap synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。
public Object put(Object Key,Object value)方法用来将元素添加到map中。
35、HashSet和HashMap的区别
HashMap HashSet
HashMap实现了Map接口 HashSet实现了Set接口
HashMap储存键值对 HashSet仅仅存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode
可能相同,所以equals()方法用来判断对象的相等性,
如果两个对象不同的话,那么返回false
HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢
36、如何在Java中实现线程?
由于线程类本身就是调用的Runnable接口所以你可以继承java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。
37、线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。
38、线程的生命周期?
线程一共有五个状态,分别如下:
新建(new):当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
运行(running):线程获得 CPU 资源正在执行任务(#run() 方法),
死亡(dead):当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
堵塞(blocked):由于某种原因导致正在运行的线程让出 CPU 并暂停自己的执行,即进入堵塞状态。直到线程进入可运行(runnable)状态,才有机会再次获得 CPU 资源,转到运行(running)状态。阻塞的情况有三种:
调用 notify() 方法,回到就绪状态。
39、创建线程有几种不同的方式?
有三种方式可以用来创建线程:
• 继承Thread类
• 实现Runnable接口
• 应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别 的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非 常高效的,很容易实现和使用。
40、sleep() 和 wait() 有什么区别?
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或not ifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
41、Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。
42、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
43、如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
44、什么是死锁(deadlock)?
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷 入了无限的等待中。
45、java 线程安全和不安全
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。(Vector,HashTab;le)
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。(ArrayList,LinkedList,HashMap等)
46、什么是线程安全?Vector是一个线程安全类吗?
多个线程可能会同时运行同一段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。
47、 什么是线程池? 为什么要使用它?
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)
48、 如何避免死锁?
Java多线程中的死锁
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:
互斥条件: 一个资源每次只能被一个进程使用。
请求与保持条件: 一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件: 进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件: 若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。
49、Java中活锁和死锁有什么区别?
这是上题的扩展,活锁和死锁类似,不同之处在于处于活锁的线程或进程的状态是不断改变的,活锁可以认为是一种特殊的饥饿。一个现实的活锁例子是两个人在狭小的走廊碰到,两个人都试着避让对方好让彼此通过,但是因为避让的方向都一样导致最后谁都不能通过走廊。简单的说就是,活锁和死锁的主要区别是前者进程的状态可以改变但是却不能继续执行。
50、有三个线程T1,T2,T3,怎么确保它们按顺序执行?
在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
51、守护线程和非守护线程有什么区别?
程序运行完毕,JVM 会等待非守护线程完成后关闭,但是 JVM 不会等待守护线程
JVM
1、什么情况下会发生栈内存溢出?
1、栈是线程私有的,栈的生命周期和线程一样,每个方法在执行的时候就会创建一个栈帧,它包含局部变量表、操作数栈、动态链接、方法出口等信息,局部变量表又包括基本数据类型和对象的引用;
2、当线程请求的栈深度超过了虚拟机允许的最大深度时,会抛出StackOverFlowError异常,方法递归调用肯可能会出现该问题;
3、调整参数-xss去调整jvm栈的大小
2、什么是类加载器,常见的类加载器有哪些?
类加载器是指:通过一个类的全限定性类名获取该类的二进制字节流叫做类加载器;
类加载器分为以下四种:
启动类加载器:
用来加载java核心类库,无法被java程序直接引用;
扩展类加载器:
用来加载java的扩展库,java的虚拟机实现会提供一个扩展库目录,该类加载器在扩展库目录里面查找并加载java类;
系统类加载器:
它根据java的类路径来加载类,一般来说,java应用的类都是通过它来加载的;
自定义类加载器:
由java语言实现,继承自ClassLoader;
3、Java内存模型是什么?
Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。
4、heap和stack有什么区别?
java的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。
堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用final修饰后,放在堆中,而不是栈中。
JDBC
1、Statement对象
优点: 在一次批处理中,SQL表现的更加灵活。
缺点: 速度慢,不能防止SQL攻击
2、PreparedStatement对象?
优点: 速度快,可以防止SQL注入攻击
缺点: 在一次批处理中,SQL不灵活,只处理骨架相同的SQL。
3、Session生命周期?
当程序第一次调用到request.getSession()代码时,服务器明确的知道了需要用到session了,此时创建session。
如果session超过30分钟(可以在web.xml中配置的)没人使用,服务器认为这个session超时了,销毁session。
明确的调用session.invalidate(),session立即销毁。
服务器被非正常关闭或web应用被移除出容器,此时随着web应用的销毁session销毁.如果是正常关闭,session会被钝化.当下次服务器正常启动时,没有超时的session还会被活化回来。
4、session的原理?
session的原理:在服务器第一次调用request.getSession()方法的时候,会在内存中创建一个session对象,此对象具有一个独一无二的id值,此id值将会以cookie(JSESSIONID)的形式发送给浏览器,浏览器以后每次访问都会带着此cookie,服务器就利用此cookie区分浏览器找到对应的session空间。
5、cookie与session的区别
cookie数据存放在客户的浏览器上,session数据放在服务器上
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE
Java面试题–数据结构
具体面试算法题—编程题2023
1、排序算法对比
算法 时间复杂度(平均) 最好 最坏 稳定性
冒泡排序 o(n^2) n o(n^2) 稳定
插入排序 o(n^2) n o(n^2) 稳定
选择排序 o(n^2) o(n^2) o(n^2) 不稳定
2、递归算法:
优点: 代码简洁、清晰,并且容易验证正确性。
缺点: 它的运行需要较多次数的函数调用,如果调用层数比较深,需要增加额外的堆栈处理(还有可能出现堆栈溢出的情况),比如参数传递需要压栈等操作,会对执行效率有一定影响。但是,对于某些问题,如果不使用递归,那将是极端难看的代码。在编译器优化后,对于多次调用的函数处理会有非常好的效率优化,效率未必低于循环。
3.循环算法:
优点: 速度快,结构简单。
缺点: 并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环。
Java面试题–网络
1、当你用浏览器打开一个链接的时候,计算机做了哪些工作步骤。
(1)、解析域名。
(2)、发起TCP的3次握手。
(3)、建立TCP请求后发起HTTP请求。
(4)、服务器相应HTTP请求。
(5)、浏览器得到HTML代码,进行解析和处理JSON数据,并请求HTML代码中的静态资源(JS、CSS、图片等)。
(6)、浏览器对页面进行渲染。
2、什么是http协议?
HTTP协议就是一套基于tcp/ip协议的应用层协议 。简单来说,就是一个基于应用层的通信规范,双方要进行通信,大家都要遵守一个规范,这个规范就是HTTP协议。它规定了客户端(通常是浏览器)和服务器之间的通信方式。
3、Http与Https的区别:
HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头
HTTP 是不安全的,而 HTTPS 是安全的
HTTP 标准端口是80 ,而 HTTPS 的标准端口是443
在OSI 网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层
HTTP 无法加密,而HTTPS 对传输的数据进行加密
HTTP无需证书,而HTTPS 需要CA机构颁发的SSL证书
6、get和post请求的区别?
(1)get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
(2)get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?“连接, 而各个变量之间使用”&“连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action 所指向URL;
(3)get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据, POST数据是没有限 制的,上传文件通常要使用post方式;
(4)使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还 是应用使用post;
(5)get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递 参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是”%20"。
(6)Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost()。
7、TCP三次握手:
发送方: 我要和你建立链接?
接收方: 你真的要和我建立链接么?
发送方: 我真的要和你建立链接,成功。
8、为什么 TCP 连接需要三次握手,两次不可以么,为什么?
为了防止已失效的连接请求报文突然又传送到了服务端,因而产生错误。客户端发出的连接请求报文并未丢失,而是在某个网络节点长时间滞留了,以致延误到链接释放以后的某个时间才到达 Server 。
9、什么是 TCP 四次挥手?
四次挥手,简单来说,就是:
发送方:我要和你断开连接!
接收方:好的,断吧。
接收方:我也要和你断开连接!
发送方:好的,断吧。
10、tcp与UDP的区别
TCP 是面向连接的;UDP 是无连接的。
TCP 是可靠的;UDP 是不可靠的。
TCP 只支持点对点通信;UDP 支持一对一、一对多、多对一、多对多的通信模式。
TCP 是面向字节流的;UDP 是面向报文的。
TCP 有拥塞控制机制;UDP 没有拥塞控制,适合媒体通信。
TCP 首部开销(20 个字节),比 UDP 的首部开销(8 个字节)要大。
11、描述Servlet调用过程?
(1)在浏览器输入地址,浏览器先去查找hosts文件,将主机名翻译为ip地址,如果找不到就再去查 询dns服务器将主机名翻译成ip地址。
(2)浏览器根据ip地址和端口号访问服务器,组织http请求信息发送给服务器。
(3)服务器收到请求后首先根据Host请求头判断当前访问的是哪台虚拟主机。
(4)服务器根据http请求头中的请求URI判断当前访问的是哪个web应用。
(5)服务器根据http请求头中的请求URI判断当前访问的是web应用中的哪个web资源。
(6)检查web应用的web.xml文件,如果根据路径找到具体的servlet处理类的全路径名交给该 ervlet处理,如果找不到就交给缺省servlet处理。
(7)这个过程中浏览器只知道自己发出来http请求,不久就收到了http响应,浏览器不知道也不关 心服务器内部是如何处理的。浏览器和服务器之间的关系是非常单纯的,只有HTTP协议。
(8)解析请求、封装RequestResponse对象、创建Servlet、调用Service方法都是服务器自动进 行 的,开发人员只需要写好Servlet配置进容器中即可,无需操心具体的底层实现。
12、Servlet的生命周期?
1:实例化:容器收到请求时,会创建一个serlvet实例。
2:初始化:容器在创建好servlet对象之后,会接着调用servlet对象的init()方法。
注意:该方法只会执行一次。作用是,获取资源。
3:就绪:调用servlet对象的service()方法
4:销毁:容器会依据自身的算法,删除servlet对象。在删除之前,会先调用destroy()方法。
13、重定向和转发的区别?
重定向:两次请求,地址改变,可以重定向到外部资源,两次请求不能共享数据;
转发:一次请求,地址不变,只能转发项目内的资源,转发时2个组件可以共用数据;
14、404和500是什么意思
答:404 :找不到url请求的路径,一般是工程名不对或者拼写错误
500 :服务器内部错误,一般是服务器内部代码编写错误,也有可能是抛异常导致
二、Java框架
MyBatis
1、谈谈你对mybatis架构的理解?
MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis封装了几乎所有的JDBC代码和参数的手工设置以及结果集的检索;MyBatis使用简单的XML或注解做配置和定义映射关系,将Java的POJOs(Plain Old Java Objects)映射城数据库中的记录.
MyBatis的优缺点
优点:
1、简单易学
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和 优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元 测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳。
总结
mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。
mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql
2、MyBatis核心文件
MyBatis 核心应用组件:
配置文件(提供基础配置信息,例如连接配置,缓存配置,映射配置)
映射文件(定义SQL映射):ORM
3、MyBatis 核心API
SqlSessionFactoryBuilder (负责读取配置文件,创建SqlSessionFactory对象)
SqlSessionFactory(负责创建SqlSession对象)
SqlSession(负责连接的维护,事务的处理,类似JDBC中的Connection)
…
4、MyBatis 框架编程中映射文件内部的对象别名配置?
配置文件中通过typeAliases元素进行配置
应用于映射文件中参数类型(parameterType),结果类型(resultType)
5、#{}和${}的区别是什么?
-
#{} 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符;而${}仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。
-
#{} 解析之后会将String类型的数据自动加上引号,其他数据类型不会;而${} 解析之后是什么就是什么,他不会当做字符串处理。
-
#{} 很大程度上可以防止SQL注入(SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作);而${} 主要用于SQL拼接的时候,有很大的SQL注入隐患。
-
在某些特殊场合下只能用${},不能用#{}。例如:在使用排序时ORDER BY ${id},如果使用#{id},则会被解析成ORDER BY “id”,这显然是一种错误的写法。
6、Mybatis是如何进行分页的?分页插件的原理是什么?
答:Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
举例: select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10
10、MyBatis实现一对一有几种方式?具体怎么操作的
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面 的结果的外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表 的查询通过select属性配置
11、MyBatis实现一对多有几种方式,怎么操作的
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次,通过在resultMap里面配 置collection节点配置一对多的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的 查询通过select节点配置
13、Mybatis 和 Mybatis Plus 的区别
Mybatis-Plus是一个Mybatis的增强工具,只是在Mybatis的基础上做了增强却不做改变,MyBatis-Plus支持所有Mybatis原生的特性,所以引入Mybatis-Plus不会对现有的Mybatis构架产生任何影响。
MyBatis-Plus 优点
1、依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring 。
2、损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 。
3、预防Sql注入:内置 Sql 注入剥离器,有效预防Sql注入攻击 。
4、通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求 。
5、多种主键策略:支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题 。
6、支持热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
7、支持ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作
8、支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码(生成自定义文件,避免开发重复代码),支持模板引擎、有超多自定义配置等。
9、支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )。
10、支持关键词自动转义:支持数据库关键词(order、key…)自动转义,还可自定义关键词 。
11、内置分页插件:基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询。
12、内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询 。
13、内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,预防误操作。
14、默认将实体类的类名查找数据库中的表,使用@TableName(value=”table1”)注解指定表名,@TableId指定表主键,若字段与表中字段名保持一致可不加注解。
Spring框架
1、什么是spring?
spring 是个Java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。
Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯
2、使用Spring框架的好处是什么?
轻量:Spring 是轻量的,基本的版本大约2MB。
控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
容器:Spring 包含并管理应用中对象的生命周期和配置。
MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,hibernate or JDO抛出的)转化为一致的unchecked 异常。
3、什么是IOC
1.IOC就是控制反转,就是将对象创建的权利交给spring容器来完成。
从此程序员无需关注对象的创建过程。spring容器来维护对象的生命周期。
4、什么是AOP
1.切面(Aspect):就是完成额外任务的类
2.连接点(Joinpoint):就是调用的目标方法
3.通知(Advice):切面中的方法
4.切入点(Pointcut):匹配连接点的断言。(执行通知的if,就是一个匹配规则)
5、 IOC的优点是什么?
IOC 或 依赖注入把应用的代码量降到最低。它使应用容易测试,单元测试不再需要单例和JNDI查找机制。最小的代价和最小的侵入性使松散耦合得以实现。IOC容器支持加载服务时的饿汉式初始化和懒加载。
6、AOP的实现原理
当获取对象时,首先将对象与切入点表达式进行匹配。如果匹配成功,
则会创建代理对象。然后代理对象执行方法时就会执行通知。
7、 在Spring AOP 中,关注点和横切关注的区别是什么?
关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。
横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如
日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点
8、 解释Spring支持的几种bean的作用域。
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.
9、spring的核心类有哪些
BeanFactory:产生一个新的实例,可以实现单例模式
BeanWrapper:提供统一的get及set方法
ApplicationContext:提供框架的实现,包括BeanFactory的所有功能
10、spring的接口有哪些
1.BeanFactory最基础最核心的接口
2.Resource接口,可以通用地访问文件资源
3.FactoryBean工厂bean
4.MessageSource接口
11、spring事务的回滚策略
1.运行时异常:
如果程序出现运行时异常,那么错误级别较高,spring会自动的回滚事务。
2.检查异常:
对于检查异常而言,spring认为检查异常是可以避免的,程序员 可以修复的,
那么spring容器就不负责回滚检查异常。
12、 Spring框架的事务管理有哪些优点?
它为不同的事务API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式。
它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API如
它支持声明式事务管理。
它和Spring各种数据访问抽象层很好得集成
13、解释Spring Bean的生命周期?
在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean不在被调用时需要进行相关的析构操作,并从bean容器中移除。
Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。
1.初始化之后调用的回调方法。
2.销毁之前调用的回调方法。
Spring框架提供了以下四种方式来管理bean的生命周期事件:
InitializingBean和DisposableBean回调接口
针对特殊行为的其他Aware接口
Bean配置文件中的Custom init()方法和destroy()方法
@PostConstruct和@PreDestroy注解方式
14、Spring框架中的单例Beans是线程安全的么?
Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和DAO类),
所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。
最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。
15、Spring 框架中都用到了哪些设计模式?
代理模式—在AOP和remoting中被用的比较多。
单例模式—在spring配置文件中定义的bean默认为单例模式。
模板方法—用来解决代码重复的问题。
比如. RestTemplate, JmsTemplate, JpaTemplate。
前端控制器—Srping提供了DispatcherServlet来对请求进行分发。
视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
工厂模式—BeanFactory用来创建对象的实例。
Spring MVC框架
1、什么是Spring MVC ?简单介绍下你对springMVC的理解?
Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块,无需中间整合层来整合 ,它和Struts2一样都属于表现层的框架。在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
2、SpringMVC的优点和缺点:
优点:
(1)使用简单,学习成本低。
(2)很容易就可以写出性能优秀的程序.
(3)灵活性强,Spring MVC的框架易扩展
缺点:
(1)Spring与MVC 的Servlet API 耦合,难以脱离容器独立运行
(2)太过于细分,开发效率低
(3)过度追求完美,有过度设计的危险解决的问题领域是:网站应用程序或者服务开发
—— URL路由、Session、模板引擎、静态Web资源等等。
3、Spring MVC的主要组键?
(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果 相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
(4)处理器Handler(需要程序员开发)
(5)视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析 根据视图逻辑名解析成真正的视图(view)
(6)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
4、SpringMVC工作原理:
1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。
2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.
3.DispatcherServlet请请求提交到目标Controller
4.Controller进行业务逻辑处理后,会返回一个ModelAndView
5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
6.视图对象负责渲染返回给客户端。
5、Springmvc 拦截器
概念:Java 里的拦截器是动态拦截 action 调用的对象。它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个 action 执行前阻止其执行,同时也提供了一种可以提取 action 中可重用部分的方式。在AOP(Aspect-Oriented Programming,面向切面编程)中拦截器用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作。
**原理:**拦截器 Interceptor 的拦截功能是基于 Java 的动态代理来实现的,具体可以参考博文“ 用 Java 实现拦截器 Interceptor 的拦截功能 ”,也可以通过阅读 Spring 源代码来了解更为权威的实现细节。
实现方法:在 Spring 框架之中,咱们要想实现拦截器的功能,主要通过两种途径,第一种是实现HandlerInterceptor接口,第二种是实现WebRequestInterceptor接口。接下来,咱们分别详细的介绍两者的实现方法。
应用场景:
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如Hibernate,在进入处理器打开Session,在完成后关闭Session。
…………本质也是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。
实现方法:
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
6、拦截器的调用:
Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。在HandlerAdapter处理之后,以及处理完成之后会调用HandlerExecutionChain的方法。用内部实现HandlerInterceptor该接口集合的各个对应方法。
7、MVC设计模式
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式: [1]
Model(模型) 表示应用程序核心(比如数据库记录列表)。
View(视图) 显示数据(数据库记录)。
Controller(控制器) 处理输入(写入数据库记录)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
8、springMVC和struts2的区别有哪些?
(1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。
(2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
(3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
(4)springmvc可以单例开发,struts2只能是多例开发。
9、SpringMVC怎么样设定重定向和转发的,以及他们的区别?
(1)在返回值前面加"forward:“就可以让结果转发,譬如"forward:user.do?name=method4”
(2)在返回值前面加"redirect:"就可以让返回值重定向,譬如"redirect:http://www.baidu.com”
1、转发是一次请求,一次响应,而重定向是两次请求,两次响应。
2、转发:servlet和jsp共享一个request,重定向:两次请求request独立,所以前面request里面 setAttribute()的任何东西,在后面的request里面都获取不到
3、转发:地址栏不会改变,重定向:地址栏发生变化。
10、SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?
答:是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。
11、@RequestMapping注解用在类上面有什么作用?
答:是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
怎么样把某个请求映射到特定的方法上面?
答:直接在方法上面加上注解@RequestMapping,并且在这个注解里面写上要拦截的路径。
三、Java微服务
Spring boot
1、SpringBoot简介
SpringBoot 是一个快速开发的框架, 封装了Maven常用依赖、能够快速的整合第三方框架;简化XML配置,全部采用注解形式,内置Tomcat、Jetty、Undertow,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringBoot原理介绍:
- 能够帮助开发者实现快速整合第三方框架 (原理:Maven依赖封装)
- 去除xml配置 完全采用注解化 (原理:Spring体系中内置注解方式)
- 无需外部Tomcat、内部实现服务器(原理:Java语言支持创建Tomcat服务器)
2、Spring Boot优点?
快速创建独立运行的spring项目与主流框架集成
使用嵌入式的servlet容器,应用无需打包成war包
starters自动依赖与版本控制
大量的自动配置,简化开发,也可修改默认值
准生产环境的运行应用监控
与云计算的天然集成
3、Spring Boot 缺点?
入门简单精通难,各种强大的功能封装的太好了,内部原理比较难得参透!再就是用多了容易产 生依赖,就像嗑药似的,用了就离不开了;SpringBoot一旦出了错误,由于内部封装比较深,部分 错误调试难度比一般Spring应用程序要大很多
4、SpringBoot和SpringMVC区别
SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringMVC是控制层。
5、SpringBoot和SpringCloud区别
SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringMVC是控制层。
SpringCloud依赖与SpringBoot组件,使用SpringMVC编写Http协议接口,同时SpringCloud是一套完整的微服务解决框架。
6、Spring Boot 提供了哪些核心功能?
1、独立运行 Spring 项目
2、内嵌 Servlet 容器
Spring Boot 可以选择内嵌 Tomcat、Jetty 或者 Undertow,这样我们无须以 war 包形式部署项目。
3、提供 Starter 简化 Maven 配置
例如,当你使用了 spring-boot-starter-web ,会自动加入如下依赖:spring-boot-starter-web
的 pom 文件
7、自动配置 Spring Bean
Spring Boot 检测到特定类的存在,就会针对这个应用做一定的配置,进行自动配置 Bean ,这样会极大地减少我们要使用的配置。
8、准生产的应用监控
Spring Boot 提供基于 HTTP、JMX、SSH 对运行时的项目进行监控。
9、如何重新加载Spring Boot上的更改,而无需重新启动服务器?
这可以使用DEV工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat将重新启动。
Spring Boot有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。
开发人员可以重新加载Spring Boot上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot在发布它的第一个版本时没有这个功能。
这是开发人员最需要的功能。DevTools模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供H2数据库控制台以更好地测试应用程序。
org.springframework.boot
spring-boot-devtools
true
10、创建一个 Spring Boot Project 的最简单的方法是什么?
Spring Initializr 是创建 Spring Boot Projects 的一个很好的工具
11、运行 Spring Boot 有哪几种方式?
1、打包成 Fat Jar ,直接使用 java -jar 运行。目前主流的做法,推荐。
2、在 IDEA 或 Eclipse 中,直接运行应用的 Spring Boot 启动类的 #main(String[] args) 启动。适用于开发调试场景。
3、如果是 Web 项目,可以打包成 War 包,使用外部 Tomcat 或 Jetty 等容器。
12、Spring Boot中的监视器是什么?
Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。
有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态。
13、什么是starter?
Starter主要是用来简化maven依赖
14、Spring Boot 常用的 Starter 有哪些?
spring-boot-starter-web :提供 Spring MVC + 内嵌的 Tomcat 。
spring-boot-starter-data-jpa :提供 Spring JPA + Hibernate 。
spring-boot-starter-data-redis :提供 Redis 。
mybatis-spring-boot-starter :提供 MyBatis 。
15、什么是YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。
与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
16、如何集成Spring Boot和ActiveMQ?
对于集成Spring Boot和ActiveMQ,我们使用spring-boot-starter-activemq依赖关系。 它只需要很少的配置,并且不需要样板代码。
17、springboot常用的starter有哪些
spring-boot-starter-web 嵌入tomcat和web开发需要servlet与jsp支持
spring-boot-starter-data-jpa 数据库支持
spring-boot-starter-data-redis redis数据库支持
spring-boot-starter-data-solr solr支持
mybatis-spring-boot-starter 第三方的mybatis集成starter
18、springboot自动配置的原理
在spring程序main方法中 添加@SpringBootApplication或者@EnableAutoConfiguration
会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean
19、springboot读取配置文件的方式
springboot默认读取配置文件为application.properties或者是application.yml
20、Spring Boot 需要独立的容器运行吗?
可以不需要,内置了 Tomcat/ Jetty 等容器。
21、运行 Spring Boot 有哪几种方式?
1)打包用命令或者者放到容器中运行
2)用 Maven/ Gradle 插件运行
3)直接执行 main 方法运行
22、Spring Boot 的核心配置文件有哪几个?它们的区别是什么?
Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件。
application 配置文件这个容易了解,主要用于 Spring Boot 项目的自动化配置。
bootstrap 配置文件有以下几个应用场景。
使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中增加连接到配置中心的配置属性来加载外部配置中心的配置信息;
少量固定的不能被覆盖的属性;
少量加密/解密的场景;
23、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
@ComponentScan:Spring组件扫描
24、为什么我们需要 spring-boot-maven-plugin?
spring-boot-maven-plugin 提供了一些像 jar 一样打包或者运行应用程序的命令。
spring-boot:run 运行你的 SpringBooty 应用程序。
spring-boot:repackage 重新打包你的 jar 包或者是 war 包使其可执行
spring-boot:start 和 spring-boot:stop 管理 Spring Boot 应用程序的生命周期(也可以说是为了集成测试)。
spring-boot:build-info 生成执行器可以使用的构造信息。
25、如何使用Spring Boot实现分页和排序?
使用Spring Boot实现分页非常简单。使用Spring Data-JPA可以实现将可分页的
org.springframework.data.domain.Pageable
传递给存储库方法。
26、什么是Swagger?你用Spring Boot实现了它吗?
Swagger广泛用于可视化API,使用Swagger UI为前端开发人员提供在线沙箱。Swagger是用于生成RESTful Web服务的可视化表示的工具,规范和完整框架实现。它使文档能够以与服务器相同的速度更新。当通过Swagger正确定义时,消费者可以使用最少量的实现逻辑来理解远程服务并与其进行交互。因此,Swagger消除了调用服务时的猜测。
27、什么是Spring Profiles?
Spring Profiles允许用户根据配置文件(dev,test,prod等)来注册bean。因此,当应用程序在开发中运行时,只有某些bean可以加载,而在PRODUCTION中,某些其他bean可以加载。假设我们的要求是Swagger文档仅适用于QA环境,并且禁用所有其他文档。这可以使用配置文件来完成。Spring Boot使得使用配置文件非常简单。
28、什么是Spring Batch?
Spring Boot Batch提供可重用的函数,这些函数在处理大量记录时非常重要,包括日志/跟踪,事务管理,作业处理统计信息,作业重新启动,跳过和资源管理。它还提供了更先进的技术服务和功能,通过优化和分区技术,可以实现极高批量和高性能批处理作业。简单以及复杂的大批量批处理作业可以高度可扩展的方式利用框架处理重要大量的信息。
29、什么是FreeMarker模板?
FreeMarker是一个基于Java的模板引擎,最初专注于使用MVC软件架构进行动态网页生成。使用Freemarker的主要优点是表示层和业务层的完全分离。程序员可以处理应用程序代码,而设计人员可以处理html页面设计。最后使用freemarker可以将这些结合起来,给出最终的输出页面。
30、什么是JavaConfig?
Spring JavaConfig是Spring社区的产品,它提供了配置Spring IoC容器的纯Java方法。因此它有助于避免使用XML配置。使用JavaConfig的优点在于:
面向对象的配置。由于配置被定义为JavaConfig中的类,因此用户可以充分利用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。
减少或消除XML配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在XML和Java之间来回切换。
JavaConfig为开发人员提供了一种纯Java方法来配置与XML配置概念相似的Spring容器。
从技术角度来讲,只使用JavaConfig配置类来配置容器是可行的,但实际上很多人认为将JavaConfig与XML混合匹配是理想的。
类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java 5.0对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找
31、启动类注解:
@SpringBootConfiguration:Spring Boot的配置类; 标注在某个类上,表示这是一个Spring Boot的配置类; @Configuration:配置类上来标注这个注解;配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component
@EnableAutoConfiguration:开启自动配置功能;
以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;
Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就失效,帮我们进行自动配置工作
配置文件的加载顺序
由jar包外向jar包内进行寻找;
优先加载带profile
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
再来加载不带profile
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
32、自动配置原理
1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2)、@EnableAutoConfiguration 作用:
将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
3)、每一个自动配置类进行自动配置功能;
根据当前不同的条件判断,决定这个配置类是否生效?
一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取 的,这些类里面的每一个属性又是和配置文件绑定的;
5)、所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功 能对应的这个属性类
33、怎么用好自动配置,精髓:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这 些属性的值;
34、Spring Boot、Spring MVC 和 Spring 有什么区别
Spring 是一个“引擎”,
Spring MVC是基于Spring的一个 MVC 框架,
Spring Boot是基于 Spring的一套快速开发整合包
spring cloud
1、微服务的优缺点分别是什么? 说下你在项目开发中碰到的坑
优点
每一个服务足够内聚,代码容易理解
开发效率提高,一个服务只做一件事
微服务能够被小团队单独开发
微服务是松耦合的,是有功能意义的服务
可以用不同的语言开发,面向接口编程
易于与第三方集成
微服务只是业务逻辑的代码,不会和HTML,CSS或者其他界面组合
开发中,两种开发模式
前后端分离
全栈工程师
可以灵活搭配,连接公共库/连接独立库
缺点
分布式系统的负责性
多服务运维难度,随着服务的增加,运维的压力也在增大
系统部署依赖
服务间通信成本
数据一致性
系统集成测试
性能监控
2、什么是Spring Cloud?
Spring cloud流应用程序启动器是基于Spring Boot的Spring集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
3、SpringBoot和SpringCloud
SpringBoot专注于快速方便的开发单个个体的微服务
SpringCloud是关注全局的微服务协调整理治理框架,整合并管理各个微服务,为各个微服务之间提供,配置管理,服务发现,断路器,路由,事件总线等集成服务
SpringBoot不依赖于SpringCloud,SpringCloud依赖于SpringBoot,属于依赖关系
SpringBoot专注于快速,方便的开发单个的微服务个体,SpringCloud关注全局的服务治理框架
4、SpringCloud和Dubbo
1).区别
服务的调用方式Dubbo使用的是RPC远程调用,而SpringCloud使用的是 Rest API,其实更符合微服务官方的定义
服务的注册中心来看,Dubbo使用了第三方的ZooKeeper作为其底层的注册中心,实现服务的注册和发现,SpringCloud使用Spring Cloud Netflix Eureka实现注册中心,当然SpringCloud也可以使用ZooKeeper实现,但一般我们不会这样做
服务网关,Dubbo并没有本身的实现,只能通过其他第三方技术的整合,而SpringCloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,SpringCloud还支持断路器,与git完美集成分布式配置文件支持版本控制,事务总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素
2).技术选型
目前国内的分布式系统选型主要还是Dubbo毕竟国产,而且国内工程师的技术熟练程度高,并且Dubbo在其他维度上的缺陷可以由其他第三方框架进行集成进行弥补
而SpringCloud目前是国外比较流行,当然我觉得国内的市场也会慢慢的偏向SpringCloud,就连刘军作为Dubbo重启的负责人也发表过观点,Dubbo的发展方向是积极适应SpringCloud生态,并不是起冲突
3).Rest和RPC对比
其实如果仔细阅读过微服务提出者马丁福勒的论文的话可以发现其定义的服务间通信机制就是Http Rest
RPC最主要的缺陷就是服务提供方和调用方式之间依赖太强,我们需要为每一个微服务进行接口的定义,并通过持续继承发布,需要严格的版本控制才不会出现服务提供和调用之间因为版本不同而产生的冲突
而REST是轻量级的接口,服务的提供和调用不存在代码之间的耦合,只是通过一个约定进行规范,但也有可能出现文档和接口不一致而导致的服务集成问题,但可以通过swagger工具整合,是代码和文档一体化解决,所以REST在分布式环境下比RPC更加灵活
这也是为什么当当网的DubboX在对Dubbo的增强中增加了对REST的支持的原因
5、文档质量和社区活跃度
SpringCloud社区活跃度远高于Dubbo,毕竟由于梁飞团队的原因导致Dubbo停止更新迭代五年,而中小型公司无法承担技术开发的成本导致Dubbo社区严重低落,而SpringCloud异军突起,迅速占领了微服务的市场,背靠Spring混的风生水起
Dubbo经过多年的积累文档相当成熟,对于微服务的架构体系各个公司也有稳定的现状
6、你所知道的微服务技术栈有哪些?请列举一二
维度 (SpringCloud)
服务开发: SpringBoot、Spring、SpringMVC
服务配置与管理: Netfilx公司的Archaiusm,阿里的Diamond
服务注册与发现: Eureka,ZooKeeper
服务调用: Rest,RPC,gRPC
服务熔断器: Hystrix
服务负载均衡: Ribbon,Nginx
服务接口调用: Feign
消息队列: Kafka,RabbitMq,ActiveMq
服务配置中心管理: SpringCloudConfing
服务路由(API网关): Zuul
事件消息总线: SpringCloud Bus
7、负载平衡的意义什么?
在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一资源的过载。使用多个组件进行负载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。
8、微服务之间是如何独立通讯的
1)远程过程调用(Remote Procedure Invocation)
也就是我们常说的服务的注册与发现
直接通过远程过程调用来访问别的service。
优点:
简单,常见,因为没有中间件代理,系统更简单
缺点:
只支持请求/响应的模式,不支持别的,比如通知、请求/异步响应、发布/订阅、发布/异步响应
降低了可用性,因为客户端和服务端在请求过程中必须都是可用的
2)消息
使用异步消息来做服务间通信。服务间通过消息管道来交换消息,从而通信。
优点:
把客户端和服务端解耦,更松耦合
提高可用性,因为消息中间件缓存了消息,直到消费者可以消费
支持很多通信机制比如通知、请求/异步响应、发布/订阅、发布/异步响应
缺点:
消息中间件有额外的复杂性
9、springcloud如何实现服务的注册和发现
服务在发布时 指定对应的服务名(服务名包括了IP地址和端口) 将服务注册到注册中心(eureka或者zookeeper)
这一过程是springcloud自动实现 只需要在main方法添加@EnableDisscoveryClient 同一个服务修改端口就可以启动多个实例
调用方法:传递服务名称通过注册中心获取所有的可用实例 通过负载均衡策略调用(ribbon和feign)对应的服务
Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别
1.Eureka取CAP中的AP,注重可用性。Zookepper取CAP理论中的CP强调高的一致性
ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的
Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,而查询到的数据并不是最新的
自我保护机制会导致
Eureka不再从注册列表移除因长时间没收到心跳而应该过期的服务
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点(高可用)
当网络稳定时,当前实例新的注册信息会被同步到其他节点中(最终一致性)
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper一样使得整个注册系统瘫痪
2.ZooKeeper有Leader和Follower角色,Eureka各个节点平等
3.ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题
4.Eureka本质上是一个工程,而ZooKeeper只是一个进程
10、eureka自我保护机制
当 Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁的启动关闭客户端),那么这个节点就会进入自我保护模式,一旦进入到该模式,Eureka server 就会保护服务注册表中的信息,不再删除服务注册表中的数据(即不会注销任何微服务),当网络故障恢复后,该 Ereaka Server 节点就会自动退出自我保护模式(我的 Eureka Server 已经几个月了,至今未自动退出该模式)
11、什么是服务熔断?什么是服务降级
在复杂的分布式系统中,微服务之间的相互调用,有可能出现各种各样的原因导致服务的阻塞,在高并发场景下,服务的阻塞意味着线程的阻塞,导致当前线程不可用,服务器的线程全部阻塞,导致服务器崩溃,由于服务之间的调用关系是同步的,会对整个微服务系统造成服务雪崩
为了解决某个微服务的调用响应时间过长或者不可用进而占用越来越多的系统资源引起雪崩效应就需要进行服务熔断和服务降级处理。
所谓的服务熔断指的是某个服务故障或异常一起类似显示世界中的“保险丝"当某个异常条件被触发就直接熔断整个服务,而不是一直等到此服务超时。
服务熔断就是相当于我们电闸的保险丝,一旦发生服务雪崩的,就会熔断整个服务,通过维护一个自己的线程池,当线程达到阈值的时候就启动服务降级,如果其他请求继续访问就直接返回fallback的默认值
12、Eureka
使用:
1、添加pom依赖
2、配置文件添加相关配置
3、启动类添加注解@EnableDiscoveryClient
13、什么是Ribbon?
ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。
使用:
1、添加pom依赖
2、配置文件添加相关配置
3、启动类添加注解@EnableEurekaServer
4、向程序的ioc注入一个bean: restTemplate;并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能
5、写一个测试类HelloService,通过之前注入ioc容器的restTemplate来消费service-hi服务的“/hi”接口
源码
Ribbon的负载均衡,主要通过LoadBalancerClient来实现的,而LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等信息,并向EurekaClient获取注册列表的信息,并默认10秒一次向EurekaClient发送“ping”,进而检查是否更新服务列表,最后,得到注册列表后,ILoadBalancer根据IRule的策略进行负载均衡。
而RestTemplate 被@LoadBalance注解后,能过用负载均衡,主要是维护了一个被@LoadBalance注解的RestTemplate列表,并给列表中的RestTemplate添加拦截器,进而交给负载均衡器去处理。
14、什么是Feign?它的优点是什么?
Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
简而言之:
Feign 采用的是基于接口的注解
Feign 整合了ribbon,具有负载均衡的能力
整合了Hystrix,具有熔断的能力
使用:
1、添加pom依赖
2、配置文件添加相关配置
3、启动类添加注解@EnableFeignClients
4、定义一个接口,使用注解@ FeignClient(“服务名”),来指定调用哪个服务
源码实现过程
首先通过@EnableFeignCleints注解开启FeignCleint
根据Feign的规则实现接口,并加@FeignCleint注解
程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的类,并将这些信息注入到ioc容器中。
当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate
RequesTemplate在生成Request
Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
15、Ribbon和Feign的区别:
Ribbon和Feign都是用于调用其他服务的,不过方式不同。
1.启动类使用的注解不同,Ribbon用的是@RibbonClient,Feign用的是@EnableFeignClients。
2.服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。
3.调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。
Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可,
不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。
16、什么是Spring Cloud Bus?
Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来。它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控。
如果修改了配置文件,发送一次请求,所有的客户端便会重新读取配置文件
使用:
1、添加依赖
2、配置rabbitmq
17、什么是zuul?
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。
使用:
1、添加pom依赖
2、配置文件添加相关配置
3、启动类添加注解@EnableZuulProxy
在zuul中, 整个请求的过程是这样的,首先将请求给zuulservlet处理,zuulservlet中有一个zuulRunner对象,该对象中初始化了RequestContext:作为存储整个请求的一些数据,并被所有的zuulfilter共享。zuulRunner中还有 FilterProcessor,FilterProcessor作为执行所有的zuulfilter的管理器。FilterProcessor从filterloader 中获取zuulfilter,而zuulfilter是被filterFileManager所加载,并支持groovy热加载,采用了轮询的方式热加载。有了这些filter之后,zuulservelet首先执行的Pre类型的过滤器,再执行route类型的过滤器,最后执行的是post 类型的过滤器,如果在执行这些过滤器有错误的时候则会执行error类型的过滤器。执行完这些过滤器,最终将请求的结果返回给客户端。
18、什么是Hystrix?它如何实现容错?
Hystrix是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现故障是不可避免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。
通常对于使用微服务架构开发的系统,涉及到许多微服务。这些微服务彼此协作。
使用:
1、添加pom依赖
2、启动类使用注解@EnableHystrix
3、在Service方法上加上@HystrixCommand注解。该注解对该方法创建了熔断器的功能,并指定了fallbackMethod熔断方法
19、springcloud断路器的作用
当一个服务调用另一个服务由于网络原因或者自身原因出现问题时 调用者就会等待被调用者的响应 当更多的服务请求到这些资源时
导致更多的请求等待 这样就会发生连锁效应(雪崩效应) 断路器就是解决这一问题
断路器有完全打开状态:一定时间内 达到一定的次数无法调用 并且多次检测没有恢复的迹象 断路器完全打开,那么下次请求就不会请求到该服务
半开:短时间内 有恢复迹象 断路器会将部分请求发给该服务 当能正常调用时 断路器关闭
关闭:当服务一直处于正常状态 能正常调用 断路器关闭
20、Spring Cloud Config
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。
使用:
1、添加pom依赖
2、配置文件添加相关配置
3、启动类添加注解@EnableConfigServer
21、Spring Cloud Gateway
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。
使用了一个RouteLocatorBuilder的bean去创建路由,除了创建路由RouteLocatorBuilder可以让你添加各种predicates和filters,predicates断言的意思,顾名思义就是根据具体的请求的规则,由具体的route去处理,filters是各种过滤器,用来对请求做各种判断和修改。
架构:
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统
在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件放在git仓库,方便开发人员随时改配置。
Spring Cloud Alibaba
微服务架构演变过程
1、传统架构
传统的架构,也就是为单点应用,也就是大家在早期所学习的JavaEE知识SSH或者SSM架构模式,会采用分层架构模式:数据库访问层、业务逻辑层、控制层,从前端到后台所有的代码都是一个开发者去完成。
该架构模式没有对我们业务逻辑代码实现拆分,所有的代码都写入到同一个工程中里面,适合于小公司开发团队或者个人开发。
这种架构模式最大的缺点,如果该系统一个模块出现不可用、会导致整个系统无法使用。
2、分布式架构
分布式架构模式是基于传统的架构模式演变过来,将传统的单点项目根据业务模块实现拆分、会拆分为会员系统、订单系统、支付系统、秒杀系统等。 从而降低我们项目的耦合度,这种架构模式开始慢慢的适合于互联网公司开发团队。
如果命名为系统的话:包含了视图层
3、SOA面向服务架构
SOA架构模式也称作为:面向服务架构模式、俗称面向与接口开发,将共同存在的业务逻辑抽取成一个共同的服务,提供给其他的服务接口实现调用、服务与服务之间通讯采用rpc远程调用技术。
SOA架构模式特点:
SOA架构通讯中,采用XML方式实现通讯、在高并发下通讯过程中协议存在非常大冗余性,所以在最后微服务架构模式中使用JSON格式替代了XML。
SOA架构模式实现方案为WebService或者是ESB企业服务总线 底层通讯协议SOAP协议(Http+XML)实现传输。
4、微服务架构产生的原因
微服务架构基于SOA架构演变过来的
在传统的WebService架构中有如下问题:
1、依赖中心化服务发现机制
2、使用Soap通讯协议,通常使用XML格式来序列化通讯数据,xml格式非常喜欢重,比较占宽带传输。
3、服务化管理和治理设施不完善
5、微服务架构基本概念
微服务架构模式是从SOA架构模式演变过来, 比SOA架构模式粒度更加精细,让专业的人去做专业的事情(专注),目的是提高效率,每个服务与服务之间互不影响,微服务架构中
每个服务必须独立部署、互不影响,微服务架构模式体现轻巧、轻量级、适合于互联网公司开发模式。
微服务架构倡导应用程序设计程多个独立、可配置、可运行和可微服务的子服务。
服务与服务通讯协议采用Http协议,使用restful风格API形式来进行通讯,数据交换格式轻量级json格式通讯,整个传输过程中,采用二进制,所以http协议可以跨语言平台,并且可以和其他不同的语言进行相互的通讯,所以很多开放平台都采用http协议接口。
6、微服务架构与SOA架构的不同
1.微服务架构基于 SOA架构 演变过来,继承 SOA架构的优点,在微服务架构中去除 SOA 架构中的 ESB 企业服务总线,采用 http+json(restful)进行传输。
2.微服务架构比 SOA 架构粒度会更加精细,让专业的人去做专业的事情(专注),目的提高效率,每个服务于服务之间互不影响,微服务架构中,每个服务必须独立部署,微服务架构更加轻巧,轻量级。
3.SOA 架构中可能数据库存储会发生共享,微服务强调独每个服务都是单独数据库,保证每个服务于服务之间互不影响。
4.项目体现特征微服务架构比 SOA 架构更加适合与互联网公司敏捷开发、快速迭代版本,因为粒度非常精细。
7、微服务架构会产生那些问题
分布式事务解决方案 (rabbitmq/rocketmq/lcn(已经淘汰)/ Seata)
分布式任务调度平台 (XXL-Job、阿里Scheduler)
分布式日志采集系统 ELJ+Kafka
分布式服务注册中心 eureka、Zookeeper、consule、nacos等。
分布式服务追踪与调用链 Zipkin等。
8、为什么我们要使用SpringCloud
SpringCloud并不是rpc远程调用框架,而是一套全家桶的微服务解决框架,理念就是解决我们在微服务架构中遇到的任何问题。
9、SpringCloud第一代与第二代的区别
SpringCloud第一代:
SpringCloud Config 分布式配置中心
SpringCloud Netflix 核心组件
Eureka:服务治理
Hystrix:服务保护框架
Ribbon:客户端负载均衡器
Feign:基于ribbon和hystrix的声明式服务调用组件
Zuul: 网关组件,提供智能路由、访问过滤等功能。
SpringCloud第二代(自己研发)和优秀的组件组合:
Spring Cloud Gateway 网关
Spring Cloud Loadbalancer 客户端负载均衡器
Spring Cloud r4j(Resilience4J) 服务保护
Spring Cloud Alibaba Nacos 服务注册
Spring Cloud Alibaba Nacos 分布式配置中心
Spring Cloud Alibaba Sentinel服务保护
SpringCloud Alibaba Seata分布式事务解决框架
Alibaba Cloud OSS 阿里云存储
Alibaba Cloud SchedulerX 分布式任务调度平台
Alibaba Cloud SMS 分布式短信系统
10、为什么Alibaba要推出SpringCloud组件
目的就是为了对阿里云的产品实现扩展。
11、服务注册与发现nacos
服务治理基本的概念
服务治理概念:
在RPC远程调用过程中,服务与服务之间依赖关系非常大,服务Url地址管理非常复杂,所以这时候需要对我们服务的url实现治理,通过服务治理可以实现服务注册与发现、负载均衡、容错等。
服务注册中心的概念
每次调用该服务如果地址直接写死的话,一旦接口发生变化的情况下,这时候需要重新发布版本才可以该接口调用地址,所以需要一个注册中心统一管理我们的服务注册与发现。
注册中心: 我们的服务注册到我们注册中心,key为服务名称、value为该服务调用地址,该类型为集合类型。Eureka、consul、zookeeper、nacos等。
服务注册: 我们生产者项目启动的时候,会将当前服务自己的信息地址注册到注册中心。
服务发现: 消费者从我们的注册中心上获取生产者调用的地址(集合),在使用负载均衡的策略获取集群中某个地址实现本地rpc远程调用。
12、Nacos对比Zookeeper、Eureka之间的区别
CAP定律
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
**一致性©:**在分布式系统中,如果服务器集群,每个节点在同时刻访问必须要保持数据的一致性。
**可用性(A):**集群节点中,部分节点出现故障后任然可以使用 (高可用)
**分区容错性§:**在分布式系统中网络会存在脑裂的问题,部分Server与整个集群失去节点联系,无法组成一个群体。
只有在CP和AP选择一个平衡点
13、SpringCloud Gateway
什么是微服务网关
微服务网关是整个微服务API请求的入口,可以实现日志拦截、权限控制、解决跨域问题、
限流、熔断、负载均衡、黑名单与白名单拦截、授权等。
过滤器与网关的区别
过滤器用于拦截单个服务
网关拦截整个的微服务
14、Zuul与Gateway有那些区别
Zuul网关属于netfix公司开源的产品属于第一代微服务网关
Gateway属于SpringCloud自研发的第二代微服务网关
相比来说SpringCloudGateway性能比Zuul性能要好:
注意:Zuul基于Servlet实现的,阻塞式的Api, 不支持长连接。
SpringCloudGateway基于Spring5构建,能够实现响应式非阻塞式的Api,支持长连接,能够更好的整合Spring体系的产品。
15、Nginx与网关的区别
相同点:都是可以实现对api接口的拦截,负载均衡、反向代理、请求过滤等,可以实现和网关一样的效果。
不同点:
Nginx采用C语言编写的
微服务都是自己语言编写的 比如Gateway就是java写的。
毕竟Gateway属于Java语言编写的, 能够更好对微服务实现扩展功能,相比Nginx如果想实现扩展功能需要结合Nginx+Lua语言等。
Nginx实现负载均衡的原理:属于服务器端负载均衡器。
16、Gateway实现负载均衡原理:
采用本地负载均衡器的形式。如何保证微服务接口的安全
接口分为内网和外网接口
外网接口 基于OATUH2.0构建开放平台 比如appid、appsocet获取accesstoken调用接口。
内网接口: 都是当前内网中实现通讯,相对于来说比较安全的。
1.需要保证接口幂等性问题(基于Token)
2.接口采用安全加密传输 https协议
3.防止数据被篡改 md5验证签名
4.使用微服务网关实现Api授权认证等、黑名单白名单。
5.对我们的接口实现服务的保护 隔离、熔断、降级等等。
最后使用apiswagger管理我们的微服务接口。
17、微服务中跨域的问题 不属于前端解决 jsonp 只能支持get请求。
核心点就是在我们后端。
解决跨域的问题
1.HttpClient转发
2.使用过滤器允许接口可以跨域 响应头设置
3.Jsonp 不支持我们的post 属于前端解决
4.Nginx解决跨域的问题保持我们域名和端口一致性
5.Nginx也是通过配置文件解决跨域的问题
6.基于微服务网关解决跨域问题,需要保持域名和端口一致性
7.使用网关代码允许所有的服务可以跨域的问题
8.使用SpringBoot注解形式@CrossOrigin
18、SpringCloud Sentinel
服务保护的基本概念
服务限流/熔断
服务限流目的是为了更好的保护我们的服务,在高并发的情况下,如果客户端请求的数量达到一定极限(后台可以配置阈值),请求的数量超出了设置的阈值,开启自我的保护,直接调用我们的服务降级的方法,不会执行业务逻辑操作,直接走本地falback的方法,返回一个友好的提示。
服务降级
在高并发的情况下, 防止用户一直等待,采用限流/熔断方法,使用服务降级的方式返回一个友好的提示给客户端,不会执行业务逻辑请求,直接走本地的falback的方法。
提示语:当前排队人数过多,稍后重试~
服务的雪崩效应
默认的情况下,Tomcat或者是Jetty服务器只有一个线程池去处理客户端的请求,
这样的话就是在高并发的情况下,如果客户端所有的请求都堆积到同一个服务接口上,
那么就会产生tomcat服务器所有的线程都在处理该接口,可能会导致其他的接口无法访问。
假设我们的tomcat线程最大的线程数量是为20,这时候客户端如果同时发送100个请求会导致有80个请求暂时无法访问,就会转圈。
服务的隔离的机制
服务的隔离机制分为信号量和线程池隔离模式
服务的线程池隔离机制:每个服务接口都有自己独立的线程池,互不影响,缺点就是占用cpu资源非常大。
服务的信号量隔离机制:最多只有一定的阈值线程数处理我们的请求,超过该阈值会拒绝请求。
19、Sentinel 与hytrix区别
前哨以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。
前哨具有以下特征:
1.丰富的应用场景:前哨兵承接了阿里巴巴近10年的双十一大促流的核心场景,例如秒杀(即突然流量控制在系统容量可以承受的范围),消息削峰填谷,传递流量控制,实时熔断下游不可用应用等。
2.完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接收应用的单台机器秒级数据,甚至500台以下规模的整合的汇总运行情况。
广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的集成模块,例如与Spring Cloud,Dubbo,gRPC的整合。您只需要另外的依赖并进行简单的配置即可快速地接入Sentinel。
3.完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适应动态数据源等。
Sentinel中文文档介绍:
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
20、Sentinel如何保证规则的持久化
默认的情况下Sentinel的规则是存放在内存中,如果Sentinel客户端重启后,Sentinel数据规则可能会丢失。
解决方案:
Sentinel持久化机制支持四种持久化的机制。
1.本地文件
2.携程阿波罗
3.Nacos
4.Zookeeper
21、目前主流分布式解决框架
1.单体项目多数据源 可以jta+ Atomikos
2.基于rabbitmq的形式解决 最终一致性的思想
3.基于rocketmq解决分布式事务 采用事务消息
4.LCN采用lcn模式 假关闭连接 (目前已经被淘汰)
5.Alibaba的Seata 未来可能是主流 背景非常强大
22、LCN基本实现原理
1.发起方与参与方都与我们的LCN管理器一直保持长连接;
2.发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
3.发起方调用接口的时候在请求头中传递事务分组id;
4.参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。
23、Seata的实现原理
Seata有3个基本组成部分:
事务协调器(TC): 维护全局事务和分支事务的状态,驱动全局提交或回滚。
事务管理器TM: 定义全局事务的范围:开始全局事务,提交或回滚全局事务。
资源管理器(RM): 管理分支事务正在处理的资源,与TC进行对话以注册分支事务并报告分支事务的状态,并驱动分支事务的提交或回滚。
redis
1、Redis支持的数据类型?
String字符串:
格式: set key value
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。
Hash(哈希)
格式: hmset name key1 value1 key2 value2
Redis hash 是一个键值(key=>value)对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
格式: lpush name value
在 key 对应 list 的头部添加字符串元素
格式: rpush name value
在 key 对应 list 的尾部添加字符串元素
格式: lrem name index
key 对应 list 中删除 count 个和 value 相同的元素
格式: llen name
返回 key 对应 list 的长度
Set(集合)
格式: sadd name value
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
zset(sorted set:有序集合)
格式: zadd name score value
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
2、什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?
持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
Redis 提供了两种持久化方式:RDB(默认) 和AOF
3、RDB:
rdb是Redis DataBase缩写
功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数
每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
4、aof写入保存:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
比较:
1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、rdb性能比aof好
4、如果两个都配了优先加载AOF
5、刚刚上面你有提到redis通讯协议(RESP ),能解释下什么是RESP?有什么特点?
RESP 是redis客户端和服务端之前使用的一种通讯协议;
RESP 的特点:实现简单、快速解析、可读性好
6、Redis 有哪些架构模式?讲讲各自的特点
主从复制:
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服 务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。
特点:
1、master/slave 角色
2、master/slave 数据相同
3、降低 master 读压力在转交从库
问题:
无法保证高可用
没有解决 master 写的压力
哨兵模式:
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。
特点:
1、保证高可用
2、监控各个节点
3、自动故障迁移
缺点: 主从模式,切换需要时间丢数据
没有解决 master 写的压力
7、使用过Redis做异步队列么,你是怎么用的?有什么缺点?
一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
缺点:
在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
8、能不能生产一次消费多次呢?
使用pub/sub主题订阅者模式,可以实现1:N的消息队列。
9、什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
10、如何避免?
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。
11、缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
12、如何避免?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2:二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
13、Memcache与Redis的区别都有哪些?
1)、存储方式
Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。
Redis有部份存在硬盘上,这样能保证数据的持久性。
2)、数据支持类型
Memcache对数据类型支持相对简单。
Redis有复杂的数据类型。
3)、使用底层模型不同
它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。
Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4),value大小
redis最大可以达到1GB,而memcache只有1MB
14、Redis 常见的性能问题都有哪些?如何解决?
1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。
2).Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
4). Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内
15、redis 最适合的场景
Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?
如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:
1 、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2 、Redis支持数据的备份,即master-slave模式的数据备份。
3 、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
(1)、会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
(2)、全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。
再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。
此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
(3)、队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
(4),排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。
(5)、发布/订阅
最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不,这是真的,你可以去核实)。
Redis提供的所有特性中,我感觉这个是喜欢的人最少的一个,虽然它为用户提供如果此多功能。
16、Redis有哪几种数据淘汰策略?
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
17、怎么理解Redis事务?
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
18、Redis如何做内存优化?
尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面。
nginx
1、nginx负载均衡的算法怎么实现的
nginx 的 upstream目前支持 4 种方式的分配
1)、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3)、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
4)、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5)、url_hash(第三方)
2、nginx内置策略包含加权轮询和ip hash
加权轮询算法分为先深搜索和先广搜索,那么nginx采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器;
3、什么是Nginx?
Nginx是一个高性能的HTTP和反向代理服务器,及电子邮件(IMAP/POP3)代理服务器,同时也是一个非常高效的反向代理、负载平衡。
多进程异步非阻塞事件处理机制:运用了epoll模型
4、为什么要用Nginx?
优点:
跨平台、配置简单
非阻塞、高并发连接:处理2-3万并发连接数,官方监测能支持5万并发
内存消耗小:开启10个nginx才占150M内存,Nginx采取了分阶段资源分配技术
nginx处理静态文件好,耗费内存少
内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送 节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
稳定性高:宕机的概率非常小
master/worker结构:一个master进程,生成一个或者多个worker进程
接收用户请求是异步的:浏览器将请求发送到nginx服务器,它先将用户请求全部接收下来,再一次性发送给后端web服务器,极大减轻了web服务器的压力
一边接收web服务器的返回数据,一边发送给浏览器客户端
网络依赖性比较低,只要ping通就可以负载均衡
可以有多台nginx服务器
事件驱动:通信机制采用epoll模型
5、为什么Nginx性能这么高?
得益于它的事件处理机制:
异步非阻塞事件处理机制:运用了epoll模型,提供了一个队列,排队解决
6、为什么不使用多线程?
Apache: 创建多个进程或线程,而每个进程或线程都会为其分配cpu和内存(线程要比进程小的多,所以worker支持比perfork高的并发),并发过大会榨干服务器资源。
Nginx: 采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量)(epoll),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换。所以才使得Nginx支持更高的并发。
7、Nginx是如何处理一个请求的呢?
首先,nginx在启动时,会解析配置文件,得到需要监听的端口与ip地址,然后在nginx的master进程里面
先初始化好这个监控的socket,再进行listen
然后再fork出多个子进程出来, 子进程会竞争accept新的连接。
此时,客户端就可以向nginx发起连接了。当客户端与nginx进行三次握手,与nginx建立好一个连接后
此时,某一个子进程会accept成功,然后创建nginx对连接的封装,即ngx_connection_t结构体
接着,根据事件调用相应的事件处理模块,如http模块与客户端进行数据的交换。
最后,nginx或客户端来主动关掉连接,到此,一个连接就寿终正寝了
正向代理
一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理
正向代理总结就一句话:代理端代理的是客户端
反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求,发给内部网络上的服务器
并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器
反向代理总结就一句话:代理端代理的是服务端
动态资源、静态资源分离
动态资源、静态资源分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路
动态资源、静态资源分离简单的概括是:动态文件与静态文件的分离
8、为什么要做动、静分离?
在我们的软件开发中,有些请求是需要后台处理的(如:.jsp,.do等等),有些请求是不需要经过后台处理的(如:css、html、jpg、js等等文件)
这些不需要经过后台处理的文件称为静态文件,否则动态文件。因此我们后台处理忽略静态文件。这会有人又说那我后台忽略静态文件不就完了吗
当然这是可以的,但是这样后台的请求次数就明显增多了。在我们对资源的响应速度有要求的时候,我们应该使用这种动静分离的策略去解决
动、静分离将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问
这里我们将静态资源放到nginx中,动态资源转发到tomcat服务器中
9、负载均衡
负载均衡即是代理服务器将接收的请求均衡的分发到各服务器中
负载均衡主要解决网络拥塞问题,提高服务器响应速度,服务就近提供,达到更好的访问质量,减少后台服务器大并发压力
Zookeeper
1、Zookeeper是什么框架
分布式开源框架,提供分布式协调服务,解决了分布式一致性问题。原本是Hadoop、HBase的一个重要组件。
应用场景
结合实际工作中,Zookeeper主要是用于dubbo框架的注册中心。Dubbo框架的提供者会向Zookeeper下的provider目录注册自己的URL。消费者订阅提供者的注册URL,并在consumer下注册自己的URL,以便在后续执行中调用提供者。消费者获取到URL之后,netty调用提供者提供的服务。提供者若发生了变化会主动通过zookeeper推送给消费者。
2、Paxos算法&Zookeeper使用协议
Paxos算法是分布式选举算法,Zookeeper使用的 ZAB协议(Zookeeper原子广播)
相同点:
比如都有一个Leader,用来协调N个Follower的运行;Leader要等待超半数的Follower做出正确反馈之后才进行提案
3、Zookeeper有哪几种节点类型
持久: 创建之后一直存在,除非有删除操作,创建节点的客户端会话失效也不影响此节点。
持久顺序: 持久节点名后缀加上一个10位数字。
临时: 创建客户端会话失效(注意是会话失效,不是连接断了),节点也就没了。不能建子节点。
临时顺序: 临时节点名后缀加上一个10位数字。
4、Zookeeper对节点的watch监听通知是永久的吗?
不是。官方声明:一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们。
5、为什么不是永久的,举个例子,
如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,这太消耗性能了。
一般是客户端执行getData(“/节点A”,true),如果节点A发生了变更或删除,客户端会得到它的watch事件,但是在之后节点A又发生了变更,而客户端又没有设置watch事件,就不再给客户端发送。
在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。
6、部署方式?集群中的机器角色都有哪些?集群最少要几台机器
单机,集群,伪集群。Leader、Follower、Observer。集群最低3(2N+1)台,保证奇数,主要是为了选举算法。
集群如果有3台机器,挂掉一台集群还能工作吗?挂掉两台呢?
过半存活即可用。
7、集群支持动态添加机器吗?
其实就是水平扩容了,Zookeeper在这方面不太好。两种方式:
全部重启:关闭所有Zookeeper服务,修改配置之后启动。不影响之前客户端的会话。
逐个重启:这是比较常用的方式。
8、Zookeeper 具有如下特性:
顺序一致性(有序性)
从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到 Zookeeper 中去。
有序性是 Zookeeper 中非常重要的一个特性。
单一视图
无论客户端连接的是哪个 Zookeeper 服务器,其看到的服务端数据模型都是一致的。
可靠性
一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直被保留,除非有另一个事务对其进行了变更。
实时性
Zookeeper 保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
9、Zookeeper 的通知机制是什么?
Zookeeper 允许客户端向服务端的某个 znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher ,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。
10、Zookeeper 的会话管理是怎么样的?
ZooKeeper 的每个客户端都维护一组服务端信息,在创建连接时由应用指定,客户端随机选择一个服务端进行连接,连接成功后,服务端为每个连接分配一个唯一标识。
集群如果有 3 台机器,挂掉 1 台集群还能工作吗?挂掉 2 台呢?
记住一个原则:过半存活即可用。所以挂掉 1 台可以继续工作,挂掉 2 台不可以工作。
11、ZooKeeper 的工作原理?
ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步):
12、Zookeeper 的选举过程?
当 Leader 崩溃,或者 Leader 失去大多数的 Follower,这时 Zookeeper 进入恢复模式,恢复模式需要重新选举出一个新的 Leader,让所有的 Server 都恢复到一个正确的状态。
RabbitMQ
1、什么是RabbitMQ?它的特性是什么
RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:
1)、可靠性(Reliability)
2)、灵活的路由(Flexible Routing)
在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
3)\消息集群(Clustering)
多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。
4)、高可用(Highly Available Queues)
队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
5)、多语言客户端(Many Clients)
RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
2、队列、路由概念
Quque(队列)是RabbitMQ的内部对象,用于存储信息,
生产者将消息发送到Exchange(交换器,下图中X),Exchange将消息路由到一个或者多个Quque中或者丢弃
routing key(路由key)
生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个路由规则,而这个routing key需要与 Exchange Type 与binding key 联合使用才能最终生效。
3、RabbitMQ 中的 Broker 是指什么?Cluster 又是指什么?
Broker ,是指一个或多个 erlang node 的逻辑分组,且 node 上运行着 RabbitMQ 应用程序。
Cluster ,是在 Broker 的基础之上,增加了 node 之间共享元数据的约束。
4、什么是元数据?元数据分为哪些类型?包括哪些内容?
在非 Cluster 模式下,元数据主要分为:
Queue 元数据(queue 名字和属性等)
Exchange 元数据(exchange 名字、类型和属性等)
Binding 元数据(存放路由关系的查找表)
Vhost 元数据(vhost 范围内针对前三者的名字空间约束和安全属性设置)。
5、RabbitMQ 概念里的 channel、exchange 和 queue 是什么?
queue 具有自己的 erlang 进程;
exchange 内部实现为保存 binding 关系的查找表;
channel 是实际进行路由工作的实体,即负责按照 routing_key 将 message 投递给 queue 。
6、如何确保消息正确地发送至 RabbitMQ?
RabbitMQ 使用发送方确认模式,确保消息正确地发送到 RabbitMQ。
发送方确认模式:将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID 。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(not acknowledged,未确认)消息。
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
7、消息发送的整个流程
消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。
通过队列路由键,可以把队列绑定到交换器上。
消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中;如果不能匹配到任何队列,消息将进入 “黑洞”。
8、常用的交换器有哪些
常用的交换器主要分为一下三种:
direct:如果路由键完全匹配,消息就被投递到相应的队列。
fanout:如果交换器收到消息,将会广播到所有绑定的队列上。
topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符,比如:“*” 匹配特定位置的任意文本, “.” 把路由键分为了几部分,“#” 匹配所有规则等。特别注意:发往 topic 交换器的消息不能随意的设置选择键(routing_key),必须是由 “.” 隔开的一系列的标识符组成。
9、RabbitMQ中实现RPC的机制是:
客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置两个值replyTo(一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和correlationId(此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败)
服务器端收到消息并处理
服务器端处理完消息后,将生成一条应答消息到replyTo指定的Queue,同时带上correlationId属性
客户端之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理
四、数据库
1、存储过程
CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT )
READS SQL DATA
BEGIN
SELECT COUNT() INTO count_num
FROM employee
WHERE d_id=emp_id ;
END
上述代码中,存储过程名称为num_from_employee;输入变量为emp_id;输出变量为count_num。SELECT语句从employee表查询d_id值等于emp_id的记录,并用COUNT()计算d_id值相同的记录的条数,最后将计算结果存入count_num中。
什么是存储过程?用什么来调用?
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。
调用:
1)可以用一个命令对象来调用存储过程。 2)可以供外部程序调用,比如:java程序。
存储过程的优缺点?
优点:
1)存储过程是预编译过的,执行效率高。 2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。 3)安全性高,执行存储过程需要有一定权限的用户。 4)存储过程可以重复使用,可减少数据库开发人员的工作量。
缺点: 移植性差
存储过程与函数的区别
用于在数据库中完成特定的操作或者任务(如插入、删除等)
程序头部声明用procedure
程序头部声明时不需描述返回类型
可以使用in/out/in out 三种模式的参数
可作为一个独立的PL/SQL语句来执行
可以通过out/in out 返回零个或多个值
SQL语句(DML 或SELECT)中不可调用存储过程 用于特定的数据(如选择)
程序头部声明用function
程序头部声明时要描述返回类型,而且PL/SQL块中至少要包括一个有效的return语句
可以使用in/out/in out 三种模式的参数
不能独立执行,必须作为表达式的一部分调用
通过return语句返回一个值,且改值要与声明部分一致,也可以是通过out类型的参数带出的变量
SQL语句(DML 或SELECT)中可以调用函数
2、函数
CREATE FUNCTION name_from_employee (emp_id INT )
RETURNS VARCHAR(20)
BEGIN
RETURN (SELECT name
FROM employee
WHERE num=emp_id );
END
2、触发器
触发器的作用?
触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
CREATE TRIGGER trigger_t1
AFTER INSERT ON table2
FOR EACH ROW
UPDATE table1 SET table1.count=table1.count+1;
3、创建索引
CREATE INDEX indexName ON mytable(username(length));
如果是CHAR VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。
4、什么是事务?什么是锁?
事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
锁:在所以的DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。
5、什么是回滚?
为了保证在应用程序、数据库或系统出现错误后,数据库能够被还原,以保证数据库的完整性 ,所以需要进行回滚。回滚(rollback)就是在事务提交之前将数据库数据恢复到事务修改之前数据库数据状态。
6、数据库的乐观锁和悲观锁是什么?
乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
7、MySQL数据库分页
Select * from 表名 limit startrow,pagesize (Pagesize为每页显示的记录条数)
10、主键和唯一索引的区别?
主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。
唯一性索引列允许空值,而主键列不允许为空值。主键列在创建时,已经默认为空值 + 唯一索引了。
主键可以被其他表引用为外键,而唯一索引不能。一个表最多只能创建一个主键,但可以创建多个唯一索引。
主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。在 RBO 模式下,主键的执行计划优先级要高于唯一索引。 两者可以提高查询的速度。
11、如何查询时去除重复数据?并且删除重复记录
比如现在有一人员表 (表名:peosons)
若想将姓名、身份证号、住址这三个字段完全相同的记录查询出来
复制代码 代码如下:
select p1.*
from persons p1,persons p2
where p1.id<>p2.id
and p1.cardid = p2.cardid and p1.pname = p2.pname and p1.address = p2.address
可以实现上述效果.
几个删除重复记录的SQL语句
(1)用rowid方法
(2)用group by方法
(3)用distinct方法
1)用rowid方法
据据oracle带的rowid属性,进行判断,是否存在重复,语句如下:
查数据:
select * from table1 a where rowid !=(select max(rowid)
from table1 b where a.name1=b.name1 and a.name2=b.name2…)
删数据:
delete from table1 a where rowid !=(select max(rowid)
from table1 b where a.name1=b.name1 and a.name2=b.name2…)
2)group by方法
查数据:
select count(num), max(name) from student --列出重复的记录数,并列出他的name属性
group by num
having count(num) >1 --按num分组后找出表中num列重复,即出现次数大于一次
删数据:
delete from student group by num having count(num) >1
这样的话就把所有重复的都删除了。
3)用distinct方法 -对于小的表比较有用
create table table_new as select distinct * from table1 minux
truncate table table1;
insert into table1 select * from table_new;
12、什么是内连接和外连接?
内连接: 内联接是用比较运算符比较要联接列的值的联接。
外连接 : 包括左向外联接、右向外联接或完整外部联接。
(1)左连接: left join 或 left outer join
左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,
则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
(2)右连接: right join 或 right outer join
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(3)完整外部联接: full join 或 full outer join
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
13、列举需要创建索引以及不适合创建索引的场合
适合创建索引的场合为:
1)为经常出现在WHERE子句中的列创建索引。
2)为经常出现在ORDER BY、DISTINCT后面的字段建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致。
3)为经常作为表的连接条件的列上创建索引
不适合创建索引的场合为:
1)不要在经常做DML操作的表上建立索引。
2)不要在小表上建立索引。
3)限制表上的索引数目,索引并不是越多越好。
14、数据库中的事务是什么?
事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,
事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。
15、sql语句优化有哪些?
1)尽量避免非操作符的使用。
2)避免对查询的列的操作。
3)避免不必要的类型转换。
4)增加查询的范围限制。
5)合理使用IN与EXISTS(关系条件只有一个列时,用IN比较合适,否则用EXISTS比较合适)
6)尽量去掉<>,避免全表扫描。
7)去掉WHERE子句中IS NULL和IS NOT NULL(不会使用索引而是进行全表搜查)、
8)尽量不要使用前导模糊查询(前面有%的like查询,不能使用索引);
9)SELECT子句中避免使用"“(数据库在解析的过程中,会将”"转化成所有的列名,这是通过查询数据字典完成的,这意味着将耗费更多时间)
10)规范所有的SQL关键字的书写(如SELECT,update…要么都大写,要么都小写)
16、事务四大特性
原子性, 要么执行,要么不执行
隔离性, 所有操作全部执行完以前,其它会话不能看到过程
一致性, 事务前后,数据总额一致
持久性, 一旦事务提交,对数据的改变就是永久的
17、如何维护数据库的完整性和一致性?
尽可能使用约束,如check,主键,外键,非空字段等来约束,这样做效率最高,也最方便。其次是使用触发器,这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的完整新和一致性。最后考虑的是自写业务逻辑,但这样做麻烦,编程复杂,效率低下。
MYSQL的两种存储引擎区别(事务、锁级别等等),各自的适用场景
MYISAM 不支持事务,不支持外键,表锁,插入数据时,锁定整个表,查表总行数时,不需要全表扫描
INNODB 支持事务,支持外键,行锁,查表总行数时,全表扫描
18、Varchar2和varchar有什么区别?
Char的长度是固定的,而varchar2的长度是可以变化的,比如,存储字符串“abc”对于char(20),表示你存储的字符将占20个字节,包含17个空,而同样的varchar2(20)只占了3个字节,20只是最大值,当你存储的字符小于20时,按实际长度存储。 char的效率要被varchar2的效率高。 目前varchar是varchar2的同义词,工业标准的varchar类型可以存储空字符串,但是oracle不能这样做,尽管它保留以后这样做的权利。Oracle自己开发了一个数据类型varchar2,这个类型不是一个标准的varchar,他将在数据库中varchar列可以存储空字符串的特性改为存储null值,如果你想有向后兼容的能力,oracle建议使用varchar2而不是varchar
19、数据库三范式
1NF 属性不可分
2NF 非主键属性,完全依赖于主键属性
3NF 非主键属性无传递依赖
20、关系型数据库和非关系型数据库区别
类型 特性
关系型数据库mysql
1、关系型数据库,是指采用了关系模型来组织数据的数据库,
2、关系型数据库的最大特点就是事务的一致性;
优点
1、容易理解:二维表结构是非常贴近逻辑世界一个概念,关系模型相对网状、层次等其他模型来说更容易理解;
2、使用方便:通用的SQL语言使得操作关系型数据库非常方便;
3、易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率;
4、支持SQL,可用于复杂的查询。
缺点
1、为了维护一致性所付出的巨大代价就是其读写性能比较差;
2、固定的表结构;
3、不支持高并发读写需求;
4、不支持海量数据的高效率读写;
非关系型数据库 特性
HBase
1、使用键值对存储数据;
2、分布式;
优点
无需经过sql层的解析,读写性能很高
基于键值对,数据没有耦合性,容易扩展
存储数据的格式:nosql的存储格式是key,value形式
缺点
不支持事务
不提供sql支持
21、索引的作用?和它的优点缺点是什么?
索引就一种特殊的查询表,数据库的搜索可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。
缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。
22、什么样的字段适合建索引
唯一、不为空、经常被查询的字段
23、什么叫视图?游标是什么?
视图:是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改会影响基本表。它使得我们获取数据更容易,相比多表查询。
游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。
24、使用游标的基本步骤有哪些?
1.声明游标2.打开游标3.读取游标中的数据4.关闭游标5.释放游标
25、order by与group by的区别
order by 排序查询、asc升序、desc降序
group by 分组查询、having 只能用于group by子句、作用于组内,having条件子句可以直接跟函数表达式。使用group by 子句的查询语句需要使用聚合函数。
26、commit在哪里会运用
oracle的commit就是DML语句提交数据(这里是释放锁不是锁表),在未提交前你前面的操作更新的都是内存,没有更新到物理文件中。 执行commit从用户角度讲就是更新到物理文件了,事实上commit时还没有写date file,而是记录了redo log file,要从内存写到data物理文件,需要触发检查点,由DBWR这个后台进程来写,这里内容有点多的,如果不深究的话你就理解成commit即为从内存更新到物理文件。
27、什么是内连接,左外连接,右外连接?
内联接(Inner Join): 匹配2张表中相关联的记录。
左外联接(Left Outer Join): 除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。
右外联接(Right Outer Join): 除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。
在判定左表和右表时,要根据表名出现在Outer Join的左右位置关系。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: