JAVA面试题

1.JDK 和 JRE 有什么区别?
JDK是JAVA开发环境也包括运行环境,JRE是JAVA运行环境。

2.== 和 equals 的区别是什么?
==比较的是内存地址,equals比较的是内容。
分情况:分两种情况,一种是基本数据,一种是引用数据类型。
JAVA八种基本数据类型:byte short int long float double char boolean 比较值
JAVA三种引用数据类型:类、接口、数组 比较内存地址
String是一个类,所以是引用数据类型,故
比较内存地址。凡new都是开辟新地址。

加深:重写equals,String类和Integer类,将equals变成了值比较。

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
不一定。通话、重地。

4.final 在 java 中有什么作用?
final修饰类:该类不能被继承。
final修饰方法:该方法不能被重写。
final修饰属性:该属性不能被修改,就是常量。

5.java 中的 Math.round(-1.5) 等于多少?
注意:这是四啥五入取整,但是负数要注意取大的。比负1.5还大的整数是负一。

6.String 属于基础的数据类型吗?
不属于基本数据类型,它属于引用数据类型。
JAVA八种基本数据类型:byte short int long float double char boolean 比较值
JAVA三种引用数据类型:类、接口、数组 比较内存地址

7.java 中操作字符串都有哪些类?它们之间有什么区别?
String:操作副本
StringBuffer:线程安全,操作本身,多线程下使用。经常用。
StringBuilder:线程不安全,速度快。单线程下使用。

8.String str="i"与 String str=new String(“i”)一样吗?
不一样,因为内存的分配方式不一样。
String str="i"的方式,java 虚拟机会将其分配到常量池中;
而 String str=new String(“i”) 则会被分到堆内存中。

9.如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

10.String 类的常用方法都有那些?
length() 字符串长度
trim() 去字符串两边空格
indexOf() 查找批定字符串位置
substring(a,b) 截取
charAt() 指定位置的字符
replace(a,b,c) 替换
toLowerCase() 转小写
toUpperCase() 转大写
getBytes() 转字节数组
split() 分隔

11.抽象类必须要有抽象方法吗?
抽象类中可以没有抽象方法,也可以有抽象方法。

12.普通类和抽象类有哪些区别?
普通类中不能包含抽象方法,包含抽象的方法的一定是抽象类。
抽象类不能实例化(不能new),普通方法可以实例化。

13.抽象类能使用 final 修饰吗?
抽象类不能使用final修饰,因为被final修饰的类不能被继承。
抽象类设计的目的是为了被继承,故与之矛盾,不能使用final修饰。

14.接口和抽象类有什么区别?
接口的实现类用implements,抽象类的子类用extends。
接口中不能有构造方法,抽象类中可以有构造方法。
抽象类中可以有main方法,并可以运行。接口不可以。但可以有静态方法。
类是单继承,一个类只能继承一个类。
接口打破了单一继承,一个类可以实现多个接口,接口也可以继承多个接口。注意:接口不能实现接口。
接口用interface定义,抽象类用class定义。
接口中的方法默认都是公共的,抽象类中的方法访问修饰符不限(四种public protected 不写 private)

15.java 中 IO 流分为几种?
按流的方向可以分为输入流和输出流。
按流的类型可以分为字节流和字符流。1个字节等于8位,按8位以字节单位传输。1个字符等于2字符,故16位,以字符为单位传输。

16.BIO、NIO、AIO 有什么区别?
BIO 同步阻塞
NIO 同步非阻塞
AIO 异步非阻塞

17.Files的常用方法都有哪些?

• Files.exists():检测文件路径是否存在。
• Files.createFile():创建文件。
• Files.createDirectory():创建文件夹。
• Files.delete():删除一个文件或目录。
• Files.copy():复制文件。
• Files.move():移动文件。
• Files.size():查看文件个数。
• Files.read():读取文件。
• Files.write():写入文件。

  1. java 容器都有哪些?
    List
    Set
    Map
    Vector
    Collection

19.Collection 和 Collections 有什么区别?
Collection是集合类的顶级接口,它包含了集合类的通用方法,它的直接接口有List和Set。
Collections是集合类的工具类,它包含了一系列的静态方法,排序,查找。

  1. List、Set、Map 之间的区别是什么?
    List 有序可重复,它的子类额ArrayList,LinkedList。
    Set 无序不可重复,它的子类有HashSet,TreeSet。
    Map 键值对,它个子类有HashMap,TreeMap。

  2. HashMap 和 Hashtable 有什么区别?
    HashMap 同步,Hashtable 非同步
    hashMap允许空键值,而hashTable不允许
    hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法

  3. 如何决定使用 HashMap 还是 TreeMap?
    对Map数据的增删改查,添加、删除、定位用HashMap.
    对一个有序key的遍历用TreeMap。

  4. 说一下 HashMap 的实现原理?
    HashMap是非同步。允许null键null值。无序。
    HashMap数据结构基于数组和模拟指针。数组和链表的结合体。
    在添加数据时,这个位置上有其它元素,以链表形式存放,
    新加入的放在链头,最先加入的放入链尾(洗盘子)
    这个位置上没有其它元素,直接放在该位置上。

需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,
该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

队列:先进先出 FIFO
链表:后进先出 LIFO
FIFO: First in, First out.先进先出。
LIFO: Last in, First out.后进先出。

  1. 说一下 HashSet 的实现原理?
    HashSet底层由HashMap实现
    HashSet的值存放于HashMap的key上
    HashMap的value统一为PRESENT

Java中HashSet的Value为什么存PRESENT而不是Null?
HashSet#add() 方法需要在加入新元素时返回 true,加入重复元素时返回 falseHashMap#add() 方法
返回的是上一次以同一 key 加入的 value若从未以该 key 加入任何数据,
则返回 null然而 HashMap 允许 null 作为 value所以如果使用 null 作为 value
利用 HashMap 当返回 null 的时候我们就无法得知 null 究竟意味着这个 key 是第一次加入还是上一次使用了 null 作为 value 加入

  1. ArrayList 和 LinkedList 的区别是什么?
    最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。
    使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

算法中的O(1), O(n),O(logn), O(nlogn)分别是什么意思?
由于平时接触算法比较少,今天看资料看到了o(1),都不知道是什么意思,百度之后才知道是什么意思。
描述算法复杂度时,常用o(1), o(n), o(logn), o(nlogn)表示对应算法的时间复杂度,是算法的时空复杂度的表示。不仅仅用于表示时间复杂度,也用于表示空间复杂度。

