一提到Redis緩存,我們不得不了解的三個問題就是:緩存雪崩、緩存擊穿和緩存穿透。這三個問題一旦發生,會導致大量的請求直接請求到數據庫層。如果並發壓力大,就會導致數據庫崩潰。那p0級的故障是沒跑了。

今天我們就來詳細的了解這個三個問題誘因以及如何解决。沒有點關注,記得先點個關注吧。 廢話不多說,我們直接開搞!!!

一、緩存雪崩

什麼是緩存雪崩?緩存雪崩就是大量請求無法在redis緩存中進行處理,而是直接發送到了數據庫層,使得數據庫壓力陡增。就好像redis一下子突然失效了一樣。一般造成緩存雪崩主要有兩個原因,我們來一一分析一下。

1.緩存中大量數據同時過期

緩存中大量數據同時過期,就會導致大量請求無法在redis緩存層面進行處理。具體來說,就是給redis中大量數據設置了相同的過期時間,一旦它們同時失效,應用就會把請求直接發送給數據庫,直接從數據庫中讀取數據。如果應用的並發量很大,那數據庫的壓力就會很大。如下圖所示:    針對大量數據同時失效帶來的緩存雪崩問題,我們一般采取以下兩種解决方案。   (1)我們在開發過程中要避免給大量數據設置相同的過期時間。我們可以在給數據設置過期時間時給時間加一個很小的隨機數,這樣不同數據的過期時間就會有所差別,但差別也不會太大,保證數據在一定範圍內過期,從而滿足業務層要求同時過期的需要。   (2)服務降級。所謂的服務降級,是指發生緩存雪崩後,針對不同的數據采取不同的策略。

  • 當業務訪問非核心數據時(例如商品屬性信息),我們直接返回預定義的信息。
  • 當業務訪問的是如庫存數據等核心數據時,仍然允許查詢緩存,如果緩存缺失,也可以從數據庫中繼續讀取。

這樣一來,只有部分過期的數據會訪問數據庫,所以數據庫壓力就沒那麼大。

2.Redis實例發生故障

當Redis實例發生故障,那就相當於緩存已經廢掉了,所以大量請求會直接請求數據庫,造成數據庫壓力變大,甚至宕機。針對這種情况發生的緩存雪崩,我們有以下兩種處理方式。 (1)在業務系統側實現服務熔斷或請求限流機制    所謂的服務熔斷,就是指在發生緩存雪崩時,為了防止大流量直接打到數據庫,我們會暫停對緩存系統的訪問。當上層應用訪問緩存時,緩存接口不會去訪問Redis實例,而是直接返回。等redis恢複後,再允許應用程序請求緩存系統。這樣就會避免因為redis緩存宕機,導致數據庫壓力陡增的情况。

服務熔斷雖然可以保證數據庫不被崩潰,但是暫停了整個服務的訪問,對業務的影響範圍大,為了减小對上層服務的影響,我們一般采用請求限流。請求限流是指業務系統去控制每秒進入系統的請求數,避免過多的請求被發送到數據庫。比如正常運行時,業務系統每秒進入的請求是1萬個,其中有80%在緩存中就可以處理了,有20%會去數據庫中處理。一旦發生緩存雪崩,100%的流量就會請求數據庫,為了不造成數據庫崩潰,我們就可以啟動請求限流機制。業務系統只允許30%的流量進入,而70%的流量被拒絕服務。這也是目前主流大廠常用的方法,比如在某個明星爆出大瓜後,我們刷微博經常刷不出來,多刷幾次就能進入,那就是因為做了服務降級。只允許一部分流量進入。

(2)使用高可靠集群
    我們可以通過主從節點來部署高可靠的Redis集群。當主節點掛掉後,從節點還可以切換成主節點。

二、緩存擊穿

緩存擊穿是指針對某個熱點數據,無法在緩存中進行處理,然後訪問該數據的大量請求,一下子都發到後端數據庫中,導致數據庫壓力激增。對於緩存擊穿的情况,經常發生在熱點數據過期失效時

為了避免這種情况發生,最常采取的措施就是對於訪問特別頻繁的熱點數據,我們就不設置過期時間了。這樣一來,對熱點數據的訪問,都可以在緩存中進行。\

