我有一个RDD(RDD [(String,Iterable [Event])],它的键代表一年中的一个月,值是该月发生的数百万个事件。
我想遍历每个键并创建键事件的RDD。 然后,我想为当月事件的每一天创建一个事件RDD,以便可以将它们发送到相关的s3位置(“目录”结构为bucketName / year / month / day)。
问题是,您似乎无法在另一个RDD的foreach中创建RDD。 因此,我不确定如何在不需要将整个主RDD加载到内存的情况下实现我想要的功能(这肯定会耗尽驱动程序的内存,并首先使Spark失效)。
也许有一种方法可以使用Spark实现我想要的功能,但我对此并不了解,并希望这里的人能为您提供帮助。
这是我目前的代码:
private def store(
eventsByMonth: RDD[(String, Iterable[Event])]
)(
implicit sqlContext: SQLContext
): Try[Unit] =
Try(
eventsByMonth
.foreach {
case (_, events: Iterable[Event]) =>
writeToS3Files(sqlContext.sparkContext.parallelize(events.toSeq))
}
)
private def writeToS3Files(events: RDD[Event])(
implicit sqlContext: SQLContext
): Try[Unit] =
Try(
// outputFilePath will contain the day that these events are related to.
events.groupBy(_.outputFilePath).foreach {
case (filePath: String, eventsForFile: Iterable[Event]) =>
writeToS3File(filePath, sqlContext.sparkContext.parallelize(eventsForFile.toSeq))
}
)
private def writeToS3File(filePath: String, events: RDD[Event]): Try[Unit] = {
val fileNameWithPath = s"${filePath}${UUID.randomUUID().toString}.gz"
Try(events.saveAsTextFile(fileNameWithPath, classOf[GzipCodec]))
}
答案 0 :(得分:1)
我假设有某种方法可以确定事件发生的月份(例如,day(类型为Int)是事件的属性)。
您可以将RDD [(String,Iterable [Event]]转换为PairRDD [(K,V)],其中键(K)是事件发生的月份和月份以及值(V)所有的事件都发生在一个月的这一天。之后,您可以轻松地将数据转储到数据库中。
val eventsByMonthAndDate = eventsByMonth.flatMap { case (month, events) => events.map(e => ((month, e.day), e)) }
eventsByMonthAndDate.groupby(_._1).foreach(writeToDB)