大家好,我是小富~

有个兄弟私下跟我说,他在面试狗东时,有一道面试题没回答上来:Redis 的Bitmap布隆过滤器啥区别与关系?

其实就是考小老弟对这两种工具的底层数据结构是否了解,不算太难的题。不过,bitmap和布隆过滤器在大数据量和高并发业务的使用频率不低,知识点应该掌握下,既然问了那咱们简单的梳理下它们的底层原理、应用场景以及它们之间的关联。

Bitmap

Redis中的Bitmap(位图)是一种较为特殊数据类型,它以最小单位bit来存储数据,我们知道一个字节由 8个 bit 组成,和传统数据结构用字节存储相比,这使得它在处理大量二值状态(true、false 或 0、1等只有两种状态)数据时具有极高的空间效率。不过,它不是一种全新的数据类型,其底层实现仍是基于 String 类型。

便于理解,你可以将 Bitmap 的底层结构看成是由一系列 bit 位组成的数组,在此数组中,每个位都对应一个偏移量(类似数组的下标)。通过将特定偏移量上的位值设置为 0 或 1,来表示不同的状态。

比如我们要设计一个答题游戏系统。其规则为:若用户答对全部 7 道题,则可获得大奖。

每个答题用户都有自己的 key,即 answer:user:X。使用 bitmap 记录用户的答题情况,将题号设置为对应偏移量,当用户答对 题目时 ,偏移量位值设为 1;当用户答错 题目时,位值设为 0。

假如用户user:1 答对了 2、5、7 号题,可将对应偏移量为 2、5、7 的位值设置为 1,其余位值默认设为 0。若要查看该用户对某个题目的回答情况,只需按照偏移量遍历此数据结构,一旦碰到位值为 1 的情况,即表示该题回答正确。

答题活动结束后,接下来需要统计获奖者,即那些全部答对 7 道题的用户。

要快速统计用户是否全部答对题目,可以使用 BITCOUNT 命令来统计位值中被设置为 1 的数量。通过执行 BITCOUNT answer:userX == 7 这样的操作进行判断,若结果等于 7,则表明该用户全部答对了题目。

聪明的你或许会产生疑惑,如果想用 bitmap 判断邮箱地址是否在黑名单内,偏移量该如何设置呢?遗憾的是,bitmap 并不支持直接以字符串作为偏移量。不过,我们可以对邮箱进行哈希运算得到哈希值,进而算出偏移量。

由于用到哈希运算,就不可避免地会出现数据碰撞问题,即不同的字符串可能得出相同的哈希值。这样一来,状态判断就可能不准确。别急,后边介绍布隆过滤器(Bloom Filter)看它如何来优化这个问题。

操作命令

Bitmap 的操作命令不多且使用简单,主要用到的就是SETBITGETBITBITCOUNTBITOP几个命令。

SETBIT:用于设置指定偏移量上的位值,其时间复杂度为 O (1)。例如,当用户答对了第 7 题时,可以将题号对应的偏移量为 7 的位值设置为 1,以此表示该题已被答对。

# 用户key answer:user:1
# 偏移量:题号 7
# 题答对,置为 1
SETBIT answer:user:1 7 1

GETBIT:获取指定偏移量上的位值,同样具有高效的时间复杂度。可以快速查询用户对特定题号的回答状态。

# 查询用户第 7 题的回答情况,1-答对 0-答错
GETBIT answer:user:1 7

BITCOUNT:用于统计位值中被设置为 1 的数量。比如上边我可以很容易统计答对全部题目的用户,但也仅能知道个数,无法查看具体的哪个题目。

# 统计用户答对题为 1 的个数
BITCOUNT answer:user:1

BITOP:对一个或多个 bitmap 进行位运算,并将结果保存到新的键中,支持 AND、OR、NOT、XOR 四种操作。这个命令的用法是将多个bitmap中相同偏移量的位值进行运算。若我想知道用户 1 和用户 2 都答对的题目,经过 AND 运算后,假如只有题号 1 是两个用户都答对的题目,那么生成新的结果集中就只有题号 1 对应的位值为 1。

# 用户1 和 用户2 都答对的题目,可以看出只有题号1的都答对了
SETBIT answer:user:1 1 1
SETBIT answer:user:1 2 0
SETBIT answer:user:1 3 1 SETBIT answer:user:2 1 1
SETBIT answer:user:2 2 1
SETBIT answer:user:2 3 0 BITOP AND resultbitmap answer:user:1 answer:user:2

扬长避短

优点

  • 极高空间效率:bitmap 是真的节省数据存储空间。粗略的算一下,一亿位的 Bitmap 大概才占 12MB 的内存,相比其他数据结构,能极大地节省存储空间;

  • 快速查询:位操作通常比其他数据结构查询速度更快。无论是设置位值还是获取位值,时间复杂度都为 O (1),能够快速响应查询请求;

  • 易于操作:支持单个位操作、位统计、位逻辑运算等,运算效率高,不需要进行比较和移位;

