Java面试题

有两个字符串String s1 = “38948598490”;
String s2 = “398758476”;
可能超出了long的范围,要求相加并返回字符串的值。javascript

解答:php

char[] a1 = s1.toCharArray();
	char[] a2 = s2.toCharArray();
	StringBuilder sb = new StringBuilder();
	int len1 = a1.length;
	int len2 = a2.length;
	
	int temp = 0;
	int i;
	for (i = 0; i < len1 && i < len2; i++) {
		int left = Integer.valueOf(a1[len1 - i - 1] + "");
		int right = 0;
		right = Integer.valueOf(a2[len2 - i - 1] + "");
		left = left + right + temp;
		temp = left / 10;
	
		int h = left % 10;
		sb.append(h + "");
	}
	if (len1 != len2) {
		if (i + 1 == len1) {
			for (i = len1; i < len2; i++) {
				int t = Integer.valueOf(a2[len2 - i - 1] + "");
				t = t + temp;
				temp = t / 10;
				
				int h = t % 10;
				sb.append(h + "");
			}
		} else {
			for (i = len2; i < len1; i++) {
				int t = Integer.valueOf(a1[len1 - i - 1] + "");
				t = t + temp;
				temp = t / 10;
				
				int h = t % 10;
				sb.append(h + "");
			}
		}
	}
	
	String s = sb.toString();
	sb = new StringBuilder();
	int l = s.length();
	for (int j = l - 1; j >= 0; j--) {
		sb.append(s.charAt(j) + "");
	}
	return sb.toString();

作的时候没有考虑周到,作错了。前端

二、JVM加载class文件的原理机制?
JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的。Java程序须要使用某个类时,JVM会确保这个类已经被加载、链接(验证、准备和解析)和初始化。类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。java

三、引起stackoverflowerror的缘由
内存不够;递归调用node

四、Error和Exception的区别
Error(错误)是系统中的错误,程序员是不能改变的和处理的,通常是指与虚拟机相关的问题。
Exception(异常)表示程序能够处理的异常,能够捕获且可能恢复。遇到这类异常,应该尽量处理异常,使程序恢复运行,而不该该随意终止异常。python

五、java中volatile能修饰数组吗?
能够,java源码中有mysql

六、volatile能使一个非原子操做变成原子操做吗?
不能,volatile保证变量的可见性。保证原子操做用synchonized或locklinux

七、java中weakReference和softReference的区别?
SoftReference 在jvm即将抛出oom的时候,垃圾回收器才会将该引用对象进行回收,避免了系统内存溢出的状况。很是适合实现内存敏感的缓存,例如加载图片的时候,bitmap缓存机制。
WeakReference当垃圾回收器扫描到弱引用的对象的时候,无论内存空间是否足够,都会直接被垃圾回收器回收。不过也不用特别担忧,垃圾回收器是一个优先级比较低的现场,所以不必定很快能够发现弱引用的对象。nginx

八、hashSet、hashMap的内部如何工做的?
equals方法相等,那么hashCode方法也必须相等。
equals方法不相等,那么hashCode方法也能够相等。程序员

hashMap的结构是数组和链表。
利用key的hashCode从新hash计算出当前对象的元素在数组中的下标;
存储时,若是出现hash值相同的key,此时有两种状况。(1)若是key相同,则覆盖原始值;(2)若是key不一样(出现冲突),则将当前的key-value放入链表中;
获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

九、依赖注入和控制反转
Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。是控制反转的另外一种说法。

十一、spring的自动装配方式有哪些?
@Autowired的属性有1,no;2,default;3,byName;4,constructor;5,byType
@Qualifier、@Resource

十二、spring中Bean的做用域?
singleton和prototype、request(对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不一样的Bean实例。只有在Web应用中使用Spring时,该做用域才有效)、session(对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例)、globalsession(每一个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型状况下,仅在使用portlet context的时候有效)

