问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Redis缓存穿透中的布隆过滤器详解

创作时间:
作者:
@小白创作中心

Redis缓存穿透中的布隆过滤器详解

引用
CSDN
1.
https://m.blog.csdn.net/qq_51350957/article/details/145752911

布隆过滤器(Bloom Filter)是一种空间效率极高、查询时间复杂度为O(k)的概率型数据结构,主要用于快速判断元素是否存在于集合中。在缓存系统中,布隆过滤器可以有效防止缓存穿透问题,通过预先过滤不存在的元素,避免大量无效请求直接打到数据库。本文将详细介绍布隆过滤器的基本概念、工作原理、应用场景以及在Redis缓存穿透中的具体应用。

基本概念

布隆过滤器(Bloom Filter)是一种概率型数据结构,用于快速判断元素是否存在于集合中。具有以下特点:

  • 空间效率极高
  • 查询时间复杂度O(k)(k为哈希函数数量)
  • 允许误判(False Positive)
  • 绝不漏判(False Negative)

数据结构组成

  • 位数组(Bit Array):长度为m的二进制向量
  • 哈希函数组:k个相互独立且均匀分布的哈希函数

工作原理


图片来自小林coding

添加元素

使用k个哈希函数计算元素值
将对应的位数组位置置1

查询元素

使用相同的k个哈希函数计算
检查所有对应位置是否都为1

特性分析

特性 描述
空间效率 O(m) 空间复杂度,m为位数组长度
时间效率 插入和查询都是O(k)
确定性结论 返回"不存在"时100%可靠
概率性结论 返回"存在"时有一定误判概率
数据不可逆 无法从位数组恢复原始数据
不支持删除 因多个元素可能共享位标志

误判率计算

误判概率公式:
P ≈ (1 - e(-kn/m))k
m:位数组长度
k:哈希函数个数
n:已插入元素数量

最佳实践公式(最小误判率时):
k = (m / n) * ln(2)

应用场景

  • 缓存系统:防止缓存穿透
  • 分布式系统:快速判断数据是否存在
  • 爬虫系统:URL去重
  • 数据库:减少磁盘查询
  • 安全领域:恶意网址检测
  • 推荐系统:已读内容过滤

优化方向

  • 动态扩容:自动扩展位数组大小
  • 参数调优:
  • 根据预期元素量选择m
  • 根据m/n比值选择k值
  • 哈希函数优化:使用更均匀分布的哈希算法
  • 变种方案:
  • 计数布隆过滤器(支持删除)
  • 分块布隆过滤器
  • 动态布隆过滤器

参数选择参考表

预期元素量(n) 推荐位数组大小(m) 推荐哈希函数数(k) 理论误判率
10,000 95,893 bits 7 1%
100,000 958,506 bits 7 1%
1,000,000 9.58MB 7 1%
10,000,000 95.8MB 7 1%

关键结论

  • 位数组越大,误判率越低
  • 哈希函数数量需要权衡:
  • 过少:容易冲突
  • 过多:位数组快速饱和
  • 实际使用需要根据业务场景:
  • 选择可接受的误判率
  • 平衡内存使用和准确性

Redis缓存穿透中布隆过滤器的应用

缓存穿透问题概述

缓存穿透是指在高并发场景下,大量请求查询数据库中不存在的数据,导致请求直接穿透缓存层打到数据库,给数据库带来巨大压力。例如,攻击者恶意构造大量不存在的商品 ID 来请求商品信息,由于缓存中没有这些数据,每次请求都要访问数据库,可能导致数据库性能下降甚至崩溃。

布隆过滤器的应用

  • 初始化布隆过滤器:在 Redis 中,可以使用第三方库(如 RedisBloom)来实现布隆过滤器。首先,根据预期的元素数量和可接受的误判率,设置布隆过滤器的参数,如位数组大小(m)和哈希函数数量(k)。例如,预期要存储 10000 个元素,希望误判率控制在 1%,可以根据相关公式计算出合适的 m 和 k 值。

  • 数据写入:当有新数据写入数据库时,同时将该数据的相关标识(如商品 ID)添加到布隆过滤器中。以添加商品信息为例,假设商品 ID 为 12345,通过 RedisBloom 的命令将其添加到布隆过滤器中。具体命令可能如下(不同库的命令可能略有差异):

BF.ADD myBloomFilter product:12345

这里 myBloomFilter 是布隆过滤器的名称,product:12345 是要添加的元素。

  • 请求处理:当有请求到来时,首先根据请求的参数(如请求的商品 ID),在布隆过滤器中进行查询。例如,请求商品 ID 为 67890 的商品信息,使用以下命令查询布隆过滤器:
BF.EXISTS myBloomFilter product:67890

如果查询结果为该元素不存在(返回 0),则直接返回结果,无需查询数据库,避免了缓存穿透。如果查询结果为该元素可能存在,则继续查询 Redis 缓存。

  • 缓存查询与处理:如果布隆过滤器判断元素可能存在,接着查询 Redis 缓存中是否存在对应的数据。如果缓存中有数据,直接返回给客户端;如果缓存中没有数据,则查询数据库,将查询到的数据存入 Redis 缓存(同时设置合适的过期时间),然后返回给客户端。在将数据存入缓存的同时,也可以再次将相关标识添加到布隆过滤器中,以确保布隆过滤器的准确性。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号