问题:海量日志数据,提取出某日访问百度次数最多的那个IP
分析:百度作为国内第一大搜索引擎,每天访问它的IP数量巨大,如果想一次性把所有IP数据装进内存处理,则内存容量明显不够,故针对数据太大,内存受限的情况,可以把大文件转化成(取模映射)小文件,从而大而化小,逐个处理。
换言之,先映射,而后统计,最后排序。
解法:具体分为以下3个步骤
- 1.分而治之/hash映射
- 首先把这一天访问百度日志的所有IP提取出来,然后逐个写入到一个大文件中,接着采用映射的方法,比如%1000,把整个大文件映射为1000个小文件。
- 2.hash_map统计
- 当大文件转化成了小文件,那么我们便可以采用hash_map(ip, value)来分别对1000个小文件中的IP进行频率统计,再找出每个小文件中出现频率最大的IP。
- 3.堆/快速排序
- 统计出1000个频率最大的IP后,依据各自频率的大小进行排序(可采取堆排序),找出那个频率最大的IP,即为所求。
注:Hash取模是一种等价映射,不会存在同一个元素分散到不同小文件中去的情况,即这里采用的是%1000算法,那么同一个IP在hash后,只可能落在同一个文件中,不可能被分散的
总结:
(1)将ip地址放入多个小文件中,保证每种IP只出现在一个文件中
(2)利用hashmap统计每个小文件中IP出现的次数
(3)利用最小堆得到所有IP访问次数最多的100个
参考:
https://segmentfault.com/a/1190000019785430
https://www.kancloud.cn/kancloud/the-art-of-programming/41613
附加:使用shell统计出出现次数排名top10的网址
#!/bin/sh
foo()
{
if [ $# -ne 1 ];
then
echo "Usage:$0 filename";
exit -1
fi
egrep -o "http://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}" website | awk '{ count[$0]++ } END { printf("%-30s %s\n","wensite","count"); for(ind in count) { printf("%-30s %d\n",ind,count[ind]); } }' | sort -nrk 2 | head -n 10 >websorted2.txt;
}
foo website