例如:
DataSet<Tuple1<Long>> input = env.fromElements(1,2,3,4,5,6,7,8,9);
DataSet<Tuple1<Long>> sum = input.reduce(new ReduceFunction()<Tuple1<Long>,Tuple1<Long>>{
public Tuple1<Long> reduce(Tuple1<Long> value1,Tuple1<Long> value2){
return new Tuple1<>(value1.f0 + value2.f0);
}
}
如果上面的reduce转换不是并行操作,我是否需要使用额外的两个转换'partitionByHash'和'mapPartition',如下所示:
DataSet<Tuple1<Long>> input = env.fromElements(1,2,3,4,5,6,7,8,9);
DataSet<Tuple1<Long>> sum = input.partitionByHash(0).mapPartition(new MapPartitionFunction()<Tuple1<Long>,Tuple1<Long>>{
public void map(Iterable<Tuple1<Long>> values,Collector<Tuple1<Long>> out){
long sum = getSum(values);
out.collect(new Tuple1(sum));
}
}).reduce(new ReduceFunction()<Tuple1<Long>,Tuple1<Long>>{
public Tuple1<Long> reduce(Tuple1<Long> value1,Tuple1<Long> value2){
return new Tuple1<>(value1.f0 + value2.f0);
}
}
以及为什么reduce转换的结果仍然是DataSet的实例而不是Tuple1<Long>
的实例
答案 0 :(得分:9)
reduce
和reduceGroup
都是分组操作,并应用于记录组。如果未使用groupBy
指定分组键,则数据集的所有记录都属于同一组。因此,只有一个组,reduce
和reduceGroup
的最终结果无法并行计算。
如果reduce转换是可组合的(对于任何ReduceFunction
和所有可组合的GroupReduceFunction
都是如此),Flink可以并行应用组合器。
答案 1 :(得分:7)
对你的两个问题有两个答案:
在第二个示例中,通过引入密钥使其并行。使用&#34; mapPartition()&#34;而不是复杂的解决方法,您也可以简单地编写(Java 8 Style)
DataSet<Tuple1<Long>> input = ...;
input.groupBy(0).reduce( (a, b) -> new Tuple1<>(a.f0 + b.f0);
但请注意,您的输入数据非常小,无论如何只会有一个并行任务。如果使用较大的输入,则可以看到并行预聚合,例如:
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(10);
DataSet<Long> input = env.generateSequence(1, 100000000);
DataSet<Long> sum = input.reduce ( (a, b) -> a + b );
DataSet仍然是群集中X的惰性表示。您可以继续在并行程序中使用该数据,而不会触发某些计算并将结果数据从分布式工作程序提取回驱动程序。这允许您编写更大的程序,这些程序完全在分布式工作程序上运行并且被懒惰地执行。没有数据被提取到客户端并重新分发给并行工作者。
特别是在迭代程序中,这非常强大,因为整个循环无需涉及客户端就需要重新部署运算符。
你总能得到&#34; X&#34;通过调用&#34; dataSet.collext()。get(0);&#34; - 这使得明确表示应该执行和获取某些内容。