TLDR:通过saveAsTextFile
从数据框保存时,rdd
上FileOutputCommitter
的{{1}}调用失败且找不到write.format(...).save(...)
,并使用FileOutputCommitter
。问题似乎与环境有关,因为我可以在一个环境(本地)中执行此操作,但不能在可能的类似环境(aws emr)中执行。据我所知,配置也是如此。
情景:
修改后的mapred-site.xml
包括:
<property>
<name>mapreduce.fileoutputcommitter.algorithm.version</name>
<value>2</value>
</property>
<property>
<name>spark.hadoop.mapred.output.committer.class</name>
<value>org.apache.hadoop.mapred.FileOutputCommitter.class</value>
</property>
<property>
<name>mapred.output.committer.class</name>
<value>org.apache.hadoop.mapred.FileOutputCommitter.class</value>
</property>
使用jars
和spark-default.conf
向spark.driver.extraClassPath
添加了正确的spark.executor.extraClassPath
。此设置在spark web ui的“环境”选项卡中确认。
问题Repro Local(OS X)运行正常:
In [2]: df = [tuple(range(3))]
In [3]: df = spark.createDataFrame([tuple(range(3))], ['one', 'two', 'three'])
In [4]: df.show()
+---+---+-----+
|one|two|three|
+---+---+-----+
| 0| 1| 2|
+---+---+-----+
In [5]: df.rdd.saveAsTextFile('test_output.txt')
In [6]: df.write.format('csv').save('test_output.csv')
问题Repro AWS EMR:
>>> df = spark.createDataFrame([tuple(range(3))], ['one', 'two', 'three'])
>>> df.show()
+---+---+-----+
|one|two|three|
+---+---+-----+
| 0| 1| 2|
+---+---+-----+
>>> df.write.format('csv').save('test_output.csv')
>>> df.rdd.saveAsTextFile('test_output.txt')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/spark/python/pyspark/rdd.py", line 1519, in saveAsTextFile
keyed._jrdd.map(self.ctx._jvm.BytesToString()).saveAsTextFile(path)
File "/usr/lib/spark/python/lib/py4j-0.10.1-src.zip/py4j/java_gateway.py", line 933, in __call__
File "/usr/lib/spark/python/pyspark/sql/utils.py", line 63, in deco
return f(*a, **kw)
File "/usr/lib/spark/python/lib/py4j-0.10.1-src.zip/py4j/protocol.py", line 312, in get_return_value
py4j.protocol.Py4JJavaError: An error occurred while calling o72.saveAsTextFile.
: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class org.apache.hadoop.mapred.FileOutputCommitter.class not found
我的直觉是我在两种情况之间存在配置差异。 EMR上的数据帧保存调用正在使用FileOutputCommitter
,因为日志表明正确提供了jar
。引擎saveAsTextFile
调用saveAsHadoopFile
并且我不确定数据框编写者是否这样做。
任何人都知道我应该在哪些配置中寻求帮助saveAsTextFile
找到提供的jar
?这是一个非显而易见的hadoop配置错误吗?