我想知道执行spark job时从hdfs到spark作业的数据流。据我所知,当sc.textFile("...")
和动作命令执行时,存储在HDFS中的数据被分区,然后它们被加载到spark端。例如,HDFS中有30Gb数据,并执行操作,然后创建分区数(可能是30Gb / 128Mb,默认),它们被分发到工作节点,spark将处理分区数据。
当工作节点的内存不足时(例如500mb或1Gb /节点),我认为传递给每个工作节点的分区不能同时在内存中。因此,我认为每个节点处理它们必须处理的总分区中的几个分区,然后将处理后的分区交换到磁盘中,然后接受下一个分区。在此过程中,即使内存资源不大,工作节点也可以处理所有分区。
在这个过程中,我认为即使内存资源很少,spark也可以处理大量数据。但是,当我用数据实验上面的概念时,我遇到了java堆空间错误。当然,我的代码有不同的转换,包括sc.textFile("...")
,但它有非常基本的操作,如下所示。
JavaRDD<String> data = sc.textFile("...")
JavaPairRDD<String, List<String>> retRDD = data.flatMapToPair(new PairFlatMapFunction<String, String, List<String>>() {
@Override
public Iterable<Tuple2<String, List<String>>> call(String s) throws Exception {
List<Tuple2<String, List<String>>> rtn = new ArrayList<Tuple2<String, List<String>>>();
String s1 = s;
String []splitted = s1.split("\t");
long ckAsLong = Long.parseLong(splitted[2]);
int batchId = (int) (ckAsLong / batchSize);
List<String> temp = new ArrayList<String>();
temp.add(splitted[2] + "\t" + splitted[3]);
rtn.add(new Tuple2<String, List<String>>(
splitted[0] + "\t" + splitted[1] + "\t" + batchId + "\t",
temp
));
return rtn;
}
});
retRDD.count() //action is performed
我有四个节点,我给每个节点500mb,然后当我运行spark-summit时,在更早的步骤发生了堆空间错误。向节点提供1Gb时,程序完成且没有错误。
根据我的经验,我认为spark作业尝试从总分区加载特定分区,然后处理它们。例如,将10个分区分配给node1,然后node1首先处理3个中的3个,然后将它们移动到磁盘中,然后加载下一个分区,依此类推。因为我认为特定分区的总大小高于执行程序的内存大小,所以发生了Java堆空间。
我的问题如下。 如果我的猜测是正确的,那么当内存不足时,如何找出火花加载的特定分区会在第一时间形成HDFS?否则你可以纠正我的假设,以便我能够准确地理解火花概念。
谢谢!