<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 什么是熱點key重建 * 開發人員使用“緩存+過期時間”的策略既可以加速數據讀寫,又保證數據的定期更新,這種模式基本能夠滿足絕大部分需求。但是**有兩個問題如果同時出現,可能就會對應用造成致命的危害:** * 當前key是一個**熱點key**(例如一個熱門的娛樂新聞),并發量非常 大 * 重建緩存**不能在短時間完成,可能是一個復雜計算**,例如復雜的SQL、多次IO、多個依賴等 * **在緩存失效的瞬間,有大量線程來重建緩存**(如下圖所示),造成 后端負載加大,甚至可能會讓應用崩潰 ![](https://img.kancloud.cn/23/0c/230c8953cf8976d043e740fe92917b02_729x517.png) 要解決這個問題也不是很復雜,但是不能為了解決這個問題給系統帶來更多的麻煩,**所以需要制定如下目標:** ## 三個目標 * **減少重建緩存的次數** * **數據盡可能一致** * **較少的潛在危險** ## 互斥鎖 * 此方法**只允許一個線程重建緩存,其他線程等待重建緩存的線程執行完**,重新從緩存獲取數據即可,整個過程如下圖所示 ![](https://img.kancloud.cn/eb/93/eb93e3e3611ab9354a787fc2b65c408a_714x489.png) **下面代碼使用Redis的setnx命令實現上述功能:** * 1)從Redis獲取數據,如果值不為空,則直接返回值;否則執行下面的2.1)和2.2)步驟 * 2.1)如果set(nx和ex)結果為true,說明此時沒有其他線程重建緩存, 那么當前線程執行緩存構建邏輯 * 2.2)如果set(nx和ex)結果為false,說明此時已經有其他線程正在執 行構建緩存的工作,那么當前線程將休息指定時間(例如這里是50毫秒,取 決于構建緩存的速度)后,重新執行函數,直到獲取到數據 ``` String get(String key) { // 從Redis中獲取數據 String value = redis.get(key); // 如果value為空,則開始重構緩存 if (value == null) { // 只允許一個線程重構緩存,使用nx,并設置過期時間ex String mutexKey = "mutext:key:" + key; if (redis.set(mutexKey, "1", "ex 180", "nx")) { //鎖 // 從數據源獲取數據 value = db.get(key); // 回寫Redis,并設置過期時間 redis.setex(key, timeout, value); // 刪除key_mutex redis.delete(mutexKey); } // 其他線程休息50毫秒后重試 else { Thread.sleep(50); get(key); } } return value; } ``` ## 永遠不過期 * **“永遠不過期”包含兩層意思:** * **從緩存層面來看**,確實沒有設置過期時間,所以不會出現熱點key過期 后產生的問題,也就是“物理”不過期; * **從功能層面來看**,為每個value設置一個邏輯過期時間,當發現超過邏 輯過期時間后,會使用單獨的線程去構建緩存; * **整個過程如下圖所示:** ![](https://img.kancloud.cn/37/4f/374f503de5c4b102f605c3c15840baf9_704x704.png) * 從實戰看,此方法有效杜絕了熱點key產生的問題,但**唯一不足的就是重構緩存期間,會出現數據不一致的情況**,這取決于應用方是否容忍這種不 一致 ``` String get(final String key) { V v = redis.get(key); String value = v.getValue(); // 邏輯過期時間 long logicTimeout = v.getLogicTimeout(); // 如果邏輯過期時間小于當前時間,開始后臺構建 if (v.logicTimeout <= System.currentTimeMillis()) { String mutexKey = "mutex:key:" + key; if (redis.set(mutexKey, "1", "ex 180", "nx")) { // 重構緩存 threadPool.execute(new Runnable() { public void run() { String dbValue = db.get(key); redis.set(key, (dbvalue,newLogicTimeout)); redis.delete(mutexKey); } }); } } return value; } ``` ## 總結 * **作為一個并發量較大的應用,在使用緩存時有三個目標:** * 第一,加快用戶訪問速度,提高用戶體驗 * 第二,降低后端負載,減少潛在的風險,保證系統平穩 * 第三,保證數據“盡可能”及時更新 * **下面將按照這三個維度對上 述兩種解決方案進行分析:** * **互斥鎖(mutex key)**:這種方案思路比較簡單,但是存在一定的隱患,如果構建緩存過程出現問題或者時間較長,可能會存在死鎖和線程池阻塞的風險,但是這種方法能夠較好地降低后端存儲負載,并在一致性上做得比較好 * **“永遠不過期”**:這種方案由于沒有設置真正的過期時間,實際上已經 不存在熱點key產生的一系列危害,但是會存在數據不一致的情況,同時代碼復雜度會增大 * **兩種解決方法對比如下圖所示:** ![](https://img.kancloud.cn/59/0b/590bfb4208ceb31d67f8ca022f7491ae_735x194.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看