1三、线程池
并发包中Executors提供了实现Executor接口用于建立线程池。
线程池显著减小处理器单元的闲置时间,增长处理器单元的吞吐能力。
一个线程池包括如下四个基本组成部分:线程池管理器、工做线程、任务接口、任务队列
常见线程池:newSingleThreadExecutor、newFixedThreadExecutor(n)、newCacheThreadExecutor(推荐使用,可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(通常是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。)、newScheduleThreadExecutor

1四、JDK和JRE的区别
JDK(Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。Java Runtime Environment(JRE)是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。

1五、==与equeals的区别
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,便是否是指相同一个对象。比较的是真正意义上的指针操做。

equals用来比较的是两个对象的内容是否相等,因为全部的类都是继承自java.lang.Object类的,因此适用于全部对象,若是没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的倒是==的判断。

1六、hashCode()和equals的做用?
hashCode()方法和equal()方法的做用其实同样,都是用来对比两个对象是否相等一致,但hashCode()并非彻底可靠,有时候不一样的对象他们生成的hashcode也会同样。
equal()相等的两个对象他们的hashCode()确定相等;hashCode()相等的两个对象他们的equal()不必定相等。

1七、final的做用?
final关键字能够用来修饰类、方法和变量。
当用final修饰一个类时,代表这个类不能被继承。
final修饰的方法表示此方法已是“最后的、最终的”含义,亦即此方法不能被重写。
final成员变量表示常量,只能被赋值一次,赋值后值再也不改变。

1八、Math.round(-1.5)等于多少?
-1

1九、String,StringBuilder,StringBuffer三者的区别
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量;
StringBuilder是线程不安全的,而StringBuffer是线程安全的

20、String str = “i”;
String s2 = new String(“i”);
System.out.println(str == s2);
输出的结果:false

2一、如何将字符串反转?
StringBuilder sb = new StringBuilder();
sb.append(“abcdefg”);
sb.reverse();
这样就能够反转字符串了。

2二、String的经常使用方法有哪些?
length()、charAt(int index)、substring(int beginIndex)、compareTo(String anotherString)、equals(Object anotherObject)、concat(String str)、indexOf(int ch/String str)、lastIndexOf(int ch/String str, int fromIndex)、replace(char oldChar, char newChar)、split(String str)

2三、抽象类和普通类及接口的区别?
普通类能够去实例化调用,抽象类不能被实例化。抽象类能够有抽象方法,子类继承抽象类必须实现抽象类的抽象方法。

接口不能包含变量,抽象类能够有具体的方法 和属性。
接口的方法必须实现,
类能够实现多个接口,但只能继承一个类。

2四、IO流分为几种?
分为两种,一种是字节流,另外一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种因此一共四个):InputStream,OutputStream,Reader,Writer。

2五、BIO、NIO、AIO有什么区别?

BIO:一个socket链接一个处理线程(这个线程负责这个Socket链接的一系列数据传输操做)。阻塞的缘由在于:操做系统容许的线程数量是有限的,多个socket申请与服务端创建链接时,服务端不能提供相应数量的处理线程,没有分配处处理线程的链接就会阻塞等待或被拒绝。

NIO: 是对BIO的改进,基于Reactor模型。咱们知道,一个socket链接只有在特定时候才会发生数据传输IO操做,大部分时间这个“数据通道”是空闲的,但仍是占用着线程。NIO做出的改进就是“一个请求一个线程”,在链接到服务端的众多socket中,只有须要进行IO操做的才能获取服务端的处理线程进行IO。这样就不会由于线程不够用而限制了socket的接入。客户端的socket链接到服务端时,就会在事件分离器注册一个 IO请求事件 和 IO 事件处理器。在该链接发生IO请求时,IO事件处理器就会启动一个线程来处理这个IO请求,不断尝试获取系统的IO的使用权限,一旦成功(即:能够进行IO),则通知这个socket进行IO数据传输。

AIO:对NIO的改进(因此AIO又叫NIO.2),它是基于Proactor模型的。每一个socket链接在事件分离器注册 IO完成事件 和 IO完成事件处理器。程序须要进行IO时,向分离器发出IO请求并把所用的Buffer区域告知分离器,分离器通知操做系统进行IO操做,操做系统本身不断尝试获取IO权限并进行IO操做(数据保存在Buffer区),操做完成后通知分离器;分离器检测到 IO完成事件,则激活 IO完成事件处理器,处理器会通知程序说“IO已完成”,程序知道后就直接从Buffer区进行数据的读写。

2六、java容器有哪些?
List、set、Map、queue

2七、List、Set、Map之间的区别是什么?
List 是可重复集合,Set 是不可重复集合,这两个接口都实现了 Collection 父接口。
Map 是一种把键对象和值对象进行映射的集合,它的每个元素都包含了一对键对象和值对象,Map 中存储的数据是没有顺序的, 其 key 是不能重复的,它的值是能够有重复的。

List 的实现类有 ArrayList,Vector 和 LinkedList
ArrayList 和 Vector 内部是线性动态数组结构,在查询效率上会高不少
LinkedList:是双向链表的数据结构存储数据,在作查询时会按照序号索引数据进行前向或后向遍历,查询效率偏低,但插入数据时只须要记录本项的先后项便可,因此插入速度较快。

Set 的实现类有 HashSet 和 TreeSet
HashSet:内部是由哈希表(其实是一个 HashMap 实例)支持的。它不保证 set 元素的迭代顺序。
TreeSet:TreeSet 使用元素的天然顺序对元素进行排序,或者根据建立 set 时提供的 Comparator 进行排序。

Map 接口实现类:Hashtable,HashMap,TreeMap,LinkedHashMap
Hashtable:内部存储的键值对是无序的是按照哈希算法进行排序,与 HashMap 最大的区别就是线程安全。键或者值不能为 null,为 null 就会抛出空指针异常。
TreeMap:基于红黑树 (red-black tree) 数据结构实现,按 key 排序,默认的排序方式是升序。
LinkedHashMap:有序的 Map 集合实现类,至关于一个栈,先 put 进去的最后出来,先进后出。

2八、hashMap、TreeMap、LinkedHashMap的使用场景?
TreeMap是基于红黑树的实现的排序Map,对于增删改查以及统计的时间复杂度都控制在O(logn)的级别
HashMap和LikedHashMap 这些 hash表的时间复杂度O(1)

须要基于排序的统计功能使用TreeMap
须要快速增删改查的存储功能hashMap
须要快速增删改查并且须要保证遍历和插入顺序一致的存储功能LinkedHashMap

2九、HashMap的实现原理?
HashMap存储的是key-value的键值对,容许key为null,也容许value为null。HashMap内部为数组+链表的结构,会根据key的hashCode值来肯定数组的索引(确认放在哪一个桶里),若是遇到索引相同的key,桶的大小是2,若是一个key的hashCode是7,一个key的hashCode是3,那么他们就会被分到一个桶中(hash冲突),若是发生hash冲突,HashMap会将同一个桶中的数据以链表的形式存储,可是若是发生hash冲突的几率比较高,就会致使同一个桶中的链表长度过长,遍历效率下降,因此在JDK1.8中若是链表长度到达阀值(默认是8),就会将链表转换成红黑二叉树。

负载因子是0.75,每次都是扩容为原来的2倍。
put方法:
1.table[]是否为空
2.判断table[i]处是否插入过值
3.判断链表长度是否大于8,若是大于就转换为红黑二叉树,并插入树中
4.判断key是否和原有key相同,若是相同就覆盖原有key的value,并返回原有value
5.若是key不相同,就插入一个key,记录结构变化一次

get方法实现:
1.判断表或key是不是null,若是是直接返回null
2.判断索引处第一个key与传入key是否相等,若是相等直接返回
3.若是不相等,判断链表是不是红黑二叉树,若是是,直接从树中取值
4.若是不是树,就遍历链表查找

30、HashSet的实现原理?
HashSet是基于HashMap实现的。

3一、Queue中remove()和poll()的区别?
若是队列为空,poll()返回null,remove()则抛出NoSuchElementException异常

3二、哪些集合类是线程安全的?
Vector、HashTable、ConcurrentHashMap、Stack、ArrayBlockingQueue、CopyOnWriteArrayList

3三、什么是Iterator?
迭代器就是遍历集合取出元素的方式,迭代器能够取出并操做集合中的元素。
Iterator模式是用于遍历集合类的标准访问方法。它能够把访问逻辑从不一样类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。

使用next()得到序列中的下一个元素;使用hasNext()检查序列中是否还有元素;使用remove()将迭代器新返回的元素删除。

3四、怎么确保一个集合不能被修改?
使用Collections工具类的方法UnmodifiableSet、UnmodifiableList、UnmodifiableMap

3五、并行和并发的区别?
并发的关键是你有处理多个任务的能力,不必定要同时
并行的关键是你有同时处理多个任务的能力

3六、线程和进程的区别?
进程是资源分配的最小单位一个应用程序就是一个进程,线程是程序执行的最小单位。
进程有本身的独立地址空间,每启动一个进程,系统就会为它分配地址空间,创建数据表来维护代码段、堆栈段和数据段,这种操做很是昂贵。而线程是共享进程中的数据的,使用相同的地址空间,所以CPU切换一个线程的花费远比进程要小不少,同时建立一个线程的开销也比进程要小不少。
线程之间的通讯更方便,进程程序更健壮。

3七、守护线程是什么?
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
存在任何一个非守护线程没有结束,守护线程就所有工做;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工做。

3八、建立线程有哪几种方式?

  1. 继承 Thread 类,而后调用 start 方法。
  2. 实现 Runnable 接口的 run 方法, 而后再用 Thread 类包裹后,调用 start 方法
  3. 实现 Callable 接口的 call 方法,用 FutureTask 类包裹 Callable 对象。而后再用 Thread 类包裹 FutureTask 类,并调用 start 方法。call() 方法能够有返回值。

3九、线程有哪些状态?
线程的生命周期大致可分为5种状态:

  1. 新建(NEW):新建立了一个线程对象。

  2. 可运行(RUNNABLE):线程对象建立后,其余线程(好比main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

  3. 运行(RUNNING):可运行状态(runnable)的线程得到了cpu 时间片(timeslice) ,执行程序代码。

  4. 阻塞(BLOCKED):阻塞状态是指线程由于某种缘由放弃了cpu 使用权,也即让出了cpu timeslice,暂时中止运行。直到线程进入可运行(runnable)状态,才有机会再次得到cpu timeslice 转到运行(running)状态。阻塞的状况分三种:
    (一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
    (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
    (三). 其余阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入可运行(runnable)状态。

  5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

40、sleep和wait的区别?
sleep是Thread线程类的方法,而wait是Object顶级类的方法。
sleep方法没有释放锁,而wait方法释放了锁
wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep能够在任何地方使用
sleep必须捕获异常,而wait,notify和notifyAll不须要捕获异常

4一、线程的run()和start()有什么区别?
调用run()只是调用这个方法;调用start()启动了一个线程

4二、线程池中submit()和execute()方法有什么区别?
submit有返回值,而execute没有
submit方便Exception处理

4三、如何保证线程安全性?
线程安全在三个方面体现:1.原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操做,(atomic,synchronized);

2.可见性:一个线程对主内存的修改能够及时地被其余线程看到,(synchronized,volatile);

3.有序性:一个线程观察其余线程中的指令执行顺序,因为指令重排序,该观察结果通常杂乱无序,(happens-before原则)。

4四、什么是死锁,怎么预防?
程死锁是指因为两个或者多个线程互相持有对方所须要的资源,致使这些线程处于等待状态,没法前往执行。
死锁的产生是必需要知足一些特定条件的:
1.互斥条件:进程对于所分配到的资源具备排它性,即一个资源只能被一个进程占用,直到被该进程释放
2.请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已得到的资源保持不放。
3.不剥夺条件:任何一个资源在没被该进程释放以前,任何其余进程都没法对他剥夺占用
4.循环等待条件:当发生死锁时,所等待的进程一定会造成一个环路(相似于死循环),形成永久阻塞。

避免死锁的技术:加锁顺序、加锁时限、死锁检测

4五、ThreadLocal原理及使用场景?
它是线程的局部变量,这些变量只能在这个线程内被读写,在其余线程内是没法访问的。 ThreadLocal 定义的一般是与线程关联的私有静态字段。
当咱们只想在自己的线程内使用的变量,能够用 ThreadLocal 来实现,而且这些变量是和线程的生命周期密切相关的,线程结束,变量也就销毁了。数据库链接、Session管理等能够用到 ThreadLocal
ThreadLocal 的使用很是简单,最核心的操做就是四个:建立、建立并赋初始值、赋值、取值。initialValue()、set()、get()、remove()

4六、synchronized和reentrantLock的区别?
synchronized是在JVM层面上实现的,不但能够经过一些监控工具监控synchronized的锁定,并且在代码执行时出现异常,JVM会自动释放锁定,可是使用Lock则不行,lock是经过代码实现的,要保证锁定必定会被释放,就必须将unLock()放到finally{}中。

4七、atomic的原理?
经过CAS乐观锁保证原子性,经过自旋保证当次修改的最终修改为功,经过下降锁粒度(多段锁)增长并发性能。

4八、什么是反射?
运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意方法和属性;而且能改变它的属性。

4九、序列化是什么,什么状况下须要使用?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。能够对流化后的对象进行读写操做,也可将流化后的对象传输于网络之间。
网络传输或将对象写入到文件中。

50、动态代理是什么?有哪些应用?怎么实现?
动态代理,利用Java的反射技术(Java Reflection),在运行时建立一个实现某些给定接口的新类及其实例。
应用场景:适配器(Adapter)或修饰器(Decorator)、面向切面编程
一、调用Proxy.newProxyInstance();这个方法有三个参数,
类加载器(Class Loader);须要实现的接口数组;InvocationHandler接口。全部动态代理类的方法调用,都会交由InvocationHandler接口实现类里的invoke()方法去处理。这是动态代理的关键所在。

二、cglib实现
类要实现MethodInterceptor接口,包含cglib的jar包

5一、深复制(深克隆)与浅复制(浅克隆)
浅复制:被复制对象的全部变量都含有与原来的对象相同的值,而全部的对其余对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所拷贝的对象,而不复制它所引用的对象。
深复制:被复制对象的全部变量都含有与原来的对象相同的值,除去那些引用其余对象的变量。那些引用其余对象的变量将指向被复制过的新对象,而再也不是原有的那些被引用的对象。
必需要实现Cloneable 接口。

5二、Jsp和servlet的区别?
jsp经编译后就变成了Servlet;jsp更擅长表现于页面显示,servlet更擅长于逻辑控制;Servlet中没有内置对象,Jsp中的内置对象都是必须经过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象获得

5三、Jsp的内置对象有哪些?做用域有哪些?
1.request 用户端请求
2.response 网页传回用户端回应
3.pageContext 网页的属性在这里管理
三、session 与请求有关会话期
四、application servlet正在执行的内容
五、out 用来传送回应的输出
六、config servlet的架构部件
七、page JSP网页自己
八、exception 针对错误网页,未捕捉的列外
JSP四大做用域分别为:page, request ,session, application

5四、session和cookie的区别?
一、cookie数据存放在客户的浏览器上,session数据放在服务器上。
二、cookie不是很安全,别人能够分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
三、session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
四、单个cookie保存的数据不能超过4K

5五、怎么避免sql注入?什么是XSS攻击,怎么避免?什么是CSRF攻击,怎么避免?
使用PreparedStatement语句;
XSS(Cross Site Scripting),即跨站脚本攻击,是一种常见于web应用程序中的计算机安全漏洞.XSS经过在用户端注入恶意的可运行脚本,若服务器端对用户输入不进行处理,直接将用户输入输出到浏览器,而后浏览器将会执行用户注入的脚本。
对用户输入进行过滤;

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕事后台的用户验证,达到冒充用户对被攻击的网站执行某项操做的目的。
目前防护 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

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

5七、final、finally、finalize的区别?
final能够用来修饰类,方法和变量
当用final修饰类的时,代表该类不能被其余类所继承。
final方法意味着“最后的、最终的”含义,即此方法不能被重写。
final成员变量表示常量,只能被赋值一次,赋值后其值再也不改变。
finally做为异常处理的一部分,它只能用在try/catch语句中,而且附带一个语句块,表示这段语句最终必定会被执行(无论有没有抛出异常),常常被用在须要释放资源的状况下。
finalize()是在java.lang.Object里定义的,也就是说每个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。

5八、常见的异常类有哪些?
IllegalArgumentException、IllegalStateException 、UnsupportedOperationException、NumberFormatException、IndexOutOfBoundsExecption、NoSuchMethodException、IOException、SQLException、NumberFormatException、ClassCastException、ArrayIndexOutOfBoundsException、NullPointerException

5九、Tcp和udp的区别?
一、TCP面向链接(如打电话要先拨号创建链接);UDP是无链接的,即发送数据以前不须要创建链接
二、TCP提供可靠的服务。也就是说,经过TCP链接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
三、TCP面向字节流,其实是TCP把数据当作一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,所以网络出现拥塞不会使源主机的发送速率下降(对实时应用颇有用,如IP电话,实时视频会议等)
四、每一条TCP链接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通讯
五、TCP首部开销20字节;UDP的首部开销小,只有8个字节
六、TCP的逻辑通讯信道是全双工的可靠信道,UDP则是不可靠信道

60、简述tcp的三次握手和四次挥手的流程,为何断开链接要 4 次,若是握手只有两次,会出现什么?
第一次握手(SYN=1, seq=x):

客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算链接的服务器的端口,以及初始序号 X,保存在包头的序列号(SequenceNumber)字段里。
发送完毕后,客户端进入 SYN_SEND 状态。

第二次握手(SYN=1, ACK=1,seq=y, ACKnum=x+1):

服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择本身 ISN 序列号,放到 Seq 域里,同时将确认序号(AcknowledgementNumber)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。
第三次握手(ACK=1,ACKnum=y+1)

客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,而且把服务器发来 ACK 的序号字段+1,放在肯定字段中发送给对方,而且在数据段放写ISN的+1
发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。

握手过程当中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP链接一旦创建,在通讯双方中的任何一方主动关闭链接以前,TCP 链接都将被一直保持下去。

四次挥手指断开链接的过程
第一次挥手(FIN=1,seq=x)

假设客户端想要关闭链接,客户端发送一个 FIN 标志位置为1的包,表示本身已经没有数据能够发送了,可是仍然能够接受数据。
发送完毕后,客户端进入 FIN_WAIT_1 状态。

第二次挥手(ACK=1,ACKnum=x+1)

服务器端确认客户端的 FIN 包,发送一个确认包,代表本身接受到了客户端关闭链接的请求,但尚未准备好关闭链接。
发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包以后,进入 FIN_WAIT_2 状态,等待服务器端关闭链接。

第三次挥手(FIN=1,seq=y)

服务器端准备好关闭链接时,向客户端发送结束链接请求,FIN 置为1。
发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

第四次挥手(ACK=1,ACKnum=y+1)

客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。
服务器端接收到这个确认包以后,关闭链接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 MaximumSegment Lifetime)以后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭链接,因而本身也关闭链接,进入 CLOSED 状态。
两次后会重传直到超时。若是多了会有大量半连接阻塞队列。

若是只有两次握手,客户端到服务器的链接是成功的,但服务器到客户端的链接是不确认的。

6一、osi的七层模型有哪些?
第7层应用层—直接对应用程序提供服务,应用程序能够变化,但要包括电子消息传输
第6层表示层—格式化数据,以便为应用程序提供通用接口。这能够包括加密服务
第5层会话层—在两个节点之间创建端链接。此服务包括创建链接是以全双工仍是以半双工的方式进行设置,尽管能够在层4中处理双工方式
第4层传输层—常规数据递送-面向链接或无链接。包括全双工或半双工、流控制和错误恢复服务
第3层网络层—本层经过寻址来创建两个节点之间的链接,它包括经过互连网络来路由和中继数据
第2层数据链路层—在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址
第1层物理层—原始比特流的传输电子信号传输和硬件接口数据发送时,从第七层传到第一层,接受方则相反。

6二、get和post的区别?
get,参数url可见;post,url参数不可见
get,经过拼接url进行传递参数;post,经过body体传输参数
get请求是能够缓存的post请求不能够缓存
get请求页面后退时,不产生影响;post请求页面后退时,会从新提交请求
get通常传输数据大小不超过2k-4k(根据浏览器不一样,限制不同,但相差不大)
post请求传输数据的大小根据php.ini 配置文件设定,也能够无限大。

6三、如何实现跨域?
浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(由于a.cn和b.cn是不一样域),因此跨域就出现了。
服务器通常须要增长以下响应头的一种或几种:Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

6五、经常使用的设计模式?
单例模式、工厂模式、观察者模式、适配器(Adapter)模式、代理模式、装饰模式

6六、简单工厂和抽象工厂的区别?
简单工厂:工厂类(SimpleFactory)拥有一个工厂方法(create),接受了一个参数,经过不一样的参数实例化不一样的产品类。
工厂方法:工厂方法是针对每一种产品提供一个工厂类。经过不一样的工厂实例来建立不一样的产品实例。
抽象工厂:抽象工厂是应对产品族概念的。

6七、什么是aop、Ioc?
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:建立被调用者的工做再也不由调用者来完成,而是由Spring容器完成,依赖关系被反转了,称为控制反转 。
AOP(Aspect Oriented Programming)面向方面编程, 将通用需求功能从不相关类之中分离出来;同时,可以使得不少类共享一个行为,一旦行为发生变化,没必要修改不少类,只要修改这个行为就能够。

6八、spring有哪些主要模块?
core、beans、context、 expression language、web、webmvc、aop、orm、dao

6九、Spring中的Bean是线程安全的吗?
Spring容器中的Bean自己不具有线程安全的特性,可是具体仍是要结合具体scope的Bean去研究。
prototype:对于原型Bean,每次建立一个新对象,也就是线程之间并不存在Bean共享,天然是不会有线程安全的问题。

singleton:对于单例Bean,全部线程都共享一个单例实例Bean,所以是存在资源的竞争。

70、spring运行流程
用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求能够访问Servlet、哪些不能访问。就是url-pattern的做用,而且会加载springmvc.xml配置文件。
前端控制器会找处处理器映射器(HandlerMapping),经过HandlerMapping完成url到controller映射的组件,简单来讲,就是将在springmvc.xml中配置的或者注解的url与对应的处理类找到并进行存储,用map<url,handler>这样的方式来存储。
HandlerMapping有了映射关系,而且找到url对应的处理器,HandlerMapping就会将其处理器(Handler)返回,在返回前,会加上不少拦截器。
DispatcherServlet拿到Handler后,找到HandlerAdapter(处理器适配器),经过它来访问处理器,并执行处理器。
执行处理器
处理器会返回一个ModelAndView对象给HandlerAdapter
经过HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet)
前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp),其实就是将ModelAndView对象中存放视图的名称进行查找,找到对应的页面造成视图对象
返回视图对象到前端控制器。
视图渲染,就是将ModelAndView对象中的数据放到request域中,用来让页面加载数据的。
经过第8步,经过名称找到了对应的页面,经过第10步,request域中有了所须要的数据,那么就可以进行视图渲染了。最后将其返回便可。
在这里插入图片描述

7一、springmvc有哪些组件?

  1. 前端控制器组件(DispatcherServlet)
    2. 处理器组件(Controller)
    3. 处理器映射器组件(HandlerMapping)
    4. 处理器适配器组件(HandlerAdapter)
    5. 拦截器组件(HandlerInterceptor)
    6. 视图解析器组件(ViewResolver)
    7. 视图组件(View)
    8. 数据转换组件(DataBinder)
    9. 消息转换器组件(HttpMessageConverter)

7二、什么是springboot?为何要用?
SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了Spring众多框架中所需的大量且繁琐的配置文件,因此 SpringBoot是一个服务于框架的框架,服务范围是简化配置文件。

  1. 配置简单了
      2. springboot内嵌了servlet容器,下降了对环境的要求,机器有java运行环境,能够将项目打包成jar包,经过java命令 java -jar ****.jar 来执行。
    3. 快速整合第三方框架,无需配置文件
    4. 代码少了、配置文件少了、不须要对第三方框架烦恼了、项目精简了,对整个团队的开发及维护来讲,更大的节约了成本。

7三、springboot核心配置文件是什么?
bootstrap和application(.yml或.properties)
bootstrap由父ApplicationContext加载,优先于application;
bootstrap主要用于从额外的资源来加载配置信息,还能够在本地外部配置文件中解密属性。不能被本地相同配置覆盖。

7四、springboot哪些方式实现热部署
1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动

2.使用springloaded本地加载启动,配置jvm参数

-javaagent:<jar包地址> -noverify

3.使用devtools工具包,操做简单,可是每次须要从新部署

7五、jpa和hibernate的区别?
JPA自己是一种规范,它的本质是一种ORM规范,只是提供了一些相关的接口,可是接口并不能直接使用,JPA底层须要某种JPA实现,JPA如今就是Hibernate功能的一个子集。
Hibernate属于遵循JPA规范的一种实现,可是JPA是Hibernate遵循的规范之一,Hibernate还有其余实现的规范。

7六、什么是springcloud?
Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案。
Spring Cloud为微服务架构开发涉及的配置管理,服务治理,熔断机制,智能路由,微代理,控制总线,一次性token,全局一致性锁,leader选举,分布式session,集群状态管理等操做提供了一种简单的开发方式。

7七、springcloud断路器的做用?
在分布式架构中,断路器模式的做用也是相似的,当某个服务单元发生故障(相似用电器发生短路)以后,经过断路器的故障监控(相似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

7八、springcloud核心组件有哪些?
服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon
断路器——Netflix Hystrix
服务网关——Netflix Zuul
分布式配置——Spring Cloud Config
服务调用 Feign

7九、Mybatis中#{}和${}的区别?
#{}将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,可以很大程度防止sql注入。
$将传入的数据直接显示生成在sql中,没法防止Sql注入,通常用于传入数据库对象,例如传入表名。

80、Mybatis有几种分页方式?
一、查询出所有数据,而后再list中截取须要的部分
二、sql分页
三、PageHelper分页插件

8一、mybatis逻辑分页和物理分页的区别?
逻辑分页 内存开销比较大,在数据量比较小的状况下效率比物理分页高;在数据量很大的状况下,内存开销过大,容易内存溢出;
物理分页 内存开销比较小,在数据量比较小的状况下效率比逻辑分页仍是低,在数据量很大的状况下,建议使用物理分页
逻辑分页是将查询的全部结果放置在内存中,每次都从内存获取。
物理分页每次只查询对应条目数量的数据,从而实现了真正意义上的分页。

8二、mybatis是否支持延迟加载,实现原理是什么?
一般会进行多表联合查询,可是有的时候并不会当即用到全部的联合查询结果,此时须要一种机制,当须要的时候再查询,这种“按需查询”的机制,就能够使用延迟加载来实现。
lazyLoadingEnabled设置为true
aggressiveLazyLoading设置为false

8三、mybatis一级缓存和二级缓存?
合理使用缓存是优化中最多见的,将从数据库中查询出来的数据放入缓存中,下次使用时没必要从数据库查询,而是直接从缓存中读取,避免频繁操做数据库,减轻数据库的压力,同时提升系统性能。
一级缓存是SqlSession级别的缓存。在操做数据库时须要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不一样的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能做用在同一个sqlSession中,不一样的sqlSession中的缓存是互相不能读取的。
二级缓存是mapper级别的缓存,多个SqlSession去操做同一个Mapper的sql语句,多个SqlSession能够共用二级缓存,二级缓存是跨SqlSession的。二级缓存的做用范围更大。

8四、mybatis于hibernate的区别?
hibernate开发中,sql语句已经被封装,直接能够使用,加快系统开发;
Mybatis 属于半自动化,sql须要手工完成,稍微繁琐;
Hibernate 自动生成sql,有些语句较为繁琐,会多消耗一些性能;
Mybatis 手动编写sql,能够避免不须要的查询,提升系统性能;
Hibernate 是完整的对象-关系映射的框架,开发工程中,无需过多关注底层实现,只要去管理对象便可;
Mybatis 须要自行管理 映射关系;

8五、Mybatis都有哪些Executor执行器?它们之间的区别是什么?
Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完马上关闭Statement对象。

ReuseExecutor:执行update或select,以sql做为key查找Statement对象,存在就使用,不存在就建立,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将全部sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每一个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
做用范围:Executor的这些特色,都严格限制在SqlSession生命周期范围内。

8六、分页插件的原理是什么?以及如何编写一个插件?
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,而后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10
Mybatis仅能够编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为须要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,固然,只会拦截那些你指定须要拦截的方法。
实现Mybatis的Interceptor接口并复写intercept()方法,而后在给插件编写注解,指定要拦截哪个接口的哪些方法便可,记住,别忘了在配置文件中配置你编写的插件。

8七、rabbitmq使用场景有哪些?
发送手机验证码,邮件;.应用解耦;流量削峰;日志处理;消息通信

8八、rabbitmq的重要组件?
消费者、生产者、队列、交换器

8九、rabbitmq中vhost做用?
每一个virtual host本质上都是一个RabbitMQ Server,拥有它本身的queue,exchagne,和bings rule等等。这保证了你能够在多个不一样的application中使用RabbitMQ。

90、如何确保rabbitMQ消息的可靠性?
publisher confirms(发布方确认);
message持久化;
acknowledgement(consumer确认)。

9一、RabbitMQ 如何保证消息不丢失?
消息持久化:要想作到消息持久化,必须知足如下三个条件,缺一不可(Exchange 设置持久化、Queue 设置持久化、Message持久化发送);
要在producer引入事务机制或者Confirm机制来确保消息已经正确的发送至broker端
ACK确认机制;
设置集群镜像模式;
消息补偿机制。

9二、rabbitmq怎么实现延迟消息队列?
消息的TTL就是消息的存活时间(Time To Live),RabbitMQ能够对队列和消息分别设置TTL。对队列设置就是队列没有消费者连着的保留时间,也能够对每个单独的消息作单独的设置。超过了这个时间,咱们认为这个消息就死了,称之为死信。若是队列设置了,消息也设置了,那么会取小的。单靠死信还不能实现延迟任务,还要靠Dead Letter Exchange。
一个消息在知足以下条件下,会进死信路由,记住这里是路由而不是队列,一个路由能够对应不少队列。一、一个消息被Consumer拒收了,而且reject方法的参数里requeue是false。也就是说不会被再次放在队列里,被其余消费者使用。二、上面的消息的TTL到了,消息过时了;三、队列的长度限制满了。排在前面的消息会被丢弃或者扔到死信路由上。

实现延迟队列:延迟任务经过消息的TTL和Dead Letter Exchange来实现。咱们须要创建2个队列,一个用于发送消息,一个用于消息过时后的转发目标队列。
第一步:给队列或者指定消息设置过时时间(TTL),过时后变成 死信
第二部:设置死信的转发规则(若是没有任何规则,则直接丢弃死信) ,重新消费

9三、rabbitmq集群有什么用?
rabbitmq有3种模式,但集群模式是2种。
单一模式:即单机状况不作集群,就单独运行一个rabbitmq而已。
普通模式:默认模式,以两个节点(rabbit0一、rabbit02)为例来进行说明。对于Queue来讲,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit0一、rabbit02间进行消息传输,把A中的消息实体取出并通过B发送给consumer。因此consumer应尽可能链接每个节点,从中取消息。即对于同一个逻辑队列,要在多个节点创建物理Queue。不然不管consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点没法取到rabbit01节点中还未消费的消息实体。若是作了消息持久化,那么得等rabbit01节点恢复,而后才可被消费;若是没有持久化的话,就会产生消息丢失的现象。
镜像模式:把须要的队列作成镜像队列,存在与多个节点属于RabbitMQ的HA方案。该模式解决了普通模式中的问题,其实质和普通模式不一样之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的反作用也很明显,除了下降系统性能外,若是镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通信大大消耗掉。因此在对可靠性要求较高的场合中适用。

容许消费者和生产者在Rabbit节点崩溃的状况下继续运行;
经过增长节点来扩展Rabbit处理更多的消息,承载更多的业务量;

9四、rabbitmq 的消息是怎么发送的?
(1)客户端链接到消息队列服务器,打开一个channel。
(2)客户端声明一个exchange,并设置相关属性。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routing key,在exchange和queue之间创建好绑定关系。
(5)客户端投递消息到exchange。

9五、rabbitmq 怎么保证消息的稳定性?
费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;若是RabbitMQ没有收到回执并检测到消费者的RabbitMQ链接断开,则RabbitMQ会将该消息发送给其余消费者(若是存在多个消费者)进行处理。

9六、rabbitmq 持久化有什么缺点?
1、若是消息的自动确认为true,那么在消息被接收之后,RabbitMQ就会删除该消息,假如消费端此时宕机,那么消息就会丢失。所以须要将消息设置为手动确认。
2、设置手动确认会出现另外一个问题,若是消息已被成功处理,但在消息确认过程当中出现问题,那么在消费端重启后,消息会从新被消费。
3、发送端为了保证消息会成功投递,通常会设定重试。若是消息发送至RabbitMQ以后,在RabbitMQ回复已成功接收消息过程当中出现异常,那么发送端会从新发送该消息,从而形成消息重复发送。
4、RabbitMQ的消息磁盘写入,若是出现问题,也会形成消息丢失。

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

9八、rabbitmq 节点的类型有哪些?
内存节点、磁盘节点。顾名思义内存节点就是将全部数据放在内存,磁盘节点将数据放在磁盘

9九、rabbitmq 集群搭建须要注意哪些问题?
每一个节点Cookie的同步;主机之间 必须能够相互识别并可达,/etc/hosts文件配置必须准确

100、rabbitmq 每一个节点是其余节点的完整拷贝吗?为何?
不是,队列的完整信息只放在一个节点,其余节点存放的是该队列的指针

10一、rabbitmq 集群中惟一一个磁盘节点崩溃了会发生什么状况?
若是惟一的磁盘节点崩溃,集群是能够保持运行的,但不能更改任何东西。

不能建立队列
不能建立交换器
不能建立绑定
不能添加用户
不能更改权限
不能添加和删除集群几点

10二、rabbitmq 对集群节点中止顺序有要求吗?
启动顺序:磁盘节点 => 内存节点
关闭顺序:内存节点 => 磁盘节点

10三、ZooKeeper是什么?
ZooKeeper是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能、高可用,且具备严格顺序访问控制能力的分布式协调服务。
分布式应用程序能够基于ZooKeeper实现数据发布与订阅、负载均衡、命名服务、分布式协调与通知、集群管理、Leader选举、分布式锁、分布式队列等功能。

10四、zookeeper有哪些功能?
.配置中心
2.命名服务
3.Master选举
4.分布式锁
5.服务注册与推送

10五、zookeeper有几种部署模式?
分为三种模式:单机模式、集群模式和伪集群模式。

10六、zookeeper怎样保证主从节点的状态同步?
Zookeeper的核心是原子广播机制,这个机制保证了各个server之间的同步。实现这个机制的协议叫作Zab协议。Zab协议有两种模式,它们分别是恢复模式和广播模式。
(1) 恢复模式
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数server完成了和leader的状态同步之后,恢复模式就结束了。状态同步保证了leader和server具备相同的系统状态。
(2) 广播模式
一旦Leader已经和多数的Follower进行了状态同步后,他就能够开始广播消息了,即进入广播状态。这时候当一个Server加入ZooKeeper服务中,它会在恢复模式下启动,发现Leader,并和Leader进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper服务一直维持在Broadcast状态,直到Leader崩溃了或者Leader失去了大部分的Followers支持。
数据一致性是靠Paxos算法保证的,Paxos能够说是分布式一致性算法的鼻祖,是ZooKeeper的基础

10七、集群中为何要有主节点?
在分布式环境中,有些业务逻辑只须要集群中的某一台机器进行执行,其余的机器能够共享这个结果,这样能够大大减小重复计算,提升性能,因此就须要主节点。

10八、集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还能够使用吗?
能够继续使用,单数服务器只要没超过一半的服务器宕机就能够继续使用。

10九、说一下 zookeeper 的通知机制?
客户端端会对某个 znode 创建一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,而后客户端能够根据 znode 变化来作出业务上的改变。

1十、数据库的三范式?
第一范式:当关系模式R的全部属性都不能在分解为更基本的数据单位时,称R是知足第一范式的
第二范式:若是关系模式R知足第一范式,而且R得全部非主属性都彻底依赖于R的每个候选关键属性,称R知足第二范式
第三范式:设R是一个知足第一范式条件的关系模式,X是R的任意属性集,若是X非传递依赖于R的任意一个候选关键字,称R知足第三范式

1十一、一张表里面有ID自增主键,当insert了17条记录以后,删除了第15,16,17条记录,再把mysql重启,再insert一条记录,这条记录的ID是18仍是15 ?
通常状况下,咱们建立的表的类型是InnoDB,若是新增一条记录(不重启mysql的状况下),这条记录的id是18;可是若是重启(文中提到的)MySQL的话,这条记录的ID是15。由于InnoDB表只把自增主键的最大ID记录到内存中,因此重启数据库或者对表OPTIMIZE操做,都会使最大ID丢失。

1十二、mysql如何获取当前数据库版本?
select version();

11三、ACID是什么?
1.Atomicity 原子性
2.Consistency 一致性
3.Isolation 隔离性
4.Durability 持久性
原子性,指的是整个事务是一个独立的单元,要么操做成功,要么操做不成功
一致性,事务必需要保持和系统处于一致的状态(若是不一致会致使系统其它的方出现bug)
隔离性,事务是并发控制机制,他们的交错也须要一致性,隔离隐藏,通常经过悲观或者乐观锁实现
持久性,一个成功的事务将永久性地改变系统的状态,因此在它结束以前,全部致使状态的变化都记录在一个持久的事务日志中

11四、char和varchar的区别?
char:存储定长数据很方便,CHAR字段上的索引效率级高,必须在括号里定义长度,能够有默认值,好比定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间(自动用空格填充),且在检索的时候后面的空格会隐藏掉,因此检索出来的数据须要记得用什么trim之类的函数去过滤空格。
varchar:存储变长数据,但存储效率没有CHAR高,必须在括号里定义长度,能够有默认值。保存数据的时候,不进行空格自动填充,并且若是数据存在空格时,当值保存和检索时尾部的空格仍会保留。另外,varchar类型的实际长度是它的值的实际长度+1,这一个字节用于保存实际使用了多大的长度。

一、常常变化的字段用varchar;
二、知道固定长度的用char;
三、超过255字节的只能用varchar或者text;
四、能用varchar的地方不用text;
五、可以用数字类型的字段尽可能选择数字类型而不用字符串类型,这会下降查询和链接的性能,并会增长存储开销。这是由于引擎在处理查询和链接回逐个比较字符串中每个字符,而对于数字型而言只须要比较一次就够了

11五、mysql中float和double、decimal的区别?
float数值类型用于表示单精度浮点数值,而double数值类型用于表示双精度浮点数值,float和double都是浮点型,而decimal是定点型;
FLOAT和DOUBLE在不指 定精度时,默认会按照实际的精度来显示,而DECIMAL在不指定精度时,默认整数为10,小数为0。
double精度高,有效数字16位,float精度7位。但double消耗内存是float的两倍,double的运算速度比float慢得多

11六、mysql中的内链接、左链接、右链接的区别?
内链接,显示两个表中有联系的全部数据;
2.左连接,以左表为参照,显示全部数据;
3.右连接,以右表为参照显示数据;

11七、mysql的索引怎么实现的?
索引是一种高效获取数据的存储结构,例:hash、 二叉、 红黑
Mysql为何不用上面三种数据结构而采用B+Tree:
若仅仅是 select * from table where id=45 , 上面三种算法能够轻易实现,但如果select * from table where id<6 , 就很差使了,它们的查找方式就相似于"全表扫描",由于他们的高度是不可控的(以下图)。B+Tree的高度是可控的,mysql一般是3到5层。注意:B+Tree只在最末端叶子节点存数据,叶子节点是以链表的形势互相指向的。

MyISAM:支持全文索引;不支持事务;它是表级锁;会保存表的具体行数.
InnoDB:5.6之后才有全文索引;支持事务;它是行级锁;不会保存表的具体行数.
汇集索引中,叶子节点的data直接包含数据;非汇集索引中,叶子节点存储数据地址的指针。
MyISAM非汇集索引,InnoDB汇集索引。

11八、怎么验证mysql索引知足需求?
用explain检查下扫描行数及索引的使用状况

11九、数据库的事务隔离?
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

③ Read committed (读已提交):可避免脏读的发生。

④ Read uncommitted (读未提交):最低级别,任何状况都没法保证。

120、mysql经常使用的引擎及区别?
InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。若是须要对事务的完整性要求比较高(好比银行),要求实现并发控制(好比售票),那选择InnoDB有很大的优点。若是须要频繁的更新、删除操做的数据库,也能够选择InnoDB,由于支持事务的提交(commit)和回滚(rollback)。

MyISAM:插入数据快,空间和内存使用比较低。若是表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。若是应用的完整性、并发性要求比较低,也能够使用。

MEMORY:全部的数据都在内存中,数据的处理速度快,可是安全性不高。若是须要很快的读写速度,对数据的安全性要求较低,能够选择MEMOEY。它对表的大小有要求,不能创建太大的表。因此,这类数据库只使用在相对较小的数据库表。

12一、mysql行锁和表锁?
表级锁: 开销小,加锁快;不会出现死锁(由于MyISAM会一次性得到SQL所需的所有锁);锁定粒度大,发生锁冲突的几率最高,并发度最低;
行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高

12二、mysql乐观锁和悲观锁?
悲观锁的特色是先获取锁,再进行业务操做,即“悲观”的认为获取锁是很是有可能失败的,所以要先确保获取锁成功再进行业务操做。一般来说在数据库上的悲观锁须要数据库自己提供支持,即经过经常使用的select … for update操做来实现悲观锁。
乐观锁的特色先进行业务操做,不到万不得已不去拿锁。乐观锁在数据库上的实现彻底是逻辑的,不须要数据库提供特殊的支持。通常的作法是在须要锁的数据上增长一个版本号,或者时间戳。

乐观锁在不发生取锁失败的状况下开销比悲观锁小,可是一旦发生失败回滚开销则比较大,所以适合用在取锁失败几率比较小的场景,能够提高系统并发性能
乐观锁还适用于一些比较特殊的场景,例如在业务操做过程当中没法和数据库保持链接等悲观锁没法适用的地方

12三、mysql问题排查的方法?
查看连接数
show PROCESSLIST;
经过mysql的端口定位是哪一个线程占用
netstat -ntp |grep 46888
经过线程号排查是哪一个应用
ps -ef | grep pid

分析sql是否属于慢查询经过是数据库的关键在EXPLAIN进行分析sql语句的性能(一、是否使用索引,二、是否查询的字段内容过大,三、查询过多的级联对表的影响);
查看mysqld进程的cpu消耗占比
确认mysql进程的cpu消耗是%user, 仍是sys%高
确认是不是物理内存不够用了
确认是否有swap产生

12四、mysql性能优化?
索引优化;查询字段优化;查询条件优化;表结构的设计优化;
将关联查询拆分红多个查询

12五、redis是什么有哪些使用场景?
Redis是一个key-value存储系统。读写性能优异、持久化、数据类型丰富、单线程、数据自动过时、发布订阅、分布式。
场景:作缓存、分布式锁、应对海量数据和高并发、排行榜

12六、redis和memcached的区别?
一、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其余东西,例如图片、视频等等;

二、Redis不只仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;

三、虚拟内存–Redis当物理内存用完时,能够将一些好久没用到的value 交换到磁盘;

四、过时策略–memcache在set时就指定,例如set key1 0 0 8,即永不过时。Redis能够经过例如expire 设定,例如expire name 10;

五、分布式–设定memcache集群,利用magent作一主多从;redis能够作一主多从。均可以一主一从;

六、存储数据安全–memcache挂掉后,数据没了;redis能够按期保存到磁盘(持久化);

七、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后能够经过aof恢复;

八、Redis支持数据的备份,即master-slave模式的数据备份;

12七、redis为何是单线程?
纯内存操做;采用单线程,避免了没必要要的上下文切换和竞争条件;采用了非阻塞I/O多路复用机制;数据结构简单,对数据操做也简单;使用底层模型不一样,它们之间底层实现方式以及与客户端之间通讯的应用协议不同,Redis直接本身构建了VM 机制 。

12八、什么是缓存穿透、缓存雪崩、缓存击穿?怎么解决?
缓存穿透,是指查询一个数据库必定不存在的数据。
解决方法是采用缓存空值的方式。
缓存雪崩,是指在某一个时间段,缓存集中过时失效。
解决方案:通常是采起不一样分类商品,缓存不一样周期;或者加分布式锁,再查询一次数据库。
缓存击穿,是指一个key很是热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案:设置缓存为不过时

12九、redis支持的数据类型?
字符串string:是一个由字节组成的序列,他在Redis中是二进制安全的,这便意味着该类型能够接受任何格式的数据
列表list:容许用户从序列的两端推入或者弹出元素,列表由多个字符串值组成的有序可重复的序列,是链表结构,因此向列表两端添加元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。
散列hash:具备String key和String value的map容器,能够将多个key-value存储到一个key中。每个Hash能够存储4294967295个键值对。
集合set:无序不可重复的,和列表同样,在执行插入和删除和判断是否存在某元素时,效率是很高的。集合最大的优点在于能够进行交集并集差集操做。Set可包含的最大元素数量是4294967295。
应用场景:1.利用交集求共同好友。2.利用惟一性,能够统计访问网站的全部独立IP。3.好友推荐的时候根据tag求交集,大于某个threshold(临界值的)就能够推荐。
有序集合sorted set:set很像,差异在于有序集合中每个成员都会有一个分数(score)与之关联,Redis正是经过分数来为集合中的成员进行从小到大的排序。
应用场景:能够用于一个大型在线游戏的积分排行榜,每当玩家的分数发生变化时,能够执行zadd更新玩家分数(score),此后在经过zrange获取几分top ten的用户信息。

130、Jedis和redisson的区别?
Jedis 和 Redisson 都是Java中对Redis操做的封装。Jedis 只是简单的封装了 Redis 的API库,能够看做是Redis客户端,它的方法和Redis 的命令很相似。Redisson 不只封装了 redis ,还封装了对更多数据结构的支持,以及锁等功能,相比于Jedis 更加大。但Jedis相比于Redisson 更原生一些,更灵活。

13一、怎么保证缓存和数据库数据的一致性?
给缓存设置过时时间,是保证最终一致性的解决方案;
更新数据库后要及时更新缓存、缓存失败时增长重试机制
若是你的项目对缓存的要求是强一致性的,那么请不要使用缓存。

13二、redis持久化几种方式?
Redis的全部数据都是保存在内存中,而后不按期的经过异步方式保存到磁盘上(这称为“半持久化模式”);也能够把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。
redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另一种是AOF(append only file)持久化(原理是将Reids的操做日志以追加的方式写入文件)。

RDB持久化配置
Redis会将数据集的快照dump到dump.rdb文件中。此外,咱们也能够经过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件以后,咱们搜索save,能够看到下面的配置信息:

save 900 1 #在900秒(15分钟)以后,若是至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)以后,若是至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)以后,若是至少有10000个key发生变化,则dump内存快照。

AOF持久化配置
在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不一样步。高效可是数据不会被持久化。

13三、redis怎么实现分布式锁?
使用redis的SETNX实现分布式锁
SETNX是将 key 的值设为 value,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不作任何动做。
返回1,说明该进程得到锁,SETNX将键 lock.id 的值设置为锁的超时时间,当前时间 +加上锁的有效时间。
返回0,说明其余进程已经得到了锁,进程不能进入临界区。进程能够在一个循环中不断地尝试 SETNX 操做,以得到锁。

  1. setnx(lockkey, 当前时间+过时超时时间) ,若是返回1,则获取锁成功;若是返回0则没有获取到锁,转向2。
    2. get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,若是小于当前系统时间,则认为这个锁已经超时,能够容许别的请求从新获取,转向3。
  2. 计算newExpireTime=当前时间+过时超时时间,而后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。
  3. 判断currentExpireTime与oldExpireTime 是否相等,若是相等,说明当前getset设置成功,获取到了锁。若是不相等,说明这个锁又被别的请求获取走了,那么当前请求能够直接返回失败,或者继续重试。
  4. 在获取到锁以后,当前线程能够开始本身的业务处理,当处理完毕后,比较本身的处理时间和对于锁设置的超时时间,若是小于锁设置的超时时间,则直接执行delete释放锁;若是大于锁设置的超时时间,则不须要再锁进行处理。

13四、redis如何内存优化?
一.redisObject对象
二.缩减键值对象
三.共享对象池
四.字符串优化
五.编码优化
六.控制key的数量

Redis存储的全部值对象在内部定义为redisObject结构体,内部结构以下图所示:
在这里插入图片描述
Redis存储的数据都使用redisObject来封装,包括string,hash,list,set,zset在内的全部数据类型。
1.type字段:
表示当前对象使用的数据类型,Redis主要支持5种数据类型:string,hash,list,set,zset。能够使用type {key}命令查看对象所属类型,type命令返回的是值对象类型,键都是string类型。
2.encoding字段:
表示Redis内部编码类型,encoding在Redis内部使用,表明当前对象内部采用哪一种数据结构实现。理解Redis内部编码方式对于优化内存很是重要 ,同一个对象采用不一样的编码实现内存占用存在明显差别,具体细节见以后编码优化部分。
3.lru字段:
记录对象最后一次被访问的时间,当配置了 maxmemory和maxmemory-policy=volatile-lru | allkeys-lru 时, 用于辅助LRU算法删除键数据。能够使用object idletime {key}命令在不更新lru字段状况下查看当前键的空闲时间。
开发提示:能够使用scan + object idletime 命令批量查询哪些键长时间未被访问,找出长时间不访问的键进行清理下降内存占用。
4.refcount字段:
记录当前对象被引用的次数,用于经过引用次数回收内存,当refcount=0时,能够安全回收当前对象空间。使用object refcount {key}获取当前对象引用。当对象为整数且范围在[0-9999]时,Redis能够使用共享对象的方式来节省内存。具体细节见以后共享对象池部分。
5. *ptr字段:
与对象的数据内容相关,若是是整数直接存储数据,不然表示指向数据的指针。Redis在3.0以后对值对象是字符串且长度<=39字节的数据,内部编码为embstr类型,字符串sds和redisObject一块儿分配,从而只要一次内存操做。
开发提示:高并发写入场景中,在条件容许的状况下建议字符串长度控制在39字节之内,减小建立redisObject内存分配次数从而提升性能。

下降Redis内存使用最直接的方式就是缩减键(key)和值(value)的长度。
当使用Redis存储大量数据时,一般会存在大量键,过多的键一样会消耗大量内存。
对于存储相同的数据内容利用Redis的数据结构下降外层键的数量,也能够节省大量内存。以下图所示,经过在客户端预估键规模,把大量键分组映射到多个hash结构中下降键的数量。

Redis全部数据都采用key-value数据类型,每次建立键值对时,至少建立两个类型对象:key对象和value对象。内存消耗能够简单的理解为sizeof(keys)+sizeof(values)。键对象都是字符串,在使用Redis时很容易忽略键对内存消耗的影响,应当避免使用过长的键。

13五、redis淘汰策略有哪些?
noeviction:达到内存限额后返回错误,客户尝试能够致使更多内存使用的命令(大部分写命令,但DEL和一些例外)
allkeys-lru:为了给新增长的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC)。
volatile-lru:为了给新增长的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC),但只限于过时设置键。
allkeys-random: 为了给新增长的数据腾出空间,驱逐任意键
volatile-random: 为了给新增长的数据腾出空间,驱逐任意键,但只限于有过时设置的驱逐键。
volatile-ttl: 为了给新增长的数据腾出空间,驱逐键只有秘钥过时设置,而且首先尝试缩短存活时间的驱逐键

