FlinkCDC 2.0使用实践体验
一、背景说明
所谓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使用实践体验的更多相关文章
- vue 2.0 开发实践总结之疑难篇
续上一篇文章:vue2.0 开发实践总结之入门篇 ,如果没有看过的可以移步看一下. 本篇文章目录如下: 1. vue 组件的说明和使用 2. vuex在实际开发中的使用 3. 开发实践总结 1. ...
- PL/0编译器实践---后记
花了几天时间,把清华版的<编译原理>一书中的PL/0编译器实践了一遍.颇有收获,记录如下: 理解代码的技巧,如何理解一份代码,比如这个程序,其逻辑相对于一般程序就比较复杂了,如何翻译,虚拟 ...
- vue2.0 开发实践总结之入门篇
vue2.0 据说也出了很久了,博主终于操了一次实刀. 整体项目采用 vue + vue-router + vuex (传说中的vue 全家桶 ),构建工具使用尤大大推出的vue-cli 后续文 ...
- Android 7.0真实上手体验
Android 7.0真实上手体验 Android 7.0的首个开发者预览版发布了,支持的设备只有Nexus6.Nexus 5X.Nexus 6P.Nexus 9.Nexus Player.Pixel ...
- AR.Drone 2.0四轴飞机体验:最好的玩具航拍器
http://digi.tech.qq.com/a/20140513/007458.htm?pgv_ref=aio2012&ptlang=2052 AR.Drone 2.0四轴飞机体验:最好的 ...
- Zabbix3.0部署实践
Zabbix3.0部署实践 Zabbix3整个web界面做了一个全新的设计. 1.1Zabbix环境准备 [root@linux-node1 ~]# cat /etc/redhat-release ...
- Thinkphp5.0 的实践一
Thinkphp5.0 的实践一 tp5.0默认没有__SELF__,需要定义, define('__SELF__',strip_tags($_SERVER['REQUEST_URI'])); tp5 ...
- AOP框架Dora.Interception 3.0 [1]: 编程体验
.NET Core正式发布之后,我为.NET Core度身定制的AOP框架Dora.Interception也升级到3.0.这个版本除了升级底层类库(.NET Standard 2.1)之外,我还对它 ...
- Spark2.1.0——Spark初体验
学习一个工具的最好途径,就是使用它.这就好比<极品飞车>玩得好的同学,未必真的会开车,要学习车的驾驶技能,就必须用手触摸方向盘.用脚感受刹车与油门的力道.在IT领域,在深入了解一个系统的原 ...
随机推荐
- 计算机网络笔记Part1 概述
总目录 1.计算机网络的功能.组成.分类 1.1功能 数据通信 资源共享 分布式处理 提高可靠性 负载均衡 1.2组成部分 硬件 软件 协议 1.3分类 按分布范围 广域网 WAN 城域网 MAN 局 ...
- 栅栏密码(The Rail-Fence Cipher)详解
最近训练CTF的时候,发现密码学这块的知识不太系统,所以自己接下来会陆陆续续整理出来 今天学习了栅栏密码,BugkuCTF里面的一道叫做"聪明的小羊"的题就与栅栏密码相关 特点 栅 ...
- i春秋“百度杯”CTF比赛 十月场-Vld(单引号逃逸+报错注入)
题目源代码给出了提示index.php.txt,打开拿到了一段看不太懂得东西. 图片标注的有flag1,flag2,flag3,同时还有三段字符,然后还出现了_GET,脑洞一一点想到访问 ?flag1 ...
- 关于c++ STL map 和 unordered_map 的效率的对比测试
本文采用在随机读取和插入的情况下测试map和unordered_map的效率 笔者的电脑是台渣机,现给出配置信息 处理器 : Intel Pentium(R) CPU G850 @ 2.90GHz × ...
- 用Ultraedit调试tk程序
tk没有自己的编译环境,Ultraedit中仅3步就可以打造一个tk调试环境: 1. 为UE添加tcl/tk语法高亮支持:从UE的网站上下载tcl/tk的wordfile: 2. 添加编译命令到菜单中 ...
- Java课程设计 ssm电影售票选座管理系统 电影网站的网页设计与制作mysql
注意:此项目只截图部分功能,可评论区咨询查看项目全部功能演示 1.开发环境 开发语言:Java 后台框架:SSM(Spring+SpringMVC+Mybatis) 前端技术:HTML+CSS+Jav ...
- minio设置永久访问链接
1.通过minio分享的链接只能支持7天. 解决方案是设置对应的bucket 可通过路径直接访问.(必须通过minio client才能设置下载策略) wget https://dl.min.io/c ...
- 页面模型 PageModel
Razor页面中的程序处理方法 OnGet 和 OnGetAsync是同样的处理程序,因此不能共存,否则会报错. 视图数据 ViewData 视图数据是从页面模型向内容页面传递数据的容器.视图数据是以 ...
- C#基础知识---?为何物
一. 可空类型修饰符(?)引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.可空类型的出现, ...
- .NET 元数据概述
元数据是一种二进制信息,用以对存储在公共语言运行库可移植可执行文件 (PE) 文件或存储在内存中的程序进行描述.将您的代码编译为 PE 文件时,便会将元数据插入到该文件的一部分中,而将代码转换为 Mi ...