所谓海量数据处理,就是基于海量数据上的存储、处理、操作。何谓海量,要么就是数据量太大导致无法在短时间内迅速解决。要么就是数据太大,导致无法一次性装入内存。
针对时间,我们可以采用恰当的算法搭配合适的数据结构,例如Bloom filter、Hash、bit-map、堆、数据库索引等。
针对空间,我们可以采用分治的思想,将大规模问题化为小规模问题,各个击破。
针对单机资源受限问题,可以考虑集群。
1、分治/hash映射+hashmap统计+堆/快速/归并排序
2.、桶划分
3.、Bloom filter/Bitmap
4、trie树、数据库索引
5、外排序
6、分布式处理hadoop/Mapreduce
海量数据(有重复),统计重复次数最多的一个?
海量日志数据,提取出某日访问百度次数最多的那个IP。
方案一:hash映射+hashmap统计
1、首先从日志文件中将这一天访问百度的所有IP取出来放入另一个大文件中。
2、分而治之/hash映射:IP是32位的,最多2^32个IP,我们可以通过哈希函数(IP%1024)将大文件映射为1024个小文件。
3、hashmap统计:对每一个小文件,我们直接在内存中通过hashmap统计IP的频率,并保存出现频率最高IP。
4、最后从这1024个频率最高IP中找到全局频率最高的那个IP。
海量数据(有重复),统计其中出现次数最多的前K个数据。
搜索引擎会通过日志文件把用户每次检索使用的检索串记录下来,每个检索串的长度为1-255字节。假设目前有一千万个记录(重复率较高,去重后不超过300万个),请你统计最热门的10个检索串,要求使用的内存不超过1G。
有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
海量数据分布在100台电脑中,想个办法高效统计出这批数据的TOP10。
方案一:hashmap统计/trie+堆
由于3M*1K/4=0.75G,因此所有的字符串可以在1G内存中处理。
1、hashmap统计/trie:维护一个key为检索串,value为其出现次数的hashmap。在O(n)时间复杂度内对所有检索串进行统计。
2、堆:针对典型的Top K的问题,我们借助堆这个数据结构。维护一个大小为K的小顶堆,然后遍历hashmap中所有的元素并与堆顶元素比较,最后统计出Top K。最终时间复杂度为O(n)+O(n*log K)
方案二:hash映射+hashmap统计/trie+堆+外排序
如果内存不够,可以先进行hash映射。
1、分而治之/hash映射:顺序读取文件,对每个词通过哈希函数(hash(x)%5000),将词划分到5000个小文件中,这样每个文件大小大概是200k,如果有文件超过1M大小,仍然可以继续划分。
2、hashmap统计/trie:对每个小文件,利用hashmap/trie等统计每个文件中词的频率。
3、堆:统计完频率后将频率最大的100个词及其频率存入文件(这里可以利用最小堆)。
4、外排序:对上一步得到的5000个文件进行外排序(类似归并排序),最后取出前100个。
方案三:hash统计+堆+堆
1、hashmap统计:每台电脑上通过hashmap统计出数据的频率。
2、堆:利用小顶堆求得每个电脑上数据频率的Top K。
3、堆:将100台电脑上的所有Top 10组合起来,利用小顶堆统计最终的Top 10。
有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。
方案一:hash映射+hashmap统计/trie+快速/归并排序+外排序
1、分而治之/hash映射:顺序读取10个文件,按照哈希函数(hash(query)%10)的结果将query写入到另外10个文件中。
2、hashmap统计/trie:对每个文件利用hashmap统计query出现的频度。
3、快速/归并排序:利用排序算法对query的频度结果进行排序并输出到另外的文件中。
3、外排序:对上一步生成的10个文件进行归并排序。
给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?如果是多个文件呢?
方案一:hash映射+hashmap统计
方案二:Bloom filer
1000万字符串,其中有些是重复的,需要把重复的全部去掉,保留没有重复的字符串。请怎么设计和实现?方案一:hash映射+hashmap统计+外排序
2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。
方案一:hash映射+hashmap统计
方案二:hash映射+bitmap
方案三:Bloom filter
5亿个int找它们的中位数。
方案一:桶划分
给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
方案一:Bloom filter
方案二:bitmap