咱们能够设置maxmemory ,当数据达到限定大小后,会选择配置的策略淘汰数据maxmemory-policy

13六、redis常见性能问题和解决方案?
1.Master最好不要作任何持久化工做,包括内存快照和AOF日志文件,特别是不要启用内存快照作持久化。

2.若是数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。

3.为了主从复制的速度和链接的稳定性,Slave和Master最好在同一个局域网内。

4.尽可能避免在压力较大的主库上增长从库

5.为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,若是Master挂了,能够立马启用Slave1作Master,其余不变。

13七、JVM的组成及做用?
虚拟机栈(一般称为Java栈)、本地方法栈(储存JNI)、程序计数器、方法区、堆、直接内存

虚拟机栈:每个方法在执行的同时都会建立一个栈帧用于存储局部变量表、操做数栈、动态连接、方法出口等信息。每个方法从调用直至执行完成的过程,对应着一个栈帧在虚拟机栈种入栈到出栈的过程。
本地方法栈:原理基本同虚拟机栈相同,区别在于虚拟机栈是为虚拟机执行java方法服务,而本地方法栈是为虚拟机执行Native方法服务
程序计数器:一块较小的内存空间,是当前线程所执行的字节码的行号指示器。

方法区:各线程共享的区域,方法区存储一杯虚拟机加载的类信息、常量、静态变量、即便编译器遍之后的代码等数据。
堆:堆中有句柄池和类的实例对象。堆是全部线程共享的一块内存区域,在虚拟机启动时建立。
直接内存:本机直接内存分配不受到Java堆大小的限制,可是,既然是内存,确定会受到本机总内存大小以及处理器寻址空间的限制。

