Redis 缓存穿透
Redis缓存穿透是指去查询一个数据库一定不存在的数据
当用redis做缓存服务时,查询一些数据一般会先去redis里面查找,找不到再去数据库查询,但是如果这个数据在数据库也不存在,就不会写入缓存,导致某些恶意攻击,一直重复这一个请求,访问数据库。在大流量的情况下,数据库可能会直接挂掉。
解决方案:
-
可以设置key-value为key-null,就是在数据库也没有查询到这个数据的时候,将请求的id或者其他标识符设置为key,value设置为null,存入缓存,并设置一个过期时间(缓存有效期可以设置短一点,太长了影响正常用户使用),这样下一次请求就会命中缓存,而不会去查询数据库,造成缓存穿透。
-
布隆过滤器
Redis 缓存击穿
缓存击穿是指查询的数据缓存中没有(一般是过期了),但是数据库中有。在大流量的情况下,全部都来请求这条数据,而缓存又没有,只能去数据库查询,就有可能导致数据库挂掉。
解决方案:
-
设置热点数据永不过期
-
使用互斥锁
public static String getData(String key) throws InterruptedException { //从Redis查询数据 String result = getDataByKV(key); //参数校验 if (StringUtils.isBlank(result)) { try { //获得锁 if (reenLock.tryLock()) { //去数据库查询 result = getDataByDB(key); //校验 if (StringUtils.isNotBlank(result)) { //插进缓存 setDataToKV(key, result); } } else { //睡一会再拿 Thread.sleep(100L); result = getData(key); } } finally { //释放锁 reenLock.unlock(); } } return result; }
Redis 缓存雪崩
缓存雪崩是指某个时间,大量的缓存过期,而请求的数据量也很大,所有的数据都只能去查询数据库,导致数据库压力过大,或者宕机。
和缓存击穿不同的是,缓存击穿是指高并发的去查同一条数据;缓存雪崩是很多缓存全部过期,所有的请求都访问数据库。
解决方案:
-
数据预热,系统启动时,将一部份数据预先加进缓存中
-
避免同一时间大量缓存过期,可在原过期时间上加一定的随机数