0%

Redis-穿透&雪崩&击穿

Redis缓存穿透

什么是缓存穿透

缓存穿透:是指查询一个数据库不存在的数据。

Redis正常使用流程:
数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存中,直接向外返回空。

问题引出:
想象一下这个情况,如果传入的参数为-1,会是怎么样?这个-1,就是不存在的对象。就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。即便是采用UUID,也是很容易找到一个不存在的KEY,进行对数据库的攻击。

解决方案

1)redis缓存空值(推荐方案)
对上诉所讲传入一个不存在的key,对数据库进行攻击,我们可以将这个不存在的key缓存一个null值放入到redis中,给null值得缓存设置一个比平常缓存短的过期时间即可。当这个不存在的key存在时,即可将null值删除,将数据存入key中即可。

2)判断key的数据格式(有局限,列如key没有任何规则)
网关判断客户端传入对应的key规则,如果不符合数据库的查询规则直接返回null值。

Redis缓存雪崩

什么是缓存雪崩

缓存雪崩:指在某一个时间段,缓存集中过期失效。

举例:
马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

解决方案

1)使用二级缓存(推荐)
一级缓存使用ehcache,二级缓存使用redis。
一级缓存为原始缓存,二级缓存为拷贝缓存,一级缓存失效时,可以访问二级缓存。一级缓存失效时间设置为短期,二级缓存设置为长期。

2)均摊分配redis key的失效时间(推荐)
不同的key,设置不同的过期时间,让缓存失效的时间点不要过于集中。这种方式需要根据业务需求和正式场景看情况设置失效时间。

Redis缓存击穿

什么是缓存击穿

缓存击穿:热点数据突然过期。

举例:一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

解决方案

1)设置热点数据永远不过期。(推荐)

2)使用锁(不推荐,效率低)
单点项目使用本地锁,分布式项目使用分布式锁。
对于某种规则key中,在缓存失效后,通过加锁来控制读数据库写缓存的线程数量。也就是同一时间只允许一个线程查询数据和写缓存,其他线程等待。