1.缓存雪崩

2.缓存击穿

3.缓存穿透

4.总结

1.缓存雪崩
缓存雪崩是如何产生的?
1)redis服务间接挂掉,redis全盘解体
2)redis中有大量缓存同时过期,导致大量查问直击mysql

解决
1.1)redis缓存集群实现高可用,主从+哨兵
1.2)ehcache本地缓存 + Hystrix或者阿里sentinel限流&降级
1.3)开启Redis长久化机制aof/rdb,尽快恢复缓存集群

2.1)设置缓存更新的工夫都为固定工夫+随机肯定的工夫,造成不会同时过期

2.缓存击穿
缓存雪崩是如何产生的?
大量的申请正在拜访同一个key, 此时这个key正好生效了,就会导致大量的申请到数据库下面。

危害:
会造成某一时刻的mysql压力过大,有宕机危险。

解决方案:
1)对于高热点key,设置永不过期
2)设置一个互斥锁,来避免缓存击穿:

    public TUser findById(Integer id) {        TUser user  = (TUser)redisTemplate.opsForValue().get(CACHE_KEY_USER + id);        if(user==null){            //小厂用          /*  user = userMapper.selectById(id);            if(user!=null) {                redisTemplate.opsForValue().set(CACHE_KEY_USER + id, user);            }*/            //大厂用,对于高qps的优化,进来就先加锁,保障一个申请操作,让里面的redis期待一下,防止击穿mysql            synchronized (TUserServiceImpl.class){                //双端检索,再次查问redis                user  = (TUser)redisTemplate.opsForValue().get(CACHE_KEY_USER + id);                if(user==null){                    //还是为空,就去查mysql                    user = userMapper.selectById(id);                    if(user!=null){                        redisTemplate.opsForValue().setIfAbsent(CACHE_KEY_USER + id, user,7L, TimeUnit.DAYS);                    }                }            }        }        return user;    }

3)双缓存保留,定时轮询,互斥更新,差别生效工夫

需要:假如咱们要实现网页上的一个聚划算性能,每隔两个小时换一批商品。比方:8:000~10:00一批商品,10:00~12:00一批商品。如果依照定时工作的做法,8:00开始更新商品,假如数据量很大,mysql在很难查出来的状况下,到点了可能缓存曾经过期了,然而mysql还没查问出商品,又会有大量查问攻打mysql,导致服务宕机。

思路:咱们设置两个缓存,都保留雷同的内容,两个缓存的过期工夫不同。缓存B比缓存A过期工夫更长一些,这样就能够保障缓存里永远有数据。

查问:先查问缓存A,如果A没有,查问缓存B。

//采纳redis list数据结构的lrange命令实现分页查问list = this.redisTemplate.opsForList().range(Constants.JHS_KEY_A, start, end);if (CollectionUtils.isEmpty(list)) {log.info("=========A缓存曾经生效了,记得人工修补,B缓存主动连续5天");//用户先查问缓存A(下面的代码),如果缓存A查问不到(例如,更新缓存的时候删除了),再查问缓存Bthis.redisTemplate.opsForList().range(Constants.JHS_KEY_B, start, end);

更新:先更新缓存B,再更新缓存A。

//先更新B缓存this.redisTemplate.delete(Constants.JHS_KEY_B);this.redisTemplate.opsForList().leftPushAll(Constants.JHS_KEY_B,list);this.redisTemplate.expire(Constants.JHS_KEY_B,20L,TimeUnit.DAYS);//再更新A缓存this.redisTemplate.delete(Constants.JHS_KEY_A);this.redisTemplate.opsForList().leftPushAll(Constants.JHS_KEY_A,list);this.redisTemplate.expire(Constants.JHS_KEY_A,15L,TimeUnit.DAYS);

留神:采纳互斥更新和查问,保障两个key都有值。

3.缓存穿透
缓存穿透是什么:
申请查问一条记录,先去redis查问后查问不到数据再去mysql查问后也查问不到数据,所以每次申请都会攻打mysql,导致数据库压力暴增

危害:第一次来查问后,个别咱们有回写redis机制,所以偶发一次没关系,然而频繁产生就有安全隐患。

解决方案:
1)空对象或者缺省值
一般来说这么做是没问题的,然而如果黑客大量拿未知的key来攻打咱们的零碎,每次都要去查问,且redis中无用key越写越多。

2)Redis布隆过滤器解决缓存穿透
深刻了解redis——布隆过滤器BloomFilter
能够应用布隆过滤器来解决缓存穿透,布隆过滤器曾经在这篇文章里解说过了。

4.总结
明天学习了缓存雪崩/缓存击穿/缓存穿透的景象以及对应计划。