Real-time data entry into the lake based on Flink CDC

In the process of building a real-time data warehouse, how to quickly and correctly synchronize business data is the first problem. This article mainly discusses how to use the real-time processing engine Flink and the data lake Apache Iceberg to solve the problem of real-time business data entering the lake. related issues.


01
Introduction to Flink CDC

The full name of CDC is Change Data Capture . Capture of change data is a relatively broad concept. As long as it can capture all data changes, such as the database captures a complete change log to record additions, deletions, and changes, it can be called CDC. This function is widely used in scenarios such as data synchronization, update cache, and data synchronization between microservices. This article mainly introduces the application of Flink CDC in real-time data synchronization scenarios.

Flink introduced the Flink CDC function in version 1.11, and supports both Table & SQL forms. Flink SQL CDC writes real-time tasks in the form of SQL, and parses and synchronizes CDC data in real time. Compared with the traditional data synchronization scheme, the scheme has been greatly improved in terms of real-time performance and ease of use. The following figure is a schematic diagram of the data synchronization scheme based on Flink SQL CDC.

There are various solutions for the collection of Oracle's change log. The Debezium real-time synchronization tool is used here as an example. This tool can parse Oracle's changlog data and synchronize the data to downstream Kafka in real time. Flink SQL creates a Kafka mapping table and specifies the format as debezium-json, and then parses it through Flink and directly inserts it into other external data storage systems. For example, the external data source in the figure is Apache Iceberg as an example.


The following is a detailed analysis of the data synchronization process. First, let's understand the format of Oracle's change log extracted by Debezium. Take update as an example. The change log records the data before the update and the data after the update. After Flink downstream of Kafka receives such data, an update operation record is Changed to delete first, then insert two records. The log format is as follows. The name field of the content of the update operation is updated from tom to jerry.

{
  "before": {          --更新之前的数据
    "id": 001,
    "name""tom"
  },
  "after": {           --更新之后的数据
    "id": 001,
    "name""jerry"
  },
  "source": {...},
  "op""u",
  "ts_ms": 1589362330904,
  "transaction": null
}

Next, let's take a look at how Flink SQL internally handles update records. Flink supports a complete changelog mechanism in version 1.11. As long as each piece of data carries the corresponding signs of addition, deletion and modification, Flink can identify the data and make corresponding additions, deletions and modifications to the result table. Action, as shown in the figure below, the changlog data stream is parsed by Flink and synchronized to the downstream Sink Database.

Through the above analysis, data synchronization based on Flink SQL CDC has the following advantages:

  • Business decoupling: There is no need to invade the business, and it is completely decoupled from the business, that is, the business side does not perceive the existence of data synchronization.

  • Performance consumption: The performance consumption of the business database is small, and the data synchronization delay is low.

  • Easy-to-use synchronization: Use SQL to perform CDC synchronization tasks, which greatly reduces the threshold for use and maintenance.

  • Data integrity: complete database change records, no records will be lost, Flink itself supports Exactly Once.


02
Introduction to Apache Iceberg

It is generally considered that a data lake is a kind of storage that supports the storage of multiple raw data formats, multiple computing engines, efficient unified management of metadata, and massive unified data storage. Among them, the data lake solution composed of the table format represented by Apache Iceberg and the Flink computing engine is particularly eye-catching. The Flink community has also actively embraced data lake technology. Currently, Flink and Iceberg have the highest level of integration in terms of data entry into the lake.

那么Apache Iceberg是什么呢?引用官网的定义是:Apache Iceberg is an open table format for huge analytic datasets。也就是Apache Iceberg是一个大规模数据分析的开放表格式。

Iceberg将数据分为元数据管理层和数据存储层。首先了解一下Iceberg在文件系统中的布局,第一部分是数据文件data files,用于存储具体业务数据,如下图中的data files文件。第二部分是表元数据文件(Metadata 文件),包含Snapshot文件、Manifest文件等。Snapshot表示当前操作的一个快照,每次commit都会生成一个快照,一个快照中包含多个Manifest,每个Manifest中记录了当前操作生成数据所对应的文件地址,也就是data files的地址。基于snapshot的管理方式,iceberg能够进行time travel(历史版本读取以及增量读取)。Iceberg文件系统设计特点如下图所示:

Iceberg的表格式设计具有如下特点:

  • ACID:不会读到不完整的commit数据,基于乐观锁实现,支持并发commit,支持Row-level delete,支持upsert操作。
  • 增量快照:Commit后的数据即可见,在Flink实时入湖场景下,数据可见根据checkpoint的时间间隔来确定的,增量形式也可回溯历史快照。
  • 开放的表格式:对于一个真正的开放表格式,支持多种数据存储格式,如:parquet、orc、avro等,支持多种计算引擎,如:Spark、Flink、Hive、Trino/Presto。
  • 流批接口支持:支持流式写入、批量写入,支持流式读取、批量读取。下文的测试中,主要测试了流式写入和批量读取的功能。


03 Flink CDC打通数据实时导入Iceberg实践

