一、缓存穿透
概念:
一次请求发现数据在缓存和DB中都没有。
通常是恶意攻击
比如:请求一个数据的ID为-1
解决方案:
1.拦截不合法请求
可考虑使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitMap中,一个一定不存在的数据会被这个bitMap拦截掉,从而避免底层存储系统的查询压力。
2.设置短期空缓存
比如:请求一个数据的ID为-1,读了缓存发现没有,读了数据库发现也没有,此时可以往缓存中写入一条key为-1 value为空的数据,把过期时间设置很短,不超过5分钟。
二、缓存击穿
概念:
某个key在缓存中没有,在DB中有,同一时间内对该key有非常大量的并发请求
解决方案:
1.使用互斥锁mutex key
第一个发现该key没有缓存的线程,在redis上价格互斥锁(可能需要分布式锁),
获取到锁后再看缓存中有不有这个key,有就返回(这时说明自己不是第一个,第一个已经把DB的数据写入到缓存中了)
如果缓存中还是没有这个key,则读db然后回写到redis中。
这样就只有一个线程去读了DB了
2.热点数据永不过期
有两种
1.就是真的不设置过期时间,比如redis的key不设置过期时间
2.把过期时间存在key对应的value中,每次请求该key的时候看一下value中存的过期时间,是不是要过期,如果发现要过期了,启动一个异步线程去进行缓存的构建
三、缓存雪崩
概念:
大部分key在缓存中没有,在DB中有,同一时间对该部分key有非常大的并发请求。
解决方案:
1.加锁或用队列
让它们去进行资源竞选, 选出相应的redis再去mysql中进行动态的操作.
2.过期时间加随机值
降低集体失效发生
3.如果是redis宕机引起的雪崩:
事发前,高可用架构
事发中,限流+(迅速恢复redis并增加redis节点)
事发后,总结