面试总结详细版(侵删)

面试的公司主要分两类:

                                          一类是项目介绍+基础知识。

                                          一类是主要问分布式,zk,redis,mq,还有多线程高并发实际使用中遇到的问题。

技术建议:

1 spring boot ,dubbo,zk,rabbitmq ,redis,spring cloud。

2线程高并发,设计模式,算法,了解大数据或者python最好。

2mysql oracle数据库优化,存储过程,触发器,重点事务和sql优化,

3 js必备,了解bootstrap。目前有的公司采用前后端分离,故前端vue.js,angularjs(有兴趣可以研究vuejs,angularjs因为一些 优化问题,貌似公司都转vuejs了),需要知道怎么给他们提供接口之类的,具体自己查下。

4 最好熟练使用git,maven,idea,码云 csdn,githup ,

5 最好是码云上有自己的项目,csdn上有自己写的博客,最好有自己的项目,可以买一个阿里云的主机服务器。

一    集合list set map.()(集合的区别,集合的常用方法的等,最好结合中队列一起看)

 <1> list分类,set分类,map分类

List接口通常表示一个列表(数组、队列、链表、栈等),其中的元素可以重复,常用实现类为ArrayList和LinkedList,另外还有不常用的Vector。同时LinkedList还是实现了Queue接口,因此也可以作为队列使用。

Set接口通常表示一个集合,其中的元素不允许重复(通过hashcode和equals方法保证),常用实现类有HashSet和TreeSet,HashSet是通过Map中的HashMap实现的,而TreeSet是通过Map中的TreeMap实现的。另外,TreeSet还实现了SortedSet接口,因此是有序的集合。

Queue接口通常表示一个队列,是一种先进先出的数据结构,元素在队列末尾添加,在队列头部删除。Queue接口扩展自Collection,并提供插入、提取、检验等操作。

Map是一个映射接口,其中的每个元素都是一个key-value键值对。

<2>ArrayList和LinkedList的区别?

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

 

2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。

 

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

 

4.查找操作indexOf,lastIndexOf,contains等,两者差不多。

 

5.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。

<3>Vector和ArrayList的区别?

相同之处:

1.它们都是List

2.它们都实现了RandomAccess和Cloneable接口,都支持快速随机访问,能克隆自己。

3.它们都是通过数组实现的,本质上都是动态数组。

4.它们的默认数组容量是10。

5.它们都支持Iterator和listIterator遍历。

不同之处:

1.线程安全性不一样。ArrayList是非线程安全的,而Vector是线程安全的; ArrayList适用于单线程,Vector适用于多线程。

2.对序列化支持不同。ArrayList支持序列化,而Vector不支持。

<4>HashMap和HashSet的区别。

1.HashMap实现了Map接口,HashSet实现了Set接口。

2.HashMap储存键值对,HashSet仅仅存储对象(且无重复对象)。

3.HashMap使用put()方法将元素放入map中,HashSet使用add()方法将元素放入set中。

4.HashMap中使用键对象来计算hashcode值,HashSet使用成员对象来计算hashcode值。对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false。

5.HashMap比较快,因为是使用唯一的键来获取对象;HashSet比HashMap来说更慢。

<5>HashMap与HashTable的区别?

1.HashTable的方法是同步的,HashMap未经同步,所以HashMap效率更高。

2.HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。

3.HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样,HashMap没有contains方法。

4.HashTable使用Enumeration,HashMap使用Iterator。

5.HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

6.哈希值的使用不同,HashTable直接使用对象的hashCode。

二   堆和栈,虚拟机,gc回收
     1 堆栈方法区分别放的什么。  

栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。

堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。

内存分 堆  栈(虚拟机栈,本地方法栈)  方法区 程序计数器

       1.栈内存存储的是局部变量而堆内存存储的是实体;

            2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

            3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

2实例化一个对象,在堆栈方法区的过程。

3  怎么优化虚拟机

除了设置jdk参数,应该还有别的方面,没有实际优化过,不是太清楚了。

