布隆过滤器

布隆过滤器是一种概率数据结构,用于检查集合中是否存在元素

布隆过滤器是 Redis Stack 中的一种概率数据结构,它允许您使用固定大小的极小内存空间来检查集合中是否存在元素。

布隆过滤器不存储集合中的所有元素,而是只存储元素的哈希表示,因此会牺牲一些精度。但好处是,布隆过滤器非常节省空间并且速度很快。

布隆过滤器可以保证一个元素不在集合中,但只能对它的存在给出估计。所以当它回答一个元素不在集合中(一个否定的答案)时,你可以确定情况确实如此。但是,每 N 个肯定的答案中就会有一个是错误的。虽然乍一看这似乎很奇怪,但这种不确定性在计算机科学中仍然有它的位置。在很多情况下,一个否定的答案可以阻止更昂贵的操作,例如检查用户名是否已经被占用,信用卡是否被报告为失窃,用户是否已经看到过广告等等。

用例

金融欺诈检测(金融)

此应用程序回答问题:“用户之前是否从这个位置付款过?”,从而检查用户购物习惯中的可疑活动。

为每个用户使用一个布隆过滤器,在每次交易时进行检查。提供极快的响应(本地延迟)。在用户移动的情况下,在不同的区域复制。防止随着规模的扩大而降低性能。

将 Redis Stack 的布隆过滤器用于此类应用程序,可以提供以下好处

  • 快速完成交易
  • 在网络分区的情况下,降低交易中断的可能性(连接需要保持更短的时间)
  • 为信用卡持卡人和零售商提供额外的安全层

布隆过滤器可以帮助金融行业回答的其他问题包括

  • 用户是否曾经购买过此类产品/服务?
  • 当用户在经过验证的在线商店(如亚马逊、苹果应用商店等大型零售商)购买时,是否需要跳过一些安全步骤?
  • 此信用卡是否被报告为丢失/被盗?在最后一种情况下使用布隆过滤器的一个额外好处是,金融机构可以交换他们被盗/被封锁的信用卡号码列表,而无需透露号码本身。

广告投放(零售、广告)

此应用程序回答以下问题

  • 用户是否已经看过这个广告?
  • 用户是否已经购买了这个产品?

为每个用户使用一个布隆过滤器,存储所有购买的产品。推荐引擎会推荐一个新产品,并检查该产品是否在用户的布隆过滤器中。

  • 如果没有,则向用户展示广告,并将其添加到布隆过滤器中。
  • 如果有,则重新开始该过程,并重复,直到找到一个不在过滤器中的产品。

将 Redis Stack 的布隆过滤器用于此类应用程序,可以提供以下好处

  • 以经济高效的方式实现定制的近实时体验
  • 无需投资昂贵的基础设施

检查用户名是否已被占用(SaaS、内容发布平台)

此应用程序回答以下问题:此用户名/电子邮件/域名/标识符是否已被使用?

为每个注册的用户名使用一个布隆过滤器。新用户输入所需的用户名。该应用程序会检查用户名是否在布隆过滤器中。

  • 如果没有,则创建用户,并将用户名添加到布隆过滤器中。
  • 如果有,该应用程序可以选择检查主数据库或拒绝用户名。

查询时间在规模上保持不变。

将 Redis Stack 的布隆过滤器用于此类应用程序,可以提供以下好处

  • 一种快速有效地执行常见操作的方法
  • 无需投资昂贵的基础设施

示例

假设一家自行车制造商生产了 100 万种不同类型的自行车,你想避免在新车型中使用重复的车型名称。可以使用布隆过滤器来检测重复项。在下面的示例中,你将创建一个容纳 100 万个条目的过滤器,误报率为 0.1%。添加一个车型名称,并检查它是否存在。然后添加多个车型名称,并检查它们是否存在。

注意:即使只有少数项目,也始终存在误报的可能性,这意味着一个项目可能“存在”,即使它没有明确添加到布隆过滤器中。要更深入地了解布隆过滤器的概率性质,请查看此页面底部的链接文章。

保留布隆过滤器

