轉載,關於緩存穿透、緩存併發、緩存雪崩那些事

0 題記數據庫

緩存穿透、緩存併發和緩存雪崩是常見的因爲併發量大而致使的緩存問題,本文講解其產生緣由和解決方案。後端

緩存穿透一般是由惡意×××或者無心形成的;緩存併發是由設計不足形成的;緩存雪崩是由緩存同時失效形成的,三種問題都比較典型,也是難以防範和解決的。本節給出通用的解決方案,以供在緩存設計的過程當中參考和使用。設計模式

1 緩存穿透緩存

緩存穿透指的是使用不存在的key進行大量的高併發查詢,這致使緩存沒法命中,每次請求都要穿透到後端數據庫系統進行查詢,使數據庫壓力過大,甚至使數據庫服務被壓死。服務器

咱們一般將空值緩存起來,再次接收到一樣的查詢請求時,若命中緩存而且值爲空,就會直接返回,不會透傳到數據庫,避免緩存穿透。固然,有時惡意襲擊者能夠猜到咱們使用了這種方案,每次都會使用不一樣的參數來查詢,這就須要咱們對輸入的參數進行過濾,例如,若是咱們使用ID進行查詢,則能夠對ID的格式進行分析,若是不符合產生ID的規則,就直接拒絕,或者在ID上放入時間信息,根據時間信息判斷ID是否合法,或者是不是咱們曾經生成的ID,這樣能夠攔截必定的無效請求。架構

固然,每一個設計人員都應該對服務的可用性和健壯性負責,應該建設健壯的服務,讓咱們的服務像不倒翁同樣,所以,咱們須要對服務設計限流和熔斷等功能,請參考《分佈式服務架構:原理、設計與實戰》中第1章關於微服務設計模式的內容。併發

2 緩存併發異步

緩存併發的問題一般發生在高併發的場景下,當一個緩存key過時時,由於訪問這個緩存key的請求量較大,多個請求同時發現緩存過時,所以多個請求會同時訪問數據庫來查詢最新數據,而且回寫緩存,這樣會形成應用和數據庫的負載增長,性能下降,因爲併發較高,甚至會致使數據庫被壓死。分佈式

咱們一般有3種方式來解決這個問題。ide

分佈式鎖

使用分佈式鎖,保證對於每一個key同時只有一個線程去查詢後端服務,其餘線程沒有得到分佈式鎖的權限,所以只須要等待便可。這種方式將高併發的壓力轉移到了分佈式鎖,所以對分佈式鎖的考驗很大。

本地鎖

與分佈式鎖相似,咱們經過本地鎖的方式來限制只有一個線程去數據庫中查詢數據,而其餘線程只需等待,等前面的線程查詢到數據後再訪問緩存。可是,這種方法只能限制一個服務節點只有一個線程去數據庫中查詢,若是一個服務有多個節點,則還會有多個數據庫查詢操做,也就是說在節點數量較多的狀況下並無徹底解決緩存併發的問題。

軟過時

軟過時指對緩存中的數據設置失效時間,就是不使用緩存服務提供的過時時間,而是業務層在數據中存儲過時時間信息,由業務程序判斷是否過時並更新,在發現了數據即將過時時,將緩存的時效延長,程序能夠派遣一個線程去數據庫中獲取最新的數據,其餘線程這時看到延長了的過時時間,就會繼續使用舊數據,等派遣的線程獲取最新數據後再更新緩存。

也能夠經過異步更新服務來更新設置軟過時的緩存,這樣應用層就不用關心緩存併發的問題了。

3 緩存雪崩

緩存雪崩指緩存服務器重啓或者大量緩存集中在某一個時間段內失效,給後端數據庫形成瞬時的負載升高的壓力,甚至壓垮數據庫的狀況。

一般的解決辦法是對不一樣的數據使用不一樣的失效時間,甚至對相同的數據、不一樣的請求使用不一樣的失效時間,例如,咱們要緩存user數據,會對每一個用戶的數據設置不一樣的緩存過時時間,能夠定義一個基礎時間,假設10秒,而後加上一個兩秒之內的隨機數,過時時間爲10~12秒,就會避免緩存雪崩

相關文章
相關標籤/搜索