布隆过滤器与缓存击穿

背景

公司用户中心,有大量的用户请求,为防止缓存击穿,需要设计一个缓存策略 ,将恶意请求过滤掉

什么是缓存击穿得搞清楚。就是有人恶意传入本来数据库就不存在的用户ID,然后大量请求数据库导致数据库挂掉(这里的缓存使用redis)

需求设计

  • redis没有拦住,那肯定是没有拦住的呀。因为redis中没有这个数据,一般策略就是去数据库中读,如果读到了就返回且更新到缓存中(且设置一个过期时间),没有读到就进行回填空值到reids中防止同一个数据库中不存在userId多次请求。但是这里的userId是不同的且不存在。如果是这样的话每来一个直接回填一个那他妈短时间内岂不是对于redis也有压力了。
    在这里插入图片描述

  • 下面我们对布隆过滤器进行简单的介绍

布隆过滤器

简介

  • 可以用来存储不重复的数据,不是真实数据,只是一个数据标识(hash function 计算出来的值),且可以占用少量的空间,且能达到较高的查询性能,但是会在有小的误差,当布隆过滤器说某个值存在时,这个值一定存在;当它说不存在时,那就可能不存在。在对于布隆过滤器见过的值不会出现误差。
  • 那我们换个思路就是把数据库的数据ID同步一份到缓存中 如果有再请求reids拿key对应的value,如果redis没有再去数据库。如果说这个缓存中的valua中没有这个userId那我们就是直接返回。

数据结构

  1. 底层数据结构是一个具有固定大小长度的M bit array。布隆过滤器每存储一个值通过计算n次 hash function 将对应的数组位置从0置为1。当进行再次add的时候寻找对应的位置如果任意一位都不为1,就认为这个数据是不重复的。

  2. 上面也说了布隆过滤器是不允许删除的元素的。由于你删除的元素及其有可能和其他数据元素公用同一个slot。当你删除了这个元素,那你其他元素也就乱掉了。如下图所示 一个key对应3个slot。你删除调key1 也就是将 F,G,H进行恢复为0,那key2毫无疑问就挂掉了。
    在这里插入图片描述

  3. 那我们进行contains比较的时候时间复杂度和空间复杂度是多少呢? 由于是一个连续数组,每次定位一个slot那就是O(1),如果有k个hash func ion那时间复杂度就是O(k)也算是常数级别的。
    那他插入和查找的复杂度就是O(K);

  4. 和set对比一下 set的定位是否重复也是O(1),但是他的战用空间是很大的,等于说是一个hash对应一个位置也就是说这个hash的散列很牛逼(在这里可以联想一下hashMap中将key进行hash计算的列子)。也就是hash的这个值是不能重复使用空间的。 通过专家的计算大概布隆过滤器可以大约90%的空间。主要一部分空间差距在 set会存储值,er布隆过滤器只需要存储值的指纹(指的就是多个hash function 计算出来的内存位置既数组下标位置 )。

  5. 布隆过滤器的误差率是有迹可循的, 可以根据预估的存入元素的数量来得出自己满意的错误率
    布隆过滤器有两个参数,第一个是预计元素的数量 n,第二个是错误率 f。公式根据这
    两个输入得到两个输出,第一个输出是位数组的长度 l,也就是需要的存储空间大小 (bit),
    第二个输出是 hash 函数的最佳数量 k。hash 函数的数量也会直接影响到错误率,最佳的数
    量会有最低的错误率。

k=0.7*(l/n) # 约等于
f=0.6185^(l/n) # ^ 表示次方计算,也就是 math.pow
  1. 说了这么多,这在代码中自己写个布隆过滤器,也不敢用啊。布隆过滤器这么牛逼。那有没有那种直接可以用的呢?

redis4.0 直接上手布隆过滤器

  1. 在redis 4.0以后就有了布隆过滤器的插件。可直接使用jedis bf.add bf.exist bf.madd bf.mexist 进行插入和查找,现在的redisson是真的太强大了。什么都有redisson布隆过滤器的使用
  2. 在使用redis插件布隆过滤器的时候我们也可以进行指定存储元素的大小和错误率,通过bf.reserve 进行创建,但是如果已经有key存在就会出现err
    有三个参数 key, error_rate 和 initial_size。错误率越低,需要的空间越大。initial_size 参数表示预计放
    入的元素数量,当实际数量超出这个数值时,误判率会上升。 所以在初始设置是一定要大概率准确。

总结

  1. 设计了简单的使用布隆过滤器拦截恶意请求
  2. 布隆过滤器是一个概率型数据结构,他可以存储不同数据的指纹。可以通过O(1)复杂度进行查找和添加,存储空间比set集合少百分之90.但是会对没见过的数据判断出现误差(出现误差的原因是一也就是hash碰撞)。
  3. 还有redis4.0 对布隆过滤器的支持以及redisson

资料

  • https://www.cnblogs.com/allensun/archive/2011/02/16/1956532.html (布隆过滤器原理)
  • https://www.bookstack.cn/read/redisson-wiki-zh/spilt.8.6.-%E5%88%86%E5%B8%83%E5%BC%8F%E5%AF%B9%E8%B1%A1.md (redisson对布隆过滤器的使用)

布隆过滤器的其他应用

  • 做新闻推荐,不能推荐该用户历史浏览过的需求,如何使用布隆过滤器实现 ?
  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
布隆过滤器是一种非常实用的解决缓存穿透、缓存击穿和缓存雪崩问题的工具。对于缓存穿透问题,布隆过滤器可以在缓存中存储空值,避免频繁查询数据库。布隆过滤器的原理是通过多次哈希运算将元素映射到一个二进制数组中,如果某个位置的值为1,则表示该元素可能存在;如果为0,则表示该元素一定不存在。通过布隆过滤器,可以快速判断一个请求是否需要查询数据库,从而避免了缓存穿透的问题。\[3\] 对于缓存击穿问题,布隆过滤器可以用于限流和降级策略。通过对热点参数进行限流,可以控制请求的并发量,避免数据库被大量请求压垮。同时,对于无效的请求,可以进行服务降级,直接返回默认值或错误信息,而不是查询数据库。\[2\] 对于缓存雪崩问题,布隆过滤器可以作为一种多级缓存的解决方案之一。除了使用Redis作为缓存外,还可以使用Nginx缓存等其他缓存工具,将请求分散到不同的缓存层,从而减轻数据库的访问压力。同时,可以通过设置缓存的过期时间,避免大量缓存同时过期,导致数据库访问压力过大。\[2\] 总之,布隆过滤器是一种非常实用的工具,可以有效解决Redis缓存雪崩、缓存穿透和缓存击穿问题。通过合理使用布隆过滤器,可以提高系统的性能和稳定性。 #### 引用[.reference_title] - *1* [redis缓存穿透之终极解决方案——布隆过滤器](https://blog.csdn.net/qq_40606397/article/details/114085367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [redis缓存雪崩、击穿、穿透](https://blog.csdn.net/weixin_45414913/article/details/124901909)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值