You need to enable JavaScript to run this app.
文档中心
流式计算 Flink版

流式计算 Flink版

复制全文
下载 pdf
Connector 参考
TOS CDC(公测中)
复制全文
下载 pdf
TOS CDC(公测中)

TOS-CDC SQL Connector 是流式计算 Flink 版提供的源表(Source)连接器,用于持续获取火山引擎对象存储 TOS 中的对象元数据。连接器可先扫描指定路径下的已有对象,再从 Kafka 接收对象创建、删除等事件,将全量快照与增量变化组合为一张持续更新的 Flink SQL 表。

功能概述

类别

详情

支持类型

Source

作业类型

Flink SQL

运行模式

流模式

支持的变更类型

INSERT、DELETE

组件形态

平台内置,无需独立部署

交付语义

At-Least-Once

版本兼容性

组件

支持版本

说明

火山引擎流式计算 Flink 版

  • 1.17
  • 1.20

Connector 已由平台内置,无需上传额外 JAR。

火山引擎对象存储 TOS

暂无版本要求。

特色功能
  • 全量与增量一体化:initial 模式先扫描指定 TOS 路径下的已有对象,再从全量扫描开始时间对应的 Kafka 位点持续消费对象事件,用于构建并维护对象元数据状态。
  • 多种启动位置:支持 initial、snapshot、earliest-offset、latest-offset、group-offsets、timestamp 和 specific-offsets 七种启动模式,可以按需执行全量加增量同步、仅快照读取、增量续读或历史事件回放。
  • 多路径扫描:一个 Source 可以配置同一 TOS Bucket 下的多个 URI。Connector 会对重复路径以及已被父路径覆盖的子路径进行去重,便于统一采集同一 Bucket 内多个目录的对象元数据。
  • 全量和增量独立并行:支持分别配置 TOS 全量快照阶段和 Kafka 增量阶段的并行度,便于根据对象数量、Kafka Partition 数量和作业资源调整处理能力。
  • 消费位点安全回拨:initial 模式支持通过 rewind.offset 将 Kafka 消费起点回拨到全量扫描开始时间之前,降低全量扫描期间对象事件遗漏的风险;同时支持配置 Kafka 历史消息过期时的处理策略。
  • 事件范围校验:默认过滤 Kafka Topic 中不属于当前 Source 范围的对象事件;开启 event.fail-on-out-of-scope 后,可在发现范围外事件时使任务失败,帮助及时发现 Topic 或数据源配置错误。
  • 统一对象元数据 Schema:快照记录与增量事件使用相同的固定 Schema,并通过 record_origin 区分 SNAPSHOT 和 EVENT 来源,便于下游统一处理和排查重复数据。
  • 支持维护对象当前状态:可以将 object_key 声明为逻辑主键,并配合支持 INSERT、DELETE Changelog 的下游 Sink,维护 Bucket 中对象的当前元数据状态。

前提条件
  • 已开通火山引擎对象存储 TOS服务,并创建用于存放待采集对象的 Bucket。
  • 已确认待采集对象所在的 TOS 路径。一个 Source 可以配置同一 Bucket 下的一个或多个 URI,不支持同时读取多个 Bucket。
  • 已为 Flink 作业配置访问目标 Bucket 的权限,确保 Connector 可以列举指定路径下的已有对象并读取对象元数据。
  • 已为目标 TOS Bucket 配置事件通知,并将推送目标设置为消息队列 Kafka 版。事件通知至少应订阅对象创建事件 tos:ObjectCreated:*;如需同步对象删除,还应订阅 tos:ObjectRemoved:*。事件通知规则的 Prefix、Suffix 应覆盖 Source 配置的对象路径。详细操作请参见设置事件通知推送至 Kafka
  • 已确保 Flink 资源池与 TOS、Kafka 之间网络互通,并准备 Kafka Broker 地址、Topic 和 Consumer Group ID。

使用限制

限制项

说明

