我正在使用Kafka Spark Streaming来获取流媒体数据。
val lines = KafkaUtils.createDirectStream[Array[Byte], String, DefaultDecoder, StringDecoder](ssc, kafkaConf, Set(topic)).map(_._2)
我正在使用此DStream并处理RDD
val output = lines.foreachRDD(rdd =>
rdd.foreachPartition { partition =>
partition.foreach { file => runConfigParser(file)}
})
runConfigParser
是一个JAVA方法,它解析文件并生成一个我必须保存在HDFS中的输出。因此,多个节点将处理RDD并将输出写入单个HDFS文件。因为我想在艾滋病病毒中加载这个病毒。
我应该输出runConfigParser
的结果并使用sc.parallze(output).saveAsTextFile(path)
,这样我的所有节点都会将RDD输出写入单个HDFS文件。这种设计有效吗?
我将在HIVE中加载这个单独的HDFS文件(将作为其流数据不断更新)并使用Impala进行查询。
答案 0 :(得分:1)
没有。因为您需要一个HDFS文件saveAsTextFile
,它为RDD分区创建了许多HDFS文件,所以不能满足您的要求。
为了获得一个HDFS文件,reduce
/ collect
输出并调用HDFS Java API来创建HDFS文件。这种方法效率很低,因为所有输出都需要在最后一次Spark动作时来到Spark驱动程序。
答案 1 :(得分:1)
你可以使用一个功能来"合并" saveAsTextFile
的结果。像这样:
import org.apache.hadoop.fs._
def saveAsTextFileAndMerge[T](hdfsServer: String, fileName: String, rdd: RDD[T]) = {
val sourceFile = hdfsServer + "/tmp/"
rdd.saveAsTextFile(sourceFile)
val dstPath = hdfsServer + "/final/"
merge(sourceFile, dstPath, fileName)
}
def merge(srcPath: String, dstPath: String, fileName: String): Unit = {
val hadoopConfig = new Configuration()
val hdfs = FileSystem.get(hadoopConfig)
val destinationPath = new Path(dstPath)
if (!hdfs.exists(destinationPath)) {
hdfs.mkdirs(destinationPath)
}
FileUtil.copyMerge(hdfs, new Path(srcPath), hdfs, new Path(dstPath + "/" + fileName), false, hadoopConfig, null)
}