SpringBoot使用布隆過濾器解決緩存穿透問題
緩存穿透基礎介紹
緩存穿透是指當緩存系統(tǒng)中無法命中需要的數據時,會直接請求底層存儲系統(tǒng)(如數據庫),但是如果請求的數據根本不存在,那么大量的請求就會直接穿透緩存層,直接訪問底層存儲系統(tǒng),導致底層系統(tǒng)壓力過大,甚至崩潰。這也是緩存系統(tǒng)面臨的一種常見攻擊。
說白了就是查詢大量不傳在的key 繞過緩存 直接查詢數據庫 導致緩存跟不不存在一樣 這就是緩存穿透
場景介紹
下面說下我的場景 我需要添加一個user 然后我再通過id去查詢 如果查詢有結果那就放入緩存 如果沒有那就直接查詢數據庫 ?
這是添加user的方法
這是查詢user的方法
問題描述
在這兩個方法中 我雖然加入的緩存的機制 但是在查詢user的方法中 會有一個問題 就是如果我查詢的id是不存在的 那就會一直查詢數據庫
@Cacheable(value = "userCache", key = "#id", condition = "#result != null")
當然你可以說 我去掉注解上面的condition = "#result != null" (這句話意思是condition 條件為真才緩存) 這樣就算我查詢一個不存在的id 然后將一個null或者空對象返回 然后再加入緩存不就可以啦 下次再去查詢這個不存在的id的時候 就不會走數據庫了
可是 如果我每一次查詢的都是不同的并且不存在的id呢? 那么這個問題還是無法解決 那么接下來就可以引入布隆過濾器 布隆過濾器具體的原理我這里就不做解釋了
解決問題
第一步在maven中導入布隆過濾器 事先說明 導入的方法很多 我的方法不一定是最優(yōu)的 但是一定是能行的
在pom.xml中引入依賴
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.1-jre</version> </dependency> Guava庫(Google Guava)是一個Google開發(fā)的Java工具庫, 它提供了許多常用的Java工具類和數據結構,包括布隆過濾器(Bloom Filter)
創(chuàng)建項目結構 這個不需要解釋吧 能看這種文章的 我相信項目結構應該都是能看懂的?
AppConfig的代碼如下 就是簡單的注入Bean對象
@Configuration public class AppConfig { @Bean public BloomFilterService bloomFilterService() { return new BloomFilterService(); } }
BloomFilterService的代碼如下
public class BloomFilterService { private BloomFilter<Long> bloomFilter; public BloomFilterService(){ // 創(chuàng)建一個布隆過濾器,設置期望插入的元素數量和誤判率 int bloomFilterSize = 1000; // 期望插入的元素數量 double falsePositiveRate = 0.001; // 誤判率 bloomFilter = BloomFilter.create(Funnels.longFunnel(), bloomFilterSize, falsePositiveRate); } // 添加元素到布隆過濾器 public void add(Long id){ bloomFilter.put(id); } //判斷元數是否在布隆過濾器中 public boolean contains(Long id){ return bloomFilter.mightContain(id); } }
接下來就是在controller中引入并且使用布隆過濾器了
正常注入
@Autowired private BloomFilterService bloomFilterService;
然后在每一次添加對象之后都將用戶的id添加到布隆過濾器中
@CachePut(value = "userCache", key = "#user.id") // value 指定緩存的名字 @PostMapping public User save(User user){ userService.save(user); bloomFilterService.add(user.getId()); //這里注意必須要放在添加之后 因為一開始傳過來的user是沒有id的 會有空指針錯誤 //這里利用的查詢回顯 不懂的可以去查查 return user; }
然后更改查詢方法 這樣每一次查詢user的時候都會先過一遍布隆過濾器 然后再去查詢用戶 如果存在那么就加入緩存 不傳在就會被布隆過濾器攔截 注意去掉, condition = "#result != null" 這個好像跟 布隆有沖突 如果有懂的可以在評論區(qū)提一下
@Cacheable(value = "userCache", key = "#id") @GetMapping("/{id}") public User getById(@PathVariable Long id){ if (!bloomFilterService.contains(id)) { // ID 不合法,可以返回錯誤響應或進行其他處理 return null; } User byId = userService.getById(id); return byId; }
最后的效果
在添加的時候會將id添加到布隆中 下一次查詢的時候如果添加的數據不合法 那就直接攔截
如果添加的數據是合法的 那么就會直接查緩存 如果緩存沒有那就直接查數據庫 然后再加入緩存
上面的效果我自己測試了發(fā)現(xiàn)是沒有什么問題的 本人的水平也不高 如果有發(fā)現(xiàn)什么問題歡迎評論區(qū)討論 謝謝觀看
以上就是SpringBoot使用布隆過濾器解決緩存穿透問題的詳細內容,更多關于SpringBoot緩存穿透的資料請關注腳本之家其它相關文章!
相關文章
基于Java并發(fā)容器ConcurrentHashMap#put方法解析
下面小編就為大家?guī)硪黄贘ava并發(fā)容器ConcurrentHashMap#put方法解析。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06SSH框架網上商城項目第9戰(zhàn)之添加和更新商品類別功能實現(xiàn)
這篇文章主要為大家詳細介紹了SSH框架網上商城項目第9戰(zhàn)之添加和更新商品類別功能實現(xiàn),感興趣的小伙伴們可以參考一下2016-06-06