基於Bloom-Filter演算法和記憶體資料庫的大量資料輕量級100%排重方案
阿新 • • 發佈:2018-11-16
總體模組:一次排重模組(基於布隆演算法) + 二次排重方案(基於記憶體資料庫)
一次排重
//雜湊函式,返回型別為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; }
===========================================================
二次排重
......到此,,經過兩次排重,記憶體資料庫裡的記錄不重不漏!