Flink CDC 2.0 数据处理流程全面解析
8 月份 FlinkCDC 发布 2.0.0 版本,相较于 1.0 版本,在全量读取阶段支持分布式读取、支持 checkpoint,且在全量 + 增量读取的过程在不锁表的情况下保障数据一致性。
Flink CDC2.0 数据读取逻辑并不复杂,复杂的是 FLIP-27: Refactor Source Interface 的设计及对 Debezium Api 的不了解。本文重点对 Flink CDC 的处理逻辑进行介绍, FLIP-27 的设计及 Debezium 的 API 调用不做过多讲解。
本文先以 Flink SQL 案例来介绍 Flink CDC2.0 的使用,接着介绍 CDC 中的核心设计包含切片划分、切分读取、增量读取,最后对数据处理过程中涉及 flink-mysql-cdc 接口的调用及实现进行代码讲解。
案例
全量读取+增量读取 Mysql 表数据,以 changelog-json 格式写入 kafka,观察 RowKind 类型及影响的数据条数。
全量数据输出:
修改表数据,增量捕获:
核心设计
切片划分
全量阶段数据读取方式为分布式读取,会先对当前表数据按主键划分成多个 Chunk,后续子任务读取 Chunk 区间内的数据。根据主键列是否为自增整数类型,对表数据划分为均匀分布的 Chunk 及非均匀分布的 Chunk。
均匀分布
主键列自增且类型为整数类型(int,bigint,decimal)。查询出主键列的最小值,最大值,按 chunkSize 大小将数据均匀划分,因为主键为整数类型,根据当前 chunk 起始位置、chunkSize 大小,直接计算 chunk 的结束位置。
非均匀分布
主键列非自增或者类型为非整数类型。主键为非数值类型,每次划分需要对未划分的数据按主键进行升序排列,取出前 chunkSize 的最大值为当前 chunk 的结束位置。
全量切片数据读取
Flink 将表数据划分为多个 Chunk,子任务在不加锁的情况下,并行读取 Chunk 数据。因为全程无锁在数据分片读取过程中,可能有其他事务对切片范围内的数据进行修改,此时无法保证数据一致性。因此,在全量阶段 Flink 使用快照记录读取+Binlog 数据修正的方式来保证数据的一致性。
快照读取
通过 JDBC 执行 SQL 查询切片范围的数据记录。
数据修正
在快照读取操作前、后执行 SHOW MASTER STATUS 查询 binlog 文件的当前偏移量,在快照读取完毕后,查询区间内的 binlog 数据并对读取的快照记录进行修正。
快照读取+Binlog 数据读取时的数据组织结构。
BinlogEvents 修正 SnapshotEvents 规则。
未读取到 binlog 数据,即在执行 select 阶段没有其他事务进行操作,直接下发所有快照记录。
读取到 binlog 数据,且变更的数据记录不属于当前切片,下发快照记录。
读取到 binlog 数据,且数据记录的变更属于当前切片。delete 操作从快照内存中移除该数据,insert 操作向快照内存添加新的数据,update 操作向快照内存中添加变更记录,最终会输出更新前后的两条记录到下游。
修正后的数据组织结构:
以读取切片[1,11)
范围的数据为例,描述切片数据的处理过程。c,d,u 代表 Debezium 捕获到的新增、删除、更新操作。
修正前数据及结构:
修正后数据及结构:
单个切片数据处理完毕后会向 SplitEnumerator 发送已完成切片数据的起始位置(ChunkStart, ChunkStartEnd)、Binlog 的最大偏移量(High watermark),用来为增量读取指定起始偏移量。
单个切片数据处理完毕后会向 SplitEnumerator 发送已完成切片数据的起始位置(ChunkStart, ChunkStartEnd)、Binlog 的最大偏移量(High watermark),用来为增量读取指定起始偏移量。
版权声明: 本文为 InfoQ 作者【大数据技术指南】的原创文章。
原文链接:【http://xie.infoq.cn/article/a250fdbbdab67d91012e878d1】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论