O后面的括号中有一个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量。 
比如时间复杂度为O(n),就代表数据量增大几倍,耗时也增大几倍。比如常见的遍历算法。再比如时间复杂度O(n2),就代表数据量增大n倍时,耗时增大n的平方倍,这是比线性更高的时间复杂度。比如冒泡排序,就是典型的O(n2)的算法,对n个数排序,需要扫描n×n次。 
再比如O(logn),当数据增大n倍时,耗时增大logn倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。二分查找就是O(logn)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。 
O(nlogn)同理,就是n乘以logn,当数据增大256倍时,耗时增大256*8=2048倍。这个复杂度高于线性低于平方。归并排序就是O(nlogn)的时间复杂度。 
O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话)

  1. 如何实现数组和 List 之间的转换?
    List转换成为数组:调用ArrayList的toArray方法。
    数组转换成为List:调用Arrays的asList方法。

  2. ArrayList 和 Vector 的区别是什么?
    Vector是同步的,而ArrayList不是。
    在迭代的时候对列表进行改变,使用CopyOnWriteArrayList。
    ArrayList比Vector快,它因为有同步,不会过载。
    ArrayList更加通用,使用Collections工具类轻易地获取同步列表和只读列表。

  3. Array 和 ArrayList 有何区别?
    数组 和 ArrayList 有何区别?
    Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
    Array是指定大小后不可变的,而ArrayList大小是可变的。
    Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

  4. 在 Queue 中 poll()和 remove()有什么区别?
    poll() 和 remove() 都是从队列中取出一个元素。
    poll() 在获取元素失败的时候会返回空,
    remove() 失败的时候会抛出异常。

  5. 哪些集合类是线程安全的?
    vector:
    statck:
    hashtable:
    enumeration:

  6. 迭代器 Iterator 是什么?
    迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象

  7. Iterator 怎么使用?有什么特点?
    Java中的Iterator功能比较简单,并且只能单向移动:
    (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
    (2) 使用next()获得序列中的下一个元素。
    (3) 使用hasNext()检查序列中是否还有元素。
    (4) 使用remove()将迭代器新返回的元素删除。 
    Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

  8. Iterator 和 ListIterator 有什么区别?
    Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
    Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
    ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

34.怎么确保一个集合不能被修改?
可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这
样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。

List list = new ArrayList<>();
list. add(“A”);
Collection unmlist = Collections.unmodifiableCollection(list);
unmlist. add(“B”); // 运行时此行报错
System. out. println(list.size());

  1. 并行和并发有什么区别?
    并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
    并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
    在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。
    所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

35.并行、并发、串行、分布式是什么意思?
并行(parallel)是指两个或者多个事件在同一时刻发生; (线程/视频)
而并发(Concurrent)是指两个或多个事件在同一时间间隔发生;
串行(Sequential)A和B两个任务运行在一个CPU线程上,在A任务执行完之前不可以执行B。
分布式(distributed)分布式在并行处理的基础上,强调任务正在执行的物理设备,
如处理器、内存等等硬件,在物理上是分开的。而并行计算是指在一台计算机上的计算,在物理上不分开。

分布式计算将任务分解成许多小的部分,分配给多台计算机进行处理,
从而整体上节约了计算时间。Hadoop的MapReduce就是一种分布式计算框架

补充:线程的五种状态
一个人出生到死亡的过程。
线程:新建、就绪、运行、阻塞、死亡。
人 :出生 学习 工作 生病 升天。

新建:new Thread()线程
就绪:可执行状态 线程象.start() 随时可以被cpu调度执行
运行:获得了CPU的调度
阻塞:放弃了CPU使用权,重新排队(就绪)
等待阻塞wait() 同步阻塞 synchronized 获取同步锁失败
其它阻塞 sleep() join()
死亡:执行完了、异常退出

36.线程和进程的区别?
一个程序至少有一个进程。
一个进程至少有一个线程(主线程)。
进程在执行的过程中拥有独立的内存单元。
同一进程中的多个线程可以并发执行。

进程是老大,线程是小弟。

37.守护线程是什么?呆萌 daemon thread 保姆
它是一个服务线程,服务其它线程。

38.创建线程的几种方式?
继承Thread类 start()
实现Runnable接口 生写run方法
Callable接口和Future创建线程 call

39.Runnable和Callable的区别
Runnable接口中的run方法没返回值,纯粹地执行run方法中的代码而已。
Callable接口中的call方法有返回值,和Future/FutureTask接合使用。

40.线程有哪些状态?
创建、就绪、运行、阻塞、死亡。

41.sleep和wait方法区别
sleep是Thread类的静态法,让调用线程进入睡眠状态,让出执行机会,
sleep(1000),等1000ms后醒来进入就绪。由于是静态方法不能改变对象锁,
当synchronized块调用了sleep方法,对象锁没有被释放,其它线程无法访问。

wait()是Object类的方法,进入到一个和该对象的等待池,同时释放对象锁,其它
线程能够访问,还可以通过notify,notifyAll方法来唤醒。

42.notify()和notifyAll区别
notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程)
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,
唯有线程再次调用 wait()方法,它才会重新回到等待池中。
而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

43.线程的run和start方法有什么区别
run方法写具体的操作,通过Thread类的start()方法来启动线程运行run方法。
只要调了start方法就启动了run方法。

44.创建线程池有哪几种方式
newFixedThreadPool(int nThreads) 固定长度线程池
newCachedThreadPool() 可缓存的线程池
newSingleThreadExecutor() 单线程线程池
newScheduledThreadPool(int corePoolSize) 固定长度可以延时或定时执行

45.线程池都有哪些状态
Running、ShutDown、Stop、Tidying、Terminated。

46.线程池submit和execute方法有什么区别
接受的参数不同,submit有返回值,execute没有。
submit异常处理容易

47.在Java程序中怎么保证多线程的运行安全
三个方法:
原子性:互斥,同一时刻只能有一个线程对数据操作,方式atomic,synchronized
可见性:一个线程对主内存的修改可以及时被其他线程看到,方式synchronized,volatile
有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,结果一般杂乱无序
可以通过volatile、synchronized、lock保证有序性。

48.多线程锁的升级原理是什么?
Java中,锁的四种状态:级别从低到高:无状态锁,偏向锁,轻量锁,重量级锁。
锁可以升级但不能降级。

49.什么是死锁?教室里有一个扫把,A同学和B学生同时抢着,互不相让。
死锁是指两个或两个以上的进程在执行过程中,
由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,
若无外力作用,它们都将无法推进下去。
此时称系统处于死锁状态或系统产生了死锁,
这些永远在互相等待的进程称为死锁进程。
是操作系统层面的一个错误,是进程死锁的简称。

50.怎么防止死锁?
死锁的四个必要条件:
互斥条件
请求和保持条件
不可剥夺条件
环路等待条件

51.ThreadLocal是什么,应用场景
Java提供ThreadLocal类来支持线程局部变量,是一种实现线程安全的方式。
但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。
任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

52.说一下 synchronized 底层实现原理?
synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
普通同步方法,锁是当前实例对象
静态同步方法,锁是当前类的class对象
同步方法块,锁是括号里面的对象
53. synchronized 和 volatile 的区别是什么?
volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

  1. synchronized 和 Lock 有什么区别?
    首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
    synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
    synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
    用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
    synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可);
    Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

  2. synchronized 和 ReentrantLock 区别是什么?
    synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:
    ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁
    ReentrantLock可以获取各种锁的信息
    ReentrantLock可以灵活地实现多路通知
    另外,二者的锁机制其实也是不一样的:ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word。

  3. 说一下 atomic 的原理?
    Atomic包中的类基本的特性就是在多线程环境下,
    当有多个线程同时对单个(包括基本类型及引用类型)变量进行操作时,
    具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,
    而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。
    这个里面大量的方法调用都会存在安全隐患,需要小心使用,否则会导致严重的后果

  4. 什么是反射?
    反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
    Java反射:在程序运行的过程中,可以知道类的所有属性和方法,对并且操作的一种能力。

  5. 什么是 Java 序列化?什么情况下需要序列化?
    Java 序列化就是将对象(各种对象的状态)保存在内存中,并且还可以读取出来(反序列化)。
    Java通过实现序列化接口来实现Serializable。
    什么情况下需要序列化:
    a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
    b)当你想用套接字在网络上传送对象的时候;
    c)当你想通过RMI传输对象的时候;

  6. 动态代理是什么?有哪些应用?
    当想要给实现了某个接口的类中的方法,加一些额外的处理。
    比如说加日志,加事务等。可以给这个类创建一个代理,
    就是创建一个新的类,这个类不仅包含原来类方法的功能,
    而且还在原来的基础上添加了额外处理的新类。
    这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。

SpringAOP,Struts的拦截器
60.怎么实现动态代理
首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。
再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。
利用到InvocationHandler,拼接代理类源码,
将其编译生成代理类的二进制码,利用加载器加载,
并将其实例化产生代理对象,最后返回。

  1. 为什么要使用克隆?
    想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。
    Java语言中克隆针对的是类的实例。

  2. 如何实现对象克隆?
    有两种方式:
    • 实现Cloneable接口并重写Object类中的clone()方法;
    • 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
    注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,
    更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,
    这项检查是编译器完成的,不是在运行时抛出异常,
    这种是方案明显优于使用Object类的clone方法克隆对象。
    让问题在编译的时候暴露出来总是好过把问题留到运行时。

  3. 深拷贝和浅拷贝区别是什么?
    • 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,
    另一个值都会随之变化,这就是浅拷贝(例:assign())

• 深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,
这就是深拷贝(例:JSON.parse()和JSON.stringify(),
但是此方法无法复制函数类型)

  1. JSP 和 Servlet 有什么区别?
    JSP经过编译之后就是Servlet,JVM识别Java源代码不识别JSP,web容器将JSP编译成
    Java类。
    JSP用于页面展示充当视图层,Servlet用于逻辑控制充当控制层。
    Servlet中没有内置对象,通过HttpServletRequest和HttpServletResponse来获得,
    JSP中有九个内置对象。

65.JSP有哪些内置对象,作用分别是什么
JSP有9个内置对象:
request:封装客户端的请求,其中包含来自GET或POST请求的参数;
response:封装服务器对客户端的响应;
pageContext:通过该对象可以获取其他对象;
session:封装用户会话的对象;
application:封装服务器运行环境的对象;
out:输出服务器响应的输出流对象;
config:Web应用的配置对象;
page:JSP页面本身(相当于Java程序中的this);
exception:封装页面抛出异常的对象。

