Java面试八股文

一、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文件中)
  1. 通过工具,VisualVM去分析dump文件,VisualVM可以加载离离线的dump文件
  1. 通过查看堆信息的情况,可以大概定位内存溢出是哪行代码出了问题

(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)怎么快速定位系统的瓶颈

​​​​​​​

相关推荐
vx_Biye_Design2 分钟前
驾校管理系统-计算机毕业设计源码49777
java·css·vue.js·spring boot·mysql·ajax·mvc
想胖的壮壮10 分钟前
python中的原子操作简介
开发语言·python
爱吃香菜¹11 分钟前
深入理解【 String类】
java·开发语言
六月的雨__15 分钟前
跑腿平台小程序的设计
java·sql·学习·小程序
u01040583622 分钟前
实现Java Web应用的高性能负载均衡方案
java·前端·负载均衡
LeoLei806026 分钟前
新特性之C++17
开发语言·c++
辣香牛肉面32 分钟前
Linux下“/proc”目录的作用
java·linux·服务器
码农超哥同学34 分钟前
Python面试题:如何在 Python 中反转一个字符串?
开发语言·windows·python·面试·编程
skyshandianxia1 小时前
java面试八股之MySQL怎么优化查询语句
java·mysql·面试
不死鸟.亚历山大.狼崽子1 小时前
python库(2):Passlib库
开发语言·python