布容过滤器


使用场景


1.解决缓存穿透。
2.解决高效去除爬虫所抓取页面重复URL。
3.计算网站用户UV。
4.高效判断用户名是否唯一。
5.如何判断垃圾邮件。


核心设计思路:
布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k。当需要判断一个key是否存在时,我们通过对当前key进行k次hash函数计算,如过K次hash计算都命中,说明key存在。当然存在hash冲突的概率,所以可以用在允许小规模误判的场景,当然这个误判的概率我们是可以通过相关代码的实现来降低的,只是需要花费一定的空间,例如以上的开篇的场景都是适用的。

 

布隆过滤器特点

布隆过滤器一个重要的特点就是不存储实际的key值,在网页大规模爬虫URL去重的情况下,如果我们对每个URL进行存储(一个URL  64长度),然后判断是否重复,我们需要放置到一个Map\Set类似的容器里面。当需要在10亿个URL里面判断是否重复,我们需要的存储空间是非常大的,而布容过滤器很巧妙的通过位数组来实现,一位只需要1bit的存储空间。一个URL如过我们进行k次hash计算,我们最多只要需要k*1bit的存储空间,当然URL多的时候,还会存在部分bit是复用的情况需要耗费的空间还能进一步降低。

 

使用DEMO


Java语言下有非常多的实现,我们常用的Guava包提供了BloomFilter的实现。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterTest {
    
    private static final int insertions = 1000000; //100w

    public static void main(String[] args){
        //初始化一个存储string数据的布隆过滤器,初始化大小100w,不能设置为0
        BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), insertions,0.00001);
        //初始化一个存储string数据的set,初始化大小100w
        Set<String> sets = new HashSet<>(insertions);
        //初始化一个存储string数据的set,初始化大小100w
        List<String> lists = new ArrayList<String>(insertions);
        
        //向三个容器初始化100万个随机并且唯一的字符串---初始化操作
        for (int i = 0; i < insertions; i++) {
            String uuid = UUID.randomUUID().toString();
            bf.put(uuid);
            sets.add(uuid);
            lists.add(uuid);
        }
        
        int wrong = 0;//布隆过滤器错误判断的次数
        int right = 0;//布隆过滤器正确判断的次数
        for (int i = 0; i < 10000; i++) {
            String test = i%100==0?lists.get(i/100):UUID.randomUUID().toString();//按照一定比例选择bf中肯定存在的字符串
            if(bf.mightContain(test)){
                if(sets.contains(test)){
                    right ++;
                }else{
                    wrong ++;
                }
            }
        }
        
        System.out.println("=================right====================="+right);//100
        System.out.println("=================wrong====================="+wrong);
    }
    
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值