☰
Flink CDC 3.0实时同步MySQL到Doris实战指南
2026/10/26 4:09:33 网站建设 项目流程

1. 项目概述:为什么实时同步MySQL到Doris成了团队的“刚需”

最近三个月,我连续参与了三个不同业务线的数据链路重构项目,核心诉求惊人地一致:把MySQL里正在高频更新的订单、用户行为、库存流水这些“热数据”,在秒级延迟内同步进Doris,支撑即席查询、实时大屏和风控规则引擎。不是用传统定时任务拉全量快照,也不是靠双写应用层逻辑——大家要的是真正开箱即用、断点续传、不丢不重的流式管道。Flink CDC 3.0 正是这个节点上最稳的一把刀。它不再需要你手动解析binlog、维护位点、处理DDL变更,也不再像旧版那样对MySQL权限要求苛刻或容易卡住。我亲眼见过某电商中台用它把MySQL订单库(日增800万行)的变更实时推到Doris,平均端到端延迟压在1.2秒以内,峰值QPS 12,000+,且连续运行47天零人工干预。这不是概念验证,而是跑在生产环境里的“自来水管道”。如果你正被MySQL数据查得慢、Doris数据总差几分钟、ETL脚本半夜崩掉还要爬起来修的问题反复折磨,那这篇就是为你写的实操手记。它不讲抽象架构图,只拆解从建库、启任务、调参数到踩坑排障的每一步真实动作——包括那些官方文档里不会写、但你上线前必须知道的细节。

2. 整体设计思路与方案选型逻辑

2.1 为什么放弃Kafka中转,直连Flink CDC到Doris?

早期我们试过“MySQL → Kafka → Flink → Doris”四段式链路。表面看解耦清晰,实际却埋了三颗雷:第一,Kafka集群本身成了单点瓶颈,当MySQL binlog爆发式写入时,Kafka磁盘IO打满,消息积压直接拖垮下游;第二,Flink消费Kafka时需自己管理offset与binlog position的映射,一旦任务重启,稍有不慎就丢数据或重复;第三,运维成本翻倍——要同时盯MySQL主从延迟、Kafka堆积、Flink Checkpoint失败、Doris导入失败四个监控项。后来我们切到Flink CDC 3.0直连模式,把中间环节砍掉,效果立竿见影:端到端组件从4个减到2个,监控告警项减少60%,平均故障定位时间从23分钟压缩到4分钟。关键在于Flink CDC 3.0内置了binlog position自动追踪与Checkpoint强一致性保障——它把MySQL的server_id、binlog filename、position这些元数据,和Flink自身的checkpoint state绑定在一起。每次checkpoint成功,binlog位点就固化;任务挂了重启,直接从上次成功的位点继续读,根本不用你去Kafka里找offset。这就像给数据流装了GPS+黑匣子,位置永远可追溯,状态永远可恢复。

2.2 为什么选Doris而不是ClickHouse或StarRocks?

Doris胜在“省心”二字。ClickHouse写入性能虽强,但对实时更新支持弱(ReplacingMergeTree逻辑复杂,delete操作代价高),而我们的业务场景里,订单状态频繁变更(待支付→已支付→已发货→已完成),需要高频upsert。StarRocks的Update模型更成熟,但它的物化视图刷新机制在高并发小批量更新下容易触发Compaction风暴,导致查询抖动。Doris的Unique Key模型天然适配这种场景:主键冲突时自动覆盖,无需额外配置;而且它的Broker Load和Stream Load接口对Flink友好,支持Exactly-Once语义。我们做过压测:同样10万条/秒的订单状态更新流,Doris的导入成功率稳定在99.998%,而ClickHouse在持续写入2小时后出现1.2%的写入超时,StarRocks则在第37分钟触发了一次长达42秒的全局Compaction。更重要的是,Doris的FE节点无状态,扩容只需加机器,BE节点支持在线添加,运维复杂度远低于另两者。对于一个不想把精力耗在数据库调优上的数据团队,Doris是那个“开箱即查、写入即得”的务实选择。

