第一次接触实时数据同步需求时,我对比过不少方案。像传统的ETL工具跑批处理,延迟经常要几个小时;自己写程序监听数据库binlog又容易出错。直到遇到Flink CDC,才发现原来实时同步可以这么简单高效。
Flink CDC的核心优势在于它把数据库变更捕获(CDC)和流处理完美结合。举个例子,电商平台的订单表有任何变动(新增、修改、删除),Flink CDC能在毫秒级感知到,并通过Flink的流水线实时同步到数据仓库。我们团队用这套方案把订单分析报表的延迟从2小时降到了10秒内。
具体来说,Flink CDC有这几个杀手级特性:
我的开发机是台MacBook Pro(16G内存),实测跑单机版完全够用。如果要用测试服务器,建议配置:
必装清单:
安装JDK后记得配置环境变量,这是我~/.bash_profile里的配置:
bash复制export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$JAVA_HOME/bin:$PATH
这里有个大坑我踩过三次:Flink和Flink CDC的版本必须严格匹配。有次用了Flink 1.15配CDC 2.4,结果发现不兼容Kafka连接器。官方兼容表要牢记:
| Flink CDC版本 | 支持的Flink版本 |
|---|---|
| 2.3.x | 1.13.x, 1.14.x, 1.15.x |
| 2.4.x | 1.13.x-1.17.x |
建议新手直接用这套组合:
官方下载地址有时候很慢,我通常用国内镜像:
bash复制wget https://mirrors.tuna.tsinghua.edu.cn/apache/flink/flink-1.16.2/flink-1.16.2-bin-scala_2.12.tgz
tar -xzvf flink-1.16.2-bin-scala_2.12.tgz
cd flink-1.16.2
解压后的目录结构很重要:
bin/:启动脚本所在处conf/:核心配置文件lib/:放各种连接器jar包log/:查看运行日志(出问题时第一个要看的地方)打开conf/flink-conf.yaml,这几个参数必须改:
yaml复制# 管理节点配置
jobmanager.rpc.address: localhost
jobmanager.memory.process.size: 4096m # 根据机器内存调整
# 工作节点配置
taskmanager.numberOfTaskSlots: 4 # 建议设为CPU核心数
taskmanager.memory.process.size: 8192m # 每个TM的内存
# Checkpoint配置(CDC的核心)
execution.checkpointing.interval: 30000 # 30秒一次
execution.checkpointing.mode: EXACTLY_ONCE # 精确一次
state.backend: filesystem # 本地开发用文件系统
state.checkpoints.dir: file:///tmp/flink-checkpoints # 检查点目录
特别提醒:taskmanager.memory.process.size设置太大会导致频繁GC,太小又容易OOM。我的经验值是单TaskManager不超过机器内存的70%。
启动集群其实就一行命令:
bash复制./bin/start-cluster.sh
检查是否启动成功:
jps应该能看到StandaloneSessionClusterEntrypointtail -100f log/flink-*-standalonesession-*.log如果页面打不开,可能是绑定IP有问题。我遇到过一次Mac上localhost不生效,改成rest.bind-address: 0.0.0.0就好了。
两种方式获取:
直接下载(推荐新手):
bash复制wget https://repo1.maven.org/maven2/com/ververica/flink-connector-mysql-cdc/2.3.0/flink-connector-mysql-cdc-2.3.0.jar
cp flink-connector-mysql-cdc-2.3.0.jar lib/
源码编译(需要定制时用):
bash复制git clone https://github.com/ververica/flink-cdc-connectors.git
cd flink-cdc-connectors
mvn clean package -DskipTests
Flink CDC需要读取MySQL的binlog,确保MySQL配置正确:
sql复制-- 检查binlog是否开启
SHOW VARIABLES LIKE 'log_bin';
-- 创建专门账号
CREATE USER 'flinkuser'@'%' IDENTIFIED BY 'Password123!';
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'flinkuser'@'%';
FLUSH PRIVILEGES;
连接器冲突:如果同时放了多个版本的connector jar,可能会报No suitable driver found。解决方法:
bash复制# 查看已加载的connector
ls lib/ | grep cdc
# 只保留需要的版本
时区问题:MySQL和Flink时区不一致会导致时间字段错乱。建议统一:
yaml复制# 在flink-conf.yaml中添加
table.local-time-zone: Asia/Shanghai
权限不足:如果报Access denied,检查账号是否有REPLICATION CLIENT权限
在MySQL创建示例表:
sql复制CREATE DATABASE demo;
USE demo;
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2)
);
INSERT INTO products VALUES (1,'iPhone',5999.00),(2,'MacBook',12999.00);
Flink自带交互式SQL客户端:
bash复制./bin/sql-client.sh
在SQL客户端中输入:
sql复制-- 创建CDC源表
CREATE TABLE products_source (
id INT,
name STRING,
price DECIMAL(10,2),
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'mysql-cdc',
'hostname' = 'localhost',
'port' = '3306',
'username' = 'flinkuser',
'password' = 'Password123!',
'database-name' = 'demo',
'table-name' = 'products'
);
-- 创建打印结果的临时表
CREATE TABLE print_table WITH ('connector' = 'print')
LIKE products_source;
-- 启动同步任务
INSERT INTO print_table SELECT * FROM products_source;
这时在MySQL中新增一条记录:
sql复制INSERT INTO products VALUES (3,'AirPods',1299.00);
几秒后就能在Flink任务的Stdout日志中看到变更事件。我第一次看到数据实时同步过来时,那种感觉就像魔术一样神奇。