缓存穿透-击穿-雪崩
缓存穿透:
查询key在缓存和数据库中均不存在数据,就会去请求数据库查询,但是数据库也可能不存在,因此就会每次去请求数据库,导致对数据库服务器造成压力,甚至压垮服务,造成整个服务的宕机。
通常此类数据的出现量是一个较低的值,如果大规模出现,则可能是有人恶意攻击。
解决方法:
1)缓存空值
缓存一些经常被访问的key为空值null,这样在访问缓存时就被拦截过滤到,避免去访问数据库,为了避免存储过多空对象,因此需要设置key的过期时间。
2)布隆过滤器(BloomFilter)
BloomFilter是一种数据结构,是由一串很长的二进制向量组成,可以将其看成一个二进制数组,存放是0或1,初始默认值为0。
布隆过滤器,不存在的一定不存在,存在的不一定存在(不确定性来自于哈希冲突)。
优点:优点很明显,二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。
缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据(因为删除操作会影响到其他元素的判断)。
redis-key与BloomFilter的结合:
将redis中数据的key都放到BloomFilter中,每次查询的时候都先去BloomFilter判断,没有就直接返回null,有就访问Redis和数据库。由于BloomFilter没有删除操作,若redis中有些key被删除,但BloomFilter仍然判断存在,查询仍旧会经过缓存和数据库,所以对于那些已被删除的key,可以在缓存中缓存null。
使用场景:
1 | 1.过滤用户已经看过的内容 |
布鲁姆过滤器是一种特殊的哈希表,存放在内存中。
BloomFilter元素清除:
- Counting Bloom Filter的出现解决了这个问题,它将标准Bloom Filter位数组的每一位扩展为一个小的计数器(Counter),在插入元素时给对应的k(k为哈希函数个数)个Counter的值分别加1,删除元素时给对应的k个Counter的值分别减1,Counting Bloom Filter通过多占用几倍的存储空间的代价,给Bloom Filter增加了删除操作
缓存击穿:
redis中某个key过期了,但该key访问量巨大,多个数据请求从服务器来请求redis数据均未命中,于是redis在短时间内发起大量对数据库中统一数据的访问。
解决方法:
1)预先设定:预先设定可能要被大量访问值的key为永久key;
2)现场调整:监控访问量,对自然流量激增的数据延迟过期时间或设置为永久key;
3)后台刷新数据:启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失;
4)二级缓存:设置不同的失效时间,保障不会被同时淘汰就行;
5)加锁:分布式锁,防止被击穿,但是要注意也会是性能瓶颈。
缓存雪崩
缓存雪崩指的是短时间内,缓存中有大量的key集中过期,此周期内请求访问都向数据库获取数据,数据库同时收到大量的请求无法及时处理,造成redis大量请求被积压,开始出现了超时现象,数据库同时压力剧增,面临崩溃。
解决方法:
1)更多的页面静态化处理;
2)构建多级缓存架构:nginx缓存+redis缓存+ehcache缓存;
3)检测mysql严重耗时业务进行优化:对数据库的瓶颈排查(例如超时查询、耗时较高事务等);
4)灾难预警机制:监控redis服务器性能指标、CPU占用、CPU使用率、内存容量、查询平均响应时间、线程数;
5)限流与降级:短时间范围内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待业务低速运转后再逐步放开访问
6)熔断:
- Redis熔断机制是一种在系统出现异常时,自动采取措施防止系统继续运行的机制。 当系统出现异常时,Redis会自动将客户端连接请求中断,从而避免异常继续扩散,保障系统的稳定运行。 Redis熔断机制主要通过设置超时时间和连接数来实现。 当客户端连接数超过设定的最大连接数时,Redis会自动将客户端连接请求中断。