如何通过 pub/sub 将旧数据重播到数据流中并保持正确的事件时间逻辑?

How can you replay old data into dataflow via pub/sub and maintain correct event time logic?

我们正在尝试使用数据流的处理时间独立性来启动一个新的流作业并通过 Pub/Sub 将我们的所有数据重播到其中,但是 运行 遇到以下问题:

管道的第一阶段是对事务 ID 进行分组,会话 window 为 10 秒,丢弃已触发的窗格,并且不允许迟到。因此,如果我们不指定重播 pub/sub 主题的时间戳标签,那么当我们重播到 pub/sub 时,所有事件时间戳都是相同的,并且 groupby 会尝试将我们所有的存档数据分组到事务 ID 中一直以来。不好。

如果我们将 timestampLabel 设置为存档数据中的实际事件时间戳,并在 pub/sub 主题中一次重放 1d,那么它适用于第一天的事件,但随后作为一旦这些用完,重播的数据水印 pub/sub 就会以某种方式向前跳到当前时间,并且所有后续重播的日期都将作为延迟数据删除。我真的不明白为什么会这样,因为它似乎违反了数据流逻辑独立于处理时间的想法。

如果我们将 timestampLabel 设置为存档数据中的实际事件时间戳,并将其全部重播到 pub/sub 主题中,然后启动流作业来使用它,则数据水印永远不会出现前进,似乎没有任何东西从 groupby 中出来。我也不太明白这是怎么回事。

您的方法 #2 和 #3 存在不同的问题:

方法#3(写入所有数据,然后开始消费):由于数据是乱序写入 pubsub 主题的,水印在所有(或大部分)数据被消费之前确实无法推进 - 因为水印是软保证 "further items that you receive you are unlikely to have event time later than this",但由于乱序发布,发布时间和事件时间之间没有任何对应关系。因此,您的管道实际上会卡住,直到它处理完所有这些数据。

方法#2:从技术上讲,它在每一天都会遇到同样的问题,但我想 1 天内的数据量不会那么大,所以管道能够处理它。然而,在那之后,pubsub 通道会长时间保持空状态,在这种情况下,PubsubIO 的当前实现会将水印提前到实时,这就是为什么进一步延迟数据的原因。 The documentation 对此进行更多解释。

总的来说,快速赶上大量积压,例如通过将历史数据用于 "seed" 管道,然后继续流入新数据,这是一个重要的用例,但我们目前还不能很好地支持它。

同时我有一些建议给你:

  • (更好)使用方法 #2 的变体,但尝试根据流管道对其进行计时,以便 pubsub 频道不会保持为空。
  • 使用方法 #3,但有更多的工作人员和每个工作人员更多的磁盘(您当前的工作似乎是使用最多 8 个工作人员的自动缩放 - 尝试更大的东西,比如 100?赶上之后它会缩减)