初认识
- 缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
- 缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
- 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。
缓存穿透
出现现象
- 服务器压力变大
- redis命中率低,redis正常运行
- 一直查询数据库
解决方案
- 对空值缓存:如果查询返回的数据为空,我们仍然把这个空结果进行缓存,设置空结果的过期时间会很短,最长不超过5分钟
- 设置可访问的名单:使用bitmaps类型定义一个可以访问的名单,名单id 作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较
- 采用布隆过滤器:它是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)
- 进行实时监控:发现redis 命中率开始急速降低,需要排查访问对象和访问的数据,和运维配合,设置黑名单限制服务
缓存击穿
出现现象
- 数据库访问压力瞬间增加
- redis没出现大量的key过期,只是某个key过期了,大量访问使用这个key
- redis正常运行
解决方案
- 预先设置热门数据:提前把热门数据存入到redis里面,加大这些热门数据key的时长
- 实时调整:现场监控那些数据热门,实时调整key的过期时长
- 使用锁
雪崩
出现现象
- 数据库压力变大服务器崩溃
- 在极少时间段,大量key过期
解决方案
- 使用多级缓存架构:nginx 缓存 + redis缓存 + 其他缓存(本地缓存)
- 使用锁或者队列,但是不适合高并发场景
- 设置过期标志更新缓存:记录缓存数据是否过期,如果过期会触发另外的线程在后台去更新实际key的缓存
- 将缓存失效时间分散开:比如我们在原有的失效时间基础上增加一个随机值,比如1-5分钟随机。