使用python bloomfilter实现大文本去重

需求:项目中在收集数据的时候,遇到日志中存在大量的重复记录,数据在入库之前需要先对日志文件做一个处理,滤掉重复的事件

bloomfilter原理参考文章:python BloomFilter(布隆过滤器)

项目环境:python3.7
需要安装的模块包:pybloom-live-3.0.0
下载pybloom_live-3.0.0.tar.gz后,直接执行pip install pybloom_live-3.0.0.tar.gz即可安装,安装过程中,如果提示缺少其他依赖包,下载安装即可。

项目逻辑
1.原始日志数据实时写入文件,每小时生成一个日志文件,文件名为"月日小时.log",如 “042401.log”(时间和系统时间相差8小时),原始日志文件路径:/data/logs
2.每小时处理前一小时的原始日志文件,将去重后的日志保存在目标路径下,如"/data/dblog/042101.log"
3.考虑到服务器硬盘空间,需要删除历史数据和处理后的数据文件,服务器中只保留最近24小时的数据

实现代码

# -*- coding: utf-8 -*-

from pybloom_live import BloomFilter
import os
import hashlib
import time
import datetime

#去重
class BloomCheckFunction(object):
    def __init__(self):
        self.filename = 'bloomFilter.blm'
        is_exist = os.path.exists(self.filename) #判断文件是否存在
        if is_exist:
            self.bf = BloomFilter.fromfile(open(self.filename, 'rb')) #存在直接打开 储存在内存中
        else:
            self.bf = BloomFilter(100000000, 0.001) #新建一个 储存在内存中

    def process_item(self, data):
        data_encode_md5 = hashlib.md5(data.encode(encoding='utf-8')).hexdigest()
        if data_encode_md5 in self.bf:
            # 内容没有更新 丢弃item return False
            return False

        else:
            self.bf.add(data_encode_md5)
            #内容不存在,新来的 return True
            return True

    def save_bloom_file(self):
        self.bf.tofile(open(self.filename, 'wb'))


#获取文件时间
def get_filename():
    h=datetime.datetime.now()-datetime.timedelta(hours=9)
    filename=h.strftime('%m%d%H')+".log"
    logname="process_"+h.strftime('%m%d')+".log"
    return filename,logname

#删除历史文件
def delFile():
    h=datetime.datetime.now()-datetime.timedelta(hours=33)#可根据硬盘空间大小,确定需要保留多久的数据,这里保留最近24小时的日志文件
    del_srcfile="/data/logs/"+h.strftime('%m%d%H')+".log"
    del_dbfile="/data/dblog/"+h.strftime('%m%d%H')+".log"
    #print(del_srcfile)
    if os.path.exists(del_dbfile):
        os.remove(del_dbfile)
        if os.path.exists(del_srcfile):
            os.remove(del_srcfile)
    
def process_data(srcfile,dstfile):
    bf = BloomCheckFunction()#对象初始化 只需要初始化一遍
    with open(dstfile,'w') as fout:        
        with open(srcfile,'r') as fin:
            for line in fin:
                if bf.process_item(line):
                    fout.write(line)
                else:
                    pass


if __name__=="__main__":
    start_time=time.time()
    filename,logname=get_filename()
    srcfile="/data/logs/"+filename
    dstfile="/data/dblog/"+filename
    if os.path.exists(srcfile):
        try:
            delFile()
            process_data(srcfile,dstfile)
            spend_time=time.time()-start_time
            with open(logname,"a+") as fin:
                fin.write("file "+srcfile+" process success , spend times: %.3f s\n" % spend_time)
        except:
            with open(logname,"a+") as fin:
                fin.write("file "+srcfile+" process failed")
    else:
        with open(logname,"a+") as fin:
                fin.write("file "+srcfile+" not exist !!!")


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jepson2017

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值