快取讀取術之防止快取雪崩

2021-08-15 18:25:33 字數 1690 閱讀 4773

如今許多網際網路應用系統都重度依賴快取來提高讀操作的效能,對於這些系統來說如何正確地使用快取至關重要。本文從快取讀取這個視角來討論快取架構設計上的一些思路。重點關注如何防止快取雪崩。

引入快取後,讀資料的流程如下:

在正常情況下,一旦miss就去查db是沒有問題的。但是如果大量快取集中在某一時間段失效,將導致所有請求都去訪問後端的db,db壓力會很大,甚至被壓垮,造成雪崩。

電商系統的某個大促活動的首頁,首頁有很多新上架的商品。活動開始前,技術團隊對快取做了預熱,由於是指令碼化預熱,這些商品的cache資料幾乎都是同時建立好,並且過期時間都設定為5分鐘。這就會導致這大量的商品資料在5分鐘後集中失效。

cache系統剛上線(或者剛從崩潰中恢復過來),沒有對cache進行預熱。cache中什麼也沒有,這時瞬時大流量過來也會產生雪崩。

針對上面的場景一,可以對cache的過期時間做乙個均勻分布的處理。比如1-5分鐘內,隨機分布。

針對場景二,可以考慮使用排斥鎖(mutex)。即第乙個執行緒過來讀取cache,發現沒有,就去訪問db。後續執行緒再過來就需要等待第乙個執行緒讀取db成功,cache裡的value變得可用,後續執行緒返回新的value。偽**如下:

public object getcachevalue(string key, int expiredtime)  else  else 

}} finally

return cachevalue;}}

方案細節:排斥鎖方案對快取過期是零容忍的:cache一旦過期,後續所有讀操作就必須返回新的value。如果我們稍微放寬點限制:在cache過期時間t到達後,允許短時間內部分讀請求返回舊值,我們就能提出兼顧吞吐率的方案。實際上既然用了cache,系統就默許了容忍cache和db的資料短時間的不一致。

限制放寬後,下面我們提出乙個優化思路。時間t到達後,cache中的key和value不會被清掉,而只是被標記為過期(邏輯上過期,物理上不過期),然後程式非同步去重新整理cache。而後續部分讀執行緒在前面的執行緒重新整理cache成功之前,暫時獲取cache中舊的value返回。一旦cache重新整理成功,後續所有執行緒就能直接獲取cache中新的value。可以看到,這個思路很大程度上減少了排斥鎖的使用(雖然並沒有完全消除排斥鎖)。 

下面先看下偽**:

public object getcachevalue(string key, int expiredtime)  else } }

} catch (exception ex) finally

});return cachevalue;

}}// 判斷快取標記是否過期

private

boolean

i***pired(string signkey)

return

false;

}// 設定signkey的過期時間

private

void

setsign(string key, int expiredseconds)

方案細節本文討論了防止快取雪崩的三個方案:

前兩個方案各自有適用的場景。第三個方案具備一定的通用性。也適用於方案一二的場景。是我推薦的方案

Redis快取設計之快取穿透 快取雪崩

提高系統響應速度,加速讀寫,redis將數全都存放在記憶體中,響應速度更快。降低了後台的負載,減少了對後端的直接訪問 資料一致性問題,快取層的資料與儲存層的資料可能存在不一致的問題 維護複雜度高了,加入快取後要同時處理快取曾和持久層的 邏輯 快取穿透就是指查詢乙個根本不存在的資料,導致很多請求直接穿...

快取穿透 快取雪崩

一 快取穿透 描述 快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為 1 的資料或id為特別大不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。解決方案 1 介面層增加校驗,如使用者鑑權校驗,id做基礎校驗,id 0的直接攔截 2 從快取取不到的資料,在...

快取之快取擊穿 穿透 雪崩

redis高頻面試題 快取穿透 概念 有乙個查詢介面,頻繁接受到資料庫中並不存在的查詢條件,每次根據key查詢快取中都查不到,則這些查詢請求紛紛落到資料庫上,請求量大,造成資料庫頻繁io最終宕機。例如介面是根據id獲取使用者,查詢引數為 1 2這種資料庫根本沒有的資料。解決方案 1.在redis中快...