66.说一下JSP的四种作用域
JSP中的四种作用域包括page、request、session和application
page代表与一个页面相关的对象和属性。
request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。
session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

67.Session和Cookie有什么区别?URL重写是什么?
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
当客户端把cookie禁用了,那怎么办呢?!这个时候就需要使用URL重写技术了。
URL重写为了页面更有利于seo优化
response.encodeURL(“logoutServlet”); 用于对超链接和action的表单提交进行重写。

response.encodeRedirectURL(“logoutServlet”); 用于对response.sendRedirect()的方法进行重写。

  1. 说一下 session 的工作原理?
    其实session是一个存在服务器上的类似于一个散列表格的文件。
    里面存有我们需要的信息,在我们需要用的时候可以从里面取出来。
    类似于一个大号的map吧,里面的键存储的是用户的sessionid,
    。这时就可以从中取出对应的值了。

  2. 如果客户端禁止 cookie 能实现 session 还能用吗?
    Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,
    而Cookie采用的是在客户端保持状态的方案。但为什么禁用Cookie就不能得到Session呢?
    因为Session是用Session ID来确定当前对话所对应的服务器Session,
    而Session ID是通过Cookie来传递的,禁用Cookie相当于失去了Session ID,也就得不到Session了。

  3. spring mvc 和 struts 的区别是什么?
    拦截机制不同:Struts2,多例。有一套挂载机制。
    SpringMVC是方法级别,线程安全。
    底层框架不同:Struts2采用的是Filter实现(StrutsPrepareAndExecuteFilter),
    SpringMVC是Servlet实现(DispatcherServlet前端控制器)
    初始化时,早于Filter调用。
    性能方面:SpringMVC性能优于Struts2。
    配置方面:SpringMVC和Spring无缝对接,容易,安全性高于Struts2。

71.如何避免SQL注入:前台,业务层,数据库
PreparedStatement
使用正则表达式过滤传入的参数
字符串过滤
JSP中调用该函数检查是否包函非法字符
JSP页面判断代码

  1. 什么是 XSS 攻击,如何避免?
    XSS攻击又称CSS,全称Cross Site Script (跨站脚本攻击),其原理是攻击者向有XSS漏洞的网站中输入恶意的 HTML 代码,当用户浏览该网站时,这段 HTML 代码会自动执行,从而达到攻击的目的。XSS 攻击类似于 SQL 注入攻击,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。 XSS是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式。
    XSS防范的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码。

  2. 什么是 CSRF 攻击,如何避免?
    CSRF(Cross-site request forgery)也被称为 one-click attack或者 session riding,中文全称是叫跨站请求伪造。一般来说,攻击者通过伪造用户的浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。
    如何避免:

  3. 验证 HTTP Referer 字段
    HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF
    攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。

  4. 使用验证码
    关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。

  5. 在请求地址中添加token并验证
    CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于session之中,然后在每次请求时把token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。
    对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。
    而对于 POST 请求来说,要在 form 的最后加上 ,这样就把token以参数的形式加入请求了。

  6. 在HTTP 头中自定义属性并验证
    这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

  7. throw 和 throws 的区别?
    throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。
    而throw则是指抛出的一个具体的异常类型。

  8. final、finally、finalize 有什么区别?
    final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
    finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
    finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System的gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾。

  9. try-catch-finally 中哪个部分可以省略?
    try{}catch(){}
    try{}catch(){}finally{}
    try{}finally{}

try不能省,catch和finally必须存在一个,也可以同时存在。
try里面的代码是有可能产生异常的代码
catch是捕获异常实例
finally无论如何都执行,主要用于释放资源

  1. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?在之前还是在之后?
    答:会执行,finally在return 前执行。

  2. 常见的异常类有哪些?
    算术异常 ArithmeticException
    空指针异常NullPointException
    数组下标越界ArrayIndexOfOutBounds
    文件读写异常IOException
    数据库异常SQLException
    参数异常 IllegalArgumentException
    文件找不到FileNotFoundException
    类无法转ClassCastException
    没有这样的方法 NoSuchMethodException

  3. http 响应码 301 和 302 代表的是什么?有什么区别?
    HTTP状态的编码,都代表着某个URL发生了转移。
    URL统一资源定位符。
    区别:
    • 301 redirect: 301 代表永久性转移(Permanently Moved)。
    • 302 redirect: 302 代表暂时性转移(Temporarily Moved )。

  4. forward 和 redirect 的区别?
    张三去买房,需要民政局的结婚证明。
    forward 转发 直接 张三去银行贷款,银行自己去查证张三是否结婚。
    redirect重定向 间接 张三去银行贷款,银行说你去开结婚证明,张三去了民政局。

  5. 简述 tcp 和 udp的区别?
    TCP传输控制协议:面向连接(靠谱) 必须有问有答。无差错,不丢失,不重复,且按序到达;
    UDP用户数据报文协议:无连接(不太靠谱)UDP尽最大努力交付,即不保证可靠交付。

UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。

每一条TCP连接只能是点到点的;
UDP支持一对一,一对多,多对一和多对多的交互通信。

TCP对系统资源要求较多,UDP对系统资源要求较少。

  1. tcp 为什么要三次握手,两次不行吗?为什么?

张三:喂
李四:听到
张三:我也听到你的声音了

为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号,
以标识发送出去的数据包中, 哪些是已经被对方收到的。
三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

  1. 说一下 tcp 粘包是怎么产生的?
    发送方产生粘包
    发送缓冲区不止一个数据包
    接收方产生粘包
    接收缓冲区不止一个数据包

发送方产生粘包(发送的数据太小,要对小数据包合并)
采用TCP协议传输数据的客户端与服务器经常是保持一个长连接的状态(一次连接发一次数据不存在粘包),
双方在连接不断开的情况下,可以一直传输数据;
但当发送的数据包过于的小时,那么TCP协议默认的会启用Nagle算法,
将这些较小的数据包进行合并发送(缓冲区数据发送是一个堆压的过程);
这个合并过程就是在发送缓冲区中进行的,也就是说数据发送出来它已经是粘包的状态了。

  1. OSI 的七层模型都有哪些?
    • 应用层:网络服务与最终用户的一个接口。
    • 表示层:数据的表示、安全、压缩。
    • 会话层:建立、管理、终止会话。
    • 传输层:定义传输数据的协议端口号,以及流控和差错校验。
    • 网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。
    • 数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。
    • 物理层:建立、维护、断开物理连接。

  2. get 和 post 请求有哪些区别?
    • GET在浏览器回退时是无害的,而POST会再次提交请求。
    • GET产生的URL地址可以被书签(Bookmark),而POST不可以。
    • GET请求会被浏览器主动缓存(cache),而POST不会,除非手动设置。
    • GET请求只能进行url编码,而POST支持多种编码方式。
    • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
    • GET请求在URL中传送的参数是有长度限制的,而POST没有。
    • 参数的数据类型,GET只接受ASCII字符,而POST没有限制。
    • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
    • GET参数通过URL传递,POST放在Request body中。

  3. 如何实现跨域?
    方式一:图片ping或script标签跨域
    图片ping常用于跟踪用户点击页面或动态广告曝光次数。
    script标签可以得到从其他来源数据,这也是JSONP依赖的根据。
    方式二:JSONP跨域
    JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据。根据 XmlHttpRequest 对象受到同源策略的影响,而利用
    • 只能使用Get请求
    • 不能注册success、error等事件监听函数,不能很容易的确定JSONP请求是否失败
    • JSONP是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,其安全性无法确保
    方式三:CORS
    Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用CORS在API容器如XMLHttpRequest来减少HTTP请求的风险来源。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。服务器一般需要增加如下响应头的一种或几种:
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400
    跨域请求默认不会携带Cookie信息,如果需要携带,请配置下述参数:
    “Access-Control-Allow-Credentials”: true// Ajax设置"withCredentials": true
    87.说一下 JSONP 实现原理?
    jsonp 即 json+padding,动态创建script标签,利用script标签的src属性可以获取任何域下的js脚本,
    通过这个特性(也可以说漏洞),服务器端不再返回json格式,而是返回一段调用某个函数的js代码,
    在src中进行了调用,这样实现了跨域。

  4. 说一下你熟悉的设计模式?23种

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

其实还有两类:并发型模式和线程池模式。

设计模式的六大原则
1、开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

5、迪米特法则(最少知道原则)(Demeter Principle)

