美文网首页PHPer不孤独
缓存穿透、缓存击穿、缓存雪崩解决方案?

缓存穿透、缓存击穿、缓存雪崩解决方案?

作者: 川川相护 | 来源:发表于2020-08-28 11:46 被阅读0次

    话不多说先上生动的例子:

    我们有个pv上亿的活动页面,页面上好多信息都缓存在redis中,碰巧我们设置的key的过期时间都是12点。在key过期的一瞬间,我有个活动开奖,大量用户涌入该页面,假设当时每秒5000个请求,原本缓存可以扛住每秒4000个请求,但是缓存失效。此时5000个请求全部落到数据库,数据库一下就报警了,此时DBA没反应过来就直接挂了。这个时候如果没有预案,直接重启数据库,新的请求会不断涌进来,数据库立马又被打挂,这就是一种缓存雪崩的表现。

    如果雪崩发生在核心用户服务模块,同一时间大面积失效,redis形同于无,这个数量级的请求直接打到数据库,此时如果没有做熔断降级,所有依赖用户服务的接口几乎都会报错,只要用户请求没有减少,无论怎么重启,都是直接被打挂,等能重启的时候,用户估计早就卸载app了,甚至感叹一句,这什么垃圾产品..

    那我们应该如何应对缓存雪崩的问题?

    1.批量写入redis缓存数据的时候,把每个key的失效时间都加一个随机值,这样可以保证数据不会在同一时间大面积失效。

    setRedis(Key,value,time+Math.random()*1000);

    2.redis集群,将热点数据分布在不同的redis库中

    3.设置热点数据永不过期,有更新操作就更新缓存

    缓存穿透:

    缓存穿透是指缓存和数据库中都没有的数据。例如一个攻击者查询一个不可能在数据库中存在的id值,高频的请求会导致数据库压力过大,严重会打挂数据库。

    穿透

    如果一直用小于0的参数去请求,每次在redis中都查不到,会直接打到数据库,数据库也查不到,此时并发足够高就容易打崩db。

    穿透的解决方案:

    1.布隆过滤器

    利用高效的数据结构和算法快速判断出key是否在数据库中,不存在就return。

    2.接口层对参数进行校验,不合法的参数直接代码过滤return,比如id<=0则直接return

    理论上对服务端来说,前端的所有参数都是不被信任的,我们要考虑到参数的所有可能情况,并作出合理校验。

    在缓存和数据库中都没有查到的数据,可以缓存一个flag,但是缓存时间不应设置过长,以免影响正常使用。这样可以防止攻击者频繁使用同一个id暴力攻击。

    从防止攻击的角度来说,也可以在网关层对ip设置访问阈值,超出阈值直接拉黑。

    缓存击穿:

    击穿可以认为是雪崩的一个特例。击穿不是大面积的缓存失效,而是热key失效,导致持续的大并发打到数据库,就像在redis中凿开了一个点。

    解决方案:

    设置热点数据不过期,或者加互斥锁

    互斥锁:请求进来发现redis里没有数据,则直接加锁到数据库请求,然后塞入redis,解锁。加锁期间所有请求直接返回空。相当于一种降级方案。

    相关文章

      网友评论

        本文标题:缓存穿透、缓存击穿、缓存雪崩解决方案?

        本文链接:https://www.haomeiwen.com/subject/vtzksktx.html