
資料內(nèi)容:
布隆過濾器就是一個大型的位數(shù)組和幾個不一樣的無偏 hash 函數(shù)。所謂無偏就是能夠把元素的 hash 值算得 
比較均勻。 
向布隆過濾器中添加 key 時,會使用多個 hash 函數(shù)對 key 進(jìn)行 hash 算得一個整數(shù)索引值然后對位數(shù)組長度 
進(jìn)行取模運(yùn)算得到一個位置,每個 hash 函數(shù)都會算得一個不同的位置。再把位數(shù)組的這幾個位置都置為 1 就 
完成了 add 操作。 
向布隆過濾器詢問 key 是否存在時,跟 add 一樣,也會把 hash 的幾個位置都算出來,看看位數(shù)組中這幾個位 
置是否都為 1,只要有一個位為 0,那么說明布隆過濾器中這個key 不存在。如果都是 1,這并不能說明這個 
key 就一定存在,只是極有可能存在,因為這些位被置為 1 可能是因為其它的 key 存在所致。如果這個位數(shù)組 
比較稀疏,這個概率就會很大,如果這個位數(shù)組比較擁擠,這個概率就會降低。 
這種方法適用于數(shù)據(jù)命中不高、 數(shù)據(jù)相對固定、 實時性低(通常是數(shù)據(jù)集較大) 的應(yīng)用場景, 代碼維護(hù)較為 
復(fù)雜, 但是緩存空間占用很少。 
可以用redisson實現(xiàn)布隆過濾器,引入依賴: 
1 <dependency> 
2 <groupId>org.redisson</groupId> 
3 <artifactId>redisson</artifactId> 
4 <version>3.6.5</version> 
5 </dependency> 
示例偽代碼: 
1 package com.redisson; 
2 
3 import org.redisson.Redisson;4 import org.redisson.api.RBloomFilter; 
5 import org.redisson.api.RedissonClient; 
6 import org.redisson.config.Config; 
7 
8 public class RedissonBloomFilter { 
9 
10 public static void main(String[] args) { 
11 Config config = new Config(); 
12 config.useSingleServer().setAddress("redis://localhost:6379"); 
13 //構(gòu)造Redisson 
14 RedissonClient redisson = Redisson.create(config); 
15 
16 RBloomFilter<String> bloomFilter = redisson.getBloomFilter("nameList"); 
17 //初始化布隆過濾器:預(yù)計元素為100000000L,誤差率為3%,根據(jù)這兩個參數(shù)會計算出底層的bit數(shù)組大小 
18 bloomFilter.tryInit(100000000L,0.03); 
19 //將zhuge插入到布隆過濾器中 
20 bloomFilter.add("zhuge"); 
21 
22 //判斷下面號碼是否在布隆過濾器中 
23 System.out.println(bloomFilter.contains("guojia"));//false 
24 System.out.println(bloomFilter.contains("baiqi"));//false 
25 System.out.println(bloomFilter.contains("zhuge"));//true 
26 } 
27 } 
使用布隆過濾器需要把所有數(shù)據(jù)提前放入布隆過濾器,并且在增加數(shù)據(jù)時也要往布隆過濾器里放,布隆過濾器 
緩存過濾偽代碼: 
1 //初始化布隆過濾器 
2 RBloomFilter<String> bloomFilter = redisson.getBloomFilter("nameList"); 
3 //初始化布隆過濾器:預(yù)計元素為100000000L,誤差率為3% 
4 bloomFilter.tryInit(100000000L,0.03); 
5 
6 //把所有數(shù)據(jù)存入布隆過濾器 
7 void init(){ 
8 for (String key: keys) { 
9 bloomFilter.put(key); 
10 } 
11 } 
12 
13 String get(String key) { 
14 // 從布隆過濾器這一級緩存判斷下key是否存在 
15 Boolean exist = bloomFilter.contains(key); 
16 if(!exist){ 
17 return ""; 
18 } 
19 // 從緩存中獲取數(shù)據(jù) 
20 String cacheValue = cache.get(key); 
21 // 緩存為空22 if (StringUtils.isBlank(cacheValue)) { 
23 // 從存儲中獲取 
24 String storageValue = storage.get(key); 
25 cache.set(key, storageValue); 
26 // 如果存儲數(shù)據(jù)為空, 需要設(shè)置一個過期時間(300秒) 
27 if (storageValue == null) { 
28 cache.expire(key, 60 * 5); 
29 } 
30 return storageValue; 
31 } else { 
32 // 緩存非空 
33 return cacheValue; 
34 } 
35 }
 
                