为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承

  1. 简单工厂和抽象工厂有什么区别?https://www.cnblogs.com/ldgg
    简单工厂:三个部分 工厂类、抽象产品、具体产品
    麓谷汽车世界 车 宝马、奔驰、奥迪
    抽象工厂:产品树和产品族
    宝马和奔驰是产品树
    宝马跑车
    奔驰跑车
    奥迪跑车
    产品族

  2. 为什么要使用 spring?
    1.流行,企业用的多。解决企业应用开发的复杂性。
    2.轻量,发布时文件小。1M左右。
    3.控制反转IOC和依赖注入DI实现解耦。
    4.面向切面AOP,让程序员更关注业务逻辑的代码开发。如日志事务的抽离。
    5.可以配置单例和多例。
    6.配置在xml中轻易实现。

  3. 解释一下什么是 aop?
    面向方面的编程,是OOP的补充和完善。
    采用横切关注点思想,将应用逻辑和通用代码分离,提高代码利用。

  4. 解释一下什么是 ioc?
    控制反转
    思想是借助于“第三方”实现对象解耦。
    相当于粘合剂。

  5. spring 有哪些主要模块?
    Beans
    Core
    Context
    AOP
    JDBC
    Web
    Servlet

  6. spring 常用的注入方式有哪些?
    set注入
    构造注入
    注解注入

  7. spring 中的 bean 是线程安全的吗?
    不具备线程安全,具体结合scope的bean去设置。
    prototype每次拿到的同一个bean不一样。
    singleton每次拿到的同一个bean一样。

  8. spring 支持几种 bean 的作用域?
    session、request、global session
    singleton(单例)、non-singleton(也称 prototype)

  9. spring 自动装配 bean 有哪些方式?
    • 隐式的bean发现机制和自动装配
    • 在java代码或者XML中进行显示配置

  10. spring 事务实现方式有哪些?
    编程式事务 TransactionProxyFactoryBean
    声明式事务 Aspectj AOP
    注解式事务@Transactional

  11. 说一下 spring 的事务隔离?
    • 脏读:一个事务读到另一个事务未提交的更新数据。
    • 幻读:例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。
    • 不可重复读:比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读。

  12. 说一下 spring mvc 运行流程?
    用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
    DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
    DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter;(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
    提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
    1、HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
    2、数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
    3、数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
    4、数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
    Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
    根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
    ViewResolver 结合Model和View,来渲染视图;
    将渲染结果返回给客户端。

  13. spring mvc 有哪些组件?
    • DispatcherServlet:中央控制器,把请求给转发到具体的控制类
    • Controller:具体处理请求的控制器
    • HandlerMapping:映射处理器,负责映射中央处理器转发给controller时的映射策略
    • ModelAndView:服务层返回的数据和视图层的封装类
    • ViewResolver:视图解析器,解析具体的视图
    • Interceptors :拦截器,负责拦截我们定义的请求然后做处理工作

  14. @RequestMapping 的作用是什么?
    RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
    RequestMapping注解有六个属性,下面我们把她分成三类进行说明。
    value, method:
    • value:指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
    • method:指定请求的method类型, GET、POST、PUT、DELETE等;
    consumes,produces
    • consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
    • produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
    params,headers
    • arams: 指定request中必须包含某些参数值是,才让该方法处理。
    • headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。

  15. @Autowired 的作用是什么?
    @Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
    @Autowired 默认是按照类去匹配,配合 @Qualifier 指定按照名称去装配 bean。

  16. 什么是 spring boot?
    SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,
    所谓简化是指简化了Spring众多框架中所需的大量且繁琐的配置文件,
    所以 SpringBoot是一个服务于框架的框架,服务范围是简化配置文件。

  17. 为什么要用 spring boot?
    简单、方便、高效

  18. spring boot 核心配置文件是什么?
    • properties文件
    • yml文件

  19. spring boot 配置文件有哪几种类型?它们有什么区别?
    是properties文件和yml文件。
    properties是键值对的写法,直观。
    yml是层级关系的写法,不容易看。
    网上有许多相互转换的工具,没有什么影响。

  20. spring boot 有哪些方式可以实现热部署?
    我常用的是:

    org.springframework.boot
    spring-boot-devtools

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<fork>true</fork>
			</configuration>
		</plugin>
	</plugins>
</ build>

未知
然后:使用 shift+ctrl+alt+"/" (IDEA中的快捷键) 选择"Registry" 然后勾选 compiler.automake.allow.when.app.running

  1. jpa 和 hibernate 有什么区别?
    JPA是一个通用的规范,
    Hibernate实现了这个规范。

  2. 什么是 spring cloud?
    属于Spring家族。致力于分布式系统、云服务的框架。
    常用的五大组件:
    Eureka
    Ribbon
    Hystrix
    Zuul
    Feign

  3. spring cloud 断路器的作用是什么?
    防止雪崩效应,导致大批量服务器瘫痪,最终应用崩溃。
    当请求到一个有问题的服务器时,会返回一个状态给客户端,告知客户端,并尝试自行修复,不让其它客户端访问。

  4. spring cloud 的核心组件有哪些?
    1.Eureka 服务的注册与发现
    用RestTemplate
    2.用Ribbon
    实现负载均衡:多台服务器处理用户的请求(平均或均衡)
    3.Hystrix断路器(由)
    防止雪崩,防止系统瘫痪。
    4.Zuul 网关 类似Nginx反向代理。通过请求路径标识达到请求指定服务器的目的。
    5.feign,Feign 是一个声明式的伪RPC(Remote Procedure Call 远程过程调用)的REST客户端,它用了基于接口的注解方式,很方便的客户端配置。
    取代了TestTemplate,让用户感觉自己像在本地操作远程方法。
    6.分布式配置config,配置合spring cloud bus实现动态配置更新。

Hibernate:全自动持久化框架
113.为什么要使用 hibernate?
简化了JDBC操作。
是一个优秀的ORM实现,实现了JPA。
是使用JAVA反射机制。
性能好,轻量级,灵活。
支持各种关系数据库,各种映射关系。

  1. 什么是 ORM 框架?
    它是对象关系映射框架。
    应用程序用实体来描述对象,数据库用表来描述对象。
    应用程序实体间有继承和关联关系,数据库中无法表述,此时需要中间层来描述,
    ORM就是实现“将程序对象映射到关系数据库中的数据。”(实体和表映射)

  2. hibernate 中如何在控制台查看打印的 sql 语句?
    spring.jpa.properties.hibernate.show_sql=true         //控制台是否打印
    spring.jpa.properties.hibernate.format_sql=true        //格式化sql语句
    spring.jpa.properties.hibernate.use_sql_comments=true //指出是什么操作生成了该语句

  3. hibernate 有几种查询方式?
    HQL 查实体和属性 区分大小写 Hibernate查询
    SQL 查表和列 不区分 原生SQL查询
    Criteria QBC:条件查询

  4. hibernate 实体类可以被定义为 final 吗?
    可以,但不建议。
    原因:影响性能。
    为什么:一个类被定义为final,Hibernate就无法使用代理。
    如何避免:让实体类实现一个接口,接口中声明了所有定义于实体类中的所有public的方法

  5. 在 hibernate 中使用 Integer 和 int 做映射有什么区别?
    Integer是一个类,故可以判断是否为空。
    int是原始数据类型,默认值为0。
    Hibernate中OID为Integer,如果为null,可以判断一个对象是不是临时的。
    Hibernate中OID为int型,那么还要设置unsaved-value为0。

  6. hibernate 是如何工作的?
    读取Hibernate配置文件
    读取实体映射文件
    创建工厂
    创建会话
    开启事务
    处理
    提交事务
    关闭会话
    关闭工厂

  7. get()和 load()的区别?
    get()即时,没有使用属性也发出SQL
    load()是延时,在使用时才发出SQL

  8. 说一下 hibernate 的缓存机制?
    一级缓存,二级缓存。
    一级缓存就是 Session 级别的缓存,在事务范围内有效是,内置的不能被卸载。
    二级缓存是 SesionFactory级别的缓存,从应用启动到应用结束有效。二级缓存用第三方插件,需要配置。
    扩展:hibernate的二级缓存默认是不支持分布式缓存的。使用 memcahe,redis等中央缓存来代替二级缓存。

  9. hibernate 对象有哪些状态?
    临时状态(瞬时状态):new
    持久状态:save() saveOrUpdate()
    脱管状态:session.close()

  10. 在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?
    getCurrentSession()如果已经有session,那么就用这个,如果没有就开启新的。
    openSession,每次都会开启新的session。

124.hibernate 实体类必须要有无参构造函数吗?为什么?
必须要一个无参的构造函数。
Hibernate通过反射来构建对象,并且是调用其默认构造方法来实现。

MyBaits 半自动化框架,让程序员更好的更灵活的使用sql

125.mybatis 中 #{}和 ${}的区别是什么?
#{}是预编译,相当于JDBC中的PreparedStatement问号占位符。
${}是拼字符串,相当于JDBC中的Statement,有sql注入的风险。
#{}可以防止sql注入。

126.mybatis 有几种分页方式?
数组分页
sql分页
拦截器分页
RowBounds分页
第三方插件分页:如PageHelper

127.RowBounds 是一次性查询全部结果吗?为什么?
RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,
因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,
它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,
它会在你执行 next()的时候,去查询更多的数据。
就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。
只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。

128.mybatis 逻辑分页和物理分页的区别是什么?
物理分页速度上并不一定快于逻辑分页,逻辑分页速度上也并不一定快于物理分页。
物理分页总是优于逻辑分页:没有必要将属于数据库端的压力加诸到应用端来,
就算速度上存在优势,然而其它性能上的优点足以弥补这个缺点

129.mybatis 是否支持延迟加载?延迟加载的原理是什么?
支持,但是仅在配置了关联关系的情况下,并且设置了azyLoadingEnabled=true。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,
比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,
那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),
于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