13八、JVM 堆和栈的区别?
栈内存:程序在栈内存中运行;栈中存的是基本数据类型和堆中对象的引用;栈是运行时的单元;栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;一个线程一个独立的线程栈。
堆内存:程序运行所需的大部分数据保存在栈内存中;堆中存的是对象;堆是存储的单元,堆只是一块共享的内存;堆解决的是数据存储的问题,即数据怎么放,放在哪儿;全部线程共享堆内存。

13九、双亲委派模型?
Java虚拟机先从最核心的API开始查找,防止不可信的类扮演被信任的类。
启动类加载器 Bootstrap ClassLoader:加载<JAVA_HOME>\lib目录下核心库
扩展类加载器 Extension ClassLoader:加载<JAVA_HOME>\lib\ext目录下扩展包
应用程序类加载器 Application ClassLoader: 加载用户路径(classpath)上指定的类库
1.当Application ClassLoader 收到一个类加载请求时,他首先不会本身去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。
2.当Extension ClassLoader收到一个类加载请求时,他首先也不会本身去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。
3.若是Bootstrap ClassLoader加载失败(在<JAVA_HOME>\lib中未找到所需类),就会让Extension ClassLoader尝试加载。
4.若是Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。
5.若是Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。
6.若是均加载失败,就会抛出ClassNotFoundException异常。

