高频面试题
# 高频面试题
# 容器:
# 1.java容器有哪些
# 2.Collection和Collections有什么区别
# 3.HashMap和Hashtable有什么区别
- Hashtable是是用了synchronized 的,保证了线程安全问题,效率较低,而hashmap是没有上锁的,线程不安全,但是效率会比较高。
- 我记得它们继承的父类是不一样的,但是具体是哪个我有点不太记得了,hashmap好像是什么AbstractMap什么的,记不太清了。
- 在源码里的PUT方法中,Hashtable里面,key和value都是不能为null的,否则就会抛一个空指针异常,但是hashmap 里面允许的,他会对key 做一个判断,如果为null,就会给个值为0.
- 初始化容量不一样,Hashtable是11,hashmap 16.而初始化,Hashtable是在构造方法里面就会初始化,并且如果你有给定初始容量值,他会直接按照你给的来初始化,而hashmap 在第一次put的时候才回去开辟这个数组,并且会把这个初始容量值来做一个运算,会返回一个大于等于这个值的一个2次幂
- 在扩容的时候,Hashtable 他是变为原来的2n+1,而HashMap则是变为原来的两倍。
- 还有就是两者的hash运算是不一样的,Hashtable 是直接调了个hashCode就结束了,然后对数组的长度来取余,但是HashMap中还会将他右移16位,然后通过异或运算来得到的一个hash值。
# 4.如何决定使用HashMap还是TreeMap?
# 5.说一下HashMap的实现原理
hashmap是我们在日常开发当中几乎每天都要用到的这么一个集合类,它是以键值对的形式来进行存储,在 jdk1.7 到 jdk1.8 之间,hashmap 的实现略有区别,其中两个比较重要的区别,一个是在 jdk1.7 的时候hashmap采用的数据结构是数组加链表的形式,而在 jdk1.8 呢,则是加入了红黑树,也就是数组+链表+红黑树的这么一个组合。加入红黑树是为了来提高他的一个查询效率,因为我们知道链表他的查询效率是很慢的,因为链表他实际上存储的是一个节点的地址,通过引用地址的这么一个操作,将两个节点建立联系。他的删除,修改的一些操作是很快的,因为我直接通过存储key的这个节点中,所存储的那个地址,就可以找到数据,那么比方说删除的话,就是只要把地址一改,就可以完成了,不像数组还要进行遍历之后再来操作。然后还有一点就是再 jdk1.7 之前,当我们遇到哈希碰撞,需要在我们这个链表上添加数据的时候,采用的是在链表的头部来进行一个插入,也就是头插法。那在 jdk1.8 呢是改成了尾插法,也就是在尾端插入。原因呢是因为,使用头插法的话,在多线程情况下会导致一些问题,比如说他会形成循环列表啊,耗尽我们cpu的性能的这么一种情况。 当然在 jdk1.7和jdk1.8之间呢还有很多的一些优化的细节,包括put方法的代码有改动,hash算法的简化等等,因为当时是看了他的源码,但是就是我可能就是记不太清了。有一些就是还记得,比如说这个创建这个hashmap 的始化容量为什么最好是要2的次幂,这个呢就是当我们在往hashmap里面put第一个值的时候呢,这个时候我们的这个数组他才会被初始化,然后他默认的一个初始容量是16,然后对我们的这个put进来的这个key的哈希值,来与上他的这个初始容量来算出他的下标,因为位运算他的效率在计算机里面是非常高的。然后呢在我们往里面添加数据的时候,会产生两个问题,一个呢就是扩容的问,另一个就是树化的问题。关于扩容的问题,在hashmap 中是有一个成员变量,也就是加载因子,他的值呢是0.75。当我们hashmap 的这个size ,就是你插入的节点的数量大于等于这个加载因子乘与这个容量的时候,他就会进行一次扩容。而树化呢就是他有前提,就是我们链表的长度要大于等于八的时候,他才会去进行树化。这是一个点,另一个点就是他会判断你的这个数组的容量是否是大于等于64,如果是,那么才会进行树化,否则呢他是优先选择对数组来进行扩容的。
关于hashmap 的话,我大概就这么多,你看还有什么问题需要问我的。
# 6.说一下HashSet的实现原理
实现原理: HashSet底层由HashMap实现 ,值存放于HashMap的key上 ,HashMap的value统一为PRESENT 。
检查重复: 先对插入的元素的hashcode值和现有的元素的hashcode作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现,直接插入。但是如果发现有相同hashcode值的对象,这时会调用equals()
方法来检查hashcode相等的对象是否真的相同。 如果两者相同,HashSet就不会让加入操作成功 。
# 7.ArrayList和Vector的区别是什么
Vector 与 ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一 个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此, 访问它比访问 ArrayList 慢。
# 8.Array和ArrayList有何区别
1.ArrayList是Array的复杂版本;
2.存储的数据类型:Array只能存储相同数据类型的数据,而ArrayList可以存储不同数据类型的数据;
3.长度的可变:Array的长度是固定的,而ArrayList的长度是可变的。
# 9.在Queue中poll() 和 remove() 有什么区别
# 10.哪些集合类是线程安全的?
# 11.迭代器Iterator是什么
# 12.Iterator 和 ListIterator 有什么区别
# 13.怎么确保一个集合不能被修改
# 异常:
# 1.throw和throws的区别?
# 2.final,finally,finalize有什么区别?
# 3.try-catch-finally中,如果catch 中 return 了,finally还会执行吗?
# 4.常见的异常类有哪些?
# 网络:
# 1.http响应码 301 和 302 代表的是什么?有什么区别?
# 2.forward 和 redirect 的区别?
# 3.简述 tcp 和 udp 的区别
# 4.get 和 post 请求有哪些区别
# 5.https 和 http 的区别
# SpringBoot/SpringCloud
# 1.什么是SpringBoot?
# 2.为什么要用SpringBoot?
编码:减少开发、测试的时间和工作量。
配置:使用 JavaConfig 有助于避免使用 XML。没有 web.xml 文件,只需添加带 @ configuration 注释的类。
避免大量 maven 导入和各种版本冲突。
部署:不需要单独的 Web 服务器。这意味着您不再需要启动 Tomcat 或其他任何东西。
# 3.SpringBoot核心配置文件是什么
# 4.SpringBoot配置文件有哪几种类型,它们有哪些区别
# 5.SpringBoot有哪几种方式可以实现热部署?
# 6.什么是SpringCloud?
# 7.SpringCloud断路器的作用是什么?
# 8.SpringCloud的核心组件有哪些?
# 9.SpringBoot 自动装配原理
额,简单来说就是,spring启动时依靠他的main方法来进行启动的,在main方法里面,我们会调用SpringApplication.run方法,在run方法执行的时候,其中他会有一个刷新容器的过程,有一个reflashContext方法,他会去刷新我们的容器。在刷新容器的时候,他就会通过解析注解,解析配置文件的方式,把我们的bean注到容器里面,这个时候他就会去解析这个SpringApplication这个注解,这个注解呢他本身是一个配置类,他里面有个开启AutoConfiguration的注解,在这个注解里面,他有一个核心的,就是会给我们impont进来一个类,一个select的类,叫什么AutoConfigurationImpontSelect类,然后这个类他会有些核心方法,帮助我们从类路径下的一个spring.factories文件里面加载一些东西,会把那个key为,我也忘了那个url的那个AutoConfiguration的那个key了,就是key底下会跟着很多的配置类,他会加载这些配置类,全部加载到容器里面,在这些AutoConfiguration 类里面呢,他会有很多的那些条件注解,它会根据你引入的jar包,以及你容器里面的bean ,把相应的bean自动给注入到容器里面。然后就实现了自动装配了。
# Spring/SpringMVC
# 1. SpringMVC 的执行流程
- 客户端发送url请求,前端控制器(DispatcherServlet)接收到这个请求然后转发给处理器映射器(HandlerMapping)。
- 处理器映射器会对url请求进行分析,找到对应的后端控制器(Handler),并且生成处理器对象及处理器拦截器(形成一条执行链)返回给前端控制器。
- 根据处理器映射器返回的后端控制器(Handler)的名称/索引, 前端控制器 会找合适的处理器适配器( HandlerAdapter )
- 处理器适配器会去执行后端控制器(Handler在开发的时候会被叫成Controller)。补充:执行之前会有转换器、数据绑定、校验器等等操作。完成上面这些才会去执行后端控制器。
- 后端控制器Handler执行完成之后返回一个 ModelAndView 对象, Model 是返回的数据对象,View 是个逻辑上的 View。
- 处理器适配器会将这个 ModelAndView 返回前端控制器。前端控制器会将 ModelAndView 对象交给合适的视图解析器 ViewResolver 。
- 视图解析器(ViewResolver)解析 ModelAndView 对象,返回 视图对象(view)。
- 前端控制器请求视图对视图对象(View)进行渲染(数据填充)之后返回并响应给浏览器/客户端。
# 2. SpringMVC 的容器结构
# 3. 谈谈你对 Spring的理解
让 java 开发模块化,并且全面。Spring 通过控制反转降低耦合性,一个对象的依赖通过被动注入的方式而非主动 new,还通过代理模式实现了面向切面编程。
# 4.什么是 Spring IOC 容器?
IOC 是一种设计思想。 IOC 容器是 Spring 用来实现 IOC 的载体, IOC 容器在某种程度上就是个Map(key,value),key是 name 属性,value 是对应的对象。
IOC主要实现原理就是工厂模式加反射机制。
调用 refresh() 方法:
- 刷新准备,设置开始时间,状态, 初始化占位符等操作
- 获取内部的 BeanFactory,Spring 容器在启动的时候,先会保存所有注册进来的 Bean 的定义信息, 注册到 BeanFactory 中。
- 设置 BeanFactory 的类加载器和后置处理器,添加几个 BeanPostProcessor,手动注册默认的环境 bean
- 为子类提供后置处理 BeanFactory 的扩展能力,初始化上下文之前,可以复写 postProcessBeanFactory这个方法
- 执行 Context 中注册的 BeanFactory 后置处理器,对 SpringBoot 来说,这一步会进行 BeanDefintion 的解析
- 按优先级在 BeanFactory 注册 Bean 的后置处理器,这是在 Bean 初始化前后执行的方法
- 初始化国际化,事件广播器的模块,注册事件监听器
- 然后 Spring容器就会创建这些非延迟加载的单例 Bean
- 最后广播事件,ApplicationContext 初始化/刷新完成
# 5. Bean 的作用域有哪些
- Singleton - 每个 Spring IoC 容器仅有一个单实例。
- Prototype - 每次请求都会产生一个新的实例。
- Request - 每次请求都会创建一个实例
- Session - 在一个会话周期内只有一个实例
- Global-session - 类似于标准的 HTTP Session 作用域,5.0版本后已不再使用
- Appilcation - 在一个 ServletContext 中只有一个实例
- Websocket - 在一个 Websocket 只有一个实例
# 6.Bean 的生命周期
Bean容器/BeanFactory 通过对象的构造器或工厂方法先实例化 Bean;
再根据 Resource 中的信息再通过设定好的方法(典型的有setter,统称为BeanWrapper)对 Bean 设置属性值,得到 BeanDefintion 对象,然后 put 到 beanDefinitionMap 中,调用 getBean 的时候,从 beanDefinitionMap 里拿出 Class 对象进行注入(使用了反射),同时如果有依赖关系,将递归调用 getBean 方法,即依赖注入的过程。
检查 xxxAware 相关接口,比如 BeanNameAware,BeanClassLoaderAware,ApplicationContextAware( BeanFactoryAware)等等,如果有就调用相应的 setxxx 方法把所需要的xxx传入到 Bean 中。
补充:关于 Aware ,Aware 就是感知的意思, Aware 的目的是为了让Bean获得Spring容器的服务。 实现了这类接口的 bean 会存在“意识感”,从而让容器调用 setxxx 方法把所需要的 xxx 传到 Bean 中。
此时检查是否存在有于 Bean 关联的任何 BeanPostProcessors, 执行 postProcessBeforeInitialization() 方法(前置处理器)。
如果 Bean 实现了InitializingBean接口(正在初始化的 Bean),执行 afterPropertiesSet() 方法。
检查是否配置了自定义的 init-method 方法,如果有就调用。
此时检查是否存在有于 Bean 关联的任何 BeanPostProcessors, 执行 postProcessAfterInitialization() 方法(后置处理器)。返回 wrapperBean(包装后的 Bean)。
这时就可以开始使用 Bean 了,当容器关闭时,会检查 Bean 是否实现了 DisposableBean 接口,如果有就调用 destory() 方法。
如果 Bean 配置文件中的定义包含 destroy-method 属性,执行指定的方法。
上面整个过程就是 Bean 的整个生命周期了。
# 7.Spring 如何解决循环依赖?
Spring使用了三级缓存解决了循环依赖的问题。在populateBean()给属性赋值阶段里面Spring会解析你的属性,并且赋值,当发现,A对象里面依赖了B,此时又会走getBean方法,但这个时候,你去缓存中是可以拿的到的。因为我们在对createBeanInstance对象创建完成以后已经放入了缓存当中,所以创建B的时候发现依赖A,直接就从缓存中去拿,此时B创建完,A也创建完。至此Bean的创建完成,最后将创建好的Bean放入单例缓存池中。
# 8.AOP 的原理(重要)
开启了 AOP 功能后,容器在注册 Bean 的后置处理器的时候,就会注册一个相关的后置处理器(AspectJAutoProxyCreator),在创建单实例 Bean 的时候,这个后置处理器就会拦截业务逻辑组件和切面组件的创建过程,怎么拦截呢?就是等组件创建完后,判断是否是通知方法,如果是就把切面的通知方法包装成增强器(Advisor),给业务逻辑组件(目标类)创建一个代理对象,代理的方式由 Spring 来判断返回这个代理对象,容器创建完成后这个代理对象执行目标方法的时候,执行拦截器链依次执行通知方法。
# 9.JDK 动态代理和 CGLIB 的区别
- JDK只能对实现了接口的类生成代理,而不能针对类。Cglib是针对类实现代理,主要是对指定的类生成一个子类。
- JDK是利用拦截器(必须实现InvocationHandler)加上反射机制来去实现代理的,而CgLib则是使用的ASM字节码生成框架。
- cglib生成的代理类是在内存中,而JDK则是会保存到磁盘中。
# 10.AspectJ 和 Spring AOP
这个没有太去了解,不过AOP是基于他的风格来去实现的。两者的区别的话,就是AOP 属于运行时增强,而 AspectJ 是编译时增强。再深入就没有太去了解了。
# 11.Spring 框架中用到了哪些设计模式?
- 工厂设计模式 : Spring使用工厂模式通过
BeanFactory
、ApplicationContext
创建 bean 对象。 - 代理设计模式 : Spring AOP 功能的实现。
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板方法模式 : Spring 中
jdbcTemplate
、hibernateTemplate
等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。 - 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配
Controller
。
# 12.
# 设计模式
# 1.说一下你熟悉的设计模式
# 2.简单工厂和抽象工厂的区别
# 多线程
# 1.并行和并发的区别?
# 2.线程和进程的区别?
# 3.守护线程是什么?
# 4.创建线程有哪几种方式?
# 5.说一下 runnable 和 callable 有什么区别
- Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;
- Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。
# 6.线程有哪些状态?(线程的生命周期)
# 7.sleep() 和 wait() 的区别
- sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
- sleep() 方法可以在任何地方使用;wait() 方法则只能在同步方法或同步代码块中使用,否则抛出异常
- sleep是线程类(Thread)的方法;wait是Object类的方法
# 8.notify() 和 notifyAll() 有什么区别
# 9.线程 run() 和 start() 有什么区别
# 10.创建线程池有哪几种方式
# 11.线程池都有哪些状态?
# 12.线程池中 submit() 和 execute() 方法有什么区别?
# 13.在java程序中怎么保证多线程的运行安全?
# 14.多线程锁的升级原理是什么?
# 15.什么是死锁?
# 16.怎么防止死锁?
# 17.ThreadLocal 是什么?有哪些使用场景?
# 18.说一下 synchronized 底层实现原理?
# 19.synchronized 和 volatile 的区别是什么
# 20.synchronized 和 Lock 有什么区别?
# 21.synchronized 和 ReentrantLock 区别是什么?
# 22.说一下 atomic 的原理?
# 反射
# 1.什么是反射
# 2.什么是java序列化?什么情况下需要序列化?
# Java Web
# 1.session 和 cookie 有什么区别?
Cookie数据存放在客户的浏览器上, Session数据放在服务器上
Session相对于Cookie更安全,但是Cookie相对于Session性能更佳,毕竟更小。
单个cookie在客户端的限制是4K
# 2.说一下session的工作原理
# 3.如果客户端禁止cookie,session 还能用吗
# 4.如何避免sql注入
# 5.servlet 的生命周期
它主要是有四个阶段,首先创建这个 Servlet 的实例,然后会调用 init() 方法来进行一个初始化,然后当请求过来的时候,就会调用 service() 方法来提供服务,最后就是Servlet容器要关闭的时候,就会调用 destroy() 方法来释放掉Servlet所占用的资源。
# Java 基础
# 1.JDK 和 JRE 有什么区别
# 2.== 和 equals 的区别是什么 ?
# 3.两个对象的 hashCode() 相同,则 equals() 也一定为true, 对吗?
# 4.final 在 java 中有什么作用?
# 5.java 中的 Math.round(-1,5)等于多少?
# 6.String 属于基础的数据类型吗?
# 7.java 中操作字符串都有哪些类?它们之间有什么区别?
# 8.String str=“i” 与 String str = new String("i") 一样吗?
# 9.如何将字符串反转
# 10.String 类的常用方法都有哪些
# 11.抽象类必须要有抽象方法吗?
# 12.普通类和抽象类有哪些区别?
# 13.抽象类能使用 final 修饰吗?
# 14.接口和抽象类有什么区别?
# 15.java 中 IO 流分为几种?
# 16.BIO , NIO , AIO 有什么区别?
# 17.Files 的常用方法都有哪些?
# 消息队列
# 1. rabbltmq 的使用场景有哪些?
1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
3.削峰,并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常
# 2. rabbltmq 有哪些重要的角色?
# 3. rabbltmq 有哪些重要的组件?
# 4.rabbltmq 中 vhost 的作用是什么?
# 5.rabbltmq 的消息是怎么发送的?
# 6.rabbltmq 怎么保证消息的稳定性?
# 7.rabbltmq 怎么避免消息丢失?
- 消息持久化
- ACK确认机制
- 设置集群镜像模式
- 消息补偿机制
# 8.要保证消息持久化成功的条件有哪些?
# 9.rabbltmq 持久化有什么缺点?
# 10.rabbltmq 有几种广播类型?
- fanout: 所有bind到此exchange的queue都可以接收消息(纯广播,绑定到RabbitMQ的接受者都能收到消息);
- direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息;
- topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息;
# 11.rabbltmq 怎么实现延迟消息队列?
# 12.rabbltmq 集群有什么用?
# 13.rabbltmq 节点的类型有哪些?
# 14.rabbltmq 集群搭建需要注意哪些问题?
# 15.rabbltmq 每个节点是其他节点的完整拷贝吗? 为什么?
# 16.rabbltmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?
# 17.rabbltmq 对集群节点停止顺序有要求吗?
# 18.RabbitMQ的工作模式
1.simple模式(即最简单的收发模式)
消息产生消息,将消息放入队列,消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除
2.work工作模式(资源的竞争)
消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息
3.publish/subscribe发布订阅(共享资源)
每个消费者监听自己的队列,生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息
4.routing路由模式
消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息
5.topic 主题模式(路由模式的一种)
就是routing查询的一种模糊匹配,星号代表多个单词,井号代表一个单词,交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费
# mybatis
# 1.mybatis 中 #{} 和 ${} 的区别是什么?
#
是预编译处理,$是字符串拼接
# 2.mybatis 有几种分页方式?
# 3.RowBounds 是一次性查询全部结果吗?为什么?
# 4.mybatis 逻辑分页和物理分页的区别是什么?
# 5.mybatis 是否支持延迟加载?延迟加载的原理是什么?
# 6.说一下 mybatis 的一级缓存和二级缓存?
一级缓存:
Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。 也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中; 第二次以后是直接去缓存中取。 当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。
二级缓存:
二级缓存我并没有太去了解,而且二级缓存他主要其实就是实现了SqlSession的共享,那我在有redis的情况下,其实也没有必要去使用这个二级缓存。
# 7.mybatis 和 hibernate 的区别有哪些
# 1.sql 方面不同
- Hibernate 不需要编写大量的 SQL,就可以完全映射,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)对 POJO 进行操作。但会多消耗性能。
- MyBatis 手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。工作量相对大些。
# 2.映射关系不同
- MyBatis 是一个半自动映射的框架,因为 MyBatis 需要手动匹配 POJO、SQL 和映射关系。
- Hibernate 是一个全表映射的框架,只需提供 POJO 和映射关系即可。
# 8.mybatis 有哪些执行器(Executor)?
# 9.mybatis 分页插件的实现原理是什么?
# 10.mybatis 如何编写一个自定义插件?
# 11.嵌套查询和嵌套结果有什么区别?
两者的区别我个人觉得,就是发一条sql和发多条sql的区别,两者同样都是要在resultMap里面定义好属性
嵌套查询就是把压力交给数据库,意思就是请求来了,要查一个对象A,然后我调用sql,查回来发现,里面有个对象B的属性,那么我再发一条sql去把B的属性也给查回来。
而嵌套结果就是,我直接一条sql,将所有要的数据,一次性通过join来全部查回来,然后再在内存中进行组装,拼接等操作。但是我至始至终都是只发了一条sql,压力是在内存而不是在数据库里。
# 12.mybatis中是如何去表明映射关系的?
- association: 一对一关联(has one)
- collection:一对多关联(has many)
# MySql
# 1.数据库的三范式是什么?
# 2.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
# 3.如何获取当前数据库版本?
# 4.说一下 ACID 是什么?
# 5.char 和 varchar 的区别是什么?
# 6.float 和 double 的区别是什么?
# 7.mysql 的内连接,左连接,右连接有什么区别?
# 8.mysql 索引是怎么实现的?
# 9.怎么验证 mysql 的索引是否满足需求?
# 10.说一下数据库的事务隔离?
# 11.说一下 mysql 常用的引擎?
# 12.说一下 mysql 的行锁和表锁?
# 13.mysql支持的索引有哪些
主键索引,唯一索引,普通索引,全文索引,组合索引
# 14.聚集索引和非聚集索引
聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储金和索引分开的结构,索引结构的叶子节点指向了数据的对应行
# 15.
# Redis
# 1. redis 是什么? 都有哪些使用场景?
Redis是C语言开发的一个开源的单进程单线程 key-value 形式的内存数据库
- 缓存
- 共享Session
- 消息队列系统
- 分布式锁
# 2. redis 有哪些功能?
数据持久化,主从复制,哨兵
# 3. redis 和 memecache 有什么区别?
- redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,String。
- Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中。
- 集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 redis 目前是原生支持 cluster 模式的.
- Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。
# 4. redis 为什么是单线程的?
因为 cpu 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且 cpu 又不会成为瓶颈,那就顺理成章地采用单线程的方案了。 可以避免多线程上下文切换。
# 5. 什么是缓存穿透? 怎么解决?
# 6. redis 支持的数据类型有哪些?
# 7. redis 支持的 Java 客户端都有哪些?
# 8. jedis 和redisson 有哪些区别?
# 9.怎么保证缓存和数据库数据的一致性?
# 10. redis 持久化有几种方式?
# 11. redis 怎么实现分布式锁?
# 12. redis 如何做内存优化?
# 13. redis 淘汰策略有哪些?
# 14. redis 常见的性能问题有哪些? 该如何解决?
# 15.如何保证缓存里都是热点数据?
我们是在查询的时候,命中一次就会给这个数据增加一个过期时间,所以如果是频繁查询的数据的话,那他的过期时间肯定是会比较长。
# 16.缓存雪崩
在一个较短的时间内,缓存中较多的key集中过期或者缓存挂了,导致了数据库服务器崩溃
解决方案大致就是:
- 在缓存失效了以后,我们通过加锁或者队列控制,来控制这个读数据库写缓存的线程数量,比如说对某一个key只允许一个线程查询数据和写缓存。
- 在往redis里存数据时,过期时间并不是定死,而是随机的,这样也可以避免在同一时间内大量的key同时失效的问题发生
总结:一般都会是使用第二种方式,因为第一种方式等于是保证了线程安全而牺牲了性能,毕竟加了锁,在高并发环境下的话,性能也是要考虑的一个方面,还不如第二种方式造成的问题小。
# 17.缓存穿透
原因:
- Redis中大面积出现未命中
- 出现非正常URL访问
解决方案:最简单粗暴的方法如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们就把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
**布隆过滤器(Bloom Filter)**这个也能很好的预防缓存穿透的发生,就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查DB刷新KV再return
# 18.
# Elasticsearch
# 1.为什么要用Elasticsearch
# 2.简述一下检索流程
就是我们在做全文检索的时候,肯定要先输入一个关键词,然后我们会对到后台提交以后,我们会对这个关键词用分词,然后用这个 es 他的倒排索引嘛,会事先通过全局的一个映射文档建立好这个索引,然后这些数据呢就会都存在这个es不同的分片上, 然后es里面会有一个主节点,就是master节点,会有数据节点。然后通过分词分出来的这些词然后去匹配,找到他是属于哪个分片上的,然后返回相应的结果。然后里面就是有这个记录的总条数啊,命中数,热度啊这些信息。
# 3.Elasticsearch 的 Master 节点的选举机制有哪些?
就是说,es 集群,就是只能而且必须有一个 master 节点,那如果出现多个 master 节点这种现象的话,就会有脑裂这种现象。为了避免这种情况,就必须保证选举出 ,这个 master 节点被多数的这个节点认可。我们处理方式就是在es 的那个配置文件中设置最小的,minimum_master_nodes:2 的这么一个配置
# 4.elasticsearch 的倒排索引是什么
我对他的理解大概就是,传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。