130.说一下 mybatis 的一级缓存和二级缓存?
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

131.mybatis 和 hibernate 的区别有哪些?
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。

132.mybatis 有哪些执行器(Executor)?
SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

133.mybatis 分页插件的实现原理是什么?
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

134.mybatis 如何编写一个自定义插件?
blog.csdn.net/qq_30051265/article/details/80266434

RabbitMQ
135.rabbitmq 的使用场景有哪些?
https://www.cnblogs.com/zhao-yi/p/9299126.html
2.1 异步处理
场景说明:用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式
(1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。 这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西.
(2)并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。
假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并性已经提高的处理时间,但是,前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,英爱是写入数据库后就返回.
(3)消息队列
引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理
这里写图片描述
由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。

2.2 应用解耦
场景:双11是购物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口.
这种做法有一个缺点:
当库存系统出现故障时,订单就会失败。(这样马云将少赚好多好多钱^ ^)
订单系统和库存系统高耦合.
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:订阅下单的消息,获取下单消息,进行库操作。
就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失(马云这下高兴了).

引入消息队列

2.3 流量削峰
流量削峰一般在秒杀活动中应用广泛
场景:秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。
作用:
1.可以控制活动人数,超过此一定阀值的订单直接丢弃(我为什么秒杀一次都没有成功过呢^^)
2.可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单)
这里写图片描述
1.用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面.
2.秒杀业务根据消息队列中的请求信息,再做后续处理.

136.rabbitmq 有哪些重要的角色?
RabbitMQ 中重要的角色有:生产者、消费者和代理:
生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

137.rabbitmq 有哪些重要的组件?
ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。
Channel(信道):消息推送使用的通道。
Exchange(交换器):用于接受、分配消息。
Queue(队列):用于存储生产者的消息。
RoutingKey(路由键):用于把生成者的数据分配到交换器上。
BindingKey(绑定键):用于把交换器的消息绑定到队列上。

138.rabbitmq 中 vhost 的作用是什么?
vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。

139.rabbitmq 的消息是怎么发送的?
首先客户端必须连接到 RabbitMQ 服务器才能发布和消费消息,客户端和 rabbit server 之间会创建一个 tcp 连接,一旦 tcp 打开并通过了认证(认证就是你发送给 rabbit 服务器的用户名和密码),你的客户端和 RabbitMQ 就创建了一条 amqp 信道(channel),信道是创建在“真实” tcp 上的虚拟连接,amqp 命令都是通过信道发送出去的,每个信道都会有一个唯一的 id,不论是发布消息,订阅队列都是通过这个信道完成的。

140.rabbitmq 怎么保证消息的稳定性?
提供了事务的功能。
通过将 channel 设置为 confirm(确认)模式。

141.rabbitmq 怎么避免消息丢失?
消息持久化
ACK确认机制
设置集群镜像模式
消息补偿机制

142.要保证消息持久化成功的条件有哪些?
声明队列必须设置持久化 durable 设置为 true.
消息推送投递模式必须设置持久化,deliveryMode 设置为 2(持久)。
消息已经到达持久化交换器。
消息已经到达持久化队列。
以上四个条件都满足才能保证消息持久化成功。

143.rabbitmq 持久化有什么缺点?
持久化的缺地就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。可尽量使用 ssd 硬盘来缓解吞吐量的问题。

144.rabbitmq 有几种广播类型?
fanout: 所有bind到此exchange的queue都可以接收消息(纯广播,绑定到RabbitMQ的接受者都能收到消息);
direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息;
topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息;

145.rabbitmq 怎么实现延迟消息队列?
使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。
146.rabbitmq 集群有什么用?
集群主要有以下两个用途:
高可用:某个服务器出现问题,整个 RabbitMQ 还可以继续使用;
高容量:集群可以承载更多的消息量。
147.rabbitmq 节点的类型有哪些?
磁盘节点:消息会存储到磁盘。
内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。

148.rabbitmq 集群搭建需要注意哪些问题?
各节点之间使用“–link”连接,此属性不能忽略。
各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。
整个集群中必须包含一个磁盘节点。

149.rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?
不是,原因有以下两个:
存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;
性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。

150.rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?
如果唯一磁盘的磁盘节点崩溃了,不能进行以下操作:
不能创建队列
不能创建交换器
不能创建绑定
不能添加用户
不能更改权限
不能添加和删除集群节点
唯一磁盘节点崩溃了,集群是可以保持运行的,但你不能更改任何东西。

151.rabbitmq 对集群节点停止顺序有要求吗?
停止服务:应当先关闭内存节点,再关闭磁盘节点。先关闭磁盘节点的话会导致无法创建交换器、队列、绑定关系,从而可能会导致数据丢失。
启动服务:先启动磁盘节点,再启动内存节点。

Kafka
kafka 可以脱离 zookeeper 单独使用吗?为什么?
kafka 不能脱离 zookeeper 单独使用,因为 kafka 使用 zookeeper 管理和协调 kafka 的节点服务器。
153. kafka 有几种数据保留的策略?
kafka 有两种数据保存策略:按照过期时间保留和按照存储的消息大小保留。
154. kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?
这个时候 kafka 会执行数据清除工作,时间和大小不论那个满足条件,都会清空数据。
155. 什么情况会导致 kafka 运行变慢?
cpu 性能瓶颈
磁盘读写瓶颈
网络瓶颈
156. 使用 kafka 集群需要注意什么?
集群的数量不是越多越好,最好不要超过 7 个,因为节点越多,消息复制需要的时间就越长,整个群组的吞吐量就越低。
集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。

Zookeeper

  1. zookeeper 是什么?
    zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 google chubby 的开源实现,是 hadoop 和 hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
  2. zookeeper 都有哪些功能?
    集群管理:监控节点存活状态、运行请求等。
    主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 可以协助完成这个过程。
    分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。
    命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。
  3. zookeeper 有几种部署模式?
    zookeeper 有三种部署模式:
    单机部署:一台集群上运行;
    集群部署:多台集群运行;
    伪集群部署:一台集群启动多个 zookeeper 实例运行。
  4. zookeeper 怎么保证主从节点的状态同步?
    zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 zab 协议。 zab 协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。
  5. 集群中为什么要有主节点?
    在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,所以就需要主节点。
  6. 集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?
    可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用。
  7. 说一下 zookeeper 的通知机制?
    客户端端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,然后客户端可以根据 znode 变化来做出业务上的改变。