13九、类加载的执行过程?
类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。
其中类加载过程包括加载、验证、准备、解析和初始化五个阶段。
类加载器的任务就是根据一个类的全限定名来读取此类的二进制字节流到JVM中,而后转换为一个与目标类对应的java.lang.Class对象实例。
连接阶段要作的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中,经由验证、准备和解析三个阶段。
将一个类中全部被static关键字标识的代码统一执行一遍,若是执行的是静态变量,那么就会使用用户指定的值覆盖以前在准备阶段设置的初始值;若是执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的全部操做。

140、怎么判断对象是否能够被回收?
算法的基本思想是经过一系列的成为“GC Roots”的对象做为起点,从这些起点开始向下搜索,搜索的路径就成为引用链(Reference Chain),当一个对象到GC Roots没有任何的引用链相连的话,也就是该对象不可达,则证实该对象是不可用的。
在Java中GC Roots对象包括如下几个:
虚拟机栈(栈帧的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈JNI引用的对象

在可达性的算法中,至少要被标记两次,才会真正的宣告一个对象死亡:若是对象那在进行可达性分析发现没有GC Roots相连的引用链,那么将会被第一次标记而且进行一次筛选,筛选的条件是此对象那个是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种状况都视为“没有必要执行”。

14一、java中有哪些引用类型?
强引用、软引用、弱引用、虚引用

引用队列能够与软引用、弱引用以及虚引用一块儿配合使用,当垃圾回收器准备回收一个对象时,若是发现它还有引用,那么就会在回收对象以前,把这个引用加入到与之关联的引用队列中去。程序能够经过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就能够在对象被回收以前采起一些必要的措施。
与软引用、弱引用不一样,虚引用必须和引用队列一块儿使用。

14二、jvm有哪些垃圾回收算法?
对象是否“已死”算法——可达性分析算法
标记-清除算法
复制算法(Java堆中新生代的垃圾回收算法)
标记-压缩算法(或称为标记-整理算法,Java堆中老年代的垃圾回收算法)

14三、jvm有哪些垃圾回收器?
在这里插入图片描述
Serial收集器、ParNew收集器、Parallel Scavenge(并行回收)收集器、Serial Old 收集器、Parallel Old 收集器、CMS收集器、G1收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤为重视服务器的响应速度,但愿系统停顿时间最短,以给用户带来较好的体验。CMS收集器就很是符合这类应用的需求。
CMS收集器是基于“标记-清除”算法实现的。它的运做过程相对前面几种收集器来讲更复杂一些,整个过程分为4个步骤:
(1)初始标记
(2)并发标记
(3)从新标记
(4)并发清除
其中,初始标记、从新标记这两个步骤仍然须要“Stop The World”.
CMS收集器主要优势:并发收集,低停顿。

CMS三个明显的缺点:

(1)CMS收集器对CPU资源很是敏感。CPU个数少于4个时,CMS对于用户程序的影响就可能变得很大,为了应付这种状况,虚拟机提供了一种称为“增量式并发收集器”的CMS收集器变种。所作的事情和单CPU年代PC机操做系统使用抢占式来模拟多任务机制的思想

(2)CMS收集器没法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而致使另外一次Full GC的产生。在JDK1.5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,若是在应用中蓝年代增加不是太快,能够适当调高参数-XX:CMSInitiatingOccupancyFraction的值来提升触发百分比,以便下降内存回收次数从而获取更好的性能,在JDK1.6中,CMS收集器的启动阀值已经提高至92%。

(3)CMS是基于“标记-清除”算法实现的收集器,手机结束时会有大量空间碎片产生。空间碎片过多,可能会出现老年代还有很大空间剩余,可是没法找到足够大的连续空间来分配当前对象,不得不提早出发FullGC。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认就是开启的),用于在CMS收集器顶不住要进行FullGC时开启内存碎片合并整理过程,内存整理的过程是没法并发的,空间碎片问题没有了,但停顿时间变长了。虚拟机设计者还提供了另一个参数-XX:CMSFullGCsBeforeCompaction,这个参数是用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,标识每次进入Full GC时都进行碎片整理)