4  怎么实现对jdk的监控(倒是没有人问jdk版本,但是我建议请熟悉jdk8开发)

我说的是jdk中有一个专门的配置,具体自己查吧。

6内存溢出和内存泄漏

java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。

java.lang.OutOfMemoryError: PermGen space ------>java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

7 虚拟机调优 gc调优,百度吧 ,反正我没有接触过233333

8 gc有一个青年代,中年代,老年代(jdk8已经删除)

GC在什么时候对什么做了什么?

        要回答这个问题,先了解下GC的发展史、jvm运行时数据区的划分、jvm内存分配策略、jvm垃圾收集算法等知识。

        先说下jvm运行时数据的划分,粗暴的分可以分为堆区(Heap)和栈区(Stack),但jvm的分法实际上比这复杂得多,大概分为下面几块:

        1、程序计数器(Program Conuter Register)

        程序计数器是一块较小的内存空间,它是当前线程执行字节码的行号指示器,字节码解释工作器就是通过改变这个计数器的值来选取下一条需要执行的指令。它是线程私有的内存,也是唯一一个没有OOM异常的区域。

        2、Java虚拟机栈区(Java Virtual Machine Stacks)

        也就是通常所说的栈区,它描述的是Java方法执行的内存模型,每个方法被执行的时候都创建一个栈帧(Stack Frame),用于存储局部变量表、操作数栈、动态链接、方法出口等。每个方法被调用到完成,相当于一个栈帧在虚拟机栈中从入栈到出栈的过程。此区域也是线程私有的内存,可能抛出两种异常:如果线程请求的栈深度大于虚拟机允许的深度将抛出StackOverflowError;如果虚拟机栈可以动态的扩展,扩展到无法动态的申请到足够的内存时会抛出OOM异常。

        3、本地方法栈(Native Method Stacks)

        本地方法栈与虚拟机栈发挥的作用非常相似,区别就是虚拟机栈为虚拟机执行Java方法,本地方法栈则是为虚拟机使用到的Native方法服务。

        4、堆区(Heap)

        所有对象实例和数组都在堆区上分配,堆区是GC主要管理的区域。堆区还可以细分为新生代、老年代,新生代还分为一个Eden区和两个Survivor区。此块内存为所有线程共享区域,当堆中没有足够内存完成实例分配时会抛出OOM异常。

        5、方法区(Method Area)

       方法区也是所有线程共享区,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。GC在这个区域很少出现,这个区域内存回收的目标主要是对常量池的回收和类型的卸载,回收的内存比较少,所以也有称这个区域为永久代(Permanent Generation)的。当方法区无法满足内存分配时抛出OOM异常。

        6、运行时常量池(Runtime Constant Pool)

        运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

 1、什么时候回收?

         上面说到GC经常发生的区域是堆区,堆区还可以细分为新生代、老年代,新生代还分为一个Eden区和两个Survivor区。

        1.1 对象优先在Eden中分配,当Eden中没有足够空间时,虚拟机将发生一次Minor GC,因为Java大多数对象都是朝生夕灭,所以Minor GC非常频繁,而且速度也很快;

        1.2 Full GC,发生在老年代的GC,当老年代没有足够的空间时即发生Full GC,发生Full GC一般都会有一次Minor GC。大对象直接进入老年代,如很长的字符串数组,虚拟机提供一个-XX:PretenureSizeThreadhold参数,令大于这个参数值的对象直接在老年代中分配,避免在Eden区和两个Survivor区发生大量的内存拷贝;

        1.3 发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则进行一次Full GC,如果小于,则查看HandlePromotionFailure设置是否允许担保失败,如果允许,那只会进行一次Minor GC,如果不允许,则改为进行一次Full GC。

 2、哪些内存需要回收

        jvm对不可用的对象进行回收,哪些对象是可用的,哪些是不可用的?Java并不是采用引用计数算法来判定对象是否可用,而是采用根搜索算法(GC Root Tracing),当一个对象到GC Roots没有任何引用相连接,用图论的来说就是从GC Roots到这个对象不可达,则证明此对象是不可用的,说明此对象可以被GC。对于这些不可达对象,也不是一下子就被GC,而是至少要经历两次标记过程:如果对象在进行根搜索算法后发现没有与GC Roots相连接的引用链,那它将会第一次标记并且进行一次筛选,筛选条件是此对象有没有必要执行finalize()方法,当对象没有覆盖finalize()方法或者finalize()方法已经被虚拟机调用执行过一次,这两种情况都被视为没有必要执行finalize()方法,对于没有必要执行finalize()方法的将会被GC,对于有必要有必要执行的,对象在finalize()方法中可能会自救,也就是重新与引用链上的任何一个对象建立关联即可。

 3、如何回收

        选择不同的垃圾收集器,所使用的收集算法也不同。

