快取擊穿,快取穿透和快取雪崩

2022-08-24 21:00:12 字數 1918 閱讀 4780

什麼是快取?

快取,就是資料交換的緩衝區,針對服務物件的不同(本質就是不同的硬體)都可以構建快取。

目的是,把讀寫速度慢的介質的資料儲存在讀寫速度快的介質中,從而提高讀寫速度,減少時間消耗。 例如:

磁碟快取:磁碟快取其實就把常用的磁碟資料儲存在記憶體中,記憶體讀寫速度也是遠高於磁碟的。

為什麼要用快取?

使用快取的目的,就是提公升讀寫效能。而實際業務場景下,更多的是為了提公升讀效能,帶來更好的效能,更高的併發量。

日常業務中,我們使用比較多的資料庫是 mysql,快取是 redis 。redis 比 mysql 的讀寫效能好很多。那麼,我們將 mysql 的熱點資料,快取到 redis 中,提公升讀取效能,也減小 mysql 的讀取壓力。例如說:

分布式快取系統面臨的問題

快取與資料庫雙寫不一致

一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求 「快取+資料庫」 必須保持一致性的話,最好不要做這個方案,即:讀請求和寫請求序列化,串到乙個記憶體佇列裡去。

序列化可以保證一定不會出現不一致的情況,但是它也會導致系統的吞吐量大幅度降低,用比正常情況下多幾倍的機器去支撐線上的乙個請求。

最經典的就是快取+資料庫讀寫的模式(cache aside pattern)。

快取穿透和快取雪崩快取穿透

概念:指查詢乙個一定不存在的資料,由於快取是不命中時被動寫,即從 db 查詢到資料,則更新到快取中,並且出於容錯考慮,如果從 db 查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要去 db 查詢,失去了快取的意義。在流量大時,db 可能就掛掉了。

舉個栗子。系統a,每秒 5000 個請求,結果其中 4000 個請求是黑客發出的惡意攻擊。資料庫 id 是從 1 開始的,而黑客發過來的請求 id 全部都是負數。這樣的話,快取中不會有,請求每次都「視快取於無物」,直接查詢資料庫。這種惡意攻擊場景的快取穿透就會直接把資料庫給打死。

解決方案:

方案一: 快取空物件,當從 db 查詢資料為空,我們仍然將這個空結果進行快取,具體的值需要使用特殊的標識, 能和真正快取的資料區分開,另外將其過期時間設為較短時間。

方案二: 使用布隆過濾器,在快取的基礎上,構建布隆過濾器資料結構,在布隆過濾器中儲存對應的 key,如果存在,則說明 key 對應的值為空。這樣整個業務邏輯如下:

快取雪崩

概念:快取由於某些原因無法提供服務,所有請求全部達到 db 中,導致 db 負荷大增,最終掛掉的情況。

比如,對於系統 a,假設每天高峰期每秒 5000 個請求,本來快取在高峰期可以扛住每秒 4000 個請求,但是快取機器意外發生了全盤宕機。快取掛了,此時 1 秒 5000 個請求全部落資料庫,資料庫必然扛不住,它會報一下警,然後就掛了。此時,如果沒有採用什麼特別的方案來處理這個故障,dba 很著急,重啟資料庫,但是資料庫立馬又被新的流量給打死了。

解決方案:

快取擊穿

概念:某個 key 非常熱點,訪問非常頻繁,處於集中式高併發訪問的情況,當這個 key 在失效的瞬間,大量的請求就擊穿了快取,直接請求資料庫,就像是在一道屏障上鑿開了乙個洞。

解決方案:

手動過期:redis 上從不設定過期時間,功能上將過期時間存在 key 對應的 value 裡,如果發現要過期,通過乙個後台的非同步執行緒進行快取的構建,也就是「手動」過期。

快取併發競爭

某個時刻,多個系統例項都去更新某個 key。可以基於 zookeeper 實現分布式鎖。每個系統通過 zookeeper 獲取分布式鎖,確保同一時間,只能有乙個系統例項在操作某個 key,別人都不允許讀和寫。

要寫入快取的資料都是從 mysql 裡查出來的,都得寫入 mysql 中,寫入 mysql 中的時候必須儲存乙個時間戳,從 mysql 查出來的時候,時間戳也要查出來。

每次要寫之前,先判斷一下當前這個 value 的時間戳是否比快取裡的 value 的時間戳要新。如果是的話,那麼可以寫,否則,就不能用舊的資料覆蓋新的資料。

快取穿透,快取雪崩和快取擊穿

q 快取穿透,是指查詢乙個資料庫一定不存在的資料。正常的使用快取流程大致是,資料查詢先進行快取查詢,如果key不存在或者key已經過期,再對資料庫進行查詢,並把查詢到的物件,放進快取。如果資料庫查詢物件為空,則不放進快取。a 1.布隆過濾器,將所有可能存在的資料雜湊到乙個足夠大的bitmap中,乙個...

快取擊穿 快取穿透和快取雪崩

快取擊穿 定義 快取中的key一般設有過期時間,如果某個key過期了,恰在這個時候,有大量的併發請求訪問這個key,則這些請求都會到達db,導致db瞬間壓力過大,壓垮db。解決方案 1.設定互斥鎖,mutex。當快取失效時不時立即去訪問資料庫,而是使用快取工具的操作成功帶返回值的操作,比如redis...

快取穿透 快取雪崩和快取擊穿

快取系統是我們平時開發經常使用到的,也是在高併發場景下減少或防止流量對db等底層系統衝擊的最有效手段之一。下面就簡單談談快取系統經常提及的三個問題以及解決方案。首先回憶下通常情況我們設定的快取機制,如下圖所示 快取載入機制 這套機制,由於出於容錯考慮,從儲存層查不到資料則不寫入快取,這就導致每次請求...