三、緩存穿透

緩存穿透是指要訪問的數據既不在緩存中,也不在數據庫中,會導致請求緩存時,發生緩存缺失,然後請求數據庫,發現數據庫中也沒有需要的數據。這樣一來,緩存就成了“擺設”,如果有大量的這種請求,就會給數據庫帶來很大的壓力。

這個問題一般都是黑客進行惡意攻擊造成的。為了避免這種問題發生,我們有三種解决方式。

1、緩存空值或者缺省值

一旦發生緩存穿透,我們就可以在redis中設置一個空值或者給定的某個缺省值。這樣,業務應用的後續這種請求,都可以命中緩存。這樣就避免了把大量請求發送給數據庫了。

2、使用布隆過濾器來快速判斷數據是否存在

這裏我們先來解釋一下什麼是布隆過濾器。

布隆過濾器由一個初值都為0的bit數組和N個哈希函數組成,可以用來快速判斷某個數據是否存在。當我們想標記某個數據存在時,布隆過濾器會通過三個操作來完成標記:

  • 首先,使用N個哈希函數,分別計算數據的哈希值,得到N個哈希值。
  • 然後把這N個哈希值對bit數組的長度取模,得到每個哈希值在數組中的比特置。
  • 最後,我們把對應比特置的bit比特設置為1,這樣就完成了布隆過濾器中標記數據的操作。

如果數據不存在,也就是我們沒有用布隆過濾器標記過,bit數組對應的bit比特為0。
   當我們需要判斷某個數據是否存在時,我們就執行上面的計算過程,我們先求出這個數據對應的hash值,然後取模,然後去bit數組查這N個比特置上的bit值。只要這N個bit值有一個不為1,就錶明這個數據沒有被標記過。
   基於布隆過濾器的快速檢測特性,我們可以把數據寫入數據庫時,使用布隆過濾器做個標記,當緩存失效後,上層應用查詢數據庫時,可以通過查詢布隆過濾器快速判斷數據是否存在。如果不存在,就不用在去數據庫中去查了。這樣一來,即使發生緩存穿透,也不會對數據庫造成壓力。

3、業務層對請求進行檢測

緩存穿透發生的原因主要就是惡意請求訪問不存在的數據,所以業務層接受到請求後,一定要進行合法性檢測,把惡意請求給過濾掉,這樣就可以避免緩存穿透的問題了。

今天我們就聊到這裏,下一次我們來聊聊Redis分布式鎖的問題,如果感興趣,記得關注一波哦。

作者:程序員學長
鏈接:https://juejin.cn/post/6996567228820750343/
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

