阿里面試官帶你一步步理解面試常問的緩存擊穿、緩存穿透和緩存雪崩

阿里面試官帶你一步步理解面試常問的緩存擊穿、緩存穿透和緩存雪崩

1、前言

對於使用過Redis的同窗,必定聽過緩存擊穿、緩存穿透或者緩存雪崩吧?這是緩存系統最多見的幾個問題。 可是我相信不少同窗對這三個之間的概念都是模模糊糊的,今天這篇文章就是爲了說明這三者之間的區別,以及若是解決這些問題。但願你在面試相關問題時能夠準確的回答。面試

2、緩存穿透

通常的緩存系統,都是按照key去緩存查詢,若是不存在對應的value,就應該去後端系統查找(好比DB)。若是key對應的value是必定不存在的,而且對該key併發請求量很大,就會對後端系統形成很大的壓力。redis

也就是說,對不存在的key進行高併發訪問,致使數據庫壓力瞬間增大,這就叫作【緩存穿透】數據庫

解決方案:對查詢結果爲空的狀況也進行緩存,緩存時間設置短一點,或者該key對應的數據insert了以後清理緩存。後端

3、緩存雪崩

當緩存服務器重啓或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(好比DB)帶來很大壓力。緩存

忽然間大量的key失效了或redis重啓,大量訪問數據庫而致使的系統壓力劇增問題就是緩存雪崩啦服務器

解決方案:併發

  1. key的失效期分散開,不一樣的key設置不一樣的有效期;
  2. 設置二級緩存;
  3. 高可用方案,好比redis集羣,保證不會由於緩存系統崩潰而致使緩存雪崩;

4、緩存擊穿

對於一些設置了過時時間的key,若是這些key可能會在某些時間點被超高併發地訪問,是一種很是「熱點」的數據。這個時候,須要考慮一個問題:緩存被「擊穿」的問題,這個和緩存雪崩的區別在於這裏針對某一key緩存,前者則是不少key。分佈式

緩存在某個時間點過時的時候,剛好在這個時間點對這個Key有大量的併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。ide

解決方案:用分佈式鎖控制訪問的線程,如:使用redis的setnx互斥鎖先進行判斷,這樣其餘線程就處於等待狀態,保證不會有大併發操做去操做數據庫。高併發

if(redis.sexnx()==1){ //先查詢緩存 //查詢數據庫 //加入緩存 }

5、緩存雙寫一致性

這個問題是業務開發中常見的問題,那就是在寫redis和數據庫時如何保證數據的一致性呢? 若是你還不瞭解什麼狀況下會出現雙寫一致性問題,那麼下面我來舉幾個例子,你們看看是否是很熟悉?大家日常是否是就是這麼來使用redis的呢?

先更新數據庫再更新緩存(不建議使用)

操做步驟(線程A和線程B都對同一數據進行更新操做):

線程A更新了數據庫
線程B更新了數據庫
線程B更新了緩存
線程A更新了緩存

顯而易見,這面這種操做的問題在於:髒讀、浪費性能

先更新數據庫再刪除緩存

操做步驟

請求A進行寫操做,刪除緩存,此時A的寫操做尚未執行完
請求B查詢發現緩存不存在
請求B去數據庫查詢獲得舊值
請求B將舊值寫入緩存
請求A將新值寫入數據庫

此方案,能夠看到在步驟4會將舊值最後寫入緩存,最終形成髒讀;

先刪除緩存再更新數據庫

操做步驟

用戶A刪除緩存失敗
用戶A成功更新了數據

或者

用戶A刪除了緩存;
用戶B讀取緩存,緩存不存在;
用戶B從數據庫拿到舊數據;
用戶B更新了緩存;
用戶A更新了數據;

按照上面的步驟,此方案也是會出現髒讀問題,致使數據雙寫不一致而引起業務系統異常。

這裏給出幾種解決方案:

  • 解決方案1:設置緩存有效時間(最簡單),在接受最終一致性的場景下,配置合理的失效時間。
  • 解決方案2:使用消息隊列,例如rocketMq等消息隊列能夠保證數據操做順序一致性,確保緩存系統的數據正常。

這就是Redis緩存系統常常問的 緩存擊穿、緩存雪崩、緩存擊穿 之間的區別,雖然這幾個概念聽着很是的類似,實質上在定義上仍是有一些細微的區別。同時也介紹了在業務系統使用中常見的 數據雙寫緩存一致性 問題的場景和推薦的解決方案,但願能幫助到你們。

相關文章
相關標籤/搜索