Redis缓存穿透、击穿、雪崩

135 阅读2分钟

Redis 缓存穿透

Redis缓存穿透是指去查询一个数据库一定不存在的数据

当用redis做缓存服务时,查询一些数据一般会先去redis里面查找,找不到再去数据库查询,但是如果这个数据在数据库也不存在,就不会写入缓存,导致某些恶意攻击,一直重复这一个请求,访问数据库。在大流量的情况下,数据库可能会直接挂掉。

解决方案:

  1. 可以设置key-value为key-null,就是在数据库也没有查询到这个数据的时候,将请求的id或者其他标识符设置为key,value设置为null,存入缓存,并设置一个过期时间(缓存有效期可以设置短一点,太长了影响正常用户使用),这样下一次请求就会命中缓存,而不会去查询数据库,造成缓存穿透。

  2. 布隆过滤器

Redis 缓存击穿

缓存击穿是指查询的数据缓存中没有(一般是过期了),但是数据库中有。在大流量的情况下,全部都来请求这条数据,而缓存又没有,只能去数据库查询,就有可能导致数据库挂掉。

解决方案:

  1. 设置热点数据永不过期

  2. 使用互斥锁

    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 缓存雪崩

缓存雪崩是指某个时间,大量的缓存过期,而请求的数据量也很大,所有的数据都只能去查询数据库,导致数据库压力过大,或者宕机。

和缓存击穿不同的是,缓存击穿是指高并发的去查同一条数据;缓存雪崩是很多缓存全部过期,所有的请求都访问数据库。

解决方案:

  1. 数据预热,系统启动时,将一部份数据预先加进缓存中

  2. 避免同一时间大量缓存过期,可在原过期时间上加一定的随机数