提示:1. 实时管道&实时任务架构
实时管道模块中,数据同步的实现为「采集任务 +实时管道」的协同工作模式。这种模式将数据同步流程解耦为三个独立的逻辑层次:读取层、传输层和写入层,显著提升了系统的可靠性、可扩展性和可维护性。

1.1 核心架构:解耦的三层模型说明
1.1.1 读取层:采集任务
采集任务详情说明请参见:实时采集任务
| 逻辑 | 说明 |
|---|---|
| 核心组件 | 读取端 (Reader) |
| 职责定义 |
|
| 关键产出 | 将捕获到的数据库变更事件,封装成标准化的消息格式(通常为 JSON),然后将其发布到传输层的消息队列中 |
| 生命周期与断点 | 采集任务自身维护着一个关键的状态——解析断点 (Parsing Breakpoint)
|
1.1.2 传输层:传输队列
详情请参见:缓存配置
| 逻辑 | 说明 |
|---|---|
| 核心组件 | 以 Apache Kafka 为例的消息队列系统 使用实时管道/实时任务模块,需要部署启动 Kafka:部署Kafka:ZooKeeper模式、部署Kafka:KRaft模式 |
| 职责定义 | 作为读取层和写入层之间的缓冲数据总线,负责可靠地存储和分发数据变更消息。它接收来自采集任务的所有消息,并按照先进先出(FIFO)的原则为写入端提供消费 |
| 关键特性 |
|
1.1.3 写入层
FineDataLink 创建的 实时任务/实时管道 任务。
| 逻辑 | 说明 |
|---|---|
| 核心组件 | 写入端 (Writer) |
| 职责定义 | 实时管道/实时任务的核心职责是消费传输队列中的消息,并准确地将数据变更应用到目标端数据库 它作为消息队列的消费者,持续拉取消息,解析后生成对应目标的 DML 语句并执行 |
| 生命周期与断点 | 实时管道/实时任务同样维护着一个独立的断点——消费断点 (Consumption Breakpoint)
|
1.2 三层架构的优势
优势一:解耦
读写分离:读取端和写入端的处理逻辑、技术选型、开发部署和运维都可以完全独立。读取端的故障(如源库连接问题)不会直接导致写入端停止,反之亦然。
环境隔离:源端和目标端的网络、资源可以有效隔离,仅通过传输队列进行交互,提升了系统整体的稳定性。
优势二:可靠性与容错
数据缓冲:传输队列作为强大的数据缓冲池,即使写入端或目标库出现长时间故障,数据也能在队列中安全积压,待恢复后继续处理,避免了数据丢失。
独立恢复:双断点机制使得读取端和写入端可以独立恢复。写入失败只需从上次的消费断点重试,无需重新从源端读取数据,大大提高了恢复效率。
优势三:性能与弹性
削峰填谷:当源端产生突发的数据洪流时(如批量更新),传输队列可以有效吸收峰值压力,允许写入端按照自己的节奏平稳地消费数据,保护目标库免受冲击。
独立扩展:如果写入目标端成为瓶颈,可以独立增加管道(写入端)的并发实例(消费者),共同消费队列中的数据,从而水平扩展写入能力,而无需对读取端做任何改动。
优势四:灵活性与可扩展性
一读多写:这是该架构最具价值的特性之一。一个采集任务可以将数据发布到传输队列,多个不同的管道可以订阅同一个数据流,将数据同步到不同的目的地(如:一份写入数据仓库进行分析,一份写入 Elasticsearch 进行搜索,一份写入 Redis 作为缓存),轻松实现数据的多场景复用。
1.3 数据变更示例说明
为了更具体地理解第一章中的机制说明,我们以源数据库中一张用户表的一条 UPDATE 操作为例,追踪它的完整旅程。
1)源端变更
在源数据库中,执行UPDATE users SET age = 30 WHERE id = 123;语句,并提交事务。
该变更被记录在数据库的事务日志中。
2)采集任务 (读取端) 捕获
采集任务的 Reader 实时监控并解析事务日志,捕获到这条 UPDATE 操作的详细信息(包括变更前后的数据镜像)。
Reader 将其封装成一个标准化的JSON消息,例如:
{
"op": "u",
"schema": "public",
"table": "users",
"before": {"id": 123, "age": 29},
"after": {"id": 123, "age": 30}
}
Reader 将此消息发送到 Kafka 的指定 Topic 中。
3)传输队列 (Kafka) 存储
Kafka 接收到消息,将其追加到对应 Topic 的一个分区末尾,并为其分配一个唯一的偏移量 (Offset),例如 offset: 4567。
消息在此处被持久化。
采集任务在收到 Kafka 的成功确认后,更新自己的解析断点至该 UPDATE 操作之后的位置。
4) (写入端) 消费与应用
实时管道/实时任务的 Writer 作为消费者,从 Kafka Topic 拉取到 offset: 4567 的这条消息。
Writer 解析消息内容,识别出这是一个针对 users 表的更新操作。
它将此消息转换为目标数据库支持的 UPDATE 或 MERGE 语句。
Writer 在目标数据库上成功执行该语句。
5)断点更新与确认
目标数据库确认写入成功后,实时管道/实时任务向 Kafka 提交 (Commit) 其最新的消费断点,更新为 offset: 4567。
至此,这条 UPDATE 操作的数据同步宣告完成。整个过程通过两个独立的断点机制,确保了端到端的数据一致性和可靠性。
1.4 常见问题
Q:为什么需要中间的传输队列?采集任务直接读取源数据,然后写入目标库不行吗
直接读写是一种紧耦合的模式,存在诸多弊端。引入传输队列(如Kafka)的核心价值在于解耦和可靠性
解耦:它将读(采集)和写(管道)彻底分开。如果目标库宕机或写入缓慢,采集任务可以继续从源库读取数据存入队列,不受影响。
可靠性:队列是持久化的。即使整个写入端服务崩溃,数据依然安全地存储在队列中,待服务恢复后可继续处理,避免了数据丢失。
性能缓冲:队列可以吸收源端突发的写入高峰,让写入端可以平稳地处理,避免冲击目标数据库。
架构灵活性:为“一读多写”等高级场景提供了可能。
Q:如果管道(写入端)或目标数据库宕机了,数据会丢失吗?管道原理如何保证这一点
数据不会丢失。这得益于传输队列的持久化和消费断点机制
当写入端宕机时,采集任务仍在正常工作,数据变更消息会持续发送并积压在Kafka中。因为Kafka是持久化的,所以消息是安全的。
写入端在每次成功将一批数据写入目标库后,会向Kafka提交它已经处理完的消息的偏移量(即消费断点)。
当写入端或目标库恢复并重启后,管道会根据之前保存的消费断点,从Kafka中它上次中断的地方继续拉取消息进行处理。这样既不会丢失数据,也避免了重复写入。
Q:“解析断点”和“消费断点”到底有什么区别
它们是两个完全独立的检查点,分别服务于链路的不同部分:
解析断点 (Parsing Breakpoint):属于 采集任务(读取端)。它记录的是“我从源头(如Binlog)已经读到哪里了”。它的作用是确保采集任务重启后,能从正确的位置继续读,不会漏掉源头的任何变更。
消费断点 (Consumption Breakpoint):属于 管道(写入端)。它记录的是“我从传输队列(Kafka)已经处理到哪条消息了”。它的作用是确保管道重启后,能从正确的位置继续 消费,不会重复处理已经成功写入目标库的数据。
Q:这个架构如何实现“一个源头,多个去向”(一读多写)
该架构天然支持此场景。您可以:
1)配置 一个采集任务,负责从您的核心源数据库(如订单库)读取数据,并将所有变更消息发布到一个统一的Kafka Topic(如 orders-topic)。
2)然后,您可以创建 多个 独立的实时管道任务:
管道A:订阅 orders-topic,将数据写入数据仓库(如Hive/ClickHouse)用于BI分析。
管道B:订阅同一个 orders-topic,将数据写入Elasticsearch,为前端提供订单搜索功能。
管道C:订阅同一个 orders-topic,将关键订单状态变更写入Redis,用于实时状态通知。
每个管道有自己独立的消费断点,它们互不干扰地消费同一份数据流。
