Apache flink Flink流水线中高内存需求的非并行任务集成

Apache flink Flink流水线中高内存需求的非并行任务集成,apache-flink,Apache Flink,我使用纱线簇中的Flink来处理使用各种源和汇的数据。在拓扑中的某个点上,有一个操作无法并行化,而且需要访问大量内存。事实上,我用于此步骤的API需要以数组形式输入。现在,我已经实现了类似于 ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); DataSet<Pojo> input = ... List<Pojo> inputList = input.collect(); P

我使用纱线簇中的Flink来处理使用各种源和汇的数据。在拓扑中的某个点上,有一个操作无法并行化,而且需要访问大量内存。事实上,我用于此步骤的API需要以数组形式输入。现在,我已经实现了类似于

ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
DataSet<Pojo> input = ...
List<Pojo> inputList = input.collect();
Pojo[] inputArray = inputList.toArray();
Pojo[] resultArray = costlyOperation(inputArray);
List<Pojo> resultList = Arrays.asList(resultArray);
DataSet<Pojo> result = env.fromCollection(resultList);
result.otherStuff()
ExecutionEnvironment env=ExecutionEnvironment.getExecutionEnvironment();
数据集输入=。。。
List inputList=input.collect();
Pojo[]inputArray=inputList.toArray();
Pojo[]resultArray=成本操作(输入阵列);
List resultList=Arrays.asList(resultArray);
数据集结果=环境fromCollection(结果列表);
result.otherStuff()
  • 这种解决办法似乎很不自然。是否有一种直接的方法将此任务纳入我的Flink管道
  • 我已经了解到,
    collect()
    函数不应用于大型数据集。我相信,将数据集收集到一个列表中,然后再收集一个数组,这并不是我目前最大的问题,但您是否仍然愿意将我上面所说的
    input
    写入一个文件,并从中构建一个数组
  • 我还看到了在flink中配置托管内存的方法。原则上,可以对其进行调整,以便为昂贵的操作留下足够的堆。另一方面,我担心拓扑中所有其他操作符的性能可能会受到影响。你对此有何看法
  • 您可以用一个代理键替换“collect->array->costlyOperation->array->fromCollection”步骤,该代理键对所有元组都具有唯一的值,这样您就只能得到一个分区。这是弗林克式的

    在作为
    GroupReduceFunction
    实现的代价高昂的操作本身中,您将获得一个数据迭代器。如果您不需要“一次”访问所有数据,那么也可以保护堆空间,因为您不需要将内存中的所有数据都保存在reduce中(但这当然取决于代价高昂的操作计算的内容)

    或者,您也可以调用
    reduce()。但是,您没有迭代器或输出收集器,只能计算部分聚合。(参见中的“减少”)


    使用Flink风格的操作有一个优点,即数据保存在集群中。如果执行
    collect()
    操作,结果将传输到客户端,代价高昂的操作将在客户端执行,结果将传输回集群。此外,如果输入较大,Flink会自动将中间结果溢出到光盘中。

    感谢您的快速回答!不幸的是,代价高昂的操作确实需要同时获得所有数据。因此,方法是:(1)将数据集的所有元素分组到一个集合中,然后(2)在GroupReduceFunction中聚合数组,对吗?在不引入不必要的代理密钥的情况下,是否有一种自然的方法来执行(1)?此外,您是否建议为(2)定义一个(富)GroupReduceFunction,其中输出数据集实际上只是由一个巨大的数组组成,还是有更好的方法来实现这一点?刚刚更新了我的答案。我想您需要坚持使用代理键,因为您需要迭代器和输出收集器。。。关于输出:我不会输出
    Pojo[]
    ,而是为函数中输出数组中的每个元素调用
    Collector.collect()
    。也许您不需要在内存中组装输出数组,只需要直接输出元组,而不是将它们添加到结果中。否则,只需在函数中循环数组。