原创 使用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;
}}

简单的实现完成了。

posted @ 2021-06-09 17:16  cris's  阅读(123)  评论(0编辑  收藏  举报