緩存內功心法:緩存基礎整理

来源:https://www.cnblogs.com/yuxiang1/archive/2019/08/30/11437196.html
-Advertisement-
Play Games

緩存雪崩 緩存雪崩是由於原有緩存失效(過期),新緩存未到期間。所有請求都去查詢資料庫,而對資料庫CPU和記憶體造成巨大壓力,嚴重的會造成資料庫宕機。從而形成一系列連鎖反應,造成整個系統崩潰。 解決方法: 一般併發量不是特別多的時候,使用最多的解決方案是加鎖排隊。 給每一個緩存數據增加相應的緩存標記,記 ...


緩存雪崩

緩存雪崩是由於原有緩存失效(過期),新緩存未到期間。所有請求都去查詢資料庫,而對資料庫CPU和記憶體造成巨大壓力,嚴重的會造成資料庫宕機。從而形成一系列連鎖反應,造成整個系統崩潰。

解決方法:

  1. 一般併發量不是特別多的時候,使用最多的解決方案是加鎖排隊。

  2. 給每一個緩存數據增加相應的緩存標記,記錄緩存的是否失效,如果緩存標記失效,則更新數據緩存。

    • 緩存標記:記錄緩存數據是否過期,如果過期會觸發通知另外的線程在後臺去更新實際key的緩存。
    • 緩存數據:它的過期時間比緩存標記的時間延長1倍,例:標記緩存時間30分鐘,數據緩存設置為60分鐘。 這樣,當緩存標記key過期後,實際緩存還能把舊數據返回給調用端,直到另外的線程在後臺更新完成後,才會返回新緩存。

加鎖排隊方案偽代碼:

//偽代碼
public object GetProductListNew() {
    int cacheTime = 30;
    String cacheKey = "product_list";
    String lockKey = cacheKey;

    String cacheValue = CacheHelper.get(cacheKey);
    if (cacheValue != null) {
        return cacheValue;
    } else {
        synchronized(lockKey) {
            cacheValue = CacheHelper.get(cacheKey);
            if (cacheValue != null) {
                return cacheValue;
            } else {
                //這裡一般是sql查詢數據
                cacheValue = GetProductListFromDB();
                CacheHelper.Add(cacheKey, cacheValue, cacheTime);
            }
        }
        return cacheValue;
    }
}

 

緩存標記方案偽代碼:

//偽代碼
public object GetProductListNew() {
    int cacheTime = 30;
    String cacheKey = "product_list";
    //緩存標記
    String cacheSign = cacheKey + "_sign";

    String sign = CacheHelper.Get(cacheSign);
    //獲取緩存值
    String cacheValue = CacheHelper.Get(cacheKey);
    if (sign != null) {
        return cacheValue; //未過期,直接返回
    } else {
        CacheHelper.Add(cacheSign, "1", cacheTime);
        ThreadPool.QueueUserWorkItem((arg) -> {
            //這裡一般是 sql查詢數據
            cacheValue = GetProductListFromDB();
            //日期設緩存時間的2倍,用於臟讀
            CacheHelper.Add(cacheKey, cacheValue, cacheTime * 2);
        });
        return cacheValue;
    }
}

 

緩存穿透

緩存穿透是指用戶查詢數據,在資料庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到,每次都要去資料庫再查詢一遍,然後返回空(相當於進行了兩次無用的查詢)。這樣請求就繞過緩存直接查資料庫,這也是經常提的緩存命中率問題。

解決方案:

  1. 布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
  2. 如果一個查詢返回的數據為空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。通過這個直接設置的預設值存放到緩存,這樣第二次到緩衝中獲取就有值了,而不會繼續訪問資料庫,這種辦法最簡單粗暴!

方案二偽代碼:

//偽代碼
public object GetProductListNew() {
    int cacheTime = 30;
    String cacheKey = "product_list";

    String cacheValue = CacheHelper.Get(cacheKey);
    if (cacheValue != null) {
        return cacheValue;
    }

    cacheValue = CacheHelper.Get(cacheKey);
    if (cacheValue != null) {
        return cacheValue;
    } else {
        //資料庫查詢不到,為空
        cacheValue = GetProductListFromDB();
        if (cacheValue == null) {
            //如果發現為空,設置個預設值,也緩存起來
            cacheValue = string.Empty;
        }
        CacheHelper.Add(cacheKey, cacheValue, cacheTime);
        return cacheValue;
    }
}

 

