对于我们的一种用例,我们需要根据文件中的更改来重做一些计算,然后广播该文件的结果,以便我们可以在其他流中使用它。
程序的生命周期大致如下:
数据流1:受监视的文件->检测到一些更改->重新处理文件中的所有元素->计算一个结果->广播
数据流2:某些转换->在使用所有当前广播的元素的同时对DS2中的每个元素执行某些操作(某些数据丢失在广播的元素中可以忍受一段时间)
我将提供一些代码示例,以更好地解释问题所在:
这是DS1: 映射每个元素,将它们发送到reducer,然后计算总数
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
我为克服此问题所做的只是在数据流上打开一个窗口,并使用带有累加器而不是reducer的聚合函数,但我更喜欢采用非窗口方法。
我做了一些调试,我意识到,即使在map阶段,它只在那个时候映射可用的元素,而在reduce阶段,它是根据先前的状态进行缩减的(通过我时间的平均结果– 1)+此时的所有元素。我发现在还原阶段具有不可见状态非常奇怪。从我的角度来看,它应该仅基于直接来自映射器的元素。也许我对Flink中的reduce的理解是错误的,但我希望对此进行一些澄清。
答案 0 :(得分:0)
是的,当Flink的任何内置聚合器(例如sum,max,reduce等)应用于流时,它会以增量,有状态的方式聚合整个流。或更准确地说,这是在KeyedStreams上完成的,聚合是在每个键的基础上完成的,但以一种持续的,不受限制的方式进行。例如,如果您在整数1、2、3、4、5 ...的流上使用sum(),那么sum()将产生流1、3、6、10、15 ...。在您的情况下,reduce()将产生不断更新的流,其中将包含越来越多的键/值对。
如果您要按时间对流进行键控,则应该获得所需的结果,但是键控状态将永远保持不变,这可能会出现问题。我建议您要么使用窗口API,要么使用RichFlatMap或ProcessFunction之类的东西,您可以在其中直接管理状态。
答案 1 :(得分:0)
不带窗口的缩小功能将滚动减少。如果要在滚动减少之间保持一致的状态,请使用状态对象保存状态,以后再检索和更新它。我认为@David Anderson也在RichReduceFunction中提出了建议。
Sub SplitterA()
Dim x As Variant
x = Split(Range("A1").Value2, vbLf)
Range("A1").Resize(, UBound(x) + 1).Value2 = x
End Sub