对象的分配策略。它分为3个阶段:
TLAB(Thread Local Allocation Buffer)线程本地分配缓冲区
Eden区中分配
Humongous区分配

G1收集器:
G1在运行过程当中主要包含以下4种操做方式:
YGC(不一样于CMS)
并发阶段
混合模式
full GC (通常是G1出现问题时发生)

14四、jvm分代垃圾回收器怎么工做?
为了提升垃圾回收的效率,咱们把生命周期不一样的对象分代处理。
垃圾回收机制根据对象的生命周期不一样划分为了三个代:年轻代、年老代、持久代
因为对象进行了分代处理,所以垃圾回收区域、时间也不同。GC有两种类型:Scavenge GC和Full GC。

1.        建立新对象,大多数放在Eden区
2.        Eden满了(或达到必定比例),触发Minor GC,   把有用的复制到Survivor1, 同时清空Eden区。
3.        Eden区再次满了,出发Minor GC, 把Eden和Survivor1中有用的,复制到Survivor2, 同时清空Eden,Survivor1。
4.        Eden区第三次满了,出发Minor GC, 把Eden和Survivor2中有用的,复制到Survivor1, 同时清空Eden,Survivor2。 造成循环,Survoivor1和Survivor中来回清空、复制,过程当中有一个Survivor处于空的状态用于下次复制的。
5.        重复屡次(默认15),没有被Survivor清理的对象,复制到Old(Tenuerd)区.
6.        当Old达到必定比例,触发Major GC,清理老年代。        
7.        当Old满了,触发Full GC。注意,Full GC清理代价大,系统资源消耗高。

14五、jvm调优工具?
jvm监控分析工具通常分为两类,一种是jdk自带的工具,一种是第三方的分析工具。
咱们最常使用的只有两款:jconsole.exe和jvisualvm.exe;第三方的分析工具备不少,各自的侧重点不一样,比较有表明性的:MAT(Memory Analyzer Tool)、GChisto等。

14六、经常使用的jvm调优参数?
1、Trace跟踪参数(跟踪GC、类、变量的内存变化状况)
-verbose:gc 或 -XX:+printGC 或 -XX:+printGCDetails、-XX:+TraceClassLoading
2、堆的分频参数
-Xmx10M 指定最大堆,JVM最多可以使用的堆空间 (超过该空间引起OOM)
-Xms5M 指定最小堆,JVM至少会有的堆空间(尽量维持在最小堆)
-Xmn 11M(new) 设置新生代大小
官方推荐:新生代占堆空间3/8;幸存代占新生代1/10
3、栈的分配参数
-Xss 每一个线程都有独立的栈空间(几百k,比较小)
须要大量线程时,须要尽量减少栈空间
栈空间过小-----StackOverFlow栈溢出

14七、为何CMS两次标记时要 stop the world?
第一次标记root对象,必需要stw(初始标记也会扫描新生代);当GC线程标记好了一个对象的时候,此时咱们程序的线程又将该对象从新加入了“关系网”中,当执行二次标记的时候,该对象也没有重写finalize()方法,所以回收的时候就会回收这个不应回收的对象。
  虚拟机的解决方法就是在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停全部当前运行的线程(Stop The World 因此叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和清除。
  这些特定的指令位置主要在:
一、循环的末尾
二、方法临返回前 / 调用方法的call指令后
三、可能抛异常的位置

14八、liunx下统计文件行数?
wc -l file.txt

14九、liunx查询文件尾部200包含order的信息?
tail -n 200 filename | grep order

150、Dubbo是什么?
Dubbo是阿里巴巴开源的基于 Java 的高性能 RPC 分布式服务框架。

15一、为何要用Dubbo?
是阿里开源项目,国内不少互联网公司都在用,已经通过不少线上考验。内部使用了 Netty、Zookeeper,保证了高性能高可用性。

15二、Dubbo须要 Web 容器吗?
不须要,若是硬要用 Web 容器,只会增长复杂性,也浪费资源

15三、Dubbo里面有哪几种节点角色?
provider 服务提供 consumer 服务消费 registry 服务注册中心
monitor 监控中心 container 服务运行容器

15四、服务注册与发现的流程图
在这里插入图片描述

15五、Dubbo默认使用什么注册中心,还有别的选择吗?
推荐使用 Zookeeper 做为注册中心,还有 Redis、Multicast、Simple 注册中心,但不推荐。

15六、Dubbo 核心的配置有哪些?之间的关系
在这里插入图片描述
在这里插入图片描述

15七、在 Provider 上能够配置的 Consumer 端的属性有哪些?
1)timeout:方法调用超时
2)retries:失败重试次数,默认重试 2 次
3)loadbalance:负载均衡算法,默认随机
4)actives 消费者端,最大并发调用限制

15八、Dubbo启动时若是依赖的服务不可用会怎样?
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,默认 check=“true”,能够经过 check=“false” 关闭检查。

15九、Dubbo推荐使用什么序列化框架,你知道的还有哪些?
推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化

160、Dubbo默认使用的是什么通讯框架,还有别的选择吗?
Dubbo 默认使用 Netty 框架,也是推荐的选择,另外内容还集成有Mina、Grizzly。

16一、Dubbo有哪几种集群容错方案,默认是哪一种?
在这里插入图片描述

16二、Dubbo有哪几种负载均衡策略,默认是哪一种?
在这里插入图片描述

16三、当一个服务接口有多种实现时怎么作?
当一个接口有多种实现时,能够用 group 属性来分组,服务提供方和消费方都指定同一个 group 便可

16四、Dubbo支持服务多协议吗?
Dubbo 容许配置多协议,在不一样服务上支持不一样协议或者同一服务上同时支持多种协议。

16五、注册了多个同同样的服务,若是测试指定的某一个服务呢?
能够配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。

16六、服务上线怎么兼容旧版本?
能够用版本号(version)过渡,多个不一样版本的服务注册到注册中心,版本号不一样的服务相互间不引用。这个和服务分组的概念有一点相似。

16七、Dubbo能够对结果进行缓存吗?
能够,Dubbo 提供了声明式缓存,用于加速热门数据的访问速度,以减小用户加缓存的工做量

16八、Dubbo服务之间的调用是阻塞的吗?
默认是同步等待结果阻塞的,支持异步调用。
Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不须要启动多线程便可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。
在这里插入图片描述

16九、Dubbo支持分布式事务吗?
目前暂时不支持

170、Dubbo的管理控制台能作什么?
管理控制台主要包含:路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等管理功能。

17一、说说 Dubbo 服务暴露的过程
Dubbo 会在 Spring 实例化完 bean 以后,在刷新容器最后一步发布 ContextRefreshEvent 事件的时候,通知实现了 ApplicationListener 的 ServiceBean 类进行回调 onApplicationEvent 事件方法,Dubbo 会在这个方法中调用 ServiceBean 父类 ServiceConfig 的 export 方法,而该方法真正实现了服务的(异步或者非异步)发布。

17二、如何设计一个秒杀系统?
什么是秒杀:在必定的时间内几秒或者几分钟,对必定数量的库存进行出卖。
1,在秒杀以前,好比上午十点开始秒杀,不少用户可能在九点五十左右就开始访问本身心仪的秒杀商品,这样就会出如今秒杀以前用不少的并发量,因此在秒杀以前的半个小时以前,是否能够将参加秒杀活动商品的一些信息缓存起来,这样就能够减少由于高并发访问,给数据库带来的压力。
2,有的用户为了抢到商品可能利用第三插件,去频繁的访问接口,这样给接口会带来很大的压力,为了不这种刻意的刷单问题,能够在后台对同一个用户的访问频率作限制,能够预测接口的实际访问频率,而后对不一样的接口,同一个用户作频率限制,如某个抢购入口,能够设置一个用户一分钟不能访问超过60次,10秒内不能超过20次等不一样时段不一样访问频率策略,这个能够经过redis等缓存框架作到,列入以某个接口+用户惟一性标准为key,能够选择value为string类型,若是缓存更多数据,value能够选择hash类型,value的值是int类型,这样用户每次访问接口,能够先判断该值有没有达到预设的访问频率限制的值,若是达到了,就告诉用户,你的访问太过频繁,请多长时间后再试,或者要求用户输入验证码(图片验证码或者短信验证码)。若是没有达到预设值,就给int值技术加一,在第一次访问的时候,即查询的前exist判断,若是不存在,插入第一条数据,而且设置过气时间,这个时间就是访问频率的时间限制例如一分钟只能访问60次,那么这里的过时时间就是60秒,预设值就是60次。这样就能够从必定程度上避免刷单问题。
3,一个用户可能当初注册了不少的帐号,平时不用,专门用来参加秒杀活动,这样其实也会形成系统压力。解决方式和上述差很少,只是对ip作限制,可是怎样作可能伤到真实的用户,由于有的场合如网吧,里面人购物实际上是同一个ip出口,这个时候,其实也能够对用户的等级作限制,只有多高的等级才能够参加秒杀活动。

秒杀场景的特色:
同一时间同时进行抢购,网站瞬时访问流量激增。
访问请求数量远远大于库存数量,可是只有少部分用户可以秒杀成功。
秒杀业务流程比较简单,通常就是下订单减库存

秒杀设计思路:
前端:页面静态化,禁止重复提交。

后端:可拓展,缓存,限流,削峰,异步处理
可拓展:服务的可扩展,能够水平添加机器将用户请求分担到不一样的机器上去。数据库可扩展,支持分库分表,对于用户的请求,映射到不一样的数据库,减小单台数据库的压力。
内存缓存:参加秒杀系统的商品是事先可知的,能够将参加秒杀的商品信息事先缓存到redis等缓存系统中,这样能够大大的提升系统的吞吐量,减小关系型数据库的读写压力。
限流: 一单秒杀开始,实际秒杀成功的用户只是库存的数量,在库存没有以后,将前端的秒杀入口关闭。
削峰:数据库削峰。对于秒杀系统瞬时会有大量用户涌入,因此在抢购一开始会有很高的瞬间峰值。对于关系型数据库而言,这个是致命的,是压垮系统很重要的缘由,因此如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的经常使用的方法有利用缓存和消息中间件等技术。
异步处理:秒杀系统是一个高并发系统,采用异步处理模式能够极大地提升系统并发量,其实异步处理就是削峰的一种实现方式。

利用redis+mysql实现简单的秒杀系统
Redis是一个分布式key-value缓存系统,value支持多种数据结构,这里value能够选择两种类型,String(或者hash):主要用于记录商品的库存,对商品减库存。Set集合(这里不要用list集合,list集合是可重复的,set是不可重复的,能够保证一个用户只卖一次,若是一个用户能够买屡次那么能够使用list集合):用于存储用户的id获取其余惟一肯定一个用户的值。

在秒杀开始的前:能够使用批处理,将参加秒杀的产品信息缓存到redis中。这里将产品的业务惟一字段做为key,库存做为value。这里的key要和前端缓存的key一致。
在秒杀开始时::用户大量提交。根据用户提交的产品信息,获取到redis中须要的key值,查询缓存(为了保证缓存有效,若是第一次没有查询到,能够到数据库查询,而后在缓存一下,不过通常不会出现),获得库存量,判断当前库存是否大于零,若是大于零,判断当前的set集合中是否用该用户ID,若是没有,减库存而且将用户的ID放入集合中,并对库存减一,若是库存为0,提示用户,商品已售完等文案信息,若是集合中已经存在该用户id,则不作任何处理,直接处理下一个请求。直到最后库存售完,上面的过程能够利用redis事务和watch功能完成对数据一致性的控制即超卖问题。
库存售完后:程序开始启动一个有个后台线程,能够阻塞等待商品库存售完的通知,在上面一步,库存一旦售完,后台进程获取set集合中的用户信息,异步处理须要操做的购买等后续操做。

这只是一个简单的秒杀系统,实际的秒杀系统,还要考虑到不少的真实场景须要不少完善的地方,但愿你们一块儿讨论如何设计一个秒杀系统。

