从 Flink 到 Doris 的实时数据写入实践——基于 Flink CDC 构建更实时高效的数据集成链路

作者:SelectDB日期:2025/11/19

Flink-Doris-Connector 作为 Apache Flink 与 Doris 之间的桥梁,打通了实时数据同步、维表关联与高效写入的关键链路。本文将深入解析 Flink-Doris-Connector 三大典型场景中的设计与实现,并结合 Flink CDC 详细介绍了整库同步的解决方案,助力构建更加高效、稳定的实时数据处理体系。

一、Apache Doris 简介

Apache Doris 是一款基于 MPP 架构的高性能、实时的分析型数据库,整体架构精简,只有 FE 、BE 两个系统模块。其中 FE 主要负责接入请求、查询解析、元数据管理和任务调度,BE 主要负责查询执行和数据存储。Apache Doris 支持标准 SQL 并且完全兼容 MySQL 协议,可以通过各类支持 MySQL 协议的客户端工具和 BI 软件访问存储在 Apache Doris 中的数据库。

在典型的数据集成和处理链路中,往往会对 TP 数据库、用户行为日志、时序性数据以及本地文件等数据源进行采集,经由数据集成工具或者 ETL 工具处理后写入至实时数仓 Apache Doris 中,并由 Doris 对下游数据应用提供查询和分析,例如典型的 BI 报表分析、OLAP 多维分析、Ad-hoc 即席查询以及日志检索分析等多种数据应用场景。

Flink-Doris-Connector 是 Apache Doris 与 Apache Flink 在实时数据处理 ETL 的结合,依托 Flink 提供的实时计算能力,构建高效的数据处理和分析链路。Flink-Doris-Connector 的使用场景主要分为三种:

  1. Scan:通常用来做数据同步或是跟其他数据源的联合分析;
  2. Lookup Join:将实时流中的数据和 Doris 中的维度表进行 Join;
  3. Real-time ETL:使用 Flink 清洗数据再实时写入 Doris 中。

二、Flink-Doris-Connector 典型场景的设计与实现

本章节结合 Scan、Lookup Join、Write 这三种场景,介绍 Flink-Doris-Connector 的设计与实现。

01 Scan 场景

Scan 场景指将 Doris 中的存量数据快速提取出来,当从 Doris 中读取大量数据时,使用传统的 JDBC 方法可能会面临性能瓶颈。因此 Flink-Doris-Connector 中可以借助 Doris Source ,充分利用 Doris 的分布式架构和 Flink 的并行处理能力,从而实现了更高效的数据同步。

Doris Source 读取流程

  • Job Manager 向 FE 端发起请求查询计划,FE 会返回要查询的数据对应的 BE 以及 Tablet;
  • 根据不同的 BE,将请求分发给不同的 TaskManager;
  • 通过 Task Manager 直接读取每个 BE 上对应 Tablet 的数据。

通过这种方式,我们可以利用 Flink 分布式处理的能力从而提高整个数据同步的效率。

02 Lookup Join 场景

对于维度表存储在 Doris 中的场景,可通过 Lookup Join 实现对实时流数据与 Doris 维度表的关联查询。

JDBC Connector

Doris 支持 MySQL 协议,所以可以直接使用 JDBC Connector 进行 Lookup Join,但是这一方式存在一定的局限:

  • Jdbc Connector 中的 Lookup Join 是同步查询的操作,会导致实时流中每条数据都要等待 Doris 查询的结果,增加了延迟。
  • 仅支持单条数据查询,在上游数据量吞吐较高时,容易造成性能瓶颈和反压。

Flink-Doris-Connector 的优化

因此针对 Lookup Join 场景 ,Flink-Doris-Connector 实现了异步 Lookup Join 和攒批查询的优化:

  • 支持异步 Lookup Join: 异步 Lookup Join 意味着实时流中的数据不需要显式等待每条记录的查询结果,可以大大的降低延迟性。
  • 支持攒批查询: 将实时流的数据追加到队列 Queue 中,后台通过监听线程 Watcher,将队列里面的数据取出来再推送到查询执行的 Worker 线程池中,Worker 线程会将收到的这一批数据拼接成一个 Union All 的查询,同时向 Doris 发起 Query 查询。