緩存預熱

緩存預熱這個應該是一個比較常見的概念,相信很多小伙伴都應該可以很容易的理解,緩存預熱就是系統上線後,將相關的緩存數據直接載入到緩存系統。這樣就可以避免在用戶請求的時候,先查詢資料庫,然後再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!

解決思路:

  1. 直接寫個緩存刷新頁面,上線時手工操作下;
  2. 數據量不大,可以在項目啟動的時候自動進行載入;
  3. 定時刷新緩存;

緩存更新

除了緩存伺服器自帶的緩存失效策略之外,我們還可以根據具體的業務需求進行自定義的緩存淘汰,常見的策略有兩種:

  1. 定時去清理過期的緩存。
  2. 當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統得到新數據並更新緩存。

緩存降級

當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級。

降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的。

在進行降級之前要對系統進行梳理,看看系統是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;比如可以參考日誌級別設置預案:

(1)一般:比如有些服務偶爾因為網路抖動或者服務正在上線而超時,可以自動降級;

(2)警告:有些服務在一段時間內成功率有波動(如在95~100%之間),可以自動降級或人工降級,併發送告警;

(3)錯誤:比如可用率低於90%,或者資料庫連接池被打爆了,或者訪問量突然猛增到系統能承受的最大閥值,此時可以根據情況自動降級或者人工降級;

(4)嚴重錯誤:比如因為特殊原因數據錯誤了,此時需要緊急人工降級。

------------------------推薦閱讀------------------------

2019年JVM最新面試題,必須收藏它

最全面的阿裡多線程面試題,你能回答幾個?

Java面試題:Java中的集合及其繼承關係

花了近十年的時間,整理出史上最全面Java面試題

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [TOC] SpringBoot基礎(二) 一、操作資料庫 1. SpringBootJdbc 1. 引入依賴 jdbc 和 mysql 2. SpringBoot預設支持的連接池策略,如果使用 jdbc 或者 jpa 就會自動連接連接池 優先尋找創建Tomcat連接池 如果沒有Tomcat連接池, ...
  • 安裝 首先安裝memory_profiler和psutil 在需要分析的函數前面添加裝飾器@profile 運行call後的輸出: Line Mem usage Increment Line Contents ============================================= ...
  • java代碼是否一定按順序執行? 這個問題聽起來有點蠢,串列的代碼確實會按代碼語意正確的執行,但是編譯器對於代碼本身的優化卻並不一定會按實際的代碼一步一步的執行。 比如: r1=a; r2=r1.x; r3=r1.x; 編譯器則可能會進行優化,將r3=r1.x這條指令替換成r3=r2,這就是指令的重 ...
  • 函數中使用全局變數 執行fun()後返回值為:500 a, b使用的是全局變數的值。 函數中覆蓋全局變數 執行fun()後返回值為:50 a, b使用的是局部變數的值。 函數中修改改全局變數 執行fun()後返回值為:110 a使用的是全局變數a=100的值, b使用的是函數func修改後b的值10 ...
  • 一、基本選擇器 1.標簽選擇器 標簽選擇器會選中所有的標簽元素,是“共性”,而不是“特性”。 2.id選擇器 由於同一個頁面中id不能重覆,所以id選中的是特性,而不是共性。 3.類選擇器 由於同一個頁面中類名可以重覆,所以選中的是共性。 重點:公共類 到底是使用id還是class? 儘可能使用cl ...
  • HttpSessionActivationListener 監聽HttpSession對象的活化、鈍化 鈍化:將HttpSession對象從記憶體中轉移至硬碟,存儲為.session文件。 活化:把HttpSession對象從持久化狀態轉變為運行狀態(從硬碟載入到記憶體,恢複原樣)。 HttpSessi ...
  • 12.33 Django框架簡介: MVC,全名是Model View Controller,是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等優點 Django框架的設計模式借鑒 ...
  • 1.下載idlex-1.18.zip 網址:https://zh.osdn.net/projects/sfnet_idlex/ 2.解壓idlex-1.18.zip 2.解壓idlex-1.18.zip (1)將LineNumbers.py(idlex-1.18\idlexlib\extension ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...