采集系统上云(阿里巴巴高级开发工程师徐榜江版本的核心特性(详解Flink-CDC))

优采云 发布时间: 2022-01-24 15:22

  采集系统上云(阿里巴巴高级开发工程师徐榜江版本的核心特性(详解Flink-CDC))

  简介:本文由社区志愿者陈正宇整理,内容来自阿里巴巴高级开发工程师徐邦江(薛劲)7月10日在北京站Flink Meetup上分享的《Flink-CDC详解》。深度解读 Flink CDC 新版本 2.0.0 带来的核心特性,包括:全量数据并发读取、检查点、无锁读取等重大改进。

  一、CDC 概述

  CDC的全称是Change Data Capture。从广义上讲,只要是能够捕捉到数据变化的技术,我们就可以称之为CDC。目前常用的CDC技术主要面向数据库变化,是一种用于捕捉数据库中数据变化的技术。CDC技术的应用场景非常广泛:

  CDC有很多技术解决方案。目前业界主流的实现机制可以分为两种:

  比较常见的开源CDC解决方案,我们可以发现:

  

  二、Flink CDC 项目

  说了这么多,让我们回顾一下开发 Flink CDC 项目的动机。

  1. 动态表和变更日志流

  大家都知道 Flink 有两个基本概念:Dynamic Table 和 Changelog Stream。

  

  如果你想想 MySQL 中的表和 binlog 日志,你会发现 MySQL 数据库中一张表的所有更改都记录在 binlog 日志中。如果不断更新表,binlog日志流会一直追加,数据库中的表就相当于binlog日志流在某个时间点的物化结果;日志流是不断捕获表的变化数据的结果。由此可见,Flink SQL 的 Dynamic Table 可以非常自然地表示一个不断变化的 MySQL 数据库表。

  

  在此基础上,我们研究了一些 CDC 技术,最终选择了 Debezium 作为 Flink CDC 的底层 采集 工具。Debezium支持全同步、增量同步、全+增量同步,非常灵活。同时,基于日志的CDC技术使得提供Exactly-Once成为可能。

  对比 Flink SQL 的内部数据结构 RowData 和 Debezium 的数据结构,可以发现两者非常相似。

  通过分析这两种数据结构,可以很容易地连接 Flink 和 Debezium 的底层数据。你可以发现 Flink 在技术上是适合 CDC 的。

  2. 传统 CDC ETL 分析

  我们来看看传统CDC的ETL分析环节,如下图所示:

  

  在传统的基于 CDC 的 ETL 分析中,数据 采集 工具是必不可少的。国外用户常用Debezium,国内用户常用阿里巴巴开源Canal。采集 工具负责采集 数据库的增量数据。,部分采集工具还支持同步全量数据。采集 接收到的数据一般会输出到 Kafka 等消息中间件,然后 Flink 计算引擎会消费这部分数据并写入目的地。目的地可以是各种数据库、数据湖、实时数仓和离线数仓。仓库。

  注意Flink提供了changelog-json格式,可以将changelog数据写入Hive/HDFS等离线数据仓库;对于实时数据仓库,Flink 支持通过 upsert-kafka 连接器将变更日志直接写入 Kafka。

  

  我们一直在思考是否可以使用 Flink CDC 来代替上图中虚线框内的 采集 组件和消息队列,从而简化分析环节,降低维护成本。同时,更少的组件也意味着可以进一步提高数据的时效性。答案是肯定的,所以我们有了基于 Flink CDC 的 ETL 分析流程。

  3. 基于 Flink CDC 的 ETL 分析

  使用 Flink CDC 之后,除了组件更少、维护更方便之外,另一个好处是 Flink SQL 大大降低了用户门槛。您可以看到以下示例:

  

  本示例使用 Flink CDC 同步数据库数据并写入 TiDB。用户直接使用 Flink SQL 创建产品和订单的 MySQL-CDC 表,然后对数据流进行 JOIN 处理,处理后直接写入下游数据库。CDC 的数据分析、处理和同步是通过一个 Flink SQL 作业完成的。

  你会发现这是一个纯SQL的工作,也就是说只要你懂SQL BI,行业的同学就可以完成这样的工作。同时,用户还可以使用 Flink SQL 提供的丰富语法进行数据清洗、分析和聚合。

  

  有了这些功能,现有的 CDC 解决方案很难清理、分析和汇总数据。

  此外,使用 Flink SQL 双流 JOIN、维表 JOIN、UDTF 语法,可以轻松完成数据拓宽和各种业务逻辑处理。

  

  4. Flink CDC 项目开发

  

  三、Flink CDC 2.0 详细信息

  1. Flink CDC 痛点

  MySQL CDC 是 Fl​​ink CDC 中使用最多、最重要的 Connector。本文的以下部分将 Flink CDC Connector 描述为 MySQL CDC Connector。

  随着 Flink CDC 项目的发展,得到了社区众多用户的反馈,主要可以总结为三点:

  

  2. Debezium 锁分析

  Flink CDC 在底部封装了 Debezium。Debezium 分两个阶段同步表:

  用户使用的场景大多是全量+增量同步。锁定发生在全量阶段。目的是确定满卷阶段的初始位置,保证增量+满卷可以做到一多一少,从而保证数据的一致性。从下图中,我们可以分析出全局锁和表锁的一些加锁过程。左边的红线是锁的生命周期,右边是MySQL启用可重复读事务的生命周期。

  

  以全局锁为例,首先获取一个锁,然后启动一个可重复读事务。这里的加锁操作是读取binlog的起始位置和当前表的schema。这样做的目的是保证binlog的起始位置和当前读取的schema可以对应,因为表的schema会发生变化,比如删除或者增加列。读取这两条信息后,SnapshotReader 将读取可重复读取事务中的全量数据。数据量全读完后,会启动BinlogReader从binlog读取的起始位置开始增量读取,以保证数据量全。数据+增量数据无缝对接。

  表锁是全局锁的退化版本,因为全局锁的权限比较高,所以在某些场景下,用户只有表锁。表锁锁需要更长的时间,因为表锁有一个特点:如果提前释放锁,默认会提交可重复读事务,所以需要在读取全量数据后释放锁。

  经过上面的分析,我们来看看这些锁的严重后果:

  

  Flink CDC 1.x 可以解锁,可以满足大部分场景,但要牺牲一定的数据准确性。Flink CDC 1.x 默认添加全局锁。虽然可以保证数据的一致性,但存在上述数据挂起的风险。

  3. Flink CDC 2.0 设计(以 MySQL 为例)

  通过以上分析可知,2.0的设计方案,核心需要解决以上三个问题,即支持无锁、水平扩展、检查点。

  

  DBLog论文中描述的无锁算法如下图所示:

  

  左边是块的分割算法的描述。chunk的切分算法其实和很多数据库中分库分表的原理类似。表中的数据按表的主键分片。假设每个Chunk的步长为10,按照这个规则进行划分,只需要将这些Chunk区间分为左开右闭或左闭右开区间,保证连通区间can等于表的主键区间,即Can。

  右边是每个 Chunk 的无锁读取算法的描述。该算法的核心思想是在对Chunk进行划分后,对每个Chunk的全读和增量读,完成无锁一致性合并。Chunk的分割如下图所示:

  

  因为每个chunk只负责自己主键范围内的数据,所以不难推断,只要能保证读取每个chunk的一致性,就可以保证读取整个表的一致性。这就是无锁算法的基本原理。.

  Netflix 的 DBLog 论文中的 Chunk 读取算法是在 DB 中维护一个信号表,然后通过信号表检查 binlog 文件,记录每个 chunk 读取前的 Low Position(低位)和读取结束后的 High Position . (高点),查询低点和高点之间的Chunk全量数据。读取这部分chunk数据后,将这两个站点之间的binlog增量数据合并为该chunk所属的全量数据,从而得到该chunk在高点时间对应的全量数据。

  结合自身情况,Flink CDC 对块读取算法进行了改进,去除了信号表。它不需要额外维护信号表。binlog 中的标记功能被直接读取 binlog 站点所取代。整体分块读取算法说明如下图:

  

  比如读取Chunk-1时,chunk范围为[K1,K10],先直接选择这个范围内的数据,存入buffer,在select前记录一个binlog的位置(低位),select完成后记录binlog的一个轨迹(high locus)。然后启动增量部分,从低点到高点消费binlog。

  观察图片右下角的最终输出,你会发现在消费chunk的binlog时,出现的key是k2、k3、k5,我们去buffer标记这些键。

  这样,chunk的最终输出就是高点的chunk中最新的数据。

  上图描述了单个Chunk的一致性读,但是如果有多个表划分为很多不同的Chunk,这些Chunk分布到不同的任务中,那么如何分布Chunk,保证全局一致读呢?

  这是基于 FLIP-27 优雅地实现的。您可以在下图中看到带有 SourceEnumerator 的组件。该组件主要用于Chunk划分。分割后的 Chunk 会提供给下游的 SourceReader 读取,并按 chunk 分发 Snapshot Chunk 的过程是针对不同的 SourceReader 实现的,并且基于 FLIP-27,我们可以很容易地在 chunk 粒度上进行 checkpoint。

  

  在读取Snapshot Chunk时,需要有一个上报流程,如下图橙色的上报信息,将Snapshot Chunk完成信息上报给SourceEnumerator。

  

  上报的主要目的是为了后续分发binlog chunks(如下图)。因为 Flink CDC 支持全量+增量同步,所以在所有 Snapshot Chunk 读取完成后,需要消费增量 binlog。这是通过将 binlog 块发送到任何 Source Reader 以进行单个并发读取来实现的。

  

  对于大部分用户来说,其实没必要过多关注如何进行无锁算法和分片的细节,了解一下整体流程就好了。

  整个过程可以概括为:首先通过主键将表划分为Snapshot Chunk,然后将Snapshot Chunk分发给多个SourceReader。在读取每个 Snapshot Chunk 时,它使用一种算法来实现无锁条件下的一致性读取。SourceReader 支持阅读。Chunk粒度检查点,读取完所有的Snapshot Chunk后,下发一个binlog chunk用于增量binlog读取,即Flink CDC 2.0的整体流程,如下图所示:

  

  Flink CDC 是一个完全开源的项目。该项目的所有设计和源代码都已贡献给开源社区。Flink CDC 2.0 也已经正式发布。核心改进和增强包括:

  作者用TPC-DS数据集中的customer表进行了测试。Flink版本为1.13.1,客户表数据量6500万,源并发8,全读阶段:

  为了提供更好的文档支持,Flink CDC 社区构建了文档网站、网站来支持文档版本管理:

  

  Document网站 支持关键字搜索功能,非常有用:

  

  四、未来规划

  

  关于CDC项目的未来规划,我们希望重点关注三个方面:稳定性、高级特性和生态融合。

  “关联”

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线