缺点

  • 由于数据结构特点,导致它仅适用于表示两种状态,即 0 和 1。对于需要表示更多状态的情况,Bitmap 就不适用了;

  • 只有当数据比较密集时才有优势,如果我们只设置(20,30,888888888)三个偏移量的位值,则需要创建一个 99999999 长度的 BitMap ,但是实际上只存了3个数据,这时候就有很大的空间浪费,碰到这种问题的话,可以通过引入另一个 Roaring BitMap 来解决

应用场景

看到 Bitmap 还是比较简单的一种数据结构,占用空间小查询效率高,非常适用于记录状态的场景,它的应用场景很常见,比如:

  • 用户签到状态(连续签到天数)

  • 用户的在线状态(统计活跃用户)

  • 问卷答题等等吧!

布隆过滤器

上边咱们提到 bitmap 记录字符元素的状态时,需要先借助哈希运算得出偏移量。但引入哈希运算后可能会出现哈希碰撞的情况,导致状态误判。

布隆过滤器对这个问题做了进一步的优化,做到了可控误判率,当我们将一个邮箱地址添加到集合中,多个不同的哈希函数会将这个邮箱地址映射到 bitmap 中的不同偏移量位置上,且将这些位值置为 1。

要判断邮箱地址是否在集合中,通过相同的哈希函数映射到 bitmap 上的多个位置,如果这些位上的值都为 1,则邮箱可能存在集合中;如果有任何一个位置的值为 0,则元素一定不在集合中。这是布隆过滤器的特点。

虽然但是布隆过滤器还是会发生误判的情况,额~,但好在我们可以通过调整布隆过滤器的大小和哈希函数的数量来控制误判率

操作命令

布隆过滤器的命令也不多,主要用到的如下几个:

BF.RESERVE:创建一个新的布隆过滤器,并指定容量 capacity 和误判率 error_rate。

BF.RESERVE <key> <error_rate> <capacity>
BF.RESERVE myfilter 0.000001 999999

BF.INFO:获取布隆过滤器的信息,包括容量、误判率等。

BF.INFO <key>

BF.ADDBF.MADD:分别是向布隆过滤器中添加元素和批量添加

# 向布隆过滤器中添加元素
BF.ADD myfilter hello
BF.MADD <key> <item> [item ...]

BF.EXISTSBF.MEXISTS:分别是检查布隆过滤器中某个元素和批量检查元素是否存在

# 元素是否存在于布隆过滤器中
BF.EXISTS myfilter hello
# 元素是否存在于布隆过滤器中
BF.MEXISTS <key> <item> [item ...]

扬长避短

优点

  • 布隆过滤器的空间占用也是极小,它本身不存储完整的数据,和 bitmap 一样底层也是通过 bit 位来表示数据是否存在。

  • 性能比较稳定,无论集合中元素的数量有多少,插入和查询操作的时间复杂度都非常低,通常为 O (k),其中 k 是哈希函数的个数。也就是说在处理大规模数据时,布隆过滤器的性能不会随着数据量的增加而急剧下降。

缺点

  • 存在一定的误识别率:布隆过滤器存在误判的情况,即当一个元素实际上不在集合中时,有可能被判断为在集合中。这是因为多个元素可能通过哈希函数映射到相同的位置,导致误判。但是,当布隆过滤器判断一个元素不在集合中时,则是 100% 正确的。

  • 删除元素比较困难:一般情况下,不能直接从布隆过滤器中删除元素。这是因为一个位置可能被多个元素映射到,如果直接将该位置的值置为 0,可能会影响其他元素的判断。

应用场景

布隆过滤器存在一定的误判,所以使用它的场景就一定要允许不准确的情况发生:

  • 解决 Redis 缓存穿透问题:秒杀商品详情通常会被缓存到 Redis 中。如果有大量恶意请求查询不存在的商品,通过布隆过滤器可以快速判断这些商品不存在,从而避免了对数据库的查询,减轻了数据库的压力。

  • 邮箱黑名单过滤:在邮件系统中,可以使用布隆过滤器来过滤垃圾邮件和恶意邮件。将已知的垃圾邮件发送者的地址或特征存储在布隆过滤器中,新邮件来时判断发送者是否在黑名单中。

  • 对爬虫网址进行过滤:在爬虫程序中,为了避免重复抓取相同的网址,可以使用布隆过滤器来记录已经抓取过的网址。新网址出现时,先判断是否已抓取过。

  • 太多太多了.....

总结

一起梳理了 bitmap 和 布隆过滤器的原理、用法以及它们各自的优缺点和应用场景,大环境不好更要多多提升自身技术能力,而且现在面试三句不离大数据量和高并发,此类问题想要应对自如,不仅要有深度还要有广度,掌握这两个知识点多提供一种答案也是好的。写的不好大家对付看吧!

