使用历史数据回填 Beam 管道

Backfill Beam pipeline with historical data

我有一个 Google 云数据流管道(使用 Apache Beam SDK 编写),在其正常操作模式下,处理发布到云的事件数据 Pub/Sub。

为了使管道状态保持最新并创建正确的输出,必须首先处理大量历史事件数据。此历史数据可通过 JDBC 获得。在测试中,我能够使用 JdbcIO.Read PTransform 读取和处理所有历史状态,但我想使用此 JDBC 事件数据初始化我的生产管道,然后干净利落地过渡到读取事件来自 Pub/Sub。如果以向后不兼容的方式更改流水线逻辑,那么将来可能会再次发生相同的过程。

请注意,在进行此历史读取时,新事件将继续到达 Pub/Sub(并且这些事件最终也会出现在数据库中),因此应该只从读取的历史事件中进行干净的切换JDBC,并且仅从 Pub/Sub 读取较新的事件。

我考虑过的一些方法:

  1. 有一个从两个输入读取的管道,但在某个时间戳之前过滤来自 JDBC 的数据,并在某个时间戳之后过滤来自 pub/sub 的数据。一旦管道被捕获,部署更新删除 JDBC 输入。

    我认为这行不通,因为删除 I/O 转换不向后兼容。或者,管道的 JDBC 部分必须永远留在那里,无缘无故地燃烧 CPU 个周期。

  2. 编写一个一次性作业,用全部历史数据填充 pub/sub,然后启动仅从 pub/sub 读取的主管道。

    这似乎使用了比必要更多的 pub/sub 资源,而且我认为管道中的新数据与更旧的数据交织在一起会导致水印提前过早。

  3. 选项 #2 的变体 -- 在处理历史数据之前停止创建新事件,以避免弄乱水印。

    这需要停机。

似乎将历史数据回填到管道中是一个常见的要求,但我一直没能找到解决这个问题的好方法。

您的第一个选项,从有界源(过滤到时间戳 <= 截止)和 PubSub(过滤到时间戳 > 截止)读取应该工作正常。

因为 JDBC.Read() 是一个有界源,它将读取所有数据然后“完成”,即不再产生任何数据,将其水印推进到 +infinity,并且不会再次调用(所以不用担心它会消耗 CPU 个周期,即使它出现在您的图表中也是如此。