redis击穿
redis缓存击穿是指某一个非常热点的key(即在客户端搜索的比较多的关键字)突然失效了,这时从客户端发送的大量的请求在redis里找不到这个key,就会去数据里找,最终导致数据库压力过大崩掉。
解决方案:
1.将value的时效设置成永不过期 这种方式非常简单粗暴但是安全可靠。但是非常占用空间对内存消耗也是极大。个人并不建议使用该方法,应该根据具体业务逻辑来操作。
2.使用timetask做一个定时任务 使用timetask做定时,每隔一段时间对一些热点key进行数据库查询,将查询出的结果更新至redis中。前条件是不会给数据库过大的压力。
3.通过synchronized+双重检查机制 当发生reids穿透的时候,这时海量请求发送到数据库。这时我们的解决办法是只让只让一个线程去查询这个热点key,其它线程保持阻塞状态(可以让它们sleep几秒)。当这个进入数据库的线程查询出key对应的value时,我们再将其同步至redis的缓存当中,其它线程睡醒以后再重新去redis里边请求数据。
例子:
private static volaite object obj = new object(); public string getvalue(string key){ string value=redis.get(key,string.class); if(value==null||stringutils.isblank(value){ synchronized(obj){ //进入synchronized以后再去redis里查一遍,防止上一个抢到锁的线程已经更新过了。 value=redis.get(key,string.class); if(value==null||stringutils.isblank(value){ value=db.query(key); redis.set(key,value,1000); } } } return value; }
缺点:存在死锁和线程阻塞的风险。
redis雪崩
指的是当海量的请求去查询多个key时,此时redis缓存中失效或者查不到,然后海量的请求都去都去db查询,从而导致db压力突然飙升崩溃。
出现原因:
1.key同时失效
2.redis本身崩溃了
解决方案:
1.设置缓存时,随机初始化其失效时间
如果是redis的key同时失效,可采取该办法,具体失效时间根据业务情况决定…
2.将不同的热点key放置到不同的节点上去
因redis一般都是集群部署,将不同的热点key平均的放置到不同节点,也可以有效避免雪崩。
3.将value的时效设置成永不过期
4.使用timetask做一个定时任务,在失效之前重新刷redis缓存
redis穿透
因为不良用户恶意频繁查询才会对系统造成很大的问题: key缓存并且数据库不存在,所以每次查询都会查询数据库从而导致数据库崩溃。
(例如:我们在数据库存放的数据其主键都是自增且没有负数的,某些黑客就利用这一点,不断用主键id为-1的参数来发起海量查询请求,导致这些请求在redis中查不到相应的数据,只能去数据库中查询,从而导致数据库崩溃。)
解决方案:
1.当类似的请求发过来,无论查出什么结果都放入redis缓存
这样解决当他下次再用同一个参数发起请求时,会直接进到redis里边去,不会再进入数据库。
2.拉黑其ip
3.对请求的参数进行合法性校验,在判断其不合法的前提下直接return掉
4.使用布隆过滤器
可以将布隆过滤器理解成一个白名单或者黑名单,它的作用就是判断一个元素是否存在于这个过滤器。
白名单: 过滤器里有数据库中所有的合法的参数key,请求经过布隆过滤器,布隆过滤器判断这个请求的key在不在过滤器,在就放行让请求进入redis,不在就直接return空数据。
public static void main(string[] args){ config config = new config(); config.usesingleserver().setaddress("redis://127.0.0.1:6379"); config.usesingleserver().setpassword("1234"); //构造redsson redissonclient redisson = redisson.create(config); rbloomfilter<string> bloomfilter = redisson.getbloomfilter("phonelist");//给我们自己定义的布隆过滤器取名叫phonelist,名字随便取 //初始化布隆过滤器设置预计元素为100000000l, 误差率为3% bloomfilter.tryinit(100000000l,0.03); //将10086插入到布隆过滤器中 bloomfilter.add("10086"); //判断下面号码是否存在布隆过滤器中 //false system.out.println("123456"); //true system.out.println("10086");}
缺点:
布隆过滤器可能会造成误判,从而穿透redis进入db,但是这个误判概率是非常小的。
以上就是redis击穿 雪崩 穿透超详细解决方案梳理的详细内容,更多关于redis 击穿 雪崩 穿透的资料请关注www.887551.com其它相关文章!