問題:海量日誌數據,提取出某日訪問百度次數最多的那個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