首次加载配置表¶
flowchart TD
subgraph MySQL
TableProcess[("table_process<br/>配置表")]
end
subgraph FlinkJob
subgraph InitPhase["🔥 算子 open() 初始化阶段 🔥"]
JDBC["JDBC Connector<br/>主动查询"]
ConfigMap[("ConfigMap<br/>本地 HashMap")]
JDBC -->|全量读取配置| ConfigMap
end
subgraph SourceLayer["Source 层"]
MainSource["主流 Source<br/>业务数据 (Kafka等)"]
BroadcastSource["广播流 Source<br/>Flink CDC"]
end
subgraph ProcessLayer["处理算子 (BroadcastProcessFunction)"]
BroadcastState[("BroadcastState<br/>广播状态")]
ConfigMap2[("ConfigMap<br/>本地副本")]
end
end
TableProcess -->|"2.Flink CDC 订阅"| BroadcastSource
BroadcastSource -->|"insert / update / delete"| BroadcastState
TableProcess -.->|"1.open() 时查询"| JDBC
MainSource -->|主流数据| ProcessLayer
ProcessLayer -->|"1. 优先读取"| BroadcastState
ProcessLayer -->|"2. 降级读取"| ConfigMap2
ConfigMap -->|"复制到每个算子实例"| ConfigMap2
%% 突出 InitPhase 子图
style InitPhase fill:#fff3b0,stroke:#d9534f,stroke-width:4px,stroke-dasharray:6 4
%% 突出 ConfigMap (初始化阶段的本地 HashMap)
style ConfigMap fill:#cfe2ff,stroke:#0d6efd,stroke-width:3px,color:#000,font-weight:bold
%% 突出 ConfigMap2 (每个算子实例的本地副本,用于降级读取)
style ConfigMap2 fill:#e0d6ff,stroke:#6f42c1,stroke-width:3px,color:#000,font-weight:bold
MySQL连接参数¶
为使用Flink连接MySQL,我们将MySQL的连接参数放入配置常量类 com.zhangsan.edu.common.EduConfig中。
public static final String MYSQL_DRIVER = "com.mysql.cj.jdbc.Driver";
public static final String MYSQL_URL = "jdbc:mysql://node1:3306/edu_config?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
public static final String MYSQL_USERNAME = "root";
public static final String MYSQL_PASSWORD = "123456";
ORM¶
ORM(Object-Relational Mapping,对象关系映射)
数据库表 ORM映射 编程语言对象
+-------------+ +-----------+ +------------+
| id | ----------> | | ----------> | user.id |
| name | ----------> | 映射规则 | ----------> | user.name |
| email | ----------> | | ----------> | user.email |
+-------------+ +-----------+ +------------+
在com.zhangsan.edu.util中定义MySQL工具类,将table_process表映射为DimTableProcess类,表中的记录便可映射为类中的多个对象。
table_process表¶
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| source_table | varchar(200) | NO | PRI | NULL | |
| sink_table | varchar(200) | YES | NULL | ||
| sink_columns | varchar(2000) | YES | NULL | ||
| sink_pk | varchar(200) | YES | NULL | ||
| sink_extend | varchar(200) | YES | NULL |
DimTableProcess¶
创建包com.zhangsan.edu.bean,并在其中创建类DimTableProcess。
public class DimTableProcess {
//来源表
String sourceTable;
//输出表
String sinkTable;
//输出字段
String sinkColumns;
//主键字段
String sinkPk;
//建表扩展
String sinkExtend;
}
自行创建 getter,setter, toString方法
MySQLUtil工具类¶
在com.zhangsan.edu.util包中创建MySQL工具类
public class MySQLUtil {
private static final Logger logger = LoggerFactory.getLogger(MySQLUtil.class);
private static final String QUERY_TABLE_PROCESS_SQL = "SELECT source_table, sink_table, sink_columns, sink_pk, sink_extend FROM table_process";
public static Map<String, DimTableProcess> getTableProcessMap() {
Map<String, DimTableProcess> configMap = new HashMap<>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
Class.forName(EduConfig.MYSQL_DRIVER);
connection = DriverManager.getConnection(
EduConfig.MYSQL_URL,
EduConfig.MYSQL_USERNAME,
EduConfig.MYSQL_PASSWORD
);
preparedStatement = connection.prepareStatement(QUERY_TABLE_PROCESS_SQL);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
DimTableProcess dimTableProcess = new DimTableProcess();
dimTableProcess.setSourceTable(resultSet.getString("source_table"));
dimTableProcess.setSinkTable(resultSet.getString("sink_table"));
dimTableProcess.setSinkColumns(resultSet.getString("sink_columns"));
dimTableProcess.setSinkPk(resultSet.getString("sink_pk"));
dimTableProcess.setSinkExtend(resultSet.getString("sink_extend"));
logger.info("初始化配置表数据:{} -> {}",
dimTableProcess.getSourceTable(),
dimTableProcess.getSinkTable());
configMap.put(dimTableProcess.getSourceTable(), dimTableProcess);
}
} catch (ClassNotFoundException e) {
logger.error("MySQL驱动加载失败", e);
throw new RuntimeException("MySQL驱动加载失败", e);
} catch (SQLException e) {
logger.error("查询MySQL配置表失败", e);
throw new RuntimeException("查询MySQL配置表失败", e);
} finally {
closeResources(resultSet, preparedStatement, connection);
}
return configMap;
}
private static void closeResources(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
logger.warn("关闭ResultSet失败", e);
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
logger.warn("关闭Statement失败", e);
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.warn("关闭Connection失败", e);
}
}
}
}
测试¶
自行在DimSinkApp中测试MySQLUtil的数据查询结果。