滑动Windows Python Apache Beam复制数据

时间:2018-11-14 15:56:56

标签: python google-cloud-dataflow apache-beam

问题

每次系统从带有滑动Windows的pubsub收到消息时,该消息都是重复的


代码

 | 'Parse dictionary' >> beam.Map(lambda elem: (elem['Serial'], int(elem['Value'])))    
 | 'window' >> beam.WindowInto(window.SlidingWindows(30, 15),accumulation_mode=AccumulationMode.DISCARDING)
 | 'Count' >> beam.CombinePerKey(beam.combiners.MeanCombineFn())

输出

如果我仅从pub / sub发送一条消息,并尝试在滑动窗口完成后使用以下代码打印我的内容:

class print_row2(beam.DoFn):
    def process(self, row=beam.DoFn.ElementParam, window=beam.DoFn.WindowParam,timestamp=beam.DoFn.TimestampParam):
        print row, timestamp2str(float(window.start)), timestamp2str(float(window.end)),timestamp2str(float(timestamp))

结果

('77777', 120.0) 2018-11-16 08:21:15.000 2018-11-16 08:21:45.000 2018-11-16 08:21:45.000
('77777', 120.0) 2018-11-16 08:21:30.000 2018-11-16 08:22:00.000 2018-11-16 08:22:00.000

如果我在'window' >> beam.WindowInto(window.SlidingWindows(30, 15))之前打印邮件,我只会收到一次


该过程处于“图形模式”:

  time: ----t+00---t+15---t+30----t+45----t+60------>
             :      :      :       :       :
  w1:        |=X===========|       :       :
  w2:               |==============|       :
  ...

消息X在滑动窗口开始时仅发送了一次,应该只接收一次,但是却接收了两次

我尝试了两个AccumulationMode值,也使用了trigger = AftyerWatermark,但我无法解决问题。

怎么了?


额外

对于FixedWindows,这是我的海豚的正确代码:

| 'Window' >> beam.WindowInto(window.FixedWindows(1 * 30))
| 'Speed Average' >> beam.GroupByKey()
| "Calculating average" >> beam.CombineValues(beam.combiners.MeanCombineFn())

| 'Window' >> beam.WindowInto(window.FixedWindows(1 * 30))
| "Calculating average" >> beam.CombinePerKey(beam.combiners.MeanCombineFn())

2 个答案:

答案 0 :(得分:0)

发出属于窗口的所有元素。如果一个元素属于多个窗口,它将在每个窗口中发出。

仅当您打算处理较晚的数据/多次触发时,累积模式才有意义。在这种情况下,当触发器再次触发时,丢弃模式只会在窗口中提供新元素,即仅发出自上一次触发器触发以来到达同一窗口的元素,已经发出的元素不会再次发出并被丢弃。在累积模式下,每次触发触发都会发射整个窗口,其中将包括上次已发射的旧元素和自那以后到达的新元素。

如果我理解您的示例,则您有滑动窗口,它们的长度为30秒,每15秒启动一次。因此它们重叠了15秒:

  time: ----t+00---t+15---t+30----t+45----t+60------>
             :      :      :       :       :
  w1:        |=============|       :       :
  w2:               |==============|       :
  w3:                      |===============|
  ...

因此,您案例中的任何元素都将至少属于两个窗口(第一个和最后一个窗口除外)。

例如在您的示例中,如果您的邮件是在17:07:15到17:07:30之间发送的,它将同时出现在两个窗口中。

固定的窗口不重叠,因此元素只能属于一个窗口:

  time: ----t+00---t+15---t+30----t+45----t+60------>
             :             :               :
  w1:        |=============|               :
  w2:                      |===============|
  w3:                                      |====...
  ...

有关Windows的更多信息:https://beam.apache.org/documentation/programming-guide/#windowing

答案 1 :(得分:0)

我有完全相同的问题,但是在Java中。我有一个持续时间为10秒,步长为3秒的窗口。当我订阅的mqtt主题发出一个事件时,它看起来就像我运行的ParDo函数,并向所有三个“构造的”窗口发出第一个也是唯一的事件。

X是我在随机时间戳记上发送的事件:2020-09-15T21:17:57.292Z

  time: ----t+00---t+15---t+30----t+45----t+60------>
             :      :      :       :       :
  w1:        |X============|       :       :
  w2:               |X=============|       :
  w3:                      |X==============|
  ...

甚至为它们分配了相同的时间戳!!我真的必须做些完全错误的事情。

我将Scala 2.12和BEAM 2.23与Direct Runner一起使用。

[提示]: 我在processElement函数中使用状态!每个键+窗口保持状态的位置。也许那里有一个bug?我将尝试在没有状态的情况下进行测试。

更新:删除了状态字段,并将单个事件分配给一个窗口。