0

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

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

请注意,当这种历史读取发生时,新事件会继续到达 Pub/Sub(这些最终也会进入数据库),因此应该从仅从 JDBC 读取的历史事件和仅读取较新的事件进行干净的切换来自发布/订阅。

我考虑过的一些方法:

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

    我认为这不会起作用,因为删除 I/O 转换不向后兼容。或者,管道的 JDBC 部分必须永远留在那里,无缘无故地消耗 CPU 周期。

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

    这似乎使用了比必要更多的发布/订阅资源,而且我认为在管道中交错的新数据与更旧的数据会导致水印过早推进。

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

    这需要停机时间。

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

4

1 回答 1

1

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

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

于 2021-05-11T18:10:07.347 回答