美文网首页
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