JVM
1、JVM运行时包含哪些区域?
    线程公共的:堆(存放一些对象)、方法区(存放一些类信息、静态变量、常量)
    线程私有的:程序计数器(单线程下计数比如循环、异常处理等跳转、多线程下线程之间的跳转)、java虚拟机栈(java方法)、本地方法栈(非java方法)
2、栈:每个线程创建,分配的一块内存区域。每执行一个方法,生成一个栈帧(存放方法的局部变量等信息),进栈,出栈
3、stackoverflow:指定单个线程虚拟机栈大小,当压栈的方法过多,单个线程请求的栈深度大于允许深度,抛出异常,比如无条件的递归函数
4、outofmenory:整个虚拟机栈内存耗尽
5、java堆内存分代策略:新生代、老年代、永久代(1.8取消老年代)
    新生成的对象进入新生代,多次回收失败的进入老年代(大对象直接进入)、静态变量和类信息进入永久代。
    1.8取消老年代,使用元空间代替,老年代和元空间都是方法区的实现,老年代使用的是堆内存,元空间属于本地空间,只存储类的元信息(运行时常量),静态和常量(字符串常量)都还存储在堆内存。
    相当于永久代的数据被分到了堆和元空间中。
6、jvm创建对象步骤:
        1、检查对象加载,没有加载先加载
        2、分配内存,内存规整的话使用指针碰撞,不规整使用空闲列表,是否规则取决于GC算法,标记清除是不规则的,标记整理和复制算法是规则的
        3、初始化零值,比如long、int之类
        4、初始化对象头,比如类信息、哈希码、gc的年龄代信息
        5、执行构造函数初始化对象
7、jvm存在强引用(不会被回收)、软引用(只有在内存不足的时候被回收)、弱引用(gc扫描到就回收)、虚引用(随时被回收)
8、GC三个算法:
    1、标记、清理算法
    2、复制算法,新生代gc使用,分为eden和survivor1 survivor2,大小比例8:1:1  eden将活着的复制到1区,清理eden,,然后new新对象进入eden,这时eden和1区都有存活对象,下次清理将eden和1区复制到2区
    3、标记、整理算法,标记,然后将标记的一移动到一边,清理边界之外的内存
    为什么要分1、2区,为了解决碎片化问题,内存占用是不连续的,会产生碎片化
9、什么时候需要立即初始化类:
        1、new 类的静态信息或者方法被引用
        2、反射
        3、main方法执行的的类
        4、初始化类的时候发现父类没被初始化
10、双亲委派
    类的初始化机制,当类加载器收到加载指令,先委派到父加载器,当父加载不了再自己加载
11、类加载的步骤
    加载 验证 准备 解析 初始化 使用 卸载
12、class文件常量和运行时常量
    class文件常量在类加载完成后进入运行时常量,运行时常量相对于class具备动态性,动态新增常量进来
13、GC优化三个指标
    1、GC的吞吐量
    2、GC延迟,引起的提顿时间
    3、GC占用的内存
    
    
并发编程
1、守护线程 thread.setdaemon true   gc垃圾回收器也是一个守护线程  一般用于监控或者资源回收
2、比较synchronized和volatile(还要再整理一下)
    1、volatile不具备原子性,synchronized具备原子性
    2、都具备可见性,synchronized的锁和volatile修饰的变量都是其他线程可见的
    3、synchronized和volatile都具有有序性
3、synchronized是可重入锁,就是一把锁可以进入多个synchronized
4、synchronized分为同步方法和同步代码块
    1、同步方法,反编译后发现class文件多了acc_synchronized,代表是同步方法,获取锁计数器+1,释放-1,如果获取失败就阻塞住,知道被释放
    2、同步代码块,同步块是由monitorenter指令进入,然后monitorexit释放锁,也会计数,2个monitorexit,第二个是用来处理异常的,处理结束释放锁
5、synchronized底层实现,Synchronized用的锁(也就是objectmonitor)就是存在Java对象头里的、对象头主要结构是由Mark Word(标记字段)、Class Pointer(类型指针)组成,其中Mark Word存储对象的hashCode、锁信息或分代年龄或GC标志等信息,Class Metadata Address是类型指针指向对象的类元数据,JVM通过该指针确定该对象是哪个类的实例。
6、sync的优化
    1、jdk1.6之后优化,新增偏向锁、轻量级锁,当只有一个线程的时候由无锁进入偏向锁,当不在同一时间点出现其他线程申请锁,变成轻量级锁,当同一时间多个线程申请锁,变成重量级锁
    2、自旋锁和适应性自旋锁,线程的阻塞和唤醒需要cpu状态切换,负担大,自旋锁就是原地循环等待,一定次数之后,线程挂起,适应性的根据前几次是否成功决定这次的次数,成功增加次数,失败减少次数甚至取消自旋锁
    3、锁消除,检测到不会出现数据共享的问题
    4、锁粗化,就是将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁,比如for循环,里面的锁挪到外面
7、CAS无锁算法
    compare and swap
    预期值A ,内存值B,将来要变成的值C,set之前比较A和B,一样,将变量设置成C,如果不一样,会循环比较直到一样
    缺点:1、出现ABA问题(在set之前,其他线程将A变成了B之后又变成了A,错认为没有变化),解决办法时内存的值添加版本号
          2、循环开销大
          3、无法保证多个变量的原子性,1.5之后可以通过对象来保证,变量存放在对象中
8、sync和lock区别
    1、 Lock是一个接口,属于JDK层面的实现;而synchronized属于Java语言的特性,其实现有JVM来控制(代码执行完毕,出现异常,wait时JVM会主动释放锁)。
    2、 synchronized在发生异常时,会自动释放掉锁,故不会发生死锁现(此时的死锁一般是代码逻辑引起的);而Lock必须在finally中主动unlock锁,否则就会出现死锁。
    3、 Lock能够响应中断,让等待状态的线程停止等待;而synchronized不行。
    4、 通过Lock可以知道线程是否成功获得了锁,而synchronized不行。
    5、 Lock提高了多线程下对读操作的效率
9、executor接口定义execute方法,接受runnable对象
   executorservice定义submit方法,接受Runnable和Callable对象,通过future来获取返回值(future没有获取结果期间会阻塞,可以设置阻塞时间)
   Executor并不是一个线程池,而只是一个执行线程的工具,而真正的线程池是ExecutorService。
10、四种线程池
    newCacbedThreadPool:没有核心线程,最大线程数很大,定时清理空闲线程(超时机制),适用于任务时间短数量大的场景
    newFixedThreadPool:有指定的线程数的线程池,只有核心的线程,里面有固定的线程数量,不会被回收,有等待队列LinkedBlockingQueue,很大很大的队列
    newScheduledThreadPool:与核心线程也有非核心线程,可以延迟执行,也可以当作定时器执行
    newSingleThreadExecutor:单一线程,没有并发功能,用于线程重用的场景,不重用的时候可以直接new thread
11、线程池参数
    corepollsize:核心池大小,线程小于该值会一直新建线程,大于的时候会放入阻塞队列
    Maximumpoolsize:最大线程数
    keeplivetime:线程空闲时间,超过回收,该参数只在线程数大于 corePoolSize 时才有用
    workQuque:阻塞队列(BlockingQueue等)
    拒绝策略:阻塞队列也满了,会创建新线程,当线程数大于最大线程数,会拒绝任务
    threadfactory:线程工厂,给线程设置名字
    当接到任务,线程少于核心线程,创建线程,超过核心线程数时,进入阻塞队列,阻塞队列也满了就拒绝任务进入池子
