当前位置: 首页 > 科技观察

Redis面试你必须知道的3个问题!

时间:2023-03-12 11:32:43 科技观察

最近没看Redis,现在回来复习一下,现在就从Redis的三大缓存开始探究到底有多深浅(^▽^)知识的启蒙!是时候执行真正的技术了。(哔哔哔....)铁子,看在二哈辛苦的份上,如果您觉得本文对您有帮助,请动动您的小手,用爱心推荐一下?(^_-)哟。下面开始我们的Redis三大缓存问题之旅。乘坐二哈小宇宙飞船,游览少女峰。Redis缓存中有3个必须知道的概念:缓存穿透、缓存击穿、缓存雪崩。缓存穿透什么是缓存穿透?意思是当用户正在查询一条数据,但是此时数据库和缓存中都没有关于这条数据的任何记录,如果在缓存中找不到这条数据,就会将这条数据发送到缓存中。数据库请求获取数据。当它拿不到数据的时候,就会不停地查询数据库,这样会给数据库访问带来很大的压力。比如用户查询一个id=-1的商品信息时,一般数据库id值是从1开始自增的,显然数据库中没有这个信息。当没有信息返回时,会一直查询数据库,给当前数据库造成很大的访问压力。这时候,我们就得想一想,怎么解决这个问题呢?o(╥﹏╥)o一般我们可以想到从缓存入手,认为如果我们给缓存设置一个信息,如果当前数据库不存在,缓存为一个空对象,返回给用户。^_^是的,这是一个解决方案,也就是我们常说的缓存空对象(代码容易维护,但效果不是很好)。Redis也给我们提供了一个解决方案,就是Bloomfilter(代码维护比较复杂,但是效果还是不错的)。接下来,二哈先解释一下这两种解决方案:缓存空对象,什么是缓存空对象,二哈!不用担心,缓存一个空对象意味着发送了一个请求。如果此时请求要查询的相关信息在缓存或数据库中不存在,则数据库会返回一个空对象,并将该空对象与请求相关联。保存在缓存中,下次请求来的时候,此时缓存命中,直接从缓存中返回空对象,可以减轻访问数据库的压力,提高当前数据库的访问性能.接下来我们可以看下面的流程~这个时候我们会问~,如果大量不存在的请求过来,那么这个时候缓存会缓存很多空对象~~~没错!这也是使用缓存的空对象带来的问题:如果时间长了,缓存中就会有大量的空对象,不仅会占用大量的内存空间,还会浪费很多资源!.那么有没有办法解决这个问题呢?我们想一想:我们是不是可以在一段时间后清理这些对象呢~嗯,没错!想着Redis有没有给我们提供关于过期时间的命令(^▽^),让我们设置空对象的时间,顺便设置一个过期时间,这个问题就可以解决了!昵称外可以关注公众号Java技术栈在后台回复福利领取我整理的最新面试题。setexkeysecondsvaluele:设置键值对并指定过期时间(s)直接调用Java中的API操作:redisCache.put(Integer.toString(id),null,60)//过期时间为60s布隆过滤器是'Bloomfilter一个过滤器,它过滤东西!哦,你真聪明,是的,它是用来过滤东西的,它是一个基于概率的数据结构,主要是用love来判断一个元素当前是否在集合中,而且运行速度很快。我们也可以简单的理解为一种不太精确的集合结构(集合有去重的作用)。但是有一个小问题:当你用它的contains方法判断一个对象是否存在时,它可能会误判。也就是说,Bloomfilter并不是特别不准确,但是只要参数设置合理,它的准确度是可以控制得比较准确的,不会有小概率的误判(这个可以接受~)。当布隆过滤器说一个值存在时,它可能不存在;当它说没有时,它肯定没有。千大有一个典型的例子:比如它说不认识你,它肯定不认识你;它与它认识的人中的某个面孔相似(某些熟悉的面孔的系数组合),因此它误判它以前见过你。在上面的使用场景中,布隆过滤器可以准确的过滤掉看过的内容,没看过的新内容,它也会过滤掉极小的一部分(误判),但是绝大部分的新内容可以准确识别。这样就可以完全保证向用户推荐的内容是不重复的。说了这么久,Bloomfilter有什么特点:有什么特点吗?来我一一吹给你(吹到怀疑人生(≧?≦)?)一个非常大的二进制位数组(数组中只有0和1)有几个哈希函数(HashFunction)分别是在空间效率和查询效率上非常高。布隆过滤器没有提供删除方法,代码维护难度大。每个布隆过滤器对应一个Redis数据结构,它是一个大的位数组和几个不同的无偏哈希函数。所谓无偏,就是可以比较统一地计算元素的哈希值。具体可以参考这篇文章:Bloomfilter有什么用?.在Bloomfilter中添加一个key时,会使用多个hash函数对key进行hash得到一个整数索引值,然后对bit数组的长度进行取模运算得到一个位置。每个哈希函数都会计算出不同的位置。然后将位数组的这些位置都置为1,完成加法运算。(每个key通过几个hash函数映射到一个巨大的位数组,映射成功后,位数组上对应的位置会变为1。)那么布隆过滤器为什么会有误报率呢?误判?没有摔跤就没有生活,只要锄头挥得好,还是可以挖的。(咳咳误导。。。)其实它会误判如下情况:当key1和key2映射到位数组的位置为1时,假设此时来了一个key3,需要检查是否它在里面,恰好key3对应的位置也映射到了它,那么Bloomfilter就会认为它存在,这时候就会出现误判(因为显然key3不存在)。O(∩_∩)O哈哈~,这时候你会问:如何提高布隆过滤器的准确率?要想提高Bloomfilter的精度,就要说说影响它的三个重要因素:哈希函数的好坏存储空间的大小哈希函数的个数哈希函数的设计也是很重要的问题,对于一个好的散列函数可以大大降低布隆过滤器的误报率。(这就好比一个优秀的配件之所以能运行的这么流畅,是因为它的内部设计得当。)同时,对于一个布隆过滤器来说,如果它的位数组比较大,那么哈希函数映射到的每个key的位置将变得更稀疏和更不紧凑,这将有助于提高布隆过滤器的准确性。同时,对于一个Bloomfilter来说,如果key通过很多hash函数进行映射,那么bit数组上会有很多位置带有符号,这样用户在查询的时候,通过Bloomfilter查找的时候,误判率就会也相应减少。关于它的内部原理,有兴趣的同学可以看看Bloomfiltering的数学知识,里面有它的设计算法和数学知识。(其实挺简单的~)缓存击穿缓存击穿是指一个经常被查询,经常被用户关心,用户非常喜欢的key(^▽^),类似于“常客”或者一个经常过时的钥匙。被访问。推荐阅读:三大缓存问题及解决方案。但是此时如果缓存过期时间过期key过期或者是冷门key,此时会突然出现大量与这个key相关的访问请求,会导致大并发请求直接穿透缓存并请求数据库。数据库访问压力增加。总结一下:缓存崩溃的原因有两个。(1)大量用户突然请求一个“冷门”密钥。(2)一个“热”键在缓存中刚刚过期,此时有大量用户前来访问。对于缓存击穿的问题:我们常见的解决方法是加锁。当key过期后,当key要查询数据库的时候加锁。此时只能使用第一个请求查询数据库,然后将从数据库中查询到的值存入缓存。对于其余相同的key,可以直接从缓存中获取。如果我们在单机环境下:只用普通锁(如:Lock、Synchronized等),在分布式环境下,我们可以使用分布式锁,如:基于数据库、Redis或zookeeper的分布式锁。缓存雪崩缓存雪崩是指在一定时间内,集中式缓存过期失效。如果这段时间内有大量的请求,查询数据量巨大,所有的请求都会到达存储层,对存储层的调用会急剧增加。造成数据库压力过大甚至宕机。原因:Redis突然宕机,大部分数据失效。举个例子来理解吧:比如我们基本都体验过购物狂欢节。假设商家在23:00-24:00举行商品断层促销活动。程序小哥在设计的时候,在23:00把商户的碎片化商品放入缓存,通过redis的expire设置过期时间为1小时。这段时间,很多用户浏览这些商品信息,购买等。但是,正好在24:00,仍然有很多用户在访问这些产品。这时候对这些产品的访问就会落在数据库上,导致数据库承受巨大的压力。直接停机(结束)。产品不失效时是这样的:缓存GG(失效)时是这样的:缓存雪崩有以下解决方案:(1)redis高可用Redis可能挂了,多加几个redis实例,(一主多从或者多主多从),这样一个挂了之后,其他的还能继续工作,其实就是搭建了一个集群。(2)限流降级缓存过期后,通过锁或队列来控制读取数据库和写入缓存的线程数。对于某个key,只允许一个线程查询数据并写入缓存,其他线程等待。(3)数据预热数据加热的意思就是在正式部署之前,我先先访问可能的数据,这样一些可能会被大量访问的数据会被加载到缓存中。在即将发生大并发访问之前手动触发不同key的加载和缓存。(4)不同的过期时间设置不同的过期时间,让缓存失效时间点尽量统一。