文中提到了Redis,相信大家在面试或者实际开发过程中对缓存雪崩、击穿、击穿并不陌生,即使没有遇到过,也一定要听一听,然而,什么是三者的区别,我们应该如何防止这种情况的发生呢?我们已经邀请了下一位受害者。采访一开始,一个大肚皮,穿着格子衬衫的中年男人,拿着一台满是划痕的Mac走到了你面前。看他光秃秃的头发,他想他一定是尼玛的顶级建筑师了!但我们有诗有书,精神饱满,无一不空虚。小伙子,我看到你的简历上写的是Redis,所以让我们开门见山地解决几个常见的大问题。你了解Redis雪崩吗?帅气的面试官你好,我了解到目前的电商首页和热点数据都会做缓存,一般都是定时任务刷新缓存,或者找不到之后再更新。定时任务刷新有问题。举个简单的例子:假设所有首页的key过期时间都是12小时,中午12点刷新,我零点有秒杀活动,大量用户涌入。假设当时每秒有6000个请求,缓存每秒可以容纳每5000个请求,但是此时缓存中的所有Key都是无效的。这时候1秒6000个请求全部落入数据库,数据库必然会失败,就会报警。在真实情况下,DBA可能会挂掉而没有响应。这时候如果没有专门的解决方案来处理这个故障,DBA很着急,重启了数据库,但是数据库马上就被新的流量杀死了。这就是我理解的缓存雪崩。特意看了下自己做过的项目,感觉这么大的QPS直接上DB是不行的,但是没有慢SQL和分库。大表和子表可能还是能搞定,但还是要用。Redis的差距还是很大的。同时,大面积失效。那一刻,Redis就跟什么都没有了一样。那么这种量级的请求直接打到数据库几乎是灾难性的。仔细想想,如果hang的是一个用户服务库,其他依赖它的库的接口几乎都会报错。如果没有熔断之类的策略,基本瞬间挂掉。不管你怎么重启用户,都会挂掉。当你可以重新启动时,用户已经进入睡眠状态。并对您的产品失去信心,多么垃圾的产品。面试官摸了摸头发,嗯,还不错,请问这种情况怎么处理?你如何解决?很容易处理缓存雪崩。在Redis中批量存储数据时,将每个Key的过期时间设置为随机加一个值即可,这样可以保证数据不会同时大面积失效。相信Redis还是能顶住这个流量的。setRedis(Key,value,time+Math.random()*10000);如果Redis部署在集群中,将热点数据均匀分布在不同的Redis库中,也可以避免所有失败的问题,但是我是在生产环境中。在运行集群时,单个服务对应单个Redis分片,这样是为了方便数据管理,但也有可能会失败的缺点。随机故障时间是一个很好的策略。或者设置热点数据永不过期,有更新操作就更新缓存(比如运维更新首页产品,那么你刷新缓存就完事了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。你了解缓存穿透和击穿吗?能说说它们和avalanche的区别吗?嗯,对,先说缓存穿透。缓存穿透是指不在缓存或数据库中的数据,用户不断发起请求,我们数据库的id是从1开始自增的,比如id值为-1的数据或者id为-1的数据特别大,不存在。这时候用户很可能就是攻击者,攻击会对数据库造成过大的压力,严重的会破坏数据库。较小的单机系统基本上可以用postman来干掉。比如我自己买的阿里云服务你不校验参数,数据库id大于0,我一直用小于0的参数,拜托,每次绕过Redis直接打数据库,还有找不到数据库。每次都是这样,并发高的时候很容易崩溃。至于缓存击穿,这个和缓存雪崩有点类似,但又有点不同。缓存雪崩是由于大面积的缓存失效,导致DB崩溃。缓存击穿的区别在于,缓存击穿指的是某个key非常热点不断承载着大并发,大并发都集中在访问这个点上。当key此刻失效,持续的大并发就会突破缓存,直接去请求数据库,就像在一个完好无损的桶里面挖了一个洞。面试官露出欣慰的眼神,那么缓存穿透他们是怎么解决的呢?我会在接口层添加校验,比如用户认证校验,参数校验,非法参数直接code返回,比如:id作为基础校验校验,直接拦截id<=0等。这里就是我们在开发程序的时候一定要有一颗“不信任”的心,就是不要相信任何调用者。比如你提供一个API接口,你有这些参数,那我觉得作为被调用者,任何可能的参数都应该考虑和验证,因为你不信任调用你的人,你不知道什么他会传递给你的参数。举个简单的例子,你的接口是逐页查询,但是你没有对逐页参数的大小进行限制。如果调用者一次性检查Integer.MAX_VALUE,你会花几秒钟的时间来请求。是不是刚挂了?如果是公司同事打来的还大不了,但如果是黑客或者竞争对手呢?如果你在双十一那天调用你的接口会发生什么,我就不用你说了。这是上届Leader跟我说的,我想大家应该都明白。从缓存中获取不到的数据,在数据库中获取不到。这时候也可以把Key对应的Value对写成null,位置不对,稍后再试。具体产品使用什么样的值,或者看具体场景,缓存的有效时间可以设置短点,比如30秒(设置太长会导致正常情况下无法使用).这样可以防止攻击用户重复使用同一个id进行暴力攻击,但是要知道普通用户不会在一秒内发起那么多请求。还记得网关层Nginx有配置项,允许运维大大屏蔽所有每秒访问次数超过单个IP阈值的IP。您还有其他解决方案吗?我记得Redis还有一个高级的布隆过滤器(BloomFilter),也可以很好的防止缓存穿透。它的原理也很简单,就是利用高效的数据结构和算法可以快速判断你的key是否存在于数据库中。如果不存在,您可以将其退回。如果存在,可以查看DB,刷新KV返回。那么另一位朋友说如果黑客有多个IP同时发起攻击怎么办?这个我一直想不通,但是一般级别的黑客没有那么多的bot,普通级别的Redis集群可以抵挡。有了这种级别的访问权限,我认为小公司不会感兴趣。系统的高可用做的不错,集群还是很能干的。如果缓存坏了,设置热点数据永不过期。或者加个互斥锁就搞定了。作为暖男,我一定会为你准备好代码的。采访结束了。还不错。你这三点都回答的很好。今天时间不早,采访先到这里。明天再来,继续向大家请教Redis集群高可用、主从同步、哨兵等知识点。晕,居然还有下一轮面试!(强推下期铺垫哈哈)不过offer还是要舔一下,嗯,好帅的面试官。能回答的这么全面这么详细,还是忍不住点赞(提示点赞,每次看都不喜欢,你是想白嫖我吗?你是好人还是不好,但我喜欢)总而言之,让我们玩得开心。拜托,不要拿面试开玩笑。本文简单介绍一下,Redis的雪崩、击穿、穿透其实大同小异,但也有一些区别。其实这是面试问缓存的必问问题。不要混淆三者。因为缓存雪崩、穿透、击穿是缓存最大的问题,或者不出现,一旦出现就是致命的问题,所以面试官肯定会问你的。大家一定要明白它是怎么发生的,怎么避免,发生了之后怎么挽救。你可能知道得很深,但你根本不能忽视它。有时候面试不一定是对知识的拷问,也许这是对你态度的一种折磨。如果你头脑清醒,然后知道为什么和为什么,那就太好了,你知道如何预防它,那就来工作吧。最后,暖男,继续给大家做一个技术小总结:一般为了避免以上情况的发生,我们从三个时间段来分析:事前:Redis高可用,主从+哨兵,Redis集群,避免全面崩溃。在作:本地ehcache缓存+Hystrix限流+降级,避免MySQL被杀。之后:Redis持久化RDB+AOF。一旦重新启动,它会自动从磁盘加载数据以快速恢复缓存数据。以上几点我都会在挂机系列的Redis篇中讲到。这个月应该可以。Redis更新了,限流组件,可以设置每秒的请求数,多少个可以通过组件,剩下失败的请求,怎么办??去降级!你可以返回一些默认值,或者友情提示,或者空白值。好处:数据库永不消亡,限流组件保证每秒只能通过多少请求。只要数据库不死,也就是说对于用户来说,3/5的请求是可以处理的。只要能处理3/5的请求,就说明你的系统没死。对于用户来说,可能页面点击几次刷新不了,但是多点击几次可以刷新一次。这在目前主流的互联网公司中最为常见。你是不是很好奇,某位明星发生了什么事,你发现不管怎么去微博,界面都是空白的,但是有的人直接又进去了。你多刷几下就出来了,现在知道了,那是降级,牺牲一部分用户的体验来换取服务器的安全,可以吗?
