所有面试题都是本人亲自面试的总结复盘,答案是百度以及结合自己的回答不唯一。
面试题:
1. 你了解的集合有那些,并且他们的区别是什么?
答:常用的集合 线程安全有 Vector,HashTable, StringBuffer
线程不安全 HashMap,TreeMap,HashSet,ArrayList,LinkedList
ArrayList和LinkedList的区别:
(1) ArrayList基于数组实现,LinkedList基于链表实现
(2)ArryList适合随机查找,LinkedList适合增删,时间复杂度不同
(3)ArrayList和LinkedList都是基于List接⼝实现的,LinkedList还实现了Deque接⼝,可以当做 队列使⽤
2. 你对Hashmap的了解有多少?
答: HashMap通过hashcode对其内容进行快速查找,HashMap 是一种存取高效但不保证有序的常用容器。
3. 在你的项目中使用Redis遇到了哪些问题,怎么解决的
谈一谈缓存穿透、缓存击穿和缓存雪崩,以及解决办法?
-
缓存穿透
问题:大量并发查询不存在的 KEY,在缓存和数据库中都不存在,同时给缓存和数据库带来压力。
原因:一般而言,缓存穿透有 2 种可能性:业务数据被误删,导致缓存和数据库中都没有数据。恶意进行 ddos 攻击。
分析:为什么会多次透传呢?不存在 一直为空,需要注意让缓存能够区分KEY不存在和查询到一个空值。
解决办法:缓存空值的 KEY,这样第一次不存在也会被加载会记录,下次拿到有这个略(异步线程负责维护缓存的数据,定期或根据条件触发更新),这样就不会触发更新。 -
缓存击穿
问题:某个 KEY 失效的时候,正好有大量并发请求访问这个KEY。
分析:跟穿透其实很像,属于比较偶然的。
解决办法:KEY 的更新操作添加全局互斥锁。完全以缓存为准,使用延迟异步加载的策将流量压力传导到数据库上,导致数据库压力过大甚至宕机。 -
缓存雪崩
问题:当某一时刻发生大规模的缓存失效的情况,导致大量的请求无法获取数据,从而KEY。Bloom 过滤或 RoaingBitmap 判断 KEY 是否存在,如果布隆过滤器中没有查到这个数据,就不去数据库中查。在处理请求前增加恶意请求检查,如果检测到是恶意攻击,则拒绝进行服务。完全以缓存为准,使用延迟异步加载的策略(异步线程负责维护缓存的数据,定期或根据条件触发更新),这样就不会触发更新。
原因:一般而言,缓存雪崩有 2 种可能性:大量的数据同一个时间失效:比如业务关系强相关的数据要求同时失效 Redis 宕机
分析:一般来说,由于更新策略、或者数据热点、缓存服务宕机等原因,可能会导致缓存数据同一个时间点大规模不可用,或者都更新。所以,需要我们的更新策略要在时间上合适,数据要均匀分享,缓存服务器要多台高可用。
解决办法:更新策略在时间上做到比较平均。如果数据需要同一时间失效,可以给这批数据加上一些随机值,使得这批数据不要在同一个时间过期,降低数据库的压力。使用的热数据尽量分散到不同的机器上。多台机器做主从复制或者多副本,实现高可用。做好主从的部署,当主节点挂掉后,能快速的使用从结点顶上。实现熔断限流机制,对系统进行负载能力控制。对于非核心功能的业务,拒绝其请求,只允许核心功能业务访问数据库获取数据。服务降价:提供默认返回值,或简单的提示信息。
4. 谈谈在做项目过程中,你是如何进行SQL优化的
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
(1)尽量选择较小的
(3)select子句中避免使用‘*’
(4). 如果排序字段没有用到索引,就尽量少排序
(5)选择最有效的表名顺序,from字句中写在最后的表是基础表,将被最先处理,在from子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。
5. 项目组有多少人
项目经理(PM)1人、产品(PD)2人、界面设计(UI)2人、前端 3人、Java后台(DE)6人,其中1人是开发组长、测试(QA)2人、运维(SRE)1人
6. 用户访问量
用户总量 几万+,日活 3000+,月活 12W+,一个月PV 30W+,并发量 500+
7. 你们项目的微服务是怎么拆分的,拆分了多少?
根据功能模块进行拆分,有多少功能模块就基本上拆出来多少个服务。
8. 如何解决并发问题的?
开发层面:微服务架构、缓存(Redis)、异步(MQ)、队排好(限流和削峰)
部署层面:集群(高可用)和负载均衡----Nginx、Gateway、Feign
硬件层面:CPU性能、硬盘(SSD)性能、内存大小
网络层面:增加网络带宽、网络加速器
9.你们项目中有没有用到什么设计模式?
1) 单例模式。 单例模式是一种常用的软件设计模式。 在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统 资源。 应用场景:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
2) 工厂模式。 工厂模式主要是为创建对象提供了接口。
应用场景如下:
a、 在编码时不能预见需要创建哪种类的实例。
b、 系统不应依赖于产品类实例如何被创建、组合和表达的细节。
3)观察者模式。 观察者模式又被称作发布/订阅模式,定义了对象间一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
应用场景如下:
a、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
b、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
10.在做这个项目的时候你碰到了哪些问题?你是怎么解决的?
(1)开发SpringBoot接口出现客户端和服务端不同步,导致接口无法测试,产生的原因沟通不畅。
(2)订单提交时由于本地bug或者意外故障导致用户钱支付了但是订单不成功,采用对账方式来解决。
(3)项目中用到了曾经没有用过的技术,解决方式:用自己的私人时间主动学习
(4)系统运行环境问题,有些问题是在开发环境下OK,但是到了测试环境就问题,比如说系统文件路径问题、导出报表中的中文问题(报表采用POI),需要在系统jdk 中添加相应的中文字体才能解决;
11.笔试(部分)有点忘记题目了
int 和 integer的区别:
int不能表示空值,integer可以将null值作为有效值, int是基本数据类型,integer是包装类
String 和 stringbuffer 和stringbuilder的区别:
可变性string不可变一旦创建就不能修改
线程安全性
string是字符串常量,其他是字符串变量
sql 优化题, 前端vue生命周期
12 多线程
多线程的创建方式的话,是有三种的,一种是直接继承Thread类、第二种是实现Runable接口,第三种嘛就是使用Callable和Future创建线程,其实还有一种的,就是使用线程池的方式来创建线程。
保证线程安全的话就是加锁嘛,像Synchronized、CAS无锁操作这一些都是可以用来保证线程安全的
new新建状态 , runnable(可运行状态) blocked阻塞状态 , waiting等待状态, terminated终止状态