暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

CDC概述

原创 sg1234 2023-03-06
1631

CDC 的全称是 Change Data Capture ,在广义的概念上,只要能捕获数据变更的技术,我们都可以称为 CDC 。我们目前通常描述的CDC 技术主要面向数据库的变更,是一种用于捕获数据库中数据变更的技术。CDC 技术应用场景非常广泛:

  • 数据同步,用于备份,容灾

  • 数据分发,一个数据源分发给多个下游系统

  • 数据采集,面向数据仓库/数据湖的 ETL 数据集成,是非常重要的数据源

CDC的技术方案非常多,目前业界主流的实现机制的可以分为两种:

基于查询的 CDC

  • 离线调度查询作业,批处理。把一张表同步到其他系统,每次通过查询去获取查询的结果

  • 无法保障数据一致性,查的过程中有可能数据已经发生了多次变更

  • 不保障实时性,基于离线调度有查询延迟

基于日志的 CDC

  • 实时消费日志,流处理,例如MYSQL的BINLOG完整记录库里面的变更,可以把BINLOG当作流的数据源

  • 保障数据一致性,因为BINLOG所有的历史明细都可以获得

  • 提供实时数据,因为提供是流式的消费方式,所以实时性有爆炸


通过图上对比我们可以看到,对于日志查询的方式,增量同步都可以做到,但是基于查询的同步是无法做到增量同步的;在断点续传中,我们的任务有可能消费数据到某个时刻点上面因为各种原因而中断导致任务失败,后面恢复作业的时候我们需要基于这个位移点进行恢复的一个功能。在日志同步功能上;在全量同步上,基于查询或者日志都可以做到,例如MYSQL可以把BINLOG进行重放或者直接整库同步,但是Canal没有做全量支持;在全量+增量的模式上,Flink CDC、Debezium、Oracle Goldengate都支持;在架构角度去看,可以分为单机和分布式,分布式我们不单纯表现在水平扩展上面,在大数据场景会影响比较大,例如我们的数据需要入湖或者入仓,我们的文件系统例如HDFS是分布式架构,在对接上面是否能有比较好的支持,从这个角度上面上看Flink CDC 会支持比较好;数据转换方面,当我们数据进入到CDC 工具时候是否能比较方便的对数据做一些过滤或者清洗,在Flink CDC 上面会比较简单操作,可以通过Flink SQL 去操作这些数据,但是例如像DataX、Debezium需要通过脚本或者模板去做,所以用户在使用的门槛会比较高;生态方面指的是下游的一些数据库或者数据源支持,例如像Flink CDC 下游有丰富的Connector,像写入到TiDB、MySQL、HBase、Kafka等常见的一些组件。


Dynamic Table 就是 Flink 内部定义的表,它是和一条流是等价的,他们两者是可以相互转换的,简单的理解就是:mysql一张表背后其实对应的有binlog,如果你一直对表进行操作更新,binlog也是一直在更新的,相当于数据流和表一直是对应关系的,那么表相当于binlog日志流在某个时刻点物化的结果,那么流就是从这个表一直把这些变更数据进行收集。在Flink中,Change Log Stream 的操作是一一对应的。例如我们表操作从一个算子流向另外一个算子的时候,是以Change Log Stream 的格式发送到下游,当我们数据流向下游时候,都是可以和一张表一一对应,我们可以翻译为一个表,也可以翻译为一个流。


Flink CDC 选择一个底层CDC工具,我们选择了debezium,我们可以做全量+增量的cdc 会比较灵活;RowData 代表了一行的数据,在 RowData 上面会有一个元数据的信息 RowKind,RowKind对应了4种类型进行一一映射 RowKind 里面包括了插入 (INSERT)、更新前 (UPDATE_BEFORE)、更新后 (UPDATE_AFTER)、删除 (DELETE),这样和数据库里面的 binlog 概念十分类似。通过 Debezium 采集的数据,包含了旧数据 (before)和新数据行 (after) 以及原数据信息 (source),op 的 u 表示是 update 更新操作标识符(op 字段的值 c,u,d,r 分别对应 create,update,delete,reade),同时还包含一些其他元数据,例如ts_ms 表示同步的时间戳。

传统CDC ETL 分析

传统CDC的ETL链路(如下图)可以看到,首先我们必须要有数据采集工具参与,例如国外常用的Debezium,国内常用阿里的Cannal去采集数据库的BINLOG,我们采集到的数据一般输出到消息中间件例如Kafka,然后Flink计算引擎再去消费这一部分数据写入到目的端,例如写入到数据湖或者离线数据仓库



其实我们一直思考是否可以使用Flink CDC去替换前面这2个虚线框内比较大的组件,简化用户的维护成本和使用成本,对于用户而言功能没发生变化,数据传输链路的减少意味着数据时效性的提高。于是就有我们基于Flink CDC 的数据分析流程

基于Flink CDC ETL 分析

我们使用了Flink CDC 之后,大大降低用户的使用门槛,我们可以看看下面的DE



可以看到我们通过Flink SQL去采集数据写入到TiDB,创建了CDC的产品表和订单表,然后对数据流进行JOIN直接写入到下游数据库,一个SQL就完成了CDC的数据同步。完全的纯SQL实现,使用BI的业务方都可以上手,与此同时可以使用Flink SQL 算子进行清洗、分析、聚合。但是如果是传统的CDC需要进行数据计算转换清洗是比较困难的




Flink CDC 痛点

基于目前版本Flink CDC ,我们通过整理社区的一些反馈,我们可以看到用户普遍有以下痛点:

  • 全量+增量同步的过程需要保证所有数据的一致性,因此需要通过加锁保证,但是加锁在数据库层面上是一个十分高危的操作。底层Debezium 在保证数据一致性时,需要对读取的库或表加锁,全局锁可能导致数据库锁住,表级锁会锁住表的读 ,DBA 一般不给锁权限。

  • 不支持水平扩展,因为Flink CDC 早期基于Debezium,架构只有1个节点,所以导致了只支持单并发。在全量阶段读取阶段,如果表非常大(亿级别), 读取时间都在小时级别,对于用户而言,期望能够通过水平资源扩展增加资源去提升作业速度。

  • 全量读取阶段不支持 checkpoint:CDC 读取分为两个阶段,全量读取和 增量读取, 目前全量读取阶段是不支持 checkpoint 的,这个就会存在一个问题,当我们同步数据假设需要5个小时,当我们同步了4小时时候作业失败,这时候就需要重新读取数据。

Debezium 锁分析

Flink CDC 底层封装了 Debezium, Debezium 同步一张表分为两个阶段:

  • 全量阶段:查询当前表中所有记录

  • 增量阶段:从 binlog 消费变更数据

大部分用户使用的场景都是全量+增量同步,加锁是发生在全量阶段,目的是为了确定全量阶段的初始位点,保证增量 + 全量实现一条不多,一条不少,保证数据一致性。在我们Flink CDC 上面默认使用无锁模式,能够满足大部分场景。从图中我们可以分析全局锁和表锁的一些加锁流程,左边红色线条是锁的生命周期,右面是MySQL开启可重复读事务的生命周期。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论