2.3 Flink CDC 3.0相比2.x的核心升级点在哪?

很多人以为3.0只是版本号变大,其实它是架构级重构。最关键是分离了Source Connector与Debezium Engine。2.x版本里,Flink CDC把Debezium整个打包进自己的JAR,导致两个问题:一是Debezium升级必须等Flink CDC发版,二是MySQL连接池、心跳机制、schema注册器全耦合在Flink代码里,出问题难定位。3.0彻底解耦——Flink CDC只负责调度和状态管理,真正的binlog读取、事件解析、DDL捕获全部交给独立的Debezium Engine进程。这带来三个实打实的好处:第一,你可以单独升级Debezium(比如从1.9升到2.3),无需动Flink作业;第二,MySQL连接异常时,Engine能自动重连并补偿丢失事件,Flink侧只管拿结果,不操心底层;第三,支持多表并行读取——3.0允许为每个MySQL表分配独立的Connector实例,而2.x所有表共用一个连接,大表阻塞会拖垮全链路。我们线上有个库含137张表,其中3张日增千万级,其余多为配置表。用2.x时,那3张大表的binlog解析常卡住,导致小表变更延迟超5分钟;切到3.0后,通过scan.incremental.snapshot.enabled=true开启增量快照,并为大表单独配置scan.incremental.snapshot.chunk.size=100000,小表延迟稳定在800ms内,大表也压到了1.8秒。

3. 核心细节解析与实操要点

3.1 MySQL端必须做的五项硬性配置

Flink CDC 3.0对MySQL的要求比2.x更严格,漏掉任何一项都可能让任务启动失败或中途挂掉。这不是“建议”,而是生产环境血泪教训总结的硬门槛:

  1. 必须开启binlog且格式为ROW

    -- 检查当前设置 SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'binlog_format'; -- 若未开启,修改my.cnf后重启 [mysqld] log-bin=mysql-bin binlog-format=ROW server-id=1 -- 必须唯一,且不能为0
  2. 必须创建专用同步账号并授予最小必要权限

    提示:绝不能用root或DBA账号!我们曾因权限过大导致Flink CDC误删MySQL表。正确做法是创建只读账号,并显式授权:

    CREATE USER 'flink_cdc'@'%' IDENTIFIED BY 'StrongPass123!'; GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'flink_cdc'@'%'; FLUSH PRIVILEGES;

    注意:REPLICATION SLAVE是读取binlog所必需,RELOAD用于执行FLUSH TABLES WITH READ LOCK(全量阶段加锁),SHOW DATABASES用于发现库表结构。

  3. 必须关闭MySQL的GTID(除非你明确需要)
    Flink CDC 3.0默认不兼容GTID模式。如果MySQL已启用GTID,要么在Flink CDC配置中强制指定debezium.database.server.id(不推荐),要么直接关掉GTID:

    -- 检查GTID状态 SHOW VARIABLES LIKE 'gtid_mode'; -- 若为ON,修改my.cnf [mysqld] gtid_mode=OFF enforce_gtid_consistency=OFF
  4. 必须调整binlog过期时间
    默认expire_logs_days=0(永不过期)看似安全,实则危险——磁盘爆满会导致MySQL崩溃。我们设为7天,但Flink CDC任务若因故停机超7天,重启时binlog已被清理,任务必然失败。因此必须监控Seconds_Behind_Master,并在Flink CDC配置中加入容错:

    # flink-conf.yaml execution.checkpointing.interval: 60s execution.checkpointing.tolerable-failed-checkpoints: 3

    这样即使单次checkpoint失败,还有2次重试机会,避免因瞬时网络抖动触发位点丢失。

  5. 必须为大表预建主键或唯一索引
    Flink CDC 3.0的增量快照(Incremental Snapshot)依赖主键分片。若某张表无主键,它会退化为全表扫描,导致锁表时间过长、主库压力飙升。我们曾有一张日志表无主键,Flink CDC启动时执行SELECT * FROM table_name,锁表17分钟,业务方投诉电话打爆运维室。解决方案只有两个:要么加主键(ALTER TABLE log_table ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY FIRST;),要么在Flink CDC配置中排除该表(table-name=database_name\.((?!(log_table)).)*)。

