Redis-布隆過濾器
1. 布隆過濾器(Bloom Filter)原理以及應用
假設現在有50億個電話號碼,現在有1萬個電話號碼,需要快速判斷這些電話號碼是否已經存在?
現在有3中途徑
- 通過資料庫查詢,但是不能快速查詢。
- 把電話號碼預先放在一個集合中,如果用long型別儲存的話,50億 * 8位元組 = 大於需要40GB(記憶體浪費或者嚴重不夠)
- 使用redis的hyperloglog,但是準確度不高。
類似的問題:
- 垃圾郵件過濾
- 文書處理中的錯誤單詞檢測
- 網路爬蟲重複URL檢測
- 會員抽獎
- 判斷一個元素在億級資料中是否存在
- 快取穿透
- 而布隆過濾器則可以解決上述問題
1 什麼是布隆過濾器
布隆過濾器(Bloom Filter)是1970年由布隆提出的。它實際上是一個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。
當一個元素被加入集合時,通過 K 個 Hash 函式將這個元素對映成一個位陣列(Bit array)中的 K 個點,把它們置為 1。檢索時,我們只要看看這些點是不是都是 1 就(大約)知道集合中有沒有它了:
如果這些點有任何一個 0,則被檢索元素一定不在; 如果都是 1,則被檢索元素很可能在。
新增元素的原理
- 將要新增的元素給k個hash函式
- 得到對應於位陣列上的k個位置
- 將這k個位置設定成 1
查詢元素原理
- 將要查詢的元素給k個hash函式
- 得到對應陣列的k個元素
- 如果k個位置中有一個為0,則肯定不在集合中
- 如果k個位置全部為1,則有可能在集合中
優點
它的優點是空間效率和查詢時間都遠遠超過一般的演算法,布隆過濾器儲存空間和插入 / 查詢時間都是常數O(k)。另外, 雜湊函式相互之間沒有關係,方便由硬體並行實現。布隆過濾器不需要儲存元素本身,在某些對保密要求非常嚴格的場合有優勢。
缺點
隨著資料的增加,誤判率隨之增加;只能判斷資料是否一定不存在,而無法判斷資料是否一定存在。
如果資料A,經過hash1(A)、hash2(A)、hash3(A),得到其hash值1、3、5,然後我們在其二進位制向量位置1、3、5設定1,然後資料B,經過hash1(B)、hash2(B)、hash3(B),其實hash值也是1、3、5,我們在做業務處理的時候判斷B是否存在的時候發現 其二進位制向量位置返回1,認為其已經存在,就跳過相關業務處理,實際上根本不存在,這就是由於hash碰撞引起的問題。也就存在了誤差率。
無法做到刪除資料
一般情況下不能從布隆過濾器中刪除元素. 我們很容易想到把位陣列變成整數陣列,每插入一個元素相應的計數器加 1, 這樣刪除元素時將計數器減掉就可以了。然而要保證安全地刪除元素並非如此簡單。首先我們必須保證刪除的元素的確在布隆過濾器裡面. 這一點單憑這個過濾器是無法保證的。
2. redis實現布隆過濾器的方式
1. guava單機版實現布隆過濾器
引入Guava依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
程式碼實現
package jedis.bloomFilter;
import com.google.common.hash.Funnels;
import com.google.common.hash.BloomFilter;
import java.util.ArrayList;
import java.util.List;
public class GuavaBloomFilter {
private static int size = 10000;
public static void main(String[] args) {
/**
* 預設誤差率3%。肯定不存在以及可能存在
* 可通過建構函式去設定誤差率
* create(
* Funnel<? super T> funnel, int expectedInsertions, double fpp)
*
*/
BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);
for (int i = 0; i < size; i++) {
bloomFilter.put(i);
}
for (int i = 0; i < size; i++) {
if (!bloomFilter.mightContain(i)) {
System.out.println("有人逃脫了");
}
}
List<Integer> list = new ArrayList<Integer>(1000);
for (int i = size + 10000; i < size + 20000; i++) {
if (bloomFilter.mightContain(i)) {
list.add(i);
}
}
System.out.println("誤傷的數量:" + list.size());
}
}
2. Rebloom外掛方式實現布隆過濾器(redis 4.0 以後)
下載並編譯
$ git clone git://github.com/RedisLabsModules/rebloom
$ cd rebloom
$ make
cd /usr/redis-4.0.11
#載入module 並設定容量與容錯率
# 容量100萬, 容錯率萬分之一
./src/redis-server redis.conf --loadmodule /usr/rebloom/rebloom.so INITIAL_SIZE 1000000 ERROR_RATE 0.0001
redis命令:
BF.ADD bloom redis
BF.EXISTS bloom redis
BF.EXISTS bloom nonxist
3. 手動實現
package com.jd.demo.test;
import java.util.Arrays;
import java.util.BitSet;
import java.util.concurrent.atomic.AtomicBoolean;
public class MyBloomFilter {
//你的布隆過濾器容量
private static final int DEFAULT_SIZE = 2 << 28;
//bit陣列,用來存放結果
private static BitSet bitSet = new BitSet(DEFAULT_SIZE);
//後面hash函式會用到,用來生成不同的hash值,可隨意設定,別問我為什麼這麼多8,圖個吉利
private static final int[] ints = {1, 6, 16, 38, 58, 68};
//add方法,計算出key的hash值,並將對應下標置為true
public void add(Object key) {
Arrays.stream(ints).forEach(i -> bitSet.set(hash(key, i)));
}
//判斷key是否存在,true不一定說明key存在,但是false一定說明不存在
public boolean isContain(Object key) {
boolean result = true;
for (int i : ints) {
//短路與,只要有一個bit位為false,則返回false
result = result && bitSet.get(hash(key, i));
}
return result;
}
//hash函式,借鑑了hashmap的擾動演算法
private int hash(Object key, int i) {
int h;
return key == null ? 0 : (i * (DEFAULT_SIZE - 1) & ((h = key.hashCode()) ^ (h >>> 16)));
}
}
一個線上計算所需空間的地址
相關文章
- 布隆過濾器過濾器
- 布隆過濾器(Bloom Filter)過濾器OOMFilter
- 大白話布隆過濾器過濾器
- Guava的布隆過濾器Guava過濾器
- 布隆過濾器 Bloom Filter過濾器OOMFilter
- Bloom Filter 布隆過濾器OOMFilter過濾器
- 布隆過濾器的概述過濾器
- 淺談布隆過濾器過濾器
- Redis 中的布隆過濾器Redis過濾器
- Redis 應用-布隆過濾器Redis過濾器
- PHP實現布隆過濾器PHP過濾器
- 布隆過濾器 與 Redis BitMap過濾器Redis
- Xor過濾器:比布隆Bloom過濾器更快,更小過濾器OOM
- 布隆過濾器(Bloom Filter)詳解過濾器OOMFilter
- 5分鐘掌握布隆過濾器過濾器
- victoriaMetrics庫之布隆過濾器過濾器
- 還有人不懂布隆過濾器嗎?過濾器
- Hbase 布隆過濾器BloomFilter介紹過濾器OOMFilter
- 布隆過濾器-使用場景的思考過濾器
- Redis詳解(十三)------ Redis布隆過濾器Redis過濾器
- 從快取穿透聊到布隆過濾器快取穿透過濾器
- 演算法(3)---布隆過濾器原理演算法過濾器
- Redis布隆過濾器分析與總結Redis過濾器
- 布隆過濾器的原理及應用過濾器
- 詳解布隆過濾器原理與實現過濾器
- 面試官問:什麼是布隆過濾器?面試過濾器
- LevelDB 學習筆記1:布隆過濾器筆記過濾器
- 品味布隆過濾器的設計之美過濾器
- 實現布隆過濾器的三種方式過濾器
- 布隆過濾器(Bloom Filter)的java實現過濾器OOMFilterJava
- 探索C#之布隆過濾器(Bloom filter)C#過濾器OOMFilter
- 那些有趣的演算法之布隆過濾器演算法過濾器
- 布隆過濾器實戰【防止快取擊穿】過濾器快取
- Redis快取穿透解決方案--布隆過濾器Redis快取穿透過濾器
- 布隆過濾器解決快取穿透問題過濾器快取穿透
- 詳解布隆過濾器的原理和實現過濾器
- 布隆過濾器(BloomFilter)原理 實現和效能測試過濾器OOMFilter
- AI考拉技術分享--布隆過濾器實戰AI過濾器