12、线程池拒绝策略
    阻塞队列已满(说明不是LinkedBlockingQueue!因为LinkedBlockingQueue是近似无界的)
    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。注:默认策略!!!!!!
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
13、线程await后需要notify或者时notifyAll来唤醒
14、写时复制容器,copyonwriteArraylist 写入数据时将容器复制一份,在新的容器中进行数据的修改,结束后将原容器的引用指向新容器,覆盖旧数据,整个操作时上锁的,读写分离思想
    适合读多写少的场景,比如白名单黑名单的实现,操作尽量时批量操作
15、volatile只能保证变量的可见性,不能保证变量的原子性(对任意单个 volatile 变量的读/写具有原子性,但类似于++这种复合操作不具有原子性)。
    变量发生变化,会把当前线程缓存刷新到主内存,cpu锁住总线,同步到其他线程的内存,一般用于一写多读的场景
16、wait和sleep区别
    wait期间会释放锁,将线程放到wait list,sleep不会,wait用户线程切换,sleep用于任务暂停
17、为什么 wait, notify 和 notifyAll 这些方法不在 thread 类里面?
    java的锁时对象级别的,wait是释放锁,是锁级别的操作
    ObjectMonitor
18、每个Java对象都有一个对应的ObjectMonitor对象,它实现了同步机制,这就是为什么Object对象都能当成锁的原因。
19、ObjectMonitor是如何实现同步机制?
    ObjectMonitor有几个关键属性:
      (1)owner,指向持有ObjectMonitor的线程;
      (2)WaitSet,wait状态的线程队列,等待被唤醒,也就是调用了wait;
      (3)EntrySet,等待锁的线程队列,;
    同步流程:
        (1)有两个线程,线程A、线程B将竞争锁访问同步代码块,先进入ObjectMonitor的EntrySet中等待锁;
        (2)当CPU调度线程A获取到锁则进入同步代码,ObjectMonitor owner属性指向线程A,线程B继续在EntryList中等待;
        (3)线程A在同步代码中执行wait,则线程进入WaitSet并释放锁,ObjectMonitor owner属性清空;
        (4)CPU调度使线程B获取到锁进入同步代码块,ObjectMonitor owner属性指向线程B,任务执行完退出同步代码之前调用notifyAll,线程A被唤醒,从WaitSet转到EntryList中等待锁,线程B退出同步代码块,ObjectMonitor owner属性清空;
        (5)CPU调度使线程A获取同步锁,继续后续代码;
20、ThreadLocal
    ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。
    底层是包装了一个map,存取就是map的存取
21、join()
    main线程调用A线程的join(),main线程必须要等到A线程执行完成才能继续执行
    join底层是调用wait方法,join(long)会挂起long时间,再并行执行
    当一个线程执行完毕之后,jvm会做清理收尾工作,这个时候才会调用notifyAll,所以join结束不需要再notify
    join会释放锁,释放调用join的线程
22、为什么Thread类的sleep()和yield()方法是静态的?
    这2个方法是作用于整在执行的线程的,不能让等待线程执行,所以定义为静态方法
23、如何终止一个线程
    1、没有阻塞的情况下可以通过共享变量,通知线程终止,比如变量为true的时候
    2、阻塞状态下,可以使用thread的interrupt方法,整个方法不能终止整在运行的线程,但是可以终止阻塞的线程
24、合理配置线程池
    任务分类:1、cpu密集型,大量计算,和内存打交道,CPU一直全速运行,cpu核数决定效率
              2、io密集型,和硬盘、网络、文件、数据库打交道,即该任务需要大量的IO,即大量的阻塞。在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待。
                 所以在IO密集型任务中使用多线程可以大大的加速程序运行,即时在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。
              3、混合型
    CPU密集型任务应配置尽可能小的线程,如配置CPU个数+1的线程数,IO密集型任务应配置尽可能多的线程,因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量,如配置两倍CPU个数+1,
    而对于混合型的任务,如果可以拆分,拆分成IO密集型和CPU密集型分别处理,前提是两者运行的时间是差不多的,如果处理时间相差很大,则没必要拆分了。
    综合而言就是等待时间越长,cpu越空闲,就需要更多的线程,提高cpu的使用率
25、公平锁和非公平锁
    公平锁获取线程是按照获取锁的顺序,非公平锁则是在锁没被占用的i情况下,直接占用线程,不需要判断是否又等待队列
    使用场景类似线程池的任务,当线程处理时间远大于线程等待时间,则不需要非公平锁
26、HashMap 和 HashTable
    1、hashmap线程不安全,效率高
    2、hashmap允许一个值为null的key,允许多个值为null的value,table(concurrenthashmap也不允许)不允许
    3、hashmap初始化默认大小是16,table是11,扩容时,前者扩充2倍,后者2倍+1
    4、hashmap需要重新计算hash值,table直接使用对象的hash值
27、HashTable和concurrenthashmap在同步上的区别
    table使用synchronize加锁,cmap使用分段加锁
    1.7concurrenthashmap采用segment(默认大小16,并发也是16,采用可重入锁 ReentrantLock)+hashentry+链表实现,put,先hash得到segment的位置,再hash得到hashentry的位置,便利链表里的key,有重复的就覆盖,没有就放到链表结尾,
        插入的时候先要通过自旋方式获取segment锁,获取次数超过指定次数就挂起等待唤醒。size()就是多次计算相等就是正确答案,或者所有segment都上锁再计算
    1.8concurrenthashmap采用node数组和链表+红黑树的方式,采用cas+sync的方式上锁,put的时候hash,判断node数组是否需要初始化,计算出node位置,判断node是否为空,为空就采用cas当时添加首节点
        如果首节点为moved,则在扩容 ,其他情况就需要判断node下时链表还是红黑树,再插入
28、ConcurrentHashMap 的 get 方法是否要上锁?
    不需要,因为node中的value和指针next是用volatile修饰的,具有可见性
29、segment中的hashentry也是volatile修饰的,是为了扩容时,其他线程的可见性
30、为什么并发类集合不允许key和value为null?
    1、源码不允许,会报空指针
    2、有二义性,比如如果某次get的结果时null,代表key不存在,然后contains(key)之前另一个线程并发写入key为null的value,contains会返回true,与原来的不存在相悖。
31、平衡二叉树和红黑树
    平衡二叉树最大的特点是所有节点的左右子树的高度差不能超过一,否则需要旋转保持平衡,很消耗性能,适用于插入删除少,读多的场景
    红黑树:父节点是黑的,非黑即红,红的2个儿子都是黑的,每条线路的黑节点是相等的,最后的null节点是黑的,他的平衡只需要底部几个节点的旋转,性能消耗少
32、ConcurrentHashMap的并发度
    1.7的并发度默认是16,设置并发度后,实际的并发度是设置的数字后面的2的指数大小,比如17,实际上是32
    
Spring
1、为什么要使用spring
    1、轻量级
    2、是一个bean工厂,可以控制反转,包括依赖注入
    3、可以面向切面编程
    4、拥有一个优良的MVC web框架
    5、提供了统一的食物管理接口
2、spring支持哪几种bean的作用域?
    一般情况分俩种:singleton、prototype
    只有在web应用中request、session(一个session)、global-session(所有的session)才起作用
3、spring几种装配模式
    1、xml,不会自动装配,需要通过ref来装配
    2、byName和byType实现自动装配
    3、constructor
4、java代理
    1、静态代理,实现被代理类一样的接口,缺点就是类增多,代理类也就增多,方法多,维护麻烦
    2、动态代理,也叫JDK代理,底层使用反射生成另一个实现目标接口的代理类,jdk封装好了,使用方便,缺点是目标对象也需要实现接口
    3、cglib代理,spring-core引入的功能,改变字节码,生成子类,随意目标类不能final,否则不能被继承
    在Spring的AOP编程中:
            如果加入容器的目标对象有实现接口,用JDK代理
            如果目标对象没有实现接口,用Cglib代理