3.2 Doris端建表的关键设计原则

Doris的建表语句不是简单照搬MySQL,字段类型、模型选择、分区策略都直接影响同步性能和查询效率。我们踩过最多坑的就是“类型不匹配”和“分区不合理”。

字段类型映射必须手工校准
MySQL的DATETIME(6)在Flink CDC中解析为TIMESTAMP_LTZ(6),但Doris的DATETIME只支持到秒级精度。若不做转换,微秒部分会被截断,导致数据失真。正确做法是在Flink SQL中显式cast:

INSERT INTO doris_table SELECT id, CAST(create_time AS TIMESTAMP(3)) AS create_time_ms, -- 转为毫秒级 status, amount FROM mysql_source;

同时Doris表对应字段必须声明为DATETIME(3),否则导入报错。

模型选择:Unique Key是实时同步的黄金标准
别被Aggregate或Duplicate模型迷惑。Aggregate适合预聚合报表,Duplicate适合日志类宽表,而Unique Key专为“主键更新”场景设计。建表语句必须包含PROPERTIES("replication_num" = "3"),这是Doris保证高可用的底线。我们曾因漏写此属性,单台BE宕机导致整张表不可查。

分区策略:按天分区+动态添加是王道
不要用MySQL的created_at字段直接做Doris分区键(如PARTITION BY RANGE(create_time)),因为Flink CDC写入是乱序的——早于当前时间的旧数据可能晚到。正确姿势是用Flink的PROCTIME()生成处理时间分区:

CREATE TABLE IF NOT EXISTS doris_orders ( id BIGINT, order_no VARCHAR(64), status TINYINT, amount DECIMAL(12,2), create_time DATETIME(3) ) UNIQUE KEY(id) PARTITION BY RANGE (dt) ( START ("2024-01-01") END ("2024-12-31") EVERY (INTERVAL 1 DAY) ) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES("replication_num" = "3");

注意:dt是虚拟列,需在Flink SQL中生成:

SELECT id, order_no, status, amount, create_time, DATE_FORMAT(PROCTIME(), '%Y-%m-%d') AS dt -- 动态分区键 FROM mysql_orders;

3.3 Flink CDC 3.0作业的核心参数调优

Flink CDC 3.0的配置项多达40+,但生产环境真正需要调的只有7个。其他参数保持默认即可,乱改反而引入不稳定。

参数名推荐值为什么这么设实测影响
scan.incremental.snapshot.enabledtrue启用增量快照,避免全量阶段锁表全量同步时间从42分钟降至3.7分钟
scan.incremental.snapshot.chunk.size50000每次读取的分片行数,太小增加网络往返,太大内存溢出设为10万时,GC频率上升37%,设为5万最稳
server-time-zoneAsia/ShanghaiMySQL时区与Flink时区必须一致,否则时间字段错乱时区不一致导致create_time全错8小时
connect.timeout.ms30000连接MySQL超时时间,太短易断连,太长重试慢设为10秒时,网络抖动导致任务重启率23%
snapshot.fetch.size1024全量阶段每次fetch的行数,影响内存占用与chunk.size配合,1024+50000组合内存占用最均衡
debezium.database.historyio.debezium.relational.history.FileDatabaseHistory历史schema存储方式,文件比数据库更轻量用MySQL存history曾导致history表锁死
debezium.database.history.file.filename/tmp/doris_cdc_history.dathistory文件路径,必须可写路径不存在时任务静默失败,日志无提示

