一、緩存穿透:大量請求不命中
1.現象:
request請求在cache中未找到數據,直接查找storage
2.原因:
2.1業務代碼自身問題--->在數據庫中未找到數據,進入死循環
2.2惡意攻擊、爬蟲等--->大量不存在數據查找數據庫,進入死循環
3.如何發現:
3.1業務響應時間
3.2業務本身問題
3.3相關指標:總調用數、緩存層命中數、存儲層命中數
4.解決方法
4.1緩存空對象:存儲層返回空對象, 使下次請求直接返回null
①如果是惡意攻擊,需要佔用更多的緩存空間--->緩存設置過期時間
②網絡原因導致,出現緩存層和存儲層數據短期的不一致
4.2布隆過濾器攔截
①位數組(二進制向量);一系列隨機映射函數--->元素通過Hash函數對應位數組
②布隆過濾不存在,數據一定不存在;布隆過濾存在,數據不一定存在
private static final int insertions = 1000000; public static void main(String[] args) { System.out.println("初始化布隆過濾器,大小爲100w,誤判率爲0.03"); BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), insertions,0.03); System.out.println("創建示例集合"); List<String> list = new ArrayList<>(insertions); for (int i = 0; i < insertions; i++) { String uuid = UUID.randomUUID().toString(); bf.put(uuid); list.add(uuid); } System.out.println("開始過濾,1w數據,100個真的,9900個假的"); int num=0; int right=0; int wrong=0; for (int i = 0; i < 10000; i++) { String data = i % 100 == 0 ? list.get(i / 100) : UUID.randomUUID().toString(); if (bf.mightContain(data)) { num++; if (list.contains(data)) { right++; } else { wrong++; } } } NumberFormat percentFormat = NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(2); System.out.println("100W中1W數據百分比結果: "); System.out.println("布隆認爲存在的:"+num); System.out.println("真實存在的:"+right+"\t 正確率"+percentFormat.format((float)right/100)); System.out.println("不存在的:"+wrong+"\t 誤判率:"+percentFormat.format((float)wrong/10000)); }
二、緩存擊穿:熱點數據集中過期
三、緩存雪崩:大量數據集中過期