-
缓存穿透
问题描述
key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源.比如用一个不存在的用户id,获取用户信息,无论是数据库或缓存都没有,若黑客利用此漏洞进行攻击可能压垮数据库.
解决方案
- 对空值进行缓存,如果一个查询返回的数据为空,我们仍然要把这个空结果进行缓存(可以定义应特殊的标识),设置一个较短的过期时间,最长不超过5分钟
- 设置可访问的白名单,使用bitmaps类型定一个一个可以访问的名单,名单id左右btimaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不存在bitmaps里面,进行拦截,不允许访问
- 采用布隆过滤器: 布隆过滤器可以用户检索一个元素是否存在一个集合中,他的优点是空间效率和查询效率时间远超一般算法,缺点是有一定的误识别和删除困难
- 进行实时监控:当发现redis的命中率开始急速降低,需要排除访问对象和访问的数据库,和运维人员配合,设置黑名单限制服务
-
缓存击穿
问题描述
key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮
解决方案
- 预先设置热门数据,在redis高峰访问之前,把一些热门数据提现存入到redis里面,加大这些热门数据key的时长
- 试试调整:监控哪些是热门数据,实时调整过期时长
- 使用锁,在缓存过期的时候,不是立即去查询数据库,先使用redis的分布式锁,对key进行加锁,加锁成功再去查询数据库,然后缓存起来,最后解锁,未抢到锁的线程,短时间睡眠,然后重试从缓存获取数据
缓存雪崩
问题描述
key对应的数据存在,但是在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从DB加载数据并返回设置到缓存,这个时候大并发大请求可能会瞬间压垮db,这里与缓存击穿的区别是这里针对的是多个key,前者针对单个key
解决方案
1 使用多级缓存,redis缓存+jvm本地缓存
2 将缓存失效时间分散开,在原有的失效时间加上一个1-5分钟的随机值
3 使用锁,参考缓存击穿的解决方案