5、cglib代理中usercache设置为false,每次都生成新的代理类,会导致内存溢出
6、事务的隔离级别(默认使用数据库的隔离级别):
    1、read uncommitted:允许一个事务读取另一个事务没有提交的数据,最低的隔离级别,会带来脏读,一般不追求数据准确性,只追求高并发才会使用
    2、read committed(oracle):不允许事务读取另一个事务还未提交的数据,解决了脏读,但是会出现不可重复读的问题,就是俩个事务同事读取一个数据,一个事务修改并提交后,会导致另一个没有提交的食物数据不准确。
    3、repeatTable read(mysql):可重复读,解决了不可重复度的问题,事务不可以修改另一个事务读取还未提交的数据。但是会出现幻读
    4、serializabel:解决幻读,最高隔离级别幻读和不可重复读的区别是,幻读是一个事务中俩次同条件查询期间,其他事务进行了数据新增或删除,导致2此查询结果数量不一致
    脏读是指一个事务读取到了其他事务没有提交的数据。
    不可重复读是指一个事务内多次根据同一个查询条件查询出来的同一行记录的值不一样。
    幻读是指一个事务内 多次根据同个条件查出来的记录行数不一样
7、事物的ACID原则: 
    原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败 
    一致性:事务前后数据的完整性必须保持一致。 
    隔离性:一个事务执行的时候最好不要受到其他事务的影响 
    持久性:一旦事务提交或者回滚.它对数据库中数据的改变就是永久性的
8、事务的传播
    一个方法调用另一个方法的时候,采取事务的策略,是挂起还是延用,还是新建或者是抛出异常
    常用的是required(默认的)、required_new、nested
    required:有就用旧的,没有就用新的
    required_new:有没有都用新的
    nested:没有就新建,有就沿用旧事务的隔离级别等属性新建一个
9、Transactional自调用失效
    就是同一个类方法A调用方法B,B的事务隔离级别和传播机制都会失效
    原因是@Transactional是通过aop来实现事务的,自调用时类自身的调用,不是代理类的调用,这样就不会产生AOP去为我们设置@Transactional配置的参数
    解决:不要直接调用,可以使用ApplicationContext重新getbean,调用
10、@Transactional对非public或者static方法会失效
    @Transactional是通过aop来实现事务的,动态代理需要目标类实现接口或者是被继承,如果方法是非public,则代理类无法实现或者重新方法
11、spring事务管理
    1、编程式事务管理,需要手动调用beagintraction,commit,roolback方法
    2、基于@Transactional实现声明式事务管理,@Transactional(timeout = 60,rollbackFor=Exception.class),时间超过60s后还有对数据库的非读操作会抛出异常并回滚,
        如果catch住再throw是不会回滚的,必须添加rollbackFor=Exception.class
        缺陷:会把所有的连接点都作为切点将事务织入进去,不能精准切入
    3、基于 TransactionProxyFactoryBean的声明式事务管理,利用xml配置
    4、基于Aspectj AOP配置事务,可以精准切入,还可以实现切面的配置
12、spring循环依赖
    a中依赖b,b中依赖a,Spring尝试通过ApplicationContext.getBean()方法获取A,创建A,发现A中需要B,再去ApplicationContext.getBean()方法获取B(此时A已经创建了),
    ApplicationContext.getBean()获取A,返回A,B创建成功,A接着也创建成功
13、beanfactory和applicationcontext的区别
    beanfactory是ioc的核心接口,Spring 使用 BeanFactory 来实例化、配置和管理 Bean。通过BeanFactory启动IoC容器时(main手动创建),并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时。
    1、BeanFactroy采用的是延迟加载形式来注入Bean的,只有用到Bean时(getBean()),才进行加载实例化,不能发现一些Spring的配置问题。
      而ApplicationContext在容器启动时,一次性创建了所有的Bean,唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
    2、BeanFactory 通常以编程的方式被创建,手动注册,ApplicationContext 还能以声明的方式创建,自动注册,如使用 ContextLoader
14、springMvc运行流程
    第一步:发起请求到前端控制器(DispatcherServlet)
    第二步:前端控制器请求 HandlerMapping 查找 Handler
    第三步:处理器映射器 HandlerMapping 向前端控制器返回 Handler
    第四步:前端控制器调用处理器适配器去执行 Handler
    第五步:Handler 执行完成向前端控制器返回 ModelAndView
    第六步:前端控制器请求视图解析器去进行视图解析
    第七步:视图解析器向前端控制器返回 View
    第八步:前端控制器进行视图渲染
    第九步:前端控制器向用户响应结果
15、spring单例是线程安全的吗?
    Spring中的默认单例bean是,并没有对单例bean进行线程安全的封装,单例bean可以分为是否有状态,也就是说是否进行数据存储,
    无状态情况下,就是不进行数据存储,此时在多线程下是安全的,
    当有状态时,进行数据存储,是非线程安全,此时可以更改bean的scope属性值为prototype来保证线程安全
    
SpringBoot
1、什么是JavaConfig?
    javaconfig是spring下的一个子项目,提供类ioc控制反转的纯java实现,通过@configuration和@bean注解实现,不需要xml来注入bean
2、使用spring-boot-devtools,无需重启就可以重新加载springboot修改的内容
3、springboot常用注解:
    
4、Spring Boot 中的监视器
    底层就是一个controller,监视器模块公开了一组可直接作为 HTTP URL 访问的 REST 端点来检查状态,比如容器中的bean,应用健康状态
5、yaml配置文件,还支持多环境的配置,spring.profiles.active指定生效的环境配置
    YAML 配置的优势在哪里 ?
        1、有层次感,简洁 2、支持list、set、对象
    @PropertySource :加载指定的配置文件; @configurationProperties:默认从全局配置文件中获取值;
    对比properties配置方式@value需要给每个属性单独注入,二yaml是一一对应的
    @springbootapplication会加载spring.factories里面的自动配置类,这些配置类使用@ConfigurationProperties绑定application.yaml配置文件,给对应的配置类注入属性
6、spring-boot-starter-security实现安全控制
    使用config,集成WebSecurityConfigurerAdapter ,重写config方法进行账号密码或者是权限控制
7、有哪些spring-boot-starter-xxx?
8、spring-boot-starter-data-jpa实现分页
9、spring-boot-starter-freemarker
10、Spring Boot 实现异常处理
    1、springboot默认会在异常时候跳转到error页面,页面我们可以自定义,必须写在src/main/resources/templates/下
    2、@ExceptionHandler 指定controller和指定异常进行处理
    3、@ControllerAdvice + @ExceptionHandler 处理全局异常,根据不同的异常对不同的异常进行处理
    4、通过配置 SimpleMappingExceptionResolver 类处理异常也是全局范围,需要将SimpleMappingExceptionResolver 类注入到 Spring 容器
    5、通过实现 HandlerExceptionResolver 接口处理异常
11、1、@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器
    2、@enableAutoConfiguration会加载EnableAutoConfigurationImportSelector类,该类会得到需要自动配置的名单。
        在META-INF/spring.factories文件中。这些Configuration类都有个对应的properties类接收配置文件信息,再在Configuration类中根据各自要求创建对象,实现自动配置
12、propertysource和importsource区别
    propertysource主要是用于yaml和propertites和java bean映射的,该注解不会把bean添加在容器中
    importsource一般放在启动类上,用于加载xml,xml中的bean会被添加到spring ioc容器中