在新生代中,每次垃圾收集都发现有大批对象死去,只有少量存活,则使用复制算法,新生代内存被分为一个较大的Eden区和两个较小的Survivor区,每次只使用Eden区和一个Survivor区,当回收时将Eden区和Survivor还存活着的对象一次性的拷贝到另一个Survivor区上,最后清理掉Eden区和刚才使用过的Survivor区,Eden和Survivor的默认比例是8:1,可以使用-XX:SurvivorRatio来设置该比例。

       而老年代中对象存活率高,没有额外的空间对它进行分配担保,必须使用“标记-清理”或“标记-整理”算法。

三 线程,主要是多线程安全,线程同步,高并发

 1 线程和进程还有程序的区别

2 线程的状态 

新建(NEW),表示线程被创建出来还没真正启动的状态,可以认为它是个 Java 内部状态。

就绪(RUNNABLE),表示该线程已经在 JVM 中执行,当然由于执行需要计算资源,它可能是正在运行,也可能还在等待系统分配给它 CPU 片段,在就绪队列里面排队。

在其他一些分析中,会额外区分一种状态 RUNNING,但是从 Java API 的角度,并不能表示出来。

阻塞(BLOCKED),这个状态和我们前面两讲介绍的同步非常相关,阻塞表示线程在等待 Monitor lock。比如,线程试图通过 synchronized 去获取某个锁,但是其他线程已经独占了,那么当前线程就会处于阻塞状态。

等待(WAITING),表示正在等待其他线程采取某些操作。一个常见的场景是类似生产者消费者模式,发现任务条件尚未满足,就让当前消费者线程等待(wait),另外的生产者线程去准备任务数据,然后通过类似 notify 等动作,通知消费线程可以继续工作了。Thread.join() 也会令线程进入等待状态。

计时等待(TIMED_WAIT),其进入条件和等待状态类似,但是调用的是存在超时条件的方法,比如 wait 或 join 等方法的指定超时版本,如下面示例:

public final native void wait(long timeout) throws InterruptedException;

终止(TERMINATED),不管是意外退出还是正常执行结束,线程已经完成使命,终止运行,也有人把这个状态叫作死亡。

3 阻塞的情况分三种:

(1)、等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,

