Bloom Filter算法优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_1290259791/article/details/82422707

Bloom Filter算法优化

  1. 基于Redis的Bloom Filter去重,利用Redis的String数据结构,但Redis的String最大只能512M,所以数据过大的时候,需要申请多个去重块。
  2. Bloom Filter对一个很长的字符串进行哈希映射时会出错,常误判为已经存在,所以我们进行一次压缩(MD5\Sha1)。
  3. 将去重队列和种子队列拆分到不同的机器上。

种子seed数量越少去重速度越快,但是漏失率越大。

Md5长度为128bit,SHA-1长度160bit。

from redis import StrictRedis
from hashlib import md5


class HashMap(object):

    def __init__(self, m, seed):
        self.m = m
        self.seed = seed

    def hash(self, value):
        ret = 0
        for i in range(len(value)):
            ret += self.seed * ret + ord(value[i])
        return (self.m - 1) & ret


class BloomFilter(object):

    def __init__(self, server, key, blockNum=1, bit=30, hash_number=6):
        self.m = 1 << bit
        self.seeds = range(hash_number)     # 种子
        self.blockNum = blockNum    # 去重块的数量
        self.maps = [HashMap(self.m, seed) for seed in self.seeds]  # 多个哈希函数
        self.server = server    # Redis连接对象
        self.key = key  # 键名

    def exists(self, value):
        if not value:
            return False
        m5 = md5()
        m5.update(value.encode())
        value_md5 = m5.hexdigest()  # 将value进行md5加密
        ret = True
        key_name = self.key + \
            str(int(value_md5[0:2], 16) % self.blockNum)  # 存储的block位置
        for map in self.maps:
            offset = map.hash(value_md5)  # hash md5加密后的数据
            ret = ret & self.server.getbit(
                key_name, offset)  # 修改每次hash过后,指定block块的位置
        return ret

    def insert(self, value):
        m5 = md5()
        m5.update(value.encode())
        value_md5 = m5.hexdigest()  # 将vlaue进行md5加密
        key_name = self.key + \
            str(int(value_md5[0:2], 16) % self.blockNum)  # 存储的block位置
        for map in self.maps:
            offset = map.hash(value_md5)  # hash md5加密后的数据
            self.server.setbit(key_name, offset, 1)

redis = StrictRedis(host='localhost', port=6379)
bf = BloomFilter(redis, 'hash_map', 3, 10, 1)
# bf.insert('asd')
print(bf.exists('asd'))
# bf.insert('Hellow')
# bf.insert('World')

猜你喜欢

转载自blog.csdn.net/qq_1290259791/article/details/82422707