一、Redis
1. 使用场景
(1)Redis的数据持久化策略有哪些
RDB:全称Redis Database Backup file(Redis数据备份文件),也被叫作Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
RDB的执行原理?
bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。fork采用的是copy-on-write技术:
当主进程执行读操作时,访问共享内存;
当主进程执行写操作时,则会拷贝一份数据,执行写操作。
AOF
AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。
(2)什么是缓存穿透,怎么解决
缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库
解决方案一:缓存空数据,查询返回的数据为空,扔把这个空结果进行缓存。优点:简单;缺点:消耗内存,可能会发生不一致的问题
解决方案二:布隆过滤器
(3)什么是布隆过滤器
误判率:数组越小误判率越大,数组越大误判率就越小,但是同时带来了更多的内存消耗。
优点:内存占用较少,没有多余key;缺点:实现复杂,存在误判
(4)什么是缓存击穿,怎么解决
缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这个时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
解决方案一:互斥锁,强一致,性能差
解决方案二:逻辑过期,高可用,性能优,不能保证数据绝对一致
(5)什么是缓存雪崩,怎么解决
缓存雪崩实质同一时间段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
(6)redis双写一致性问题(redis作为缓存,mysql的数据如何与redis进行同步)
双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
先删除缓存,还是先修改数据库?
(7)Redis分布式锁如何实现
(8)Redis实现分布式锁如何合理的控制锁的有效时长
(9)Redis的数据过期策略有哪些
惰性删除:设置key过期时间后,我们不去管它,当需要该key时,我们再检查其是否过期,如果过期,我们就删掉它,反之返回该key
优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
缺点:对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放。
定期删除:每隔一段时间,我们就会对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行删除,并删除其中的过期key)。
(10)Redis的数据淘汰策略有哪些
数据的淘汰策略:当Redis中的内存不够用时,此时再向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则则被称之为内存的淘汰策略。
2. 面试题
(1)Redis集群有哪些方案
在Redis中中提供的集群方案总共有三种:
- 主从复制
- 哨兵模式
- 分片集群
(2)什么是Redis主从同步
单结点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。
(3)哨兵的作用
Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下:
(4)Redis集群(哨兵模式)脑裂,该怎么解决?
(5)你们使用Redis是单点还是集群?哪种集群
(6)Redis分片集群中数据是怎么存储和读取的
主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:
- 海量数据存储问题
- 高并发写的问题
使用分片集群可以解决上述问题,分片集群特征:
- 集群中有多个master,每个master保存不同数据
- 每个master都可以有多个slave节点
- master之间通过ping监测彼此健康状态
- 客户端请求可以访问集群任意节点,最终都会转发到正确节点
(6)怎么保证Redis的高并发高可用
(7)你们用过Redis的事务吗?事务的命令有哪些?
(8)Redis是单线程的,但是为什么还那么快?
二、MySQL
1. SQL优化
(1)在MySQL,如何定位慢查询?
- 聚合查询
- 多表查询
- 表数据量过大查询
- 深度分页查询
表象:页面加载过慢、接口压测响应时间过长(超过1s)
方案一:开源工具
- 调试工具:Arthas
- 运维工具:Prometheus、Skywalking
方案二:MySQL自带慢日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。如果要开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
配置完毕之后,通过以下命令重新启动MySQL服务器进行测试,查看慢日志文件中记录的信息:/var/lib/mysql/localhost-slow.log
(2)一个SQL语句执行很慢,如何分析
可以采用EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息
(3)了解过索引吗?什么是索引?
索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构(B+树),这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
(4)什么是聚簇索引,什么是非聚簇索引?
什么是聚集索引,什么是二级索引(非聚集索引),什么是回表?
在二级索引中找到name字段对应的主键值,然后再根据主键值到聚集索引中查找对应行数据。
(5)什么是覆盖索引?
(6)MySQL超大分页处理
在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。
优化思路:一般分页查询时,通过创建覆盖索引能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。
(7)索引创建原则有哪些?
- 主键索引
- 唯一索引
- 根据业务创建的索引(复合索引)
①针对于数据量较大,且查询比较频繁的表建立索引 -> 单表超过10万条数据(增加用户体验)
②针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
③尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高
④如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
⑤尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
⑥要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
⑦如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。
(8)什么情况下索引会失效?
(9)谈谈你对sql的优化经验?
- 表的设计优化
- 索引优化
- SQL语句优化
- 主从复制、读写分离
- 分库分表
2. 其他面试题
(1)事务的特性是什么?可以详细说一下吗?
事务是一组操作的集合,它是越高不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么成功,要么同时失败。
ACID是什么?
(2)并发事务带来哪些问题?怎么解决这些问题呢?MySQL的默认隔离级别是?
并发事务问题:脏读、不可重复读、幻读
隔离级别:读未提交、读已提交、可重复读、串行化
解决方案:对事务进行隔离
注意:事务隔离级别越高,数据越安全,但是性能越低。
MySQL默认的隔离级别是Repeatable Read(可重复读)
(3)undo log和redo log的区别
(4)解释一下MVCC -> 事务隔离性
全称Multi-Version Concurrency Control,多版本并行控制。指维护一个数据的多个版本,使得读写操作没有冲突。MVCC的具体实现,主要依赖于数据库记录中的隐式字段、undo log日志、readView读视图。
- 记录中的隐藏字段
- undo log
- undo log版本链
- readview
(5)MySQL主从同步原理
(6)你们项目用过分库分表吗?
拆分策略:垂直拆分、水平拆分
垂直分库:以表为依据,根据业务将不同表拆分到不同库中。
特点:
- ①按业务对数据分级管理、维护、监控、扩展
- ②在高并发下,提高磁盘IO和数据量连接数
垂直分表:以字段为依据,根据字段熟悉将不同字段拆分到不同表中。
拆分规则:
- 把不常用的字段单独放到一张表
- 把text、blob等大字段拆分出来放在附表中
特点:①冷热数据分离;②减少IO过渡争抢,两表互不影响
水平分库:将一个库的数据拆分到多个库中。
水平分表:将一个表的数据拆分到多个表中(可以在同一个库内)。
三、Spring
(1)Spring框架中的单例bean是线程安全的吗?
(2)什么是AOP,你们项目中有没有使用到AOP
AOP基础-CSDN博客
(3)Spring中的事务是如何实现的?
Spring支持编程式事务管理和声明式事务管理两种方式。
(4)Spring中事务失效的场景有哪些?
情况一:异常捕获处理
如果在一个事务方法内部捕获了异常并对其进行了处理,Spring事务管理可能无法感知异常的发生,从而导致事务失效。事务通知只有捕捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉异常,事务通知无法知悉。
情况二:抛出异常
如果抛出的异常不是继承自RuntimeException,Spring默认不会回滚事务。所以,确保抛出的异常继承自RuntimeException或声明在方法签名中。
情况三:非public方法导致的事务失效
情况四:未使用代理对象
Spring的事务管理通常通过代理对象来实现事务的增强,如果直接调用一个带有@Transactional注解的方法而不是通过代理对象调用,事务将不会生效。
情况五:编程式事务管理下,抛出异常未被捕获
在基于编程式事务管理时,如果一个带有@Transactional注解的方法内部发生但未被捕获,在异常传播至事务管理器时,可能导致事务无法回滚。
情况六:运行时异常未被声明
只有在方法声明的检查异常(checked exception)被抛出时,Spring 事务管理器才会触发事务回滚。如果抛出的是运行时异常,且未被显式声明在方法签名中,可能会导致事务未能正确回滚。
情况七:嵌套调用问题
在嵌套调用的情况下,事务的传播机制需要正确设置,否则可能导致外部事务失效或内部事务回滚不受控制。
情况八:多个事务注解嵌套使用
在某个方法上同时使用多个 @Transactional
注解,可能导致事务失效或者事务传播不符合预期。
(5)Spring的bean的生命周期
(6)Spring中的循环引用
什么是Spring的循环依赖?
三级缓存解决循环依赖
Spring解决循环依赖是通过三级缓存,对应的三级缓存如下所示:
一级缓存作用:限制bean在beanFactory中只存一份,即实现singleton scope,解决不了循环依赖
如果要想打破循环依赖,就需要一个中间人的参与,这个中间人就是二级缓存
(7)SpringMVC的执行流程
视图阶段(JSP)
(8)SpringBoot的自动配置原理
(9)Spring框架常见注解(Spring、SpringBoot、SpringMVC)
Spring的常见注解有哪些?
SpringMVC的常见注解有哪些?
SpringBoot常见注解有哪些?
四、MyBatis
(1)MyBatis执行流程
(2)MyBatis是否支持延迟加载?
(3)MyBatis的一级、二级缓存用过吗?
一级缓存
一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Session进行flush或close之后,该Session中的所有Cache就将清空,默认打开一级缓存。
二级缓存
二级缓存是基于namespace和mapper的作用域起作用的,不是依赖于SQL session,默认也是采用PerpetualCache,HashMap存储
注意事项:
- 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)进行了新增、删除操作后,默认该作用域所有select中的缓存将被clear
- 二级缓存需要缓存的数据实现Serializable接口
- 只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
五、SpringCloud
(1)Spring Cloud的5大组件有哪些?
通常情况下:
Eureka/Nacos:注册中心
Ribbon/SpringCloudLoadBalancer:负载均衡
Feign:远程调用
Hystrix/Sentinel:服务熔断
Zuul/Gateway:网关
(2)服务注册和发现是什么意思?Spring Cloud如何实现服务注册发现?
常见的注册中心:Eureka、Nacos、Zookeeper
(3)你们项目负载均衡是如何实现的?
(4)什么是服务雪崩,怎么解决这个问题?
服务降级:是服务自我保护的一种方式,或者保护下游服务的一种方式,用于确保服务不会受请求突增影响变得不可用,确保服务不会崩溃
服务熔断:Hystrix熔断机制,用于监控微服务调用情况,默认是关闭的,如果需要开启需要在引导类上添加注解:@EnableCircuitBreaker。如果检测到10秒内请求的失败率超过50%,就触发熔断机制,之后每隔5秒重新尝试请求微服务,如果微服务不能响应,继续走熔断机制。如果微服务可达,则关闭熔断机制,恢复正常请求。
(5)你们的微服务是怎么监控的?
(6)你们项目中有没有做过限流?怎么做的?
为什么要限流?
- 并发的确大(突发流量)
- 防止用户恶意刷接口
限流的实现方式:
- Tomcat:可以设置最大连接数
- Nginx:漏桶算法
- 网关:令牌桶算法
- 自定义拦截器
Nginx限流
- 控制速率(突发流量)
- 控制并发连接数
网关限流
yml配置文件中,微服务路由设置添加局部过滤器RequestRateLimiter
(7)解释一下CAP和BASE
CAP定理
BASE理论
(8)你们采用的是哪种分布式事务解决方案?
(9)分布式服务的接口幂等性如何设计?
(10)你们项目中使用了什么分布式任务调度?
六、RabbitMQ
(1)RabbitMQ如何保证消息不丢失?
(2)RabbitMQ消息的重复消费问题如何解决?
(3)RabbitMQ中死信交换机?(RabbitMQ延迟队列有了解过吗?)
(4)RabbitMQ如果有100万消息堆积在MQ,如何解决(消息堆积怎么解决)
(5)RabbitMQ的高可用机制有了解过吗?
七、Kafka
(1)Kafka是如何保证消息不丢失?
(2)Kafka是如何保证消费的顺序性的?
(3)Kafka的高可用机制有了解过吗?
(4)Kafka数据清理机制了解过吗?
(5)Kafka中实现高性能的设计有了解过吗?
八、Java集合
1. 数据结构
(1)数组
(2)ArrayList源码分析
(3)ArrayList底层的实习原理是什么?
(4)ArrayList list = new ArrayList(10)中的list扩容几次
(5)如何实现数组和List之间的转换
(6)单向链表
(7)双向链表
(8)ArrayList和LinkedList的区别是什么?
(9)二叉树
(10)散列表
(11)HashMap的实现原理
(12)HashMap的put方法的具体流程
(13)讲一讲HashMap的扩容机制
(14)HashMap的寻址算法
(15)HashMap在1.7情况下的多线程死循环问题
九、多线程
(1)线程和进程的区别?
(2)并行和并发有什么区别?
(3)创建线程的方式有哪些?
(4)线程包括哪些状态,状态之间是如何变化的
(5)新建T1、T2、T3三个线程,如何保证它们按顺序进行?
(6)notify()和notifyAll()有什么区别?
(7)在Java中wait和sleep方法的不同?
(8)如何停止一个正在运行的线程?
(9)synchronized关键字的底层原理
(10)你谈谈JMM(Java内存模型)
JMM(Java Memory Model)Java内存模型,定义了共享内存中多线程程序读写操作的行为规范,通过这些规则来规范对内存的读写操作从而保证指令的正确性。
(11)CAS你知道吗?
(12)谈谈你对volatitle的理解
(13)什么是AQS?
全称是AbstractQueuedSynchronizer,即抽象队列同步器。它是构建锁或者其他同步组件的基础框架。
(14)ReentrantLock的实现原理
(15)synchronized和Lock有什么区别?
(16)死锁产生的条件是什么?
(17)谈谈你对ConcurrentHashMap的理解
(18)导致并发程序出现问题的根本原因是什么?(Java程序中怎么保证多线程的执行安全)
Java并发编程的三大特性:原子性、可见性、有序性
(19)说一下线程池的核心参数(线程池的执行原理知道吗)
(20)线程池中有哪些常见的阻塞队列
(21)如何确定核心线程数
(22)线程池的种类有哪些?
(23)为什么不建议用Executors创建线程池
嵩山版Java开发手册-阿里云开发者社区
(24)线程池使用场景(CountDownLatch、Future)
CountDownLatch
(25)如何控制某个方法允许并发访问线程的数量
(26)谈谈你对ThreadLocal的理解
十、JVM
(1)JVM是什么
Java Virtual Machine:Java程序的运行环境(java二进制字节码的运行环境)
(2)JVM由哪些部分组成,运行流程是什么?
(3)什么是程序计数器?
程序计数器:线程私有的,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。
(4)能详细介绍一下Java堆吗?
线程共享的区域:主要用来保存对象实例、数组等,当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
(5)什么是虚拟机栈
Java Virtual machine Stacks(java 虚拟机栈)
每个线程运行时所需要的内存,称为虚拟机栈,先进后出
每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存
每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
(6)能不能解释一下方法区?
(7)你听过直接内存吗?
直接内存:并不属于JVM中的内存结构,不由JVM进行管理。是虚拟机的系统内存,常见于NIO操作时,用于数据缓存区,它分配回收成本较高,但读写性能高,不受JVM内存回收管理。
(8)什么是类加载器,类加载器有哪些?
(7)什么是双亲委派模型?
(8)说一下类装载的执行过程
类从加载到虚拟机中开始,知道卸载为止,它的整个生命周期包括了:加载、验证、解析、初始化、使用和卸载着7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)
(9)对象什么时候可以被垃圾器回收
如果一个对象或多个对象没有任何的引用指向它了,那么这个对象限现在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。
如果要定位什么是垃圾,有两种方式来确定,第一个是引用计数法,第二个是可达性分析算法
(10)JVM垃圾回收算法有哪些?
①标记清除算法;②复制算法;③标记整理算法
(11)说一下JVM中的分代回收
(12)说一下JVM有哪些垃圾回收器?
在JVM中,实现了多种垃圾收集器,包括:①串行垃圾收集器、并行垃圾收集器、CMS(并发)垃圾收集器;④G1垃圾收集器
复制完成,内存得到释放。进入下一轮的新生代回收、并发标记、混合收集
(13)强引用、软引用、弱引用、虚引用的区别
强引用:只有所有GC Roots对象不通过【强引用】引用该对象,该对象才能被垃圾回收
软引用:仅有软引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收
弱引用:仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法释放直接内存。
(14)JVM调优的参数可以在哪里设置参数值
war包部署在tomcat中设置
修改TOMCAT_HOME/bin/catalina.sh文件
jar包部署在启动参数设置
通常在linux系统下直接加参数启动springboot项目
nohup:用于在系统后台不断地运行命令,退出终端不会影响程序的运行
参数 &:让命令在后台执行,终端退出后命令仍旧执行
(15)JVM调优的参数都有哪些?
d对于JVM调优,主要是调整年轻代、老年代、元空间的的内存空间大小及使用的垃圾回收器类型。
Java HotSpot VM Options
设置堆空间大小
虚拟机栈的设置
年轻代中Eden区和两个Survivor区的大小比例
年轻代晋升老年代阈值
设置垃圾回收收集器
(16)说一下JVM调优的工具?
(17)Java内存泄露的排查思路?
1. 通过jmap指令打印它的内存快照dump(Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中)
2. 通过工具,VisualVM去分析dump文件,VisualVM可以加载离离线的dump文件
3. 通过查看堆信息的情况,可以大概定位内存溢出是哪行代码出了问题
(18)CPU飙高排查方案与思路?
十一、设计模式
(1)简单工厂模式
(2)工厂方法模式
(3)抽象工厂模式
(4)策略模式
(5)责任链设计模式
十二、其他
(1)单点登录这块怎么实现?
单点登录的英文名叫作:Single Sign On(简称SSO),只需要登录一次,就可以访问所有信任的应用系统。
(2)权限认证是如何实现的?
后台的管理系统,更注重权限控制,最常见的就是RBAC模型来指导实现权限
RBAC(Role-Based Access Control)基于角色的访问控制
(3)上传数据的安全性你们是怎么控制的?
(4)你负责项目的时候遇到了哪些比较棘手的问题?怎么解决的?
(5)你们项目中日志怎么采集的?
(6)查看日志的命令
(7)生产问题怎么排查?
(8)怎么快速定位系统的瓶颈