全量扫描范围

path 可以设置多个 URI,但这些 URI 必须都来自同一个 TOS 存储桶,不允许一个数据源同时从多个存储桶获取数据。

增量事件范围

默认过滤 Kafka Topic 中不属于当前 Bucket 或配置路径范围的事件。设置 event.fail-on-out-of-scope = true 后,遇到范围外事件时作业失败。

变更日志语义

全量快照和增量 PUT 事件输出 INSERT,增量删除事件输出 DELETE,不产生 UPDATE_BEFORE 或 UPDATE_AFTER 消息。

数据一致性

当前采用至少一次(At-Least-Once)语义。故障恢复或通过 rewind.offset 回拨消费位置时,可能产生重复数据。
下游如需精确去重,建议结合业务主键及对象元信息,按业务语义构造去重键。

语法结构

使用 CREATE TABLE 语句创建 TOS-CDC 源表。字段可以按任意顺序声明,也可以只声明需要使用的字段,但必须包含 object_key字段,且必须为STRING NOT NULL。

CREATE TABLE <source_table> (
    object_key    STRING NOT NULL,
    object_url    STRING,
    bucket_name   STRING,
    file_name     STRING,
    object_etag   STRING,
    object_size   BIGINT,
    mtime         TIMESTAMP_LTZ(3),
    event_time    TIMESTAMP_LTZ(3),
    record_origin STRING
    -- PRIMARY KEY (object_key) NOT ENFORCED -- 可选
) WITH (
    'connector' = 'tos-cdc',
    'path' = 'tos://<bucket>/<path>',
    'scan.startup.mode' = '<startup_mode>',
    'topic' = '<kafka_topic>',
    'properties.bootstrap.servers' = '<kafka_broker>',
    'properties.group.id' = '<consumer_group>'
);

固定Schema说明

TOS-CDC SQL Connector 使用固定的对象元数据 Schema。
DDL 可声明下表中的任意字段子集,但 object_key 必须声明为 STRING NOT NULL。

字段

Flink SQL 类型

是否必需

说明

object_key

STRING NOT NULL

是

对象在 Bucket 中的原始 Key,可在单 Bucket 内唯一标识对象。

object_url

STRING

否

根据 Bucket 和 Key 生成的完整 TOS URL,格式为 tos://<bucket_name>/<object_key>。

bucket_name

STRING

否

TOS Bucket 名称。

file_name

STRING

否

从 object_key 中提取的文件名。

object_etag

STRING

否

全量快照或增量事件提供的 ETag;部分事件可能不包含该值。

object_size

BIGINT

否

全量快照或增量事件提供的对象大小,单位为字节。

mtime

TIMESTAMP_LTZ(3)

否

全量快照中的对象修改时间;增量事件中通常为空。

event_time

TIMESTAMP_LTZ(3)

否

增量事件的发生时间;全量快照阶段为空。

record_origin

STRING

否

记录来源。SNAPSHOT 表示全量快照,EVENT 表示 Kafka 增量事件。

WITH参数

通用连接参数

说明

“无默认值”表示连接器不会自动填充该参数。参数是否必填取决于对应的启动模式,详情参见”生效模式“和”说明“列。

参数

类型

默认值

生效模式

说明

connector

STRING

无

全部

必填。固定取值为 tos-cdc。

path

STRING

无

全部

必填。一个或多个 TOS URI,格式为 tos://bucket[/path];多个 URI 使用英文逗号分隔。所有 URI 必须属于同一个 Bucket。
重复路径和被父路径覆盖的子路径会被去重,空格等非法 URI 字符必须编码。

scan.startup.mode

STRING

initial

全部

启动模式。各取值的运行方式和必填参数请参见启动模式。

scan.startup.timestamp-millis

BIGINT

无

timestamp

必填。非负 Unix 时间戳,单位为毫秒;其他模式忽略该参数。

scan.startup.specific-offsets

STRING

无

