比较Google Cloud Dataflow中唯一匹配的数据集

时间:2016-10-11 06:14:57

标签: google-cloud-dataflow

假设您有来自两个不同pubsub主题的信息进入Google Cloud Dataflow,并且您希望将来自一个主题的信号与来自其他主题的信号进行比较,并在它们相等时生成匹配。如果同时(或几乎同时)在其中一个主题上有多个相等的信号,那么我们就不应该生成匹配。是否有可能以近乎实时的方式在Dataflow中生成匹配,这样我们就可以100%确定生成的匹配是否正确(即没有误报)?如果是这样,你会如何实现它?由于数据可能会延迟到Dataflow的时间窗口,我怀疑这很难。

为了简化,如果我们从一个pubsub主题获得“A”,从另一个主题获得“A”,我们应该生成一个匹配,但前提是没有任何其他A进入任一主题大约在同一时间(比如说加减1秒)。

1 个答案:

答案 0 :(得分:0)

如果我理解你的问题,我会按如下方式分解。我将使用我们标准的四个问题,因为它在这种情况下很有用。

  • 你在计算什么?” - 您正在进行流加入,根据您的说明,我认为您需要选择基于CoGroupByKey的加入。
  • 在哪个事件时间内你想对数据进行分组?” - 如果事件发生在附近,您有兴趣一起查看事件。这大致对应于SDK中提供的Sessions。但我不知道你是否希望会话在两个流上,或者每个流都是单独的。希望我的回答足以让你工作。
  • 何时你想产生输出?” - 根据您100%确定性的目标,我认为您只有在决定放弃所有进一步的数据后才想生成输出。要真正具有100%的确定性,您必须知道数据来自何处(这与Dataflow无关)。
  • 如何对先前产出的改进有何关联?” - 由于单个连接结果没有多个输出,因此这不是问题。

我们假设你有这些输入:

PCollection<String> streamA
PCollection<String> streamB

如果你想根据流中的同时性进行匹配+重复数据删除,那么你可以直接进入Sessions并进行CoGroupByKey

PCollection<KV<String, String>> windowedA = streamA
    .apply(WithKeys.of(String v -> v))
    .apply(Window.into(
        Sessions.withGapDuration(Duration.standardSeconds(1))));

PCollection<KV<String, String>> windowedB = // ditto

// Set up join handles
TupleTag<String> tagA = new TupleTag<String>() {};
TupleTag<String> tagb = new TupleTag<String>() {};

KeyedPCollectionTuple joinInput =
    KeyedPCollectionTuple
        .of(tagA, windowedA)
        .and(tagB, windowedB);

PCollection<String> result = joinInput

    // Group streams together by shared key
    .apply(CoGroupByKey.create())

    // Eliminate all but 1-to-1 matches
    .apply(Filter.by(
        KV<String, CoGbkResult> joined ->
            Iterables.size(joined.getValue().getAll(tagA)) == 1
            && Iterables.size(joined.getValue().getAll(tagB)) == 1))

    // The key is all we care about
    .apply(Keys.create());

集合result包含具有近同步匹配但在一秒内没有重复的字符串。您的真实用例可能需要进行一些调整。

如果你想分别对两个流进行重复数据删除,那就稍微复杂一些,但不要太多。您需要为每个流单独进行会话和GroupByKey,然后根据您希望窗口连接输出的方式重新窗口。