13、跨域问题:域名、端口、协议不同都会导致跨域问题,cookie,js等都不能获取到,ajax也不能发
    1、前端使用jsonp解决,请求方式为jsonp,jsonp不是数据格式,是脚本代码
        使用函数回调的方式,将json数据包裹起来返回,只支持get请求 
    2、CORS springboot,支持所有类型的http请求,实现WebMvcConfigurer接口,重写addCorsMappings
        它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源
14、Spring Data 是 Spring 的一个子项目
    支持非关系型数据库和关系型数据库,只要用户声明Dao接口,规范方法名字就可以直接对接数据库
15、Spring Batch是一个基于Spring的企业级批处理框架,内部定义job,批量进行数据读取修改存储

SpringCloud
1、什么是springcloud:微服务工具包,为开发者提供了在分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等开发工具包。
2、springcloud服务注册与发现,Eureka(这个服务可以使用springboot启动)
    Eureka包含了服务器端和客户端组件。服务器端,也被称作是服务注册中心,用于提供服务的注册与发现。
    Eureka支持高可用的配置,当集群中有分片出现故障时,Eureka就会转入自动保护模式,它允许分片故障期间继续提供服务的发现和注册,当故障分片恢复正常时,
        集群中其他分片会把他们的状态再次同步回来。
    客户端组件包含服务消费者与服务生产者。在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性的发送心跳来更新它的服务租约。
        同时也可以从服务端查询当前注册的服务信息并把他们缓存到本地并周期性的刷新服务状态。
    eureka包含eureka service 和 eureka client(向service发送心跳检测)
    自我保护模式,网络异常的时候保护注册信息,不在注销任何服务,正常之后再取消这个模式

Mybatis
1、一级缓存
    默认开始,缓存在sqlsession中,就是同意额session第一次查询会将结果缓存起来,方便后面相同条件的查询(2此查询期间如果有插入删除修改,则清空缓存)
    通过简单Map集合,但是多个session缓存无法共享,所以才会存在二级缓存
2、二级缓存
    需要手动的配置和开启
    三步骤:1、总配置文件打开2、各自映射文件打开3、dto累实现serializable序列化
    二级缓存是mapper级别的缓存,存放在namespace,只有当查询的sqlsession close的时候才会将结果缓存到二级缓存中去
    缺点:存在其他mapper对当前dto操作的亲何况(多表操作,关联查询),导致不同mapper的数据不一致
3、先查询二级缓存,再查询一级缓存,最后再去数据库,也可以用第三方代替二级,因为二级逇不是很好
4、#{}和${}的区别,#是预编译处理,使用preparestatement的set方法赋值,可以防止sql注入,$则是直接字符串替换
5、 Mybatis 是半自动 ORM 映射工具,因为他还要手动编写sql,但是hibernate不需要,根据对象模型直接获取,它是全自动的
6、延迟加载
    一步分成2个步骤,当第二部在需要的时候再去查询
    原理是使用调用对象的get方法时触发懒加载,拦截机发现为空,会执行事先保存的sql,查到对象的结果set,那么get就会获取到相应的值

Hibernate
1、hibernate:读取配置文件,生成sessionfactory(一个,比较耗内存,线程安全),session有很多个,线程不安全,生命周期短,session.close就关闭

2、懒加载:个属性设置lazy,懒加载对象,只要访问了自身的属性就会去查询数据库,然后获取到所有的数据。那这些操作是谁做的呢,其实就是这个动态创建出来的代理对象,代理对象属性中含有对真实对象        的引用。并且对其增加了监听。这个监听所做的事情就是监听是否有调用懒加载对象的方法,如果调用了,则该监听被触发,从而去访问数据库,获得真实对象的数据。

3、hibernate的三种状态之间如何转换:
    瞬时态:没有持久化标识OID,没有被纳入Session对象的管理
    持久态:有持久化标识OID,已经被纳入Session对象的管理
    托管态:有持久化标识OID,但没有被Session对象管理
    new出来的对象是瞬时状态->保存到数据库中(受Session管理)就是持久化状态->将session close掉就是游离状态
    session没有被close之前是持久化,save和事务提交期间,对数据进行修改也会update
        原理:save会持久化对象,session管理,保存到一级缓存的而同时保存一个快照,事务提交之前的修改会改变缓存但是快照不会修该,事务提交时会比较,不同的话除了save还会对修改的属性额外的update
        
4、hibernate的query().list与query().iterator
    list查询所有,结果存到一级缓存,iterator是查询所有id,根据单个id先看缓存,没有再去数据库查询,结果也会存到缓存
    
5、hibernate里面的sorted collection 和ordered collection有什么区别
    sort是在内存总通过java算法排序,order是在数据库中order by
    对于比较大的数据集,为了避免在内存中对它们进行排序而出现 Java中的OutOfMemoryError,最好使用ordered collection。

6、hibernate Session为应用程序提供了两个管理缓存的方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象,flush():使缓存与数据库同步。

7、Hibernate中没有自己去实现二级缓存,而是利用第三方的,比如EHcache,一般要求不是特别准确的数据,很少被修改的数据,不会被并发访问的数据

8、Hibernate缓存策略:
    Read-only:  这种策略适用于那些频繁读取却不会更新的数据,这是目前为止最简单和最有效的缓存策略 
    Read/write:这种策略适用于需要被更新的数据,比read-only更耗费资源,在非JTA环境下,每个事务需要在session.close和session.disconnect()被调用 
    Nonstrict read/write: 这种策略不保障两个同时进行的事务会修改同一块数据,这种策略适用于那些经常读取但是极少更新的数据 
    Transactional: 这种策略是完全事务化得缓存策略,可以用在JTA环境下
    
9、Hibernate三种查询方式:
    1、hql,类似sql,表明和字段名都只用类名和属性名,可以跨数据库
    2、qbc,面向对象,Session.createCriteria().list(),可以进行简单的查询,排序,分组,比较大小等
    3、sql,不能跨平台,不易维护,不能面向对象
    
    
10、Criteria 和 DetachedCriteria 的主要区别?
    Criteria是在线的,依赖于session创建,DetachedCriteria是离线的,可以在session创建之前就创建,然后可以getExecutableCriteria(session)获取Criteria,DetachedCriteria是不能连接数据库的
    当参数很多的时候,条件很复杂,map只能传递简单的key value,不能传递条件,所以需要在session之前DetachedCriteria组装数据和条件,查询语句的构造完全被搬离到web层实现
    
11、Hibernate的sessionfactory是线程安全的,单例

12、Hibernate get和load区别
    get查询空返回null,load会报异常(有值会返回代理对象)
    get会先查一级缓存, 再查二级缓存,然后查数据库;load会先查一级缓存,如果没有找到,就创建代理对象, 等需要的时候去查询二级缓存和数据库。

13、save和persist的差别?
    1、save会立即持久化到数据库,有问题再回滚,并且会返回主键id,所以必须立即insert
    2、persist要等事务提交才会insert,不会返回主键
    
14、hibernate中getCurrentSession和openSession区别?
    getCurrentSession获取的session会绑定当前线程,而采用OpenSession()则不会。
    getCurrentSession()创建的Session在commit或rollback后会自动关闭,采用OpenSession()必须手动关闭。
    getCurrentSession()需要配置事务
    
15、Hibernate的实体类中要提供一个无参数的构造器?
    jvm在创建对象的时候,如果没有无参构造,会提供默认的构造来创建对象,但是hibernate不会,对象是由Hibernate框架创建的,所以会报错

Mysql
1、数据库的三范式
    每个字段不能不拆分,也就是一列只有一个值
    每一行都要能区分,也就是要有唯一标识
    每个表不包含其他表的非关键字段