Bitmap 和 布隆过滤器傻傻分不清?你这不应该啊的更多相关文章

  1. [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!

    十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...

  2. 学点经济学:M0、M1、M2、M3,傻傻分不清?(转载)

    来源:http://t.10jqka.com.cn/pid_97006727.shtml 学点经济学:M0.M1.M2.M3,傻傻分不清? 25,508人浏览 2018-08-03 11:06 常听人 ...

  3. ASCII、Unicode、UTF-8、UTF-8(without BOM)、UTF-16、UTF-32傻傻分不清

    ASCII.Unicode.UTF-8.UTF-8(without BOM).UTF-16.UTF-32傻傻分不清 目录 ASCII.Unicode.UTF-8.UTF-8(without BOM). ...

  4. 【jvm】08-垃圾回收器那么多傻傻分不清?

    [jvm]08-垃圾回收器那么多傻傻分不清? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...

  5. cookie、session,、token,还在傻傻分不清?

    摘要:session 和 token 本质上是没有区别的,都是对用户身份的认证机制,只是他们实现的校验机制不一样而已. 本文分享自华为云社区<Session/Cookie/Token 还傻傻分不 ...

  6. MVP MVC MVVM 傻傻分不清

    最近MVC (Model-View-Controller) 和MVVM (Model-View-ViewModel) 在微软圈成为显学,ASP.NET MVC 和WPF 的Prism (MVVM Fr ...

  7. OCA,OCP,OCM傻傻分不清?

    可能大家知道OCA.OCP.OCM的关系是一个比一个难考,一个比一个含金量高,但是你知道具体的考试科目.考试方式.就业形势区别吗?不知道的话这篇通俗易懂的文章会让你一目了然. 区别一:含金量 ■OCA ...

  8. session cookie傻傻分不清

    做了这么多年测试,还是分不清什么是cookie,什么是session?很正常,很多初级开发工程师可能到现在都搞不清什么是session,cookie相对来说会简单很多. 下面这篇文章希望能够帮助大家分 ...

  9. 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】

    文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...

  10. Shell中傻傻分不清楚的TOP3

    Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...

随机推荐

  1. 【转载】 arch linux下nvidia 驱动死机问题

    原文地址: https://my.oschina.net/u/947271/blog/288063 ================================================== ...

  2. 分享某Python下的mpi教程 —— A Python Introduction to Parallel Programming with MPI 1.0.2 documentation

    如题: 无意中发现了一个Python下的mpi教程<A Python Introduction to Parallel Programming with MPI 1.0.2 documentat ...

  3. [rCore学习笔记 022]多道程序与分时任务

    写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 思考 ...

  4. 3.2.0 版本预告!远程日志解决 Worker 故障获取不到日志的问题

    Apache DolphinScheduler 3.2.0 版本已经呼之欲出,8 月 中下旬,这个大版本就要和用户见面了.为了让大家提前了解到此版本更新的主要内容,我们已经制作了几期视频和内容做了大致 ...

  5. 白鲸调度系统助力国内头部券商打造国产信创化 DataOps 平台

    导读 国内某头部券商是国内排名前三的全国性大型综合证券公司.作为证券行业领头羊之一,该券商一直高度重视核心系统的自主可控以及网络信息安全.早些时候,其已经完成了信创化数据库改造和OA系统适配,接下来的 ...

  6. Telegram第三方登录步骤

    网上看到的不多,简单做个记录,本文主要对下面的文章做补充 Telegram(电报)授权登录(web)第三方 整体步骤为: 找 botFather 创建机器人 给机器人设置域名白名单,用于设置回调地址, ...

  7. .NET 开源实时监控系统 - WatchDog

    前言 在平时的开发中随着我们系统应用不断地迭代变的复杂,对应用的实时监控变得越来越重要.实时监控不仅可以帮助我们快速定位问题,还能在出现问题时及时采取措施,减少业务中断的时间. 本文将介绍一个名为Wa ...

  8. MATLAB 使用

    MATLAB CLI 启动 MATLAB CLI 交互式界面(需要已安装 MATLAB): matlab -nodesktop -nosplash # 无桌面环境,无启动动画 不启动 MATLAB 直 ...

  9. pyinstaller 打包 win32ctypes.pywin32.pywintypes.error: (225, '', '无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。')

    背景: 使用python 写了一个程序,使用pyinstaller打包, 不使用-w --noconsole的命令打包隐藏命令行窗口时,是正常的, 但是使用-w或者--noconsole就会报错win ...

  10. 解密Prompt系列37. RAG之前置决策何时联网的多种策略

    之前我们分别讨论过RAG中的召回多样性,召回信息质量和密度,还有calibration的后处理型RAG.前置判断模型回答是否要走RAG的部分我们之前只提及了自我矛盾和自我拒绝者两个方案.这一章我们再补 ...