繁体   English   中英

减少键控流中的函数行为

Reduce function behaviour in keyed streams

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

对于我们的一个用例,我们需要根据文件中的更改重做一些计算,然后广播该文件的结果,以便我们可以在另一个流中使用它。

程序的生命周期,几乎是这样的:

数据流 1:监控文件 -> 检测一些变化 -> 重新处理文件中的所有元素 -> 计算一个结果 -> 广播

数据流 2:一些转换 -> 在使用所有现有广播元素的同时对 DS2 中的每个元素做一些事情(在广播元素中可以容忍一些数据丢失一段时间)

我将给出一些代码示例来更好地解释问题所在:

所以这是 DS1:映射每个元素,将它们发送到减速器,然后计算总数

env.readFile(format, clientPath, FileProcessingMode.PROCESS_CONTINUOUSLY, interval)
    .map(new Adder())
    .keyBy(Map::size)
    .reduce(new Reducer());

这是映射阶段,它只是从一行创建一个哈希图

public static class Adder extends RichMapFunction<String, Map<String, String>> {
  private static final long serialVersionUID = 1L;

  @Override
  public Map<String, String> map(String string) throws Exception {
    String[] strings = string.split("=");
    HashMap<String, String> hashMap = new HashMap<>();
    hashMap.put(strings[0], strings[1]);
    return hashMap;
  }
}

这是最后一步,减速器。 获取来自映射器的所有减少元素,然后返回总数,单个哈希图

public static class Reducer extends RichReduceFunction<Map<String, String>> {
  private static final long serialVersionUID = 1L;

  @Override
  public Map<String, String> reduce(Map<String, String> stringStringMap, Map<String, String> t1) throws Exception {
    stringStringMap.putAll(t1);
    return stringStringMap;
  }
}

然后像下面的代码片段一样广播 DS1。

MapStateDescriptor<String, String> descriptor = new MapStateDescriptor<>("Brodcasted map state", Types.STRING, Types.STRING);
BroadcastStream<Map<String, String>> broadcastedProperties =  clientProperties.broadcast(descriptor); 
ds2.connect(broadcastedProperties).process(new EventListener(properties));

在给定时间内使用以下元素

Time    Document
T1      K1=V1, K2=V2
T2      K2=V2
T3      K3=V3, K1=V4

当我运行我们的程序时,我期望的是:

Time    Broadcasted Elements
T1      K1=V1, K2=V2
T2      K2=V2
T3      K3=V3, K1=V4

我看到的是这样的:

Time    Broadcasted Elements
T1      K1=V1, K2=V2
T2      K1=V1, K2=V2
T3      K1=V4, K2=V2, K3=V3

我为克服这个问题所做的只是简单地在数据流上打开一个窗口,并使用带有累加器而不是减速器的聚合函数,但我更愿意使用非窗口方法。

我做了一些调试,我已经意识到,即使在映射阶段它只映射当时可用的元素,在减少阶段它根据以前的状态减少(我的意思是结果time – 1 ) + 此时的所有元素。 我发现在 reduce 阶段有一个不可见的状态很奇怪。 从我的角度来看,它应该仅基于直接来自映射器的元素。 也许我对 Flink 中的 reduce 的理解是错误的,但我很想得到一些澄清。

2 个回复

是的,当 Flink 的任何内置聚合器(例如 sum、max、reduce 等)应用于流时,它都会以增量的、有状态的方式聚合整个流。 或者更准确地说,这是在 KeyedStreams 上完成的,聚合是在逐个键的基础上完成的,但是以一种持续的、无限制的方式完成的。 例如,如果您在整数流 1, 2, 3, 4, 5, ... 上使用 sum() 那么 sum() 将产生流 1, 3, 6, 10, 15, ... 。 在您的情况下,reduce() 将产生一个不断更新的流,其中将包含越来越多的键/值对。

如果您要按时间键控流,那么您应该得到您正在寻找的结果,但键控状态仍将永远保持,这可能会出现问题。 我建议您使用窗口 API,或者使用 RichFlatMap 或 ProcessFunction 之类的东西,您可以在其中直接管理状态。

