【專項測試系列】-快取擊穿、穿透、雪崩專項測試

京東雲開發者發表於2022-11-18

作者:劉須華

一、背景概述:

R2M快取的使用,極大的提升了應用程式的效能和效率,特別是資料查詢方面。而快取最常見的問題是快取穿透、擊穿和雪崩,在高併發下這三種情況都會有大量請求落到資料庫,導致資料庫資源佔滿,引起資料庫故障。平時對快取測試時除了關注增刪修改查詢等基本功能,應該要重點關注快取穿透、擊穿和雪崩三種異常場景的測試覆蓋,避免出現線上事故。

二、基本概念說明

1、快取擊穿:是指在超級熱點資料突然過期,導致針對超級熱點的資料請求在過期期間直接打到資料庫,這樣資料庫伺服器會因為某一超熱資料導致壓力過大而崩掉。





2、快取穿透:是指查詢的資料在快取和資料庫中都不存在,導致每一次請求資料從快取中都獲取不到,而將請求打到資料庫伺服器,但資料庫中也沒有對應的資料,最後每一次請求都到資料庫;如果在高併發場景或有人惡意攻擊,就會導致後臺資料庫伺服器壓力增大,最終系統可能崩掉。






3、快取雪崩:是指突然快取層不可用,導致大量請求直接打到資料庫,最終由於資料庫壓力過大可能導致系統崩掉。快取層不可用指以下兩方面:快取伺服器當機,系統將請求打到資料庫; 快取資料突然大範圍集中過期失效,導致大量請求打到資料庫重新載入資料, 與快取擊穿的區別在於這裡針對很多key快取,前者則是某一個key。






三、測試工具(非必須):   1、使用Titan壓測平臺進行併發請求測試

  2、使用jmeter工具模擬併發請求

四、測試方法舉例說明(非必須)

環境:測試環境

工具:jmeter

(1)快取穿透場景

測試方法:查詢一個根本不存在的資料,快取層和儲存層都不會命中。

查詢介面相關程式碼實現:






透過JMETER模擬多次重複呼叫:單執行緒重複呼叫






檢視日誌結果: 從日誌可以看出:執行併發請求後, 所有請求每次都走向了資料庫。








預防方案:

當資料庫查詢為空時,將快取賦值預設值,後續查詢都走快取,減少資料庫壓力。

上述介面,增加賦值為empty,則第一次查詢到資料庫為空,後續查詢都查詢到快取中,快取值為empty。






再次執行併發測試:從日誌可以看出,可以看出每個ID都只執行了一次資料庫查詢並設定快取,之後請求都命中了快取,有效防止了快取穿透問題。






(2)快取擊穿場景

測試方法:對某個Key有大量的併發請求,這時從快取中刪除這個key。模擬熱key過期失效的場景。這個時候大併發的請求可能會瞬間把後端DB壓垮。

介面相關部分程式碼實現:






操作步驟:

1、查詢pin為liuxuhua的請求,這時pin為liuxuhua的資料會載入到快取

2、再次查詢pin為liuxuhua的請求,命中快取

3、50併發請求pin為liuxuhua的資料,這個時候請求全部命中快取

4、將pin為liuxuhua的快取手動刪除,模擬快取失效

5、50併發請求pin為liuxuhua的資料,這個時候大量請求走向資料庫,pin為liuxuhua

的快取被擊穿








檢視日誌結果:






預防方案:

在設定預設快取值的基礎上,進行加鎖處理。只有拿到鎖的第一個執行緒去請求資料庫,然後插入快取,當然每次拿到鎖的時候都要去查詢一下快取有沒有。






從日誌記錄可以看到只有一個請求執行了資料庫查詢並設定快取,其他請求都命中了快取, 有效防止了快取的擊穿。






(3)快取雪崩

測試方法:對多個使用到快取的介面進行併發呼叫,設定這些快取時間已過期(即刪除快取),呼叫時這些介面查詢快取時無資料,去查詢資料庫,這些請求都指向資料庫,資料庫壓力增大,耗時增加。

模擬介面:













透過JMETER模擬多次重複呼叫:單執行緒多介面重複呼叫






檢視日誌結果:可以看出大量請求到達資料庫,並且同一個pin或id執行了多次資料庫查詢








預防方案:

增加限流操作,即介面頻繁呼叫時,增加一個快取,設定時間為3s,3s內處理一定次數的請求,超過限制次數的請求直接返回結果,不做處理。

介面:3s內處理6次請求,超過則不處理;






從日誌可以看出:可以看到每個都只查詢了一次資料庫並設定快取,之後的請求都命中了快取

【專項測試系列】-快取擊穿、穿透、雪崩專項測試



五、測試指標:(或者叫透過標準,包括關注點以及意義)

1、模擬快取穿透場景測試,每個不存在的資料都只執行了一次資料庫查詢並設定快取,之後請求都命中了快取,有效防止了快取穿透問題。

2、模擬快取雪崩場景測試,每個快取失效的資料都只執行了一次資料庫查詢並設定快取,之後請求都命中了快取。

3、模擬快取擊穿場景測試,快取失效的那個資料只有一個請求執行了資料庫查詢並設定快取,其他請求都命中了快取。



六、適用業務場景:

 1、秒殺活動

 2、熱門營銷活動

 3、618和雙11大促



七、研發側常見解決方案(參考):

1、快取穿透解決方案:

1、快取空值 之所以發生穿透,是因為快取中沒有儲存這些資料的key,從而每次都查詢資料庫 我們可以為這些key在快取中設定對應的值為null,後面查詢這個key的時候就不用查詢資料庫了 當然為了健壯性,我們要對這些key設定過期時間,以防止真的有資料

2、BloomFilter BloomFilter 類似於一個hbase set 用來判斷某個元素(key)是否存在於某個集合中 我們把有資料的key都放到BloomFilter中,每次查詢的時候都先去BloomFilter判斷,如果沒有就直接返回null 注意BloomFilter沒有刪除操作,對於刪除的key,查詢就會經過BloomFilter然後查詢快取再查詢資料庫,所以BloomFilter可以結合快取空值用,對於刪除的key,可以在快取中快取null 快取擊穿

2、快取擊穿解決方案:

採用分散式鎖,只有拿到鎖的第一個執行緒去請求資料庫,然後插入快取,當然每次拿到鎖的時候都要去查詢一下快取有沒有

3、快取雪崩解決方案:

1、採用叢集,降低服務當機的機率

2、ehcache本地快取 + 限流&降級

3、均勻過期,通常可以為有效期增加隨機值


相關文章