Apache Flink:使用mapPartition

时间:2017-06-30 06:32:29

标签: java apache-flink

我正在尝试一个简单的Flink程序,只需要一个文件,就可以反转文件中的字符串。把它写出来。

该程序有效,只有各行无序。

E.g。

文件输入

Thing,Name
Person,Vineet
Fish,Karp
Dog,Fido

输出文件

Fish,praK
Thing,emaN
Person,teeniV
Dog,odiF

我在期待:

Thing,emaN
Person,teeniV
Fish,praK
Dog,odiF

以下是我为实现这一目标而编写的程序:

package testflink;

import java.util.Iterator;
import java.util.StringJoiner;

import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.operators.DataSource;
import org.apache.flink.core.fs.FileSystem.WriteMode;
import org.apache.flink.util.Collector;

public class BatchJob {

    public static void main(String[] args) throws Exception {
        final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        System.err.println(env.getParallelism());
        DataSource<String> file = env.readTextFile("./data.csv");
        file.mapPartition((Iterable<String> values, Collector<String> out) -> {
            System.err.println("************* " + out.hashCode() + " Begin");
            Iterator<String> iterator = values.iterator();
            while (iterator.hasNext()) {
                String tuple = iterator.next();
                System.err.println("************* " + out.hashCode() + tuple);
                String[] split = tuple.split(",");
                String tuple1Rev = new StringBuilder(split[1]).reverse().toString();
                out.collect(new StringJoiner(",").add(split[0]).add(tuple1Rev).toString());
            }
            System.err.println("************* " + out.hashCode() + " End");
        }).returns(String.class).writeAsText("./dataO.csv", WriteMode.OVERWRITE).setParallelism(1);
        env.execute("Flink Batch Java API Skeleton");
        System.out.println("Done");
    }
}
  • 是否可以维持输入顺序?有没有好的解决方法?
  • 我知道我正在阅读csv&amp;当有readAsCsv()方法可用时拆分字符串。问题是csv每行/元组可以有一个动态数量的comlumns。我无法弄清楚如何将其转换为具有每个元组的动态列数的DataSource。 MapPartition需要定义的类型 - 如何在运行时替换Tuple0 - Tuple25
  • 最后一个问题 - 我可以限制分区永远不会超过Iterable<String> values参数中的n个值吗?

提前致谢! :)

1 个答案:

答案 0 :(得分:3)

Flink的mapPartition维护每个并行分区中的记录顺序。但是,您的用例中的问题是如何将数据分发到MapPartition运算符的并行任务。

您正在使用TextInputFormat将输入文件划分为多个输入拆分,这些输入拆分由数据源运算符的并行实例独立处理。每个数据源实例在本地将其所有记录转发到后续的MapPartition操作符,并将其结果记录转发到接收器。管道如下所示:

source_1 -> mapPartition_1 -> sink_1
source_2 -> mapPartition_2 -> sink_2
source_3 -> mapPartition_3 -> sink_3
...

因此,从源代码开始,所有记录都按顺序处理。但是,由于输入拆分被随机分配给源任务并且接收器独立运行(无协调),因此输出仅部分排序(从同一拆分读取的记录是有序的)。

将源的并行性设置为1将无济于事,因为它将以循环方式将结果记录发送到后续任务,以利用后续运​​算符的并行性。将整个作业的并行性设置为1也无济于事,因为单个源任务仍然可以按随机顺序处理拆分。我所知道的唯一解决方案是在写入结果之前将每个输入记录编号为sorting on that number (with range partitioning for parallel processing)