海量数据处理

1、引言

海量数据处理工作为:基于海量数据上的存储、处理和操作。

时间: 采用巧妙的算法,搭配合适的数据结构,如Bloom filter(布隆过滤器)、hash、bitmap、堆、trie树。
空间: 大而化之,分而治之(hash映射)。

2、算法/数据结构基础

2.1 boolm filter(布隆过滤器)

Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。它是一个判断元素是否存在集合的快速的概率算法。Bloom Filter有可能会出现错误判断,但不会漏掉判断。也就是Bloom Filter判断元素不再集合,那肯定不在。如果判断元素存在集合中,有一定的概率判断错误。因此,Bloom Filter不适合那些
“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter比其他常见的算法(如hash,折半查找)极大节省了空间。

适用范围:
可以用来实现数据字典,进行数据的判重,或者集合求交集。

Bloom Filter有以下几个特点:

  • 不存在漏报(False Negative),即某个元素在某个集合中,肯定能报出来。
  • 可能存在误报(False Positive),即某个元素不在某个集合中,可能也被爆出来。
  • 确定某个元素是否在某个集合中的代价和总的元素数目无关。

Bloom Filter优点:

  • 相比于其它的数据结构,Bloom Filter在空间和时间方面都有巨大的优势。
  • Bloom Filter存储空间和插入/查询时间都是常数。
  • 另外, Hash函数相互之间没有关系,方便由硬件并行实现
  • Bloom Filter不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

Bloom Filter缺点:

  • 一般情况下不能从Bloom Filter中删除元素. 我们很容易想到把位列阵变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全的删除元素并非如此简单。首先我们必须保证删除的元素的确在Bloom Filter里面. 这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。

2.2 Hash

散列,或称为“哈希”,是一种压缩映射,简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

2.3 Bit-map

用一个bit位来标记某个元素对应的值value。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。

优点:

  1. 运算效率高,不许进行比较和移位;
  2. 占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M。

缺点:

  1. 所有的数据不能重复。即不可对重复的数据进行排序和查找。

算法思想比较简单,但关键是如何确定十进制的数映射到二进制bit位的map图。(用位移将十进制数转换为对应的bit位)

Bit-Map的应用
1)可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下。
2)去重数据而达到压缩数据

应用
**具体问题场景1分析:**给一台普通PC,2G内存,要求处理一个包含40亿个不重复并且没有排过序的无符号的int整数,给出一个整数,问如果快速地判断这个整数是否在文件40亿个数据当中?

问题思考:

40亿个int占(40亿*4)/1024/1024/1024 大概为14.9G左右,很明显内存只有2G,放不下,因此不可能将这40亿数据放到内存中计算。要快速的解决这个问题最好的方案就是将数据搁内存了,所以现在的问题就在如何在2G内存空间以内存储着40亿整数。一个int整数在java中是占4个字节的即要32bit位,如果能够用一个bit位来标识一个int整数那么存储空间将大大减少,算一下40亿个int需要的内存空间为40亿/8/1024/1024大概为476.83 mb,这样的话我们完全可以将这40亿个int数放到内存中进行处理。

具体思路:

1个int占4字节即4*8=32位,那么我们只需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据,其中N代表要进行查找的总数,tmp中的每个元素在内存在占32位可以对应表示十进制数0~31,所以可得到BitMap表:

tmp[0]:可表示0~31

tmp[1]:可表示32~63

tmp[2]可表示64~95

那么接下来就看看十进制数如何转换为对应的bit位:

假设这40亿int数据为:6,3,8,32,36,…,那么具体的BitMap表示为:
在这里插入图片描述

如何判断int数字在tmp数组的哪个下标?
这个其实可以通过直接除以32取整数部分,例如:整数8除以32取整等于0,那么8就在tmp[0]上。

另外,我们如何知道了8在tmp[0]中的32个位中的哪个位?
这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8 mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。

步骤总结:
1.求十进制0-N对应在数组a中的下标: n/32

2.求0-N对应0-31中的数:N%32=M

3.利用移位0-31使得对应32bit位为1: 1<<M,并置1;

**应用场景2分析:**在3亿个整数中找出不重复的整数,限制内存不足以容纳3亿个整数。

对于这种场景我可以采用2-BitMap来解决,即为每个整数分配2bit,用不同的0、1组合来标识特殊意思,如00表示此整数没有出现过,01表示出现一次,11表示出现过多次,就可以找出重复的整数了,其需要的内存空间是正常BitMap的2倍,为:3亿*2/8/1024/1024=71.5MB。

具体的过程如下:

扫描着3亿个整数,组BitMap,先查看BitMap中的对应位置,如果00则变成01,是01则变成11,是11则保持不变,当将3亿个整数扫描完之后也就是说整个BitMap已经组装完毕。最后查看BitMap将对应位为11的整数输出即可。

(2)对没有重复元素的整数进行排序。

对于非重复的整数排序BitMap有着天然的优势,它只需要将给出的无重复整数扫描完毕,组装成为BitMap之后,那么直接遍历一遍Bit区域就可以达到排序效果了。

举个例子:对整数4、3、1、7、6进行排序

BitMap如下:
在这里插入图片描述
直接按Bit位输出就可以得到排序结果了。
BitMap的应用场景远远不止点,比如还可以用于压缩、爬虫系统中url去重、解决全组合问题。可能有些人觉得BitMap算法实现起来有点麻烦,其实某些语言是对BitMap算法进行了封装的,比如java中对应BitMap的数据结构就有BitSet类。

2.4 堆

堆是一种特殊的二叉树,具备以下两种性质:
1)每个节点的值都大于(或者都小于,称为最小堆)其子节点的值
2)树是完全平衡的,并且最后一层的树叶都在最左边这样就定义了一个最大堆。

2.5 trie树

Trie树,又叫字典树、前缀树(Prefix Tree)、单词查找树 或 键树,是一种多叉树结构。如下图:
在这里插入图片描述

适用范围:
前缀统计,词频统计。

具体说明如下:
第一:词频统计。
可能有人要说了,词频统计简单啊,一个hash或者一个堆就可以打完收工,但问题来了,如果内存有限呢?还能这么玩吗?所以这里我们就可以用trie树来压缩下空间,因为公共前缀都是用一个节点保存的。
第二: 前缀匹配
就拿上面的图来说吧,如果我想获取所有以"a"开头的字符串,从图中可以很明显的看到是:and,as,at,如果不用trie树,你该怎么做呢?很显然朴素的做法时间复杂度为O(N2) ,那么用Trie树就不一样了,它可以做到h,h为你检索单词的长度,可以说这是秒杀的效果。

参考学习:6天通吃树结构—— 第五天 Trie树

2.6 外排序

适用范围:
大数据的排序,去重

基本原理及要点:
外部排序的两个独立阶段:
1)首先按内存大小,将外存上含n个记录的文件分成若干长度L的子文件或段。依次读入内存并利用有效的内部排序对他们进行排序,并将排序后得到的有序字文件重新写入外存,通常称这些子文件为归并段
2)对这些归并段进行逐趟归并,使归并段逐渐由小到大,直至得到整个有序文件为之。

外排序的优化方法:置换选择 败者树原理,最优归并树

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值