2、数据库优化
    1、尽量避免外键,影响插入和删除的效率
    2、 UNION ALL 要比 UNION 快很多, UNION会去重+排序,慢点
    3、尽可能把表设计的小,字段少,字段类型长度小
    4、使用json代替子查询,子查询会创建临时表
    5、用索引,也不是索引越多越好
    6、分库分表
    7、读写分离
3、索引注意事项
    1、避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
    2、避免在 where 子句中对字段进行 null 值判断,会导致放弃使用索引,可以给null设值为0等操作
    3、避免在 where 子句中使用!=或<>,会导致放弃使用索引
    4、where 子句中使用 or 来连接条件,会导致放弃使用索引,可以使用UNION ALL
    5、避免使用in 和 not in,,会导致放弃使用索引,可以使用between
    6、避免like 前置%,会导致索引失效,可以后置%
    7、避免字段表达式和函数操作,比如num*2
    8、复合索引,必须要把索引第一个字段作为查询条件,尽量字段顺序和索引一致
    9、字段重复率高,不要索引
    10、索引降低了 insert 及 update 的效率,因为insert会重建索引
    11、避免大事务
4、mysql比较常用的数据库引擎有两种,一种是innodb、一种是myisam ,myisam数据存于内存,效率高1-2倍,但是myisam锁是表级的,不适合经常修改插入删除的业务场景
5、索引类型
    普通索引
    唯一索引,可以有空值
    复合索引就是组合索引
    主键索引,特殊的唯一索引,不允许空值
    任何标准表最多可以创建 16 个索引列
6、索引:排序的数据结构
    索引的实现通常使用 B 树及其变种 B+树
    
7、各种树
    1、二叉树,第一个数作为根节点,左边小,右边大,缺点就是,如果第一个是最小的,一次增大,会导致都在右边,严重偏科
    2、平衡二叉树,特殊的二叉树,会旋转
    3、B树,可以一个节点存多个数据
    4、B+树,索引就是使用这个数据结构,b树村的是数据,b+是存的是指向记录的指针,所以一个节点可以存储更多的数据,叶子节点存放数据,而且是链表结构的,定位快
8、为什么用b不用二叉树,因为二叉树每个节点只能存一个数据,b可以存多个数据,减少节点数量,数据库性能瓶颈是io,二叉树会导致多次io
9、主从复制
     (1)master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
     (2)slave将master的binary log events拷贝到它的中继日志(relay log);
     (3)slave重做中继日志中的事件,将改变反映它自己的数据。
10、支持的复制类型
    1、基于语句的复制
    2、基于行的复制
    3、混合复制,当发现语句不能精准复制,会采用行复制
11、innodb、myisam
    1、myisam不支持事务,innodb支持事务
    2、InnoDB 支持行级锁,而 MyISAM 支持表级锁
    3、InnoDB 支持外键,而 MyISAM 不支持
    4、InnoDB 不支持全文索引,而 MyISAM 支持
    5、MyISAM数据是以文件的形式存储,InnoDB十一二进制日志存储的
12、innodb的行锁是加在索引上的索引项的,如果没通过索引检索数据,就会表锁
13、where和having区别
    where 早于 group by 早于 having
    having可以用于group by后,介乎聚合函数,对查询结果进行的过滤操作
14、自增主键,删除15的id,重启数据库,再插入时15还是16
    myisam时16,InnoDB时15,因为myisam把id最大值记录在文件中,而InnoDB存在内存中
15、 FLOAT 和 DOUBLE
     FLOAT精度8,4个字节    DOUBLE精度18,8个字节
16、CHAR 和 VARCHAR
    CHAR 列长度固定为创建表时声明的长度,长度值范围是 1 到 255,检索 CHAR 值时需删除尾随空格
17、一列定义为 TIMESTAMP,将发生什么? 
    每当行被更改时,时间戳字段将获取当前时间戳。
18、 AUTO INCREMENT 时,如果在表中达到最大值,会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用
19、LIKE 声明中的%和_
    %:0和多个字符
    _:一个字符
20、mysql执行select过程
    连接、查询缓存(mysql8后没有了,因为只要数据修改了就会清空缓存,命中率比较低)、分析(包括查看是否语法错误)、优化(多索引情况决定使用哪个,多表关联决定表的连接顺序)、执行
21、索引为什么要保存在硬盘中?因为内存空间小并且宕机数据容易丢失
22、是不是b+每个节点存储的越多越好?操作系按数据页大小来访问硬盘,每次IO只读取一个数据页大小的数据,大于一个数据页,则会导致多次IO。尽量让每个节点的数据大小刚好等于一个数据页大小,即每访     问一个节点只需一次 IO
23、新增和删除数据是,b+会分裂或者合并节点,保证一个节点的数据不超过阈值或者是不过度浪费,还需要旋转
24、B+树会把最大元素放在更节点,存在于每一行,叶子结点会从大到小排列所有的元素并串联起来
    每个叶子结点之间是双向链表,每个叶子结点中的数据是单向链表
25、组合索引尽量让数据重合度低的放第一位
26、DATETIME和TIMESTAMP
    TIMESTAMP存的是自1970.1.1起的时间戳,截止到2038年,4个字节,更省空间,DATETIME存的是时间,1000-9999
27、读写分离,环节锁的竞争,读服务器可以使用myisam,提高效率
28、explain(MySQL5.6之前的版本,只允许解释SELECT语句,从 MySQL5.6开始,非SELECT语句也可以被解释了)
    expain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
    在id列上也会有几种情况:
            如果id相同执行顺序由上至下。
            如果id不相同,id的序号会递增,id值越大优先级越高,越先被执行(子查询)
    select_type属性下有好几种类型:
            SIMPLLE:简单查询,该查询不包含 UNION 或子查询
            UNION:表示此查询是 UNION 中的第二个或者随后的查询
    type:
            range:索引范围扫描,常见于使用>,<,is null,between,in ,like等运算符的查询中。
            index:索引全表扫描,把索引从头到尾扫一遍
            all:这个就是全表扫描数据文件
            index_merge:表示查询使用了两个以上的索引,常见and ,or
            system:表中只有一行数据或者是空表
            const:使用唯一索引或者主键,返回记录一定是1行记录

Dubbo(Dubbo 是一个分布式、高性能、透明化的 RPC 服务框架,提供服务自动注册、自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成。)
1、支持哪些协议,常用,不同服务可以指定协议
    1、默认是dubbo协议(hessian 序列化),tcp传输,适用于并发高数据小的场景,生产者少,消费者多,单一长连接,减少连接握手验证等
    2、http 协议(json),多链接,短链接,场景:需同时给应用程序和浏览器JS使用的服务
    3、webservice 协议(soap序列化),适用系统集成和跨语言
2、注册中心
    1、zookeeper
    2、redis,采用 key/Map 存储,住 key 存储服务名和类型,Map 中 key 存储服务 URL,value 服务过期时间
3、负载均衡策略
    1、随机的
    2、轮询的
    3、使用次数最少的
    4、ha'sh,导致用一种请求一直请求同一台服务,挂掉之后会分台到其他机器
4、Dubbo 服务注册与发现的流程
    provider启动服务,并把服务信息,端口ip发送到注册中心,注册,消费者连接注册中心,并把所需服务发送到注册中心,注册中心把相应的服务信息发送给消费者,消费者将信息缓存到本地
    provider状态的变更即使通知注册中心,注册中心实时推送给消费者
5、Dubbo 好处
    provider和comsumer解耦,可动态扩展
    去中心化, 即使注册中心挂掉,也可以短时间内依靠缓存进行服务调用
