布隆過濾器是防止緩存穿透的方案之一。布隆過濾器主要是解決大規(guī)模數(shù)據(jù)下不需要精確過濾的業(yè)務(wù)場(chǎng)景,如檢查垃圾郵件地址,爬蟲URL地址去重, 解決緩存穿透問題等。
布隆過濾器:在一個(gè)存在一定數(shù)量的集合中過濾一個(gè)對(duì)應(yīng)的元素,判斷該元素是否一定不在集合中或者可能在集合中。它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間都比一般的算法要好的多,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。
google的guava工具類已經(jīng)幫我們?cè)旌昧溯喿?,通過實(shí)例來感受一下。
dependency> groupId>com.google.guava/groupId> artifactId>guava/artifactId> version>30.1.1-jre/version> /dependency>
import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; import lombok.extern.slf4j.Slf4j; /** * 布隆過濾器簡(jiǎn)單實(shí)現(xiàn) * @author ludangxin * @date 2021/8/16 */ @Slf4j public class BloomFilterTest { /** * 預(yù)計(jì)要插入元素個(gè)數(shù) */ private static final int SIZE = 1000000; /** * 誤判率 */ private static final double FPP = 0.01; /** * 布隆過濾器 */ private static final BloomFilterInteger> BLOOMFILTER = BloomFilter.create(Funnels.integerFunnel(), SIZE, FPP); public static void main(String[] args) { //插入數(shù)據(jù) for (int i = 0; i 1000000; i++) { BLOOMFILTER.put(i); } int count = 0; // 過濾判斷 for (int i = 1000000; i 3000000; i++) { if (BLOOMFILTER.mightContain(i)) { count++; log.info(i + "誤判了"); } } log.info("總共的誤判數(shù):" + count); } }
如上代碼,我們?cè)O(shè)置了0.01的誤差,過濾判斷時(shí)從1000000到3000000,誤判了2 * 20000000 ≈ 20339 符合預(yù)期。
.....
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999004誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999045誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999219誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999699誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999753誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999838誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999923誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 2999928誤判了
21:40:21.529 [main] INFO com.ldx.redisson.controller.BloomFilterTest - 總共的誤判數(shù):20339
guava的工具包雖然好用,但是數(shù)據(jù)集是存儲(chǔ)在jvm中的,分布式環(huán)境下依然沒法使用。
dependency> groupId>org.redisson/groupId> artifactId>redisson-spring-boot-starter/artifactId> version>3.16.1/version> /dependency>
import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RBloomFilter; import org.redisson.api.RedissonClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * redisson 布隆過濾器實(shí)現(xiàn) * * @author ludangxin * @date 2021/8/16 */ @Slf4j @RestController @RequestMapping("bloomFilter") @RequiredArgsConstructor public class BloomFilterWithRedisson { private final RedissonClient redissonClient; /** * 預(yù)計(jì)要插入元素個(gè)數(shù) */ private static final long SIZE = 1000000L; /** * 誤判率 */ private static final double FPP = 0.01; /** * 自定義布隆過濾器的 key */ private static final String BLOOM_FILTER_KEY = "bloomFilter"; /** * 向布隆過濾器中添加數(shù)據(jù), 模擬向布隆過濾器中添加10億個(gè)數(shù)據(jù) */ @GetMapping public void filter() { // 獲取布隆過濾器 RBloomFilterInteger> bloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_KEY); // 初始化,容量為100萬, 誤判率為0.01 bloomFilter.tryInit(SIZE, FPP); // 模擬向布隆過濾器中添加100萬個(gè)數(shù)據(jù) for (int i = 0; i SIZE; i++) { bloomFilter.add(i); } int count = 0; // 過濾判斷 for (int i = 1000000; i 3000000; i++) { if (bloomFilter.contains(i)) { count++; log.info(i + "誤判了"); } } log.info("size:" + bloomFilter.getSize()); log.info("總共的誤判數(shù):" + count); } }
由于機(jī)器性能有限,又是單機(jī)環(huán)境,所以程序沒有跑完。
但由此也可以看出,基于redis的布隆過濾器雖然解決了分布式問題,但是性能和guava bloomfilter沒法比。
到此這篇關(guān)于Redis BloomFilter實(shí)例講解的文章就介紹到這了,更多相關(guān)Redis BloomFilter實(shí)例內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
標(biāo)簽:大慶 果洛 吉安 臺(tái)州 江蘇 楊凌 北京 朝陽
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Redis BloomFilter實(shí)例講解》,本文關(guān)鍵詞 Redis,BloomFilter,實(shí)例,講解,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。