一文搞懂布隆过滤器和缓存穿透

缓存穿透

什么是缓存穿透

缓存数据的处理流程流程

请添加图片描述
简要来说就是缓存这一层它读取速度很快,我们可以把热数据(也就是被访问频率很高的数据)放在这一层。一是增加效率,二是缓解躲在在缓存坚实的后背下的数据库的压力。至于当在数据库中读取到数据后更新缓存数据这一步,当然是为了保证缓存中的数据是使用最频繁的了,当一个数据多次跳过缓存在数据库中取访问时,那把他更新到缓存中一般是一种很好的办法,因为这样可以增加缓存的命中率,因为缓存效率高嘛,命中率高了当然好。

缓存穿透的概念

了解到上述流程后,缓存穿透其实顾名思义就是缓存被什么东西"穿过"了。其实也就是用户请求穿过了缓存。直接到达了数据库。简单来说就是大量请求的 key 根本不存在于缓存中,导致请求没有命中缓存,直接到了数据库上,根本没有经过缓存这一层(注意是大量请求)。没有经过这一层,也就是相当于穿过了缓存,即为缓存穿透。这样大量请求就会直接落到持久层数据库,给数据库造成巨大的压力。很有可能这时候数据库就蚌埠住,挂掉了。

怎么处理缓存穿透

look look 标题,今天的主角登场了,其他的方法我就不做介绍了。我们直接有请我们的主角登场——布隆过滤器
布隆过滤器有什么作用呢?它最最主要的一个功能就是判断给定的数据是否存在。而且效率极高。
为了避免缓存穿透,也就是我们要避免大量请求落到持久层数据库中,说我们需要在请求到来的时候过滤一下。我们都知道缓存中一般是一个key+value的组合,数据库中如果没有某个key对应的value,那么缓存中也不会存在。因为缓存中存的就是数据库中的访问频率高的数据。
布隆过滤器就可以对每个进来的请求的key进行过滤,刚刚说到它最主要的功能是判断数据是否存在,在缓存穿透场景中,我们可以用它来判断请求的key是否在数据库中存在。存在才能给你放行,不存在那么你这个请求基本是无意义的,还会对数据库产生压力。索性直接不让你进门,这就形成了一个过滤。
请添加图片描述
那小朋友这里你是否有很多问号?所有请求都要经过这个布隆过滤器,那这布隆过滤器扛得住吗?上面有提到,布隆过滤器这个玩意儿,效率是真的高。具体怎么个高法,有请收看下集↓↓↓——布隆过滤器原理解析。

布隆过滤器原理

布隆过滤器组成

很长的二进制向量 + 一系列随机映射函数。
很长的二进制向量其实就是位数组,可能位数组不够清晰。bit数组可能就清晰了吧。话不多说看图:

位数组

请添加图片描述
每个元素都是0或1,bit嘛,一个格子就是1bit。1KB的空间就能存8192个bit。可以看出这个玩意儿占用的空间是非常小的。
一系列随机映射函数就是Hash映射函数,可以有很多个。跟我们的HashSet、HashMap差不多,当一个元素加入的时候,经过一系列Hahs映射最终存到某个位置。但是也有一些不同。

实现过程

当一个元素加入布隆过滤器

首先,位数组初始化中,每个位置都是0。

  1. 使用布隆过滤器中的一系列哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
  2. 根据得到哈希值,得到对应位置,然后把该位置的bit置位1。
判断一个元素是否在布隆过滤器中
  1. 对给定元素再次进行相同的哈希计算,注意是相同,这样相同元素经过相同的Hash映射肯定是相同的位置。
  2. 得到多个值(也就是多个位置)之后判断得到的每个位置在位数组中是否都为 1,如果值都为 1,那么说明这个值可能在布隆过滤器中。如果存在一个值不为 1,说明该元素一定不在布隆过滤器中。
    请添加图片描述

注意我上面说的可能和一定。先抛个结论:
布隆过滤器判断某个元素存在,小概率会误判。布隆过滤器判断某个元素不在,那么这个元素一定不存在。

再来听我分析(结合上图食用更佳):

当一个value要加入到布隆过滤器中时,该value首先由多个哈希函数生成不同的哈希值,然后将对应位置的位数组的下标设置为 1(初始全是0)。当需要判断value是否存在时,由于相同值经过相同Hash映射值一样,所以如果经计算的所有对应位置都已设置为 1,那么很容易就能知道该值存在。去重也是同理,所以布隆过滤器也有很强大高效的去重功能。

但为什么判断存在会误判呢?你想想,不同的value经过多个Hash映射出来的位置,虽然肯定不可能全部位置都相同,但是有可能其中某一个或者几个位置可能是重复的。举个例子,假如A映射的位置是1,2,3,B映射的位置是3,4,5。那么12345五个个位置都是1。现在有个C来了,映射出来是234,C确实和AB映射不一样,但是C的映射钻了他们两的空子。这时候由于234都是1,布隆过滤器会判断C存在,这就造成了误判。但其实这种情况发生概率是比较小的,而且我们可以通过适当增加位数组大小或者调整哈希映射函数来大大降低误判概率。

但是布隆过滤器说不存在,那就肯定不存在。如果经映射的位置存在一个值不为 1,说明该元素不在布隆过滤器中。因为大家都经过同样个数同样的映射方式,你只要有一个地方不为1,说明你肯定不存在在布隆过滤器中。只有别人映射占了你的位置,才造成了你可能存在,但是你的位置是0,别人没来过,你更没有来过,那肯定不存在。

是不是现在对于布隆过滤器有很清晰的认识了,建议再结合缓存穿透场景仔细思考一下,你一定收获满满。

以上只是个人学习中一些感悟与分享,如有错误欢迎指正与交流。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值