Z-Blog編輯器支援ppt自動匯入
阿新 • • 發佈:2022-05-10
瞭解
- 1970年,由Bloom 提出的
- 由二進向量(位陣列)與 隨機對映函式組成對映關係
- BitSet 作為位容器(位陣列),位值為 0 或者 1
- 隨機對映函式(HashFunction),目的生成一個對應的數值,然後存入到 BitSet中。
- 優點:
- 陣列容器佔用空間小。儲存100W個數據,佔 122 KB(100W*1bit/8/1024)
- 如果儲存過資料,容器必定有痕跡
- 缺點:
- 容器有痕跡的,不一定儲存過資料
- 容器中只能新增資料,不能刪除資料。刪除元素導致位值的變化,會提高容器的錯誤率
- 資料量越大,錯誤率會越高。所以一般 位容器的初始位數會很大
注 : 1 M = 1024 KB = 1024 * 1024 B(byte) = 1024 * 1024 * 8 bit
原理
新增物件
被新增的物件,通過 HashFunction 會生產一個或多個對應的數值,並存儲到 BitSet 容器中。BitSet 中位值會由 0->1 ,多個物件儲存時,位值也只會儲存到 1。
判斷物件
判斷的過程中,實際是看物件通過 HashFunction 所生產的一個或多個對應的數值,在 BitSet 中的位值是否都為1。
圖中,物件4 對應的所有位值裡面,存在一個值為 0,則 物件4 一定沒儲存過。
實現
/** * 布隆過濾器 * * @author ZZ_C * */ public class TestBloomFilter { /** * 一個長度為10億的位 */ private static int DEFAULT_SIZE = 256 << 22; /** * 為了降低錯誤率,使用hash演算法,定義8個不同的質數 */ private static final int[] seeds = { 3, 5, 7, 11, 13, 17, 19, 23 }; /** * 定義seeds.length 個 hash 函式用於雜湊計算 */ private static HashFunction[] functions = new HashFunction[seeds.length]; /** * 布隆過濾器的核心容器,初始化,定義了 10 億個位 */ private static BitSet bitSet = new BitSet(DEFAULT_SIZE); TestBloomFilter() { for (int i = 0; i < seeds.length; i++) { functions[i] = new HashFunction(DEFAULT_SIZE, seeds[i]); } } public void add(String value) { for (HashFunction function : functions) { bitSet.set(function.toHash(value)); } } public boolean contains(String value) { for (HashFunction function : functions) { // 只要有一個不存在,則 value 一定不存在 boolean result = bitSet.get(function.toHash(value)); if (Objects.equals(result, false)) { return false; } } return true; } public static void main(String[] args) { TestBloomFilter bloomFilter = new TestBloomFilter(); bloomFilter.add("斗羅大陸"); bloomFilter.add("辰東"); System.out.println(bloomFilter.contains("我愛吃西紅柿")); // false System.out.println(bloomFilter.contains("辰東")); // true } /** * 作用就是算 hash值 * 靜態類,便於處理 * @author ZZ_C * */ static class HashFunction { private int size; private int seed; public HashFunction(int size, int seed) { super(); this.size = size; this.seed = seed; } public int toHash(String value) { int h; return (value == null) ? 0 : Math.abs(seed * (size - 1) & ((h = value.hashCode()) ^ (h >>> 16))); } } }
應用場景
擊穿
使用布隆過濾器,將全部的有效資料都走一遍佈隆過濾器,這樣新來請求時,先走一遍請求的元素是否能通過布隆過濾器的驗證,若未通過就直接放棄請求,若通過再執行查詢
去重
使用者瀏覽記錄存入資料庫時,會在Filter上通過key的hash演算法儲存判斷其是否存在,類似於資料存在資料庫中,判斷該資料是否存在的資訊即元資料存放在BloomFilter中,避免了每次判斷資料是否存在都要去資料庫exist一遍;這樣推送新聞時通過布隆過濾器判斷,推送內容是否已經存在,如果存在則不推送,如果不存在則推送;