specific-offsets

必填。格式为 partition:<非负整数>,offset:<非负长整数>,多项使用分号分隔,例如 partition:0,offset:42;partition:1,offset:300。不允许重复配置同一个 Partition。

topic

STRING

无

除 snapshot 外

必填。用于接收 TOS 对象事件通知的 Kafka Topic。

properties.bootstrap.servers

STRING

无

除 snapshot 外

必填。Kafka Broker 地址。

properties.group.id

STRING

无

增量阶段

group-offsets 和 specific-offsets 模式下必填。对于 specific-offsets 未显式配置的当前或后续新增 Partition,连接器会先查询该 Consumer Group 已提交的 Offset。

properties.*

STRING

无

增量阶段

透传给底层 Kafka Consumer 的参数。

snapshot.parallelism

INT

-1

initial、snapshot

全量快照阶段的并发度上限。-1 表示使用作业默认并发度;显式设置时必须为正整数。

scan.parallelism

INT

-1

除 snapshot 外

增量 Kafka 阶段的最大活跃 Reader 数。-1 表示使用作业默认并发度;显式设置时必须为正整数。

snapshot.max-objects-per-split

INT

500000

initial、snapshot

单个 LIST Split 允许包含的最大对象数。超过该值时作业失败,以避免单个 Split 过大引发内存风险。

snapshot.file-suffix

STRING

无

initial、snapshot

全量快照阶段的文件后缀过滤条件,例如 .json 或 json。未带点号时会自动补充。

rewind.offset

DURATION

0 ms

initial

增量阶段从 T_snapshot_start - rewind.offset 对应的 Kafka 时间戳开始消费。取值不得小于 0,例如 30 s 或 5 min。

rewind.retention-miss-policy

STRING

fail

initial

回拨目标早于 Kafka 最早保留消息时的处理策略。fail:作业失败,避免静默丢数;earliest:从当前最早 Offset 开始并打印警告,已过期事件会丢失。

event.fail-on-out-of-scope

BOOLEAN

false

除 snapshot 外

是否在收到范围外 Kafka 对象事件时使作业失败。默认过滤范围外事件。

metadata.timestamp-offset

STRING

0 ms

全部

为生成的 mtime 和 event_time 增加时间偏移,例如 -8h、+8h 或 +30m,不影响其他字段。

启动模式

以下是针对启动模式参数scan.startup.mode 的说明:

取值

额外必填参数

运行方式

适用场景

initial

topic、properties.bootstrap.servers

先读取 TOS 路径下的已有对象,再切换到 Kafka 持续读取对象事件。

首次构建完整对象状态并持续同步。

snapshot

无

仅读取 TOS 快照;读取完成后 Source 结束。

一次性获取对象清单快照。

earliest-offset

topic、properties.bootstrap.servers

跳过快照,从 Kafka 当前可用的最早 Offset 开始读取。

读取当前仍保留的全部增量事件。

latest-offset

topic、properties.bootstrap.servers

跳过快照,从 Kafka 当前末尾开始读取。

只消费作业启动后新增的事件。

group-offsets

topic、properties.bootstrap.servers、properties.group.id

跳过快照,从 Consumer Group 已提交的 Offset 开始读取。

延续已有 Consumer Group 的消费进度。

timestamp

topic、properties.bootstrap.servers、scan.startup.timestamp-millis

跳过快照,从指定时间戳对应的 Kafka Offset 开始读取。

从指定时间开始消费。

specific-offsets

topic、properties.bootstrap.servers、properties.group.id、scan.startup.specific-offsets

跳过快照,从指定的 Kafka Partition Offset 开始读取。

精确控制各 Partition 的消费起点。

Kafka 参数透传

所有以 properties. 开头的参数都会去掉该前缀后透传给底层 Kafka Consumer。例如:

DDL 参数

Kafka Consumer 参数

properties.bootstrap.servers

bootstrap.servers

properties.group.id

group.id

