TOS-CDC Pipeline Source 用于捕获火山引擎对象存储 TOS 中对象的元数据变更。该连接器可先读取指定 TOS 路径下的存量对象,再持续消费 Kafka 中的对象事件通知,并将对象的创建、覆盖和删除操作转换为 Flink CDC Pipeline 事件。
类别 | 详情 |
|---|---|
支持类型 | Source |
作业类型 | Flink CDC Pipeline YAML |
运行模式 | 流模式; |
读取阶段 | TOS 对象全量快照、Kafka 对象增量事件 |
支持的变更类型 | 全量快照对象及增量 PUT 事件转换为 INSERT,增量删除事件转换为 DELETE |
输出数据 | 使用固定的对象元数据 Schema,输出对象键、对象地址、Bucket 名称、文件名、ETag、对象大小、修改时间、事件时间和记录来源等信息 |
处理语义 | 采用 At-least-once 处理语义;故障恢复、消费位点回拨等情况下可能重复处理事件。端到端一致性还取决于下游 Sink 的写入语义 |
组件 | 支持版本 | 说明 |
|---|---|---|
火山引擎流式计算 Flink版 |
| Connector 已由平台内置。 |
Flink CDC | 3.4及以上版本 | 创建 Pipeline 作业时选择 3.4 或以上版本。 |
火山引擎对象存储 TOS | 不适用 | TOS 不提供用户可选的服务版本,兼容性以当前线上服务为准。 |
initial 模式先扫描指定 TOS 路径下的已有对象,再从全量扫描开始时间对应的 Kafka 位点持续消费对象事件,用于构建并维护对象元数据状态。initial、snapshot、earliest-offset、latest-offset、group-offsets、timestamp 和 specific-offsets 七种启动模式,可以按需执行全量加增量同步、仅快照读取、增量续读或历史事件回放。initial 模式支持通过 rewind.offset 将 Kafka 消费起点回拨到全量扫描开始时间之前,降低全量扫描期间对象事件遗漏的风险;同时支持配置 Kafka 历史消息过期时的处理策略。event.fail-on-out-of-scope 后,可在发现范围外事件时使任务失败,帮助及时发现 Topic 或数据源配置错误。record_origin 区分 SNAPSHOT 和 EVENT 来源,便于下游统一处理和排查重复数据。object_key 声明为逻辑主键,并配合支持 INSERT、DELETE Changelog 的下游 Sink,维护 Bucket 中对象的当前元数据状态。使用 TOS-CDC Pipeline Source 前,请完成以下准备工作:
tos:ObjectCreated:*;如需同步对象删除,还应订阅 tos:ObjectRemoved:*。事件通知规则的 Prefix、Suffix 应覆盖 Source 配置的对象路径。详细操作请参见设置事件通知推送至 Kafka限制项 | 说明 |
|---|---|
全量 Bucket 扫描范围 |
|
增量事件范围 | 默认会过滤掉 Kafka Topic 里不在当前 |
表语义 | 快照和增量 PUT 都相当于 |
重复数据 | Source 采用 At-Least-Once 处理语义,下游可能收到重复记录。例如,在进行故障恢复时,可能会重新处理上次检查点之后的数据;或者手动设置了 |
以下示例先读取指定 TOS 路径下的已有对象,再持续消费对象事件,并将结果写入 Paimon:
sources: - source: type: tos-cdc name: TOS CDC Source table-id: object_store.object_changes path: tos://my-bucket-test/model-data/images schema.primary-key: object_key properties.bootstrap.servers: kafka-example01.kafka.ivolces.com:9092 properties.group.id: test-group-id topic: test-topic scan.startup.mode: initial sink: type: paimon name: Paimon Sink catalog.properties.metastore: filesystem catalog.properties.warehouse: tos://my-bucket-test/warehouse pipeline: name: TOS Object Metadata to Paimon parallelism: 4
说明
schema.primary-key 为可选配置。需要在下游维护对象当前状态时,建议使用 object_key 作为主键。
说明
“无默认值”表示连接器不会自动填充该参数;是否必须配置由“生效模式”和“说明”列决定。
参数 | 类型 | 默认值 | 生效模式 | 说明 |
|---|---|---|---|---|
|
| 无默认值 | 全部 | 必填,必须为 |
|
| 无默认值 | 全部 | Source 名称。 |
|
| 无默认值 | 全部 | 必填,Source 输出的逻辑表标识,支持 |
|
| 无默认值 | 全部 | 固定输出 Schema 的主键字段,多个字段使用英文逗号分隔。 |
|
| 无默认值 | 全部 | 必填,一个或多个 TOS URI,多个 URI 用英文逗号分隔。格式为 |
|
|
| 全部 | 启动模式,支持 |
|
| 无默认值 |
| 必填。非负 Unix epoch 毫秒时间戳。其他模式忽略。 |
|
| 无默认值 |
| 必填。格式为 |
|
| 无默认值 | 除 | 承载 TOS 对象事件通知的 Kafka Topic;增量阶段均需配置。 |
|
| 无默认值 | 除 | Kafka Broker 地址;增量阶段均需配置。 |
|
| 无默认值 | 增量阶段 | Kafka Consumer Group ID; |
|
| 无默认值 | 增量阶段 | 透传给底层 Kafka consumer 的参数。 |
|
| 无默认值 |
| 透传给 TOS FileSystem 的参数,传递时会移除 |
|
|
|
| 全量快照阶段并发度上限。 |
|
|
| 除 | 增量 Kafka 阶段最大活跃 reader 数。 |
|
|
|
| 单个 LIST split 允许的最大对象数。超过后任务失败,避免单个 split 过大导致内存风险。 |
|
| 无默认值 |
| 适用于全量快照阶段的文件后缀过滤条件,例如 |
|
|
|
| 回拨时间。增量阶段从 |
|
|
|
| 回拨目标早于 Kafka 最早保留消息时的策略。 |
|
|
| 除 | 是否在遇到范围外 Kafka 对象事件时使任务失败。默认过滤范围外事件。 |
|
|
| 全部 | 只对生成的时间字段 |
配置项 scan.startup.mode 用于指定 TOS CDC Source 的启动模式:
scan.startup.mode取值 | 额外必填参数 | 运行原理说明 | 适用场景 |
|---|---|---|---|
|
| 先读取 TOS 路径下的已有对象,再切换到 Kafka 持续读取对象事件。 | 首次构建完整对象状态并持续同步。 |
| 无 | 仅读取 TOS 快照;读取完成后 Source 结束。 | 一次性获取对象清单快照。 |
|
| 跳过快照,从 Kafka 当前可用的最早位点开始读取。 | 从当前仍保留的全部增量事件开始。 |
|
| 跳过快照,从 Kafka 当前末尾开始读取。 | 只消费作业启动后新增的事件。 |
|
| 跳过快照,从 Consumer Group 已提交的位点开始读取。 | 延续已有 consumer group 进度。 |
|
| 跳过快照,从指定时间戳对应的 Kafka 位点开始读取。 | 从指定时间开始消费。 |
|
| 跳过快照,从指定的 Kafka 分区位点开始读取。 | 精确控制每个 partition 的起点。 |
TOS CDC Source 使用固定的对象元数据 Schema:
字段名 | CDC 类型 | 说明 |
|---|---|---|
| STRING NOT NULL | 对象在存储桶(Bucket)里的原始键(key),在一个存储桶内,它可作为对象的唯一标识。 |
| STRING | 对象的完整 TOS URL,根据 Bucket 和 key 计算得出 tos://<bucket_name>/<object_key> |
| STRING | TOS 存储桶的名称 |
| STRING | 从对象 |
| STRING | 全量快照或增量事件提供的 etag,但有些事件可能没有这个值。 |
| BIGINT | 全量快照或增量事件提供的对象大小,单位为字节。 |
| TIMESTAMP_LTZ(3) | 全量快照中的对象修改时间;增量事件通常为空。 |
| TIMESTAMP_LTZ(3) | 增量事件时间;在全量快照阶段,这个值为空。 |
| STRING | 数据来源:SNAPSHOT 表示这条记录来自全量快照,EVENT 表示来自 Kafka 增量事件。 |
说明
快照对象以及增量创建、覆盖事件会生成 Insert;增量删除事件会生成 Delete。
需要在下游维护对象当前状态时,应选择支持 Insert/Delete Changelog 的 Sink,并使用稳定的对象标识作为主键。
以下示例先扫描 tos://my-bucket-test/model-data/images 路径下的已有对象,再持续消费 Kafka Topic 中的对象创建、覆盖和删除事件,最后将对象元数据写入 Paimon 表。
运行前请替换 TOS 路径、Kafka Broker 地址、Consumer Group ID、Topic 和 Paimon Warehouse 路径。
sources: - source: type: tos-cdc name: TOS CDC Source table-id: object_store.object_changes # 需要采集的 TOS 路径 path: tos://my-bucket-test/model-data/images # Source 输出表的逻辑主键 schema.primary-key: object_key # 接收 TOS 对象事件通知的 Kafka properties.bootstrap.servers: kafka-example01.kafka.ivolces.com:9092 properties.group.id: test-group-id topic: test-topic # 先读取已有对象,再持续读取增量事件 scan.startup.mode: initial sink: type: paimon name: Paimon Sink # 使用文件系统方式管理 Paimon Catalog catalog.properties.metastore: filesystem # Paimon Warehouse 存储路径 catalog.properties.warehouse: tos://my-bucket-test/warehouse pipeline: name: TOS Object Metadata to Paimon parallelism: 4
配置说明:
sources:定义 Pipeline 的数据来源。本示例使用 TOS-CDC Source。path:指定需要扫描的 TOS Bucket 和对象路径。table-id:定义 Source 在 Pipeline 中产生的逻辑表标识。本示例使用 object_store.object_changes。schema.primary-key:声明 Source 输出表的逻辑主键。本示例使用 object_key 标识对象。properties.bootstrap.servers:Kafka Broker 地址。properties.group.id:Kafka Consumer Group ID,用于标识该作业的 Kafka 消费组。topic:接收 TOS 对象事件通知的 Kafka Topic。scan.startup.mode: initial:启动时读取指定路径下的已有对象,完成后持续处理 Kafka 中的增量事件。sink:定义数据写入目标。本示例将结果写入 Paimon。pipeline.parallelism:设置 Pipeline 的默认并行度。假设作业启动前,指定路径下已有以下对象:
model-data/images/a.jpg model-data/images/b.jpg
全量扫描阶段会为两个对象分别输出一条 INSERT 事件。
作业进入增量阶段后,如果依次发生以下操作:
创建 model-data/images/c.jpg 覆盖 model-data/images/a.jpg 删除 model-data/images/b.jpg
Source 会输出:
TOS 操作 | Pipeline 事件 |
|---|---|
创建 |
|
覆盖 |
|
删除 |
|
该 Connector 不会为对象覆盖操作输出 UPDATE_BEFORE 和 UPDATE_AFTER。
如果 Paimon 目标表以 object_key 为主键并按主键更新,最终表中预计包含 a.jpg 和 c.jpg,不再包含已删除的 b.jpg。实际结果还取决于 Paimon 目标表结构及 Sink 的写入语义。
说明
全量扫描和 Kafka 增量事件可能存在重叠,同一个对象事件也可能在故障恢复时被重新处理。下游需要根据业务要求使用主键写入或进行事件去重。
TOS-CDC Pipeline Source 通过“TOS 全量扫描 + Kafka 增量事件消费”持续维护指定路径下的对象元数据。
当 scan.startup.mode 设置为 initial 时,Connector 首先列举 path 指定范围内的已有对象,读取每个对象的元数据信息,并将每个对象转换为一条 INSERT 事件。
例如,指定:
path: tos://my-bucket-test/model-data/images
启动时该路径下存在:
model-data/images/a.jpg model-data/images/b.jpg
Source 会分别输出 a.jpg 和 b.jpg 的对象元数据。
注意
如果 path 配置了同一 Bucket 下的多个 URI,Connector 会合并扫描范围,并对重复路径以及已经被父路径覆盖的子路径进行去重,避免对同一路径进行重复扫描。
全量扫描用于发现作业启动前已经存在的对象,Kafka 事件用于捕获作业运行期间发生的对象变化。
全量扫描完成后,Source 持续消费 Kafka Topic 中的对象事件通知。为降低全量扫描和增量消费交接过程中遗漏对象变化的风险,Kafka 增量读取范围可能与全量扫描范围发生重叠。
例如:
images/。images/c.jpg。c.jpg。c.jpg 的创建事件。c.jpg 有关的 INSERT 事件。说明
这种设计优先避免事件遗漏,但可能产生重复数据。使用 rewind.offset 将 Kafka 消费起点向前回拨时,重叠范围还可能进一步扩大。
Connector 持续消费指定 Kafka Topic 中的 TOS 对象事件,并根据 Source 的采集范围筛选事件。
当前事件转换规则如下:
数据来源或对象操作 | Pipeline 事件 |
|---|---|
全量扫描发现已有对象 |
|
增量创建对象(PUT) |
|
增量覆盖对象(PUT) |
|
增量删除对象 |
|
对象覆盖不会转换为 UPDATE_BEFORE 和 UPDATE_AFTER。如果下游需要把同一对象的多次 PUT 合并为当前状态,可以使用 object_key 等对象标识作为主键,通过主键表的 Upsert 语义处理。
说明
Kafka Topic 中不属于当前 Source 采集范围的事件默认会被过滤。将 event.fail-on-out-of-scope 设置为 true 后,Source 检测到范围外事件时会使任务失败。
作业运行期间,Flink 通过 Checkpoint 定期保存 Source 的处理状态,例如全量扫描进度和 Kafka 消费位置。
任务发生故障时,会从最近一次成功的 Checkpoint 恢复。Checkpoint 完成后新处理、但尚未被下一次 Checkpoint 确认的事件可能被重新消费,因此 Source 采用至少一次(At-Least-Once)处理语义:
端到端一致性不仅取决于 Source,还取决于 Sink 是否支持事务提交、主键更新或幂等写入。
Source 输出的对象变更事件经过 Pipeline 传递给 Sink。本示例使用 Paimon Sink:
INSERT 用于新增对象记录,或者更新主键相同的对象状态。DELETE 用于删除主键对应的对象记录。INSERT 是否形成重复行,取决于目标表是否具有主键以及 Paimon Sink 的具体写入语义。如果下游保存的是对象当前状态,建议采用主键表;由于当前输出 Schema 不包含稳定的事件标识,无法可靠区分事件重放与同一对象的多次真实变更,因此不适合用于需要精确事件级去重或审计的完整变更历史场景。
首次使用 TOS-CDC Pipeline Source 时,建议使用测试 Bucket、测试路径和独立的 Kafka Consumer Group 完成全量扫描、增量采集和故障恢复验证,再应用于生产环境。
建议按照以下步骤进行验证:
path 中的 Bucket 和对象路径是否存在,并确认 Flink 作业具有列举对象和读取对象元数据的权限。path 范围内的已有对象已写入下游。INSERT 和 DELETE 事件。假设 Source 配置如下:
path: tos://my-bucket-test/model-data/images
可以在该路径下执行以下测试:
测试操作 | 预期 Source 事件 | 下游当前状态表的预期结果 |
|---|---|---|
创建 |
| 新增 |
覆盖 |
| 更新或覆盖 |
删除 |
| 删除 |
在其他 Bucket 创建对象 | 默认过滤,或根据配置使任务失败 | 不应写入目标表 |
重启作业并恢复状态 | 部分事件可能被重放 | 主键表最终状态应保持一致 |
对象覆盖事件能否覆盖下游已有记录,取决于 Sink 是否支持主键更新以及目标表是否正确配置主键。
现象 | 可能原因 | 处理建议 |
|---|---|---|
作业提交后立即失败 | YAML 层级或参数格式错误;缺少必填参数;Connector 类型不受支持 | 检查 |
提示 TOS URI 不合法 | URI 格式错误;路径中包含未编码的空格、中文或特殊字符;多个 URI 分隔方式错误 | 按照 |
提示多个 URI 不属于同一 Bucket |
| 将不同 Bucket 拆分到不同 Source 或不同 Pipeline 中 |
作业运行但没有全量数据 | 指定路径下没有对象;路径配置错误;缺少 TOS 列举对象权限 | 检查 Bucket、对象 Key 前缀和访问权限,并使用测试对象验证 |
无法连接 Kafka | Broker 地址错误;网络不通;认证参数缺失;Kafka 访问控制未放行 | 检查 |
可以读取全量数据,但收不到增量事件 | TOS Bucket 未配置事件通知;事件类型未包含对象创建或删除;Prefix、Suffix 未覆盖 Source 路径;推送目标不是当前 Kafka Topic;TOS 向 Kafka 投递所需的用户或角色权限不足 | 参见设置事件通知推送至 Kafka,检查 Bucket 的事件通知规则、事件类型、Prefix、Suffix、Kafka 实例、Topic、Kafka 用户和授权角色;然后在目标路径创建测试对象,并检查 Kafka Topic 是否收到事件 |
可以收到对象创建事件,但删除对象后下游没有变化 | 事件通知规则只订阅了 | 检查 TOS 事件通知规则是否包含 |
增量事件被忽略 | 事件不属于当前 Source 采集范围 | 检查事件中的 Bucket、对象 Key 与 |
遇到范围外事件后任务失败 |
| 检查 Kafka Topic 是否混入其他 Bucket 或路径的事件;不需要严格校验时改为默认过滤行为 |
下游出现重复数据 | 故障恢复导致事件重放;配置了 | 使用主键表、幂等写入或业务去重键处理重复事件 |
覆盖对象后下游出现多行 | Source 将对象覆盖转换为 | 根据业务目标配置主键;保存当前状态时可考虑使用 |
删除对象后下游记录仍然存在 | DELETE 事件未进入 Topic;主键配置错误;Sink 不支持按主键删除 | 检查 Kafka 中的删除事件、 |
写入 Paimon 失败 | Warehouse 路径错误;缺少读写权限;目标表结构不兼容 | 检查 |
恢复后重复处理部分事件 | Source 采用 At-Least-Once 语义,从最近成功的 Checkpoint 恢复时发生重放 | 属于预期行为;使用主键 Upsert 或事件去重保证最终结果 |
作业恢复失败 | 修改了 Bucket、Topic、表标识、主键或其他状态相关配置 | 使用与原作业兼容的配置恢复;重大配置变更建议创建新作业并重新同步 |
全量扫描速度较慢 | Bucket 对象数量较多;路径范围过大;并行度不足;TOS 或 Sink 存在限流 | 缩小扫描路径,检查 Source 和 Sink 是否存在反压,并结合资源和限流情况调整并行度 |
Kafka 消费延迟持续增加 | Kafka Partition 数不足;作业并行度不足;Sink 写入缓慢导致反压 | 检查 Kafka Lag、Flink 反压和 Sink 吞吐,综合调整 Partition、并行度及下游资源 |
Checkpoint 长时间失败 | 下游阻塞、状态过大、网络异常或 Checkpoint 存储不可用 | 检查 Checkpoint 详情、作业反压、状态大小和存储访问情况 |
scan.startup.mode: initial 会读取已有对象并继续消费增量事件。全量扫描与增量消费可能存在重叠,下游不能假设每个对象事件只会收到一次。rewind.offset 前应评估重复数据范围。生产作业不建议在缺少去重方案的情况下随意向前回拨消费位置。object_key 作为全局主键,应考虑使用 Bucket 和对象 Key 的组合作为主键。设置事件通知推送至 Kafka:配置 TOS Bucket 的事件通知规则,将对象创建、覆盖和删除事件推送至 Kafka。它是本 Connector 实现增量采集最重要的前置文档。
对象存储 TOS 产品文档:了解 TOS Bucket、对象 Key、访问权限、SDK 和 API 等基础能力。
Flink CDC Pipeline 连接器列表:了解火山引擎 Flink CDC Pipeline Connector 的文档分类和支持范围。
Kafka Pipeline Connector:了解 Kafka Connector 的配置参数和数据读取、写入方式。
Paimon Pipeline Connector:了解示例中 Paimon Sink 的 Catalog、Warehouse、主键和写入配置。
Apache Flink CDC:Data Pipeline:了解 Flink CDC Pipeline 中 Source、Sink、Transform、Route 和 Pipeline 的关系。
Apache Flink:Checkpoint:了解 Flink 如何保存作业状态和数据流读取位置,以及故障恢复机制。
Apache Flink:Fault Tolerance:了解 At-Most-Once、At-Least-Once 和 Exactly-Once 等处理语义。