我正在考虑将一组可抢占实例添加到我在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
函数调用中以编程方式控制它?
答案 0 :(得分:1)
Dynamic resource allocation在Spark中不会在其他任务中重新分配RDD,而是根据工作量扩展执行程序的数量。
关于使用可抢占实例,在实例被抢占的情况下,该实例上的工作会丢失并重新分配给其他实例,这会使作业进度受阻。