6、Dubbo 的核心功能
    通讯模块、服务模块、注册模块
7、服务治理中心:路由规则,配置规则,服务降级,访问控制,权重调整,负载均衡,等手动配置
8、Dubbo 的集群容错方案
    默认是failover,失败自动切换其他服务
9、在调用服务不成功时,默认是会重试两次的
10、安全
    1、token令牌,可以在服务端,也可以i设置全局的
    2、可以设置服务黑名单
11、dubbox 基于 dubbo 上做了一些扩展,如加了服务可 restful 调用,更新了开源组件
12、Dubbo关注于服务的调用,流量分发、流量监控和熔断。而 Spring Cloud 考虑的是微服务治理的方方面面。Dubbo 定位服务治理、Spirng Cloud 是一个生态

分库分表
1、mysql 主从同步
    建议是一般在读远远多于写,而且读的时候一般对数据时效性要求没那么高的时候,用 mysql 主从同步。因为主库上并行的操作,在从库上会串行执行,所以高并发场景下,从库会慢一点
2、数据库主键
    1、自增id:空间小,性能好,但是如果需要和表就很麻烦,数据量大,可能会超出自增范围,数据库只能单点,不然id会重复
    2、uuid:适合高并发和分布式,和数据很方便,,性能不高,站控磁盘空间大

网络通讯

消息中间件
1、生产者数据丢失怎么办?
    1、RabbitMQ,第一种是开启事务,如果RabbitMQ没接收到消息,就会爆出异常,事务回滚,再重试,但是这个比较影响性能,因为是同步的
                 第二种是confirm模式,消息发送会附带一个id,RabbitMQ有一个回调函数,告诉失败还是成功,如果超过一定时间还没接收到这个消息的回调,重发,这个模式因为id的原因,是异步的,效率高
    2、kafka:设置acks=all,保证leader和所有的follower都同步了信息才算是接受成功。retries=MAX,一旦写入失败,这无限重试
2、RabbitMQ 弄丢了数据
    RabbitMQ开启持久化,将数据存在硬盘上,如果在持久化到硬盘之前挂掉了,那么可以结合生产者的confirm模式,如果还没持久化,就不回调,生产者会重试
3、消费者弄丢了数据
    1、RabbitMQ:将RabbitMQ的自动ack关闭,采用手动ack,消费者在消费完成之后再手动ack,有异常就将消息分派到其他的消费者
    2、kafka:关闭自动提交 offset,和rabbitmq一样
    问题:在ack或者offset之前,消费完之后恰巧挂掉,其实已经消费完,这样会导致重复消费
    解决:消费端保证幂等就好了,比如通过数据库保证,唯一约束,主键或者是redis保证数据的唯一
4、kafka弄丢了数据
    高可用,acks=all,重试,保证数据不会丢失,leader挂了,会立即推选出其他的follower为leader
5、是不是把所有的信息都持久化硬盘
    不是,会影响性能,选择比较重要的信息持久化或者是采用其他方式持久化(存放到ssd上)
6、kafka采用pull的方式(rabbitmq采用push)
    如果是push模式下,当broker推送的速率远大于consumer消费的速率时,consumer可能崩溃。pull可以更具自身的情况来决定抓取的频率。缺点是在没有新消息的时候会不断轮询。
7、rabbitmq在金融场景中经常使用,具有较高的严谨性,数据丢失的可能性更小,同事具备更高的实时性;而kafka优势主要体现在吞吐量上,虽然可以通过策略实现数据不丢失,但从严谨性角度来讲,大不如rabbitmq;而且由于kafka保证每条消息最少送达一次,有较小的概率会出现数据重复发送的情况;
8、kafka 的 ack 机制
    request.required.acks有三个值 0、 1、 -1
    0:不等待回调,可能会导致消息丢失
    1:等待ack,但是只会在leader收到后发出ack,leader挂了不确保备机数据完全一致,导致数据丢失
    -1:等到leader和备机都收到消息才ack
9、kafaka 生产数据时数据的分组策略
    生产者决定数据产生到集群的哪个partition中,每一条消息都是以(key,value)格式
10、消息队列有什么优点和缺点
    优点:解耦(A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费)
          异步(A 系统产生n条数据,发送到 MQ 里面去,n个系统需要数据自己去 MQ 里面消费)
          削峰(mq将需要消费的消息积压,等到峰值过去慢慢消费)
    缺点:新增一个mq系统,可用性变低,风险变高
          系统复杂性提高,确保消息不会丢失,不会重复消费
11、高可用
    传统的只是提供了集群和一些高可用的机制而已,不是真的高可用
    kafka:某个 broker 宕机了,broker上面的 partition 在其他机器上都有副本的,如果这上面有某个 partition 的 leader,
          那么此时会从 follower 中重新选举一个新的 leader 出来,大家继续读写那个新的 leader 即可.
12、kafka
        架构:由多个 broker 组成,每个 broker 是一个节点;你创建一个 topic,这个 topic 可以划分为多个 partition,
            每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据。
        写数据:生产者就写 leader,然后 leader 将数据落地写本地磁盘,接着其他 follower 自己主动从 leader 来 pull 数据。一旦所有 follower 同步好数据了,就会发送 ack 给 leader,
            leader 收到所有 follower 的 ack 之后,就会返回写成功的消息给生产者
        消费:只会从 leader 去读,但是只有当一个消息已经被所有 follower 都同步成功返回 ack 的时候,这个消息才会被消费者读到
13、保证消息的有序性
    通过队列,每个队列只保证一个线程去消费
14、数据积压怎能么办?
    扩展机器数量,创建新的topicB ,设定10个partition,之前A的消费者逻辑改为获取到topicA的消息之后,发topicB的消息,然后新的10台机器来处理topicB的数据,这样效率是以前的3倍。
15、消息过期
    MQ是由过期时间的,如果过期只能自己想办法找回丢失数据,硬盘?    
    
    
Redis(快!支持5种数据结构,支持大value存储512M)
1、场景:Redis 适合的场景主要局限在较小数据量的高性能操作和运算
2、redis支持的数据类型
    String:很常见的场景用于统计网站访问数量,当前在线人数等。incr命令(++操作)
    List:可以将元素从俩端存入或者是取出(链表,有顺序可重复),1.最新消息排行榜。2.消息队列,以完成多程序之间的消息交换。可以用push操作将任务存在list中(生产者),然后线程在用pop操作将任务取出进行执行。(消费者)
    Set:无序不可重复的。1.利用交集求共同好友。2.利用唯一性,可以统计访问网站的所有独立IP。3.好友推荐的时候根据tag求交集,大于某个threshold(临界值的)就可以推荐。
    zSet:有序,不重复,每一个成员都会有一个分数(score),所以可以用作分数排行,zadd和zrange(获取分段之间的数据)
    hash:key-map的格式,一个key对应一个map,一般用于用户信息记录name,age,pwd等
3、redis使用内存
    内存速度快,异步将数据写入磁盘,磁盘受io限制,性能不行
4、分布式锁
    获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