MySql

  1. 数据库的三范式是什么?
    第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
    第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
    第三范式:任何非主属性不依赖于其它非主属性。

  2. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
    表类型如果是 MyISAM ,那 id 就是 8。
    表类型如果是 InnoDB,那 id 就是 6。
    InnoDB 表只会把自增主键的最大 id 记录在内存中,所以重启之后会导致最大 id 丢失。

  3. 如何获取当前数据库版本?
    使用 select version() 获取当前 MySQL 数据库版本。

  4. 说一下 ACID 是什么?
    Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
    Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
    Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

  5. char 和 varchar 的区别是什么?
    char(n) :固定长度类型,比如订阅 char(10),当你输入"abc"三个字符的时候,它们占的空间还是 10 个字节,其他 7 个是空字节。
    char 优点:效率高;缺点:占用空间;适用场景:存储密码的 md5 值,固定长度的,使用 char 非常合适。
    varchar(n) :可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。
    所以,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,二者使用需要权衡。

  6. float 和 double 的区别是什么?
    float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。
    double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。

  7. mysql 的内连接、左连接、右连接有什么区别?
    内连接关键字:inner join;左连接:left join;右连接:right join。
    内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示出来,右边的表显示出符合条件的数据;右连接正好相反。

  8. mysql 索引是怎么实现的?
    索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。
    具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,
    但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,(BTree一是平衡树)
    可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。

  9. 怎么验证 mysql 的索引是否满足需求?
    使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。
    explain 语法:explain select * from table where type=1。

  10. 说一下数据库的事务隔离?
    MySQL 的事务隔离是在 MySQL. ini 配置文件里添加的,在文件的最后添加:transaction-isolation = REPEATABLE-READ
    可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
    READ-UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。
    READ-COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。
    REPEATABLE-READ:可重复读,默认级别,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)。
    SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
    脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
    不可重复读 :是指在一个事务内,多次读同一数据。
    幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

  11. 说一下 mysql 常用的引擎?
    InnoDB 引擎:InnoDB 引擎提供了对数据库 acid 事务的支持,并且还提供了行级锁和外键的约束,
    它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,
    InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎是不支持全文搜索,
    同时启动也比较的慢,它是不会保存表的行数的,所以当进行 select count(*) from table 指令的时候,
    需要进行扫描全表。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。

MyIASM 引擎:MySQL 的默认引擎,但不提供事务的支持,也不支持行级锁和外键。
因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率会降低。
不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,
可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,
可以将 MyIASM 作为数据库引擎的首选。

  1. 说一下 mysql 的行锁和表锁?
    MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
    表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低。
    行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高。

  2. 说一下乐观锁和悲观锁?
    乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
    悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
    数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,
    这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。

  3. mysql 问题排查都有哪些手段?
    使用 show processlist 命令查看当前所有连接信息。
    使用 explain 命令查询 SQL 语句执行计划。
    开启慢查询日志,查看慢查询的 SQL。

  4. 如何做 mysql 的性能优化?
    为搜索字段创建索引。
    避免使用 select *,列出需要查询的字段。
    垂直分割分表。
    选择正确的存储引擎。

mysql 分库分表(水平切割和垂直切割)
分表是分散数据库压力的好方法。
分表,最直白的意思,就是将一个表结构分为多个表,然后,可以再同一个库里,也可以放到不同的库。
当然,首先要知道什么情况下,才需要分表。个人觉得单表记录条数达到百万到千万级别时就要使用分表了。

纵向分表
将本来可以在同一个表的内容,人为划分为多个表。(所谓的本来,是指按照关系型数据库的第三范式要求,是应该在同一个表的。)
分表理由:根据数据的活跃度进行分离,(因为不同活跃的数据,处理方式是不同的)

案例:
对于一个博客系统,文章标题,作者,分类,创建时间等,是变化频率慢,查询次数多,而且最好有很好的实时性的数据,我们把它叫做冷数据。而博客的浏览量,回复数等,类似的统计信息,或者别的变化频率比较高的数据,我们把它叫做活跃数据。所以,在进行数据库结构设计的时候,就应该考虑分表,首先是纵向分表的处理。
这样纵向分表后:
首先存储引擎的使用不同,冷数据使用MyIsam 可以有更好的查询数据。活跃数据,可以使用Innodb ,可以有更好的更新速度。
其次,对冷数据进行更多的从库配置,因为更多的操作时查询,这样来加快查询速度。对热数据,可以相对有更多的主库的横向分表处理。
其实,对于一些特殊的活跃数据,也可以考虑使用memcache ,redis
之类的缓存,等累计到一定量再去更新数据库。或者mongodb 一类的nosql 数据库,这里只是举例,就先不说这个。

横向分表
字面意思,就可以看出来,是把大的表结构,横向切割为同样结构的不同表,如,用户信息表,user_1,user_2 等。表结构是完全一样,但是,根据某些特定的规则来划分的表,如根据用户ID来取模划分。
分表理由:根据数据量的规模来划分,保证单表的容量不会太大,从而来保证单表的查询等处理能力。
案例:同上面的例子,博客系统。当博客的量达到很大时候,就应该采取横向分割来降低每个单表的压力,来提升性能。例如博客的冷数据表,假如分为100个表,当同时有100万个用户在浏览时,如果是单表的话,会进行100万次请求,而现在分表后,就可能是每个表进行1万个数据的请求(因为,不可能绝对的平均,只是假设),这样压力就降低了很多很多。

redis 是什么?都有哪些使用场景?
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis 使用场景:
数据高并发的读写
海量数据的读写
对扩展性要求高的数据
180. redis 有哪些功能?
数据缓存功能
分布式锁的功能
支持数据持久化
支持事务
支持消息队列
181. redis 和 memecache 有什么区别?
memecached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
redis的速度比memcached快很多
redis可以持久化其数据

  1. redis 为什么是单线程的?
    cpu不是Redis的瓶颈,它受内存和带宽的影响,单线程容易实现。

补充:nginx 和 nodejs 也都是高性能单线程的代表。

  1. 什么是缓存穿透?怎么解决?
    缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透
    解决方案:最简单粗暴的方法如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们就把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

  2. redis 支持的数据类型有哪些?
    string、list、hash、set、zset。

  3. redis 支持的 java 客户端都有哪些?
    Redisson、Jedis、lettuce等等,官方推荐使用Redisson。

  4. jedis 和 redisson 有哪些区别?
    Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持。
    Redisson实现了分布式和可扩展的Java数据结构。
    和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。
    Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上

  5. 怎么保证缓存和数据库数据的一致性?
    合理设置缓存的过期时间。
    新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证数据的一致性。

  6. redis 持久化有几种方式?
    RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
    AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。

  7. redis 怎么实现分布式锁?
    Redis 分布式锁其实就是在系统里面占一个“坑”,其他程序也要占“坑”的时候,占用成功了就可以继续执行,失败了就只能放弃或稍后重试。
    占坑一般使用 setnx(set if not exists)指令,只允许被一个程序占有,使用完调用 del 释放锁。

  8. redis 分布式锁有什么缺陷?
    Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

  9. redis 如何做内存优化?
    尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,
    所以你应该尽可能的将你的数据模型抽象到一个散列表里面。
    比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,
    而是应该把这个用户的所有信息存储到一张散列表里面。

  10. redis 淘汰策略有哪些?
    1.已设置过期时间的数据集
    最近最少使用淘汰策略
    将要过期
    任意淘汰
    2.从数据集
    最近最少使用淘汰策略
    任意淘汰
    禁止驱逐数据

  11. redis 常见的性能问题有哪些?该如何解决?
    主服务器写内存快照,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以主服务器最好不要写内存快照。
    Redis 主从复制的性能问题,为了主从复制的速度和连接的稳定性,主从库最好在同一个局域网内。

JVM

  1. 说一下 jvm 的主要组成部分?及其作用?
    类加载器(ClassLoader)
    运行时数据区(Runtime Data Area)
    执行引擎(Execution Engine)
    本地库接口(Native Interface)
    组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

  2. 说一下 jvm 运行时数据区?
    程序计数器
    虚拟机栈
    本地方法栈

    方法区

有的区域随着虚拟机进程的启动而存在,有的区域则依赖用户进程的启动和结束而创建和销毁。

196.说一下堆栈的区别?
栈内存存储的是局部变量而堆内存存储的是实体;
栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

197.队列和栈是什么?有什么区别?
队列和栈都是被用来预存储数据的。
队列允许先进先出检索元素,但也有例外的情况,Deque 接口允许从两端检索元素。
栈和队列很相似,但它运行对元素进行后进先出进行检索。

