Apache Flink - 为输入分配唯一ID

时间:2016-07-27 16:00:01

标签: apache-flink

我正在加载CSV文件,并使用自定义地图功能将每一行转换为POJO。对于我的程序逻辑,我需要每个POJO一个从0到n的唯一id(其中n是总行数)。我的问题是,我可以使用转换函数为每个POJO分配一个唯一的ID(例如初始行号)吗?理想的方法是在UDF中获取Iterable并在迭代输入元组时递增变量,最后输出相应的POJO。我的代码目前看起来像这样:

DataSet<MyType> input = env.readCsvFile("/path/file.csv")
  .includeFields("1111")
  .types(String.class, Double.class, Double.class,Double.class)
  .map(new ParseData());

其中ParseData将元组转换为MyType POJO。

是否有实现此任务的最佳做法?

1 个答案:

答案 0 :(得分:3)

棘手的部分是,您在分布式系统中运行代码,因此ParseData函数的并行实例彼此独立运行。

您仍然可以使用ParseData中的本地ID计数器分配唯一ID。避免重复的技巧是正确的初始化和计数器增量。假设你有四个并行性,你会得到四个ParseData个实例(我们称之为PD1 ... PD4)。您将执行以下ID分配:

PD1: 0, 4, 8, 12, ...
PD2: 1, 5, 9, 13, ...
PD3, 2, 6, 10, 14, ...
PD4: 3, 7, 11, 15, ...

您可以通过初始化具有不同值的并行实例(详情如下)来完成此操作,并通过并行性(即ID += parallelism)增加每个实例中的计数。

在Flink中,并行函数的所有实例都会自动获得一个唯一的编号(所谓的任务索引)。您只需使用此号码初始化您的ID计数器即可。您可以通过RuntimeContext.getIndexOfThisSubtask()获取任务索引。您还可以通过RuntimeContext.getNumberOfParallelSubtasks()

接收运算符/函数并行性

https://ci.apache.org/projects/flink/flink-docs-master/api/java/org/apache/flink/api/common/functions/RuntimeContext.html

要让RuntimeContext使用RichMapFunction来实施ParseData并在getRuntimeContext()中致电open()

https://ci.apache.org/projects/flink/flink-docs-master/api/java/org/apache/flink/api/common/functions/RichFunction.html

像这样(只显示相关方法):

class ParseDate extends RichMapFunction {
    private long parallelism;
    private long idCounter;

    public void open(Configuration parameters) {
        RuntimeContext ctx = getRuntimeContext();
        parallelism = ctx.getNumberOfParallelSubtasks();
        idCounter = ctx.getIndexOfThisSubtask();
    }

    public OutputDataType map(InputDataType value) {
        OutputDataType output = new OutputDataType();
        output.setID(idCounter);
        idCounter += parallelism;
        // further processing
        return output;
    }
}