0


Flink实战之基于Flink SQL 实现长周期数据去重: 分层去重方案介绍

    在大数据处理中,如何高效去重数据,尤其是面对长周期流数据时,是一个值得深入探讨的问题。Flink SQL 作为流处理的强大工具,提供了灵活的查询和变换能力,尤其是在数据去重场景中,可以采用分层去重方案以提高性能和准确性。本文将通过一段基于 Flink SQL 的去重实现代码,详细介绍如何设计并实现一个适用于长周期数据的分层去重方案。
1. 背景与挑战
    在实时数据处理中,数据去重是常见的需求之一。尤其是在长周期数据流的场景中,如金融交易、实时日志监控等,如何在确保低延迟的同时,正确去除重复数据,避免数据冗余和错误统计,是一个技术挑战。

    传统的去重方法往往依赖于状态管理,如在内存中保持一份已经处理过的数据记录,然后基于时间戳或事件时间进行去重。然而,对于长周期数据,数据量庞大,流量高,且去重操作需要处理的数据时间跨度较长,这就要求我们采用更高效的去重策略。
2. Flink SQL 中的分层去重方案
    Flink SQL 提供了强大的窗口、聚合、时间语义等功能,使得去重操作不仅能在流中执行,还能在状态的管理上灵活应用。分层去重方案,顾名思义,就是通过多个阶段、多个层级的去重逻辑,来实现对数据的高效去重。

在该方案中,我们采用了两层去重机制:

  1. 第一层去重:通过 Flink 的流处理状态结合 row_number() 函数,在流数据内部有效状态范围内进行去重。
  2. 第二层去重:通过外存进行去重,利用 HBase 作为外部数据存储,确保历史数据不会被重复处理,同时可以保证海量数据高效去重。
3. 代码详解
3.1 创建数据源表
create temporary table tbl_data_source(
    word     string,
    proctime as proctime()
) with (
    'connector' = 'datagen',
    'rows-per-second' = '100',
    'fields.word.length' = '2'
);
    首先,我们创建了一个名为 
tbl_data_source

的临时表,它通过

datagen

连接器生成模拟的数据流。此数据流每秒产生 100 行数据,字段

word

的长度为 2 个字符(最多有256种枚举,因此去重结果最多256行数据)。这部分数据模拟的是一个实时流数据源。

3.2 创建 HBase 辅助去重维表
create table dim_hbase_data_source(
    word string,
    cf   row(status string)
) with (
    'connector' = 'hbase-2.2',
    'table-name' = 'dim_hbase_data_source',
    'zookeeper.quorum' = 'localhost:2181'
);
    我们通过 HBase 作为外存来存储历史数据状态。HBase 用作辅助去重的维度存储表 
dim_hbase_data_source

。这里存储了

word

字段和

status

状态字段,用于在第二层去重时过滤已处理的数据。

3.3 创建中间结果临时表
create table tmp_result(
    word     string,
    proctime as proctime()
) with (
    'connector' = 'kafka',
    'topic' = 'tmp_result',
    'properties.bootstrap.servers' = 'localhost:9092',
    'properties.group.id' = 'tmp_group_one',
    'scan.startup.mode' = 'earliest-offset',
    'format' = 'json'
);
    我们创建了一个 
tmp_result

表来存储去重后的中间结果。数据源通过 Kafka 连接,保证实时读取和处理流数据。

proctime

用于记录每条数据的处理时间。

3.4 FlinkSQL分层去重完整代码
insert into tmp_result 
select 
    t1.word as word 
from ( -- 1 第一层过滤: 子查询为第一层去重(通过state去重)
    select 
        tmp.word     as word,
        tmp.proctime as proctime
    from (
        select 
            word                                                      as word,
            proctime                                                  as proctime,
            row_number()over(partition by word order by proctime asc) as rn 
        from tbl_data_source 
    ) tmp 
    where tmp.rn = 1 
) t1 
-- 2 第二层过滤: 通过外存过滤 
left join dim_hbase_data_source for system_time as of t1.proctime t2 on t1.word = t2.word 
where t2.status is null 
;
3.4.1 第一层去重:基于Flink状态进行去重
select 
    tmp.word     as word,
    tmp.proctime as proctime
from (
    select 
        word                                                      as word,
        proctime                                                  as proctime,
        row_number() over(partition by word order by proctime asc) as rn 
    from tbl_data_source 
) tmp 
where tmp.rn = 1 
    第一层去重通过 
row_number()

实现。这里的

row_number()

为每个

word

分配一个序号,并按照

proctime

升序排列。通过

partition by word

,对每个

word

的重复记录进行分组,保留每组中最早的一条数据,即

rn = 1

的记录。这样实现了基于时间排序的去重,保证了同一个

word

只保留第一条数据(保留最后一条数据将产生变更日志流)。

3.4.2 第二层去重:通过外存过滤 HBase 数据
left join dim_hbase_data_source for system_time as of t1.proctime t2 on t1.word = t2.word 
where t2.status is null 
    第二层去重是通过与外存 HBase 的联合查询实现的。我们通过 
for system_time as of

语法,结合

proctime

来确保数据在外部存储表中是最新的。只有当

word

在 HBase 中不存在(即

status is null

)时,才会将其保留为有效数据。这样能有效避免重复处理已经去重的数据。

3.5 将去重后的数据同步到 HBase
insert into dim_hbase_data_source select word as word, row('1') as cf from tmp_result;
    在数据去重完成后,我们将去重后的数据同步到 HBase 表中,以便后续查询时使用。通过将 
word

字段写入

dim_hbase_data_source

表,并标记状态为

1

,标记为已处理过的数据,确保在后续的数据处理中不会再次出现相同的记录。

3.6 验证测试结果
select * from tmp_result;
    最后,我们可以通过查询 
tmp_result

表来验证数据去重的效果,检查去重后的数据是否符合预期。

4. 技术分析
    通过这种分层去重方案,我们能够有效地管理流数据中的重复记录。第一层去重通过 
row_number()

基于Flink状态实现,保证了同一数据源中相同

word

的唯一性。第二层去重则通过 HBase 等外部存储,进一步去除历史已经处理过的数据,确保数据的准确性。

这种方案的优势在于:

  1. 实时性:通过 Flink SQL 实现流处理,能够即时去重。
  2. 准确性:通过上述去重方案可以保证去重数据不重不漏。
  3. 低延迟:利用 row_number() 窗口函数,确保去重过程对流数据的影响最小。
  4. 高效性:通过分层去重,减少了重复计算和存储压力。
  5. 可扩展性:可以灵活地引入更多的数据源或存储作为去重的层次,提升方案的通用性。
5. 总结
    Flink SQL 提供了灵活的流数据处理能力,特别适用于大规模实时数据的去重。通过设计分层去重方案,不仅可以在数据流中高效去重,还能通过外部存储进一步确保数据的唯一性。随着数据规模的不断增长和实时性要求的提升,这种方案为长周期数据的去重提供了有效的解决路径。
标签: flink sql

本文转载自: https://blog.csdn.net/wen811651208/article/details/143522714
版权归原作者 GawynKing 所有, 如有侵权,请联系我们删除。

“Flink实战之基于Flink SQL 实现长周期数据去重: 分层去重方案介绍”的评论:

还没有评论