zoukankan      html  css  js  c++  java
  • 吃透redis缓存穿透,缓存击穿,缓存雪崩原因+解决方案

    一、缓存的基本使用

          如下图,前台请求,后台先从缓存中获取数据,取到直接返回结果,取不到时从数据库中获取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。设计一个缓存系统,不得不考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。

       

    二、缓存穿透

        问题描述

         1、用户发起大量的请求

       2、结果发现Redis中没有数据

               3、后台查询数据库,发现数据库中也没有数据

               4、就这样一直请求,导致数据库崩溃

     在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。这种大量的请求,可能是接口本身并发量就比较大,也可能是有黑客在攻击。

        解决方案

          1、异常参数校验:比如发起一个id为“-1”的请求,这一看就是有问题,id不可能为负的,或者一些非空参数,传了空值,直接后台判断拦截。

          2、缓存空值:从缓存取不到的数据,在数据库中也没有取到,这时可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

        

    二、缓存击穿

        问题描述 

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

     解决方案

           1、设置热点数据永远不过期

           2、设置热点数据的存活时间较长,且分布均匀的岔开过期时间

           3、接口限流与熔断,降级。重要的接口一定要做好限流策略。防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时,可进行熔断,失败快速返回机制

      4、使用互斥锁(mutex key),简单的来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如redis的setnx)去set一个mutex key,当操作返回成功时,再进行load db的操作并更新缓存,否则就重试整个get缓存的方法。代码如下:

    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并回设到缓存了,这时候重试获取缓存值即可
                          sleep(50);
                          get(key);  //重试
                  }
              } else {
                  return value;      
              }
     }

    二、缓存雪崩

        问题描述 

            1、由于redis层压力过大,导致redis服务器宕机

            2、缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至宕机。和缓存击穿不同的是,缓存击穿指并发查询同一条数据,缓存雪崩是不同数据都过期了,很多数据查不到从而查数据库。

     解决方案

        1、缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

        2、如果缓存数据库是分布式部署,将热点数据均匀分布在不同节点缓存数据库中

        3、设置热点数据永远不过期

  • 相关阅读:
    Python基础语法 第2节课(数据类型转换、运算符、字符串)
    python基础语法 第5节课 ( if 、 for )
    python基础语法 第4节课 (字典 元组 集合)
    Python基础语法 第3节课 (列表)
    A. Peter and Snow Blower 解析(思維、幾何)
    C. Dima and Salad 解析(思維、DP)
    D. Serval and Rooted Tree (樹狀DP)
    C2. Balanced Removals (Harder) (幾何、思維)
    B. Two Fairs 解析(思維、DFS、組合)
    D. Bash and a Tough Math Puzzle 解析(線段樹、數論)
  • 原文地址:https://www.cnblogs.com/maowenqiang/p/14702057.html
Copyright © 2011-2022 走看看