Redis緩存穿透問題解決

Redis緩存結構
在這裏插入圖片描述
什麼是緩存穿透?
用戶發送請求查詢了一條數據,但是數據庫並沒有這條數據,數據庫沒有這條數據,緩存中肯定也沒有這條數據,所以這個請求就越過了緩存去數據庫中查詢,數據庫查詢不到返回空值,而這種場景就稱之爲緩存穿透
緩存穿透的危害?
試想若是在高併發的情況下,緩存被穿透了導致數據庫壓力倍增甚至會出現宕機,若是被別人惡意訪問緩存穿透又會造成怎樣的後果?
解決方案
1.簡單粗暴的方式:如果一個查詢返回的數據爲空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
2.布隆過濾器:將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
這裏只介紹布隆過濾器感覺第一種方式沒啥可介紹的

需要依賴

        <!-- guava 引入布隆過濾器 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0.1-jre</version>
        </dependency>

布隆過濾器代碼

@Component
public class BloomFilterImpl {

    // 預存的數據個數 100w
    private static int size = 1000000;

    // 創建布隆過濾器的對象   3.容錯率容錯率越小越費性能越安全
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(),size,0.001);

    @Resource
    private UserDao userDao;

    /**
     * BloomFilterImpl對象被創建後,立即初始化的方法
     */
    @PostConstruct
    public void initData(){
        // 查詢數據庫中所有的id的值
        List<Integer> ids = userDao.selectAllIds();
        // 初始化到布隆過濾器中
        for (Integer id : ids) {
            bloomFilter.put(id);
        }
    }
    /**
     * 判斷布隆過濾器中是否存在該id
     * @param id
     * @return
     */
    public boolean mightContain(Integer id){
        return bloomFilter.mightContain(id);
    }

}

使用方式就不介紹了,只需在訪問數據庫前判斷布隆過濾器中是否存在即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章