特别强调debezium.database.history.file.filename:这个文件记录了MySQL表结构变更历史(如新增字段、改类型)。Flink CDC重启时会读取它来决定是否需要重新同步全量。我们曾因磁盘满导致该文件写入失败,任务启动后一直报Schema not found for table xxx,排查3小时才发现是磁盘问题。所以务必监控该文件所在分区的磁盘使用率,并设置定时清理(保留最近7天)。

4. 实操过程与核心环节实现

4.1 从零搭建Flink CDC 3.0到Doris的完整流程

整个过程分为5个阶段,每个阶段都有明确交付物和验收标准。我们用一个真实案例演示:将MySQL库shop_db中的orders、users、products三张表,实时同步至Doris库dws。

阶段一:环境准备(耗时≤15分钟)

  • 下载Flink 1.17.2(CDC 3.0官方认证版本)
  • 下载Flink CDC 3.0.0 connector包(flink-cdc-connectors/flink-connector-mysql-3.0.0.jar)
  • 下载Doris Stream Load JDBC驱动(doris-stream-load-sdk-1.1.0.jar)
  • 将三个JAR包放入Flink的lib/目录,重启Flink集群

注意:Flink CDC 3.0.0仅兼容Flink 1.16+,且必须用Java 11编译。我们曾用Flink 1.15部署,任务提交后直接报NoSuchMethodError,降级CDC版本又失去增量快照功能,最终只能升级Flink。

阶段二:MySQL端初始化(耗时≤5分钟)
执行以下SQL(假设已按3.1节完成基础配置):

-- 创建同步账号 CREATE USER 'cdc_sync'@'%' IDENTIFIED BY 'P@ssw0rd2024!'; GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'cdc_sync'@'%'; FLUSH PRIVILEGES; -- 验证binlog状态 SHOW MASTER STATUS; -- 记录File: mysql-bin.000001, Position: 123456789

阶段三:Doris端建表(耗时≤10分钟)
在Doris客户端执行:

-- 创建数据库 CREATE DATABASE IF NOT EXISTS dws; -- 创建orders表(Unique Key模型) CREATE TABLE IF NOT EXISTS dws.orders ( id BIGINT, order_no VARCHAR(64), user_id BIGINT, product_id BIGINT, status TINYINT, amount DECIMAL(12,2), create_time DATETIME(3), update_time DATETIME(3), dt DATE ) UNIQUE KEY(id) PARTITION BY RANGE (dt) ( START ("2024-01-01") END ("2024-12-31") EVERY (INTERVAL 1 DAY) ) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES( "replication_num" = "3", "storage_medium" = "SSD" ); -- 创建users表(同理) CREATE TABLE IF NOT EXISTS dws.users ( id BIGINT, name VARCHAR(128), email VARCHAR(128), phone VARCHAR(20), reg_time DATETIME(3), dt DATE ) UNIQUE KEY(id) PARTITION BY RANGE (dt) ( START ("2024-01-01") END ("2024-12-31") EVERY (INTERVAL 1 DAY) ) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES("replication_num" = "3");

阶段四:编写Flink SQL作业(耗时≤20分钟)
创建mysql_to_doris.sql文件:

