Pinterest 为下一代数据库摄取框架引入了基于事件时间的分区最终确认机制,让下游任务能够判断流式数据何时已经足够完整,可以安全消费。该方案使用 Apache Flink 衡量事件时间的推进情况,并通过 Apache Iceberg 元数据发布一个不会回退的最终确认水位线,解决持续变更数据捕获(CDC)摄取中的一个难题:即使某个分区对应的自然时间区间已经结束,数据仍可能延迟到达。
Pinterest 的摄取框架使用 CDC、Kafka、Flink、Spark 和 Iceberg,将 MySQL、TiDB 和 KVStore 中的数据库变更写入分析表。Pinterest 表示,该平台支持 PB 级数据和数千条流水线,线上变更通常可以在 15 分钟到一小时内供分析使用。在此前基于批处理的方案中,任务完成意味着分区已经就绪;而流式摄取会持续提交变更,不存在与之对应的明确完成点。

Google 架构师 Nitesh Singhal 在 LinkedIn 帖子中介绍了这一设计,并写道:
其中最巧妙的部分,是这个不会回退的安全读取水位线。
新机制运行在 Flink 到 Iceberg 的 Sink 内部。系统会从每条 CDC 记录中提取一个预先配置的事件时间。在 Flink 执行检查点时,系统会收集事件时间的最小值、最大值和百分位数统计信息。这些数据会存储在 Iceberg 的快照摘要中,同时使用 t-digest 将事件时间分布压缩到几百字节。
Iceberg 完成提交后,系统会根据近期检查点统计信息计算分区最终确认水位线。默认策略会取可配置数量的近期提交中的最小事件时间,并向下取整到对应小时。该水位线单调递增,可以防止延迟到达的记录使已经发布的值向后回退。基于百分位数的策略则可以牺牲一部分完整性,换取更新鲜的数据。
Pinterest 表示,该水位线以 Iceberg 表属性的形式存储,因此下游传感器无需单独的协调服务即可读取。Spark 在执行 CDC 更新插入提交时,也会将这些元数据传播到基础表。Pinterest 强调:
最终确认不再是任务结束所带来的副产品。
该设计建立在 Flink 和 Iceberg 的现有能力之上。Flink 水位线用于追踪乱序数据流中的事件时间进度,Iceberg 快照则提供持久化的表元数据。Pinterest 将两者结合起来,推导出特定于数据表的完整性信号,并将其与数据存储在一起。

时间线展示了延迟到达的 CDC 事件、Flink 检查点、事件时间进度,以及单调递增的最终确认水位线。
Salesforce 工程师 Tharun Kumar Reddy Polu 在 LinkedIn 评论中指出了流处理与批处理之间的权衡,并写道:
这项设计之所以令人信服,正是因为它准确呈现了流处理与批处理之间的取舍。既获得数据新鲜度,又不丢失批处理曾经提供的保证,这才是核心难题。
Pinterest 利用 Flink-to-Iceberg Sink 中的扩展点实现了这一机制。累加器负责收集记录统计信息,提交处理器则围绕 Iceberg 提交执行最终确认逻辑。另外,Apache Iceberg 的一项议题正在讨论如何扩展 IcebergSink,以支持下游集成,其中包括水位线信息等自定义可提交元数据。
原文链接:
https://www.infoq.com/news/2026/10/pinterest-event-time-partition/





