位图-布隆过滤器

https://time.geekbang.org/column/article/76827  

极客时间学习

布隆过滤器实际是基于位图来实现的一种数据存储结构;

关于位图

https://en.wikipedia.org/wiki/Bit_array

对于位图的底层存储结构实际为数组结构,目的是为了存储大量的数据,为了表示存储的数据是否存在,可以使用0/1代表true/false

存储的数据流程为

  1. 根据自定义的hash计算公式得到对应的数组下标
  2. 并将数据进行相应的位运算得到的结果存储到数组中;

当需要查询数据时

  1. 将当前要查询的数据转换为对应的数组索引
  2. 根据索引定位数组中的数据并执行存储时位运算的相反操作判断数据是否存在

可以看出位图基于数组下标查询效率非常高效,且相对而言,位运算使用cpu计算也比较高效

 

位图也存在一些缺点,对于随着数据量的增加,要申请数组的空间也越来越大;

位图的相关实现类

java 中的 BitSet

 

布隆过滤器

布隆过滤器的产生就是为了解决位图在数据量过大情况下导致了内存浪费;

布隆过滤器为了解决内存占用的问题,由于位图实际是利用一个index来定位一个数据,如果在数据密集度相对稀疏的情况下,会导致数组空间浪费(存在大量空洞插槽); 布隆过滤器利用多个插槽位置来定义一个元素,尽最大的可能性来提高空间利用率; 对于一个数据对应多个插槽,实际就是利用多个hash函数生成多个索引位置

但要注意的是,布隆过滤器 主要是为了解决空间浪费问题,并不能完全解决hash冲突;

由于hash冲突的存在会导致一些误判的发生,虽然使用多个hash函数可以降低冲突的概率,但还是会存在一些极端的情况出现hash冲突,导致不存在的数据被布隆过滤器判定为存在;

但是对于布隆过滤器判定为不存在的数据,是肯定不存在的

 

虽然布隆过滤器对于空间利用率较高,但随着数组剩余空间越来越小,会导致hash冲突的概率越来越大,因此需要设置一个阈值,当剩余空间达到一定阈值后,就需要执行扩容,降低hash冲突概率

 

布隆过滤器的应用场景

redis 缓存穿透 就可以利用 布隆过滤器来降低缓存穿透发生概率;

redis 缓存穿透的理解 ,  对于 redis中和数据库中都不存在的数据,当从redis中获取不到数据时,请求就会请求到服务端执行db查询操作,当存在大量缓存穿透的情况就会导致redis和服务以及数据库的压力剧增;

当redis 使用 布隆过滤器后,

  • 首先能通过布隆过滤器的判定,对于不存在的数据,redis和db中肯定都不存在;
  • 但对于布隆过滤器判断为存在的数据,即使经过redis查询发生数据不存在,从而查找db也发现数据不存在 的情况, 但对于这种情况毕竟几率较低,即使出现了对整个redis以及服务的压力也不会非常大

 

相关技术实现

位图、布隆过滤器应用如此广泛,很多编程语言都已经实现了。比如 Java 中的 BitSet 类就是一个位图,Redis 也提供了 BitMap 位图类,Google 的 Guava 工具包提供了 BloomFilter 布隆过滤器的实现

-- 极客时间 https://time.geekbang.org/column/article/76827  王争老师的 <<数据结构与算法之美>>

posted @ 2020-12-16 20:55  郭星  阅读(281)  评论(0)    收藏  举报