(2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。

(3)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

4 线程池

  • //创建一个单线程的线程池

  • ExecutorService es=Executors.newSingleThreadExecutor();

  • //创建一个固定大小的线程池

  • ExecutorService es1=Executors.newFixedThreadPool(2);

  • //创建一个可缓存的线程池

  • ExecutorService es2=Executors.newCachedThreadPool();

  • //创建一个大小无限的线程池

  • ExecutorService es3=Executors.newScheduledThreadPool(2);

6线程安全

1. 多实例、或者是多副本(ThreadLocal):对应着思路2,ThreadLocal可以为每个线程的维护一个私有的本地变量,可参考java线程副本–ThreadLocal; 

2. 使用锁机制 synchronize、lock方式:为资源加锁,可参考我写的一系列文章; 

3. 使用 java.util.concurrent 下面的类库:有JDK提供的线程安全的集合类(面试一道题:是否用过这个包下的类库)

7 线程同步

1.同步方法   2.同步代码块   3.使用特殊域变量(volatile)实现线程同步  4.使用重入锁实现线程同步 5.使用局部变量实现线程同步  6.使用阻塞队列实现线程同步  7.使用原子变量实现线程同步

8 什么是ThreadLocal变量?

ThreadLocal是Java里一种特殊的变量。每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量,竞争条件被 彻底消除了。它是为创建代价高昂的对象获取线程安全的好方法,比如你可以用ThreadLocal让SimpleDateFormat变成线程安全的,因 为那个类创建代价高昂且每次调用都需要创建不同的实例所以不值得在局部范围使用它,如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通 过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。线程局部变量的另一个不错的例子是 ThreadLocalRandom类,它在多线程环境中减少了创建代价高昂的Random对象的个数。

9如何彻底停止一个线程

10 线程中一个集合问题 :ConcurrentHashMap 具体自己百度

11有三个线程T1,T2,T3,怎么确保它们按顺序执行?

在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。

12如果你提交任务时,线程池队列已满。会时发会生什么?

这个问题问得很狡猾,许多程序员会认为该任务会阻塞直到线程池队列有空位。事实上如果一个任务不能被调度执行那么ThreadPoolExecutor’s submit()方法将会抛出一个RejectedExecutionException异常。

13 写出3条你遵循的多线程最佳实践

这种问题我最喜欢了,我相信你在写并发代码来提升性能的时候也会遵循某些最佳实践。以下三条最佳实践我觉得大多数Java程序员都应该遵循:

  •  

    给你的线程起个有意义的名字。

    这样可以方便找bug或追踪。OrderProcessor, QuoteProcessor or TradeProcessor 这种名字比 Thread-1. Thread-2 and Thread-3 好多了,给线程起一个和它要完成的任务相关的名字,所有的主要框架甚至JDK都遵循这个最佳实践。

  •  

    避免锁定和缩小同步的范围

    锁花费的代价高昂且上下文切换更耗费时间空间,试试最低限度的使用同步和锁,缩小临界区。因此相对于同步方法我更喜欢同步块,它给我拥有对锁的绝对控制权。

  •  

    多用同步类少用wait 和 notify

    首先,CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger 这些同步类简化了编码操作,而用wait和notify很难实现对复杂控制流的控制。其次,这些类是由最好的企业编写和维护在后续的JDK中它们还会不断 优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。

  •  

    多用并发集合少用同步集合

    这是另外一个容易遵循且受益巨大的最佳实践,并发集合比同步集合的可扩展性更好,所以在并发编程时使用并发集合效果更好。如果下一次你需要用到map,你应该首先想到用ConcurrentHashMap。

14  Java多线程中调用wait() 和 sleep()方法有什么不同?

Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而 sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。

四  dubbo,redis zookeeper

1dubbo启动方式

1、使用Servlet容器运行(Tomcat、Jetty等) -不可用 缺点:增加复杂性(端口、管理) 浪费资源(内存) 需要占用多个端口和内存,这种方式是不可取的

 2、自己建立Main方法类运行(Srping容器) 本地调试用,本地调试的方式是很重要的,在本地测试中,必须掌握。 缺点:Dobbo本省提供的高级特性没用上,自己的启动类可能有缺陷 案例查看:Dubbo之入门案例-yellowcong

 3、使用Dubbo框架提供的Main方法类来运行(Spring 容器) 建议使用 优点:框架本身提供(com.alibaba.dubbo.container.Main),可是现优雅关机(ShutdownHook)

2  问题集合

1、默认使用的是什么通信框架,还有别的选择吗?         默认也推荐使用netty框架,还有mina。   2、服务调用是阻塞的吗?         默认是阻塞的,可以异步调用,没有返回值的可以这么做。   3、一般使用什么注册中心?还有别的选择吗?        推荐使用zookeeper注册中心,还有redis等不推荐。   4、默认使用什么序列化框架,你知道的还有哪些?     默认使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。   5、服务提供者能实现失效踢出是什么原理?         服务失效踢出基于zookeeper的临时节点原理   6、服务上线怎么不影响旧版本?           采用多版本开发,不影响旧版本。     7、如何解决服务调用链过长的问题?     可以结合zipkin实现分布式服务追踪。   8、说说核心的配置有哪些?       核心配置有     dubbo:service/ dubbo:reference/ dubbo:protocol/ dubbo:registry/ dubbo:application/ dubbo:provider/ dubbo:consumer/ dubbo:method/    9、dubbo推荐用什么协议?           默认使用dubbo协议。还有 rmi,http,hessian,webservice 10、同一个服务多个注册的情况下可以直连某一个服务吗?         可以直连,修改配置即可,也可以通过telnet直接某个服务。 11、画一画服务注册与发现的流程图      12、集群容错怎么做?      13、在使用过程中都遇到了些什么问题?          14、dubbo和dubbox之间的区别?       dubbox是当当网基于dubbo上做了一些扩展,如加了服务可restful调用,更新了开源组件等。   15、你还了解别的分布式框架吗?     spring cloud 

1 zk宕机 

启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。但是在注册中心全部挂掉后增加新的提供者,则不能被消费者发现: 

监控中心宕掉不影响使用,只是丢失部分采样数据

数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务

注册中心对等集群,任意一台宕掉后,将自动切换到另一台

注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯

服务提供者无状态,任意一台宕掉后,不影响使用

服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

---------------------

2 dubbo 直连

<dubbo:reference id="whoami"

                 interface="com.alibaba.fastjson.xxxx"

                 url="dubbo://121.11.222.254:2181"

                 version="1.0.0" timeout="10000"

                 check="false"

/>

3 dubbo 即使消费者也是提供者

3 会问一些dubbo开发中实际遇到的问题,比如zk宕机怎么办,zk集群配置,zk在服务器上的配置,zk选举制度等等

4 mq使用中的一些问题,我也用的不是太多,过。。。。。。

五 redis

1 redis五种数据类型

2 redis集群配置

3Redis是单进程单线程的

redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销

4 redis的并发竞争问题如何解决?

 Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是 由于客户端连接混乱造成。对此有2种解决方法:

  1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。

   2.服务器角度,利用setnx实现锁。

   注:对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。

5 redis持久化的几种方式

一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另外一种是AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件)