当前使用Flink最新版本1.12,支持CDC功能和更好的流批一体。Apache Iceberg最新版本0.11已经支持Flink API方式upsert,如果使用编写框架代码的方式使用该功能,无异于镜花水月,可望而不可及。本着SQL就是生产力的初衷,该测试使用最新Iceberg的master分支代码编译尝鲜,并对源码稍做修改,达到支持使用Flink SQL方式upsert。

先来了解一下什么是Row-Level Delete?该功能是指根据一个条件从一个数据集里面删除指定行。那么为什么这个功能那么重要呢?众所周知,大数据中的行级删除不同于传统数据库的更新和删除功能,在基于HDFS架构的文件系统上数据存储只支持数据的追加,为了在该构架下支持更新删除功能,删除操作演变成了一种标记删除,更新操作则是转变为先标记删除、后插入一条新数据。具体实现方式可以分为Copy on Write(COW)模式和Merge on Read(MOR)模式,其中Copy on Write模式可以保证下游的数据读具有最大的性能,而Merge on Read模式保证上游数据插入、更新、和删除的性能,减少传统Copy on Write模式下写放大问题。

在Apache Iceberg中目前实现的是基于Merge on Read模式实现的Row-Level Delete。在 Iceberg中MOR相关的功能是在Iceberg Table Spec Version 2: Row-level Deletes中进行实现的,V1是没有相关实现的。虽然当前Apache Iceberg 0.11版本不支持Flink SQL方式进行Row-Level Delete,但为了方便测试,通过对源码的修改支持Flink SQL方式。在不远的未来,Apache Iceberg 0.12版本将会对Row-Level Delete进行性能和稳定性的加强。

Flink SQL CDC和Apache Iceberg的架构设计和整合如何巧妙,不能局限于纸上谈兵,下面就实际操作一下,体验其功能的强大和带来的便捷。并且顺便体验一番流批一体,下面的离线查询和实时upsert入湖等均使用Flink SQL完成。

1,数据入湖环境准备

以Flink SQL CDC方式将实时数据导入数据湖的环境准备非常简单直观,因为Flink支持流批一体功能,所以实时导入数据湖的数据,也可以使用Flink SQL离线或实时进行查询。如下测试是使用Flink提供的sql-client完成的:

第一步,新建Kafka映射表,用于实时接收Topic中的changlog数据:

  id STRING,
name STRING
) WITH (
'connector' = 'kafka',
'topic' = 'topic_name',
'properties.bootstrap.servers' = 'localhost:9092',
'properties.group.id' = 'testGroup',
'scan.startup.mode' = 'earliest-offset',
'format' = 'debezium-json'
);

第二步,新建iceberg结果表,用于存储实时入湖的数据:

CREATE TABLE iceberg_catalog.default.IcebergTable ( id STRING, name STRING );

注:

a)其中省略了配置catalog过程

b)当前iceberg 0.11默认创建表格式版本V1,通过代码更改版本为V2,以支持upsert方式导入数据湖

第三步,启动upsert方式实时入湖的Flink任务:

SET table.dynamic-table-options.enabled=true;

INSERT INTO IcebergTable /*+OPTIONS('equality-field-columns'='id')*/ SELECT * FROM KafkaTable;

注:当前iceberg 0.11不支持Flink SQL形式upsert,通过修改源码达到支持配置指定字段更新功能。

第四步,离线或者实时查询统计IcebergTable表中的数据行数:

a)离线方式

SET execution.type=batch;
SELECT COUNT(*) FROM IcebergTable;

b)实时方式

SET execution.type=streaming;
SELECT COUNT(*) FROM IcebergTable;

2,数据入湖速度测试

数据入湖速度测试会根据环境配置、参数配置、数据格式等不同有所不同,下面是列出主要配置和测试出的数据作为参考。

a)资源配置情况

TaskManager 内存4G,slot:1
Checkpoint 1分钟
测试数据列数 10列
测试数据行数 1000万
iceberg存储格式 parquet

b)测试数据情况

数据入湖分为append和upsert两种方式。append方式只能新增数据,不能对结果数据进行更新操作;upsert方式即能够对结果数据更新。

append方式使用场景是导入数据之前已经明确该表数据不需要更新,如离线数据导入数据湖的场景,append方式下导入数据速度如下:

INSERT INTO IcebergTable SELECT * FROM KafkaTable;

并行度1 12.2万/秒
并行度2 19.6万/秒
并行度4 28.3万/秒

update方式使用场景是既有插入的数据又有对之前插入数据的更新的场景,如数据库实时同步,upsert方式下导入数据速度,该方式需要指定在更新时以那个字段查找,类似于update语句中的where条件,一般设置为表的主键即可,如下:

INSERT INTO IcebergTable /*+OPTIONS('equality-field-columns'='id')*/ SELECT * FROM KafkaTable;

导入的数据 只有数据插入 只有数据更新
并行度1 3.2万/秒 2.9万/秒
并行度2 4.9万/秒 4.2万/秒
并行度4 6.1万/秒 5.1万/秒

