<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Redis 緩存高并發(fā)常見(jiàn)問(wèn)題

          共 5027字,需瀏覽 11分鐘

           ·

          2021-07-10 12:20

          0x01:緩存的三大問(wèn)題

          • 緩存穿透訪問(wèn)不存在的數(shù)據(jù)Bloom Filter,緩存空對(duì)象

          • 緩存擊穿熱點(diǎn) key 重建過(guò)程中,造成的緩存問(wèn)題(分布式鎖)

          • 緩存雪崩Redis 宕機(jī),或緩存批量失(高可用集群,錯(cuò)開(kāi)緩存失效時(shí)間)

            緩存粒度控制

            通俗來(lái)講,緩存粒度問(wèn)題就是我們?cè)谑褂镁彺鏁r(shí),是將所有數(shù)據(jù)緩存還是緩存部分?jǐn)?shù)據(jù)?

            數(shù)據(jù)類(lèi)型

            通用性

            空間占用

            (內(nèi)存空間+網(wǎng)絡(luò)碼率)

            代碼維護(hù)

            全部數(shù)據(jù)

            簡(jiǎn)單

            部分?jǐn)?shù)據(jù)

            較為復(fù)雜

            緩存粒度問(wèn)題是一個(gè)容易被忽視的問(wèn)題,如果使用不當(dāng),可能會(huì)造成很多無(wú)用空間的浪費(fèi),可能會(huì)造成網(wǎng)絡(luò)帶寬的浪費(fèi),可能會(huì)造成代碼通用性較差等情況,必須學(xué)會(huì)綜合數(shù)據(jù)通用性、空間占用比、代碼維護(hù)性 三點(diǎn)評(píng)估取舍因素權(quán)衡使用。


            0x02:緩存穿透問(wèn)題,訪問(wèn)不存在的數(shù)據(jù)

            緩存穿透是指查詢(xún)一個(gè)一定不存在的數(shù)據(jù),由于緩存不命中,并且出于容錯(cuò)考慮, 如果從存儲(chǔ)層查不到數(shù)據(jù)則不寫(xiě)入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到存儲(chǔ)層去查詢(xún),失去了緩存的意義。

            可能造成原因

            • 業(yè)務(wù)代碼自身問(wèn)題

            • 惡意攻擊。爬蟲(chóng)等等

            危害

            對(duì)底層數(shù)據(jù)源壓力過(guò)大,有些底層數(shù)據(jù)源不具備高并發(fā)性。  例如 MySQL 一般來(lái)說(shuō)單臺(tái)能夠扛1000 QPS 就已經(jīng)很不錯(cuò)了

            解決方案

            緩存空對(duì)象

            缺點(diǎn):惡意攻擊的清空下,會(huì)產(chǎn)生大量的空對(duì)象,數(shù)據(jù)庫(kù)壓力仍然存在,治標(biāo)不治本

            public class NullValueResultDO implements Serializable {
            }

            public class UserManager {
                 UserDAO userDAO;
                 LocalCache localCache;

                 public UserDO getUser(String userNick) {
                      Object object = localCache.get(userNick);
                      if(object != null) {
                           if(object instanceof NullValueResultDO) {
                                return null;
                           }
                           return (UserDO)object;
                      } else {
                           User user = userDAO.getUser(userNick);
                           if(user != null) {
                                localCache.put(userNick,user);
                           } else {
                                localCache.put(userNick, new NullValueResultDO());
                           }
                           return user;
                      }
                 }          
            }

            布隆過(guò)濾器

            • Google 布隆過(guò)濾器的缺點(diǎn)

            • 不需要網(wǎng)絡(luò) IO,效率高,維護(hù)成本低

            • 缺點(diǎn):基于JVM內(nèi)存的一種布隆過(guò)濾器,重啟即失效,本地內(nèi)存無(wú)法用在分布式場(chǎng)景,不支持大數(shù)據(jù)量存儲(chǔ)

            • Redis 布隆過(guò)濾器

            • 可擴(kuò)展性 Bloom 過(guò)濾器:一旦 Bloom 過(guò)濾器達(dá)到容量,就會(huì)在其上創(chuàng)建一個(gè)新的過(guò)濾器,不存在重啟即失效或者定時(shí)任務(wù)維護(hù)的成本:基于 Google 實(shí)現(xiàn)的布隆過(guò)濾器需要啟動(dòng)之后初始化布隆過(guò)濾器

            • 缺點(diǎn):需要網(wǎng)絡(luò) IO,性能比 Google 布隆過(guò)濾器低


            0x03:緩存擊穿,熱點(diǎn) key 重建緩存問(wèn)題

            可能造成的原因

            緩存擊穿是指緩存中沒(méi)有數(shù)據(jù)庫(kù)中有的數(shù)據(jù)(一般是緩存時(shí)間到期),這時(shí)由于大量的并發(fā)訪問(wèn)特別多,同時(shí)讀緩存沒(méi)讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫(kù)去取數(shù)據(jù),引起數(shù)據(jù)庫(kù)壓力瞬間增大,造成過(guò)大壓力。

            危害

            我們知道,使用緩存,如果獲取不到,才會(huì)去數(shù)據(jù)庫(kù)里獲取。但是如果是熱點(diǎn) key,訪問(wèn)量非常的大,數(shù)據(jù)庫(kù)在重建緩存的時(shí)候,會(huì)出現(xiàn)很多線程同時(shí)重建的情況。因?yàn)楦卟l(fā)導(dǎo)致的大量熱點(diǎn)的 key 在重建還沒(méi)完成的時(shí)候,不斷被重建緩存的過(guò)程,由于大量線程都去做重建緩存工作,導(dǎo)致服務(wù)器拖慢的情況。

            解決方案

            • 互斥鎖

            第一次獲取緩存的時(shí)候,加一個(gè)鎖,然后查詢(xún)數(shù)據(jù)庫(kù),接著是重建緩存。這個(gè)時(shí)候,另外一個(gè)請(qǐng)求又過(guò)來(lái)獲取緩存,發(fā)現(xiàn)有個(gè)鎖,這個(gè)時(shí)候就去等待,之后都是一次等待的過(guò)程,直到重建完成以后,鎖解除后再次獲取緩存命中。

            public String getKey(String key){
                String value = redis.get(key);
                if(value == null){
                    // 設(shè)置互斥鎖的key
                    String mutexKey = "mutex:key:"+key;
                    // 給這個(gè)key上一把鎖,ex 表示只有一個(gè)線程能執(zhí)行,過(guò)期時(shí)間為 180 秒
                    if(redis.set(mutexKey,"1","ex 180","nx")){
                      value = db.get(key);
                      redis.set(key,value);
                      redis.delete(mutexKety);
                    }else{
                      // 其他的線程休息100毫秒后重試
                      Thread.sleep(100);
                      getKey(key);
                    }
               }
               return value;
            }

            互斥鎖的優(yōu)點(diǎn)是思路非常簡(jiǎn)單,具有一致性,但是互斥鎖也有一定的問(wèn)題,就是大量線程在等待的問(wèn)題。存在死鎖的可能性。


            0x04: 緩存雪崩,批量失效問(wèn)題

            可能造成的原因

            緩存雪崩是指機(jī)器宕機(jī)或在我們?cè)O(shè)置緩存時(shí)采用了相同(近似)的過(guò)期時(shí)間,導(dǎo)致緩存在某一時(shí)刻大批量緩存數(shù)據(jù)同時(shí)(批量)失效

            危害

            請(qǐng)求全部轉(zhuǎn)發(fā)到 DB,DB 瞬時(shí)壓力過(guò)重,導(dǎo)致雪崩。

            解決方案

            • 在緩存失效后,通過(guò)加鎖或者隊(duì)列來(lái)控制讀數(shù)據(jù)庫(kù)寫(xiě)緩存的線程數(shù)量。比如對(duì)某個(gè) key 只允許一個(gè)線程查詢(xún)數(shù)據(jù)和寫(xiě)緩存,其他線程等待

            • 做二級(jí)緩存,A1 為原始緩存,A2 為拷貝緩存,A1 失效時(shí),可以訪問(wèn) A2,A1 緩存失效時(shí)間設(shè)置為短期,A2 設(shè)置為長(zhǎng)期

            • 不同的 key,設(shè)置不同的過(guò)期時(shí)間,讓緩存失效的時(shí)間點(diǎn)盡量均勻

            • 如果緩存數(shù)據(jù)庫(kù)是分布式部署,將熱點(diǎn)數(shù)據(jù)均勻分布在不同的緩存數(shù)據(jù)庫(kù)中

            source:https://www.yuque.com/nashihuakai/qlwgtg/bwcko4

            喜歡,在看

            瀏覽 52
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            評(píng)論
            圖片
            表情
            推薦
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            <kbd id="afajh"><form id="afajh"></form></kbd>
            <strong id="afajh"><dl id="afajh"></dl></strong>
              <del id="afajh"><form id="afajh"></form></del>
                  1. <th id="afajh"><progress id="afajh"></progress></th>
                    <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    男人的天堂在线视频 | 成人三级在线播放 | 爱逼综合 | 91在线成人传媒 | 国产精品在线视频免费 |