通过异步 Lookup join 以及攒批查询,可以在上游数据量比较大的时候大幅度提高维表关联吞吐量,保障了数据读取与处理的高效性。

03 实时 ETL 场景

对于实时写入来说,Doris Sink 的写入是基于 Stream Load 的导入方式去实现的。Stream Load 是 Apache Doris 中最为常见的数据导入方式之一,支持通过 HTTP 协议将本地文件或数据流导入到 Doris 中。主要流程如下:

  • Sink 端在接收到数据后会开启一个 Stream Load 的长链接请求。在 Checkpoint 期间,它会将接收到的数据以 Chunk 的形式持续发送到 Doris 中。
  • Checkpoint 时,会对刚才发起的 Stream Load 的请求进行提交,提交完成后,数据才会可见。

如何保证数据写入的 Exactly-Once 语义

那么,如何保证数据写入期间,端到端数据的精确一次性?

以 Kafka 同步到 Drois 的 Checkpoint 过程为例:

  1. Checkpoint 时,Source 端会接收到 Checkpoint Barrier;
  2. Source 端接收到 Barrier 后,首先会对自身做一个快照,同时会将 Checkpoint Barrier 下发到 Sink 端;
  3. Sink 端接收到 Barrier 后,执行 Pre-commit 提交,成功后数据就会完整写入到 Doris,由于此处执行的是预提交,所以在 Doris 上,此时对用户来说数据是不可见的;
  4. 将 Pre-Commit 成功的事务 ID 保存到状态中;
  5. 所有的算子 Checkpoint 都做完后,Job Manager 会下发本次 Checkpoint 完成的通知;
  6. Sink 端会对刚才 Pre-commit 成功的事务进行一次提交。

通过这种两阶段提交,就可以实现端到端的精确一次性。

实时性与 Exactly-Once

上面提到,Doris Sink 端的写入与 Checkpoint 绑定,数据写入 Doris 的延迟性取决于 Checkpoint 的间隔。但在一些用户的场景下,希望数据可以实时写入,但是 Checkpoint 不能做的太频繁,同时对于一些作业来说,如果 Checkpoint 太频繁会消耗大量资源,针对该情况,Flink-Doris-Connector 引入了攒批机制,以平衡实时性与资源消耗之间的矛盾。

攒批的实现原理是 Sink 端接收上游数据之后,不会立即将每条数据单独写入 Doris,而是先在内存中进行缓存,然后通过对应参数设置,将缓存数据提交到 Doris 中。结合攒批写入和 Doris 中的主键模型,可以确保数据写入的幂等性。

通过引入攒批机制,既满足了用户对数据实时写入的需求,又避免了频繁 Checkpoint 带来的资源消耗问题,从而实现性能与效率的优化。

三、基于 Flink CDC 的整库同步方案

以上是对 Flink-Doris-Connector 的典型场景和实现原理介绍,接下来我们来看它在实际业务中的一个重要应用——整库同步。相比底层实现,整库同步更偏向具体使用场景。下面我们基于前面介绍的能力,进一步探讨如何通过 Flink CDC 实现 TP 数据库到 Doris 的高效、自动化同步。

01 整库同步痛点

在数据迁移过程中,用户通常希望可以尽快将数据迁移到 Doris 中,然而在同步 TP 数据库时,整库同步往往面临以下几点挑战:

  • 建表:
    • 存量表的快速批量创建:TP 数据库中往往存在成千上万的表,这些表的结构各异,对于存量表而言需要逐一在 Doris 中创建对应的表结构;
    • 同步任务开启后,新增表的自动创建与同步: 为了保证数据的完整性和实时性,同步工具需要实时监控 TP 数据库的变化,并自动在 Doris 中创建和同步新表。
  • 元数据映射: 上下游之间字段元数据的便捷映射,包括字段类型的转换、字段名称的对应修改等。
  • DDL 自动同步: 增加、删除列等操作会导致数据库结构发生变化,进而影响到数据同步。因此,同步工具需要能够实时捕获 DDL 并动态地更新 Doris 表结构,以确保数据的准确性和一致性。
  • 开箱即用: 零代码,低门槛,理想的同步工具只需进行简单配置,即可实现数据的迁移和同步。

02 基于 Flink CDC 实现整库同步

