高併發狀態下快取失效及其解決辦法

2021-10-17 15:47:16 字數 1338 閱讀 3362

專案中使用redis快取,會存在各種各樣的問題,例如快取沒有命中,沒有查到資料,快取沒有使用到,這一系列的問題,簡單的說就是:快取穿透快取雪崩快取擊穿

快取穿透
當查詢乙個一定不存在的資料,由於快取中沒有這個資料,所以將會去資料庫中查詢,但是資料庫中也沒有這個資料,而我們在資料庫查詢到為null的資料沒有寫入快取,這將導致這個不存在的資料每次請求都會去資料庫中查詢,失去了快取的意義,這也會導致別人利用不存在的資料進行攻擊,資料庫瞬時壓力增大,最終導致奔潰。解決辦法:查詢到的null結果也進行快取,並加入短暫過期時間

快取雪崩
在我們設定快取時key採用了相同的過期時間,導致快取在某一時刻同時失效,請求全部**到資料庫,資料庫瞬時壓力過重雪崩。解決辦法:將失效時間改為隨機值,保證快取不在同一時間失效

快取擊穿
對於一些設定了過期時間的key,當在大量請求同時進來前這個key剛好失效,那麼所有的查詢都會**到資料庫。解決辦法:加鎖,大量併發只讓乙個請求去資料庫查詢,其他請求等待,查到以後在釋放鎖,其他請求獲取到鎖,先查詢快取,就會有資料

那麼怎麼解決這些問題,快取穿透和快取雪崩比較好解決。快取穿透在查詢到資料庫,如果查詢的結果為null,可以向快取中存放乙個標誌位,代表當前key的值為空,並且給這個key設定乙個較短的過期時間;而快取雪崩在將資料存到快取中時,設定不一樣的過期時間,可以通過隨機數獲取時間,保證key不會在同一時間過期;而快取擊穿的解決比較麻煩,所以本部落格會重點說明

快取擊穿的解決辦法是通過加鎖來解決的,但是我們現在的服務趨向於分布式系統,當專案用分布式進行部署時,會涉及到分布式鎖的使用,本文主要介紹單體應用下的本地鎖的使用,下一章部落格會重點說分布式鎖的使用

加鎖主要使用synchronized,可以修飾方法,也可以在方法內加synchronized**塊

public

void

testdemo()

}public

synchronized

void

testdemo()

本地鎖使用起來很簡單,主要是乙個關鍵字synchronized,但是現在我們的服務基本都是基於分布式的,如果在分布式中加本地鎖,那部署了幾個服務,就會有幾個鎖,在高併發狀態下,每個應用都只能鎖自己的服務,每個服務沒有在快取中查詢到資料,都會去資料庫查,這就是本地鎖在分布式中的現象,下一章說說在分布式應用中使用分布式鎖鎖住每個服務,保證只查詢一次資料庫

php高併發狀態下檔案的讀寫

背景 1 對於pv不高或者說併發數不是很大的應用,不用考慮這些,一般的檔案操作方法完全沒有問題 2 如果併發高,在我們對檔案進行讀寫操作時,很有可能多個程序對進一檔案進行操作,如果這時不對檔案的訪問進行相應的獨佔,就容易造成資料丟失 對於這樣的問題,一般的解決方案 1 當一程序對檔案進行操作時,首先...

binlog在併發狀態下的記錄

前兩天看binlog發現個奇怪的地方 對於position靠後的記錄,timestamp卻比之前的記錄還要小。當時覺得大概和併發有關係 後來做了個實驗 開兩個session 對於session1 begin insert into t1 values 1 insert into t1 values ...

讀 寫鎖的實現和應用(高併發狀態下的map實現)

程式中涉及到對一些共享資源的讀和寫操作,且寫操作沒有讀操作那麼頻繁。在沒有寫操作的時候,兩個執行緒同時讀乙個資源沒有任何問題,所以應該允許多個執行緒能在同時讀取共享資源。但是如果有乙個執行緒想去寫這些共享資源,就不應該再有其它執行緒對該資源進行讀或寫 譯者注 也就是說 讀 讀能共存,讀 寫不能共存,...