properties.security.protocol

security.protocol

properties.sasl.mechanism

sasl.mechanism

properties.sasl.jaas.config

sasl.jaas.config

properties.max.poll.records

max.poll.records

CREATE TABLE object_meta (
    object_key STRING NOT NULL
) WITH (
    'connector' = 'tos-cdc',
    'path' = 'tos://my-bucket/ingest/',
    'scan.startup.mode' = 'initial',
    'topic' = 'object-events',
    
    'properties.bootstrap.servers' = 'kafka.example:9092',
    'properties.group.id' = 'ingest-cg',
    'properties.security.protocol' = 'SASL_SSL',
    'properties.sasl.mechanism' = 'PLAIN',
    'properties.sasl.jaas.config' = 'org.apache.kafka.common.security.plain.PlainLoginModule required username="<username>" password="<password>";',
    'properties.max.poll.records' = '500'
);

使用示例

以下示例使用 initial 模式读取指定 Bucket 中两个路径下的已有对象,并持续消费 Kafka 中的对象事件。示例将变更日志写入 Print Connector 来查看输出结果。

CREATE TABLE object_changes (
    object_key    STRING NOT NULL,
    object_url    STRING,
    bucket_name   STRING,
    file_name     STRING,
    object_etag   STRING,
    object_size   BIGINT,
    mtime         TIMESTAMP_LTZ(3),
    event_time    TIMESTAMP_LTZ(3),
    record_origin STRING,
    PRIMARY KEY (object_key) NOT ENFORCED
) WITH (
    'connector'                    = 'tos-cdc',
    'path'                         = 'tos://my-bucket/images01/, tos://my-bucket/images02/',    
    'properties.bootstrap.servers' = 'kafka.example:9092',
    'properties.group.id'          = 'ingest-cg',
    'topic'                        = 'object-events',
    'scan.startup.mode'            = 'initial'
);

CREATE TABLE object_state (
    object_key    STRING NOT NULL,
    object_url    STRING,
    bucket_name   STRING,
    file_name     STRING,
    object_etag   STRING,
    object_size   BIGINT,
    mtime         TIMESTAMP_LTZ(3),
    event_time    TIMESTAMP_LTZ(3),
    record_origin STRING
) WITH (
    'connector' = 'print'
);

INSERT INTO object_state
SELECT
    object_key,
    object_url,
    bucket_name,
    file_name,
    object_etag,
    object_size,
    mtime,
    event_time,
    record_origin
FROM object_changes;

输出结果示例:

