一、背景说明

所谓CDC:全称是 Change Data Capture ,在广义的概念上,只要能捕获数据变更的技术,我们都可以称为 CDC 。通常我们说的 CDC 技术主要面向数据库的变更,是一种用于捕获数据库中数据变更的技术。

目前实时链路对于数据的处理是大多数使用的方案是通过工具,对业务数据日志的监控(如canal/maxwell),并连接到kafka,实现对业务数据的实时获取,在实时数仓架构上,ods层一般也会设计在kafka(数据入湖另外说),参考下面图1。而通过FlinkCDC则可以在确保数据一致性的前提下,绕过消息中间组件,Flink实现对数据的直接处理,减少数据的流转链路,另外,由于还支持分布式处理,因此可以获得比canal等组件更高的效率,流程如下面图2。



二、代码部分

关于版本兼容一点说明:使用StreamAPI的话,1.12的版本是支持CDC2.0,如若使用FlinkSQL,需按照官方指定的版本,使用1.13

/**
* @Author: Rango
* @Date: 2021/09/12/下午10:25
* @Description: FlinkCDC监控MySQ,DataStream写法,demo不写checkpoint
*/
public class flincdc {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1); DebeziumSourceFunction<String> mysqlSource = MySqlSource.<String>builder()
.hostname("localhost")
.port(3306)
.username("root")
.password("123456")
.databaseList("test_cdc")
.tableList("test_cdc.cdc_flink") //必须加库名
.deserializer(new myDeserializationSchema()) //自定义反序列化
//.deserializer(new StringDebeziumDeserializationSchema()) //原反系列化器
.startupOptions(StartupOptions.initial())
.build(); DataStreamSource<String> mysqlDS = env.addSource(mysqlSource);
mysqlDS.print();
env.execute();
}
}
//自定义反序列化器
class myDeserializationSchema implements DebeziumDeserializationSchema<String> {
/*
期望输出效果
{
db:数据库名
tb:表名
op:操作类型
befort:{} 数据修改前,create操作没有该项
after:{} 数据修改后,delete操作没有该项
}
*/
public void deserialize(SourceRecord sourceRecord, Collector<String> collector) throws Exception { JSONObject result = new JSONObject(); String[] split = sourceRecord.topic().split("\\.");
result.put("db",split[1]);
result.put("tb",split[2]); //获取操作类型
Envelope.Operation operation = Envelope.operationFor(sourceRecord);
result.put("op",operation.toString().toLowerCase()); Struct value =(Struct)sourceRecord.value();
JSONObject after = getValueBeforeAfter(value, "after");
JSONObject before = getValueBeforeAfter(value, "before"); if (after!=null){result.put("after",after);}
if (before!=null){result.put("before",before);} collector.collect(result.toJSONString());
} public JSONObject getValueBeforeAfter(Struct value,String type){
Struct midStr = (Struct)value.get(type);
JSONObject result = new JSONObject();
if(midStr!=null){
List<Field> fields = midStr.schema().fields();
for (Field field : fields) {
result.put(field.name(),midStr.get(field));
}
return result;
}return null;
} public TypeInformation<String> getProducedType() {
return BasicTypeInfo.STRING_TYPE_INFO;
}
}

效果展示:

#监控的MySQL数据库对应的表结构及数据如下:
mysql> select * from test_cdc.cdc_flink;
+------+----------+--------+
| id | name | sex |
+------+----------+--------+
| 1001 | zhangsan | female |
| 1002 | lisilsi | male |
+------+----------+--------+
2 rows in set (0.00 sec) #命令行提交jar包
./bin/flink run -c com.hll.flincdc FlinkCDC-1.0-SNAPSHOT-jar-with-dependencies.jar

默认 initial 模式,也就是任务启动会把数据库原有数据全打印出来。其他模式在第三部分介绍

三、2.0版本的主要优化点说明

在1.x的版本有如下提到的几个问题,而在2.0的版本,则实现了无锁读取的方式来实现一致性的保证,并且全量读取支持checkpoint,失败无需从头再开启任务。

