1. 程式人生 > >【高併發】面試官:講講什麼是快取穿透?擊穿?雪崩?如何解決?

【高併發】面試官:講講什麼是快取穿透?擊穿?雪崩?如何解決?

## 寫在前面 > 在前面的《[【高併發】Redis如何助力高併發秒殺系統?看完這篇我徹底懂了!!](https://mp.weixin.qq.com/s?__biz=Mzg3MzE1NTIzNA==&mid=2247487271&idx=1&sn=6bd9f4627357b1ec2353504f7db5381b&chksm=cee510eaf99299fcf5c841a5f5435edb29c9c08703982e07ed0ed8b327a28fd0ecd5e699df59&token=1430223481&lang=zh_CN#rd)》一文中,我們以高併發秒殺系統中扣減庫存的場景為例,說明了Redis是如何助力秒殺系統的。那麼,說到Redis,往往更多的場景是被用作系統的快取,說到快取,尤其是分散式快取系統,在實際高併發場景下,稍有不慎,就會造成快取穿透、快取擊穿和快取雪崩的問題。那什麼是快取穿透?什麼是快取擊穿,又什麼是快取雪崩呢?它們是如何造成的?又該如何解決呢?今天,我們就一起來探討這些問題。 ## 快取穿透 首先,我們來說說快取穿透。什麼是快取穿透呢?快取穿透問題在一定程度上與快取命中率有關。如果我們的快取設計的不合理,快取的命中率非常低,那麼,資料訪問的絕大部分壓力都會集中在後端資料庫層面。 ### 什麼是快取穿透? 如果在請求資料時,在快取層和資料庫層都沒有找到符合條件的資料,也就是說,在快取層和資料庫層都沒有命中資料,那麼,這種情況就叫作快取穿透。 我們可以使用下圖來表示快取穿透的現象。 ![](https://img-blog.csdnimg.cn/2020091314310366.png) 造成快取穿透的主要原因就是:查詢某個Key對應的資料,Redis快取中沒有相應的資料,則直接到資料庫中查詢。資料庫中也不存在要查詢的資料,則資料庫會返回空,而Redis也不會快取這個空結果。這就造成每次通過這樣的Key去查詢資料都會直接到資料庫中查詢,Redis不會快取空結果。這就造成了快取穿透的問題。 ### 如何解決快取穿透問題? 既然我們知道了造成快取穿透的主要原因就是快取中不存在相應的資料,直接到資料庫查詢,資料庫返回空結果,快取中不儲存空結果。 那我們就自然而然的想到了第一種解決方案:就是把空物件快取起來。當第一次從資料庫中查詢出來的結果為空時,我們就將這個空物件載入到快取,並設定合理的過期時間,這樣,就能夠在一定程度上保障後端資料庫的安全。 第二種解決快取穿透問題的解決方案:就是使用布隆過濾器,布隆過濾器可以針對大資料量的、有規律的鍵值進行處理。一條記錄是不是存在,本質上是一個Bool值,只需要使用 1bit 就可以儲存。我們可以使用布隆過濾器將這種表示是、否等操作,壓縮到一個數據結構中。比如,我們最熟悉的使用者性別這種資料,就非常適合使用布隆過濾器來處理。 ## 快取擊穿 如果我們為快取中的大部分資料設定了相同的過期時間,則到了某一時刻,快取中的資料就會批量過期。 ### 什麼是快取擊穿? 如果快取中的資料在某個時刻批量過期,導致大部分使用者的請求都會直接落在資料庫上,這種現象就叫作快取擊穿。 我麼可以使用下圖來表示快取擊穿的執行緒。 ![](https://img-blog.csdnimg.cn/20200913143139638.png) 造成快取擊穿的主要原因就是:我們為快取中的資料設定了過期時間。如果在某個時刻從資料庫獲取了大量的資料,並設定了相同的過期時間,這些快取的資料就會在同一時刻失效,造成快取擊穿問題。 ### 如何解決快取擊穿問題? 對於比較熱點的資料,我們可以在快取中設定這些資料永不過期;也可以在訪問資料的時候,在快取中更新這些資料的過期時間;如果是批量入庫的快取項,我們可以為這些快取項分配比較合理的過期時間,避免同一時刻失效。 還有一種解決方案就是:使用分散式鎖,保證對於每個Key同時只有一個執行緒去查詢後端的服務,某個執行緒在查詢後端服務的同時,其他執行緒沒有獲得分散式鎖的許可權,需要進行等待。不過在高併發場景下,這種解決方案對於分散式鎖的訪問壓力比較大。 ## 快取雪崩 如果快取系統出現故障,所有的併發流量就會直接到達資料庫。 ### 什麼是快取雪崩? 如果在某一時刻快取集中失效,或者快取系統出現故障,所有的併發流量就會直接到達資料庫。資料儲存層的呼叫量就會暴增,用不了多長時間,資料庫就會被大流量壓垮,這種級聯式的服務故障,就叫作快取雪崩。 我們可以用下圖來表示快取雪崩的現象。 ![](https://img-blog.csdnimg.cn/20200913143155718.png) 造成快取雪崩的主要原因就是快取集中失效,或者快取服務發生故障,瞬間的大併發流量壓垮了資料庫。 ### 如何解決快取雪崩問題? 解決快取雪崩問題最常用的一種方案就是保證Redis的高可用,將Redis快取部署成高可用叢集(必要時候做成異地多活),可以有效的防止快取雪崩問題的發生。 為了緩解大併發流量,我們也可以使用限流降級的方式防止快取雪崩。例如,在快取失效後,通過加鎖或者使用佇列來控制讀資料庫寫快取的執行緒數量。具體點就是設定某些Key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。則能夠有效的緩解大併發流量對資料庫打來的巨大沖擊。 另外,我們也可以通過資料預熱的方式將可能大量訪問的資料載入到快取,在即將發生大併發訪問的時候,提前手動觸發載入不同的資料到快取中,併為資料設定不同的過期時間,讓快取失效的時間點儘量均勻,不至於在同一時刻全部失效。 ## 重磅福利 關注「 **冰河技術** 」微信公眾號,後臺回覆 “**設計模式**” 關鍵字領取《**深入淺出Java 23種設計模式**》PDF文件。回覆“**Java8**”關鍵字領取《**Java8新特性教程**》PDF文件。回覆“**限流**”關鍵字獲取《**億級流量下的分散式限流解決方案**》PDF文件,三本PDF均是由冰河原創並整理的超硬核教程,面試必備!! **好了,今天就聊到這兒吧!別忘了點個贊,給個在看和轉發,讓更多的人看到,一起學習,一起進步!!** ## 寫在最後 > 如果你覺得冰河寫的還不錯,請微信搜尋並關注「 **冰河技術** 」微信公眾號,跟冰河學習高併發、分散式、微服務、大資料、網際網路和雲原生技術,「 **冰河技術** 」微信公眾號更新了大量技術專題,每一篇技術文章乾貨滿滿!不少讀者已經通過閱讀「 **冰河技術** 」微信公眾號文章,吊打面試官,成功跳槽到大廠;也有不少讀者實現了技術上的飛躍,成為公司的技術骨幹!如果你也想像他們一樣提升自己的能力,實現技術能力的飛躍,進大廠,升職加薪,那就關注「 **冰河技術** 」微信公眾號吧,每天更新超硬核技術乾貨,讓你對如何提升技術能力不再迷茫! ![](https://img-blog.csdnimg.cn/20200906013715