Flink CDC系列之:flink-cdc-base模块config
flink-cdc-base 模块是 Flink CDC 项目中的核心基础库,它封装了构建变更数据捕获(CDC)连接器所需的通用逻辑、接口和基础组件。
SourceConfig
这是一个 CDC 数据源配置接口,定义了变更数据捕获(CDC)连接器的基本配置选项。
java
@Experimental
public interface SourceConfig extends Serializable {
- @Experimental: 表示这是一个实验性接口,API 可能在未来版本中改变
- Serializable: 支持序列化,便于在分布式环境中传输配置
配置方法详解
启动选项配置
java
StartupOptions getStartupOptions();
作用: 定义数据捕获的起始位置
可能的值:
- initial: 从最早的可用位置开始
- latest: 从最新位置开始
- timestamp: 从指定时间戳开始
- specific_offset: 从特定偏移量开始
数据分片配置
java
int getSplitSize();
作用: 控制数据分片的大小
影响:
- 较小的值 → 更多并行任务,但开销更大
- 较大的值 → 较少并行任务,但每个任务处理更多数据
java
int getSplitMetaGroupSize();
作用: 定义元数据分组的大小
用途: 优化元数据管理和传输效率
Schema 变更处理
java
boolean isIncludeSchemaChanges();
作用: 是否包含 Schema 变更事件(如 DDL 语句)
场景:
- true: 捕获表结构变更
- false: 只捕获数据变更(DML)
资源优化配置
java
boolean isCloseIdleReaders();
作用: 是否关闭空闲的读取器
优势: 节省系统资源,提高效率
java
boolean isSkipSnapshotBackfill();
作用: 是否跳过快照回填
用途: 在增量同步场景中避免全量数据扫描
动态表发现
java
boolean isScanNewlyAddedTableEnabled();
作用: 是否扫描新添加的表
场景: 在运行时动态发现并捕获新创建的表
分片分配策略
java
boolean isAssignUnboundedChunkFirst();
作用: 是否优先分配无边界分片
策略:
- true: 优先处理可能持续增长的分片
- false: 使用默认分配策略
工厂接口
java
@FunctionalInterface
interface Factory<C extends SourceConfig> extends Serializable {
C create(int subtask);
}
设计特点:
- @FunctionalInterface: 函数式接口,只有一个抽象方法
- 泛型约束: 确保创建的是 SourceConfig 子类
- 子任务感知: create(int subtask) 可以根据子任务 ID 创建不同的配置
使用示例
java
SourceConfig.Factory<MySourceConfig> factory = subtask -> {
MySourceConfig config = new MySourceConfig();
// 根据 subtask ID 进行特定配置
if (subtask == 0) {
config.setSpecialOption(true);
}
return config;
};
与具体连接器的关系:
java
// MySQL CDC 连接器可能实现为:
public class MySqlSourceConfig implements SourceConfig {
// 实现所有接口方法
// 添加 MySQL 特定配置,如:
// - serverId
// - connectTimeout
// - heartbeatInterval
}
设计优势
统一配置接口
- 所有 CDC 连接器使用相同的配置模式
- 便于用户理解和迁移
灵活的工厂模式
- 支持每个子任务有不同的配置
- 适应不均匀的数据分布
资源优化选项
- 提供多种性能调优参数
- 适应不同的部署环境
扩展性良好
- 实验性标注允许 API 演进
- 为未来功能预留接口
这个 SourceConfig 接口为 Flink CDC 提供了强大而灵活的数据源配置能力,是构建高效、可靠数据管道的基础。
BaseSourceConfig
这是一个 CDC 数据源基础配置抽象类,为所有增量数据源提供统一的配置基础。
类概述
java
/** A basic Source configuration which is used by {@link IncrementalSource}. */
public abstract class BaseSourceConfig implements SourceConfig {
抽象类: 需要具体的数据源连接器继承实现
用途: 被 IncrementalSource 使用的通用配置
角色: 实现 SourceConfig 接口,提供默认实现
核心配置字段
基础配置字段
java
protected final StartupOptions startupOptions; // 启动选项
protected final int splitSize; // 分片大小
protected final int splitMetaGroupSize; // 元数据分组大小
protected final boolean includeSchemaChanges; // 是否包含Schema变更
protected final boolean closeIdleReaders; // 是否关闭空闲读取器
protected final boolean skipSnapshotBackfill; // 是否跳过快照回填
protected final boolean isScanNewlyAddedTableEnabled; // 是否扫描新表
protected final boolean assignUnboundedChunkFirst; // 优先分配无边界分片
数据分布优化字段
java
protected final double distributionFactorUpper; // 分布因子上限
protected final double distributionFactorLower; // 分布因子下限
作用: 控制数据分片的均衡性,避免数据倾斜
Debezium 配置字段
java
// Debezium 配置
protected final Properties dbzProperties; // 属性形式
protected transient Configuration dbzConfiguration; // 配置对象(不序列化)
构造函数详解
java
public BaseSourceConfig(
StartupOptions startupOptions, // 启动选项
int splitSize, // 分片大小
int splitMetaGroupSize, // 元分组大小
double distributionFactorUpper, // 分布上界
double distributionFactorLower, // 分布下界
boolean includeSchemaChanges, // 包含Schema变更
boolean closeIdleReaders, // 关闭空闲读取器
boolean skipSnapshotBackfill, // 跳过快照回填
boolean isScanNewlyAddedTableEnabled, // 扫描新表
Properties dbzProperties, // Debezium属性
Configuration dbzConfiguration, // Debezium配置
boolean assignUnboundedChunkFirst) { // 优先分配无边界分片
// 初始化所有字段
}
方法实现分析
接口方法实现
java
@Override
public StartupOptions getStartupOptions() {
return startupOptions;
}
@Override
public int getSplitSize() {
return splitSize;
}
@Override
public int getSplitMetaGroupSize() {
return splitMetaGroupSize;
}
@Override
public boolean isIncludeSchemaChanges() {
return includeSchemaChanges;
}
@Override
public boolean isCloseIdleReaders() {
return closeIdleReaders;
}
@Override
public boolean isSkipSnapshotBackfill() {
return skipSnapshotBackfill;
}
@Override
public boolean isAssignUnboundedChunkFirst() {
return assignUnboundedChunkFirst;
}
特点: 简单返回对应的 final 字段值
额外方法
java
public double getDistributionFactorUpper() {
return distributionFactorUpper;
}
public double getDistributionFactorLower() {
return distributionFactorLower;
}
分布因子作用:
- 控制数据分片的均衡性
- 避免某些分片过大或过小
- 优化并行处理性能
Debezium 配置方法
java
public Properties getDbzProperties() {
return dbzProperties;
}
public Configuration getDbzConfiguration() {
return Configuration.from(dbzProperties); // 从属性重新创建
}
注意: dbzConfiguration 是 transient 的,不参与序列化,需要时重新创建
设计模式分析
模板方法模式
java
// 基础类提供通用实现
public abstract class BaseSourceConfig implements SourceConfig {
// 通用字段和方法实现
}
// 具体连接器继承并添加特定配置
public class MySqlSourceConfig extends BaseSourceConfig {
private final String hostname;
private final int port;
// MySQL 特定配置...
}
不可变对象模式
java
// 所有字段都是 final
protected final StartupOptions startupOptions;
protected final int splitSize;
// ... 其他字段都是 final
优势:
- 线程安全
- 易于推理
- 避免意外修改
建造者模式(通常配合使用)
java
// 典型的建造者模式使用
MySqlSourceConfig config = MySqlSourceConfig.builder()
.startupOptions(StartupOptions.initial())
.splitSize(1000)
.includeSchemaChanges(true)
.hostname("localhost")
.port(3306)
.build();
- MySqlSourceConfig:表示 MySQL 数据源的配置类。
- .builder():静态方法,返回一个建造者实例,开始配置流程。
- .startupOptions(StartupOptions.initial())指定启动选项为 initial(),即从数据库的初始快照开始读取数据(全量同步)。
- .splitSize(1000)定义拆分大小,可能是指每次从数据库中拉取数据的批次大小或并行切分的阈值。
- .includeSchemaChanges(true)设置为 true 时,会捕获并包括 DDL 变更事件(如表结构变化),使管道能响应表结构的动态更新。
- .hostname("localhost")
- .port(3306)
- 分别设置 MySQL 服务器的主机地址和端口号。
- .build();
- 结束配置链,生成最终的不可变 MySqlSourceConfig 对象供后续使用。
配置参数详解
数据分片相关
java
// 分片大小控制并行度
int splitSize = 1000; // 每个分片大约1000行
// 元数据分组优化网络传输
int splitMetaGroupSize = 100; // 每100个分片一组元数据
// 分布因子避免数据倾斜
double upper = 1.5; // 最大分片不超过平均值的1.5倍
double lower = 0.5; // 最小分片不小于平均值的0.5倍
性能优化相关
java
boolean closeIdleReaders = true; // 及时释放资源
boolean skipSnapshotBackfill = false; // 执行全量快照
boolean scanNewlyAddedTable = true; // 支持动态表发现
Debezium 集成
java
Properties dbzProps = new Properties();
dbzProps.setProperty("snapshot.mode", "initial");
dbzProps.setProperty("decimal.handling.mode", "double");
// 其他 Debezium 配置...
在 Flink CDC 架构中的位置
配置层次结构:
java
SourceConfig (接口)
↑
BaseSourceConfig (抽象基类)
↑
具体连接器配置 (如 MySqlSourceConfig、PostgresSourceConfig)
↑
IncrementalSource (数据源实现)
序列化考虑:
java
// transient 字段不参与序列化
protected transient Configuration dbzConfiguration;
// 需要时重新创建
public Configuration getDbzConfiguration() {
if (dbzConfiguration == null) {
dbzConfiguration = Configuration.from(dbzProperties);
}
return dbzConfiguration;
}
扩展示例
MySQL 连接器配置
java
public class MySqlSourceConfig extends BaseSourceConfig {
private final String hostname;
private final int port;
private final String username;
private final String password;
// 构造函数、getter方法等
// 可以添加MySQL特定配置,如:
// - serverId
// - connectTimeout
// - heartbeatInterval
}
总结
BaseSourceConfig 抽象类:
- 提供统一基础: 所有 CDC 连接器共享相同的配置结构
- 封装通用逻辑: 处理序列化、Debezium 集成等通用问题
- 支持性能优化: 提供数据分布、资源管理等优化参数
- 保证一致性: 确保所有连接器具有相似的行为和配置方式
- 易于扩展: 具体连接器只需添加特定数据库的配置参数
这个类是 Flink CDC 连接器框架的核心组件,为构建可靠、高效的变更数据捕获管道提供了坚实的基础。
JdbcSourceConfig
这是一个 JDBC 数据源配置抽象类,专门为基于 JDBC 的关系型数据库 CDC 连接器提供配置。
类概述
java
/**
* A Source configuration which is used by {@link IncrementalSource} which used JDBC data source.
*/
public abstract class JdbcSourceConfig extends BaseSourceConfig {
继承关系: 继承自 BaseSourceConfig
专门用途: 为使用 JDBC 数据源的增量源提供配置
抽象类: 需要具体数据库连接器实现抽象方法
核心配置字段
JDBC 连接配置
java
protected final String driverClassName; // JDBC 驱动类名
protected final String hostname; // 数据库主机名
protected final int port; // 数据库端口
protected final String username; // 用户名
protected final String password; // 密码
数据库对象过滤
java
protected final List<String> databaseList; // 数据库列表
protected final List<String> schemaList; // 模式列表(如 PostgreSQL)
protected final List<String> tableList; // 表列表
连接和性能优化
java
protected final int fetchSize; // 每次获取的行数
protected final String serverTimeZone; // 服务器时区
protected final Duration connectTimeout; // 连接超时时间
protected final int connectMaxRetries; // 最大重试次数
protected final int connectionPoolSize; // 连接池大小
数据分块配置
java
protected final String chunkKeyColumn; // 分块键列
构造函数详解
java
public JdbcSourceConfig(
StartupOptions startupOptions, // 启动选项(继承)
List<String> databaseList, // 数据库列表
List<String> schemaList, // 模式列表
List<String> tableList, // 表列表
int splitSize, // 分片大小(继承)
int splitMetaGroupSize, // 元分组大小(继承)
double distributionFactorUpper, // 分布上界(继承)
double distributionFactorLower, // 分布下界(继承)
boolean includeSchemaChanges, // 包含Schema变更(继承)
boolean closeIdleReaders, // 关闭空闲读取器(继承)
Properties dbzProperties, // Debezium属性(继承)
Configuration dbzConfiguration, // Debezium配置(继承)
// JDBC 特有参数
String driverClassName, // 驱动类名
String hostname, // 主机名
int port, // 端口
String username, // 用户名
String password, // 密码
int fetchSize, // 获取大小
String serverTimeZone, // 服务器时区
Duration connectTimeout, // 连接超时
int connectMaxRetries, // 最大重试次数
int connectionPoolSize, // 连接池大小
String chunkKeyColumn, // 分块键列
boolean skipSnapshotBackfill, // 跳过快照回填(继承)
boolean isScanNewlyAddedTableEnabled, // 扫描新表(继承)
boolean assignUnboundedChunkFirst) { // 优先分配无边界分片(继承)
// 调用父类构造函数
super(...);
// 初始化 JDBC 特有字段
this.driverClassName = driverClassName;
// ... 其他字段初始化
}
核心方法分析
抽象方法 - 必须由子类实现
java
public abstract RelationalDatabaseConnectorConfig getDbzConnectorConfig();
- 作用: 获取 Debezium 关系型数据库连接器配置
- 实现要求: 每个具体数据库连接器必须提供自己的实现
Getter 方法
提供所有字段的访问方法:
java
public String getDriverClassName() { return driverClassName; }
public String getHostname() { return hostname; }
public int getPort() { return port; }
// ... 其他 getter 方法
表过滤器方法
java
public RelationalTableFilters getTableFilters() {
return getDbzConnectorConfig().getTableFilters();
}
作用: 获取表过滤器,用于确定哪些表需要被捕获
来源: 从 Debezium 连接器配置中获取
配置参数详解
JDBC 连接参数
java
// 数据库连接
String driverClassName = "com.mysql.cj.jdbc.Driver";
String hostname = "localhost";
int port = 3306;
String username = "user";
String password = "pass";
// 连接优化
int fetchSize = 1000; // 每次获取1000行
Duration connectTimeout = Duration.ofSeconds(30); // 30秒超时
int connectMaxRetries = 3; // 最多重试3次
int connectionPoolSize = 20; // 连接池大小20
数据库对象选择
java
// 捕获特定数据库和表
List<String> databaseList = Arrays.asList("mydb", "testdb");
List<String> schemaList = Arrays.asList("public"); // PostgreSQL
List<String> tableList = Arrays.asList("users", "orders");
数据分块优化
java
String chunkKeyColumn = "id"; // 使用 id 列进行数据分块
设计模式分析
模板方法模式
java
// 抽象方法,子类必须实现
public abstract RelationalDatabaseConnectorConfig getDbzConnectorConfig();
// 具体实现示例(MySQL)
public class MySqlSourceConfig extends JdbcSourceConfig {
@Override
public RelationalDatabaseConnectorConfig getDbzConnectorConfig() {
// 返回 MySQL 特定的 Debezium 配置
return new MySqlConnectorConfig(...);
}
}
建造者模式配合使用
java
// 典型的使用方式
MySqlSourceConfig config = MySqlSourceConfig.builder()
.hostname("localhost")
.port(3306)
.username("user")
.password("pass")
.databaseList("mydb")
.tableList("users", "orders")
.fetchSize(1000)
.connectionPoolSize(20)
.build();
在 Flink CDC 架构中的位置
配置层次结构:
java
SourceConfig (接口)
↑
BaseSourceConfig (抽象基类)
↑
JdbcSourceConfig (JDBC数据源抽象配置)
↑
具体JDBC连接器配置 (如 MySqlSourceConfig、PostgresSourceConfig)
↑
JdbcIncrementalSource (JDBC增量源实现)
与 Debezium 的集成:
java
// 通过抽象方法获取数据库特定的 Debezium 配置
public abstract RelationalDatabaseConnectorConfig getDbzConnectorConfig();
// 使用配置创建 Debezium 引擎
DebeziumEngine<ChangeEvent> engine = DebeziumEngine.create(Connect.class)
.using(config.getDbzConnectorConfig().getConfig())
.notifying(this::handleChangeEvent)
.build();
具体实现示例
MySQL 连接器配置
java
public class MySqlSourceConfig extends JdbcSourceConfig {
private final String serverId;
private final boolean useSSL;
public MySqlSourceConfig(...) {
super(...);
this.serverId = serverId;
this.useSSL = useSSL;
}
@Override
public RelationalDatabaseConnectorConfig getDbzConnectorConfig() {
Configuration config = Configuration.copy(getDbzProperties())
.with(MySqlConnectorConfig.SERVER_ID, serverId)
.with(MySqlConnectorConfig.SSL_MODE, useSSL ? "required" : "disabled")
.build();
return new MySqlConnectorConfig(config);
}
}
PostgreSQL 连接器配置
java
public class PostgresSourceConfig extends JdbcSourceConfig {
private final String pluginName;
private final String slotName;
public PostgresSourceConfig(...) {
super(...);
this.pluginName = pluginName;
this.slotName = slotName;
}
@Override
public RelationalDatabaseConnectorConfig getDbzConnectorConfig() {
Configuration config = Configuration.copy(getDbzProperties())
.with(PostgresConnectorConfig.PLUGIN_NAME, pluginName)
.with(PostgresConnectorConfig.SLOT_NAME, slotName)
.build();
return new PostgresConnectorConfig(config);
}
}
配置应用场景
生产环境配置
java
JdbcSourceConfig config = new MySqlSourceConfig(
StartupOptions.initial(), // 从初始位置开始
Arrays.asList("prod_db"), // 生产数据库
Collections.emptyList(), // 无模式限制
Arrays.asList("users", "orders"), // 特定表
1000, // 分片大小
100, // 元分组大小
1.5, 0.5, // 分布因子
true, // 包含Schema变更
true, // 关闭空闲读取器
dbzProperties, // Debezium属性
dbzConfiguration, // Debezium配置
"com.mysql.cj.jdbc.Driver", // 驱动
"mysql-prod.example.com", // 主机
3306, // 端口
"cdc_user", // 用户
"secure_password", // 密码
2000, // 获取大小
"UTC", // 时区
Duration.ofSeconds(60), // 连接超时
5, // 最大重试
30, // 连接池大小
"id", // 分块键列
false, // 不跳过快照
true, // 扫描新表
true // 优先无边界分片
);
总结
JdbcSourceConfig 抽象类:
- 专门化设计: 为基于 JDBC 的关系型数据库提供统一配置基础
- 完整连接支持: 包含所有 JDBC 连接必需的参数
- 性能优化: 提供连接池、超时、重试等生产级配置
- 数据分片支持: 支持数据分块和并行处理
- Debezium 集成: 通过抽象方法支持不同数据库的 Debezium 配置
- 易于扩展: 具体数据库连接器只需实现一个抽象方法
这个类是构建关系型数据库 CDC 连接器的核心组件,为 MySQL、PostgreSQL、Oracle 等数据库提供了统一的配置框架。
JdbcSourceConfigFactory
这是一个 JDBC 数据源配置工厂抽象类,采用建造者模式来创建 JDBC 源配置。
类概述
java
/** A {@link Factory} to provide {@link SourceConfig} of JDBC data source. */
@Internal
public abstract class JdbcSourceConfigFactory implements Factory<JdbcSourceConfig> {
工厂模式: 实现 Factory 接口
建造者模式: 提供链式调用的配置方法
内部使用: @Internal 表示这是内部 API,不建议用户直接使用
抽象类: 需要具体数据库连接器实现 create 方法
配置字段与默认值
基础连接配置
java
protected int port;
protected String hostname;
protected String username;
protected String password;
数据库对象过滤
java
protected List<String> databaseList;
protected List<String> tableList;
启动和运行配置
java
protected StartupOptions startupOptions = StartupOptions.initial();
protected boolean includeSchemaChanges = false;
protected boolean closeIdleReaders = false;
数据分片和分布配置(带默认值)
java
protected double distributionFactorUpper =
SourceOptions.SPLIT_KEY_EVEN_DISTRIBUTION_FACTOR_UPPER_BOUND.defaultValue();
protected double distributionFactorLower =
SourceOptions.SPLIT_KEY_EVEN_DISTRIBUTION_FACTOR_LOWER_BOUND.defaultValue();
protected int splitSize = SourceOptions.SCAN_INCREMENTAL_SNAPSHOT_CHUNK_SIZE.defaultValue();
protected int splitMetaGroupSize = SourceOptions.CHUNK_META_GROUP_SIZE.defaultValue();
JDBC 连接优化配置
java
protected int fetchSize = SourceOptions.SCAN_SNAPSHOT_FETCH_SIZE.defaultValue();
protected String serverTimeZone = JdbcSourceOptions.SERVER_TIME_ZONE.defaultValue();
protected Duration connectTimeout = JdbcSourceOptions.CONNECT_TIMEOUT.defaultValue();
protected int connectMaxRetries = JdbcSourceOptions.CONNECT_MAX_RETRIES.defaultValue();
protected int connectionPoolSize = JdbcSourceOptions.CONNECTION_POOL_SIZE.defaultValue();
高级功能配置
java
protected Properties dbzProperties;
protected String chunkKeyColumn;
protected boolean skipSnapshotBackfill =
JdbcSourceOptions.SCAN_INCREMENTAL_SNAPSHOT_BACKFILL_SKIP.defaultValue();
protected boolean scanNewlyAddedTableEnabled =
JdbcSourceOptions.SCAN_NEWLY_ADDED_TABLE_ENABLED.defaultValue();
protected boolean assignUnboundedChunkFirst =
JdbcSourceOptions.SCAN_INCREMENTAL_SNAPSHOT_UNBOUNDED_CHUNK_FIRST_ENABLED.defaultValue();
建造者方法详解
基础连接配置方法
java
public JdbcSourceConfigFactory hostname(String hostname) {
this.hostname = hostname;
return this;
}
public JdbcSourceConfigFactory port(int port) {
this.port = port;
return this;
}
public JdbcSourceConfigFactory username(String username) {
this.username = username;
return this;
}
public JdbcSourceConfigFactory password(String password) {
this.password = password;
return this;
}
数据库对象选择方法
java
public JdbcSourceConfigFactory databaseList(String... databaseList) {
this.databaseList = Arrays.asList(databaseList);
return this;
}
public JdbcSourceConfigFactory tableList(String... tableList) {
this.tableList = Arrays.asList(tableList);
return this;
}
启动选项配置
java
public JdbcSourceConfigFactory startupOptions(StartupOptions startupOptions) {
switch (startupOptions.startupMode) {
case INITIAL:
case SNAPSHOT:
case LATEST_OFFSET:
case COMMITTED_OFFSETS:
break;
default:
throw new UnsupportedOperationException(
"Unsupported startup mode: " + startupOptions.startupMode);
}
this.startupOptions = startupOptions;
return this;
}
支持的启动模式:
- INITIAL: 初始快照
- SNAPSHOT: 快照模式
- LATEST_OFFSET: 最新偏移量
- COMMITTED_OFFSETS: 已提交偏移量
性能优化方法
java
public JdbcSourceConfigFactory splitSize(int splitSize) {
this.splitSize = splitSize;
return this;
}
public JdbcSourceConfigFactory fetchSize(int fetchSize) {
this.fetchSize = fetchSize;
return this;
}
public JdbcSourceConfigFactory connectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
return this;
}
高级功能方法
java
public JdbcSourceConfigFactory includeSchemaChanges(boolean includeSchemaChanges) {
this.includeSchemaChanges = includeSchemaChanges;
return this;
}
public JdbcSourceConfigFactory closeIdleReaders(boolean closeIdleReaders) {
this.closeIdleReaders = closeIdleReaders;
return this;
}
public JdbcSourceConfigFactory skipSnapshotBackfill(boolean skipSnapshotBackfill) {
this.skipSnapshotBackfill = skipSnapshotBackfill;
return this;
}
核心抽象方法
java
@Override
public abstract JdbcSourceConfig create(int subtask);
作用: 子类必须实现此方法,根据配置创建具体的 JdbcSourceConfig 实例
参数: subtask - 子任务 ID,可用于创建特定于子任务的配置
设计模式分析
建造者模式
java
// 链式调用示例
JdbcSourceConfigFactory factory = new MySqlSourceConfigFactory()
.hostname("localhost")
.port(3306)
.username("user")
.password("pass")
.databaseList("mydb")
.tableList("users", "orders")
.splitSize(1000)
.fetchSize(2000);
优势:
- 配置过程清晰直观
- 支持可选参数
- 避免复杂的构造函数
工厂方法模式
java
public abstract class JdbcSourceConfigFactory implements Factory<JdbcSourceConfig> {
@Override
public abstract JdbcSourceConfig create(int subtask);
}
作用: 将对象创建延迟到子类
模板方法模式
父类提供配置构建框架,子类实现具体的创建逻辑。
具体实现示例
MySQL 源配置工厂
java
public class MySqlSourceConfigFactory extends JdbcSourceConfigFactory {
private String serverId;
public MySqlSourceConfigFactory serverId(String serverId) {
this.serverId = serverId;
return this;
}
@Override
public JdbcSourceConfig create(int subtask) {
// 创建 MySQL 特定的配置
Properties dbzProps = new Properties();
if (dbzProperties != null) {
dbzProps.putAll(dbzProperties);
}
dbzProps.setProperty("connector.class", "io.debezium.connector.mysql.MySqlConnector");
if (serverId != null) {
dbzProps.setProperty("database.server.id", serverId + "-" + subtask);
}
return new MySqlSourceConfig(
startupOptions,
databaseList,
null, // schemaList - MySQL 不需要
tableList,
splitSize,
splitMetaGroupSize,
distributionFactorUpper,
distributionFactorLower,
includeSchemaChanges,
closeIdleReaders,
dbzProps,
Configuration.from(dbzProps),
"com.mysql.cj.jdbc.Driver",
hostname,
port,
username,
password,
fetchSize,
serverTimeZone,
connectTimeout,
connectMaxRetries,
connectionPoolSize,
chunkKeyColumn,
skipSnapshotBackfill,
scanNewlyAddedTableEnabled,
assignUnboundedChunkFirst
);
}
}
使用示例
完整配置示例
java
// 创建 MySQL 源配置
MySqlSourceConfigFactory factory = new MySqlSourceConfigFactory()
.hostname("mysql.example.com")
.port(3306)
.username("cdc_user")
.password("secure_password")
.databaseList("orders_db", "users_db")
.tableList("orders_db.orders", "users_db.customers")
.startupOptions(StartupOptions.initial())
.splitSize(2000)
.fetchSize(1000)
.connectionPoolSize(20)
.connectTimeout(Duration.ofSeconds(30))
.connectMaxRetries(3)
.includeSchemaChanges(true)
.closeIdleReaders(true)
.serverTimeZone("UTC")
.chunkKeyColumn("id")
.serverId("12345");
// 为子任务创建配置
JdbcSourceConfig config = factory.create(0);
在 Flink CDC 架构中的位置
配置创建流程:
java
用户配置
→ JdbcSourceConfigFactory (建造者模式)
→ 具体工厂实现 (如 MySqlSourceConfigFactory)
→ create(subtask) 方法
→ JdbcSourceConfig 实例
→ IncrementalSource 数据源
与子任务的关系:
java
// 为每个并行子任务创建配置
for (int subtask = 0; subtask < parallelism; subtask++) {
JdbcSourceConfig config = factory.create(subtask);
// 为每个子任务分配不同的配置
}
配置默认值来源
SourceOptions 默认值
java
SourceOptions.SPLIT_KEY_EVEN_DISTRIBUTION_FACTOR_UPPER_BOUND.defaultValue() // 分布因子上限
SourceOptions.SCAN_INCREMENTAL_SNAPSHOT_CHUNK_SIZE.defaultValue() // 分片大小
JdbcSourceOptions 默认值
java
JdbcSourceOptions.SERVER_TIME_ZONE.defaultValue() // 服务器时区
JdbcSourceOptions.CONNECT_TIMEOUT.defaultValue() // 连接超时
JdbcSourceOptions.CONNECTION_POOL_SIZE.defaultValue() // 连接池大小
总结
JdbcSourceConfigFactory 抽象类:
- 提供建造者接口: 支持链式调用的配置方式
- 封装默认值逻辑: 所有配置都有合理的默认值
- 支持子任务特定配置: 通过 create(int subtask) 方法
- 类型安全: 编译时检查配置参数
- 易于扩展: 具体数据库连接器只需实现一个方法
- 生产就绪: 提供完整的性能优化和高级功能配置
这个工厂类是 Flink CDC JDBC 连接器的核心配置构建器,使得创建复杂的数据源配置变得简单而直观。