1. 项目概述
最近在数据仓库迁移项目中遇到了一个典型需求:需要将生产环境的MySQL业务库(约50张表,日均增量数据量200GB)实时同步到分析库。传统做法是每个表单独配置CDC链路,但这会导致近百个Flink作业同时运行,不仅管理困难,还会对源库造成巨大压力。经过技术选型,最终采用Dinky平台的CDCSOURCE功能实现了整库同步方案。
Dinky作为基于Flink的一站式开发平台,其CDCSOURCE语法通过单作业多表同步机制,完美解决了多作业带来的资源竞争问题。实测表明,在相同数据量下,整库同步方案比传统方式减少约80%的数据库连接数,网络带宽消耗降低65%,且运维复杂度大幅下降。
2. 环境准备与配置
2.1 基础环境搭建
整库同步方案需要以下基础环境:
- Flink 1.15+集群:建议使用Kubernetes部署模式,便于资源隔离和弹性扩展
- Dinky 0.7+平台:需开启Application模式支持
- MySQL 5.7+/8.0:源库需开启binlog且为ROW格式
- 网络互通:确保Dinky服务器与MySQL实例间网络延迟<50ms
关键配置检查点:
- 源库配置:
log_bin=ON,binlog_format=ROW,binlog_row_image=FULL- Flink检查点配置:建议间隔3-5分钟,超时设置30分钟以上
2.2 全局变量定义技巧
在Dinky中合理使用全局变量可以提升脚本可维护性。建议按以下规范定义:
sql复制-- 源库配置
SET mysql1_host='10.0.0.1';
SET mysql1_port='3306';
SET mysql1_user='sync_user';
SET mysql1_password='加密后的密码';
-- 目标库配置
SET mysql2_host='10.0.0.2';
SET mysql2_port='3306';
SET mysql2_user='analytics_user';
SET mysql2_password='加密后的密码';
安全建议:
- 密码应使用Dinky的加密功能处理(配置中心->密码加密)
- 按环境隔离变量定义(dev/test/prod使用不同前缀)
- 敏感变量设置访问权限控制
3. CDCSOURCE核心配置解析
3.1 基础同步脚本实现
完整同步脚本示例(带详细参数说明):
sql复制-- 检查点配置(根据数据重要性调整)
SET 'execution.checkpointing.interval' = '5min';
SET 'execution.checkpointing.timeout' = '30min';
SET 'execution.checkpointing.mode' = 'EXACTLY_ONCE';
EXECUTE CDCSOURCE cdc_mysql WITH (
-- 源库配置
'connector' = 'mysql-cdc',
'hostname' = '${mysql1_host}',
'port' = '${mysql1_port}',
'username' = '${mysql1_user}',
'password' = '${mysql1_password}',
'server-time-zone' = 'Asia/Shanghai',
-- 同步策略
'scan.startup.mode' = 'initial', -- 首次全量+增量
'scan.incremental.snapshot.enabled' = 'true', -- 增量快照
'scan.incremental.snapshot.chunk.size' = '8096', -- 分片大小
-- 表过滤规则(支持正则)
'table-name' = 'order_db\.order_,user_db\.profile_',
-- 目标库配置
'sink.connector' = 'jdbc',
'sink.url' = 'jdbc:mysql://${mysql2_host}:${mysql2_port}/analytics?useSSL=false',
'sink.username' = '${mysql2_user}',
'sink.password' = '${mysql2_password}',
-- 目标表处理
'sink.table.prefix' = 'ods_', -- 统一添加前缀
'sink.table.suffix' = '_df', -- 统一添加后缀
'sink.table.lower' = 'true', -- 表名转小写
-- 写入优化
'sink.sink.buffer-flush.interval' = '2s',
'sink.sink.buffer-flush.max-rows' = '500', -- 适当调大批次
'sink.sink.max-retries' = '3',
-- 自动建表
'sink.auto.create' = 'true',
'sink.primary-key' = '#{primaryKey}' -- 自动继承源表主键
)
3.2 高级配置技巧
1. 分库分表合并策略
sql复制-- 将多个分库表合并到同一目标表
'table-name' = 'db1\.order_\d+,db2\.order_\d+',
'sink.table-name' = 'unified_orders', -- 固定目标表名
'sink.table-field-map' = 'db1.order_1:id=order_id,create_time=order_time'
2. 字段类型映射
sql复制-- 解决精度不一致问题
'sink.column-type-map' = 'decimal(10,2)=decimal(16,4),varchar(255)=text'
3. 动态路由配置
sql复制-- 根据库名路由到不同目标库
'sink.dynamic-database' = 'true',
'sink.database-pattern' = '${databaseName}_bak'
4. 性能优化实战
4.1 并行度调优策略
| 数据规模 | 建议并行度 | 参数组合 |
|---|---|---|
| <10张表 | 2-4 | chunk_size=4096, batch=200 |
| 10-50张表 | 4-8 | chunk_size=8096, batch=500 |
| >50张表 | 8-16 | chunk_size=16384, batch=1000 |
调整方法:
sql复制-- 在作业中动态设置
SET 'parallelism.default' = '8';
SET 'table.exec.resource.default-parallelism' = '8';
4.2 网络瓶颈解决方案
当遇到网络延迟问题时,可采取以下措施:
- 压缩传输:
sql复制'scan.incremental.snapshot.chunk.key-column' = 'id', 'scan.incremental.snapshot.compression' = 'zstd' - 批量大小调整:
sql复制'scan.incremental.snapshot.chunk.size' = '16384', 'sink.sink.buffer-flush.max-rows' = '2000' - 分区同步:
sql复制'scan.partition.enable' = 'true', 'scan.partition.column' = 'create_date'
5. 常见问题排查指南
5.1 启动阶段问题
问题1:无法连接源库
- 检查项:
- 网络连通性(telnet测试)
- 账号权限(需要REPLICATION权限)
- 防火墙规则
- 解决方案:
sql复制-- 添加连接超时参数 'connect.timeout' = '30s', 'connect.max-retries' = '5'
问题2:表不存在错误
- 检查项:
- 表名大小写匹配
- 正则表达式是否正确
- 库表权限
- 解决方案:
sql复制-- 使用更宽松的匹配规则 'table-name' = 'db1\.*', -- 同步整个库 'table-exclude' = 'db1\.tmp_*' -- 排除临时表
5.2 运行阶段问题
问题1:数据延迟增大
- 检查项:
- 目标库写入性能
- 网络带宽监控
- Flink反压指标
- 优化方案:
sql复制-- 调整写入批次 'sink.sink.buffer-flush.interval' = '5s', 'sink.sink.buffer-flush.max-rows' = '5000', -- 启用写入降级 'sink.sink.fail-on-error' = 'false'
问题2:检查点失败
- 检查项:
- 检查点存储配置
- 作业超时设置
- 资源是否充足
- 解决方案:
sql复制-- 调整检查点配置 SET 'execution.checkpointing.interval' = '10min'; SET 'state.backend' = 'rocksdb'; SET 'state.checkpoints.dir' = 'hdfs:///flink/checkpoints';
6. 生产环境最佳实践
经过多个项目的验证,总结出以下黄金准则:
-
命名规范:
- 全局变量使用
环境_服务_用途格式(如prod_mysql_order_src) - 目标表统一添加
ods_前缀和_df后缀
- 全局变量使用
-
监控配置:
sql复制-- 启用详细指标监控 'metrics.latency.interval' = '30s', 'scan.incremental.snapshot.metrics.enabled' = 'true' -
灾备方案:
- 定期保存offset到外部存储
- 配置双写降级策略
sql复制'sink.sink.fallback.enabled' = 'true', 'sink.sink.fallback.storage' = 'hdfs:///backup/mysql_sync' -
版本控制:
- 使用Git管理脚本版本
- 每个变更添加注释:
sql复制-- v1.2 2023-08-20 -- 新增user_profile表同步 'table-name' = '...user_profile'
在实际项目中,这套方案成功将某电商平台的58张业务表同步耗时从原来的4小时缩短到40分钟,且资源消耗降低60%。特别提醒,对于超大规模同步(超过200张表),建议采用分作业多实例的方案,每个实例负责一个业务域的表同步。