5、集群
    1、主从复制模式:slave启动后,向master发送SYNC命令,master接收到SYNC命令后通过bgsave保存快照(即上文所介绍的RDB持久化)slave接收到快照文件后,加载快照文件,载入数据,此后master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性
        优点:读写分离,数据同步时异步的,不阻塞请求
        缺点:任何一台宕机,需要重启机器或者时手动切换ip,如果时master宕机,还会造成数据丢失
              难以支持在线扩容,Redis的容量受限于单机配置
    2、哨兵模式:基于主从复制,多个哨兵。 监控master、slave是否正常运行。当master出现故障时,能自动将一个slave转换为master(大哥挂了,选一个小弟上位)。多个哨兵可以监控同一个Redis,哨兵之间也会自动监控
        优点;master挂掉可以自动进行切换,系统可用性更高
        缺点:Redis的容量受限于单机配置
              实现复杂
    3、Cluster模式,所有的redis节点彼此互联,没有master,每个节点都有备机,备机不做读功能,只为了防止主节点宕机。节点宕机需要健测投票,半数以上才算。
                    客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
                    Cluster模式集群节点最小配置6个节点(3主3从,因为需要半数以上)
        优点:无中心架构,数据按照分布在多个节点。
             可以动态的删减节点
    其中主从复制模式能实现读写分离,但是不能自动故障转移;哨兵模式基于主从复制模式,能实现自动故障转移,达到高可用,但与主从复制模式一样,不能在线扩容,容量受限于单机的配置;Cluster模式通过无中心化架构,实现分布式存储,可进行线性扩展,也能高可用,但对于像批量操作、事务操作等的支持性不够好。三种模式各有优缺点,可根据实际场景进行选择。
6、如何保证redis种存放的时热点数据
        redis有数据淘汰策略,非常用的会删掉腾位置
7、redis场景
    全局session、队列、分布式锁、一般缓存、发布订阅
8、Redis 哈希槽,cluster模式
    没有使用一致性 hash,而是引入了哈希槽。Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
9、Redis key 的过期时间和永久有效分别怎么设置? 
    EXPIRE 和 PERSIST 命令
10、内存优化
    尽量使用hash存储,比如用户的名字邮箱,地址等等,不要单独设置key。
11、持久化
    1、RDB(快照):全量持久化,在不同的时间点将 redis 的数据生成的快照同步到磁盘等介质上):内存到硬盘的快照,定期更新。缺点:耗时,耗性能(fork+io 操作),易丢失数据
    2、AOF:增量持久化,将 redis 所执行过的所有指令都记录下来,在下次 redis 重启时,只需要执行指令就可以了):写日志。缺点:体积大,恢复速度慢
12、缓存穿透(缓存和数据库都没有)
    查询一个不存在的数据,每次查询都会穿过缓存,直接去db,造成数据库崩溃
    解决:查询结果为空也存进缓存,设置过期时间
13、缓存雪崩(大量key同时过期)
    大量数据同时过期,同时有大量请求,这是都去了db,搞崩数据库
    解决:将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机
14、是缓存击穿(缓存没有,数据库有)
    某个key过期的同时,对这个key查询的大量请求去了db
    解决:1、设置热点数据不过期
          2、加互斥锁,去db查询的时候上锁
15、Redis 常见的性能问题和解决方案 
    1、master 最好不要做持久化工作,如 RDB 内存快照和 AOF 日志文件
    2、如果数据比较重要,某个 slave 开启 AOF 备份,策略设置成每秒同步一次
    3、为了主从复制的速度和连接的稳定性,master 和 Slave 最好在一个局域网内
    4、尽量避免在压力大得主库上增加从库
    5、主从复制不要采用网状结构,尽量是线性结构,Master<--Slave1<----Slave2 ....
16、查出以某个字段开头的key
        keys命令,可以扫出指定模式的key
        由于单线程,这个命令会阻塞线上服务。还可以使用scan,但是会有重复数据,而且时间花费更长一点
17、Redis 如何实现延时队列
    zset可以获取某个score区间的数据,可以把score取值时间,消息内容为key    
            
Zookeeper
1、一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
    简单说zookeeper=文件系统+监听通知机制,本质上只一个分布式的文件存储系统 
2、假设 3台机器组成的集群,可以有允许一台失效,如果有2台失效,这个集群就不可用,1<1.5,一般的搭建zookeeper集群时,以奇数台机器来搭建。
3、zookeeper下分为很多节点,znode,不仅能存储文件,还可以存储数据,最大1M,节点也分为临时节点(session结束自动删除且不能拥有子节点)和永久节点,创建时确定且不能被改变
    客户端还可以给节点设置watch监控
4、分布式锁
    谁在目录下创建指定名字的目录成功,锁资源就归谁,结束之后锁释放,watch通知所有竞争者再来抢占
5、高可用服务
    a机器启动q服务,并创建目录q,在节点下添加a机器ip,b机器页启动q服务,由于q目录已经创建,所以只能设置watch,当a机器宕机,会把q目录删除,
    通知a,b机器,b机器把q服务由备用状态调整为运行状态,同时创建目录
6、角色
    leader领导者,负责投票发起、决议、数据同步、心跳发送
    follower跟随着,负责和客户端交互,参与投票
    observer观望着,负责和客户交互,不参与投票,只是为了方便扩展和提高读取速度
7、核心是原子广播,zab协议,该协议有俩种模式
    恢复模式:服务启动或者领导者宕机,进入回复模式,不接受客户端请求,当领导者被选举出来,大部分service和leader状态同步之后,恢复模式结束
    广播模式:领导者和大多数service同步之后进入广播模式,,一直持续到服务结束胡总和leader失去大部分支持。当一个服务加入,在恢复模式下同步结束后再进入广播模式,leader负责关播消息
8、操作流程
    1、写操作
        服务接受client请求,并转发给leader,leader向所有service发起提案,Follwer收到提案后执行写操作,然后把操作结果发送给Leader,
            当多数follower返回提案结果后,leader会commit该提议,通知其他Follower 和 Observer 同步信息;
    2、读操作
        服务端接受消息,并读取数据给client返回
9、应用
    1、发布订阅(配置管理),应用配置集中到节点上,应用启动时主动获取,并在节点上注册一个watcher,每次配置更新都会通知到应用。
    2、命名空间服务,分布式命名服务,创建一个节点后,节点的路径就是全局唯一的,可以作为全局名称使用。
    3、分布式的通知协调,基于目录的订阅功能,目录的修改删除都会通知订阅者。
    4、分布式锁,zookeeper保证数据的强一致性
                1、创建节点,节点不存在,创建,抢占成功   存在,抢占失败
                2、父节点下创建子节点,序列号最小的获得锁
    5、集群管理,集群每新增一个节点,都在父节点下新增一个子节点,任何新增删除修改,都会被父节点的watch所监控并作出相应的处理
10、四种类型的znode
    1、持久化的,zookeeper断开连接,节点依旧保存
    2、持久化顺序编号,zookeeper断开连接,节点依旧保存,zookeeper给该节点进行顺序编号
    3、临时,zookeeper断开连接,节点删除
    4、临时顺序编号,zookeeper断开连接,节点删除,zookeeper给该节点顺序编号
11、servcie三种状态
    不知道leader是谁LOOKING ,leader本身,和leader整在同步种
12、选举机制
    比如有5台机器,1启动状态LOOKING,第二台启动,获得2个人支持,但是没超过一半,状态还是LOOKING ,3启动,获取3个人支持,直接乘位leader,4、5启动直接成为小弟
13、zxid
    ZooKeeper状态的每一次改变, 都对应着一个递增的Transaction id, 该id称为zxid. 由于zxid的递增性质, 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2发生.
    创建任意节点, 或者更新任意节点的数据, 或者删除任意节点, 都会导致Zookeeper状态发生改变, 从而导致zxid的值增加.
14、事务顺序性
    zxid
15、同步流程
    service给leader发送最大zxid,leader根据zxid确定同步点,将同步信息发送给service,service更新完成后继续接受client请求
    
数据结构与算法
1、为什么集合遍历时不能新增删除元素?
    在遍历过程中使用一个modCount 变量,集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount 变量是否为expectedmodCount 
    值,是的话就返回遍历;否则抛出异常ConcurrentModification,终止遍历
