redis面试题:说说对缓存雪崩和缓存穿透的理解?
缓存雪崩:是存储在缓存中的大量数据在同一个时刻全部过期,原本缓存组件能够抗住大部分流量,全部请求到了数据库,从而导致数据库压力增加,造成数据库服务器崩溃的一种现象。
导致缓存雪崩的原因有几个方面。
一是缓存服务器宕机,当然可以对缓存中间件做高可用集群来避免。
二是缓存中的大部分key都设置了相同的过期时间,导致同一时刻这些key同时过期。针对这种情况可以在失效的时间里面增加1-5分钟的随机值,从而去避免同时失效这样的问题。
缓存穿透:表示是指短时间内,有大量的不存在的key请求到应用程序里面。而这些不存在的key在缓存里面又找不到,从而导致全部的请求,全部穿透到了数据库,造成了数据库的压力增加。
我认为这个场景的问题是针对于缓存的攻击行为。因为正常的业务里面,即便是出现这样一个不存在key的情况,由于缓存的不断预热影响也不会很大。而攻击行为就需要具备时间的持续性,而只有key确定在数据库里面不存在的情况下,才能达到这样一个目的。
在这样的场景下有两个方法可以去解决,一是把无效的key保存到redis里面,并且设置为一个特殊的值,例如null字符串,这样下次再来访问的时候就不会再查数据库了。但是攻击者不断地用随机的不存在的key来访问也还是会存在相同的问题。所以第二种方法可以使用布隆过滤器来实现。在系统启动的时候,我们可以把目标数据全部缓存到布隆过滤器里面,当攻击者不断使用不存在的key进行访问的时候,先到布隆过滤器里面去查询,如果不存在,就没有必要再去查询数据库了。布隆过滤器采用的是bitmap,也就是位图方式去存储,占用的内存小。
在一个成熟的系统里面,热点数据,必然会有一个专门的缓存系统来维护,同时它的过期时间的key必然要和其他业务的key有所区别。对于重要的场景,我们还是会设计多级缓存的一个实现。其次即便是触发了缓存雪崩,数据库的容灾能力也没有那么脆弱。数据库的主从、双主,读写分离的这些策略,都可以很好的缓解并发流量。最后数据库的本身也有最大连接数的限制,超过限制的请求会被拒绝。再结合熔断机制也可以很好的保护数据库系统,最多就是造成部分用户的体验不好而已。另外在程序设计上为了避免缓存未命中导致大量的请求穿透到数据库的问题,我们也可以在访问数据库的层面去加锁,虽然影响了性能,但是对于整个系统是安全的。总而言之,具体的方法有很多,具体的解决方法还是要看具体的业务场景。