害...原來阿裏面試Redis最常問的是它呀的更多相關文章

  1. 金九銀十跳槽高峰,面試必備之 Redis + MongoDB 常問80道面試題

    前言 有著“金九銀十”之稱的招聘旺季已經開啟,跳槽高峰期也如約而至. 本文為主要是 Redis + MongoDB 知識點的攻略,希望能幫助到大家. 內容較多,大家准備好耐心和瓜子礦泉水. Redis ...

  2. 大廠面試官最常問的@[email protected](JDKConfig編程方式)

    大廠面試官最常問的@[email protected](JDKConfig編程方式)   現在大部分的Spring項目都采用了基於注解的配置,采用了@Configuration 替換標簽的做法.一 ...

  3. Java面試官最常問的volatile關鍵字

    在Java相關的職比特面試中,很多Java面試官都喜歡考察應聘者對Java並發的了解程度,以volatile關鍵字為切入點,往往會問到底,Java內存模型(JMM)和Java並發編程的一些特點都會被牽扯 ...

  4. 手撕面試官系列(十一):BAT面試必備之常問85題

    JVM專題 (面試題+答案領取方式見側邊欄)  Java 類加載過程? 描述一下 JVM 加載 Class 文件的原理機制? Java 內存分配. GC 是什麼? 為什麼要有 GC? 簡述 Java ...

  5. 深度分析:面試騰訊,阿裏面試官都喜歡問的String源碼,看完你學會了嗎?

    前言 最近花了兩天時間,整理了一下String的源碼.這個整理並不全面但是也涵蓋了大部分Spring源碼中的方法.後續如果有時間還會將剩餘的未整理的方法更新到這篇文章中.方便以後的複習和面試使用.如果 ...

  6. 面試有關TCP常問的幾個問題

    在面試中網絡問題是一定會考察的,而TCP協議則是考察網絡知識的重點.經常會被問道的問題如下: 請講一下TCP協議建立連接的過程 請介紹TCP協議中的三次握手和四次揮手是怎麼樣的 為什麼TCP協議要三次 ...

  7. HTML5 面試中最常問到的 10 個問題

    1. HTML5 新的 DocType 和 Charset 是什麼?HTML5 現在已經不是 SGML 的子集,DocType 簡化為:                  <!doctype h ...

  8. 手撕面試官系列(十):面試必備之常問Dubbo29題+MySQL55題

    Dubbo專題 (面試題+答案領取方式見側邊欄) 1.Dubbo 支持哪些協議,每種協議的應用場景,優缺點?2.Dubbo 超時時間怎樣設置?3.Dubbo 有些哪些注册中心?4.Dubbo 集群的負 ...

  9. 阿裏面試官最喜歡問的21個HashMap面試題

    1.HashMap 的數據結構? A:哈希錶結構(鏈錶散列:數組+鏈錶)實現,結合數組和鏈錶的優點.當鏈錶長度超過 8 時,鏈錶轉換為紅黑樹. transient Node<K,V>\[\ ...

  10. 阿裏面試這樣問:redis 為什麼把簡單的字符串設計成 SDS?

    2021開工第一天,就有小夥伴私信我,還給我分享了一道他面阿裏的redis題(這家夥絕比已經拿到年終獎了),我看了以後覺得挺有意思,題目很簡單,是那種典型的似懂非懂,常常容易被大家忽略的問題.這裏整理 ...

隨機推薦

  1. C# I/O

    獲取運行時的動態目錄 private static string GetDataDir_Data() { var parent = Directory.GetParent(Directory.GetC ...

  2. php後臺權限管理

    今天新到一家公司,重新維護昇級了之前的權限管理. 權限管理思路:1.三張錶(公司項目比較複雜,所以數據錶遠比這個複雜,這裏只實現權限管理,簡化一下)action錶------權限大菜單:這個錶沒有實際 ...

  3. 北京VR視頻外包團隊:全景VR視頻科普

    近期很多用戶資訊問關於全景視頻,這裏動點給大家介紹一下: 首先,全景360VR視頻(全景視頻使用VR設備控制)是一種特殊的視頻形式,與普通視頻的最大區別就是,全景視頻的每一幀都是涵蓋360度空間場景信 ...

  4. A version is required for an API group definition.

    A version is required for an API group definition.

  5. Two shortest

    sgu185:http://acm.sgu.ru/problem.php?contest=0&problem=185 題意:找兩條最短路徑,沒有邊相交的最短路勁,並且輸出路徑. 題解:這一題和 ...

  6. 讀《不要告訴我你懂margin(海玉的博客)》有感

    原文來自海玉的博客:http://www.hicss.net/do-not-tell-me-you-understand-margin/ [個人想法] 1."這個問題發生的原因是根據規範,一 ...

  7. VC中獲取窗口控件相對客戶區的坐標

    1: RECT rect; 2: GetDlgItem(item_id).GetWindowRect(&rect); 3: ScreenToClient(&rect);

  8. keepalived工作原理

    keepalived是一個類似於Layer2,4,7交換機制的軟件.是Linux集群管理中保證集群高可用的一個服務軟件,其功能是用來防止單點故障.   keepalived的工作原理:         ...

  9. mysql 好文章

    http://my.oschina.net/OpenSourceBO/blog/353464 http://www.oschina.net/p/cobar mysql集群 http://www.dew ...

  10. mongodb 遇到的問題一 Error: connect ECONNREFUSED 127.0.0.1:27017

    node配合mongodb是配置完成後,訪問時出現 Error: connect ECONNREFUSED 127.0.0.1:27017,的報錯 原因在於你的mongodb數據庫沒開, node下的 ...