缓存穿透解决方案:布隆过滤器

BitSet基础

我们会遇到这样的需求,在海量数据中找出某个数据,我们想要的就是BitSet,BitSet本质是一个bit数组,使用1表示存在,0表示不存在。

简单使用示例:

 BitSet bitSet = new BitSet(10);# 数组大小10
        bitSet.set(1); # 索引1,记1
        bitSet.set(2); # 索引2,记1
        System.out.println(bitSet.get(1212));# 索引1212,没有数据,所以为0
        System.out.println(bitSet.get(1));# 索引1,值为1,表示存在

BitSet占用空间小,1G的空间,可以表示85亿的不同数,所以广泛应用于大数据处理。

当然,BitSet也有不好的地方,

  1. 当数据分布不均匀,BitSet造成空间浪费。比如1,2,999,存入bitSet的时候,需要初始化BitSet空间为999,有效位置只有3个,其他都被浪费。
  2. BitSet只面向数字,且是正数,其他类型需要转为int类型,但是转换的时间也难免出现重复,BitSet准确率则降低。

所以,guava的BloomFilter诞生了,它就是bitSet的增强版本。

BloomFilter布隆过滤器

话不多说,使用起来很方便,如下:

  • 引入google的guava pom
 <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
     <version>19.0</version>
  </dependency>
  • 实现代码
BloomFilter blackListIps = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")),10000);
        blackListIps.put("192.168.2.1");
        blackListIps.put("192.168.2.3");
        blackListIps.put("192.168.3.3");

        System.out.println(blackListIps.mightContain("192.168.2.1"));
        System.out.println(blackListIps.mightContain("192.168.4.1"));

应用

  • 缓存穿透

在使用缓存时候,需要注意很多的坑,其中黑客利用不存在的key去进行缓存穿透,很容易将DB打爆,BloomFilter就可以派上用场了,在每次查询redis之前加个BloomFilter,看是否存在key,没有则直接返回空,防止无效请求到db。

  • 推荐内容去重
  • 爬虫URL判重
  • 垃圾邮件过滤
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页