所谓无锁读取的方式则是通过全量数据chunk切分后并行读取,通过高低水位的方式来确保全量数据一致性读取,而增量部分则是单线程汇报方式,碍于篇幅此处不做源码解读,感兴趣可以看看源码BlinlogSplit部分。

四、其他说明

  • 关于反序列那块,由于cdc直连数据库会有太多冗余信息,只提取需要内容即可,原生内容为SourceRecord对象,对内容进行对应提取即可,SourceRecord对象完整内容如下:
SourceRecord{sourcePartition={server=mysql_binlog_source}, sourceOffset={ts_sec=1631413470, file=mysql-bin.000002, pos=8281, snapshot=true}} ConnectRecord{topic='mysql_binlog_source.test_cdc.cdc_flink', kafkaPartition=null, key=Struct{id=1001}, keySchema=Schema{mysql_binlog_source.test_cdc.cdc_flink.Key:STRUCT}, value=Struct{after=Struct{id=1001,name=zhangsan,sex=female},source=Struct{version=1.5.2.Final,connector=mysql,name=mysql_binlog_source,ts_ms=1631413470946,snapshot=true,db=test_cdc,table=cdc_flink,server_id=0,file=mysql-bin.000002,pos=8281,row=0},op=r,ts_ms=1631413470950}, valueSchema=Schema{mysql_binlog_source.test_cdc.cdc_flink.Envelope:STRUCT}, timestamp=null, headers=ConnectHeaders(headers=)}
  • 关于连接source的模式,可以先看官网介绍:

initial (default): Performs an initial snapshot on the monitored database tables upon first startup, and continue to read the latest binlog.

latest-offset: Never to perform snapshot on the monitored database tables upon first startup, just read from the end of the binlog which means only have the changes since the connector was started.

简单理解,initial是默认模式,cdc任务启动后会把数据库中表原数据全打印出来,可用于历史全量历史数据的输出,而last-offset则是任务启动后,以后数据库有数据变更cdc才有数据输出,用于只关注增量数据的方式。

  • FlinkSQL的写法比较简单,上面的例子,则写法如下:
//注意sql写法必须指定表,每次只能读一张表,stramapi的方式可以监控整个库
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
tableEnv.executeSql("CREATE TABLE mysql_binlog (" +
" id INT NOT NULL," +
" name STRING," +
" sex STRING," +
" PRIMARY KEY(id) NOT ENFORCED" +
") WITH (" +
" 'connector' = 'mysql-cdc'," +
" 'scan.startup.mode' = 'latest-offset'," +
" 'hostname' = 'localhost'," +
" 'port' = '3306'," +
" 'username' = 'root'," +
" 'password' = '123456'," +
" 'database-name' = 'test_cdc'," +
" 'table-name' = 'cdc_flink')");

学习交流,有任何问题还请随时评论指出交流。

