我对spark的了解是初学者级的,我创建了一个程序,它将从目录中读取所有文件并应用一些转换并将结果保存到HDFS中。我使用的是Spark + Yarn。
IIUC,我的工作只有1个阶段和5个任务。现在,由于我的目录有22个文件,我假设将有22个分区(假设文件大小<块大小),并且这5个任务中的每一个都将在每个分区上执行。
我提供了4个执行程序,我可以看到4个执行程序正在Spark UI上运行。
问题
我希望每次执行程序完成分区上的所有任务时,驱动程序都会收到10条记录,但它并没有这样做。相反,它看起来像驱动程序只打印一个分区的输出。我做错了什么?或者我的理解错了吗?
以下是代码 -
没什么特别的;只需应用一堆转换并修改输入行并将其保存到HDFS中。
@Override
public void process() {
// _inputDirectoryName has 22 files inside it.
JavaRDD<String> linesRDD = _context.textFile(_inputDirectoryName);
JavaRDD<StringBuilder> resultRDD = linesRDD
.filter(row -> !AirlineDataUtils.isHeader(row))
.map(row -> AirlineDataUtils.getSelectResultsPerRow(row))
.map(new Function<String[], StringBuilder>() {
private static final long serialVersionUID = -3504370368751118677L;
@Override
public StringBuilder call(String[] arrayRow) throws Exception {
String delayType = null;
int departureDelay = AirlineDataUtils.parseMinutes(arrayRow[8], 0);
int arrivalDelay = AirlineDataUtils.parseMinutes(arrayRow[9], 0);
if(departureDelay >= _delayInMinutes && arrivalDelay >= _delayInMinutes) {
delayType = "B";
} else if(departureDelay >= _delayInMinutes){
delayType = "D";
} else if (arrivalDelay >= _delayInMinutes) {
delayType = "O";
}
if(delayType != null) {
return AirlineDataUtils.mergeStringArray(arrayRow, ",").append(delayType);
} else {
return null;
}
}
})
.filter(row -> row != null);
resultRDD.saveAsTextFile(_outputFileName);
resultRDD.take(10).forEach(System.out :: println);
}
以下是我开火的命令 -
spark-submit --class com.sanjeevd.sparksimple.airlines.JobRunner
--master yarn
--deploy-mode client
--driver-memory=1g
--executor-memory 1g
--executor-cores 1
--num-executors 4
--driver-java-options "$DRIVER_JAVA_OPTS"
--conf spark.yarn.jars=hdfs://sanjeevd.xxx:9000/user/spark/share/lib/*.jar SparkSimple-0.0.1-SNAPSHOT.jar select-all-where
我得到的输出是
SLF4J:类路径包含多个SLF4J绑定。 SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/slf4j-log4j12-1.7.5.jar!/ org / slf4j /中找到绑定IMPL / StaticLoggerBinder.class] SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/avro-tools-1.7.6-cdh5.4.7.jar中找到绑定!/组织/ SLF4J / IMPL / StaticLoggerBinder.class] SLF4J:有关解释,请参阅http://www.slf4j.org/codes.html#multiple_bindings。 SLF4J:实际绑定的类型为[org.slf4j.impl.Log4jLoggerFactory] 14分之10/ 1987,0741,0912,SAN,SFO,447,91,79,11,23B 10/15 / 1987,0729,0903,SAN,SFO,447,94,79,-1,14O 17分之10/ 1987,0741,0918,SAN,SFO,447,97,79,11,29B 19分之10/ 1987,0749,0922,SAN,SFO,447,93,79,19,33B 23分之10/ 1987,0731,0902,SAN,SFO,447,91,79,1,13O 24分之10/ 1987,0744,0908,SAN,SFO,447,84,79,14,19B 26分之10/ 1987,0735,0904,SAN,SFO,447,89,79,5,15O 28分之10/ 1987,0741,0919,SAN,SFO,447,98,90,16,24B 29分之10/ 1987,0742,0906,SAN,SFO,447,84,90,17,11B 10月1日/ 1987,0936,1035,SFO,RNO,192,59,46,21,34B SLF4J:类路径包含多个SLF4J绑定。 SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/slf4j-log4j12-1.7.5.jar!/ org / slf4j /中找到绑定IMPL / StaticLoggerBinder.class] SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/avro-tools-1.7.6-cdh5.4.7.jar中找到绑定!/组织/ SLF4J / IMPL / StaticLoggerBinder.class] SLF4J:有关解释,请参阅http://www.slf4j.org/codes.html#multiple_bindings。 SLF4J:实际绑定的类型为[org.slf4j.impl.Log4jLoggerFactory]
答案 0 :(得分:1)
如果您仅使用take(10)
和filter
转换在RDD上调用map
,则spark将从随机分区返回10个匹配的行。 Spark以懒惰方式执行take
动作,因此它读取一个分区,如果少于10个结果,那么它会再探测4个,然后再探测20个等等,所以我假设你的代码甚至没有触及剩下的21个文件在HDFS上(你可以确保查看SparkUI)
您正在寻找的可能是foreachPartition
操作 - 它为驱动程序传递可迭代分区内容的每个分区执行一个函数,因此您可以轻松打印样本行。