原创 使用redis位图实现布隆过滤器
1 实现布隆过滤器服务类
@Service
public class RedisBloom {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 根据给定的布隆过滤器添加值
*/
public <T> void addByBloomFilter(BloomFilterHelper<T> 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 <T> boolean includeByBloomFilter(BloomFilterHelper<T> 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;
}}
2 helper类
public class BloomFilterHelper
private int numHashFunctions;
private int bitSize;
private Funnel<T> funnel;
public BloomFilterHelper(Funnel<T> 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)));
}}
3 测试布隆过滤器
@RestController
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public class OrderController {
private static BloomFilterHelper<Integer> bloomFilter = new BloomFilterHelper(Funnels.integerFunnel(), 1000, 0.001);
@Value("${key.dev2}")
private String key2;
@Autowired
OrderService orderService;
@Autowired
ProductService productService;
@Autowired
RedisBloom redisBloom;
@PostMapping("/tsBloom")
public int tsBloom() {
int count = 0;
// 先添加全集
// for (int i = 0; i < 1000; i++) {
// redisBloom.addByBloomFilter(bloomFilter, "tsbloom", i);
// }
for (int i = 1000; i < 2000; i++) {
if (redisBloom.includeByBloomFilter(bloomFilter, "tsbloom", i)) {
count++;
}
}
return count;
}}
简单的实现完成了。
化繁为简,极致高效。
所有代码为本人原创,转载请联系本人。