【Java面試】怎麼防止快取擊穿的問題?

「怎麼防止快取擊穿?」

這是很多一二線大廠面試的時候考察頻率較高的問題。

在並發量較高的系統中,快取可以提升數據查詢的性能,還能緩解後端存儲系統的並發壓力。可謂是屢試不爽的利器。

我把這個問題的回答,整理到了一個20W字的面試文檔裡面。大家可以私信我領取。

下面看看高手的回答。

高手:

在實際應用中,我們會在程式和資料庫之間增加一個快取層。

一方面是為了提升數據檢索效率,提升程式性能,另一方面是為了緩解資料庫的並發壓力。

image-20220706143157312

快取擊穿,表示請求因為某些原因全部打到了資料庫,快取並沒有起到流量緩衝的作用。

我認為有2種情況會導致快取擊穿。

  • 在Redis裡面保存的熱點key,在快取過期的瞬間,有大量請求進來,導致請求全部打在資料庫上。

  • 客戶端惡意發起大量不存在的key的請求,由於訪問的key對應的數據本身就不存在,所以每次必然都會穿透到資料庫,導致快取成為了擺設。

總之,當Redis承擔了流量緩衝功能的時候,就需要考慮到Redis失效導致並發壓力過大對後端存儲設備造成衝擊的問題。

因此,我認為可以通過幾種方法來解決。

  1. 對於熱點數據,我們可以不設置過期時間,或者在訪問數據的時候對數據過期時間進行續期。

  2. 對於訪問量較高的快取數據,我們可以設計多級快取,盡量減少後端存儲設備的壓力。

  3. 使用分散式鎖,當發現快取失效的時候,不是先從資料庫載入,而是先獲取分散式鎖,獲得分散式鎖的執行緒從資料庫查詢數據後寫回到快取裡面。

    後續沒有獲得鎖的執行緒就只需要等待和重試即可。

    這個方案犧牲了一定的性能,但是確保護了資料庫避免被壓垮。

  4. 對於惡意攻擊類的場景,可以使用布隆過濾器,應用啟動的時候把存在的數據快取到布隆過濾器裡面。

    每一次請求進來的時候先訪問布隆過濾器,

    如果不存在,則說明這個數據一定沒有在資料庫裡面,就沒必要再去訪問資料庫了。

另外,我們在整個快取架構設計中,除了儘可能避免快取穿透的問題,還需要從全局視角做整體考慮

比如業務隔離、多級快取、部署隔離、安全性考慮等。

總結

在我看來,很多面試題,其實更多的是考察求職者的技術底蘊以及思維邊界,有些問題不一定會有答案,或者說在面試的過程中不一定立刻能提出非常好的解決辦法我們只需要說大概的方向和思路即可。

大家記得點贊、收藏加關注!!!

file

版權聲明:本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Mic帶你學架構
如果本篇文章對您有幫助,還請幫忙點個關注和贊,您的堅持是我不斷創作的動力。歡迎關注「跟著Mic學架構」公眾號公眾號獲取更多技術乾貨!