Flink-CDC-PostgreSQL 之 自定义同步实例

一、依赖引入

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <flink.version>1.16.0</flink.version>
<!--        <flink.version>1.17.0</flink.version>-->
<!--        <flink-cdc.version>3.1.0</flink-cdc.version>-->
        <flink-cdc.version>3.0.1</flink-cdc.version>
<!--        <flink-cdc.version>2.3.0</flink-cdc.version>-->
    </propert>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-api-java-bridge</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-planner-loader</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-runtime</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-base</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-jdbc</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <dependency>
<!--            <groupId>org.apache.flink</groupId>-->
            <groupId>com.ververica</groupId>
            <artifactId>flink-sql-connector-postgres-cdc</artifactId>
            <version>${flink-cdc.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-statebackend-rocksdb</artifactId>
            <version>${flink.version}</version>
<!--            <version>2.1.1</version>--
        </dependency>

二、数据库的设置

1、数据库配置

wal_level = logical
max_replication_slots = 20
max_wal_senders = 20
wal_sender_timeout = 180s
shared_preload_libraries = 'pgoutput'

2、数据库权限设置

CREATE USER cdc_user WITH PASSWORD 'cdc@dip001';
ALTER ROLE cdc_user REPLICATION;
GRANT CONNECT ON DATABASE dip_basedata TO cdc_user;
GRANT USAGE ON SCHEMA public TO cdc_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO cdc_user;
-- 使用超级用户登录后执行
-- CREATE PUBLICATION flink_cdc_pub FOR ALL TABLES;
CREATE PUBLICATION tasktable_cdc_pub FOR TABLE public.t_common_sync_task;
ALTER TABLE public.t_common_sync_task REPLICA IDENTITY FULL;

三、代码编写

1、创建flink执行环境

        // 创建Flink流执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 启用检查点
        env.enableCheckpointing(30000); // 每30秒触发一次检查点
//        env.setStateBackend(new RocksDBStateBackend("hdfs:///flink/checkpoints", true));// 第二个参数启用增量检查点
        env.setStateBackend(new RocksDBStateBackend("file:///tmp/flink/checkpoints", true));// 第二个参数启用增量检查点
        env.getCheckpointConfig().setTolerableCheckpointFailureNumber(3); // 允许3次检查点失败
        env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); // 精确一次语义
        env.getCheckpointConfig().setMinPauseBetweenCheckpoints(10000); // 强制两次检查点间隔至少10000ms(防止频繁触发),如果设置的检查点触发时间小于此值,则会强制使用此值作为检查点间隔
        env.getCheckpointConfig().setCheckpointTimeout(600000); // 检查点超时时间(10分钟)
        env.getCheckpointConfig().setTolerableCheckpointFailureNumber(3); // 允许连续失败次数
        env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION); // 作业取消后保留检查点
//        env.getCheckpointConfig().setString("state.backend.rocksdb.compression", "zstd");
        // 设置并行度
        env.setParallelism(1);

2、debezium属性配置

        Properties properties = new Properties();
        // 好像不起作用使用slot.name
//        properties.setProperty("debezium.slot.name", "bgpc_cdc_slot");
//        properties.setProperty("slot.name", "bgpc_flink_slot");
        properties.setProperty("slot.name", "dbz_customerdb_europe_slot");
        properties.setProperty("publication.name", "tasktable_cdc_pub");
        properties.setProperty("publication.create.enable", "true");
        properties.setProperty("debezium.slot.drop.on.top", "false");
        properties.setProperty("include.schema.changes", "false");//忽略ddl变更
        // 指定连接器启动时执行快照的条件:****重要*****
        //initial- 连接器仅在没有为逻辑服务器名称记录偏移量时才执行快照。
        //always- 连接器每次启动时都会执行快照。
        //never- 连接器从不执行快照。
        //initial_only- 连接器执行初始快照然后停止,不处理任何后续更改。
        //exported- 连接器根据创建复制槽的时间点执行快照。这是一种以无锁方式执行快照的绝佳方式。
        //custom- 连接器根据snapshot.custom.class属性的设置执行快照
        if (initReadIgnore) {
            properties.setProperty("debezium.snapshot.mode", "never");
            properties.setProperty("snapshot.mode", "never");
//            deserialization = new PostgreSQLDeserialization(new PostgreSQLReadDataFilter());
        } else {
            properties.setProperty("debezium.snapshot.mode", "initial");
            properties.setProperty("snapshot.mode", "initial");
//            deserialization = new PostgreSQLDeserialization();
        }

3、创建CDC源

        // 创建PostgreSQL CDC源
//        PostgreSQLSource<String> source = PostgreSQLSource.<String>builder()
        DebeziumSourceFunction<String> source = PostgreSQLSource.<String>builder()
                .hostname("10.17.16.204")
                .port(5432)
                .username("cdc_user")
                .password("cdc@dip001")
                .database("dip_basedata")
                .schemaList("public")
                .tableList("public.t_common_sync_task")
                .debeziumProperties(properties)
                .deserializer(new JsonDebeziumDeserializationSchema())
                .decodingPluginName("pgoutput")  // PostgreSQL 10+ 使用pgoutput
                .build();

4、启动任务

        DataStreamSource<String> sourceStream = env.addSource(source, "PG_SOURCE").setParallelism(1);
        SinkFunction<String> sink=new SinkFunction<String>() {
            @Override
            public void invoke(String value, Context context) throws Exception {
                log.info("监听数据: {}", JSONUtil.toJsonStr(value));
                SinkFunction.super.invoke(value, context);
            }
        };
        sourceStream.addSink(sink).name("PG_SINK");
        env.execute("PG_JOB");

三、结果验证

-- 日志

Starting PostgresConnectorTask with configuration:
connector.class = io.debezium.connector.postgresql.PostgresConnector
slot.name = dbz_customerdb_europe_slot
publication.name = tasktable_cdc_pub
schema.include.list = public
include.schema.changes = false
debezium.slot.drop.on.top = true
tombstones.on.delete = false
offset.storage.file.filename =
publication.create.enable = true
value.converter = com.ververica.cdc.connectors.shaded.org.apache.kafka.connect.json.JsonConverter
database.history.instance.name = b95c8e68-db7b-4b1a-ad9f-7472bb4d04f9
key.converter = com.ververica.cdc.connectors.shaded.org.apache.kafka.connect.json.JsonConverter
database.user = cdc_user
database.dbname = dip_basedata
offset.storage = com.ververica.cdc.debezium.internal.FlinkOffsetBackingStore
database.server.name = postgres_cdc_source
offset.flush.timeout.ms = 5000
heartbeat.interval.ms = 300000
database.port = 5432
plugin.name = pgoutput
offset.flush.interval.ms = 9223372036854775807
internal.key.converter = com.ververica.cdc.connectors.shaded.org.apache.kafka.connect.json.JsonConverter
debezium.snapshot.mode = never
database.hostname = 108.19.16.205
database.password = ********
name = engine
internal.value.converter = com.ververica.cdc.connectors.shaded.org.apache.kafka.connect.json.JsonConverter
table.include.list = public.t_common_sync_task
snapshot.mode = never
database.history = com.ververica.cdc.debezium.internal.FlinkDatabaseSchemaHistory
posted @ 2025-11-27 15:02  蓝迷梦  阅读(70)  评论(0)    收藏  举报