在数据抽取方面,Flink-Doris-Connector 借用了 Flink CDC 的特性能力:

  • 增量快照读取
    • 无锁读取与并发读取:不论存量数据量多大,都可以通过横向提高 Flink 的并发提升数据读取速度。
    • 断点续传:当存量数据比较大时,可能面临同步中断的情况,CDC 支持中断任务的衔接同步。
  • 丰富数据源支持,Flink CDC 支持多种数据库,如 MySQL、Oracle、SQLServer 等。
  • 无缝对接 Flink 现有生态,方便与 Flink 已有Source 和 Sink 结合使用。

一键建表与元数据自动映射

Flink-Doris-Connector 中集成了 Flink CDC 等能力,可以让用户只提交一个操作,就能进行整库同步的操作。其主要原理是 Flink CDC Source 在接收到上游的数据源之后,会进行分流处理,不同的表用不同的 Sink。同时在最新的 Connector 版本中,也支持单个 Sink 同步多张表,支持新增表的创建和同步。

集成 Flink CDC 的功能后,用户仅需通过 Flink-Doris-Connector 提交任务,就可以在 Doris 自动创建所需的表,而无需配置上下游表之间的显式关联,实现数据快速同步

当 Flink 任务启动后,Doris-Flink-Connector 将自动识别对应的 Doris 表是否存在。如果表不存在,Doris Flink Connector 会自动创建表,并根据 Table 名称进行分流,从而实现下游多个表的 Sink 接入;如果表存在,则直接启动同步任务。

这一改进,不仅简化了配置流程,还使得新增表的创建和同步更加便捷,从而提升数据处理的整体效率。

Light Schema Change 与 DDL 自动同步

在 Apache Doris 1.2 版本之前,Schema Change 操作比较繁琐,需要手动增改数据列。在上游 TP 数据库发生表结构变更时,需要暂停数据同步任务、待 Doris 中的 Schema Change 完成后再重启任务。

自 Apache Doris 1.2 版本起,我们引入了轻量级的 Light Schema Change 机制,极大地简化了操作流程,常见的增减列场景其处理速度可达毫秒级。Light Schema Change 机制原理如下:

  • Schema Change:
    • 客户端向 FE 发起增减列的请求;
    • FE 在接收到请求后,修改当前元数据,并将最新的 Schema 持久化;
    • FE 向客户端同步 Schema Change 的结果;
  • Data Load:
    • 当后续导入任务发起时,FE 将导入任务与最新的 Schema 信息发送给 BE;
    • 在数据写入过程中,BE 的每个 Rowset 都会存储当前导入的 Schema 信息;
  • Query:
    • FE 将查询计划与最新的 Schema 一起发送给 BE;
    • BE 使用最新 Schema 执行查询计划;
  • Compaction:
    • 在 BE 中,对参与合并的 Rowset 版本进行比较;
    • 根据最新的 Schema Change 信息进行数据合并。

经测试,与早期的 Schema Change 相比,Light Schema Change 的数据同步性能有了数百倍的提升,

Light Schema Change 与 Flink-Doris-Connector 的结合,通过 Flink CDC 可以实现 DDL 的自动同步,具体步骤如下:

  1. Source 端捕获上游 Schema Change 信息,开启 DDL 变更同步;
  2. Doris Sink 端识别并解析 DDL 操作(加减列);
  3. Table 校验,判断是否可以进行 Light Schema Change;
  4. 发起 Schema Change 操作;

基于这一实现,Doris 能自动获取到 DDL 语句并在毫秒级即可完成 Schema Change 操作,在上游 TP 数据库发生表结构变更时,数据同步任务无需暂停。

开箱即用:MySQL 整库同步示例

对于用户来讲,只要有 Flink 客户端,通过上图的操作就可以提交整库同步作业。支持传入 Flink 的配置,比如并发设置、Checkpoint 间隔等,也支持正则表达式去配置需要同步的表, 同时可以将 Flink CDC Source 和 Doris Sink 的配置直接透传给具体的 Connector。通过这种方式,用户可以很便捷地提交整库同步作业。

03 Flink-Doris-Connector 核心优势

