canal和FlinkCDC的总结

文章目录

    • 1.canal
      • canal的介绍
      • Canal原理流程图
    • 2.FlinkCDC
      • 2.1什么是CDC
      • 2.2 CDC的种类
        • 2.2.1 DataStream的方式 (默认序列化器)
        • 2.2.2 FinkSQL的方式
        • 2.2.3 DataStream的方式 (自定义反序列化器)

1.canal

canal的介绍

Canal是基于Mysql二进制的高性能数据同步系统,Canal在阿里巴巴集团中被广泛使用,以提供可靠的低延迟增量数据管道(白话文:其实就是根据mysql的biglog日志,进行增量同步数据)

首先了解Canal的原理之前,我们先了解简单了解一下Mysql主从复制原理:

canal和FlinkCDC的总结_第1张图片

1.所有的save、update、delete操作,都会进入主Mysql服务器,也就是Master节点。
2.Master节点会生成一个BinLog二进制文件,每次操作Mysql数据库就会记录到二进制文件当中。
3.Slave节点(从服务器),会订阅Master节点的BinLog日志,以增量备份的形式同步数据到Slave节点。

Canal原理流程图

canal和FlinkCDC的总结_第2张图片

1.首先第一个步跟上面主从复制原理一样。
2.Canal会伪装成Mysql的Slave服务器,向Mysql的Master服务器传输dump协议
3.Master服务器接受到Dump请求后,开通推送BinLog日志给Slave服务器(也就是Canal服务端),解析BinLog对象(原始为Byte流) ,转成JSON格式
4.Cannal客户端,可以有两种方式来监听服务端(TCP协议/MQ),但是最好是通过MQ形式(目前支持KafKa,RocketMQ ),发送JSON数据到Server端,消费者监听到消 息,消费即可(MQ集群需要考虑消息顺序消费性问题)

2.FlinkCDC

2.1什么是CDC

CDC是Change Data
Capture(变更数据获取)的简称。核心思想是,监测并捕获数据库的变动(包括数据或数据表的插入、更新以及删除等),将这些变更按发生的顺序完整记录下来,写入到消息中间件中以供其他服务进行订阅及消费。
FlinkCDC监控MySQL中变化的数据。

2.2 CDC的种类

CDC主要分为基于查询和基于Binlog两种方式,我们主要了解一下这两种之间的区别:

canal和FlinkCDC的总结_第3张图片
FlinkCDC其实和canal差不多,只不过就是flink社区开发的组件,用起来更方便一些。

2.2.1 DataStream的方式 (默认序列化器)

第一部分:
创建环境
第二部分:
设置ck检查点那一套,每隔多久做一次ck,ck的一致性语义,ck的重启策略,状态后端,访问hdfs的用户名。
第三部分:
创建Flink-MySQL-CDC的Source

Properties properties = new Properties();

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

初始(默认):在第一次启动时对受监控的数据库表执行初始快照,并继续读取最新的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.

最新偏移:从不在第一次启动时对被监视的数据库表执行快照,只是从binlog的末尾读取,这意味着只有连接器启动后的更改。

        //timestamp: Never to perform snapshot on the monitored database tables upon first startup, and directly read binlog from the specified timestamp. The consumer will traverse the binlog from the beginning and ignore change events whose timestamp is smaller than the specified timestamp.
时间戳:从不在第一次启动时对被监视的数据库表执行快照,并且直接从指定的时间戳读取binlog。使用者将从头开始遍历binlog,并忽略时间戳小于指定时间戳的更改事件。

        //specific-offset: Never to perform snapshot on the monitored database tables upon first startup, and directly read binlog from the specified offset.
特定偏移量:从不在第一次启动时对被监控的数据库表执行快照,直接从指定的偏移量读取binlog。
    properties.setProperty("scan.startup.mode", "initial"); //这里就是设置配置。
    DebeziumSourceFunction mysqlSource = MySQLSource.builder()    //因为数据源是MySQL,所以创建MySQL的source,并创建builder。
            .hostname("hadoop102")  //MySQL所在的主机名
            .port(3306)
            .username("root")
            .password("000000")
            .databaseList("gmall-flink") //需要在MySQL中开启binlog。
            .tableList("gmall-flink.z_user_info")         //可选配置项,如果不指定该参数,则会读取上一个配置(数据库)下的所有表的数据 //注意:指定的时候需要使用"db.table"的方式。
            .debeziumProperties(properties) //这个就是方才设置的配置,从哪个位置读取。
            .deserializer(new StringDebeziumDeserializationSchema())  //序列化器,这里用的是自带的。
            .build();
    //4.使用CDC Source从MySQL读取数据
    DataStreamSource mysqlDS = env.addSource(mysqlSource);

    //5.打印数据
    mysqlDS.print();

    //6.执行任务
    env.execute();

