redis缓存穿透,击穿和雪崩以及解决方案

一:redis雪崩

redis雪崩是指redis在某个时间大量失效,突然造成数据库访问压力急剧增大,像雪崩一样,redis雪崩危害巨大,甚至有可能服务器宕机,给公司造成巨大的经济损失。

解决方案:设置超时时间的时候要设置随机值,不要设置固定值

     * 缓存雪崩: key在同一时间失效,导致大量请求去访问数据库
     * 返回min 和max 之间的一个随机秒数
	private Long getRandomExpirationTime(Integer min, Integer max) {
        return RandomUtils.nextLong(min * 60 * 60, max * 60 * 60);
    }

二: redis缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。

在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解决方案:

1.设置并发锁,防止请求大量请求数据库,如果获取到锁了,去数据库查询,如果没有,说明有其他线程在查询数据库,那么只需要重试一下就好了
 

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
	       if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
		       value = db.get(key);
		       redis.set(key, value, expire_secs);
		       redis.del(key_mutex);
	       } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
		      Thread.sleep(50);
		      get(key);  //重试
	       }
       } else {
              return value;      
       }
}

2.设置拦截器,对于不存在得key,进行拦截

三:缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

解决方案:
1.设置热点数据永不过期
2.加互斥锁
 

你可能感兴趣的:(redis,redis)