美文网首页
3.分布式缓存(击穿、雪崩、穿透)

3.分布式缓存(击穿、雪崩、穿透)

作者: 指尖架构141319 | 来源:发表于2019-12-09 18:22 被阅读0次

1.概念示意图

1.1缓存击穿
  • 概念:
    缓存中没有但数据库中有的数据(一般是某一个key缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力 瞬间增大,造成过大压力
  • 示意图:


    image.png
1.2缓存雪崩
  • 概念:
    缓存中数据大批量key到过期时间,而查询数据量巨大,引起数据库压力过大甚至 down 机。
    和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
  • 示意图:


    image.png
1.3缓存穿透
  • 概念:
    缓存和数据库中都没有的数据,而用户不断发起请求,如发起为 id 为“-1”的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导 致数据库压力过大。
  • 示意图:


    image.png

2.解决方案

2.1 击穿和雪崩
  • 加锁、限流
  • 缓存预热(常用值,使用http接口预热错峰加载)
  • 改被动失效为主动失效(什么时候失效,设计者控制)

加锁、限流代码实现:

       if (valueWrapper != null) {//缓存中查询
            logger.info("缓存中得到数据");
            return (Provinces) (valueWrapper.get());
        }
        //2.加锁排队,阻塞式锁
        doLock(provinceid);
        try{//第二个线程进来了
             //双重校验
            valueWrapper = redisTemplate.get(provinceid);//第二个线程,能从缓存里拿到值?
            if (valueWrapper != null) {
                logger.info("缓存中得到数据");
                return (Provinces) (valueWrapper.get());//第二个线程,这里返回
            }
            Provinces provinces = super.detail(provinceid);
            // 3.从数据库查询的结果不为空,则把数据放入缓存中,方便下次查询
            if (null != provinces){
                cm.getCache(CACHE_NAME).put(provinceid, provinces);
            }
          return provinces;
        }catch(Exception e){
            return null;
        }finally{
            //释放锁
            releaseLock(provinceid);
        }
2.2缓存穿透
  • 直接把查询的key和value写入缓存,并设置失效时间(量大有风险)
  • 布隆过滤器
  • 或者放一个大的map存储查询

相关文章

网友评论

      本文标题:3.分布式缓存(击穿、雪崩、穿透)

      本文链接:https://www.haomeiwen.com/subject/ihligctx.html