Flink CDC 经过版本迭代,也逐渐进入到大家的视野当中,今天就给大家介绍一下Flink CDC 是什么以及它早期版本的痛点,当然最重要的是2.X版本的迭代内容。
一、Flink CDC概述
1.1 什么是Flink CDC
要了解FlinkCDC我们首先要知道CDC是什么?CDC是Change Data Capture变更数据获取的简称。核心思想就是检测捕获数据库的变动(包括数据或数据表的插入,更新以及删除等),将这些变更按发生的顺序完成记录下来,写入消息中间件中提供给其他的消费者。
而我们的flink-cdc-connectors组件,是一个可以直接从Mysql,PostgreSQL 等数据库中直接读取全量数据和增量变更数据的 source 组件。而它的研发主要是来自阿里云开源大数据团队核心成员云邪。
1.2 为什么要使用Flink CDC
传统的CDC流式分析图
1-1
经过整个链路我们可以看到刚开始数据进入到Kafka一定要有数据采集工具的参与,我们国内主要使用阿里的Cannal去采集数据库的binlog文件,国外常用的是Debezium。采集到之后我们将数据输入到Kafka然后Flink再进行消费计算输入到目的地。
这时候我们就可以思考,flink的本质就是灵活就是快,毫秒级,但是整个数据链路不仅仅只有flink,所以为了更快更便捷,我们可以用Flink CDC来代替中间虚线框内的两大组件。还有一个关键的因素就是可以减少用户的学习成本和使用成本。
Flink-CDC的流式分析图
1-2
通过上图我们可以清晰地看到,在图1-1中出现的虚线框中的部分已经被取代,由此可以看出Flink-CDC的特点就是数据链路的优化以及数据的时效性。
1.3 Flink CDC 1.x的痛点
我们知道在全量和增量同步的情况下需要保证数据的一致性,而要保证数据的一致性就得加锁进行保证。底层Debezium在保证数据一致性时需要对读取的库或者表加锁,但全局锁可能导致数据库锁住,表级锁会锁住表的读,而我们整个业务数据都在其中,这个是非常危险的,DBA一般也不会给权限。
当然,也不支持水平增加扩展,因为早期是基于Debezium,架构只有1个节点,所以导致只支持单并发。如果在全量读取阶段这个表是很大的(亿级别),读取的时间要在几个小时,这个时间有点过长,而对于我们用户而言肯定是希望能够水平的进行扩展,就像Hadoop的Mapreduce能够根据切片的个数并行地运行多个map任务一样,希望能够通过支持水平扩展的方式来提升我们的作业速度。
在全量读取的阶段是不支持checkpoint的,这个时候就会产生一个很大的问题,当我们有一个全量同步的任务,这个任务需要8个小时,但是在第7小时59分时它挂掉了,这时候就需要重新进行读取。
二、Flink CDC 2.0 详解
2.1 Flink CDC 2.x
如今的flink2.0要克服的困难首先就是要支持无锁,支持水平扩展,支持checkpoint。
-
整体概览
在对有主键的表做初始化模式时,整体的流程主要分为5个阶段:
-
Chunk切分;
-
Chunk分配(全量)。将数据切分成一小块一小块,切分好后分配给不同的slot进行运行(并行), (实现并行& CheckPoint)各自做CheckPoint;
-
Chunk读取。(实现无锁读取)分配完成之后要读取数据,这个过程是无锁读取;
-
Chunk汇报。向上游汇报自己的CheckPoint已经完成了,收集完成之后启动增量的数据;
-
Chunk分配(增量)。最后读取最新的binlog日志所做的分配,也就是增量任务开始。
-
切分
2-1
对目标数据,按照主键进行数据的分片。chunk的切分其实和很多数据库的分库分表原理类似,一张表有主键我们可以按照主键对数据进行分片,设置每个切片的区间是左闭右开或者左开右闭来保证数据的连续性。
2.2 Chunk分配
2-2
Chunk划分好之后就开始分配给SourceReader,因为SourceReader有多个所以就实现了并行读取的功能。而且每个Chunk在读取的时候可以自己做CheckPoint,就算某个Chunk执行失败了也不用再重头开始进行。
如果每个SourceReader保证了数据的一致性,则全表就一定保证了数据的一致性。
2.3 Chunk 读取
2-3
因为在读取的过程中可能会有一些增量的变化。我们会有一个高位点和低位点,如图所示当前Chunk所在的区间K1-K10,我们先将这个区间select出来存在window buffer里面,在select 之前我们保存一下binlog的位置叫做低位点,在select 之后我们再保存一下binlog 的位置叫做高位点。而增量的部分就是低位点到高位点之间,我们再根据主键对我们Window buffer 里面的数据进行修正输出。
上面保证的是单个chunk的一致性读。
但是如果我们有多个表分了很多不同的chunk,这些chunk都分布在不同的地方,那如何保证一致性读呢?在图2-2中我们可以看到有SourceEnumerator的组件,这个组件主要用于划分Chunk,划分好的Chunk会提供给下游的SourceReader去读取,通过把 Chunk分发给不同的 SourceReader 便实现了并发读取 Snapshot Chunk 的目的。
2.4 Chunk汇报
2-4
汇报的主要目的是为了方便我们后续读取binlog。因为我们支持的是全量和增量,当我们全量消费完成之后只需要消费增量的binlog即可。
2.5 Chunk分配
2-5
FlinkCDC这个chunk的分配主要是为了消费增量的binlog。此时是通过下发Binlog Chunk给任意一个SourceReader进行单并发读取来实现的。
总述:
我们可以整理一下这个整体的流程:我们先是通过主键对这个表进行分片,分片之后分配给不同的SourceRead去读取数据,先读取全量的数据,再读取增量的数据。类似flink的全量窗口后面加上了一个允许迟到的时间,当水印到达窗口的关闭时间时窗口会触发计算,后续在迟到时间之内再来的数据以增量计算的方式进行处理。
好了,以上就是本篇的全部内容了,希望通过对 Flink CDC 早期1.X痛点的描述,以及2.X这些痛点的改进方案介绍,能让大家对它有更多的了解和认识。
—END—