Java教程:防缓存穿透利器-布隆滤器(BloomFilter)

防缓存穿透利器-布隆滤器(BloomFilter)

一、布隆过滤器原理

​ 如果想要判断一个元素是不是在一个集合中存在,一般的想法是将所有元素保存起来,然后再拿着这个元素在集合中一个一个进行比对。但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢。 针对这种需要在大量数据中去判断某一个值是事否存在的情况,1970年由布隆提出了布隆过滤器的概念。布隆过滤器本质是一个位数组,位数组就是数组的每个元素都只占用 1 bit 。每个元素只能是 0 或者 1。这样申请一个 10000 个元素的位数组只占用 10000 / 8 = 1250 字节 的空间。布隆过滤器除了一个位数组,还有 n个哈希函数。

​ 它具体的实现思想是并不将具体的数据存储在数组中,而是通过hash函数对要存储的数据进行三次hash运算,并将hash运算的结果做为位数组的下标,将对应的数组元素修改为1。

​ 例如:我们要将"oracle"、“database”、"filter"存储到布隆过滤器中可以这样做。如下图所示

在这里插入图片描述

​ 从上图中可以看到,我们有三个hash函数(h1()、h2()、h3())和一个位数组,oracle经过三个hash函数,得到第1、4、5位为1,database同理得到2、5、10位1,这样如果我们需要判断oracle是否在此位数组中,则通过hash函数判断位数组的1、4、5位是否均为1,如果均为1,则判断oracle在此位数组中,database同理。这就是布隆过滤器判断元素是否在集合中的原理。

​ 但同学们也会发现,如果我们现在要判断"mysql"是否存在,例如它通过三次hash运算得到的值分别是4,5,10。现在即使你的位数中没有存储“mysql”,布隆过滤器也会判断它存在。这是因为"oracle"、“database”、"filter"算出的hash值已经导致上面的三个位置的值被改为了1,这样就会导致误判。但是可以保证的是,如果布隆过滤器判断一个元素不在一个集合中,那这个元素一定不会再集合中。

​ 产生上面误判的主要原因是hash碰撞导致的。但如果我们将位数组设置的足够大,并且让hash运算执行的次数多一些,这样就会降低误判率。

​ 布隆过率器还有另一个问题就是不能删除。这是因为在位数组上的同一个点有可能有多个输入值的映射,如果删除了会影响布隆过滤器里其他元素的判断结果。

​ 所以我们可以总结出布隆过滤器的优缺点如下:

  • 优点:

    • 所占空间小(并不存储真正的数据),空间效率高

    • 查询时间短

  • 缺点:

    • 元素添加到数组中后,不能被删除

    • 有一定的误判率

二、布隆过滤器使用场景

  • 解决缓存穿透问题,缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中就到数据库中去查,并且出于容错考虑,如果从数据库中查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库中去查询,失去了缓存的意义。在流量大时,可能数据库就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则再到数据库中查。如果不在布隆器中,则直接返回
  • 在业务场景中可以用来判断用户是否阅读过某些文章或视频,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。
  • 黑名单:比如在邮件系统中可以使用布隆器设置黑名单,判断邮件地址是否在黑名单中。也可以设IP黑名单防止网格爬虫等。
  • 垃圾邮件过滤,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱。

三、实践

3.1 通过 Java 编程手动实现布隆过滤器

package com.heima.rbac.controller;

import java.util.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值