在执行情况下,Spark如何在执行器/任务之间重新调整RDD。失败还是动态洗牌?

时间:2018-08-22 14:16:07

标签: apache-spark google-cloud-dataproc

我正在考虑将一组可抢占实例添加到我在Google Could Dataproc上运行的Spark作业的Worker池中,但是我试图了解如果其中某些实例被杀死会发生什么情况。我目睹了Spark执行某种本机操作(例如使用SparkSQL等)时会发生什么,并且看起来它设法保留了RDD的“弹性”元素。

但是,对于由.forEach().forEachPartition()之类的自定义编写的函数处理的RDD,RDD如何精确地处理RDD?如果正在处理此类任务的工人被杀,究竟会发生什么?

具体来说,假设.forEachPartition() Java代码看起来像这样:

public void test(JavaRDD<String> RDD)
{
    RDD.foreachPartition(new VoidFunction<Iterator<String>>(){
        private static final long serialVersionUID = 1L;

        @Override
        public void call(Iterator<String> t) throws Exception
        {
            Queue<String> elementQ = new LinkedList<>();
            while (t.hasNext())
                elementQ.offer(t.next());

            while(elementQ.size() >0)
            {
                String curElement = elementQ.remove();
                System.out.println("Doing something with element " + curElement);
                boolean condition = false;
                if(condition)
                    elementQ.offer(curElement);
            }
        }});
}

当任务实例最初启动时,它将采用分配给它的RDD中的所有元素,并将它们放入队列。然后,它将继续遍历此队列-根据某些内部逻辑,要么删除已处理的元素,要么将其放回以备不时之需。

如果执行这些任务之一的工作人员被杀,究竟发生了什么?是否将最初分配给它的所有RDD元素重新分配给其他工人上的其他任务?还是没有办法以编程方式标记哪些元素已被“处理​​”以及哪些元素待处理?

我还注意到,如果使用 yarn shuffle服务 启用了动态分配,则Spark有时会开始认为某些任务正在执行太长而无法完成,它会尝试在其他任务中重新分配RDD。这可能可能非常有用,但是再次说明这种重新分配是如何发生的,有没有办法在.forEachPartition函数调用中以编程方式控制它?

1 个答案:

答案 0 :(得分:1)

Dynamic resource allocation在Spark中不会在其他任务中重新分配RDD,而是根据工作量扩展执行程序的数量。

关于使用可抢占实例,在实例被抢占的情况下,该实例上的工作会丢失并重新分配给其他实例,这会使作业进度受阻。