FlinkCDC2.0实现原理剖析

更新时间:2023-06-29 16:00:20 阅读: 评论:0

FlinkCDC2.0实现原理剖析
Connectors 是 Apache Flink 的⼀组源端(Source)连接器,通过捕获变更数据(Change Data Capture)从不同数据库中采集数据。项⽬早期通过集成 Debezium 引擎来采集数据,⽀持 全量 + 增量 的模式,保证所有数据的⼀致性。
但因为集成了 Debezium Engine,⽤户在使⽤过程中出现了⼀些痛点:
1. ⼀致性通过加锁保证
Debezium 在保证数据⼀致性时,需要对读取的库或表加锁,全局锁可能导致数据库 hang 住,表级锁会锁住表的读
不⽀持⽔平扩展
Flink CDC ⽬前只⽀持单并发,在全量阶段读取阶段,如果表⾮常⼤(亿级别),读取时间在⼩时级别
全量读取阶段不⽀持 checkpoint
CDC 读取分为两个阶段,全量读取和增量读取,全量读取阶段不⽀持 checkpoint,fail 后需要重新读取
Flink CDC 2.0 为了解决如上痛点⽽设计,借鉴 Netflix DBLog 的⽆锁算法,并基于 FLIP-27 实现,以达成如下⽬标:
北京味道1. ⽆锁
2. ⽔平扩展
3. ⽀持全量阶段 checkpoint
在介绍 Flink CDC 2.0 之前,先来了解⼀下 FLIP-27。FLIP-27 旨在解决 SourceFunction 中存在的⼏个痛点:
split 的发现逻辑(work discovery)和实际读取数据的逻辑耦合在 SourceFunction 和 DataStream 接⼝中,导致 source 实现的复杂性
批处理和流处理需要实现不同的 source活动反思
partitions/shards/splits 等概念没有在接⼝中显⽰定义,使得很难以独⽴于源的⽅式实现事件时间对齐、分区 watermark、动态split 分配、work stealing 等功能
枪械checkpoint 锁由 source function 占有会带来⼀系列问题,导致框架难以优化
没有通⽤框架,这意味着每个 source 都要实现⼀个复杂的线程模型,增加了新 source 实现及测试的难度
FLIP-27 的 Source API 包含两个组件:cpu的主频
SplitEnumerator 负责发现并发现 split,运⾏在 JobManager
SourceReader 负责读取 split 的实际数据,运⾏在 TaskManager
123木头人歌词这两个组件封装了核⼼功能,使得 Source 接⼝本⾝只是⼀个⽤于创建 SplitEnumerator 和 SourceReader 的⼯⼚类。下图展⽰
了 SplitEnumerator 和 SourceReader 的拓扑关系。
新架构下实现的 source connector 可以做到批流⼀体,唯⼀的区别是对批处理 SplitEnumerator 会产出固定数量的 split 集合并且每个split 都是有限数据集;对于流处理 SplitEnumerator 要么产出⽆限多的 split 要么 split ⾃⾝是⽆限数据集。
SplitEnumerator 和 SourceReader 需要由⽤户提供具体的实现类,FLIP-27 在这两个组件之间引⼊了通⽤的消息传递机制,通过传
递 SourceEvent 接⼝进⾏通信,如下图所⽰:
SourceCoordinator 和 SourceOperator 作为上图中 OperatorCoordinator 和 Operator 针对 FLIP-27 的实现,其类结构如下(图中忽略了Failover 相关结构):
徐字组词有哪些
可以看出 SourceCoordinator 封装了 SplitEnumerator,SourceOperator 封装了 SourceReader,在不
考虑 Failover 相关结构时,其接⼝⾮常简单,Flink 框架调⽤ SourceCoordinator#start 函数创建 SplitEnumerator 并将其启动,调⽤ SourceOperator#open 创建、注册并启
动 SourceReader,其序列图如下:
雷达鱼
SourceOperator#emitNext 调⽤ SourceReader#pollNext 接⼝将读取到的数据传递给下游。
思考的乐趣Source 核⼼接⼝(the lowest level interface)被设计地⾮常通⽤,这使得它⾮常灵活,但是也增加了复杂 Reader 的实现难度。因此FLIP-27 中提出了通过构建更⾼层级的抽象来提供更简单的接⼝以允许阻塞调⽤。SourceReaderBa 作为 SourceReader 的⼀个抽象实现,提供了主线程(mail box main thread)和内部读取线程之间的同步机制,⽤户只需专注于:
从外部系统获取记录(通过实现 SplitReader 接⼝)
执⾏记录解析和转换(通过实现 RecordEmitter 接⼝)
提取时间戳并选择是否处理 watermark
下图展⽰了 SourceReaderBa 的⼯作流程:
FLIP-27 在框架层⾯提供了多算⼦并⾏读取的机制,下⾯我们来看⼀下 Flink CDC 2.0 是如何结合 FLIP-27 和 DBLog ⽆锁算法来实现并发读取全量数据后⽆缝转换为单线程读取增量数据的。
源端读取的表结构必须具有物理主键,⽤来将表进⾏切分,ChunkSplitter 可以根据主键将表均匀切分为 (max - min)/chunkSize 个
split(min/max 指主键的最⼩值和最⼤值),或者使⽤ limit 查询保证⼀个 split 中有 chunkSize 条数
据(最后⼀个 split 数据记录数 <= chunkSize)。
DBLog 提出的算法叫做 Watermark-bad Chunk Selection,通过在源数据库中维护⼀个单⾏单列的表作为辅助,在查询每个 chunk(即split)数据前后分别更新该记录使得在事务⽇志中⽣产两个事件 lw(低⽔位)和 hw(⾼⽔位),然后将 lect 数据和 [lw, hw] 之间的⽇志进⾏处理,获得该 chunk 的 point-in-time 为 hw 的⼀组数据。与 DBLog 不同,Flink CDC 2.0 没有维护额外的表,⽽是在 lect 数据前后使⽤ SHOW MASTER STATUS 获取 binlog offt,这种⽅式避免了侵⼊源端系统。
快照读取的逻辑:
1. SHOW MASTER STATUS 获取 lw,插⼊队列
2. 读取该分⽚内的记录,插⼊队列
3. SHOW MASTER STATUS 获取 hw,插⼊队列
4. 判断 lw 与 hw 之间是否有增量变更
5. 如果没有变更,队列中插⼊ BINLOG_END 记录
6. 否则读取 [lw, hw] 之间的 binlog 并插⼊队列,最后⼀条记录为 BINLOG_END
MySqlSnapshotSplitReadTask#doExecute

本文发布于:2023-06-29 16:00:20,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1060335.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:读取   实现   数据   全量   痛点
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图