大数据处理(位图,布隆过滤器)

位图法

位图的基本概念是用一个位(bit)来标记某个数据的存放状态。

  • 海量数据排序
   从最简单的情况说起,如果要对90个小于100的不重复的正整数排序。用位图的思想就是先申请一块100bit的空间,第一遍遍历所有的数,将出现的数字在位图中对应的位置置为1;第二遍遍历位图,依次输出值为1的位对应的数字。先且不说这种情况出现的频率不是很高,就仅这种情况,还是有很多其他的排序算法有它们自己的优势(不用额外占用空间之类)。但更进一步,如果我们把数字范围放大,对1000,000,000中的900,000,000个不重复的正整数排序,由于需要的内存非常大,其他算法在不分治的情况下就很难再处理这个问题。而用位图法只需要1000000000/(8*1024*104)=119.2MB空间,对现在的计算机来说没有任何问题。
  • 海量数据去重
     看一个比较常见的面试题:在2.5亿个整数中找出不重复的整数,内存不足以放下算有的数。我们可以采用两位的位图法,为每个数分配两位,00表示没有出现,01表示出现一次,10表示出现多次,11没有意义。这样下来总共需要
2322=1232∗2=1GB

(这里没有限定整数的范围,所有把所有32位整数都考虑进去)的内存。接下去扫描着2.5亿个整数,查看位图中相对应的位,如果是00就变为01,如果是01就变为10,其他情况保持不变。扫描完成后仍为01的整数就是需要查找的数。

 总结:

Bitmap适用于数据规模大,但数据状态少的情况。同时Bitmap在存在以下一些不足:

  • 存储离散数据利用率低 
    Bitmap申请空间时要根据最大的数来决定申请的空间大小,如果数据是离散的,那空间的利用率就会非常低。
  • 不适合多状态 
    一个bit只能表示两种状态,如果要表示更多的状态,就需要更多的状态位来实现。如果一个数字需要多个状态位来表示的话,Bitmap的优越性也会大打折扣,而且复杂度却在增加。
  • 可读性差 
    将数据抽象为bit不利于理解,尤其是用多个bit位来表示一个数时。
  • 性能一般 
    需要维护额外的逻辑,计算速度会受到一定的影响。

参考链接:https://blog.csdn.net/u013291394/article/details/50211181

位图其他应用:https://blog.csdn.net/wenqiang1208/article/details/76724338

布隆过滤器

然而Bitmap不是万能的,如果数据量大到一定程度,如开头写的64bit类型的数据,就不能用Bitmap。

所以Bitmap的好处在于空间复杂度不随原始集合内元素的个数增加而增加,而它的坏处也源于这一点——空间复杂度随集合内最大元素增大而线性增大

Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。Bloom Filter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省。

布隆过滤器需要的是一个位数组(和位图类似)和K个独立的映射函数(和Hash表类似)

直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。
和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。

算法:
1. 首先需要k个hash函数,每个函数可以把key散列成为1个整数
2. 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
3. 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,可能在集合中。如果不全为1,则一定不在集合中。

优点:

不需要存储key,节省空间

缺点:
1. 算法判断key在集合中时,有一定的概率key其实不在集合中
2. 无法删除

下图为K=3,哈希函数为X,Y,Z的情况:



误判补救方法是:再建立一个小的白名单,存储那些可能被误判的信息

应用:

网页URL的去重,垃圾邮件的判别,集合重复元素的判别,查询加速(比如基于key-value的存储系统)等。

主要工作是判断一条URL是否在现有的URL集合之中(可以认为这里的数据量级上亿)。 
对于HTTP缓存服务器,当本地局域网中的PC发起一条HTTP请求时,缓存服务器会先查看一下这个URL是否已经存在于缓存之中,如果存在的话就没有必要去原始的服务器拉取数据了(为了简单起见,我们假设数据没有发生变化),这样既能节省流量,还能加快访问速度,以提高用户体验。 
对于Web爬虫,要判断当前正在处理的网页是否已经处理过了,同样需要当前URL是否存在于已经处理过的URL列表之中。 每个URL都有其独特的指纹。虽然布隆过滤器还有极小的可能将一个没有抓取过的URL误判为已经抓取过,但它绝对不会对已经抓取过的URL进行重新抓取

假设邮件服务器通过发送方的邮件域或者IP地址对垃圾邮件进行过滤,那么就需要判断当前的邮件域或者IP地址是否处于黑名单之中。如果邮件服务器的通信邮件数量非常大(也可以认为数据量级上亿),那么也可以使用Bloom Filter算法。 

在 leveldb 中有应用,提升查询未命中的效率。在从磁盘加载数据前,先从布隆过滤器中判断数据是否存在。如果不存在,就直接返回。这样可以减少磁盘访问,提升响应速度。

参考链接:https://www.cnblogs.com/liyulong1982/p/6013002.html

                  https://blog.csdn.net/wenqiang1208/article/details/76769001

                  https://www.cnblogs.com/cpselvis/p/6265825.html

猜你喜欢

转载自blog.csdn.net/u012864854/article/details/80042806