zoukankan      html  css  js  c++  java
  • 原创 使用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;
    }}
    

    简单的实现完成了。

    化繁为简,极致高效。 所有代码为本人原创,转载请联系本人。
  • 相关阅读:
    在C#中使用SQL存储过程说明
    asp.net后台获取html控件值
    SQL字符串操作汇总[记住这个]select substring(quantityperunit,charindex('',quantityperunit)+1,100) as 结果 from products
    分页控件AspnetPager的用法,巩固用
    摆脱Access在.net中中模糊查询,老错的困扰
    基于黑金开发板的秒表verilog hdl程序
    2808 sci 接收中断
    黑金开发板状态机实现的可用按键控制的流水灯
    基于黑金开发板的键盘边沿检测程序
    可以使用键盘实现加减数的数码管的verilog hdl程序(基于黑金开发板)
  • 原文地址:https://www.cnblogs.com/crissblog/p/14867771.html
Copyright © 2011-2022 走看看