第三种、虚拟内存方式(我一般只是说前两种)

  当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.

  当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.

二者优缺点

RDB存在哪些优势呢?

1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。

2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。

3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。

4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

RDB又存在哪些劣势呢?

1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

AOF的优势有哪些呢?

1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。

2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。

3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

AOF的劣势有哪些呢?

1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。

4、常用配置

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          #从不同步。高效但是数据不会被持久化。

6 redis 最适合的场景  

Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?

如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:

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

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

  3 、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

(1)、会话缓存(Session Cache)

  最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,

  他们还会这样吗?

  幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。

(2)、全页缓存(FPC)

  除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。

  再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。

  此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

(3)、队列

  Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。

  如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。

(4),排行榜/计数器

  Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们

  称之为“user_scores”,我们只需要像下面一样执行即可:

  当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:

  ZRANGE user_scores 0 10 WITHSCORES 

  Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。

(5)、发布/订阅

  最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不,这是真的,你可以去核

https://blog.csdn.net/u010682330/article/details/81043419?utm_source=copy杂乱问题

8 redis 宕机,还有redis使用中的一些问题

六  oracle和mysql   熟练使用sql sql sql (三遍)

1 mysql和oracle 语法,数据类型等的区别

2 sql优化  (以下仅是一少部分),

1 减少对全局查询2 like使用3 or改成union all4 合适的索引5 主键6 减少not in 和in的使用,使用exists  7 使用between 而不是in

3 约束 索引 主键

约束 1 非空  2 主键 3 唯一 4 外键约束  5 默认值

索引1 主键2 普通 3 全文 4 check 5 等

