基于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;
}

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

二次排重


......到此,,经过两次排重,内存数据库里的记录不重不漏!



猜你喜欢

转载自blog.csdn.net/qq_24243483/article/details/79638565