Flink SqlServer CDC 连接器的使用

Flink SqlServer CDC 连接器的使用

本sqlserver使用的是2017版本

  • 在使用sqlServerCD连接器之前需要启动对应sqlServer的CDC功能

    需执行以下步骤开启sqlServer的CDC:

--开启表级别的CDC  @source_name = '数据库表名'
EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = '数据库表名', @role_name = NULL, @supports_net_changes = 0;

--查看该表是否启用
SELECT is_cdc_enabled,CASE WHEN is_cdc_enabled=0 THEN 'CDC功能禁用' ELSE 'CDC功能启用' END 描述
FROM sys.databases
WHERE name='数据库表名'

--启用sqlserver的进程
EXEC master.dbo.xp_servicecontrol N'QUERYSTATE', N'SQLSERVERAGENT'
  • 在pom文件加入cdc依赖(flinkcdc 2.x引入):
        <dependency>
            <groupId>com.ververica</groupId>
            <artifactId>flink-connector-sqlserver-cdc</artifactId>
            <version>2.2.1</version>
        </dependency>
  • 代码实现
public class SQLServerTest {
    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1);

        SourceFunction<String> sourceFunction = SqlServerSource.<String>builder()
                .hostname("host")
                .port(1433)
                .database("数据库名") // monitor sqlserver database
                .tableList("dbo.数据库表名") // monitor products table
                .username("用户名")
                .password("密码")
                .deserializer(new JsonDebeziumDeserializationSchema()) // converts SourceRecord to JSON String
                .build();


        env.addSource(sourceFunction).print();


        env.execute();
    }


    public static class JsonDebeziumDeserializationSchema implements DebeziumDeserializationSchema {

        @Override
        public void deserialize(SourceRecord sourceRecord, Collector collector) throws Exception {
            HashMap<String, Object> hashMap = new HashMap<>();

            String topic = sourceRecord.topic();
            String[] split = topic.split("[.]");
            String database = split[1];
            String table = split[2];
            hashMap.put("database",database);
            hashMap.put("table",table);

            //获取操作类型
            Envelope.Operation operation = Envelope.operationFor(sourceRecord);
            //获取数据本身
            Struct struct = (Struct)sourceRecord.value();
            Struct after = struct.getStruct("after");
            Struct before = struct.getStruct("before");
        /*
            1,同时存在 beforeStruct 跟 afterStruct数据的话,就代表是update的数据
             2,只存在 beforeStruct 就是delete数据
             3,只存在 afterStruct数据 就是insert数据
        */

            if (after != null) {
                //insert
                Schema schema = after.schema();
                HashMap<String, Object> hm = new HashMap<>();
                for (Field field : schema.fields()) {
                    hm.put(field.name(), after.get(field.name()));
                }
                hashMap.put("data",hm);
            }else if (before !=null){
                //delete
                Schema schema = before.schema();
                HashMap<String, Object> hm = new HashMap<>();
                for (Field field : schema.fields()) {
                    hm.put(field.name(), before.get(field.name()));
                }
                hashMap.put("data",hm);
            }else if(before !=null && after !=null){
                //update
                Schema schema = after.schema();
                HashMap<String, Object> hm = new HashMap<>();
                for (Field field : schema.fields()) {
                    hm.put(field.name(), after.get(field.name()));
                }
                hashMap.put("data",hm);
            }

            String type = operation.toString().toLowerCase();
            if ("create".equals(type)) {
                type = "insert";
            }else if("delete".equals(type)) {
                type = "delete";
            }else if("update".equals(type)) {
                type = "update";
            }

            hashMap.put("type",type);

            Gson gson = new Gson();
            collector.collect(gson.toJson(hashMap));

        }

        @Override
        public TypeInformation<String> getProducedType() {
            return  BasicTypeInfo.STRING_TYPE_INFO;
        }
    }

}

本文内容来自于官网及个人总结: Flink SqlServer CDC 连接器

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
根据提供的引用内容,可以得知问题出现在将数据库操作代码放入`addSink`方法中时会报错。因此,我们需要将数据库操作代码放入`addSink`方法中,并使用`JdbcSinkFunction`类进行入库操作。以下是连接GaussDB并使用Flink SQL CDC进行数据同步的步骤: 1.首先,需要在Flink中添加GaussDB的JDBC驱动程序。可以将驱动程序jar包放入Flink的lib目录中,或者在启动Flink Job时使用`--classpath`参数指定驱动程序jar包的路径。 2.在Flink SQL Client中创建一个表,用于存储CDC数据。例如,可以使用以下命令创建一个名为`my_table`的表: ```sql CREATE TABLE my_table ( id INT, name STRING, age INT ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:postgresql://localhost:5432/mydb', 'table-name' = 'my_table', 'username' = 'myuser', 'password' = 'mypassword', 'sink.buffer-flush.max-rows' = '5000' ) ``` 其中,`connector`参数指定使用JDBC连接器,`url`参数指定GaussDB的连接URL,`table-name`参数指定表名,`username`和`password`参数指定连接数据库的用户名和密码,`sink.buffer-flush.max-rows`参数指定缓冲区大小。 3.在Flink SQL Client中创建一个CDC源表,用于捕获GaussDB中的变更数据。例如,可以使用以下命令创建一个名为`my_source`的CDC源表: ```sql CREATE TABLE my_source ( id INT, name STRING, age INT, ts TIMESTAMP(3), watermark FOR ts AS ts - INTERVAL '5' SECOND ) WITH ( 'connector' = 'postgresql-cdc', 'hostname' = 'localhost', 'port' = '5432', 'username' = 'myuser', 'password' = 'mypassword', 'database-name' = 'mydb', 'schema-name' = 'public', 'table-name' = 'my_table' ) ``` 其中,`connector`参数指定使用PostgreSQL CDC连接器,`hostname`和`port`参数指定GaussDB的主机名和端口号,`username`和`password`参数指定连接数据库的用户名和密码,`database-name`参数指定数据库名,`schema-name`参数指定模式名,`table-name`参数指定表名。 4.在Flink SQL Client中创建一个查询,用于将CDC源表中的数据写入目标表。例如,可以使用以下命令创建一个查询: ```sql INSERT INTO my_table SELECT id, name, age FROM my_source ``` 5.在Flink中编写一个Job,将上述查询转换为Flink Job。例如,可以使用以下代码编写一个Job: ```java StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); StreamTableEnvironment tEnv = StreamTableEnvironment.create(env); tEnv.executeSql("CREATE TABLE my_table (id INT, name STRING, age INT) WITH (...)"); tEnv.executeSql("CREATE TABLE my_source (id INT, name STRING, age INT, ts TIMESTAMP(3), watermark FOR ts AS ts - INTERVAL '5' SECOND) WITH (...)"); tEnv.executeSql("INSERT INTO my_table SELECT id, name, age FROM my_source"); env.execute(); ``` 其中,`StreamExecutionEnvironment`和`StreamTableEnvironment`分别用于创建Flink执行环境和Flink Table环境,`executeSql`方法用于执行SQL语句,`env.execute()`方法用于启动Flink Job。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值