我正在使用Spark Streaming + Kafka将数据提取到HDFS中。
val ssc = new StreamingContext(sparkContext, Seconds(30))
val messageRecBased = KafkaUtils.createStream(ssc, zkQuorum, group, topic)
.map(_._2)
每30秒,Kafka队列中的所有数据都将存储在HDFS的单独文件夹中。某些文件夹包含一个名为part-00000的空文件,因为相应的批处理间隔(30秒)内没有数据。 我使用以下行来过滤这些文件夹:
messageRecBased.filter { x => x.size == 0 }
messageRecBased.repartition(1).saveAsTextFiles("PATH")
但它不起作用,它仍然会生成带有空文件的文件夹。
答案 0 :(得分:1)
如果您查看DStream.saveAsTextFiles()方法定义,它只会向RDD.saveAsObjectFile
中的每个RDD
生成DirectKafkaInputDStream
。
def saveAsObjectFiles(prefix: String, suffix: String = ""): Unit = ssc.withScope {
val saveFunc = (rdd: RDD[T], time: Time) => {
val file = rddToFileName(prefix, suffix, time)
rdd.saveAsObjectFile(file)
}
this.foreachRDD(saveFunc)
}
因此,您可以选择编写自己喜欢的内容,而不是使用DStream.saveAsTextFiles()
:
messageRecBased.foreachRDD{ rdd =>
rdd.repartition(1)
if(!rdd.isEmpty)
rdd.saveAsObjectFile("FILE_PATH")
}
答案 1 :(得分:0)
您可以检查分区是否为空,如果不是,则只保存RDD,如下所示。此代码应防止空RDD保存。
messageRecBased.partitions.isEmpty
答案 2 :(得分:0)
这就是我创建新目录并避免空批处理的方式。
import java.time.format.DateTimeFormatter
import java.time.LocalDateTime
messageRecBased.foreachRDD{ rdd =>
rdd.repartition(1)
val eachRdd = rdd.map(record => record.value)
if(!eachRdd.isEmpty)
eachRdd.saveAsTextFile("hdfs/location/"+DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now)+"/")
}