火车过隧道,洗盘子

  1. 什么是双亲委派模型?
    双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。

  2. 说一下类加载的执行过程?
    加载:根据查找路径找到相应的 class 文件然后导入;
    检查:检查加载的 class 文件的正确性;
    准备:给类中的静态变量分配内存空间;
    解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;
    初始化:对静态变量和静态代码块执行初始化工作。

  3. 怎么判断对象是否可以被回收?
    一般有两种方法来判断:
    引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;
    可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

  4. java 中都有哪些引用类型?
    https://blog.csdn.net/sinat_21118695/article/details/82392028
    强引用
    软引用
    弱引用
    虚引用(幽灵引用/幻影引用)

  5. 说一下 jvm 有哪些垃圾回收算法?
    https://blog.csdn.net/wuzhiwei549/article/details/80563134
    标记-清除算法
    标记-整理算法
    复制算法
    分代算法

  6. 说一下 jvm 有哪些垃圾回收器?
    Serial:最早的单线程串行垃圾回收器。
    Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。
    ParNew:是 Serial 的多线程版本。
    Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。
    Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。
    CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。
    G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。

  7. 详细介绍一下 CMS 垃圾回收器?
    CMS 是英文 Concurrent Mark-Sweep 的简称,是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
    CMS 使用的是标记-清除的算法实现的,所以在 gc 的时候会产生大量的内存碎片,当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old 回收器进行垃圾清除,此时的性能将会被降低。

205.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
新生代回收器:Serial、ParNew、Parallel Scavenge
老年代回收器:Serial Old、Parallel Old、CMS
整堆回收器:G1
新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低;老年代回收器一般采用的是标记-整理的算法进行垃圾回收。

  1. 简述分代垃圾回收器是怎么工作的?
    分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
    老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。

  2. 说一下 jvm 调优的工具?
    JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
    jconsole:用于对 JVM 中的内存、线程和类等进行监控;
    jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

  3. 常用的 jvm 调优的参数都有哪些?
    -Xms2g:初始化推大小为 2g;
    -Xmx2g:堆最大内存为 2g;
    -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
    -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
    -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
    -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
    -XX:+PrintGC:开启打印 gc 信息;
    -XX:+PrintGCDetails:打印 gc 详细信息。

补充-Springboot+SpringCloud
209.什么是SpringBoot?
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
Spring Boot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

210.SpringBoot常用的starter
1、spring-boot-starter-web(嵌入Tomcat和web开发需要的servlet和jsp支持)
2、spring-boot-starter-data-jpa(数据库支持)
3、spring-boot-starter-data-Redis(Redis支持)
4、spring-boot-starter-data-solr(solr搜索应用框架支持)
5、mybatis-spring-boot-starter(第三方mybatis集成starter)

211.SpringBoot自动配置原理
1、@EnableAutoConfiguration这个注解会"猜"你将如何配置spring,前提是你已经添加了jar依赖项,如果spring-boot-starter-web已经添加Tomcat和SpringMVC,这个注释就会自动假设您在开发一个web应用程序并添加相应的spring配置,会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建spring容器中bean
2、在main方法中加上@SpringBootApplication和@EnableAutoConfiguration

212.SpringBoot starter工作原理
1、SpringBoot在启动时扫描项目依赖的jar包,寻找包含spring.factories文件的jar
2、根据spring.factories配置加载AutoConfigure
3、根据@Conditional注解的条件,进行自动配置并将bean注入到Spring Context

213.SpringBoot的优点
1、减少开发、测试时间和努力
2、使用JavaConfig有助于避免使用XML
3、避免大量的maven导入和各种版本冲突
4、提供意见发展方法
5、通过提供默认值快速开始开发
6、没有单独的web服务器需要,这就意味着不再需要启动Tomcat、Glassfish或其他任何东西
7、需要更少的配置,因为没有web.xml文件。只需添加用@Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。甚至可以将@Autowired添加到bean方法中,以使用Spring自动装入需要的依赖关系中

214.Springcloud解决那些问题
配置管理、(注册中心eureka、zk)、服务发现、服务注册、断路器、路由策略、全局锁、分布式会话、客户端调用、接口网关(zuul)、服务管理系统.

215.SpringBoot与Springcloud
1、SpringBoot简化了xml配置,快速整合框架
2、Springcloud是一套微服务解决方案—RPC远程调用
3、关系Springcloud依赖与SpringBoot(web组件用的SpringMVC),为什么Springcloud会依赖与SpringBoot?因为Springcloud写接口就是SpringMVC接口
4、SpringBootproperties和yml中可以使用${random}设置一些随机值

215.服务的调用
restTemplate、feign(均使用httpClient技术),负载均衡ribbon

216.服务调用的原理
服务首先注册到注册中心eureka中(注册一个名字通过名字调用)

217.负载均衡
ribbon,先去注册中心取到对应的服务,然后交给我ribbon

218.配置详解
1、eureka.client.register-with-eureka:是否向注册中心注册自己,注册为true反之为false
2、eureka.client.fetch-registry: 是否需要去检索服务,检索为true反之为false
3、eureka.client.serviceUrl.defaultZone : 指定服务注册中心的地址

219.Eureka
1、eureka可分为三个角色:服务发现者、服务注册者、注册发现中心,但是这三个角色并不和实际部署的模型是一对一的关系
2、所有的网络通信都是基于http(s)协议的
3、Eureka和AWS是紧密结合的,无论是配置还是源码,比如Region、zone…,Region可以通过配置文件进行配置,如果不配置默认使用us-east-1。同样Zone也可以配置,若不配置默认使用defaultZone

220.高可用配置
Eureka server 的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用效果。

221.微服务
以前所有的代码都放在同一个工程中、部署在同一个服务器、同一项目的不同模块不同功能互相抢占资源,微服务就是将工程根据不同的业务规则拆分成微服务,部署在不同的服务器上,服务之间相互调用,java中有的微服务有dubbo(只能用来做微服务)、springcloud( 提供了服务的发现、断路器等)。

222.微服务的特点
按业务划分为一个独立运行的程序,即服务单元
服务之间通过HTTP协议相互通信
自动化部署
可以用不同的编程语言
可以用不同的存储技术
服务集中化管理
微服务是一个分布式系统

223.微服务的优势
1、将一个复杂的业务拆分为若干小的业务,将复杂的业务简单化,新人只需要了解他所接管的服务的代码,减少了新人的学习成本。
2、由于微服务是分布式服务,服务于服务之间没有任何耦合。微服务系统的微服务单元具有很强的横向拓展能力。
3、服务于服务之间采用HTTP网络通信协议来通信,单个服务内部高度耦合,服务与服务之间完全独立,无耦合。这使得微服务可以采用任何的开发语言和技术来实现,提高开发效率、降低开发成本。
4、微服务是按照业务进行拆分的,并有坚实的服务边界,若要重写某一业务代码,不需了解所以业务,重写简单。
5、微服务的每个服务单元是独立部署的,即独立运行在某个进程中,微服务的修改和部署对其他服务没有影响。
6、微服务在CAP理论中采用的AP架构,具有高可用分区容错特点。高可用主要体现在系统7x24不间断服务,他要求系统有大量的服务器集群,从而提高系统的负载能力。分区容错也使得系统更加健壮。

224.微服务的不足
1、微服务的复杂度:构建一个微服务比较复杂,服务与服务之间通过HTTP协议或其他消息传递机制通信,开发者要选出最佳的通信机制,并解决网络服务差时带来的风险。
2、分布式事物:将事物分成多阶段提交,如果一阶段某一节点失败仍会导致数据不正确。如果事物涉及的节点很多,某一节点的网络出现异常会导致整个事务处于阻塞状态,大大降低数据库的性能。
3、服务划分:将一个完整的系统拆分成很多个服务,是一件非常困难的事,因为这涉及了具体的业务场景
4、服务部署:最佳部署容器Docker
微服务和SOA的关系:
微服务相对于和ESB联系在一起的SOA轻便敏捷的多,微服务将复杂的业务组件化,也是一种面向服务思想的体现。对于微服务来说,它是SOA的一种体现,但是它比ESB实现的SOA更加轻便、敏捷和简单。

225.微服务和SOA的关系
微服务相对于和ESB联系在一起的SOA轻便敏捷的多,微服务将复杂的业务组件化,也是一种面向服务思想的体现。对于微服务来说,它是SOA的一种体现,但是它比ESB实现的SOA更加轻便、敏捷和简单。

226.springcloud如何实现服务注册与发现
服务发布时指定对应的服务名(IP地址和端口号),将服务注册到注册中心(eureka和zookeeper),但是这一切是Springcloud自动实现的,只需要在SpringBoot的启动类上加上@EnableDisscoveryClient注解,同一服务修改端口就可以启动多个实例调用方法:传递服务名称通过注册中心获取所有的可用实例,通过负载均衡策略(Ribbon和Feign)调用对应的服务