17三、内存溢出可能缘由和解决?
缘由多是A,数据加载过多,如1次从数据库中取出过多数据 B,集合类中有对对象的引用,用完后没有清空或者集合对象未置空致使引用存在等,是的JVM没法回收 C,死循环,过多重复对象 D,第三方软件的bug E,启动参数内存值设定的太小。

17四、幂等的处理方式?
1、查询与删除操做是自然幂等
2、惟一索引,防止新增脏数据
3、token机制,防止页面重复提交
4、悲观锁 for update
5、乐观锁(经过版本号/时间戳实现, 经过条件限制where avai_amount-#subAmount# >= 0)
6、分布式锁
7、状态机幂等(若是状态机已经处于下一个状态,这时候来了一个上一个状态的变动,理论上是不可以变动的,这样的话,保证了有限状态机的幂等。)
8、select + insert(并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行)

17五、RabbitMQ消息堆积怎么处理?
增长消费者的处理能力(例如优化代码),或减小发布频率
单纯升级硬件不是办法,只能起到一时的做用
考虑使用队列最大长度限制,RabbitMQ 3.1支持
给消息设置年龄,超时就丢弃
默认状况下,rabbitmq消费者为单线程串行消费,设置并发消费两个关键属性concurrentConsumers和prefetchCount,concurrentConsumers设置的是对每一个listener在初始化的时候设置的并发消费者的个数,prefetchCount是每次一次性从broker里面取的待消费的消息的个数
创建新的queue,消费者同时订阅新旧queue
生产者端缓存数据,在mq被消费完后再发送到mq
打破发送循环条件,设置合适的qos值,当qos值被用光,而新的ack没有被mq接收时,就能够跳出发送循环,去接收新的消息;消费者主动block接收进程,消费者感觉到接收消息过快时主动block,利用block和unblock方法调节接收速率,当接收线程被block时,跳出发送循环。
新建一个topic,partition是原来的10倍;而后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费以后不作耗时的处理,直接均匀轮询写入临时创建好的10倍数量的queue;接着临时征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的数据;等快速消费完积压数据以后,得恢复原先部署架构,从新用原先的consumer机器来消费消息;

17六、负载均衡算法?
常见6种负载均衡算法:轮询,随机,源地址哈希,加权轮询,加权随机,最小链接数。
nginx5种负载均衡算法:轮询,weight,ip_hash,fair(响应时间),url_hash
dubbo负载均衡算法:随机,轮询,最少活跃调用数,一致性Hash

17七、ThreadPoolExecutor内部工做原理?
先查看当前运行状态,若是不是RUNNING 状态会拒绝执行任务,若是是RUNNING状态,就会查看当前运行的线程数量,若是小于核心线程数,会建立新的线程来执行这个任务,若是不小于核心线程,会将这个任务放到阻塞队列去等代执行,直到上一个任务执行完再来执行这个任务。若是失败会建立一个非核心线程来执行这个任务若是当前线程数大于最大线程数,会直接拒绝该任务。

17八、mysql数据库锁表怎么解决?
当前运行的全部事务
select * from information_schema.innodb_trx
当前出现的锁
select * from information_schema.innodb_locks
锁等待的对应关系
select * from information_schema.innodb_lock_waits
经过 select * from information_schema.innodb_trx 查询 trx_mysql_thread_id而后执行 kill 线程ID
KILL 8807;//后面的数字即时进程的ID

17九、Spring+MyBatis实现读写分离简述?
方案一:经过MyBatis配置文件建立读写分离两个DataSource,每一个SqlSessionFactoryBean对象的mapperLocations属性制定两个读写数据源的配置文件。将全部读的操做配置在读文件中,全部写的操做配置在写文件中。
方案二:经过Spring AOP在业务层实现读写分离,在DAO层调用前定义切面,利用Spring的AbstractRoutingDataSource解决多数据源的问题,实现动态选择数据源
方案三:经过Mybatis的Plugin在业务层实现数据库读写分离,在MyBatis建立Statement对象前经过拦截器选择真正的数据源,在拦截器中根据方法名称不一样(select、update、insert、delete)选择数据源。
方案四:经过spring的AbstractRoutingDataSource和mybatis Plugin拦截器实现很是友好的读写分离,原有代码不须要任何改变。推荐第四种方案

这里转载的实现,能够试试https://www.jianshu.com/p/2222257f96d3

180、redis主从复制?
能够经过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另外一个服务器,咱们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave)
假设如今有两个Redis服务器,地址分别为127.0.0.1:6379和127.0.0.1:12345,若是咱们向服务器127.0.0.1:12345发送如下命令:
127.0.0.1:12345> SLAVEOF 127.0.0.1 6379
那么服务器127.0.0.1:12345将成为127.0.0.1:6379的从服务器,而服务器127.0.0.1:6379则会成为127.0.0.1:12345的主服务器。

只有一个主 redis,能够有多个从 redis;
主从复制不会阻塞 master,在同步数据时,master 能够继续处理 client 请求;
一个 redis 能够便是主又是从。
主从配置:主 redis 配置无需特殊配置;从redis配置修改从 redis 服务器上的 redis.conf 文件,添加 slaveof 主 redisip 主 redis 端口(slaveof 192.168.0.1 6379)

复制过程说明:slave 服务启动,slave 会创建和 master 的链接,发送 sync 命令;master 启动一个后台进程将数据库快照保存到 RDB 文件中;master 就发送 RDB 文件给 slave;slave 将文件保存到磁盘上,而后加载到内存恢复;master 把缓存的命令转发给 slave。

18一、redis集群搭建?
redis集群采用P2P模式,是彻底去中心化的,不存在中心节点或者代理节点;
redis集群是没有统一的入口的,客户端(client)链接集群的时候链接集群中的任意节点(node)便可,集群内部的节点是相互通讯的(PING-PONG机制),每一个节点都是一个redis实例;
redis-cluster有这么一个投票容错机制:若是集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
若是集群中任意一个节点挂了,并且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;
由于集群内置了16384个slot(哈希槽),而且把全部的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当须要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,而后获得一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪一个节点中。因此一旦某个节点挂了,该节点对应的slot就没法使用,那么就会致使集群没法正常工做。
每一个Redis集群理论上最多能够有16384个节点

Redis集群至少须要3个节点,由于投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,因此2个节点没法构成集群。
要保证集群的高可用,须要每一个节点都有从节点,也就是备份节点,因此Redis集群至少须要6台服务器。

经过配置文件来启动3个不一样的Redis实例,因为Redis默认端口为6379,因此这里使用了6380、638一、6382来运行3个Redis实例。
配置文件中如下两种保存日志的方式(保存在文件中、保存到System Log中)请根据需求选择其中一种便可:

loglevel notice #日志的记录级别,notice是适合生产环境的
  logfile “D:/Redis/Logs/redis6380_log.txt” #指定log的保持路径,默认是建立在Redis安装目录下,若是有子目录须要手动建立,如此处的Logs目录
  syslog-enabled yes #是否使用系统日志   
  syslog-ident redis6380 #在系统日志的标识名

redis.6380.conf 内容以下:
port 6380
loglevel notice
logfile “D:/Redis/Logs/redis6380_log.txt”
appendonly yes
appendfilename “appendonly.6380.aof”
cluster-enabled yes
cluster-config-file nodes.6380.conf
cluster-node-timeout 15000
cluster-slave-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes

redis.6381.conf 内容以下:
port 6381
loglevel notice
logfile “D:/Redis/Logs/redis6381_log.txt”
appendonly yes
appendfilename “appendonly.6381.aof”
cluster-enabled yes
cluster-config-file nodes.6381.conf
cluster-node-timeout 15000
cluster-slave-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes

redis.6382.conf 内容以下:
port 6382
loglevel notice
logfile “D:/Redis/Logs/redis6382_log.txt”
appendonly yes
appendfilename “appendonly.6382.aof”
cluster-enabled yes
cluster-config-file nodes.6382.conf
cluster-node-timeout 15000
cluster-slave-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes

下载并安装ruby;下载ruby环境下Redis的驱动
下载Redis官方提供的建立Redis集群的ruby脚本文件redis-trib.rb
使用redis-trib.rb来建立Redis集群:
redis-trib.rb create --replicas 0 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382
检验是否真的建立成功,输入如下命令:redis-trib.rb check 127.0.0.1:6380

18二、斐波那契数列的实现?
public static int add(int num) {//递归
if (num == 1 || num == 2) return 1;
return add(num - 1) + add(num - 2);
}

public static int add3(int first, int second, int num) {//递归的优化版 (num要比实际数加一,从0开始
if (num < 1) {
return 0;
} else if (num == 2 || num == 1) {
return 1;
} else if (num == 3) {
return first + second;
} else {
return add3(second, first + second, num - 1);
}
}

public static int add2(int num) {//非递归
if (num == 1 || num == 2) return 1;
int first = 1;
int second = 1;
int temp = 0;
for (int i = 3; i <= num; i++) {
temp = first + second;
first = second;
second = temp;
}
return second;
}

18三、Redis相比memcached有哪些优点?
memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型;
redis的速度比memcached快不少;
redis能够持久化其数据,而Memecache把数据所有存在内存之中;
Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的IO复用模型

Redis的全称是Remote Dictionary Server;支持String、List、Set、Sorted Set、hashes

18四、分布式系统惟一ID生成方案
转载https://blog.csdn.net/yeyazhishang/article/details/81564520
uuid(UUID每每是使用字符串存储,查询的效率比较低,没有排序,没法保证趋势递增)
Redis生成ID:能够用Redis的原子操做 INCR和INCRBY来实现。
Twitter的snowflake算法:结果是一个long型的ID。其核心思想是:使用41bit做为毫秒数,10bit做为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit做为毫秒内的流水号(意味着每一个节点在每毫秒能够产生 4096 个 ID),最后还有一个符号位,永远是0。

private RedisTemplate mRedisTemp;

public long generate(String key) {
    RedisAtomicLong counter = new RedisAtomicLong(key,mRedisTemp.getConnectionFactory());
    return counter.incrementAndGet();
}

public long generate(String key,Date expireTime) {
    RedisAtomicLong counter = new RedisAtomicLong(key, mRedisTemp.getConnectionFactory());
    counter.expireAt(expireTime);
    return counter.incrementAndGet();
}

/**
 * 获取能按固定步长增加的有过时时间的ID
 * @param key
 * @param increment
 * @return
 */
public long generate(String key,int increment,Date expireTime) {
    RedisAtomicLong counter = new RedisAtomicLong(key, mRedisTemp.getConnectionFactory());
    counter.expireAt(expireTime);
    return counter.addAndGet(increment);
}

18五、Paxos算法
paxos算法是基于消息传递且具备高度容错特性的一致性算法。是目前公认的解决分布式一致性问题最有效的算法之一。
一致性算法: 确保这些被提议的值中有且只有一个被选中. (若是没有值被提出, 那么就没有值会被选中.) 若是一个值被选中, 那么每一个进程必需要能够感知到.

提议者(proposer): 进行提议的角色
批准者(acceptor): 经过提议的角色
学习者(learner): 感知(learn)被选中的提议

P1. 一个Acceptor必须批准它收到的第一个提案
P2. 若是一个值为v的提案被选中, 那么更高编号的被选中的提案的值必须也为v
P2a. 若是值为v的提案被选中, 那么后续任何acceptor能批准的更高版本的提案都必需要有值v.
P2b. 若是值为v的提案被选中, 那么后续任意的proposer所起草的更高编号的提案的值必须也是v.
P2c. 对于任意的N和V, 若是[N, V]被提出, 那么确定存在一个由半数以上(majority)的acceptor组织的集合S, 知足下面两个条件之一
(a) S中不存在任何批准过编号小于N的提案的Acceptor
(b) S中全部Acceptor批准的编号小于N的提案中编号最大的值为V

总结:知足p1&P2c咱们就可以确保一致性算法的安全性。
在这里插入图片描述

