追求性能极致 - Redis:聊聊布隆过滤器(原理篇)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

1 Bloom Filter 介绍

布隆过滤器(Bloom Filter)是 Redis 4.0 版本提供的新功能,我们一般将它当做插件加载到 Redis 服务器中,给 Redis 提供强大的去重功能。
它是一种概率性数据结构,可用于判断一个元素是否存在于一个集合中。相比较之 Set 集合的去重功能,布隆过滤器空间上能节省 90% +,不足之处是去重率大约在 99% 左右,那就是有 1% 左右的误判率,这种误差是由布隆过滤器的自身结构决定的。

  • 优点:空间效率和查询时间都比一般的算法要好的多
  • 缺点:有一定的误识别率和删除困难

2 原理分析

布隆过滤器(Bloom Filter)是一个高空间利用率的概率性数据结构,由二进制向量(即位数组)和一系列随机映射函数(即哈希函数)两部分组成。
通过使用exists()来判断某个元素是否存在于自身结构中。当布隆过滤器判定某个值存在时,其实这个值只是有可能存在;当它说某个值不存在时,那这个值肯定不存在,这个误判概率大约在 1% 左右。
原理拆解如下:

  • 在一个很长的二进制向量和一系列随机映射函数的基础上,将元素哈希成不同的位置,每个位置对应二进制向量中的一个比特位。
  • 当加入一个元素时,采用 n 个相互独立的 Hash 函数计算key,然后将元素 Hash 映射的 n 个位置全部设置为 1。
  • 检测 key 是否存在,仍然用 Hash 函数计算出这 n 个位置,如果元素key 存在于集合中,则对应的位置为1,否则为0。
  • 如果n个位置均为1的话,可以确定元素key可能存在于集合中;如果有一个为0,那么元素的key一定不存在于集合中,下面会详细分析这句话。
  • 这种判断机制会存在误判的可能,但它以较小的空间代价和极简的时间复杂度来近似解决集合交、并、差等操作。

2.1 添加元素步骤


当使用布隆过滤器添加 key 时,会使用不同的 hash 函数对 key 存储的元素值进行哈希计算,从而会得到多个哈希值。根据哈希值计算出一个整数索引值,将该索引值与位数组长度做取余运算,最终得到一个位数组位置,并将该位置的值变为 1。每个 hash 函数都会计算出一个不同的位置,然后把数组中与之对应的位置变为 1。这边可能出现元素碰撞的情况,比如位置3,a元素和b元素的hash计算位置一致,所以出现了碰撞。

2.2 判定元素是否存在步骤

如果我们要判定一个元素是否存在,需要如下步骤:

  • 首先对给定元素key执行哈希计算,这样可以得到元素增加时的bit位数组位置
  • 判断这些位置是否都为 1,如果其中有一个为 0,那么说明元素不存在
  • 若全部位置都为 1,则说明元素有可能存在。

为啥说是可能存在呢,因为上面说过了,哈希函数出的结果会出现碰撞,所以布隆过滤器会存在误判。


如上图c,他的位置被其他元素的位置完全覆盖,即使c没有存储,对应位置上也被a和b的Hash函数设置为1,这时候就可能误判为c是有存储的。
有概率存在这样的 key,它们内容不同,但多次 Hash 后的 Hash 值都相同。

2.3 元素删除步骤

一般不会删除元素,我们上面说了,因为可能存在碰撞情况,所以也有可能存在误删除情况。


删除意味着需要将对应的 n 个 bits 位置设置为 0,其中有可能是其他元素对应的位。
比如图中的b删除之后,位置3的值也被设置为0,这样a也可能会被判定为不存在。

3 使用场景介绍

我们在遇到数据量大的时候,为了去重并避免大批量的重复计算,可以考虑使用 Bloom Filter 进行过滤。
具体常用的经典场景如下:

  • 解决大流量下缓存穿透的问题
  • 过滤被屏蔽、拉黑、减少推荐的信息,一般你在浏览抖音或者百度App的时候,看到不喜欢的会设置减少推荐、屏蔽此类信息等,都可以采用这种原理设计。
  • 各种名单过滤,使用布隆过滤器实现第一层的白名单或者黑名单过滤,可用于各种AB场景。

4 安装集成

如果是自己编译安装,可以从 github 下载,目前的latest 的 release 版本是 v2.6.12,下载地址如下:
Release v2.6.12 · RedisBloom/RedisBloom · GitHub

直接按照编译的方式进行安装:

    # 解压文件:
    tar -zxvf tar -zxvf RedisBloom-2.6.12.tar.gz
    # 进入目录:
    cd RedisBloom-2.6.12
    # 执行编译命令,生成redisbloom.so 文件:
    make
    # 拷贝至指定目录:
    cp redisbloom.so /usr/local/redis/RedisBloom-2.6.12/redisbloom.so
    
    # 需要修改 redis.conf 文件,新增 loadmodule配置,并重启 Redis。
    # 在redis配置文件里加入以下配置:
    loadmodule /usr/local/redis/RedisBloom-2.6.12/redisbloom.so
    
    # 配置完成后重启redis服务:
    redis-server /usr/local/redis/RedisBloom-2.6.12/redis.conf
    
    # 测试是否安装成功
    127.0.0.1:6379> bf.add user brand
    (integer) 1
    127.0.0.1:6379> bf.exists user brand
    (integer) 1

5 总结

大致说了布隆过滤器的原理和使用场景,下一篇我们来看看实战。

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值