OpenRTMFP/Cumulus開發筆記(6) Cumulus大資料處理執行個體

來源:互聯網
上載者:User

一.問題描述:海量日誌資料,提取出某日訪問網頁YY,http://yy.com/次數最多的那個IP,如下:

,可以在右下角輸入一個頻道號,如2080進入相關頻道。

二.問題類比:

1.產生海量IP,並把這些IP儲存在一個檔案中,如下:

void ConstructBigData::constructIps(std::string fileName){
    std::ofstream outfile(fileName.c_str(), std::ios::out);
    std::stringstream ip("");
    unsigned short num = 0;
    srand((unsigned) time(NULL));
    for (int i = 0; i < 9000000; ++i) {
        for (int j = 0; j < 4; ++j) {
            num = (rand() % 256);//產生IPv4地址
            ip << num;
            if (j < 3)
                ip << '.';
            else
                ip << '\n';
        }
        outfile << ip.str();
        ip.str("");
        outfile.flush();
    }
    outfile.close();
}

說明:這裡產生了9000000個IP,也許離海量還有點距離,但是海量是相對的,處理方法是相通的,需要根據具體情況具體產生,這裡考慮的是一般情況。fileName即我們儲存IP的檔案名稱。

2.這9000000個IP可以一次性裝入記憶體,進行相關計算統計,但是我們講的是這類問題的處理方法,比如一次性沒法裝載時,就可以這樣處理。這裡可以把這些IP讀出來,根據模數把它們劃分成幾個更小的檔案,前提是要保證相同的IP被劃分在相同的小檔案中,如下:

void ConstructBigData::filePartition(std::string fileName){
    std::ifstream infile(fileName.c_str(),std::ios::in);
    std::ofstream outfile0("outfile0.txt",std::ios::out);
    std::ofstream outfile1("outfile1.txt",std::ios::out);
    std::ofstream outfile2("outfile2.txt",std::ios::out);
    std::ofstream outfile3("outfile3.txt",std::ios::out);
    std::ofstream outfile4("outfile4.txt",std::ios::out);
    if(!infile){
        return;
    }
    unsigned short val1,val2,val3,val4;
    unsigned char ch1,ch2,ch3;
    unsigned long ipval = 0;
    int modval = 0;
    std::stringstream ss;
    std::string buffer;
    std::stringstream ssbuf("");
    while (!infile.eof()) {
        getline(infile,buffer);
        ssbuf<<buffer;
        if(!infile.eof()){
            ssbuf >> val1 >> ch1 >> val2 >> ch2 >> val3 >> ch3 >> val4;
            ipval = (((((val1<<8) + val2)<<8)+val3)<<8)+val4;
            modval = ipval % 5;
            switch(modval){
            case 0:
                outfile0 << ssbuf.str() << '\n';
                break;
            case 1:
                outfile1 << ssbuf.str() << '\n';
                break;
            case 2:
                outfile2 << ssbuf.str() << '\n';
                break;
            case 3:
                outfile3 << ssbuf.str() << '\n';
                break;
            case 4:
                outfile4 << ssbuf.str() << '\n';
                break;
            default:
                std::cout<<"sb"<<std::endl;
                break;
            }
            ipval = 0;
        }
        ssbuf.clear();
        ssbuf.str("");
    }
    outfile0.flush();
    outfile1.flush();
    outfile2.flush();
    outfile3.flush();
    outfile4.flush();

    outfile0.close();
    outfile1.close();
    outfile2.close();
    outfile3.close();
    outfile4.close();
    infile.close();
}

說明:這裡取值為mod5,也只是僅僅樣本而已,需要根據具體情況具體處理,這裡講的是一般方法。

3.依次讀取每個檔案,取出每個檔案訪問次數最多的那個IP,再比較這些IP中的最大值即可,這裡可以使用暴雪的雜湊演算法,因為雜湊演算法是最快的hash演算法,如下:

