15. Redis缓存穿透和雪崩
Redis缓存穿透和雪崩
Redis缓存的应用,极大提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也有一些列的问题,数据一致性就是其中比较重点的问题。那么这个问题其实目前的解决方案都是最终一致性,当然也是要看具体需求而定。
这其中还有一些缓存穿透、雪崩也是比较经典的问题
缓存穿透
缓存穿透是指查询一个在缓存和数据库中都不存在的数据。由于缓存没有这个数据,所以每次查询都会“穿透“缓存直接查询数据库,如果有大量此类查询,会给数据库带来极大的压力。
这种情况如果一旦访问量过大,很容易造成MySQL服务器宕机

解决办法
1. 布隆过滤器(Bloom Filter):这是一种空间效率极高的概率型数据结构,它可以用来判断一个元素是否在一个集合中。将所有可能会被请求的数据的key先存入布隆过滤器,当有请求过来时,先使用布隆过滤器判断数据是否存在,如果布隆过滤器判断数据不存在,那就直接返回,不再查询数据库。
2.空值缓存:即使一个key在数据库中没有对应的值,也依然将这个结果进行缓存,但是可以设置一个较短的过期时间。这样,即使攻击者使用大量不存在的key进行攻击,也只能触及到缓存层,无法达到数据库层。
3.限流:对单个用户的访问频率进行限制,防止恶意用户或者爬虫通过高并发的方式进行攻击。
缓存击穿(缓存过期的瞬间)
缓存击穿是指一个存在的key在缓存中过期,此时有大量的并发请求这个key,都查不到结果,于是都去数据库中查询并回填缓存,造成数据库短时间内压力过大。简单来说,缓存击穿是指请求的数据在缓存中不存在(可能是过期,或者根本没有缓存过),导致所有的请求都去请求数据库,可能会导致数据库瞬间压力过大。
为了防止缓存击穿,有一些常见的解决办法:
1.设置热点数据永不过期:如果某些数据特别热门,访问的频率远远超过其他数据,那么可以将这部分数据设置为永不过期,这样就可以避免大量请求突然落到数据库上。
2.加锁排队:对于查询数据库的操作进行加锁,即在缓存失效的时候,不是直接去查询数据库,而是先进行加锁操作。第一个请求获取到锁,然后进行数据库查询并回填缓存,后续的请求如果获取不到锁,可以选择等待或者返回未获取到数据。
3.使用互斥锁:可以在缓存失效的时候使用互斥锁,即第一个请求去数据库查找数据,其他的请求就等待,当第一个请求处理完毕后,其他请求再从缓存中获取数据。这些方法可以根据实际的业务情况进行选择,理想的情况是可以将数据库的访问量降到最低,从而避免数据库因为过大的压力而崩溃。
缓存雪崩
缓存雪崩是指在缓存系统中,由于大量的数据同时失效,而引发大量的请求同时去请求数据库,从而可能会导致数据库的压力过大甚至导致数据库崩溃的情况。比如,如果一个系统的缓存策略设置的是某一刻所有的缓存同时失效,那么在这一刻,所有的请求都
将会去请求数据库,这就可能会造成缓存雪崩。其实最致命的雪崩就是服务器某个节点突然宕机或者断网,因为此时对数据库服务器的压力是不可预估的,很有可能瞬间把数据库压垮!
为了防止缓存雪崩,有一些常见的解决策略:
1.缓存数据的过期时间设置为随机:避免所有数据同时过期,不会出现瞬间大量的数据库请求。
2.使用多级缓存策略:例如,使用一级缓存和二级缓存,一级缓存的失效时间短于二级缓存,一级缓存失效后,请求会访问二级缓存,而不是直接落到数据库。
3.缓存预热:在业务低峰期,对将要过期的缓存进行预热,预热的方式就是提前去更新数据。
4.使用高可用的缓存集群:即使某些节点挂掉,仍然可以保证系统的可用性。这些策略可以根据实际情况进行选择和使用,以提高系统的稳定性和可用性,减少因为大量请求落到数据库而引发的问题。