簡介:
布隆過濾器是一種實現去重的思想,不屬於redis,它也可以在其他地方單獨使用。
布隆過濾器也是做去重的,那和Hyperloglog有什么區別.
Hyperloglog用來來估值,有偏差,它里面主要提供了兩個方法:
- pfadd
- pfcount
但是沒有判斷是否包含的命令,例如pfexist,pfcontains這樣的命令。舉個例子:在刷進入頭條的時候,每次推送的內容都相似,但都不一樣,那有什么解決方案呢?,可以將每個用戶的瀏覽歷史記錄下來,然后每次推送的時候去判斷,但是這種的在高並發,數據量很大的時候就不適用。因此這里可以使用布隆過濾器去處理。
bloom Filter:是專門用來做去重操作的,它相比於緩存的話,它不那么浪費空間,但是和Hyperloglog一樣都是不太精確的,但是這個精確度可以自己調節。當數據量小的時候,精確度高一點,占用的空間就多,當數據量很大的時候,可以把精確度調低一點,這樣占用的空間就小一點。
bloom Filter相當於一個不太精確的set集合,我們可以使用contains方法去判斷某個對象是否存在,但是這個判斷不太精確,當判斷不存在的時候 ,他一定不存在,當判斷它存在的時候,它不一定存在。以今日頭條為例,假設我們將用戶的瀏覽記錄用 B 表示,A 表示用戶沒有瀏覽的新聞,現在要給用戶推送消息,先去 B 里邊判斷這條消息是否已經推送過,如果判斷結果說沒推送過(B 里邊沒有這條記錄),那就一定沒有推送過。如果判斷結果說有推送過(B 里邊也有可能沒有這條消息),這個時候該條消息就不會推送給用戶,導致用戶錯過該條消息。
原理:
每個布隆過濾器就相當於一個大型的位數組,和幾個不同的hash函數。
所謂add操作,就是根據幾個不同的hash函數元素進行hash算出一個整數索引值,拿到這個索引值后,對維數組進行取模運算,得到一個位置,每個hash函數都會得到一個位置,將位數組中對應的位置設置為1,這樣就完成添加操作。
當判斷元素是否存在的時候,依然對元素先進行hash運算,將運算結果和位數組的長度取模,然后在對應的位置查看是否有相應的數據,如果有,表示元素可能存在(因為有可能是其他元素存進來的),如果沒有,那就一定沒有。
誤判的概率和位數組的大小有關,位數組越大,誤判概率越小,所占用的空間就越大。
安裝:
public class BloomFilter { public static void main(String[] args) { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxIdle(300); config.setMaxTotal(1000); config.setMaxWaitMillis(30000); config.setTestOnBorrow(true); JedisPool pool = new JedisPool(config, "192.168.91.128", 6379, 30000, "zl"); Client client = new Client(pool); //存入數據 for (int i = 0; i < 100000; i++) { client.add("name", "zl-" + i); } //檢查數據是否存在 boolean exists = client.exists("name", "zl-9999999"); System.out.println(exists); } }
默認布隆過濾器的錯誤率是0.01,默認元素的大小為100,當然也可以存超過100個,只不過錯誤率會上升。
這兩個參數可以去配置的:bf.reserve
應用場景:
新聞推送過濾
解決redis穿透,或者緩存擊穿問題