void ConstructBigData::findMax(){
    int fileNum = 5;
    std::stringstream ss("");
    for(int i=0;i<fileNum;++i){
        std::string fileName = "outfile";
        std::string suffix = ".txt";
        ss<<fileName<<i<<suffix;
        std::ifstream infile(ss.str().c_str(),std::ios::in);
        std::string buffer;
        while (!infile.eof()) {
                getline(infile,buffer);
                if(!infile.eof()){
                    mpq.SetHashTable(buffer);//雜湊,其中mpq是暴雪hash演算法實現的一個執行個體。
                }
        }
        infile.close();
        printf("from %s->",ss.str().c_str());
        Max();
        ss.clear();
        ss.str("");
    }
}

void ConstructBigData::Max(){//尋找每個檔案中的訪問最多的IP的值
    int index = 0;
    for (int i = 0; i < hashMpqLen; ++i) {
        if (mpq.m_HashIndexTable[i].bExists) {
            if(mpq.m_HashIndexTable[i].count > mpq.m_HashIndexTable[index].count){
                index = i;
            }
        }
    }
    if(mpq.m_HashIndexTable[index].bExists){
        printf("%s,%d\n",mpq.m_HashIndexTable[index].test_filename,mpq.m_HashIndexTable[index].count);
    }
    mpq.reset(hashMpqLen);//重設hash結構
}

三.暴雪hash演算法實現的執行個體講解,如下:

1.定義hash表資料結構,如下:

typedef   struct
{
    long  nHashA;//用於hash演算法
    long  nHashB;//用於hash演算法
    bool  bExists;//用於hash演算法
    char  test_filename[MAXFILENAME];//儲存IP地址
    int count;//用於儲存訪問的次數
} MPQHASHTABLE;

2.hash表的初始化以及重設,如下:

void HashMpq::reset(const long nTableLength) {//nTableLength為hash表的長度
    for (int i = 0; i < nTableLength; i++) {
        m_HashIndexTable[i].nHashA = -1;
        m_HashIndexTable[i].nHashB = -1;
        m_HashIndexTable[i].bExists = false;
        m_HashIndexTable[i].test_filename[0] = '\0';
        m_HashIndexTable[i].count = 0;
    }
}

3.對IP地址進行hash,如下:

bool HashMpq::SetHashTable(std::string lpszString )
{
    const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
    unsigned long nHash = HashString(lpszString, HASH_OFFSET);
    unsigned long nHashA = HashString(lpszString, HASH_A);
    unsigned long nHashB = HashString(lpszString, HASH_B);
    unsigned long nHashStart = nHash % m_tablelength, nHashPos = nHashStart;
    while (m_HashIndexTable[nHashPos].bExists) {

        /*

        TODO,判斷該IP地址是否已經存在,存在的話,只需在原來的基礎上加1即可,這裡略去

        */
        nHashPos = (nHashPos + 1) % m_tablelength;//處理衝突的方法,即順延
        if (nHashPos == nHashStart) {
            return false;
        }
    }

  //否則表示該IP在hash表中還木有。

    m_HashIndexTable[nHashPos].bExists = true;
    m_HashIndexTable[nHashPos].nHashA = nHashA;
    m_HashIndexTable[nHashPos].nHashB = nHashB;
    strcpy( m_HashIndexTable[nHashPos].test_filename, lpszString.c_str());//表示該IP地址
    m_HashIndexTable[nHashPos].count = 1;//表示第一次訪問,所以設定count為1
    return true;
}

四.main函數,如下:

#include "ConstructBigData.h"
#include <iostream>
#include <stdio.h>
int main(int argc,char** argv){
    ConstructBigData bd(10000000);//參數表示hash表的長度
    std::string fileName = "bigdata.txt";//表示儲存的海量IP的檔案名稱
    bd.constructIps(fileName);//構造海量IP
    bd.filePartition(fileName);//partition
    bd.findMax();//尋找每個partition中的最大值
    return 0;
}

未完待續~


PS:初寫文章,文筆生澀之處,各位請見諒,若有疑問或者交流的,可加本人YY號:301558660

轉載請註明出處:山水間部落格,http://blog.csdn.net/linyanwen99/article/details/8182814


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.