1. 程式人生 > >基於Bloom-Filter演算法和記憶體資料庫的大量資料輕量級100%排重方案

基於Bloom-Filter演算法和記憶體資料庫的大量資料輕量級100%排重方案

總體模組:一次排重模組(基於布隆演算法) + 二次排重方案(基於記憶體資料庫)

一次排重


//雜湊函式,返回型別為int型
//int型數的總數量[4294967296] (範圍大約在正負21億)
//int型別4個位元組,32bits
//排重標誌陣列的總長度[4294967296/(4*8)=134217728]
//陣列過長,編譯器編譯錯誤
//拆分成二維陣列
//綜合考慮空間佔用和雜湊衝突,選擇兩個排重標誌二維陣列
//每個陣列佔用512MB記憶體空間
//支援多執行緒共享
static unsigned int distinctFlgArr1[16][134217728/16];
static unsigned int distinctFlgArr2[16][134217728/16];

//雜湊函式
static int hashCode1(std::string &str);  //雜湊計算1
static int hashCode2(std::string &str);  //雜湊計算2
static int hashCode3(std::string &str);  //雜湊計算3
static int hashCode4(std::string &str);  //雜湊計算4

//引數1:loc即為雜湊結果+2147483648
//引數2:mode標識查詢哪個排重陣列(1或2)
//引數3:引用傳遞指標,返回要位操作的排重陣列元素的地址
//返回值:位操作(位與、位或)需要的引數,該值通過移位操作產生
static unsigned int getFlgInfo(unsigned  int loc,int mode,unsigned int* &pFlgVal);
static int getBit(unsigned int* pFlgVal, unsigned int bitOptionVal);    //位操作-判斷某一位是否為1
static void setBit(unsigned int* pFlgVal, unsigned int bitOptionVal);   //位操作-置某一位為1

//一次排重函式
bool judgeDistinct(std::string &str);

//雜湊函式定義
int hashCode1(std::string &str){
    int h=0;
    if(str.length()>0){
        for(int i=0;i<str.length();++i){
            h=31*h+str.at(i);
        }
    }
    return h;
}
int hashCode2(std::string &str){
    int h=0;
    if(str.length()>0){
        int mode=str.length()>=10?str.length()/5:2;
        int num=0;
        for(int i=str.length()-1;i>=0;--i){
            if((i+1)%mode==0){
                ++num;
                if(num%2==0){  //跳過此位的雜湊
                    continue;
                }else{        //增加一位雜湊,雜湊字元ASCII碼值固定為31
                    h=31*h+31;
                }
            }
            h=31*h+str.at(i);
        }
    }
    return h;
}
int hashCode3(std::string &str) {
    int h=0;
    if(str.length()>0){
        int mode=str.length()>=10?str.length()/5:2;
        int num=0;
        for(int i=0;i<str.length();++i){
            if((i+1)%mode==0){
                ++num;
                if(num%2==0){  //跳過此位的雜湊
                    continue;
                }else{        //增加一位雜湊,雜湊字元ASCII碼值固定為31
                    h=31*h+31;
                }
            }
            h=31*h+str.at(i);
        }
    }
    return h;
}
int hashCode4(std::string &str) {
    int h=0;
    if(str.length()>0){
        int mode=str.length()>=10?str.length()/5:2;
        for(int i=0;i<str.length();++i){
            if(i%2==0){
                h=31*h+(str.at(i)+str.at(str.length()-1-i));
            }else{
                h=31*h+(str.at(i)-str.at(str.length()-1-i));
            }
        }
    }
    return h;
}

//得到陣列元素指標 和 位操作引數
//指標引用傳遞
unsigned int getFlgInfo(unsigned  int loc,int mode,unsigned int* &pFlgVal){
    unsigned int absSeq = loc / 32;                         //在一維陣列的絕對順序(第幾個元素)
    unsigned int relBit = loc % 32;                         //在這個元素第幾位(bit)
    unsigned int absSeqX = absSeq / 8388608;                //在二維陣列的絕對位置(X,Y)
    unsigned int absSeqY = absSeq % 8388608;
    unsigned int baseVal = (unsigned int)2147483648;        //10000000 00000000 00000000 00000000
    unsigned int bitOptionVal = baseVal >> relBit;

    if(mode==1){
        pFlgVal=&distinctFlgArr1[absSeqX][absSeqY];
    }
    if(mode==2){
        pFlgVal=&distinctFlgArr2[absSeqX][absSeqY];
    }
    return bitOptionVal;
}

//查詢是否置位
int getBit(unsigned int* pFlgVal, unsigned int bitOptionVal){
    if((*pFlgVal & bitOptionVal) > 0){
        return 1;  //已經置位
    }else{
        return 0;  //沒有置位
    }
}

//置位
void setBit(unsigned int* pFlgVal, unsigned int bitOptionVal) {
    *pFlgVal |= bitOptionVal;  //置位
}

//一次排重函式
bool judgeDistinct(std::string &str){
    bool rst=false;   //預設不重複
    unsigned int hashLoc1=hashCode1(str)+2147483648;
    unsigned int hashLoc2=hashCode2(str)+2147483648;
    unsigned int hashLoc3=hashCode3(str)+2147483648;
    unsigned int hashLoc4=hashCode4(str)+2147483648;
    unsigned int* pFlgVal1=NULL;
    unsigned int bitOptionVal1=0;
    unsigned int* pFlgVal2=NULL;
    unsigned int bitOptionVal2=0;
    unsigned int* pFlgVal3=NULL;
    unsigned int bitOptionVal3=0;
    unsigned int* pFlgVal4=NULL;
    unsigned int bitOptionVal4=0;
    bitOptionVal1=getFlgInfo(hashLoc1,1,pFlgVal1);
    bitOptionVal2=getFlgInfo(hashLoc2,2,pFlgVal2);
    bitOptionVal3=getFlgInfo(hashLoc3,2,pFlgVal3);
    bitOptionVal4=getFlgInfo(hashLoc4,1,pFlgVal4);

    //pthread_mutex_lock(&mutex);  //加互斥鎖
    if(getBit(pFlgVal1,bitOptionVal1)==1){
        if(getBit(pFlgVal2,bitOptionVal2)==1){
            if(getBit(pFlgVal3,bitOptionVal3)==1){
                if(getBit(pFlgVal4,bitOptionVal4)==1){
                    rst=true;  //重複
                }else{
                    setBit(pFlgVal4,bitOptionVal4);
                }
            }else{
                setBit(pFlgVal3,bitOptionVal3);
                setBit(pFlgVal4,bitOptionVal4);
            }
        }else{
            setBit(pFlgVal2,bitOptionVal2);
            setBit(pFlgVal3,bitOptionVal3);
            setBit(pFlgVal4,bitOptionVal4);
        }
    }else{
        setBit(pFlgVal1,bitOptionVal1);
        setBit(pFlgVal2,bitOptionVal2);
        setBit(pFlgVal3,bitOptionVal3);
        setBit(pFlgVal4,bitOptionVal4);
    }
    //pthread_mutex_unlock(&mutex);  //釋放互斥鎖

    return rst;
}

===========================================================

二次排重


......到此,,經過兩次排重,記憶體資料庫裡的記錄不重不漏!