快取失效 快取穿透問題解決方案

2022-07-10 09:27:09 字數 2522 閱讀 8671

快取失效(快取雪崩):

引起這個原因的主要因素是高併發下,我們一般設定乙個快取的過期時間時,可能有一些會設定5分鐘啊,10分鐘這些;併發很高時可能會出在某乙個時間同時生成了很多的快取,並且過期時間在同一時刻,這個時候就可能引發——當過期時間到後,這些快取同時失效,請求全部**到db,db可能會壓力過重。 

處理方法: 乙個簡單方案就是將快取失效時間分散開,不要所以快取時間長度都設定成5分鐘或者10分鐘;比如我們可以在原有的失效時間基礎上增加乙個隨機值,比如1-5分鐘隨機,這樣每乙個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。 快取失效時產生的雪崩效應,將所有請求全部放在資料庫上,這樣很容易就達到資料庫的瓶頸,導致服務無法正常提供。盡量避免這種場景的發生。 

和快取擊穿不同的是,  快取擊穿指併發查同一條資料,快取雪崩是不同資料都過期了,很多資料都查不到從而查資料庫。

快取穿透:

出現場景:指查詢乙個一定不存在的資料,由於快取是不命中時被動寫的,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。

方法2.如果乙個查詢返回的資料為空(不管是資料不存在,還是系統故障),我們仍然把這個空結果進行快取,但它的過期時間會很短,一般只有幾分鐘。 

public function getarticles($key)

$data = $this->searchdb();

cache::put($key, $data, $expire);

return $data;

}

這樣處理的原因是,即使當前查詢的key為空字串,或者空陣列,結果也會被快取起來。當下一次訪問時會直接返回,不會造成快取穿透

方法3.採用布隆過濾器,將所有可能存在的資料雜湊到乙個足夠大的bitmap中,乙個一定不存在的資料會被這個bitmap攔截掉,從而避免了對底層儲存系統的查詢壓力。

如果是非法攻擊時,介面層增加校驗,如使用者鑑權校驗,id做基礎校驗,id<=0的直接攔截;

快取併發:

出現場景:當**併發訪問高,乙個快取如果失效,可能出現多個程序同時查詢db,同時設定快取的情況,如果併發確實很大,這也可能造成db壓力過大,還有快取頻繁更新的問題。 

處理方法:,如果key不存在,就加鎖,然後查db入快取,然後解鎖;其他程序如果發現有鎖就等待,然後等解鎖後返回資料或者進入db查詢。

我們可以使用redis的setnx()

setnx($key) 的作用類似於set($key) ,setnx的意思為 set not exists 如果$key不存在則設定,存在則不進行任何操作. 設定成功設定返回1,說明當前的請求獲得了當前的操作許可權,設定失敗返回0,說明此資源已經被其他請求獲得。使用**實現的話,思路如下:

給存入快取的資料增加乙個過期時間字段暫時給這個欄位起名字叫$data['expire'](這個過期時間要短於實際的快取過期時間),方便在快取過期前執行加鎖和快取更新。

如果$data['expire']達到過期時間,則執行加鎖以及快取更新。

此時如果有其他請求進入則返回更新之前的資料。

**如下:

public function getarticleslock($key)

//加鎖失敗說明已經有請求執行加鎖,返回之前的快取資料

if (!redis::setnx($lockkey,1))

}sleep(3);

$datat = $this->searchdb();

$data = [

'data' => $datat,

'expire' => $time + $expire - 10

];$r = cache::put($key, $data, $expire);

//解鎖

redis::del($lockkey);

return $data['data'];

}

當然此處也可以使用set()來代替setnx()加鎖,以及使用lua指令碼解鎖。

三、快取擊穿

描述:快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由於併發使用者特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力

解決方案:

設定熱點資料永遠不過期。

加互斥鎖,互斥鎖參考**如下

說明:1)快取中有資料,直接走上述**13行後就返回結果了

2)快取中沒有資料,第1個進入的執行緒,獲取鎖並從資料庫去取資料,沒釋放鎖之前,其他並行進入的執行緒會等待100ms,再重新去緩訪問資料。這樣就防止都去資料庫重複取資料,重複往快取中更新資料情況出現。

3)當然這是簡化處理,理論上如果能根據key值加鎖就更好了,就是執行緒a從資料庫取key1的資料並不妨礙執行緒b取key2的資料,上面**明顯做不到這點。

快取雪崩和快取穿透問題解決方案

快取雪崩 簡介 快取同一時間大面積的失效,所以,後面的請求都會落到資料庫上,造成資料庫短時間內承受大量請求而崩掉。快取穿透 簡介 一般是黑客故意去請求快取中不存在的資料,導致所有的請求都落到資料庫上,造成資料庫短時間內承受大量請求而崩掉。解決辦法 有很多種方法可以有效地解決快取穿透問題,最常見的則是...

redis快取雪崩和快取穿透問題解決方案

快取雪崩 簡介 快取同一時間大面積的失效,所以,後面的請求都會落到資料庫上,造成資料庫短時間內承受大量請求而崩掉。事前 盡量保證整個 redis 集群的高可用性,發現機器宕機盡快補上。選擇合適的記憶體淘汰策略。事中 本地ehcache快取 hystrix限流 降級,避免mysql崩掉 事後 利用 r...

快取失效 快取穿透 快取併發及其解決方案

問題描述 引起這個原因的主要因素是高併發下,我們一般設定乙個快取的過期時間時,可能有一些會設定5分鐘啊,10分鐘這些 併發很高時可能會出在某乙個時間同時生成了很多的快取,並且過期時間在同一時刻,這個時候就可能引發 當過期時間到後,這些快取同時失效,請求全部 到db,db可能會壓力過重。處理方法 乙個...