227.Ribbon和Feign的区别
Ribbon添加的maven依赖是spring-starter-ribbon,使用@RibbonClient(value=“服务名称”)使用RestTemplate调用远程服务对应的方法,
Feign添加的maven依赖是spring-starter-feign,服务提供方提供对外接口,调用方使用,在接口上使用FeignClient(“指定服务名”),
具体区别:
1、启动类使用的注解不同,Ribbon使用的是@RibbonClient,Feign使用的是@EnableFeignClients
2、服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明
3、调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤比较繁琐。Feign则是在Ribbon的基础上进行了一次改进,采用接口调用的方式,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求,不过要注意的是抽象方法的注解、方法签名要和提供方的完全一致。

228.雪崩效应
分布式系统中的服务通信依赖于网络,网络不好,必然会对分布式系统带来很大的影响。在分布式系统中,服务之间相互依赖,如果一个服务之间出现了故障或者网络延迟,在高并发的情况下,会导致线程阻塞,在很短的时间内该服务的线程资源会消耗殆尽,最终使得该服务不可用。由于服务的相互依赖,可能会导致整个系统的不可用,这就是“雪崩效应”。为了防止此类事件的发生,分布式系统必然要采取相应的措施,如熔断机制(Springcloud采用的是Hystrix)

229.熔断机制
1、当一个服务出现故障时,请求失败次数超过设定的阀值(默认50)之后,该服务就会开启熔断器,之后该服务就不进行任何业务逻辑操作,执行快速失败,直接返回请求失败的信息。其他依赖于该服务的服务就不会因为得不到响应而造成线程阻塞,这是除了该服务和依赖于该服务的部分功能不可用外,其他功能正常。
2、熔断器还有一个自我修复机制,当一个服务熔断后,经过一段时间(5s)半打开熔断器。半打开的熔断器会检查一部分请求(只能有一个请求)是否正常,其他请求执行快速失败,检查的请求如果响应成功,则可判断该服务正常了,就可关闭该服务的熔断器,反之则继续打开熔断器。这种自我熔断机制和自我修复机制可以使程序更加健壮、也可以为开发和运维减少很多不必要的工作。
3、熔断组件往往会提供一系列的监控,如:服务可用与否、熔断器是否被打开、目前的吞吐量、网络延迟状态的监控等,从而可以让开发人员和运维人员的了解服务的状况。

230.Eureka基础架构
1>、服务注册中心:Eureka提供的服务端,提供服务注册与发现的功能
1>>、失效剔除:对于那些非正常下线的服务实例(内存溢出、网络故障导致的),服务注册中心不能收到“服务下线”的请求,为了将这些无法提供服务的实例从服务列表中剔除,Eureka Server在启动的时候会创建一个定时任务,默认每隔一段时间(默认60s)将当前清单中超时(默认90s)没有续约的服务剔除出去。
2>>、自我保护:Eureka Server 在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(生产环境由于网络不稳定会导致),Eureka Server会降当前的实例注册信息保护起来,让这些实例不过期,尽可能保护这些注册信息,但是在这保护期间内实例出现问题,那么客户端就很容易拿到实际上已经不存在的服务实例,会出现调用失败的情况,所以客户端必须有容错机制,比如可以使用请求重试、断路器等机制。
在本地进行开发时可以使用 eureka.server.enable-self-preseervation=false参数来关闭保护机制,以确保注册中心可以将不可用的实例剔除。

2>、服务提供者:提供服务的应用,可以是SpringBoot应用也可以是其他的技术平台且遵循Eureka通信机制的应用。他将自己提供的服务注册到Eureka,以供其他应用发现,(如:service层)
1>>、服务注册:服务提供者在启动的时候会通过发送Rest请求的方式将自己注册到Eureka Server(服务注册中心)中,同时带上自身服务的一些元数据,Eureka Server 接收到这个Rest请求后,将元数据存储在一个双层结构Map中,第一层的key是服务名,第二层key是具体服务的实例名
2>>、服务同步:若有两个或两个以上的Eureka Server(服务注册中心)时,他们之间是互相注册的,当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发到集群中相连的其他注册中心,从而实现注册中心间的服务同步,这样服务提供者的服务信息可以通过任意一台服务中心获取到
3>>、服务续约:在注册完服务之后,服务提供者会维护一个心跳来持续告诉Eureka Server:“我还活着”,以防止Eureka Server的“剔除任务”将该服务实例从服务列表中排除出去。配置:eureka.instance.lease-renewal-in-seconds=30(续约任务的调用间隔时间,默认30秒,也就是每隔30秒向服务端发送一次心跳,证明自己依然存活),eureka.instance.lease-expiration-duration-in-seconds=90(服务失效时间,默认90秒,也就是告诉服务端,如果90秒之内没有给你发送心跳就证明我“死”了,将我剔除)

3>、服务消费者:消费者应用从服务注册中心获取服务列表,从而使消费者可以知道去何处调用其所需要的服务,如:Ribbon实现消费方式、Feign实现消费方式
1>>、获取服务:当启动服务消费者的时候,它会发送一个Rest请求给注册中心,获取上面注册的服务清单,Eureka Server会维护一份只读的服务清单来返回给客户端,并且每三十秒更新一次
2>>、服务调用:在服务消费者获取到服务清单后,通过服务名可以获得具体提供服务的实例名和该实例的元信息,采用Ribbon实现负载均衡
3>>、服务下线:当服务实例进行正常的关闭操作时,它会触发一个服务下线的Rest请求给Eureka Server,告诉服务注册中心“我要下线了”。服务端接收到请求之后,将该服务状态设置为下线,并把下线时间传播出去。

231.Eureka和zookeeper都可以提供服务注册与发现的功能,两者的区别
Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用,P:分区容错)
1、Zookeeper-----当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用的。也就是说服务注册功能对高可用性要求比较高,但是zk会出现这样的一种情况,当master节点因为网络故障与其他节点失去联系时,剩余的节点会重新选leader。问题在于,选取leader的时间过长(30~120s),且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务最终恢复,但是漫长的选择时间导致的注册长期不可用是不能容忍的
2、Eureka则看明白这一点,因此再设计的优先保证了高可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响到正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端再向某个Eureka注册时如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保证注册服务的可用(保证可用性),只不过查到的信息可能不是最新的(不保证一致性)。除此之外Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时就会出现以下几种情况:
1>、Eureka不再从注册列表移除因为长时间没收到心跳而应该过期的服务
2>、Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(保证当前节点可用)
3>、当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka还有客户端缓存功能(Eureka分为客户端程序和服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。所以即便Eureka集群中所有节点都失效,或者发生网络分隔故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者任然可以通过Eureka客户端缓存来获取所有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生响应也没有更好的服务器解决方案来解决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要,因此Eureka可以很好的应对网络故障导致部分节点失去联系的情况,而不像Zookeeper那样使整个注册服务瘫痪。

232.CAP理论
1、Consistency:指数据的强一致性。如果写入某个数据成功,之后读取,读到的都是新写入的数据;如果写入失败,读到的都不是写入失败的数据。
2、Availability:指服务的可用性
3、Partition-tolerance:指分区容错

233.Ribbon和Nginx的区别
Nginx性能好,但Ribbon可以剔除不健康节点,Nginx剔除比较麻烦,Ribbon是客户端负载均衡,Nginx是服务端负载均衡

234.服务注册与发现
服务注册就是向服务注册中心注册一个服务实例,服务提供者将自己的服务信息(服务名、IP地址等)告知注册中心。服务发现是服务消费另一个服务时,注册中心将服务的实例返回给服务消费者,一个服务既是服务提供者又是服务消费者。
服务注册中心健康检查机制,当一个服务实例注册成功以后,会定时向注册中心发送一个心跳证明自己可用,若停止发送心跳证明服务不可用将会别剔除。若过段时间继续想注册中心提供心跳,将会重新加入服务注册中心列表中。

235.服务的负载均衡
为什么要用:微服务是将业务代码拆分为很多小的服务单元,服务之间的相互调用通过HTTP协议来调用,为了保证服务的高可用,服务单元往往都是集群化部署的,那么消费者该调用那个服务提供者的实例呢?
介绍:服务消费者集成负载均衡组件,该组件会向服务消费者获取服务注册列表信息,并隔一段时间重新刷新获取列表。当服务消费者消费服务时,负载均衡组件获取服务提供者所有实例的注册信息,并通过一定的负载均衡策略(可以自己配置)选择一个服务提供者实例,向该实例进行服务消费,这样就实现了负载均衡。

236.Redis集群搭建的三种方式
https://blog.csdn.net/e3002/article/details/100691472

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页