• 布隆过滤器


    目录

    前言:

    使用场景:

    实现原理:

    使用方式:

    总结:

    参考文章

    高频面试考点:解读布隆过滤-极客时间


    前言:

            提到布隆过滤器,我想大家首先能想到的就是解决缓存击穿的问题。确实不错,它确实能在Redis中应用的最为广泛。其实布隆过滤器是一种算法思想,常用来用作判断某一个对象是否存在。接下来我将从使用场景、实现原理、如何使用、优劣势来介绍它。


    使用场景:

       在前言中我们提到了布隆过滤器常用来判断某一个对象是否存在,最常见的应用就是在Redis中,判断某一个key是否在Redis中存在,避免因为缓存穿透,认为恶意的攻击Redis缓存中不存在的值,直接将请求打到数据库,增加数据库的压力。

    我们还有一些常用的使用场景比如:

    •    爬虫应用中,对重复爬虫的URL进行去重。
    •    垃圾邮件、短信过滤:通过判断当前的号码是否在维护的黑名单的号码池中,进行过滤,拦截。
    •    秒杀系统:查看用户是否重复购买。

    实现原理:

        我们在前面提供布隆过滤器的主要使用场景,在于过滤,在于判断某个对象是否存在。如果说仅仅只是判断是否存在。

         其实我们可以使用HashMap去判断一个key是否存在。并且时间复杂度为O(1) , 可以说是非常的高效。在数据量小的情况下HashMap确实能帮助我们实现,但是当数据量特别大的时候,时间复杂度还是没有变化,但是空间复杂度却发生变化。HashMap需要更多的内存去存储数据的内容。

         为了解决内存占用的问题。布隆过滤器使用bit位的0和1来存储对象是否存在的结果。和HashMap一样,布隆过滤器也使用hash函数来判断对象是否存在,但是Hash函数我们知道有冲突的可能性。为了解决这个问题的解决方案是。如果一个Hash函数有冲突,那么就利用多个hash函数,然后将多个hash函数的判断结果存放到bit位中。这样既解决了内存消耗的问题,也解决了hash冲突的问题。具体实现原理如下图:


    使用方式:

       在使用方式上,有分单机版和分布式版本。

    在单机版本上,我们可以直接使用Google开源的Guava库布隆过滤器的实现类Bloomfilter

    1. // 创建布隆过滤器对象
    2. BloomFilter filter = BloomFilter.create(
    3.     Funnels.stringFunnel(Charsets.UTF_8),
    4.     10000,
    5.     0.1);
    6. // 判断指定元素是否存在
    7. System.out.println(filter.mightContain("ABC"));
    8. // 将元素添加进布隆过滤器
    9. filter.put("ABC");
    10. System.out.println(filter.mightContain("ABC"));

                如果需要在分布式的场景下使用布隆过滤器就需要使用Redis,布隆过滤器是redis的一个插件,如果想使用需要单独安装。RedisBloom 是 Redis 官方推荐的布隆过滤器插件,可以通过https://github.com/RedisBloom/RedisBloom来下载。

     下面我们介绍一个判断元素是否存在的命令 

     bf.exists test user1

       bf.exists 判断 user1 是否在 test 过滤器中,与之对应的有一个 bf.mexists 命令可以批量判断多个元素是否存在:

    bf.mexists test user1 user2

     最后我们介绍最重要的命令 bf.reserve,它的功能是创建一个布隆过滤器,

    格式如下:

    bf.reserve {key} {error_rate} {size} [expansin]

    下面我介绍一下每个参数的含义:

    • key:布隆过滤器的名称。
    • error_rate : 误报率,这是一个小数。例如,error_rate 则配置为 0.01 表示误报率为 1%。该数字越小,服务器资源消耗就越大。考虑到资源占用,通常我们不会把这个指标设置得太小,可以把 error_rate 设置的稍大一些,因为我们使用布隆过滤器就是来判断某个元素不存在的,而判断某个元素存在的业务场景非常少。
    • size: 过滤器的容量。建议根据业务场景来配置,若空间不足会增加误判的几率。
    • expansion:作为最后一个参数,这个参数不是必须的,默认是 2。当布隆过滤器满了之后,布隆过滤器会自动创建默认容量是自己 2 倍的新的过滤器

    总结:

     针对布隆过滤器使用的优势与劣势。

              首先最大的优势是在数据量特别大的场景。能占用比较小的场景下快速判断对象是否存在。虽然需要用多个hash函数,但是判断过程是CPU密集型的计算,相比HashMap的一次hash函数,但是需要在内存中比较是否对象是否相等。这是属于内存密集型计算,理论上布隆过滤器的判断更加高效。

              缺点就是:布隆过滤器存在一定的误判率,一般用于判断元素不存在。

    经过它计算的结果是不存在,那么元素一定不存在,如果计算的结果为存在,会存在,不能一定确认元素存在,因为,可能所有的hash函数都冲突了,别的元素提前将bit为设置为1

    参考文章

    高频面试考点:解读布隆过滤-极客时间

    算法(3)---布隆过滤器原理 - 雨点的名字 - 博客园

  • 相关阅读:
    skywalking功能介绍
    面试突击86:SpringBoot 事务不回滚?怎么解决?
    【C++刷题】二叉树进阶刷题
    文本处理之xml
    C# 去除utf-8 BOM头
    查找xml文件
    PCB走线规则
    关于content-type的理解
    java01
    Docker (二): Docker安装及配置镜像加速
  • 原文地址:https://blog.csdn.net/weixin_44399827/article/details/126285425