1. 程式人生 > 其它 >python入門學習篇二十八

python入門學習篇二十八

https://www.one-tab.com/page/0bEKXW4PQC6yYTPmotOOnw

布隆過濾器

主要用於判斷一個元素是否在一個集合中。假如某個資料集很大 ,比如說在 Mysql 中 ,資料量很大 ,即使加上了索引 ,大量的查詢也會影響效能 (缺頁,底層IO等)而布隆過濾器就是為了解決這種問題 ,

可以看到一個值通過多個 hash 函式在一個 bitmap 中進行 01賦值 .

查詢某個變數的時候我們只要看看這些點是不是都是 1 就可以大概率知道集合中有沒有它了
- 如果這些點有任何一個 0,則被查詢變數一定不在;
- 如果都是 1,則被查詢變數很可能存在
為什麼說是可能存在,而不是一定存在呢?那是因為對映函式本身就是雜湊函式,雜湊函式是會有碰撞的。

詳細的布隆過濾器原理見這篇文章

布隆過濾器特徵

  • 一個元素如果判斷結果為存在的時候元素不一定存在,但是判斷結果為不存在的時候則一定不存在。
  • 布隆過濾器可以新增元素,但是不能刪除元素。因為刪掉元素會導致誤判率增加。

布隆過濾器實戰

瞭解完布隆過濾器, 我們看一下實戰章節, 有以下場景 :
有一批資料數量在 15w 左右 , 需要定時從外部同步回來篩選出有哪些資料是新增的, 哪些是更新的, 其中資料有兩個欄位一個 (noname欄位) , 假設 15w 資料都去資料庫一一比對 ,這個過程非常消耗時間 ,當允許少量誤差率的情況下我們使用兩個布隆過濾器

方案流程圖

安裝 redis布隆過濾器

  redis:
    image: redis:5
    container_name: redis
    command: redis-server /conf/redis.conf
    volumes:
      - ./mydata/redis/data:/data #資料檔案掛載
      - ./mydata/redis/conf/redis.conf:/conf/redis.conf #配置檔案掛載
      - ./mydata/redis/conf/sentinel.conf:/conf/sentinel.conf #配置檔案掛載
      - ./mydata/redis/bloom/redisbloom.so:/data/redisbloom.so #載入布隆過濾器
      - ./mydata/redis/bloom/bankcspn.lua:/data/bankcspn.lua #資料插入過濾器lua指令碼
    ports:
      - 6379:6379

建立 no的布隆過濾器 :

BF.RESERVE bankCspn 0.00001 160000 

然後是插入資料的初始化指令碼

local key ='bankCspn'
redis.call("BF.ADD" , key,"000132800023")
redis.call("BF.ADD" , key,"000998800006")
redis.call("BF.ADD" , key,"001100011002")
redis.call("BF.ADD" , key,"001110012009")
redis.call("BF.ADD" , key,"001110012017")
redis.call("BF.ADD" , key,"001121013007")
redis.call("BF.ADD" , key,"001121013015")
redis.call("BF.ADD" , key,"001121013023")
redis.call("BF.ADD" , key,"001121013031")
redis.call("BF.ADD" , key,"001121013040")
redis.call("BF.ADD" , key,"001121013058")
redis.call("BF.ADD" , key,"001121013066")
redis.call("BF.ADD" , key,"001121013074")
redis.call("BF.ADD" , key,"001121013082")
redis.call("BF.ADD" , key,"001121013099")
.....

建立完了之後長這個樣子 :

後續就是程式碼程式設計的工作了. 一個簡單的實戰就完成了.

參考資料