Google cloud dataflow 数据流上的重复数据流消除|在数据流服务上运行服务

Google cloud dataflow 数据流上的重复数据流消除|在数据流服务上运行服务,google-cloud-dataflow,Google Cloud Dataflow,我想以窗口方式基于ID对数据流进行重复数据消除。我们接收到的流已经存在,我们希望在N小时时间窗口内删除匹配的数据。一种直接的方法是使用外部密钥存储(BigTable或类似的东西),我们在其中查找密钥并在需要时写入,但是我们的QP非常大,这使得维护这样的服务非常困难。我提出的另一种方法是在一个时间窗口内进行分组,以便用户在一个时间窗口内的所有数据都属于同一个组,然后,在每个组中,我们使用一个单独的密钥存储服务,在其中按密钥查找重复项。因此,我对这种方法有几个问题 [1] 如果我运行groupBy转

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

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

[2] 如果可行的话,我的下一个问题是我们是否可以在运行作业的每台从机上运行这样的其他服务——在上面的示例中,我希望运行一个本地Redis,然后每个组也可以使用它来查找或写入ID

这个想法似乎偏离了数据流应该做的事情,但我相信这样的用例应该是常见的——因此,如果有更好的模型来解决这个问题,我也很期待。考虑到我们拥有的数据量,我们基本上希望尽可能避免外部查找。

1)在数据流模型中,不能保证同一台机器会在窗口中看到密钥的所有组。假设一个虚拟机死亡或添加了新的虚拟机,并在它们之间分割工作以进行扩展

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

请注意,如果它适合您的用例,您可能希望查看并使用它

您可能还想使用它来消除元素的重复。你可以打电话:

PCollection<T> pc = ...;
PCollection<T> windowed_pc = pc.apply(
    Window<T>into(Sessions.withGapDuration(Duration.standardMinutes(N hours))));
PCollection pc=。。。;
PCollection加窗的_pc=pc.apply(
Windowinto(Sessions.withGapDuration(Duration.standardMinutes(N小时)));
每个新元素将不断延长窗口的长度,以便在间隙闭合之前不会闭合。如果还对下游GroupByKey应用AfterCount推测触发器1和AfterWatermark触发器。触发器将尽快触发,这将是在它看到至少一个元素之后,然后在会话关闭时再次触发。在GroupByKey之后,您将拥有一个DoFn,该DoFn根据窗格信息([],[])筛选出一个不是提前触发的元素

DoFn(T->KV)
|
\|/
进入(会话窗口)
|
\|/
按键分组
|
\|/
DoFn(基于窗格信息的过滤器)

你的描述有点不清楚,你能提供更多的细节吗?

很抱歉不清楚。我尝试了一下你提到的设置,除了早期和晚期点火部分,它正在处理较小的样本。我有几个后续问题,与扩大规模有关。另外,我希望我能给你更多关于具体情况的信息

所以,我们有传入的数据流,其中的每一项都可以通过其字段唯一地标识。我们也知道重复发生的时间相隔很远,现在,我们关心的是6小时内发生的重复。关于数据量,我们每秒至少有10万个事件,跨越100万个不同的用户-因此在这6小时的时间内,我们可以将数十亿个事件输入管道

在这种背景下,我的问题是 [1] 对于按键进行的会话,我应该在类似

PCollection<KV<key, T>> windowed_pc = pc.apply(
        Window<KV<key,T>>into(Sessions.withGapDuration(Duration.standardMinutes(6 hours))));
PCollection窗口化的\u pc=pc.apply(
Windowinto(Sessions.withGapDuration(持续时间.标准分钟(6小时));
其中,
key
是我前面提到的3个ID的组合。根据会话的定义,只有在这个KV上运行它,我才能管理每个密钥的会话。这意味着数据流在任何给定时间都会有太多的开放会话等待它们关闭,我担心它是否会扩展,或者会遇到瓶颈

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

[3] 如果[1]中的解决方案是一个问题,另一种方法是将会话的
键减少为
用户id,会话id
忽略
序列id
,然后在每个结果窗口顶部运行
RemovedUpplicates
。这可能会减少开放会话的数量,但仍然会留下大量的开放会话(每个用户#个用户*#个会话),很容易达到数百万。FWIW,我不认为我们只能通过
用户id
进行会话,因为会话可能永远不会结束,因为同一用户的不同会话可能会不断出现,并且在这种情况下确定会话间隔变得不可行

希望这次我的问题更清楚一点。请让我知道我的任何方法都能最好地利用数据流,或者如果我遗漏了什么


感谢

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

在这次会议之后,我
PCollection<KV<key, T>> windowed_pc = pc.apply(
        Window<KV<key,T>>into(Sessions.withGapDuration(Duration.standardMinutes(6 hours))));
events.apply(
    WithKeys.<String, EventInfo>of(new SerializableFunction<EventInfo, String>() {
        @Override
        public java.lang.String apply(EventInfo input) {
            return input.getUniqueKey();
        }
    })
)
.apply(
    Window.named("sessioner").<KV<String, EventInfo>>into(
        Sessions.withGapDuration(mSessionGap)
    )
    .triggering(
        AfterWatermark.pastEndOfWindow()
        .withEarlyFirings(AfterPane.elementCountAtLeast(1))
    )
    .withAllowedLateness(Duration.ZERO)
    .accumulatingFiredPanes()
);