如何保证P2c成立
要维护P2c的成立, 一个proposer在起草提案[n, x]以前必需要先知道 (某个majority中) 各个acceptor目前经过的小于n最高的提案. 这很容易, 可是这个多是变化的, 如何预测未来就比较困难了. 和上面P2a到P2b的思路相似, 相较于直接预测未来, proposer经过向acceptor们索取承诺来解决这个问题. 换句话说, proposer请求acceptor们不要再经过任何低于n的提案了.
因而咱们有了下面的起草提案的算法:
proposer选择一个新的编号n, 并发送给 (某个majority中) 每一个acceptor, 要它作出以下回应:
(a) 承诺不会再经过任何比n小的提案
(b) 小于n的最大编号的提案(若有)
若是proposer受到了绝大多数acceptor的响应, 那么它就能够起草一个提案. 提案的编号是n, 值是根据 1 中的 (b) 里面响应的提案的值来的(若是没有提案, 或者提案值为空, 那么这个proposer能够用任意值)
上面提到的proposer向acceptor发起的请求咱们称之为prepare request.
当proposer经历了上面过程, 并起草了提案以后, 它就能够向 (某个majority中) acceptor们发送这个提案并等待它们审批. (注: 并不必定是上面prepare request发给的那个majority集合.) 这个请求被称为accept request.
如何保证P1成立

  1. acceptor能够在任意时刻响应prepare request;
  2. acceptor能够在不违背响应prepare request的前提下, 响应(经过)任何accept request
    因此对于acceptor来讲能够归纳为:
    P1a. 一个acceptor能够经过一个proposal [n, v], 当且仅当它没有响应过任何编号大于n的prepare request.
    很明显P1a => P1
    因此Paxos能够保证P2c & P1, 这样咱们就获得了一个一致性的算法!

在这里插入图片描述

18六、几种经典的hash算法

  1. Hash的主要原理就是把大范围映射到小范围;因此,你输入的实际值的个数必须和小范围至关或者比它更小。否则冲突就会不少。
  2. 因为Hash逼近单向函数;因此,你能够用它来对数据进行加密。
  3. 不一样的应用对Hash函数有着不一样的要求;好比,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。
    加法Hash:就是把输入元素一个一个的加起来构成最后的结果;
    位运算Hash:利用各类位运算(常见的是移位和异或)来充分的混合输入元素。
    乘法Hash:利用了乘法的不相关性(String的hashCode计算)
    除法Hash:由于除法太慢,这种方式几乎找不到真正的应用;
    查表Hash:查表Hash最有名的例子莫过于CRC系列算法
    混合Hash:混合Hash算法利用了以上各类方式。各类常见的Hash算法,好比MD五、Tiger都属于这个范围
    虽然说以上的hash能极大程度地避免冲突,可是冲突是在所不免的。因此不管用哪一种hash函数,都要加上处理冲突的方法。

18七、分布式事务的原理,如何使用分布式事务?
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不一样的分布式系统的不一样节点之上。简单的说,就是一次大的操做由不一样的小操做组成,这些小的操做分布在不一样的服务器上,且属于不一样的应用,分布式事务须要保证这些小操做要么所有成功,要么所有失败。本质上来讲,分布式事务就是为了保证不一样数据库的数据一致性。

XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想。
所谓的消息事务就是基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操做成功成功而且对外发消息成功,要么二者都失败。
在这里插入图片描述

分布式事务,本质上是对多个数据库的事务进行统一控制,按照控制力度能够分为:不控制、部分控制和彻底控制。不控制就是不引入分布式事务,部分控制就是各类变种的两阶段提交,包括上面提到的消息事务+最终一致性、TCC模式,而彻底控制就是彻底实现两阶段提交。部分控制的好处是并发量和性能很好,缺点是数据一致性减弱了,彻底控制则是牺牲了性能,保障了一致性,具体用哪一种方式,最终仍是取决于业务场景。做为技术人员,必定不能忘了技术是为业务服务的,不要为了技术而技术,针对不一样业务进行技术选型也是一种很重要的能力!

18八、linux怎么将一个目录下除了某个文件外的文件都删除
rm -rf !(file1|file2)

18九、查询端口是否被占用
netstat -anp |grep 5000
看监控状态为LISTEN表示已经被占用,最后一列显示5000端口被服务python占用

190、删除表数据怎么最快?
truncate (table) tb 删除表中的全部数据,不能与where一块儿使用
delete from tb (where) 删除表中的数据
truncate和delete的区别
一、事务:truncate是不能够rollback的,可是delete是能够rollback的;
缘由:truncate删除整表数据(ddl语句,隐式提交),delete是一行一行的删除,能够rollback
二、效果:truncate删除后将从新水平线和索引(id从零开始) ,delete不会删除索引
三、 truncate 不能触发任何Delete触发器。
四、delete 删除能够返回行数
效率上truncate比delete快,但truncate删除后不记录mysql日志,不能够恢复数据。
truncate至关于保留mysql表的结构,从新建立了这个表,全部的状态都至关于新表。

19一、集线器、路由器、交换器分别属于哪一层?
第一层: 物理层 网线,集线器
第二层:数据链路层 网卡,交换机
第三层:网络层 路由器

19二、编程建立一个500k的文件?
RandomAccessFile raf = null;
File filename = new File(“F:\psb.jpg”);
long length = 5;
try {
raf = new RandomAccessFile(filename, “rw”);
raf.setLength(length * 100000);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

19三、泛型和多态的含义?
泛型,即“参数化类型”,就是将类型由原来的具体的类型参数化。
多态是同一个行为具备多个不一样表现形式或形态的能力

19四、运行时异常和非运行时异常的区别及应用场景
运行时异常(RuntimeException)不须要编译器来检测。RuntimeException是全部能够在运行时抛出的异常的父类,须要手动捕捉异常。
受检查异常(checked exception)都是编译器在编译时进行校验的,经过throws语句或者try{}cathch{} 语句块来处理检测异常。编译器会分析哪些异常会在执行一个方法或者构造函数的时候抛出。

19五、说明几种保证线程安全的方法
synchronized或lock

19六、javaweb的分层方式及应用?
DAO层主要是作数据持久层的工做,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,而后在Spring的配置文件中定义此接口的实现类
Service层主要负责业务模块的逻辑应用设计,一样是首先设计接口,再设计其实现的类,接着再Spring的配置文件中配置其实现的关联。
Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程
View层:此层与控制层结合比较紧密,须要两者结合起来协同工做。View层主要负责前台jsp页面的表示。

mvc能够说是三层中的一个展示层框架,属于展示层。三层和mvc能够共存。 三层是基于业务逻辑来分的,而mvc是基于页面来分的。 MVC主要用于表现层,3层主要用于体系架构,3层通常是表现层、中间层、数据层,其中表现层又能够分红M、V、C,(Model View Controller)模型-视图-控制器 。

总的来讲,也不能一律而论的说MVC和三层架构之间一点关系都没有,由于它们两者使用范围不一样:三层能够应用于任何语言、任何技术的应用程序;而MVC只是为了解决B/S(Browser/Server)应用程序视图层各部分的耦合关系。它们互不冲突,能够同时存在,也可根据状况使用其中一种。

19七、如何避免java内存泄漏
内存泄漏就是存在一些被分配的对象,这些对象有下面两个特色,首先,这些对象是可达的,即在有向图中,存在通路能够与其相连;其次,这些对象是无用的,即程序之后不会再使用这些对象。
一、尽早释放无用对象的引用 ,好的办法是使用临时变量的时候,让引用变量在推出活动域后自动设置为null;
二、避免集中建立对象,尤为是大对象,若是能够的话尽可能使用流操做
三、不要在常常调用的方法中建立对象,尤为忌讳在循环中建立对象
四、尽可能运用对象池技术以提升系统性能
五、避免使用finalize方法

19八、如何利用Chrome工具进行前端js调试
一、在Chrome浏览器中运行你的web工程,打开“开发者模式”(右键选择检查或者按“F12“”)。打开你的sources选项,找到你所要调试的js文件。
二、在你想要调试的地方单击插入断点

19九、Web开发常见安全问题及解决?
1.SQL注入
其本质是对于输入检查不充分,致使SQL语句将用户提交的非法数据看成语句的一部分来执行。解决方法使用SQL预处理方法prepareStatement
2.CSRF攻击(跨站点请求伪造)
伪造请求,冒充用户在站内的正常操做。
经过session token来实现保护。当客户端请求页面时,服务器会生成一个随机数Token,而且将Token放置到session当中,而后将Token发给客户端(通常经过构造hidden表单)。下次客户端提交请求时,Token会随着表单一块儿提交到服务器端。接收到请求后,服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则能够证实请求有效,不是伪造的。
三、XST处理
XST(跨站追踪)攻击,关闭Web 服务器的TRACE方法。
四、XSS攻击
XSS攻击是在HTML里代码执行了用户输入,解决方法是对数据进行转义处理。

200、Linux查看CPU和内存使用状况
top命令是Linux下经常使用的性能分析工具,可以实时显示系统中各个进程的资源占用情况,相似于Windows的任务管理器
top -u oracle
PID:进程的ID
  USER:进程全部者
  PR:进程的优先级别,越小越优先被执行
  NInice:值
  VIRT:进程占用的虚拟内存
  RES:进程占用的物理内存
  SHR:进程使用的共享内存
  S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
  %CPU:进程占用CPU的使用率
  %MEM:进程使用的物理内存和总内存的百分比
  TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。
  COMMAND:进程启动命令名称

20一、数据库结构设计考虑因素?
数据类型、索引、三大范式、冗余字段、应对大数据量

20二、HDFS读写文件流程和读文件流程
写的详细流程:
① 客户端向HDFS写数据,首先跟namenode通讯以确承认以写文件(namenode检查目标文件是否存在,父目录是否存在),确承认以上传,返回给客户端client
② client会先对文件进行切分,默认一个block块是128M,好比说,文件有300M,就会被切分红3块,两个128M,一个44M。而后client会向namenode请求上传第一个block
③ namenode返回datanode的服务器
④ client会请求一台datanode来上传数据(本质上是一个RPC 调用,创建pipeline).第一个datanode接收到请求会继续调用第二个datanode,而后第二个datanode会调用第三个datanode(多少个datanode跟配置的副本数有关),将整个pipeline创建完成,逐级返回给客户端
⑤ client开始往第一台datanode上上传第一个block(先从磁盘读取数据放到本地内存缓存中),以packet为单位(一个packet为64KB).固然在写入的时候datanode会进行数据校验,它并非经过一个packet进行一次校验,而是以chunk为单位进行校验(512byte),第一台datanode收到一个packet就会传给第二台datanode,第二台再传给第三台。。。每一台每传一个packet会放入一个应答队列等待应答
⑥ 当一个block传输完成以后,client会再次请求namenode上传第二个block的datanode服务器。循环
在这里插入图片描述

读的详细流程:
① client向namenode请求下载文件,即向namenode通讯查询元数据(block所在的datanode节点),找到文件块所在的datanode服务器
② client挑选一台datanode(就近原则,而后随机)服务器,请求创建socket流
③ datanode开始发送数据(从磁盘里面读取数据输入流,以packet为单位来作校验)
④ 客户端以packet为单位接收,先在本地缓存,而后写入目标文件,后面的block块就至关因而append到前面的block块最后合成最终须要的文件。
在这里插入图片描述
20三、Spark的RDD五大特性
RDD,弹性分布式数据集,是spark的底层数据结构。
1 、A list of partitions
  --RDD是由多个partition构成的。
二、A function for computing each split
  --RDD的每一个分区上都有一个函数去做用
三、 A list of dependencies on other RDDs
  --RDD有依赖性,一般状况下一个RDD是来源于另外一个RDD,这个叫作lineage。RDD会记录下这些依赖,方便容错。
四、Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
  --可选项,若是RDD里面存的数据是key-value形式,则能够传递一个自定义的Partitioner进行从新分区,例如这里自定义的Partitioner是基于key进行分区,那则会将不一样RDD里面的相同key的数据放到同一个partition里面。
五、Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
最优的位置去计算,也就是数据的本地性。

20四、linux下删除大量文件?
在linux中删除大量文件时,直接用rm会出现:-bash: /bin/rm: 参数列表过长的错误
find . -name “name*” | xargs rm -rf
假如文件名或文件夹名中包含空格:find . -name “name*” -print0 | xargs -0 rm -rf

20五、将一个正整数分解为质因数

int n = 60;
		for (int i = 2; i <= n / 2; i++) {
			if (n % i == 0) {
				System.out.print(i + "*");
				n = n / i;
				i = 1;
			}
		}
		System.out.print(n);

20六、容器和虚拟机的区别及应用场景? 一个运用于应用程序,另外一个是为操做系统设计的。 容器最大的优势之一是能够预留比虚拟机少的资源。请记住,容器本质上是单个应用程序,而虚拟机须要更多资源来运行整个操做系统。 容器对于快速的跨发行版部署是更可行的,而虚拟机对于像运行LAMP堆栈这样的单一应用程序使用状况是更好的。 与容器相比,虚拟机提供了更多的安全性。 容器能够共享系统资源而虚拟机不行。 容器用更少的硬件更高效地运行。在另外一方面,虚拟机仍然是服务器和云空间的主要内容。