c)结论

  • append方式导入速度远大于upsert导入数据速度。在使用的时候,如没有更新数据的场景时,则不需要upsert方式导入数据。
  • 导入速度随着并行度的增加而增加。
  • upsert方式数据的插入和更新速度相差不大,主要得益于MOR原因。

3,数据入湖任务运维

在实际使用过程中,默认配置下是不能够长期稳定的运行的,一个实时数据导入iceberg表的任务,需要通过至少下述四点进行维护,才能使Iceberg表的入湖和查询性能保持稳定。

a)压缩小文件
Flink从Kafka消费的数据以checkpoint方式提交到Iceberg表,数据文件使用的是parquet格式,这种格式无法追加,而流式数据又不能等候太长时间,所以会不断commit提交数据产生小文件。目前Iceberg提供了一个批任务action来压缩小文件,需要定期周期性调用进行小文件的压缩功能。示例代码如下:
Table table = ... 
Actions.forTable(table)
.rewriteDataFiles()
    .targetSizeInBytes(100 * 1024 * 1024) // 100 MB
    .execute();
b)快照过期处理
iceberg本身的架构设计决定了,对于实时入湖场景,会产生大量的snapshot文件,快照过期策略是通过额外的定时任务周期执行,过期snapshot文件和过期数据文件均会被删除。如果实际使用场景不需要time travel功能,则可以保留较少的snapshot文件。
Table table = ... 
Actions.forTable(table)
    .expireSnapshots()
.expireOlderThan(System.currentTimeMillis())
.retainLast(5)
    .execute();
c)清理orphan文件
orphan文件的产生是由于正常或者异常的数据写入但是未提交导致的,长时间积累会产生大量脱离元数据的孤立数据文件,所以也需要类似JVM的垃圾回收一样,周期性清理这些文件。该功能不需要频繁运行,设置为3-5天运行一次即可。
Table table = ...
Actions.forTable(table)
    .removeOrphanFiles()
    .execute();
d)删除元数据文件
  • 每次提交snapshot均会自动产生一个新的metadata文件,实时数据入库会频繁的产生大量metadata文件,需要通过如下配置达到自动删除metadata文件的效果。
Property Description
write.metadata.delete-after-commit.enabled Whether to delete old metadata files after each table commit
write.metadata.previous-versions-max The number of old metadata files to keep

4,数据入湖问题讨论

这里主要讨论数据一致性和顺序性问题。

Q1: 程序BUG或者任务重启等导致数据传输中断,如何保证数据的一致性呢?

Answer:数据一致保证通过两个方面实现,借助Flink实现的exactly once语义和故障恢复能力,实现数据严格一致性。借助Iceberg ACID能力来隔离写入对分析任务的不利影响。

Q2:数据入湖否可保证全局顺序性插入和更新?

Answer:不可以全局保证数据生产和数据消费的顺序性,但是可以保证同一条数据的插入和更新的顺序性。首先数据抽取的时候是单线程的,然后分发到Kafka的各个partition中,此时同一个key的变更数据打入到同一个Kafka的分区里面,Flink读取的时候也能保证顺序性消费每个分区中的数据,进而保证同一个key的插入和更新的顺序性。


04 未来规划

新的技术最终是要落地才能发挥其内在价值的,针对在实践应用中面临的纷繁复杂的数据,结合流计算技术Flink、表格式Iceberg,未来落地规划主要集中在两个方面,一是Iceberg集成到本行的实时计算平台中,解决易用性的问题;二是基于Iceberg,构建准实时数仓进行探索和落地。

1,整合Iceberg到实时计算平台

目前,我所负责的实时计算平台是一个基于SQL的高性能实时大数据处理平台,该平台彻底规避繁重的底层流计算处理逻辑、繁琐的提交过程等,为用户打造一个只需关注实时计算逻辑的平台,助力企业向实时化、智能化大数据转型。

实时计算平台未来将会整合Apache Iceberg数据源,用户可以在界面配置Flink SQL任务,该任务以upsert方式实时解析changlog并导入到数据湖中。并增加小文件监控、定时任务压缩小文件、清理过期数据等功能。

2,准实时数仓探索

本文对数据实时入湖从原理和实战做了比较多的阐述,在完成实时数据入湖SQL化的功能以后,入湖后的数据有哪些场景的使用呢?下一个目标当然是入湖的数据分析实时化。比较多的讨论是关于实时数据湖的探索,结合所在企业数据特点探索适合落地的实时数据分析场景成为当务之急。

随着数据量的持续增大,和业务对时效性的严苛要求,基于Apache Flink和Apache Iceberg构建准实时数仓愈发重要和迫切,作为实时数仓的两大核心组件,可以缩短数据导入、方便数据行级变更、支持数据流式读取等。

--END--

非常欢迎大家加我个人微信有关大数据的问题我们在群内一起讨论

长按上方扫码二维码,加我微信,拉你进群

    本文分享自微信公众号 - 五分钟学大数据(gh_d4a7af3ecd50)。
    如有侵权,请联系 [email protected] 删除。
    本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

    {{o.name}}
    {{m.name}}

    Guess you like

    Origin http://43.154.161.224:23101/article/api/json?id=324175230&siteId=291194637