2、ArrayList 和 LinkedList
    ArrayList底层是个数组,查询效率高    LinkedList底层是个链表,插入删除效率高    LinkedList 比ArrayList 需要更多内存
3、hashset怎么保证数据不重复?
    底层就是个hashmap,因为hashmap的key是不允许重复的,set的值作为key,一个相同的虚值作为valeu
4、BlockingQueue
    一般用于生产者和消费者。
    入队:1、offer,队列没满,返回true,队列满,返回false
          2、 put,队列满,阻塞,直到不满或者线程被中断
          3、offer(超时时间),如果满,阻塞,直到不满或者线程被中断或者超时
    出队:1、poll():如果没有元素,直接返回null;如果有元素,出队    
          2、take():如果队列空了,一直阻塞,直到队列不为空或者线程被中断-->阻塞
          3、poll(long timeout, TimeUnit unit):如果队列不空,出队;如果队列已空且已经超时,返回null;如果队列已空且时间未超时,则进入等待,直到
5、JDK8 中 HashMap 为什么选用红黑树而不是 AVL 树
    如果map中存储的对象hash算法写的不好,可能会导致一个捅内hash冲突很多,这个时候就会把链表转为红黑树。一个桶中冲突1024个key,使用链表平均需要查询512次,但是红
黑树仅仅10次。
    插入删除等操作效率提高很多。红黑树不像avl树一样追求绝对的平衡,他允许局部很少的不完全平衡,这样对于效率影响不大,但省去了很多没有必要的调平衡操作,avl树调平衡
有时候代价较大,所以效率不如红黑树。
6、hashmap扩容,
    一般再map容量0.75时扩容,扩大一倍,扩容需要重新计算元素位置,好性能,所以我们创建map最好是指定大小,大小不是元素n,二十大于n/0.75的2的次方
7、HashSet 和 TreeSet 有什么区别? 
    HashSet 是由一个 hash 表来实现的,因此,它的元素是无序的。
    TreeSet 是由一个树形的结构来实现的,它里面的元素是有序的。
8、Iterator
    Iterator提供了很多集合迭代的方法,每种集合都有方法能返回一个迭代器,迭代器可以删除元素,但是不能使用集合直接删除
9、排序
    1、快速排序:选一个基数,一般是第一个(或者最后一个),分别从左右俩边开始,左边找比基数大的,右边找比基数小的,交换位置,一直重复,直到左右俩边相遇,相遇的位置和基数互换位置
        至此基数左侧都是小于基数的,右侧都是大约基数的,分为2个数组,重复上一次操作,直到排序完成
        优点:速度快,剩空间,缺点:非常脆弱,在实现时一定要注意几个小细节。
    2、冒泡排序
    3、直接选择排序

java面试问题总结相关推荐

  1. java面试常见问题之Hibernate总结

    1  Hibernate的检索方式 Ø  导航对象图检索(根据已经加载的对象,导航到其他对象.) Ø  OID检索(按照对象的OID来检索对象.) Ø  HQL检索(使用面向对象的HQL查询语言.) ...

  2. 2021年Java面试题目最新总结【90%面试会踩的坑】

    学会java技术之后大家面临的最多的问题就是面试这关,求职面试java岗位是否能够成功是直接影响我们的工作机会的,所以对于Java程序员面试你准备好了吗?今天小编汇总了一下关于Java程序员面试,90 ...

  3. Github 一夜爆火:这份金九银十 Java 面试手册我给跪了

    这几天给筒子们整理了一份<Java面试手册>,106页,目前大约6万字左右,初衷也很简单,就是希望在面试的时候能够帮助到大家,减轻大家的负担和节省时间. 废话不多说,本手册目前为第一版,后 ...

  4. Java面试参考指南(二)

    2019独角兽企业重金招聘Python工程师标准>>> 访问修饰符 对于基本的OOPS(面向对象)概念,请看Java面试参考指南的第一部分.访问修饰符规定了一个类如何访问另一个类及它 ...

  5. 卧槽,又一个Java面试神器!!!

    临近秋招,又到了"金九银十"面试求职高峰期,在金三银四时也参与过不少面试,2020都说工作不好找,也是对开发人员的要求变高.前段时间自己有整理了一些Java后端开发面试常问的高频考 ...

  6. 200 道 Java 面试题解!某阿里 P7 只答上来 70%!

    最近,经常有读者朋友们在后台给我留言,问我有没有什么面试资料可以分享的,因为之前一直比较忙,所以没有时间整理. 最近终于抽出一些时间,整理了一下,一发不可收拾了,一口气整理出好几本电子书出来.其中有一 ...

  7. 美团架构师开源5万字的《Java面试手册》PDF免费下载!

    美团一位架构师利用空余时间在github整理了一份<Java面试手册>,现整理成PDF,初衷也很简单,就是希望在面试的时候能够帮助到大家,减轻大家的负担和节省时间. 前两天,朋友圈分享了这 ...

  8. 5万字的《Java面试手册》V1.0版本,高清PDF免费获取

    利用空余时间整理了一份<Java面试手册>,初衷也很简单,就是希望在面试的时候能够帮助到大家,减轻大家的负担和节省时间. 前两天,朋友圈分享了这份这份面试手册的初稿,再几位同学的提议下,对 ...

  9. JAVA面试解析(有赞二面)

    作者:孤独烟 来自:打杂的ZRJ 本文的题目出自博客 http://www.54tianzhisheng.cn/2018/07/12/youzan/ 但是作者没有给出答案,博主斗胆来制作答案版. 也是 ...

  10. Java 面试,这样拿 Offer!

    (含答案) 所有面试资料及技术好文精选文档都整理到网盘了. Java面试官手册需要加微信免费领取 长按扫码或搜索微信号:gupao666666,免费领取

最新文章

  1. reactor与proactor模式
  2. hibernate动态表名映射
  3. VS .NET(C#)四舍五入方法(转)
  4. Android 常用的地球经纬度转换公里(km)计算工具类
  5. 简单拨号器(Android)
  6. 什么是Marketing Cloud的ABM - Account-Based Marketing
  7. python3 set_python3.x 基础三:set集合
  8. it计算机哪些专业术语,IT之家学院:笔记本电脑专业术语科普
  9. 我最爱用的一款 Redis 可视化管理工具!好用到爆!!!
  10. [Java] 蓝桥杯BASIC-18 基础练习 矩形面积交
  11. Arcgis server——arcgis server manager忘记密码
  12. 二维联合分布的密度函数计算
  13. Proteus软件的安装与使用方法(超详细)
  14. 批量导入手机通讯录_大批量手机号导入通讯录软件
  15. 双目测距算法matlab模拟,基于BM算法的双目测距.pdf
  16. DOJP1520星门跳跃题解
  17. Ubuntu20.04设置网络共享文件夹
  18. 视频怎么压缩变小?视频压缩变小的具体操作步骤
  19. python二维数组的行和列_python 定义N行2列二维数组与赋值
  20. vueTable大数据展示优化

热门文章

  1. 关于替换SSHD的banner的方法[反编译版][应付漏扫]
  2. 新手用降低转速来解决显卡风扇噪音大的问题(有图有真相)
  3. ATA-L6水声功率放大器用于水声系统测试—西安电子测量仪器
  4. 搜集到的visa几个文章资料
  5. 数据结构 — 排序算法
  6. 软件测试之ios自动化——文件上传
  7. 电路分析第三章 一阶电路
  8. maven项目需要提交到版本库管理的文件
  9. HRM人力资源系统-Day11
  10. 熊猫直播被传破产:王思聪也救不了 员工发文告别