基于以上优化,可以完美解决用户的痛点:

  1. 自动建表,即存量表与增量表的自动创建,无需用户提前在 Doris 中预先创建对应的表结构;
  2. 自动映射上下游字段,无需手动写入上下游字段间的匹配规则,节省大量人力成本;
  3. 增减列无感同步,及时获取上游 DDL 语句并自动在 Doris 中实现毫秒级 Schema Change,无需停服、数据同步任务平稳运行;
  4. 开箱即用,降低学习成本,更专注业务本身。

04 最佳实践

在生产环境中,若作业数量较多,直接采用上述提交方式的作业管理复杂度较高。通常建议借助任务托管平台(如 StreamPark),实现对作业的统一创建、监控与运维,从而提升任务管理效率与系统稳定性。

四、未来规划

未来,基于 Flink-Doris-Connector 的能力规划如下:

  1. 支持实时读取。目前 Doris Source 只是把数据 Scan 出来,是一个有界流的读取,后续会支持 CDC 的场景,可以使用 Flink 来对 Doris 中的数据进行流式的读取。
  2. Sink 一流多表。目前Flink-Doris-Connector支持单个 Sink 同步多张表,但是 Stream Load 的导入方式还是只支持单个表的导入。所以在表特别多的时候,需要在 Sink 端维护大量 StreamLoad 的连接,在后续会做到单个 Stream Load 的连接支持多张表的写入。
  3. 整库同步方面,支持更多的上游数据源,满足更多数据同步场景。

从 Flink 到 Doris 的实时数据写入实践——基于 Flink CDC 构建更实时高效的数据集成链路》 是转载文章,点击查看原文


相关推荐


Vue 3.0 源码解读
艾光远2025/11/18

1. 工程架构设计 Vue 3 是一个现代化的前端框架,采用模块化设计,源码项目被划分为多个模块,每个模块负责不同的功能。 1.1. compiler-core compiler-core 是 Vue 3 的编译核心模块,主要负责将模板转换为渲染函数。其模块如下: Parser(解析器):将模板字符串解析成抽象语法树(AST)。 Transform(转换器):遍历 AST,进行必要的转换,比如处理指令、插值、事件等。 Codegen(代码生成器):将转换后的 AST 转换成 Jav


用 Rust 构建 Git 提交历史可视化工具
掘金者阿豪2025/11/17

在软件开发中,版本控制系统的历史记录往往承载着项目的演进脉络。然而,当项目规模扩大、分支增多时,纯文本的 git log 输出很难直观地展现提交之间的复杂关系。今天,我想分享一个用 Rust 构建的轻量级工具 —— git-graph-rs,它能把 Git 仓库的提交历史转换为可视化的图结构,为代码审查、项目复盘和工程决策提供直观的支持。 @TOC 为什么需要可视化? 在参与大型项目时,我经常会遇到这样的场景: 需要快速了解某个功能分支的合并路径 在代码审查时想知道某个提交在整体历史中的位置


Python 的内置函数 oct
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 oct Python 的内置函数 oct() 用于将一个整数转换为八进制(以 8 为基数)字符串表示形式。该函数返回的字符串以 0o 为前缀,表示这是一个八进制数。 语法 oct(x) 参数 x:必须是一个整数(可以是十进制、二进制、十六进制或其他形式的整数)。如果 x 不是整数,则需要先实现 __index__() 方法返回一个整数。 返回值 返回一个以 0o 为前缀的八进制字符串。 示例 十进制转八进制 prin


【大模型】重磅升级!文心 ERNIE-5.0 新一代原生全模态大模型,这你都不认可它吗?!
南方者2025/11/14

🧩 前言速读 11 月 13 日,2025百度世界大会上,新一代「原生全模态」大模型文心 5.0 正式亮相,2.4 万亿参数量,采用原生全模态统一建模技术,具备全模态理解与生成能力,支持「文本、图像、音频、视频」等多种信息的输入与输出,将国内大模型竞争力推向全球顶尖水准。 大会上强调:“智能本身是最大的应用,技术迭代速度是唯一的护城河”,而文心 5.0 正是这一理念的最新实践 —— 它不仅是参数规模的跃升,更标志着 AI 从 “单模态处理” 迈入 “原生多模态融合” 的新阶段。 接下来,让


OpenCVSharp:ArUco 标记检测与透视变换
mingupup2025/11/13

