百度面試題:從海量日誌中提取訪問百度次數最多的IP

weixin_34116110發表於2017-10-30

題目:

每一個ip訪問百度,其ip地址都會被記錄到後臺日誌檔案中,假設一天的訪問日誌有100G,求出一天中訪問百度次數最多的ip地址,可以使用的記憶體大小是1G。

分析

首先解決大檔案問題,也就是如何處理100G的一個大檔案,這個通常的解決方法就是將大檔案分解成許多小檔案。我們可以通過對IP地址求hash然後對1024取模將一個100G的大檔案分解成1024個小檔案(file0,file1......file1023),注意這裡的1024個檔案並不是平均分的,也就是每個檔案大小並不是(100G/1204)。當然我們考慮的時候可以假設檔案是平均分的,那麼每個檔案大小為100M,這樣一個100M的檔案是可以全部讀入大小為1G記憶體中。這樣就解決了第一個檔案太大不能一次讀入記憶體的問題。

考慮到ip地址是32位,那麼總共有232=4G種可能出現的ip地址,每個ip地址出現的次數不確定,這個具體是由100G大檔案決定的。對每個小檔案進行處理,我們知道前面每個檔案中的ip是通過hash(ip)%1024。這樣相當於將232=4G種ip地址進行了分段,每個檔案中可能出現的ip最大範圍是4G/1024=4M,並且每個檔案之間的ip不會出現相同情況。

建立一個hashmap,讀取小檔案中的每個ip地址,判斷hashmap中是否有這個ip,如果沒有,這往haspmap中插入一個<ip,1>的鍵值對,即hashmap.put(ip,1);如果haspmap中已經存在了這個ip,那麼求出這個ip所對應的值count=haspmap.get(ip),然後往修改這個ip所對應的value,使其數量增加1,即hashmap.set(ip,count+1)。

當我們求出每個檔案中出現次數最大的ip地址以後,我們在比較這1024個檔案中的那個ip出現次數最大。


hash(IP)%N get many small files

int max = 0;
String maxip = null;
for each file
    Hashmap hashmap;
      for each IP in file10       if(hashmap.has(IP)) {
          int cnt = hashmap.get(IP);
          hashmap.set(IP, cnt+1);
          if(cnt+1 > max) { 
              max = cnt+1;
              maxip = IP;
          }
      }
      else hashmap.put(IP, 1);

相關文章