借助 Redis Stack 的布隆过滤器,大部分大小调整工作都已为您完成

BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion] [NONSCALING]

1. 误报率(error_rate

该比率是介于 0 到 1 之间的十进制值。例如,对于所需的 0.1%(1/1000)的误报率,error_rate 应设置为 0.001。

2. 预期容量(capacity

这是您预计过滤器中总共包含的元素数量,当您拥有一个静态集合时,这很简单,但当您的集合随着时间的推移而增长时,它会变得更具挑战性。正确获取此数字非常重要,因为如果您**过度扩大**,最终会导致浪费内存。如果您**过小**,过滤器将填满,一个新的过滤器将不得不堆叠在它的上面(子过滤器堆叠)。在过滤器由多个子过滤器堆叠在一起的情况下,添加的延迟保持不变,但存在检查的延迟会增加。造成这种情况的原因是检查的方式:常规检查将首先在最顶层(最新)过滤器上执行,如果返回否定答案,则检查下一个过滤器,依此类推。这就是增加的延迟来源。

3. 缩放(EXPANSION

由于数据结构“填满”,向布隆过滤器添加元素永远不会失败。相反,误报率开始增长。为了使误报率接近过滤器初始化时设置的误报率,布隆过滤器将自动缩放,这意味着当容量达到时,将创建一个额外的子过滤器。
新子过滤器的尺寸是最后一个子过滤器的尺寸乘以 EXPANSION。如果要存储在过滤器中的元素数量未知,我们建议您使用 2 或更大的扩展值来减少子过滤器的数量。否则,我们建议您使用 1 的扩展值来减少内存消耗。默认扩展值为 2。

过滤器将为每个新的子过滤器添加更多哈希函数,以保持您所需的误报率。

您可能想知道“如果我知道无论如何都要进行缩放,为什么我要创建一个具有高扩展率的小型过滤器?”;答案是:对于需要保存许多过滤器(例如,每个用户一个过滤器,或每个产品一个过滤器)的情况,其中大多数过滤器将保持较小,但一些具有更多活动的过滤器将不得不进行缩放。

4. NONSCALING

如果您知道自己不会进行缩放,请使用 NONSCALING 标志,因为这样过滤器将使用一个更少的哈希函数。请记住,如果您最终达到了最初分配的容量,您的误报率将开始增长。

布隆过滤器的总大小

布隆过滤器实际使用的内存是所选误报率的函数

bits_per_item = -log(error)/ln(2)
memory = capacity * bits_per_item
  
memory = capacity * (-log(error)/ln(2))
  • 1% 的误报率需要每个项目 10.08 位
  • 0.1% 的误报率需要每个项目 14.4 位
  • 0.01% 的误报率需要每个项目 20.16 位

为了比较,当使用 Redis 集合进行成员资格测试时,所需的内存为

memory_with_sets = capacity*(192b + value)

例如,对于一个 IP 地址集合,我们将每个元素大约有 40 字节(320 位),这明显高于我们对于误差率为 0.01% 的布隆过滤器所需的每个元素 20 位。

布隆过滤器与布谷鸟过滤器

布隆过滤器在插入项目时通常表现出更好的性能和可扩展性(因此,如果您经常向数据集添加项目,那么布隆过滤器可能很理想)。布谷鸟过滤器在检查操作方面更快,并且还允许删除。

性能

布隆过滤器中的插入操作为 O(K),其中 k 是哈希函数的数量。

检查一个元素为 O(K) 或 O(K*n),对于堆叠的过滤器,其中 n 是堆叠的过滤器数量。

学术来源

参考资料

网络研讨会

  1. 概率数据结构 - 您可能没有使用的 Redis 中最实用的东西

博客文章

  1. RedisBloom 快速入门教程
  2. 使用布隆过滤器进行开发
  3. RedisBloom 在 Redis Enterprise 上
  4. 可能和否:Redis、RedisBloom 和布隆过滤器
  5. RedisBloom - Redis 的布隆过滤器数据类型
RATE THIS PAGE
Back to top ↑