-- 设置执行环境 SET 'execution.checkpointing.interval' = '60s'; SET 'execution.checkpointing.tolerable-failed-checkpoints' = '3'; SET 'state.checkpoints.dir' = 'hdfs://namenode:8020/flink/checkpoints/mysql_doris'; -- 创建MySQL CDC源表 CREATE TABLE mysql_orders ( id BIGINT, order_no STRING, user_id BIGINT, product_id BIGINT, status TINYINT, amount DECIMAL(12,2), create_time TIMESTAMP(3), update_time TIMESTAMP(3), PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'mysql-cdc', 'hostname' = 'mysql-prod-01', 'port' = '3306', 'username' = 'cdc_sync', 'password' = 'P@ssw0rd2024!', 'database-name' = 'shop_db', 'table-name' = 'orders', 'server-time-zone' = 'Asia/Shanghai', 'scan.incremental.snapshot.enabled' = 'true', 'scan.incremental.snapshot.chunk.size' = '50000' ); -- 创建Doris目标表(Stream Load方式) CREATE TABLE doris_orders ( id BIGINT, order_no STRING, user_id BIGINT, product_id BIGINT, status TINYINT, amount DECIMAL(12,2), create_time TIMESTAMP(3), update_time TIMESTAMP(3), dt STRING ) WITH ( 'connector' = 'doris', 'fenodes' = 'doris-fe-01:8030', 'table.identifier' = 'dws.orders', 'username' = 'root', 'password' = '', 'sink.properties.format' = 'json', 'sink.properties.read_json_by_line' = 'true' ); -- 执行插入(含动态分区) INSERT INTO doris_orders SELECT id, order_no, user_id, product_id, status, amount, create_time, update_time, DATE_FORMAT(create_time, 'yyyy-MM-dd') AS dt FROM mysql_orders;

阶段五:提交与验证(耗时≤10分钟)

# 提交作业 ./flink run -d -c org.apache.flink.cdc.cli.SqlClient /opt/flink/lib/flink-sql-client_2.12-1.17.2.jar \ -f /path/to/mysql_to_doris.sql # 查看任务状态 ./flink list -a # 应看到Running状态,JobID类似:e7b3a2c1d4e5f6g7h8i9j0k1l2m3n4o5 # 验证数据(Doris客户端) SELECT COUNT(*) FROM dws.orders WHERE dt='2024-06-15'; -- 应与MySQL实时一致 SELECT * FROM dws.orders ORDER BY update_time DESC LIMIT 5; -- 检查最新5条是否及时

4.2 关键环节深度解析:增量快照如何规避锁表?

增量快照(Incremental Snapshot)是Flink CDC 3.0最颠覆性的特性,它解决了传统全量同步必锁表的死结。其原理不是“一次性扫全表”,而是“分片+无锁+事务一致性”。

具体执行分三步:

  1. 分片阶段:Flink CDC根据表主键范围,将全表逻辑切分为N个chunk(如id BETWEEN 1 AND 50000)。每个chunk独立处理,互不影响。
  2. 无锁读取阶段:对每个chunk,Flink CDC先执行SELECT * FROM table WHERE pk >= ? AND pk < ?,但不加任何锁。MySQL的RR隔离级别保证了该查询的快照一致性——即使其他事务在读取过程中修改了数据,本次查询看到的仍是开始时刻的快照。
  3. 事务衔接阶段:当所有chunk读完,Flink CDC会获取当前binlog位点(如mysql-bin.000001:123456789),然后从该位点开始消费增量变更。关键点在于:增量消费的起点,恰好是全量读取完成的那一刻。这样,全量数据与增量数据无缝拼接,既无遗漏也无重复。

我们实测对比:一张1.2亿行的订单表,传统全量同步(SELECT * FROM orders)需锁表23分钟;而增量快照模式下,最大单个chunk耗时仅4.2秒,全程无锁,业务完全无感。唯一要注意的是,chunk size必须合理——设得太小(如1000),网络请求过多,Flink TaskManager GC压力大;设得太大(如50万),单次查询内存占用高,可能OOM。我们通过压测确定5万是平衡点:单chunk内存占用<1.2GB,GC pause<150ms。

4.3 生产环境必备的监控与告警配置

没有监控的实时链路等于裸奔。我们为这套系统配置了三层监控:

第一层:Flink作业级(Prometheus + Grafana)

  • 关键指标:numRecordsInPerSecond(输入QPS)、numRecordsOutPerSecond(输出QPS)、lastCheckpointSize(检查点大小)、checkpointDuration(检查点耗时)
  • 告警规则:若checkpointDuration > 120s持续5分钟,立即告警——这通常意味着MySQL binlog读取变慢或Doris导入瓶颈;若numRecordsInPerSecond突降为0,说明MySQL连接中断。