没有窗口的reduce函数将是一个滚动reduce。 如果要在滚动减少之间保持一致的状态,请使用状态对象来保存状态,稍后检索并更新它。 我认为这也是@David Anderson 对 RichReduceFunction 提出的建议。

public static class Reducer extends RichReduceFunction<Map<String, String>> {     
private static final long serialVersionUID = 1L;
private final MapStateDescriptor<String, String> mapStateDesc = new MapStateDescriptor<>("myMapState", BasicTypeInfo.STRING_TYPE_INFO, BasicTypeInfo.STRING_TYPE_INFO); 

@Override
public void open(Configuration parameters) {
        getRuntimeContext().getMapState(this.mapStateDesc);
}

@Override     
public Map<String, String> reduce(Map<String, String> stringStringMap, Map<String, String> t1) throws Exception {       
     MapState<String, String> myMapState = getRuntimeContext().getMapState(this.mapStateDesc);
     HashMap<String, String> newMap = new HashMap<>();
     //updating your map from previous state 
     for(Map.Entry<String,String> entry : myMapState.entries()) {
        newMap.put(entry.getKey(),entry.getValue());
     }       
     newMap.putAll(stringStringMap);       
     newMap.putAll(t1);
     //update the state with latest data set
     myMapState.putAll(newMap);
     return newMap;     
} 
1 “对键控数据流进行滚动式缩减”是什么意思?DataStream reduce函数

我试图理解键控数据流上的“滚动”减少。 我有一种情况,我想忽略某些在特定时间到达的消息。 例如,第一个事件-&gt;在事件之间-&gt;最后一个事件,我只想捕获第一个和最后一个事件,并想从流中跳过/删除事件之间。 而且重要的是,它应该在某些密钥的基础上发生。在我的情况下,当我应用密钥时 ...

2 python中reduce函数的行为

我对reduce函数的行为感到困惑。 在第一个例子中,我得到了预期的结果:(1-1 / 2)*(1-1 / 3)= 1/3 在第二个例子中,我没有得到预期的结果:(1-1 / 2)*(1-1 / 3)*(1-1 / 5)= 0.2666666 有人可以解释一下我错过了什 ...

6 无法加入 Kafka Streams 的相同键控主题

我最近在流应用程序中遇到了一个我以前没有遇到过的问题,并且很难跟踪与键控/连接(以及更新后的分区)相关的问题。 我有两个主题(raw_events 和 processing_users),它们的键控完全相同,但是当我尝试对这两个主题执行联接时,尽管键控相同,但只有部分联接成功。 工作流(上下文) ...

7 KeyBy不会为不同的键创建不同的键流

我正在读取一个简单的JSON字符串作为输入,并基于两个字段A和B键入流。 但是KeyBy会针对B不同值但针对A和B的特定组合生成相同的密钥流。 输入: 这是我的Flink代码的核心逻辑: GenericDataObject是一个POJO,具有三个字段A , B和C ...

8 如何为通用 ArrayList 编写 reduce 函数通过流

我的任务是实现一个自定义类来模仿 Set 的属性(不使用 Set 的任何数据结构)。 因此,我选择将 T 类型的元素作为类的字段存储到 ArrayList 中。 我的任务之一是实现一个 reduce 函数,它接收一个种子和一个二元运算符来返回减少的值(不使用显式循环,即使用流),以便观察到以下情 ...

9 使用reduce(3参数)函数传递集合 - 流java 8

我试图使用java 8的流使用前两个值计算值的乘法。 我想调用一个返回数组/列表/集合的函数。 我正在创建一个List并向其添加1,2。 假设列表名称是结果。 现在问题是尝试将结果传递到流中以使用流继续使用新值更新列表。 根据java教程,尽管效率低下,但它是可能的。 ...

10 在没有窗口的键控流上减少Flink

我阅读了源代码,将每个结果都减少到下游。 我想通过没有窗口的键减少流, 如果在窗口上缩小,则flink将在水印到达时将元素前移到下游,因此flink如何确定无窗口的缩小完成。 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM