我们正在使用Spark 1.4进行Spark Streaming。 Kafka是Spark Stream的数据源。
记录每秒都在Kafka上发布。我们的要求是将Kafka上发布的记录每分钟存储在一个文件夹中。流将每五秒读取一次记录。例如,在1200 PM和1201PM期间发布的记录存储在文件夹“1200”中;在1201PM到1202PM之间的文件夹“1201”等等。
我写的代码如下
//First Group records in RDD by date
stream.foreachRDD (rddWithinStream -> {
JavaPairRDD<String, Iterable<String>> rddGroupedByDirectory = rddWithinStream.mapToPair(t -> {
return new Tuple2<String, String> (targetHadoopFolder, t._2());
}).groupByKey();
// All records grouped by folders they will be stored in
// Create RDD for each target folder.
for (String hadoopFolder : rddGroupedByDirectory.keys().collect()) {
JavaPairRDD <String, Iterable<String>> rddByKey = rddGroupedByDirectory.filter(groupedTuples -> {
return groupedTuples._1().equals(hadoopFolder);
});
// And store it in Hadoop
rddByKey.saveAsNewAPIHadoopFile(directory, String.class, String.class, TextOutputFormat.class);
}
由于Stream每五秒处理一次数据,因此saveAsNewAPIHadoopFile会在一分钟内多次调用。这会导致每次都覆盖“Part-00000”文件。
我原以为在“directory”参数指定的目录中,即使我有一个sinlge工作节点,saveAsNewAPIHadoopFile也会继续创建part-0000N文件。
非常感谢任何帮助/替代方案。
感谢。
答案 0 :(得分:1)
在这种情况下,您必须自己构建输出路径和文件名。只有在DStream
上直接调用输出操作时,增量文件命名才有效(不是每RDD
}。
stream.foreachRDD
中的参数函数可以获得每个微批次的Time
信息。参考Spark documentation:
def foreachRDD(foreachFunc: (RDD[T], Time) ⇒ Unit)
因此,您可以按如下方式保存每个RDD
:
stream.foreachRDD((rdd, time) -> {
val directory = timeToDirName(prefix, time)
rdd.saveAsNewAPIHadoopFile(directory, String.class, String.class, TextOutputFormat.class);
})
答案 1 :(得分:0)
您可以尝试--
将过程分为2个步骤:
Step-1 :- Write Avro file using saveAsNewAPIHadoopFile to <temp-path>
Step-2 :- Move file from <temp-path> to <actual-target-path>
希望这会有所帮助。