海量数据处理:是针对数据量较大,导致内存不足或十分占内存的情况而有的解决算法
1 给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
【问题分析】
(1)日志文件一般为一行一条日志,并且有一定的格式,每一条日志中含一个IP地址,
我们可以看一下这个笔记的日志信息,简单有一个认识:
(2)日志文件共100G,占用内存过大,可以尝试对100G的文件进行切分,对一个个小文件中的IP地址进行次数统计,这样可以把内存的压力减小;
(3)如果只是简单的进行切分,存在一个问题:如果一个IP地址在每个小文件中都均匀出现,这样在每个文件中计算该IP地址出现的次数都不算是较多的,但实际上其出现次数较高,这样统计显然不太准确;
(4)换一种切分方式:哈希切分
【解题思路】:
(1)采用哈希切分成1000份:
HashFunc(ip) % 1000
(2)建立KV模型的哈希表,并统计次数
HashTable<ip.count> counttable;
读取file0, file1, ... ,file999 每个文件的内容
counttable[ip]++;//统计每个IP的次数
(3)借助堆/STL--优先级队列(建小堆),找出出现次数最多的IP地址。
【注】相同的借助堆,也就可以找到出现次数最多的前K个IP地址(即TopK问题)
2 给定100亿个整数,设计算法找到只出现一次的整数
1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
【解题思路】:
(1)100亿个整数,共占用内存40G,内存过大;
(2)如果使用位图,则只需要占用500M(一共只有42亿9千万的整数),但位图只能表明该整数“在”、“不在”两种状态;
(3)需要能够表示“不在”、“出现一次”、“出现两次”、“出现多次”四种状态;
(4)扩展位图,用两个比特位表示一个整数,即:00(不存在),01(出现一次),10(出现两次),11(出现多次)
【注】:还有一种方法,同样采用哈希切分,将对文件中100亿个整数进行哈希切分,借助KV模型的哈希表,统计整数出现的次数,找到只出现一次的整数
位图扩展实现:
voidSet(constsize_t&x)
{
size_tn =x/ 16;//n表示x在第几个整型上
size_t
pos = (
x
% 16) * 2;
//pos表示x在第几个位上(低位)
if
(Test(
x
) == 0)
//没有x,set后置01
{
_bsonce[n] |= (1 << pos);
//将第n个位置的pos位置1
}
else
if
(Test(
x
) == 1)
//x出现过一次,set后置为10(出现2次)
{
_bsonce[n] &= (~(1 << pos));
//将第n个位置的pos位 置0
_bsonce[n] |= (1 << (pos + 1));
//将第n个位置的pos+1位 置1
}
else
if
(Test(
x
) == 2)
//x出现过2次,set后置为11(出现多次)
{
_bsonce[n] |= (1 << pos);
//将pos位置1
}
}
size_tTest(constsize_t&x)
{
size_t
n =
x
/ 16;
//n表示x在第几个整型上
size_t
pos = (
x
% 16) * 2;
//pos表示x在第几个位上
//第pos位和pos+1位都为0,表示x不存在
if
(((_bsonce[n] & (1 << pos)) == 0 )
&& ((_bsonce[n] & (1 << (pos + 1))) == 0))
return
0;
//只出现一次:pos位是1,pos+1位是0
else
if
(((_bsonce[n] & (1 << pos)) != 0)
&& ((_bsonce[n] & (1 << (pos + 1))) == 0))
return
1;
//出现2次
else
if
(((_bsonce[n] & (1 << pos)) == 0)
&& ((_bsonce[n] & (1 << (pos + 1))) != 0))
return
2;
else
return
-1;
}
3 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确
算法和近似算法?
【解题思路】:
精确算法:(1)100亿个query,假设平均一个query占30个字符,共需要内存2 * 300G = 600G;
(2)采用哈希切分,对两个文件分别进行切分,每个文件切分成1000份,切分后共需要2 * 300M = 600M;
(3)对Afile0文件中的每个query都在Bfile0,...Bfile999中找,如果找到了就是交集;
(4)采用上述方法对Afile1,...,Afile999进行。
近似算法:(1)100亿个query,假设平均一个query占30个字符,共需要内存2 * 300G = 600G;
(2)对两个文件中的query分别放入两个布隆过滤器中,共需要内存2 * 500M = 1G;
(3)对两个BloomFilter进行按位与运算,表示结果的BloomFilter进行这两个文件的交集。
【注】:两个文件的并集:按位或
两个文件的差集:按位异或
4
给上千个文件,每个文件大小为1K—100M。给n个词,设计算法对每个词找到所有包含它的文
件,你只有100K内存
有一个词典,包含N个英文单词,现在任意给一个字符串,设计算法找出包含这个字符串的所
有英文单词
【解题思路】:
对于这个问题还得要用到布隆过滤器来进行操作,有上千份文件就要有上千个布隆过滤器,并将这上千个布隆过滤器存到一个文件中去。将内存分为两部分,一部分用来进行读取一个布隆过滤器,还有一部分用来读取文件。对每个读进去的单词判断是否包含这个单词。如果不包含就读取下一个文件,如果包含的话就把这个词和这个词对应的文件信息存到一个专门的文件中去。直到所有的词已经读完。
5 “倒排索引”