※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!
以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。
本篇博客我們主要介紹如何用Redis實現布隆過濾器,但是在介紹布隆過濾器之前,我們首先介紹一下,為啥要使用布隆過濾器。
1、布隆過濾器使用場景
比如有如下幾個需求:
①、原本有10億個號碼,現在又來了10萬個號碼,要快速準確判斷這10萬個號碼是否在10億個號碼庫中?
解決辦法一:將10億個號碼存入數據庫中,進行數據庫查詢,準確性有了,但是速度會比較慢。
解決辦法二:將10億號碼放入內存中,比如Redis緩存中,這裏我們算一下佔用內存大小:10億*8字節=8GB,通過內存查詢,準確性和速度都有了,但是大約8gb的內存空間,挺浪費內存空間的。
②、接觸過爬蟲的,應該有這麼一個需求,需要爬蟲的網站千千萬萬,對於一個新的網站url,我們如何判斷這個url我們是否已經爬過了?
解決辦法還是上面的兩種,很顯然,都不太好。
③、同理還有垃圾郵箱的過濾。
那麼對於類似這種,大數據量集合,如何準確快速的判斷某個數據是否在大數據量集合中,並且不佔用內存,布隆過濾器應運而生了。
2、布隆過濾器簡介
帶着上面的幾個疑問,我們來看看到底什麼是布隆過濾器。
布隆過濾器:一種數據結構,是由一串很長的二進制向量組成,可以將其看成一個二進制數組。既然是二進制,那麼裏面存放的不是0,就是1,但是初始默認值都是0。
如下所示:
①、添加數據
介紹概念的時候,我們說可以將布隆過濾器看成一個容器,那麼如何向布隆過濾器中添加一個數據呢?
如下圖所示:當要向布隆過濾器中添加一個元素key時,我們通過多個hash函數,算出一個值,然後將這個值所在的方格置為1。
比如,下圖hash1(key)=1,那麼在第2個格子將0變為1(數組是從0開始計數的),hash2(key)=7,那麼將第8個格子置位1,依次類推。
②、判斷數據是否存在?
知道了如何向布隆過濾器中添加一個數據,那麼新來一個數據,我們如何判斷其是否存在於這個布隆過濾器中呢?
很簡單,我們只需要將這個新的數據通過上面自定義的幾個哈希函數,分別算出各個值,然後看其對應的地方是否都是1,如果存在一個不是1的情況,那麼我們可以說,該新數據一定不存在於這個布隆過濾器中。
反過來說,如果通過哈希函數算出來的值,對應的地方都是1,那麼我們能夠肯定的得出:這個數據一定存在於這個布隆過濾器中嗎?
答案是否定的,因為多個不同的數據通過hash函數算出來的結果是會有重複的,所以會存在某個位置是別的數據通過hash函數置為的1。
我們可以得到一個結論:布隆過濾器可以判斷某個數據一定不存在,但是無法判斷一定存在。
※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化
台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境
③、布隆過濾器優缺點
優點:優點很明顯,二進制組成的數組,佔用內存極少,並且插入和查詢速度都足夠快。
缺點:隨着數據的增加,誤判率會增加;還有無法判斷數據一定存在;另外還有一個重要缺點,無法刪除數據。
3、Redis實現布隆過濾器
①、bitmaps
我們知道計算機是以二進制位作為底層存儲的基礎單位,一個字節等於8位。
比如“big”字符串是由三個字符組成的,這三個字符對應的ASCII碼分為是98、105、103,對應的二進制存儲如下:
在Redis中,Bitmaps 提供了一套命令用來操作類似上面字符串中的每一個位。
一、設置值
setbit key offset value
我們知道”b”的二進製表示為0110 0010,我們將第7位(從0開始)設置為1,那0110 0011 表示的就是字符“c”,所以最後的字符 “big”變成了“cig”。
二、獲取值
gitbit key offset
三、獲取位圖指定範圍值為1的個數
bitcount key [start end]
如果不指定,那就是獲取全部值為1的個數。
注意:start和end指定的是字節的個數,而不是位數組下標。
②、Redisson
Redis 實現布隆過濾器的底層就是通過 bitmap 這種數據結構,至於如何實現,這裏就不重複造輪子了,介紹業界比較好用的一個客戶端工具——Redisson。
Redisson 是用於在 Java 程序中操作 Redis 的庫,利用Redisson 我們可以在程序中輕鬆地使用 Redis。
下面我們就通過 Redisson 來構造布隆過濾器。
1 package com.ys.rediscluster.bloomfilter.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://192.168.14.104:6379"); 13 config.useSingleServer().setPassword("123"); 14 //構造Redisson 15 RedissonClient redisson = Redisson.create(config); 16 17 RBloomFilter<String> bloomFilter = redisson.getBloomFilter("phoneList"); 18 //初始化布隆過濾器:預計元素為100000000L,誤差率為3% 19 bloomFilter.tryInit(100000000L,0.03); 20 //將號碼10086插入到布隆過濾器中 21 bloomFilter.add("10086"); 22 23 //判斷下面號碼是否在布隆過濾器中 24 System.out.println(bloomFilter.contains("123456"));//false 25 System.out.println(bloomFilter.contains("10086"));//true 26 } 27 }
這是單節點的Redis實現方式,如果數據量比較大,期望的誤差率又很低,那單節點所提供的內存是無法滿足的,這時候可以使用分佈式布隆過濾器,同樣也可以用 Redisson 來實現,這裏我就不做代碼演示了,大家有興趣可以試試。
4、guava 工具
最後提一下不用Redis如何來實現布隆過濾器。
guava 工具包相信大家都用過,這是谷歌公司提供的,裏面也提供了布隆過濾器的實現。
1 package com.ys.rediscluster.bloomfilter; 2 3 import com.google.common.base.Charsets; 4 import com.google.common.hash.BloomFilter; 5 import com.google.common.hash.Funnel; 6 import com.google.common.hash.Funnels; 7 8 public class GuavaBloomFilter { 9 public static void main(String[] args) { 10 BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8),100000,0.01); 11 12 bloomFilter.put("10086"); 13 14 System.out.println(bloomFilter.mightContain("123456")); 15 System.out.println(bloomFilter.mightContain("10086")); 16 } 17 }
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。