Flink 并行度调优"黄金三步法" (从保守到激进,可回滚)
🎯 第一步:基线配置(保守启动)
原则:先跑起来,不追求极限,收集基准数据
配置公式
yaml
# flink-conf.yaml
taskmanager.numberOfTaskSlots: 4 # 先设物理核心数的一半(8核机器设4)
taskmanager.memory.process.size: 4096m # 给4G内存,别一下吃光
scss
// 代码里
env.setParallelism(4); // 严格等于Slot数,1:1匹配
为什么先保守:
- 避免一开始就挤爆数据库连接池
- 观察单机处理能力的真实基线(每秒处理多少条)
📊 第二步:四维监控(观察期,跑10分钟)
看四个指标,全部绿灯才能进下一步:
| 监控维度 | 查看方式 | 健康标准 | 红灯信号 |
|---|---|---|---|
| CPU | top 或 Flink Web UI |
60%-80% | >90% (瓶颈)或 <30% (资源浪费) |
| 数据库连接 | MySQL: show processlist; PG: SELECT count(*) FROM pg_stat_activity; |
连接数 < 池上限的70% | 连接池耗尽("Too many connections") |
| 网络IO | iftop 或 nload |
带宽占用 < 50% | 打满网卡(千兆网卡跑900Mbps+) |
| Flink反压 | Web UI 看 BackPressure | OK / LOW | HIGH(红色,下游处理不过来) |
操作指令(复制即用):
bash
# 1. 看Flink任务背压(BackPressure)
curl http://localhost:8081/jobs/<job-id>/vertices | grep backPressured
# 2. 看数据库连接数(MySQL)
mysql -e "show status like 'Threads_connected';"
# 3. 实时看CPU和内存
htop # 或 top
🚀 第三步:渐进扩容(黄金倍增法)
原则:每次只翻一倍,对比效率,发现瓶颈立即回退
升级流程
yaml
当前:并行度4,速度 1000条/秒,CPU 40%
↓
调整:并行度8(翻倍),速度 1800条/秒,CPU 65% ✔️ 有效,继续
↓
调整:并行度16(再翻倍),速度 2000条/秒,CPU 90% ✔️ 边际效益下降,停!
↓
回退:并行度12(往回找甜点),速度 2200条/秒,CPU 75% ✨ 最佳配置
回滚触发条件(出现任一立即回退)
| 现象 | 诊断 | 回退动作 |
|---|---|---|
| 速度不升反降 | 线程切换开销 > 并行收益 | 并行度减半 |
数据库报错 Connection refused |
连接池耗尽 | 并行度降至连接池数的70% |
| Flink Task 全红 | 反压严重,下游(Sink)跟不上 | 先降并行度,或优化Sink批量写入 |
| OOM 崩溃 | 内存不够分 | 减少并行度,或增加 TM 内存 |
| 磁盘IO 100% | RocksDB Compaction 占满磁盘 | 减少并行度,或换 SSD |
🎛️ 场景化配置表(直接抄作业)
根据你的数据迁移场景对号入座:
场景A:小表迁移(< 100万条,单机MySQL)
特征:数据量小,网络快,MySQL是瓶颈
scss
env.setParallelism(2); // 别太高,省得把MySQL打爆
arduino
taskmanager.numberOfTaskSlots: 2
taskmanager.memory.process.size: 2048m
数据库侧配合:
sql
-- MySQL 加大连接池
SET GLOBAL max_connections = 50; -- 给Flink留20个够了
场景B:大表迁移(1000万+,分库分表)
特征:数据量大,可横向扩展,Flink是瓶颈
scss
env.setParallelism(16); // 拉满,但要看下面限制
yaml
taskmanager.numberOfTaskSlots: 8 # 如果开2个TM,总Slot=16
taskmanager.memory.process.size: 8192m
关键限制:
- Source 并行度 ≤ MySQL 分片数(比如分了8个库,最多设8,避免一个库被多个线程抢)
- Sink 并行度 ≤ PostgreSQL 连接池 / 2(留一半给查询)
场景C:跨机房迁移(网络延迟高)
特征:RTT 高(ping > 50ms),网络是瓶颈,CPU空等
scss
// 增大批量写入,减少网络往返,并行度不用太高
env.setParallelism(4);
scss
// 关键:加大批次,弥补网络延迟
jdbcSink.setBatchSize(5000); // 默认可能是100,改成5000
jdbcSink.setBatchIntervalMs(1000); // 攒1秒数据一次性发
🔍 瓶颈快速诊断树(出现卡顿用)
erlang
速度不理想?
│
├─ CPU < 50%? → 并行度太低,翻倍试试
│
├─ CPU > 90%? → 并行度太高或数据序列化开销大
│ └─ 检查:是否开了Checkpoint却用MemoryState?
│
├─ 数据库连接数打满? → 降并行度,或加大连接池
│
├─ 网络带宽打满? → 压缩数据,或增大BatchSize减少发包次数
│
└─ Flink Web UI 显示反压(BackPressure HIGH)?
│
├─ Source 反压 → 下游处理太慢,降并行度或优化Sink
│
└─ Sink 反压 → 数据库写不动,降并行度或优化PG索引
⚡ 紧急回滚方案(生产环境救命用)
如果调太高了导致系统崩溃,5秒内恢复:
ini
// 在代码里预留动态调整接口,或启动时从配置中心读取
int parallelism = ConfigUtils.getInt("etl.parallelism", 4); // 默认值4兜底
env.setParallelism(parallelism);
配置中心热更新(Nacos/Apollo):
yaml
etl:
parallelism: 4 # 发现不对劲,改这个数字,重启作业即可
不重启修改(仅适用于SQL作业):
arduino
# 如果是 Flink SQL,可以 Savepoint 后重启改并行度
flink stop <job-id> --savepointPath hdfs://xxx
flink run -s hdfs://xxx -p 4 new-job.jar # -p 4 指定新并行度
💡 一句话总结(带走这个)
"先保守基线,看四维指标,黄金倍增,遇瓶颈就退,找到甜点锁定。"
你的操作清单:
- 今天:设并行度=4,跑起来看监控
- 明天:如果CPU<50%且数据库空闲,改8,对比速度
- 后天:如果速度提升<50%,停,退到6或保持8
- 永远不要:一次从4跳到32(找死)