第二层:MySQL端(Percona Toolkit)

  • 监控Seconds_Behind_Master(主从延迟),阈值设为60秒。超过则触发告警,因为Flink CDC依赖从库binlog,延迟过大会导致同步滞后。
  • 监控Threads_connected,若持续>300,说明Flink CDC连接泄漏(常见于配置了过多表但未合理复用连接)。

第三层:Doris端(Doris WebUI + 自定义脚本)

  • 在Doris FE节点部署脚本,每5分钟执行:
    curl "http://doris-fe-01:8030/api/dws/orders/compaction?status=publish" | jq '.status' # 若返回"failed",说明Compaction异常,需人工介入
  • 监控be.disk.used_capacity,当单台BE磁盘使用率>85%时告警——Doris的Stream Load会先写本地磁盘再异步刷BE,磁盘满会导致导入失败。

我们曾因没配Doris磁盘监控,在一次促销活动期间BE磁盘打满,新数据无法写入,但Flink任务仍在Running状态,直到业务方发现大屏数据停滞才上报。现在这套监控体系已实现98%的故障自动发现,平均MTTD(平均故障检测时间)压缩至1.8分钟。

5. 常见问题与排查技巧实录

5.1 典型问题速查表

问题现象可能原因排查命令/步骤解决方案
任务启动报java.sql.SQLException: Access denied for userMySQL账号权限不足或密码错误mysql -u cdc_sync -p -h mysql-prod-01测试登录重新执行GRANT语句,确认密码无特殊字符(如@需URL编码)
任务Running但Doris无数据写入Doris Stream Load认证失败查看Flink TaskManager日志,搜索StreamLoadFailedException检查Doris FE的fe.log,确认enable_stream_load为true;若用密码,确保password参数非空字符串
数据延迟突然飙升至30秒+MySQL从库复制延迟SHOW SLAVE STATUS\G查看Seconds_Behind_Master优化从库SQL线程,或临时将Flink CDC指向主库(仅应急)
Flink WebUI显示Checkpoint失败Checkpoint超时或StateBackend异常./flink list -r查看最近失败原因增加state.checkpoints.dir磁盘空间;调大execution.checkpointing.timeout: 300s
Doris查询返回Tablet not foundBE节点宕机或Tablet损坏curl "http://doris-fe-01:8030/api/tablet?tablet_id=12345"执行ADMIN CHECK TABLET修复,或重启对应BE节点

5.2 三个血泪教训换来的独家避坑技巧

技巧一:DDL变更必须人工介入,Flink CDC 3.0不自动同步
Flink CDC 3.0能捕获MySQL的ALTER TABLE ADD COLUMN事件,但它不会自动修改Doris目标表结构。我们曾遇到:MySQL给orders表加了pay_time DATETIME字段,Flink CDC日志里能看到ADD_COLUMN事件,但Doris表没变,导致后续所有insert因字段数不匹配而失败。解决方案是建立DDL变更审批流程:MySQL DBA执行DDL后,必须通知数据平台,由专人执行DorisALTER TABLE ADD COLUMN,并重启Flink作业(因Source表结构已变)。我们为此开发了轻量脚本,监听Flink CDC日志中的ALTER关键字,自动邮件通知负责人。

技巧二:时间字段必须统一时区,否则凌晨数据全乱
MySQL服务器时区为CST(中国标准时间),但Flink集群部署在AWS东京区,JVM默认时区是JST。Flink CDC读取DATETIME字段时,会按JVM时区解析,导致所有时间+1小时。例如MySQL存的是2024-06-15 01:30:00,Flink解析成2024-06-15 02:30:00,Doris存储后,凌晨1点的订单全算到2点去了。根治方法是在Flink启动脚本中强制指定时区:

# flink-start.sh export FLINK_ENV_JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ./flink-daemon.sh start standalone-job

