溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

redis緩存穿透怎么理解

發(fā)布時間:2021-12-08 14:16:25 來源:億速云 閱讀:126 作者:iii 欄目:大數(shù)據(jù)

本篇內容主要講解“redis緩存穿透怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“redis緩存穿透怎么理解”吧!

Bloom Filter 概念

布隆過濾器(英語:Bloom Filter)是1970年由一個叫布隆的小伙子提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數(shù)。布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。

Bloom Filter 原理

布隆過濾器的原理是,當一個元素被加入集合時,通過K個散列函數(shù)將這個元素映射成一個位數(shù)組中的K個點,把它們置為1。檢索時,我們只要看看這些點是不是都是1就(大約)知道集合中有沒有它了:如果這些點有任何一個0,則被檢元素一定不在;如果都是1,則被檢元素很可能在。這就是布隆過濾器的基本思想。

Bloom Filter跟單哈希函數(shù)Bit-Map不同之處在于:Bloom Filter使用了k個哈希函數(shù),每個字符串跟k個bit對應。從而降低了沖突的概率。

redis緩存穿透怎么理解

緩存穿透

redis緩存穿透怎么理解

(2)哈希函數(shù)選擇

由預估數(shù)據(jù)量n以及bit數(shù)組長度m,可以得到一個hash函數(shù)的個數(shù)k:

img

哈希函數(shù)的選擇對性能的影響應該是很大的,一個好的哈希函數(shù)要能近似等概率的將字符串映射到各個Bit。選擇k個不同的哈希函數(shù)比較麻煩,一種簡單的方法是選擇一個哈希函數(shù),然后送入k個不同的參數(shù)。

哈希函數(shù)個數(shù)k、位數(shù)組大小m、加入的字符串數(shù)量n的關系可以參考Bloom Filters - the math,Bloom_filter-wikipedia

要使用BloomFilter,需要引入guava包:

 <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
 </dependency>

測試分兩步:

1、往過濾器中放一百萬個數(shù),然后去驗證這一百萬個數(shù)是否能通過過濾器

2、另外找一萬個數(shù),去檢驗漏網(wǎng)之魚的數(shù)量

/**
 * 測試布隆過濾器(可用于redis緩存穿透)
 */
public class TestBloomFilter {

    private static int total = 1000000;
    private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), total);
//    private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), total, 0.001);

    public static void main(String[] args) {
        // 初始化1000000條數(shù)據(jù)到過濾器中
        for (int i = 0; i < total; i++) {
            bf.put(i);
        }

        // 匹配已在過濾器中的值,是否有匹配不上的
        for (int i = 0; i < total; i++) {
            if (!bf.mightContain(i)) {
                System.out.println("有壞人逃脫了~~~");
            }
        }

        // 匹配不在過濾器中的10000個值,有多少匹配出來
        int count = 0;
        for (int i = total; i < total + 10000; i++) {
            if (bf.mightContain(i)) {
                count++;
            }
        }
        System.out.println("誤傷的數(shù)量:" + count);
    }

}

運行結果:

redis緩存穿透怎么理解

運行結果表示,遍歷這一百萬個在過濾器中的數(shù)時,都被識別出來了。一萬個不在過濾器中的數(shù),誤傷了320個,錯誤率是0.03左右。

看下BloomFilter的源碼:

public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions) {
        return create(funnel, (long) expectedInsertions);
    }  

    public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {
        return create(funnel, expectedInsertions, 0.03); // FYI, for 3%, we always get 5 hash functions
    }

    public static <T> BloomFilter<T> create(
          Funnel<? super T> funnel, long expectedInsertions, double fpp) {
        return create(funnel, expectedInsertions, fpp, BloomFilterStrategies.MURMUR128_MITZ_64);
    }

    static <T> BloomFilter<T> create(
      Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy) {
     ......
    }

BloomFilter一共四個create方法,不過最終都是走向第四個??匆幌旅總€參數(shù)的含義:

  1. funnel:數(shù)據(jù)類型(一般是調用Funnels工具類中的)

  2. expectedInsertions:期望插入的值的個數(shù)

  3. fpp 錯誤率(默認值為0.03)

  4. strategy 哈希算法(我也不懂啥意思)Bloom Filter的應用

在最后一個create方法中,設置一個斷點:

redis緩存穿透怎么理解

上面的numBits,表示存一百萬個int類型數(shù)字,需要的位數(shù)為7298440,700多萬位。理論上存一百萬個數(shù),一個int是4字節(jié)32位,需要481000000=3200萬位。如果使用HashMap去存,按HashMap50%的存儲效率,需要6400萬位。可以看出BloomFilter的存儲空間很小,只有HashMap的1/10左右

上面的numHashFunctions,表示需要5個函數(shù)去存這些數(shù)字

使用第三個create方法,我們設置下錯誤率:

private static BloomFilter<Integer> bf = BloomFilter.create(Funnels.integerFunnel(), total, 0.0003);

再運行看看:

redis緩存穿透怎么理解

當錯誤率設為0.0003時,所需要的位數(shù)為16883499,1600萬位,需要12個函數(shù)

和上面對比可以看出,錯誤率越大,所需空間和時間越小,錯誤率越小,所需空間和時間約大

常見的幾個應用場景:

  • cerberus在收集監(jiān)控數(shù)據(jù)的時候, 有的系統(tǒng)的監(jiān)控項量會很大, 需要檢查一個監(jiān)控項的名字是否已經(jīng)被記錄到db過了, 如果沒有的話就需要寫入db.

  • 爬蟲過濾已抓到的url就不再抓,可用bloom filter過濾

  • 垃圾郵件過濾。如果用哈希表,每存儲一億個 email地址,就需要 1.6GB的內存(用哈希表實現(xiàn)的具體辦法是將每一個 email地址對應成一個八字節(jié)的信息指紋,然后將這些信息指紋存入哈希表,由于哈希表的存儲效率一般只有 50%,因此一個 email地址需要占用十六個字節(jié)。一億個地址大約要 1.6GB,即十六億字節(jié)的內存)。因此存貯幾十億個郵件地址可能需要上百 GB的內存。而Bloom Filter只需要哈希表 1/8到 1/4 的大小就能解決同樣的問題。

到此,相信大家對“redis緩存穿透怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI