千万数据去重_基于 Flink 的百亿数据去重实践

本文探讨了在大数据场景下如何处理数据重复问题,重点讲述了使用 Flink 实现百亿数据去重的策略。针对 Kafka 中可能出现的数据重复,提出通过全局 set 集合、BloomFilter 以及 HBase 维护去重集的方法,并分析了各自优缺点。BloomFilter 提供低成本去重但存在误判率,HBase 方案则面临一致性挑战。最后,文章提到了使用 Flink 内置 KeyedState 实现去重的可能性。
摘要由CSDN通过智能技术生成

在工作中经常会遇到去重的场景,例如基于 App 的用户行为日志分析系统,用户的行为日志从手机客户端上报到 Nginx 服务端,通过 Logstash、Flume 或其他工具将日志从 Nginx 写入到 Kafka 中。

由于用户手机客户端的网络可能出现不稳定,所以手机客户端上传日志的策略是:宁可重复上报,也不能丢日志。所以导致 Kafka 中必然会出现日志重复的情况,即:同一条日志出现了 2 条或 2 条以上。

通常情况下,Flink 任务的数据源都是 Kafka,若 Kafka 中数据出现了重复,在实时 ETL 或者流计算时都需要考虑对日志主键进行去重,否则会导致流计算结果偏高或结果不准确的问题,例如用户 a 在某个页面只点击了一次,但由于日志重复上报,所以用户 a 在该页面的点击日志在 Kafka 中出现了 2 次,最后统计该页面的 click 数时,结果就会偏高。

这里只阐述了一种可能造成 Kafka 中数据重复的情况,在生产环境中很多情况都可能造成 Kafka 中数据重复,这里不一一列举,本节主要讲述出现了数据重复后,该如何处理。

实现去重的通用解决方案

Kafka 中数据出现重复后,各种解决方案都比较类似,一般需要一个全局 set 集合来维护历史所有数据的主键。当处理新日志时,需要拿到当前日志的主键与历史数据的 set 集合按照规则进行比较,若 set 集合中已经包含了当前日志的主键,说明当前日志在之前已经被处理过了,则当前日志应该被过滤掉,否则认为当前日志不应该被过滤应该被处理,而且处理完成后需要将新日志的主键加入到 set 集合中,set 集合永远存放着所有已经被处理过的数据。程序流程图如下图所示:

image

处理流程很简单,关键在于如何维护这个 set 集合,可以简单估算一下这个 set 集合需要占用多大空间。本小节要解决的问题是百亿数据去重,所以就按照每天 1 百亿的数据量来计算。

由于每天数据量巨大,因此主键占用空间通常会比较大,如果主键占用空间小意味着表示的数据范围就比较小,就可能导致主键冲突,例如:4 个字节的 int 类型表示数据范围是为 -2147483648~2147483647,总共可以表示 42 亿个数,如果这里每天百亿的数据量选用 int 类型做为主键的话,很明显会有大量的主键发生冲突,会将不重复的数据认为是发生了重复。

用户的行为日志是在手机客户端生成的,没有全局发号器,一般会选取 UUID 做为日志的主键,UUID 会生成 36 位的字符串,例如:"f106c4a1-4c6f-41c1-9d30-bbb2b271284a"。每个主键占用 36 字节,每天 1 百亿数据,36 字节 * 100亿 ≈ 360GB。这仅仅是一天的数据量,所以该 set 集合要想存储空间不发生持续地爆炸式增长,必须增加一个功能,那就是给所有的主键增加 ttl(Time To Live的缩写,即:过期时间)。

如果不增加 ttl,10 天数据量的主键占用空间就 3.6T,100 天数据量的主键占用空间 36T,所以在设计之初必须考虑为主键设定 ttl。如果要求按天进行去重或者认为日志发生重复上报的时间间隔不可能大于 24 小时,那么为了系统的可靠性 ttl 可以设置为 36 小时。每天数据量 1 百亿,且 set 集合中存放着 36 小时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值