摘要:再來看怎么結合一起使用根據給定的布隆過濾器添加值不能為空根據給定的布隆過濾器判斷值是否存在不能為空很簡單,只有兩個方法,往里面添加元素,檢查元素是否在里面這里的客戶端使用的是封裝的,可以在我的項目中查看完整的使用代碼。
前言
最近在研究布隆過濾器(如果不了解什么是布隆過濾器的,推薦看這篇如何判斷一個元素在億級數據中是否存在?了解),發現Guava提供了封裝好的類,但是只能單機使用,一般現在的應用都是部署在分布式系統的,所以想找個可以在分布式系統下使用的布隆過濾器,找了半天只找到一個基于redis開發的模塊項目ReBloom,但是這個是需要額外安裝的,而且文檔里只說了怎么在docker下運行,沒研究過docker所以放棄了。后來找到一篇博客講怎么利用布隆過濾器統計消息未讀數的(博客地址不記得了,是一位淘寶同學寫的),博客最后放了一份整合redis和bloomFilter的代碼demo,詳見BloomFilter.java,看了下實現比較簡單,但是使用方式不是我想要的,所以參考著自己整理了一份。BloomFilterHelper
package com.doodl6.springmvc.service.cache.redis; import com.google.common.base.Preconditions; import com.google.common.hash.Funnel; import com.google.common.hash.Hashing; public class BloomFilterHelper{ private int numHashFunctions; private int bitSize; private Funnel funnel; public BloomFilterHelper(Funnel funnel, int expectedInsertions, double fpp) { Preconditions.checkArgument(funnel != null, "funnel不能為空"); this.funnel = funnel; bitSize = optimalNumOfBits(expectedInsertions, fpp); numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, bitSize); } int[] murmurHashOffset(T value) { int[] offset = new int[numHashFunctions]; long hash64 = Hashing.murmur3_128().hashObject(value, funnel).asLong(); int hash1 = (int) hash64; int hash2 = (int) (hash64 >>> 32); for (int i = 1; i <= numHashFunctions; i++) { int nextHash = hash1 + i * hash2; if (nextHash < 0) { nextHash = ~nextHash; } offset[i - 1] = nextHash % bitSize; } return offset; } /** * 計算bit數組長度 */ private int optimalNumOfBits(long n, double p) { if (p == 0) { p = Double.MIN_VALUE; } return (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2))); } /** * 計算hash方法執行次數 */ private int optimalNumOfHashFunctions(long n, long m) { return Math.max(1, (int) Math.round((double) m / n * Math.log(2))); } }
BloomFilterHelper是實現功能的關鍵,包含了計算bitmap的核心算法,其實大部分代碼都是來源于Guava庫里面的BloomFilterStrategies類,但是因為這個類是專門為Guava的BloomFilter類使用的,所以沒有對外暴露一些重要的算法邏輯。
再來看怎么結合redis一起使用BloomFilterHelper
RedisServicepackage com.doodl6.springmvc.service.cache.redis; import com.google.common.base.Preconditions; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Collection; import java.util.Map; import java.util.concurrent.TimeUnit; @Service public class RedisService { @Resource private RedisTemplateredisTemplate; /** * 根據給定的布隆過濾器添加值 */ public void addByBloomFilter(BloomFilterHelper bloomFilterHelper, String key, T value) { Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能為空"); int[] offset = bloomFilterHelper.murmurHashOffset(value); for (int i : offset) { redisTemplate.opsForValue().setBit(key, i, true); } } /** * 根據給定的布隆過濾器判斷值是否存在 */ public boolean includeByBloomFilter(BloomFilterHelper bloomFilterHelper, String key, T value) { Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能為空"); int[] offset = bloomFilterHelper.murmurHashOffset(value); for (int i : offset) { if (!redisTemplate.opsForValue().getBit(key, i)) { return false; } } return true; } }
RedisService很簡單,只有兩個方法
addByBloomFilter,往redis里面添加元素
includeByBloomFilter,檢查元素是否在redis bloomFilter里面
這里redis的客戶端使用的是spring-data-redis封裝的,可以在我的項目SpringMVC-Project中查看完整的使用代碼。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72665.html
摘要:方法,即表示自動擴容,這個函數名是從中搬過來的。自動擴容最后,也是最重要的,其中用了布隆過濾器中計算型數組長度的方法,得到之后使用命令初始化一個全部為的位數組。 本文源地址:http://www.fullstackyang.com/...,轉發請注明該地址或segmentfault地址,謝謝! 一、背景知識 在網上已經有很多關于布隆過濾器的介紹了,這里就不再贅述,下面簡單地提煉幾個要點...
摘要:方案二布隆過濾器攔截布隆過濾器介紹概念布隆過濾器英語是年由布隆提出的。這就是布隆過濾器的基本思想。防緩存穿透的布隆過濾器判斷是否為合法非法則不允許繼續查庫從緩存中獲取數據緩存為空從數據庫中獲取緩存空對象參考書籍開發與運維 上周在工作中遇到了一個問題場景,即查詢商品的配件信息時(商品:配件為1:N的關系),如若商品并未配置配件信息,則查數據庫為空,且不會加入緩存,這就會導致,下次在查詢同...
閱讀 3618·2021-11-24 10:25
閱讀 2539·2021-11-24 09:38
閱讀 1230·2021-09-08 10:41
閱讀 2914·2021-09-01 10:42
閱讀 2586·2021-07-25 21:37
閱讀 1991·2019-08-30 15:56
閱讀 922·2019-08-30 15:55
閱讀 2759·2019-08-30 15:54