通常應用中會使用資料庫來作為資料儲存,但是資料庫面向磁碟,磁碟的讀寫速度比較慢,不合適處理高併發的應用場景,為了避免高併發場景下瞬間大量訪問db導致資料庫系統癱瘓的問題,我們通常會使用快取來提高系統支援高併發的能力。快取一般都是基於記憶體的資料庫,讀寫效率相比於磁碟讀寫都有大幅提公升,但引入快取後相應也會引入一些快取相關的問題。
下面我們以redis為例,來分析這些問題並給出對應的解決方案。
快取穿透指的是資料來源(通常是db)中,沒有key對應的資料來源,因此請求這類不存在的key,在快取中獲取不到的話就需要直接請求資料來源,請求併發量大的話就會給資料來源造成壓力和風險。
針對這類問題,有兩個常用的解決方案:
1.即使查詢資料來源沒有該key對應的值,也在快取中快取該key,並設定空的value值。需要注意的是,必須給這種key設定乙個短的過期時間,在這段時間內資料來源新增了這個key對應的記錄但是獲取不到的情況。由此可見,該方案存在乙個問題就是新增的記錄可能存在不能立即生效的問題。
2.第二種方案是使用布隆過濾器,將可能的key值資料取雜湊儲存到乙個bitmap中,通過判斷key值是否在bitmap內來避免向資料來源請求不存在的記錄。
快取擊穿和快取穿透不同,快取穿透是請求不存在key記錄,而快取擊穿請求的key在資料來源中是有對應的記錄的。對於熱點資料的key,如果剛好在快取過期的時間後有大量併發請求,就會給資料來源造成服務崩潰風險。
針對這一問題,通常的方案是加互斥鎖,只有獲取鎖的執行緒可以請求資料來源,其他請求可以等待重試獲取快取。
對於redis來說,可以通過setnx
操作來設定乙個互斥key來實現互斥鎖,設定成功則代表成功獲取鎖。需要注意的是需要給互斥key來設定乙個過期時間,避免死鎖問題。
此外,也可以設定熱點資料不過期來解決這類問題。
快取擊穿是針對某乙個key過期時的併發問題,而快取雪崩是快取伺服器重啟或者大量快取集中在乙個時間段過期,導致大量併發請求直接打到資料來源,造成資料來源服務崩潰。
快取雪崩的幾個解決方案:
採用隨機的過期時間。可以在設定快取過期時間時,盡量分散各個key的過期時間避免集中過期的場景
使用鎖或者佇列。通過鎖或者佇列來避免所有請求直接請求資料庫。這種會導致執行緒阻塞,可能影響使用者體驗。
快取標記。通過記錄快取資料是否過期,如果過期則通知專門的執行緒來處理實際key的更新。
快取使用的是記憶體資源,相比於磁碟儲存來說可以快取的資料有限的。快取溢位是指快取的資料達到上限,無法快取更多的資料。
這種問題的解決方案通常是給快取設定一定的淘汰策略,一般使用lru(least recently used)。最近最少使用的key會被優先淘汰。
快取資料在記憶體中,如果快取伺服器宕機或者重啟,記憶體中的資料就會丟失。
針對這一問題,主要依賴於快取服務的持久化。redis提供了兩種資料持久化的方案,一種是rdb,一種是aof。
rdb是在指定的時間間隔內生成資料集的時間點快照,是乙個非常緊湊的檔案,適用於災難恢復,同時資料備份時只需要分配乙個子程序來處理資料儲存工作,父程序無需執行磁碟io操作,可以最大化redis的效能。
aof的話可以讓redis非常耐久,盡可能短的減少資料丟失問題。但是備份檔案體積要大於rdb,效能及恢復效率上不如rdb。
快取穿透 快取雪崩 快取擊穿及解決方案
快取穿透 查詢的資料在快取伺服器 redis 中沒有,就繞過快取伺服器 直接與資料庫進行io互動,對伺服器造成巨大壓力 解決方案 查詢資料在redis如果沒有,就將該資料設定為null放在redis中 防止暴力攻擊 或者使用布隆過濾器 本質上布隆過濾器是一種資料結構,比較巧妙的概率型資料結構 pro...
快取穿透,快取雪崩,快取擊穿及解決方案
快取穿透 快取穿透是指,請求獲取的資料來源不存在,redis沒有則會去請求資料庫,資料庫也沒有,這時候大量請求可能會壓垮資料庫。快取擊穿 快取擊穿是指,請求獲取的某個redis key剛好過期,資料庫中有資料,這時候大量的請求就落到的資料庫上,造成資料庫掛掉。快取雪崩 快取雪崩是指,有大量的redi...
快取穿透 快取擊穿 快取雪崩問題
快取穿透 快取穿透,是指查詢乙個資料庫一定不存在的資料正常的使用快取流程大致是,資料查詢先進行快取查詢,如果 key 不存在或者 key 已經過期,再對資料庫進行查詢,並把查詢到的物件,放進快取。如果資料庫查詢物件為空,則不放進快取,就會每次都去查詢資料庫,而每次查詢都是空,每次又都不會進行快取。假...