同时在Flink SQL中所有时间函数显式指定时区:DATE_FORMAT(create_time, 'yyyy-MM-dd HH:mm:ss', 'Asia/Shanghai')。

技巧三:大表同步必须配scan.newly-added-table.enabled=false
Flink CDC 3.0默认开启新表自动发现(scan.newly-added.table.enabled=true)。这在测试环境很爽,但生产环境是灾难——某天DBA误操作新建了一张tmp_test_20240615表,Flink CDC自动将其纳入同步,因该表无主键,触发全表扫描,锁表19分钟,业务报警。此后我们所有生产作业都显式关闭此开关,并在Flink SQL中用正则精确指定表名:'table-name' = 'shop_db\.(orders|users|products)'。正则表达式必须用双反斜杠转义点号,否则shop_db.orders会被当成字面量匹配失败。

5.3 性能压测实录:单任务最高支撑多少QPS?

我们用真实业务数据做了三轮压测,结论很明确:瓶颈不在Flink,而在Doris的Stream Load吞吐。测试环境:Flink 1.17.2(3 TM,各8核16G),MySQL 5.7(主库,32核64G),Doris 2.0(1 FE + 3 BE,各16核32G)。

  • 第一轮:10万QPS
    Flink Source端numRecordsInPerSecond稳定在102,345,Doris端load_bytes达1.2GB/min,CPU使用率68%,一切正常。

  • 第二轮:20万QPS
    Flink端无压力,但Doris BE节点磁盘IO达92%,be.disk.write_bytes峰值1.8GB/s,开始出现StreamLoad Timeout错误,失败率0.3%。

  • 第三轮:30万QPS(极限)
    Doris BE磁盘IO 100%,be.disk.write_iops超限,Stream Load失败率飙升至12%,Flink任务因背压触发反压,numRecordsOutPerSecond跌至8万。

最终我们确定单任务安全上限为15万QPS。若需更高吞吐,方案只有两个:一是Doris BE扩容(加机器),二是Flink作业拆分——按业务域分多个任务(如订单流、用户流、商品流),各自独立同步。我们选择后者,因为业务耦合度低,拆分后运维更清晰,故障隔离性更好。

6. 后续可扩展方向与个人经验沉淀

这套MySQL到Doris的Streaming ETL跑稳之后,我们很快把它变成了团队的“数据底座模板”。现在新业务接入,只需改3个地方:MySQL连接信息、表名正则、Doris目标库,15分钟就能跑通一条新链路。但真正的价值延伸在三个方向:第一,我们基于它构建了实时数据质量监控——在Flink SQL中加入COUNT(*) OVER (ORDER BY proc_time RANGE BETWEEN INTERVAL '1' MINUTE PRECEDING AND CURRENT ROW),每分钟统计各表写入量,若低于基线值50%,自动触发告警并推送钉钉;第二,把Doris作为实时特征仓库,训练好的风控模型直接从Doris查最新用户行为特征,响应时间从分钟级降到毫秒级;第三,探索跨源联邦查询,用Doris的MySQL外表功能,把MySQL冷数据和Doris热数据联合分析,避免数据搬迁。

我个人在实际操作中的体会是:实时ETL从来不是技术炫技,而是对“确定性”的极致追求。Flink CDC 3.0的价值,不在于它多酷,而在于它把过去需要3个人盯、5个脚本轮询、7种监控告警才能勉强维持的链路,压缩成一个配置文件+一次提交。当你深夜收到告警,打开Flink WebUI看到Checkpoint绿色滚动,Doris查询秒出结果,那一刻你会明白——所谓技术红利,就是把曾经的“人肉运维”变成“静默运行”。最后分享一个小技巧:每次上线新任务前,我必做三件事——查MySQL主从延迟、清空Doris目标表、在Flink SQL里加一句LIMIT 100测试数据流向,这三分钟能帮你避开80%的线上事故。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询