2.2.2 FinkSQL的方式

//1.创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

    //2.创建Flink-MySQL-CDC的Source
    tableEnv.executeSql("CREATE TABLE user_info (" +
            "  id INT," +
            "  name STRING," +
            "  phone_num STRING" +
            ") WITH (" +
            "  'connector' = 'mysql-cdc'," +
            "  'hostname' = 'hadoop102'," +
            "  'port' = '3306'," +
            "  'username' = 'root'," +
            "  'password' = '000000'," +
            "  'database-name' = 'gmall-flink'," +
            "  'table-name' = 'z_user_info'" +
            ")");

    tableEnv.executeSql("select * from user_info").print();

    env.execute();

2.2.3 DataStream的方式 (自定义反序列化器)

    //1.创建执行环境
    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
    env.setParallelism(1);

    //2.创建Flink-MySQL-CDC的Source
    Properties properties = new Properties();

    //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.
//timestamp: Never to perform snapshot on the monitored database tables upon first startup, and directly read binlog from the
specified timestamp. The consumer will traverse the binlog from the
beginning and ignore change events whose timestamp is smaller than the
specified timestamp.
//specific-offset: Never to perform snapshot on the monitored database tables upon first startup, and directly read binlog from the
specified offset.
properties.setProperty(“debezium.snapshot.mode”, “initial”); //如果用CDC代替canal或者Maxwell的话,就得需要写这些,并且自定义反序列化器。
DebeziumSourceFunction mysqlSource = MySQLSource.builder()
.hostname(“hadoop102”)
.port(3306)
.username(“root”)
.password(“000000”)
.databaseList(“gmall-flink”)
.tableList(“gmall-flink.z_user_info”) //可选配置项,如果不指定该参数,则会读取上一个配置下的所有表的数据,注意:指定的时候需要使用"db.table"的方式
.debeziumProperties(properties)
.deserializer(new DebeziumDeserializationSchema() { //自定义数据解析器
@Override
public void deserialize(SourceRecord sourceRecord, Collector collector) throws Exception {

                    //获取主题信息,包含着数据库和表名  mysql_binlog_source.gmall-flink.z_user_info
                    String topic = sourceRecord.topic();
                    String[] arr = topic.split("\\.");
                    String db = arr[1];
                    String tableName = arr[2];

                    //获取操作类型 READ DELETE UPDATE CREATE
                    // sourceRecord就是源纪录,就是具体的什么操作,然后翻译出来,这样我们就看到是read,还是delete,还是update,还是create。
                    Envelope.Operation operation = Envelope.operationFor(sourceRecord);

                    //获取值信息并转换为Struct类型
                    Struct value = (Struct) sourceRecord.value();

             //获取变化后的数据,数据是存放在after来面的json字段串里面。
                Struct after = value.getStruct("after");
                 if(after!=null){
                    //创建JSON对象用于存储数据信息
                    JSONObject data = new JSONObject();
                    for (Field field : after.schema().fields()) {
                        Object o = after.get(field);
                        data.put(field.name(), o);
                    }

                    //创建JSON对象用于封装最终返回值数据信息
                    JSONObject result = new JSONObject();
                    result.put("operation", operation.toString().toLowerCase());
                    result.put("data", data);//data所在的json放在result这个json里面。
                    result.put("database", db);
                    result.put("table", tableName);
           }
                 //发送数据至下游
                    collector.collect(result.toJSONString());
                }

                @Override
                public TypeInformation getProducedType() {
                    return TypeInformation.of(String.class);
                }
            })
            .build();

    //3.使用CDC Source从MySQL读取数据
    DataStreamSource mysqlDS = env.addSource(mysqlSource);

    //4.打印数据
    mysqlDS.print();

    //5.执行任务
    env.execute();

由此可见,如果DataStream的方式,想得到数据的话,就得自定义序列化器。用flinkSQL得方式就不用。

具体写法参考

https://github.com/ververica/flink-cdc-connectors

你可能感兴趣的:(FlinkCDC与Canal)