Apache Beam中的早期触发和链式聚合

时间:2017-12-10 20:35:46

标签: google-cloud-dataflow apache-beam

是否可以在Apache Beam中使用不同的窗口和触发组合/链接多个聚合。

示例:

我有PCollection<KV<String, Long>>的输入,我需要计算2个总和:1分钟固定窗口,每1分钟滑动窗口1小时,我想每分钟获得推测结果。

触发:

Trigger trigger =
    Repeatedly.forever(
            AfterProcessingTime.pastFirstElementInPane()
                // Speculative every ONE_MINUTE
                .plusDelayOf(ONE_MINUTE))
        // final result past watermark
        .orFinally(AfterWatermark.pastEndOfWindow());

有输入:PCollection<KV<String, Long>> input我可以使用2个聚合来完成:

PCollection<KV<String, Long>> oneMinSum = input
    .apply(Window.into(1 min).triggering(trigger))
    .apply(Sum.longsPerKey())

PCollection<KV<String, Long>> slidingSum = input
    .apply(Window.into(1 hour sliding 1 min).triggering(trigger))
    .apply(Sum.longsPerKey())

但是在这种情况下,如果我可以使用oneMinSum作为滑动聚合的输入,那么第二个聚合将对已经在一分钟总和中使用的完全相同的数据进行求和,我会节省大量的CPU,但这不起作用,第二次聚合计算早期触发的窗格和最终窗格的总和,重复计算并产生不正确的滑动总和。

完整的测试用例在这里:https://gist.github.com/anonymous/2920e870a02abcbec51e10c3fd293236

输出

key=a value=1
    window=[2017-01-01T00:00:00.000Z..2017-01-01T00:10:00.000Z)
    pane=PaneInfo{isFirst=true, timing=EARLY, index=0}
key=a value=5
    window=[2017-01-01T00:00:00.000Z..2017-01-01T00:10:00.000Z)
    pane=PaneInfo{timing=EARLY, index=1}
key=a value=7
    window=[2017-01-01T00:00:00.000Z..2017-01-01T00:10:00.000Z)
    pane=PaneInfo{isLast=true, timing=ON_TIME, index=2, onTimeIndex=0}

我所见过的所有示例都假设Window.into仅应用于PCollection一次,并且在计算了聚合后,结果会转到某些存储空间(例如BigQuery等等),I& #39;从未见过任何&#34;链接&#34;聚合和多次更改窗口。

Beam编程模型的用例是否正确?或梁编程模型假设Window.into(...).triggering(...)只会被指定一次?

1 个答案:

答案 0 :(得分:0)

TLDR:要解决此问题,请在第一个聚合中使用<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Backers Online</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div id="root"></div> <script src="../build/app.bundle.js"></script> </body> </html>

您指定的触发器与您的想法不同。 discardingFiredPanes 在窗格中第一个元素后1分钟触发,但由于您还使用AfterProcessingTime.pastFirstElementInPane().plusDelayOf(ONE_MINUTE))accumulatingFiredPanes(),触发器将触发

(i)第一次元素后1分钟

(ii)每次在(i)满足后出现新元素

对于您的测试用例,我注释了Repeatedly.forever(...)

会发生什么
oneMinSum

解释了.advanceWatermarkTo(t0) .addElements(KV.of("a", 1)) .advanceProcessingTime(TWO_MINUTES) // emit (a, 1) because of (i) .addElements(KV.of("a", 1)) .advanceProcessingTime(TWO_MINUTES) // emit (a, 2) because of (ii) .advanceWatermarkTo(t1) // emit another (a, 2) past watermark .addElements(KV.of("a", 1)) .advanceProcessingTime(TWO_MINUTES) // emit (a, 1) because of (i) .advanceWatermarkToInfinity(); // emit another (a, 1) past watermark (a, 2)的双重发射here

对于(a, 1),你得到

    因为早期触发而
  • onHourSums
  • 因为早期触发而
  • key=a value=1
  • 由于关闭窗口,
  • key=a value=5 (1+2+2)