1> +I[full-data/images/test09.jpg, tos://zx-source-test/full-data/images/test09.jpg, zx-source-test, test09.jpg, null, 16673, 2026-07-27T11:43:35Z, null, SNAPSHOT]
2> +I[full-data/images/test14.jpg, tos://zx-source-test/full-data/images/test14.jpg, zx-source-test, test14.jpg, "5b31d1c97b76087ba6129148a9fdd3b1", 517, null, 2026-07-27T18:01:45Z, EVENT]
1> +I[full-data/images/test13.jpg, tos://zx-source-test/full-data/images/test13.jpg, zx-source-test, test13.jpg, "5b31d1c97b76087ba6129148a9fdd3b1", 517, null, 2026-07-27T18:01:45Z, EVENT]
1> -D[full-data/images/test13.jpg, tos://zx-source-test/full-data/images/test13.jpg, zx-source-test, test13.jpg, "5b31d1c97b76087ba6129148a9fdd3b1", 517, null, 2026-07-27T18:02:00Z, EVENT]
1> -D[full-data/images/test06.jpg, tos://zx-source-test/full-data/images/test06.jpg, zx-source-test, test06.jpg, "ef4bc467b27e4bc95a7d23f534ae95b8", 427, null, 2026-07-27T18:02:00Z, EVENT]

说明

+I 表示插入记录,-D 表示删除记录;record_origin 可用于区分全量快照和增量事件。

运行机制

全量与增量衔接

在 initial 模式下,连接器启动时记录时间 T_snapshot_start,然后对 path 指定的对象范围执行全量 LIST。全量阶段结束后,连接器从 Kafka Topic 中 T_snapshot_start - rewind.offset 对应的位置开始消费,避免遗漏全量扫描期间产生的对象事件。
生产环境建议将 rewind.retention-miss-policy 保持为默认值 fail。当回拨目标早于 Kafka 最早保留消息时,作业会失败,避免在没有提示的情况下丢失事件。只有在明确接受历史事件丢失风险时,才设置为 earliest。

变更日志语义

全量快照记录和对象 PUT 事件输出 RowKind.INSERT,对象删除事件输出 RowKind.DELETE。连接器不输出 UPDATE_BEFORE 或 UPDATE_AFTER。
若需要将删除事件同步到结果表,下游 Sink 必须支持 Flink DELETE 变更日志,并配置能够唯一标识对象的主键。单 Bucket 场景可使用 object_key;将多个 Bucket 汇总到同一结果表时,建议使用 object_url。

验证与排障

验证方法

  1. 使用“使用示例”中的 SQL 启动作业。
  2. 确认全量扫描阶段能够输出 record_origin = SNAPSHOT 的 +I 记录。
  3. 在配置路径下上传对象,确认作业输出 record_origin = EVENT 的 +I 记录。
  4. 删除测试对象,确认作业输出对应的 -D 记录。

常见问题

问题

处理建议

全量结束后切换增量阶段失败

检查 Kafka 消息保留时间是否覆盖全量扫描耗时和 rewind.offset。若使用默认的 fail 策略,回拨目标早于最早保留消息时作业会主动失败。

结果表中的记录未随 TOS 对象删除

确认下游 Sink 支持 Flink DELETE 变更日志,并在结果表中配置了可唯一标识对象的主键。单Bucket场景可使用object_key 字段作为主键,多个Bucket汇总到同一张结果表时,建议使用object_url字段作为主键。
TOS CDC 接收到对象删除事件后,会输出 RowKind.DELETE,下游SinK根据主键定位并删除对应记录。以 Paimon 为例,无主键的 Append-Only 表不支持 DELETE。

故障恢复后出现重复记录

连接器采用至少一次语义,恢复时可能重新处理上次 Checkpoint 后的数据。下游应结合业务主键和对象元数据构造去重键。

收到不属于配置范围的对象事件

默认情况下连接器会过滤范围外事件。若希望立即暴露事件通知配置问题,可设置 event.fail-on-out-of-scope = true。

  1. 按时间戳timestamp模式启动时遗漏延迟消息
  2. 什么情况下需要配rewind.offset?

检查 Kafka 消息时间戳是否准确反映消息写入时间。若存在以下情况,建议设置正数 rewind.offset 让起始位置向前偏移,避免遗漏:

  • 消息投递存在延迟(事件发生到写入 Kafka 有时间差)
  • 生产者时钟与实际时间存在偏差
  • Kafka 消息时间戳记录的是对象事件发生时间,而非写入时间

注意事项
  • 使用 initial 模式前,应根据 Bucket 对象规模评估全量扫描耗时,并为 Kafka Topic 配置足够的消息保留时间。
  • rewind.offset 会扩大重复消费的时间窗口。增大该值前,应确认下游具备符合业务语义的去重能力。
  • 一个 TOS-CDC Source 只能读取一个 Bucket。配置多个 URI 时,所有 URI 必须属于同一个 Bucket,并使用英文逗号分隔。重复路径以及已被父路径覆盖的子路径会被去重。
  • Source 表是否声明主键不影响连接器输出 DELETE 事件;下游 Sink 是否支持删除及是否配置主键,决定删除事件能否同步到结果表。

相关文档
最近更新时间:2026.09.21 10:09:26
这个页面对您有帮助吗?
有用
有用
无用
无用