Dataflow上的流重复数据删除在Dataflow服务上运行服务

时间:2016-11-12 01:49:29

标签: google-cloud-dataflow

我希望以窗口方式基于ID去除数据流。我们收到的流有,我们想删除N小时时间窗内的匹配数据。一种直接的方法是使用外部密钥存储(BigTable或类似的东西),我们查找密钥并在需要时写入但是我们的qps非常大,这使得维护这样的服务非常困难。我提出的替代方法是在一个时间窗口内对groupBy进行分组,以便时间窗口内用户的所有数据都属于同一组,然后在每个组中,我们使用单独的密钥存储服务,我们在其中查找密钥重复。所以,我对这种方法有几个问题

[1]如果我运行groupBy转换,是否可以保证每个组都将在同一个slave中处理?如果有保证,我们可以按用户ID进行分组,然后在每个组中比较每个用户的sessionid

[2]如果可行,我的下一个问题是我们是否可以在每个运行该作业的从机中运行此类其他服务 - 在上面的示例中,我希望运行本地Redis可以运行然后被每个小组用来查找或写一个ID。

这个想法似乎与Dataflow应该做的不同,但我相信这样的用例应该是常见的 - 所以如果有更好的模型来解决这个问题,我也很期待。考虑到我们拥有的数据量,我们基本上希望尽可能避免外部查找。

3 个答案:

答案 0 :(得分:2)

1)在Dataflow模型中,无法保证同一台计算机将在窗口中查看密钥的所有组。想象一下,虚拟机死机或添加了新的虚拟机,并将工作分开进行扩展。

2)欢迎您在Dataflow VM上运行其他服务,因为它们是通用的,但请注意,您必须应对主机上其他应用程序的资源需求,这可能会导致内存不足问题。

请注意,您可能需要查看RemoveDuplicates并使用它,如果它适合您的用例。

您似乎也希望使用session windows重复数据删除元素。你会打电话:

PCollection<T> pc = ...;
PCollection<T> windowed_pc = pc.apply(
    Window<T>into(Sessions.withGapDuration(Duration.standardMinutes(N hours))));

每个新元素将继续延伸窗口的长度,以便在间隙关闭之前不会关闭。如果您还在下游GroupByKey上应用AfterCount推测触发器1并使用AfterWatermark触发器。一旦它看到至少一个元素,然后在会话结束时再次触发,触发器将立即触发。在GroupByKey之后,您将拥有一个DoFn,它根据窗格信息([3],[4])筛选出不是早期触发的元素。

DoFn(T -> KV<session key, T>)
         |
        \|/
Window.into(Session window)
         |
        \|/
Group by key
         |
        \|/
DoFn(Filter based upon pane information)

从您的描述中有点不清楚,您能提供更多详细信息吗?

答案 1 :(得分:1)

很抱歉不清楚。我提供了你提到的设置,除了早期和晚期的点火部分,它正在处理较小的样品。我有几个跟进问题,与扩展这个问题有关。另外,我希望我能为您提供有关具体情况的更多信息。

因此,我们有传入的数据流,其中的每个项目都可以通过其字段进行唯一标识。我们也知道副本相隔很远,而且现在,我们关注那些在6小时之内的窗口。关于数据量,我们每秒至少有100K事件,跨越一百万不同的用户 - 因此在这6小时的窗口内,我们可以将几十亿个事件带入管道。

鉴于这种背景,我的问题是 [1]对于按密钥发生的会话,我应该在类似

的情况下运行它
PCollection<KV<key, T>> windowed_pc = pc.apply(
        Window<KV<key,T>>into(Sessions.withGapDuration(Duration.standardMinutes(6 hours))));

其中key是我之前提到的3个ID的组合。根据Sessions的定义,只有当我在这个KV上运行它时,我才能管理每个密钥的会话。这意味着Dataflow在任何给定时间都会有太多的开放会话等待它们关闭,我担心它是否会扩展或者我会遇到任何瓶颈。

[2]一旦我执行了如上所述的会话,我已经根据解雇删除了重复项,因为我只关心每个会话中的第一次触发已经破坏了重复。我不再需要RemoveDuplicates转换,我发现它是(WithKeys,Combine.PerKey,Values)的组合顺序转换,基本上执行相同的操作。这是正确的假设吗?

[3]如果[1]中的解决方案成为一个问题,另一种方法是将会话的key简化为user-id, session-id而忽略sequence-id然后,通过RemoveDuplicates在每个结果窗口的顶部运行sequence-id。这可能会减少打开会话的数量,但仍然会留下大量的开放会话(每个用户使用#users * #sessions),这些会话很容易达到数百万。 FWIW,我不认为我们只能通过user-id进行会话,因为会话可能永远不会关闭,因为同一用户的不同会话可能会继续进入,并且确定此场景中的会话差距变得不可行。

希望这次我的问题更清楚一点。请让我知道我的任何方法都能充分利用Dataflow,或者如果我遗漏了某些内容。

由于

答案 2 :(得分:0)

我尝试了更大规模的解决方案,只要我提供足够的工作人员和磁盘,管道就可以很好地扩展,尽管我现在看到了不同的问题。

在此会话之后,我在密钥上运行Combine.perKey,然后执行查看ParDo的{​​{1}},并且仅拒绝c.pane().getTiming()点击以外的任何内容。我尝试计算此EARLY中的EARLYONTIME次点击,看起来ontime-panes实际上比早期窗格更精确。我的意思是,#early-firedings仍然有一些重复,而#ontime-firings小于那个并且删除了更多的重复。这有可能发生吗?另外,我的方法是使用正确的ParDo进行重复数据删除还是可以做得更好?

Combine+ParDo