- 每日小结
本栏目Java开发岗高频面试题主要出自以下各技术栈:Java基础知识
、集合容器
、并发编程
、JVM
、Spring全家桶
、MyBatis等ORMapping框架
、MySQL数据库
、Redis缓存
、RabbitMQ消息队列
、Linux操作技巧
等。
===============================================================================
缓存穿透
:指缓存和数据库中都没有的数据
,导致所有的请求都打到数据库上,然后数据库还查不到(如null
),没法写缓存,造成数据库短时间线程数被打满而导致其他服务阻塞,最终导致线上服务不可用。此时缓存就好像被穿透
了一样,起不到任何作用。
当然,使用缓存难免会有穿透的发生。
-
缓存容量有限,不可能去缓存所有数据,查询到未被缓存的数据就会发生穿透是正常情况。
-
互联网业务的数据访问模型一般是遵循
二八原则
的,即 20% 的数据为热点数据,80% 的数据是非热点不被常访问的数据。既然缓存容量有限,且20%的数据为热点数据,那我们可以利用有限的容量去缓存那 20% 的数据
来保护我们的系统,至于80%非热点不常用的数据发生穿透就穿透了,数据库吃得住。
其实,只有大量穿透请求超过了我们后端系统的承受范围
,比如恶意的穿透攻击,这样的穿透才有可能把我们的系统给干崩。
那我们怎样来解决这种缓存穿透问题呢?
- 接口参数校验:
防君子不防小人。在参数校验层加上参数合法性校验,如查询订单ID为20位随机值,正则核对一下ID长度是否规范
,不规范的直接过滤掉。
- 设置空值:
当访问缓存和DB都没有查询到值时,该key我们当做是恶意参数来看,可以将该key的空值写进缓存,设置较短的过期时间
。
但是如果有大量的获取并不存在数据的穿透请求的话如恶意攻击,则会浪费缓存空间,如果这种null值过量的话,还会淘汰掉本身缓存存在的数据,这就会使我们的缓存命中率下降
。
因此在使用设置空值方案时,我们要做好监控,预防缓存空间被过多null值占领造成的缓存空间浪费,如果这种数据量太大,就不再建议使用,那就使用另一种方案,即布隆过滤器
。
- 布隆过滤器:
布隆过滤器在查询缓存之前起到初步过滤作用,布隆过滤器存储所有可能访问的 key
,将不存在的 key 直接过滤,存在的 key 再进一步查询缓存和数据库。
布隆过滤器的特点是判断不存在的,则一定不存在
;判断存在的,大概率存在,但也有小概率不存在
。并且这个概率是可控的,根据具体需求,我们可以让这个概率小幅降低或变高。
布隆过滤器由一个 bitSet 和 一组 Hash 函数(算法)组成,是一种空间效率极高的概率型算法和数据结构,通过二进制来进行数据存储。在初始化时,bitSet 的每一位被初始化为0。
当数据加入布隆过滤器集合时,流程如下
:
-
经过K个哈希函数计算该数据,返回K个计算出的hash值
-
这些K个hash值映射到对应的K个二进制的数组下标
-
将K个下标对应的二进制数据改为1。
布隆过滤器查询一个key是否在集合中,流程如下
:
-
经过K个哈希函数计算该数据,对应计算出的K个hash值
-
经过hash值找到对应的二进制的数组下标
-
如果存在其中一处位置的二进制数据是0,那么该数据不存在。若是都是1,该数据存在集合中(但由于存在Hash碰撞,
判断数据存在时
可能存在误判)。
布隆过滤器的优缺点
优势
-
因为存储的是二进制数据,因此占用的空间很小;
-
它的插入和查询速度是很是快的,时间复杂度是O(K),能够联想一下HashMap的过程;
-
保密性很好,由于自己不存储任何原始数据,只有二进制数据
缺点
1、存在误判
添加数据是经过计算数据的hash值,hash是存在碰撞的,也就是说,存在两个不一样的数据计算获得相同的hash值。
例如图中的你好
和hello
,假如最终算出hash值相同,那么他们会将同一个下标的二进制数据改成1。因此也无法确定key为你好
和hello
是否存在。
2、删除困难
如上,你好
和hello
的hash值相同,对应的数组下标也是同样的。如果想删除你好
,即将坐标值改为0,可能会影响到其他key,比如是否会连hello
都一块儿删了之类的。
课间休息,来看看群里铁子的组长小姐姐??
作者:W.M.H
======================================================================================
缓存击穿
:指缓存中没有但数据库中有的数据(一般是热点数据缓存时间到期
),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去查,引起数据库压力瞬间增大
,线上系统卡住。
解决方案:
1、加互斥锁(mutex key)
。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。
互斥锁
缓存击穿后,多个线程会同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。
static Lock reenLock = new ReentrantLock();
public List getData04() throws InterruptedException {
List result = new ArrayList();
// 从缓存读取数据
result = getDataFromCache();
if (result.isEmpty()) {
if (reenLock.tryLock()) {
try {
System.out.println(“拿到锁了,从DB获取数据库后写入缓存”);
// 从数据库查询数据
result = getDataFromDB();
// 将查询到的数据写入缓存
setDataToCache(result);
} finally {
reenLock.unlock();// 释放锁
}
} else {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/3bd8f0b361382253740269ab06a2bb0b.jpeg)
Ending
Tip:由于文章篇幅有限制,下面还有20个关于MySQL的问题,我都复盘整理成一份pdf文档了,后面的内容我就把剩下的问题的目录展示给大家看一下
如果觉得有帮助不妨【转发+点赞+关注】支持我,后续会为大家带来更多的技术类文章以及学习类文章!(阿里对MySQL底层实现以及索引实现问的很多)
吃透后这份pdf,你同样可以跟面试官侃侃而谈MySQL。其实像阿里p7岗位的需求也没那么难(但也不简单),扎实的Java基础+无短板知识面+对某几个开源技术有深度学习+阅读过源码+算法刷题,这一套下来p7岗差不多没什么问题,还是希望大家都能拿到高薪offer吧。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
13442978894)]
吃透后这份pdf,你同样可以跟面试官侃侃而谈MySQL。其实像阿里p7岗位的需求也没那么难(但也不简单),扎实的Java基础+无短板知识面+对某几个开源技术有深度学习+阅读过源码+算法刷题,这一套下来p7岗差不多没什么问题,还是希望大家都能拿到高薪offer吧。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!