FlinkCDC 2.0使用实践体验的更多相关文章

  1. vue 2.0 开发实践总结之疑难篇

    续上一篇文章:vue2.0 开发实践总结之入门篇 ,如果没有看过的可以移步看一下. 本篇文章目录如下: 1.  vue 组件的说明和使用 2.  vuex在实际开发中的使用 3.  开发实践总结 1. ...

  2. PL/0编译器实践---后记

    花了几天时间,把清华版的<编译原理>一书中的PL/0编译器实践了一遍.颇有收获,记录如下: 理解代码的技巧,如何理解一份代码,比如这个程序,其逻辑相对于一般程序就比较复杂了,如何翻译,虚拟 ...

  3. vue2.0 开发实践总结之入门篇

    vue2.0 据说也出了很久了,博主终于操了一次实刀. 整体项目采用  vue +  vue-router +  vuex (传说中的vue 全家桶 ),构建工具使用尤大大推出的vue-cli 后续文 ...

  4. Android 7.0真实上手体验

    Android 7.0真实上手体验 Android 7.0的首个开发者预览版发布了,支持的设备只有Nexus6.Nexus 5X.Nexus 6P.Nexus 9.Nexus Player.Pixel ...

  5. AR.Drone 2.0四轴飞机体验:最好的玩具航拍器

    http://digi.tech.qq.com/a/20140513/007458.htm?pgv_ref=aio2012&ptlang=2052 AR.Drone 2.0四轴飞机体验:最好的 ...

  6. Zabbix3.0部署实践

    Zabbix3.0部署实践   Zabbix3整个web界面做了一个全新的设计. 1.1Zabbix环境准备 [root@linux-node1 ~]# cat /etc/redhat-release ...

  7. Thinkphp5.0 的实践一

    Thinkphp5.0 的实践一 tp5.0默认没有__SELF__,需要定义, define('__SELF__',strip_tags($_SERVER['REQUEST_URI'])); tp5 ...

  8. AOP框架Dora.Interception 3.0 [1]: 编程体验

    .NET Core正式发布之后,我为.NET Core度身定制的AOP框架Dora.Interception也升级到3.0.这个版本除了升级底层类库(.NET Standard 2.1)之外,我还对它 ...

  9. Spark2.1.0——Spark初体验

    学习一个工具的最好途径,就是使用它.这就好比<极品飞车>玩得好的同学,未必真的会开车,要学习车的驾驶技能,就必须用手触摸方向盘.用脚感受刹车与油门的力道.在IT领域,在深入了解一个系统的原 ...

随机推荐

  1. Java异常02——自定义异常

    Error与Exception与自定义异常 Error与Exception Error Exception 自定义异常 快捷键: ctrl + alt + t  package exception.d ...

  2. Windows协议 LDAP篇 - 域用户和计算机用户

    域用户 查询域用户 通过SAMR协议查询(net user就是通过这种协议查询的),samr也不是一种专门的协议,是一个RPC接口 在impacket里有个脚本samrdump.py,就是专门调用这个 ...

  3. VMware 安装 Centos 7 虚拟机配置网络

    在 Windows 机器上如果想使用 Linux 环境,最方便的方式莫过于使用虚拟机,最常用的软件各位肯定也不陌生,大名鼎鼎的 VMware . 不过这玩意有点稍稍不是那么智能,每次安装 Linux ...

  4. 【剑指offer】59 - I. 滑动窗口的最大值

    剑指 Offer 59 - I. 滑动窗口的最大值 知识点:队列:滑动窗口:单调 题目描述 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值. 示例 输入: nums = [ ...

  5. 如何看待Android开发的“前景和内卷”

    我们首先来意淫一波 5G时代Android即将崛起,Android将与物联网强强联合,配合上5G信息高速传递的模式,再搭配物联网号召的"万物互通"的旗号,同时各位Android开发 ...

  6. myvimrc

    set nocompatible execute pathogen#infect() call pathogen#helptags() call pathogen#incubate() imap jk ...

  7. linux服务器下TCP抓包

    1.首先ifconfig查看当前服务器的网卡信息 2.执行tcpdump -i ens160[网卡信息] -s 0 port 8080[监听的端口号] -w ./fileName.pcapng 3.可 ...

  8. 使用sklearn中的fetch_mldata的错误情况以及可能可行的解决方法

    使用sklearn中的fetch_mldata的错误情况以及可能可行的解决方法 在notebook使用的时候出现了报错 from sklearn.datasets import fetch_mldat ...

  9. vue cli中的env详解

    前言 相信使用过 vueCli 开发项目的小伙伴有点郁闷,正常开发时会有三个接口环境(开发,测试,正式),但是 vueCli 只提供了两种 development,production(不包含 tes ...

  10. Python 应用爬虫下载酷狗音乐

    应用爬虫下载酷狗音乐 首先我们需要进入到这个界面 想要爬取这些歌曲链接,然而这个是一个假的网站,虽然单机右键进行检查能看到这些歌曲的链接,可进行爬取时,却爬取不到这些信息. 这个时候我们就应该换一种思 ...