唯一约束和主键区别,联合索引的最左原则

4 什么是存储过程?用什么来调用?

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

5  事务特性,隔离级别,事务传播机制 事务回滚         重点

.事务四大特性 

原子性,要么执行,要么不执行 

隔离性,所有操作全部执行完以前,其它会话不能看到过程 

一致性,事务前后,数据总额一致 

持久性,一旦事务提交,对数据的改变就是永久的

2.数据库隔离级别,每个级别会引发什么问题,mysql默认是哪个级别

脏读:事务B读取事务A还没有提交的数据 

不可重复读:两次事务读的数据不一致 

幻读:事务A修改了数据,事务B也修改了数据,这时在事务A看来,明明修改了数据,昨不一样, 

隔离级别 读数据一致性 脏读 不可重复读 幻读 

未提交读 最低级别 是 是 是 

已提交读 语句级 否 是 是 

事务级 事务级 否 否 是 

串行化 最高级别 否 否 否

6  数据库的主从复制,数据库的分库分表 数据库的读写分离

7  left join right join

8数据库优化参考  https://blog.csdn.net/baidu_37107022/article/details/77043959?utm_source=copy

9  ORACLE和MYSQL的简单区别

1,Oracle没有offet,limit,在mysql中我们用它们来控制显示的行数,最多的是分页了。oracle要分页的话,要换成rownum。

2,oracle建表时,没有auto_increment,所有要想让表的一个字段自增,要自己添加序列,插入时,把序列的值,插入进去。

3,oracle有一个dual表,当select后没有表时,加上的。不加会报错的。select 1 这个在mysql不会报错的,oracle下会。select 1 from dual这样的话,oracle就不会报错了。

4,对空值的判断,name != ""这样在mysql下不会报错的,但是oracle下会报错。在oracle下的要换成name is not null

5,oracle下对单引号,双引号要求的很死,一般不准用双引号,用了会报

ERROR at line 1:

ORA-00904: "t": invalid identifier

MySQL要求就没有那么严格了,单引号,双引号都可以。

6,oracle有to_number,to_date这样的转换函数,oracle表字段是number型的,如果你$_POST得到的参数是123456,入库的时候,你还要to_number来强制转换一下,不然后会被当成字符串来处理。而mysql却不会。

7,group_concat这个函数,oracle是没有的,如果要想用自已写方法。

8,mysql的用户权限管理,是放到mysql自动带的一个数据库mysql里面的,而oracle是用户权限是根着表空间走的。

9,group by,在下oracle下用group by的话,group by后面的字段必须在select后面出现,不然会报错的,而mysql却不会。

10,mysql存储引擎有好多,常用的mysiam,innodb等,而创建oracle表的时候,不要这样的,好像只有一个存储引擎。

11,oracle字段无法选择位置,alter table add column before|after,这样会报错的,即使你用sql*plus这样的工具,也没法改字段的位置。

12,oracle的表字段类型也没有mysql多,并且有很多不同,例如:mysql的int,float合成了oracle的number型等。

13,oracle查询时from 表名后面 不能加上as 不然会报错的,select t.username from test as t而在mysql下是可以的。

14,oracle中是没有substring这个函数的,mysql有的。

10  sql注入 

1  (简单又有效的方法)PreparedStatement

2.使用正则表达式过滤传入的参数

3.字符串过滤

11 千万千万要会写sql

12 sql优化的硬件级

七   js jsp

1 js 直接看 菜鸟教程

2 jsp直接看菜鸟教程

3 ajax ,表单提交倒是没人问,但是spring mvc的前后端交互,怎么获取到前端的数据,有人问

4 前端我也不是太会

八 设计模式

1 会手写单例模式(懒汉和饿汉)

2工厂模式

3 最好会其他的设计模式

九算法

问的特别少,建议看一下

十 数据结构

问的也特别少,建议看下,提工资必备

十一   逻辑题和智力题,类似 有一个没刻度只知道是70升和一个50升的桶,如何只用这两个桶得到60升水?

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值