前言 对于.NET开发者而言,入门OpenCV的一个很舒适的方式就是先去使用OpenCVSharp,它是 OpenCV 的 .NET 封装,而且作者还开源了一个示例库,可以通过示例库进行入门学习。 OpenCVSharp仓库地址:github.com/shimat/open… opencvsharp_samples仓库地址:github.com/shimat/open… 作者提供了几十个可以直接运行的示例代码,一开始可以先大概运行一下这些示例,看一下用这个库可以实现哪些功能。 入门第一步就是


🚀 MateChat发布V1.10.0版本,支持附件上传及体验问题修复,欢迎体验~
2025/11/12

✨ 本期亮点 最新发布的 MateChat V1.10.0 版本新增文件列表组件和重新生成功能等特性,希望这个版本为你带来全新的体验! 🎯 核心功能升级(新特性) 🔄 新增文件列表组件 1、基本用法 McFileList 组件的核心功能是接收一个文件对象数组,并将它们渲染为信息卡片。通过 fileItems 属性传入数据,并可使用 context 属性控制其在不同场景下的外观,详情点击文件列表组件Demo 2、不同上下文与状态 McFileList 提供了两种上下文模式和多种文件状态,以适


Service Worker 深度解析:让你的 Web 应用离线也能飞
前端嘿起2025/11/10

在现代 Web 开发中,用户体验已经成为了衡量一个应用成功与否的重要标准。用户不仅希望网站加载速度快,还希望即使在网络不稳定或完全断网的情况下也能正常使用应用。这就引出了我们今天的主角——Service Worker。 前言 Service Worker 是一种在浏览器后台运行的脚本,它独立于网页主线程,可以拦截网络请求、缓存资源,甚至在离线状态下也能提供完整的用户体验。它是实现 PWA(渐进式 Web 应用)的核心技术之一,为 Web 应用带来了原生应用般的离线能力。 在本文中,我们将从基础


Thread.sleep 与 Task.sleep 终极对决:Swift 并发世界的 “魔法休眠术” 揭秘
大熊猫侯佩2025/11/8

📜 引子:霍格沃茨的 “并发魔咒” 危机 在霍格沃茨城堡顶层的 “魔法程序与咒语实验室” 里,金色的阳光透过彩绘玻璃洒在悬浮的魔法屏幕上。哈利・波特正对着一段闪烁着蓝光的 Swift 代码抓耳挠腮,罗恩在一旁急得直戳魔杖 —— 他们负责的 “魁地奇赛事实时计分器” 又卡住了。 赫敏抱着厚厚的《Swift 并发魔法指南》凑过来,眉头紧锁:“肯定是上次加的‘休眠咒语’出了问题!我早就说过 Thread.sleep 像‘摄魂怪的拥抱’,会吸干线程的活力,你们偏不信!” 这时,实验室的门 “吱呀”


Godot游戏开发——C# (一)
云缘若仙2025/11/6

1. 素材管理 核心内容:明确游戏开发所需基础素材类型,为场景与节点提供资源支撑,具体包括: AssetBundle:资源打包容器,用于统一管理与加载资源; Audio 音频素材:提供游戏音效、背景音乐等音频资源; Sprites 精灵图片素材:提供角色、道具、场景元素等可视化图片资源。 2. 场景树与核心节点 节点类型 功能描述 Root Node(根节点) 场景树顶层节点,所有子节点均嵌套于其下,构成场景层级框架的基础。


高并发电商架构设计与落地:从微服务拆分到全链路优化
kennylee262025/10/31

一、交易核心 - 高并发订单的生成与落地 1.1 引言:为什么“收单”是系统的生命线 在电商体系中,交易是核心,而订单是起点。一个高效、稳定的收单系统,决定了平台的承载能力与用户体验。在高并发场景(如秒杀、大促)下,系统的挑战早已超越传统的“增删改查”,转向对性能极限、数据一致性与弹性扩展的全面考验。本章将解析如何通过微服务拆分与架构优化,构建一个能从容应对瞬时流量洪峰的订单处理系统。 1.2 架构总览:微服务拆分与职责边界 微服务架构的核心价值在于解耦、弹性伸缩与容错。在订单处理流程中

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读