Apache spark 什么';DStream.foreachRDD函数的含义是什么?

Apache spark 什么';DStream.foreachRDD函数的含义是什么?,apache-spark,spark-streaming,Apache Spark,Spark Streaming,在spark streaming中,每个数据批处理间隔总是生成一个且仅生成一个RDD,为什么我们要使用foreachRDD()来生成foreachRDD?RDD只是一个,不需要foreach。 在我的测试中,我从未见过多个RDD。数据流或“离散化流”是将连续数据流分解为小块的抽象。这被称为“微博客”。每个微批次都成为一个RDD,交给Spark进行进一步处理在每个批次间隔,为每个数据流生成一个且只有一个RDD RDD是数据的分布式集合。将其视为指向集群中实际数据所在位置的一组指针 DStream.

在spark streaming中,每个数据批处理间隔总是生成一个且仅生成一个RDD,为什么我们要使用
foreachRDD()
来生成foreachRDD?RDD只是一个,不需要foreach。 在我的测试中,我从未见过多个RDD。

数据流或“离散化流”是将连续数据流分解为小块的抽象。这被称为“微博客”。每个微批次都成为一个RDD,交给Spark进行进一步处理在每个批次间隔,为每个数据流生成一个且只有一个RDD

RDD是数据的分布式集合。将其视为指向集群中实际数据所在位置的一组指针

DStream.foreachRDD
是Spark流媒体中的“输出操作符”。它允许您访问数据流的底层RDD,以执行对数据进行实际操作的操作。例如,使用
foreachRDD
可以将数据写入数据库

这里的一个小小的思想扭曲是要理解数据流是一个有时间限制的集合。让我将其与一个经典集合进行对比:获取一个用户列表并对其应用foreach:

val userList: List[User] = ???
userList.foreach{user => doSomeSideEffect(user)}
这将对
userList
集合的每个元素应用副作用函数
doSomeSideEffect

现在,假设我们现在不知道所有的用户,所以我们无法建立他们的列表。相反,我们有一个用户流,就像人们在早上高峰时间进入咖啡馆一样:

val userDStream: DStream[User] = ???
userDstream.foreachRDD{usersRDD => 
    usersRDD.foreach{user => serveCoffee(user)}
}
请注意:

  • DStream.foreachRDD
    为您提供了一个
    RDD[User]
    而不是一个用户。回到我们的咖啡示例,这是在某个时间间隔内到达的用户的集合
  • 要访问集合的单个元素,我们需要进一步操作RDD。在本例中,我使用
    rdd.foreach
    为每个用户提供咖啡

想想执行力:我们可能会有一群咖啡师在煮咖啡。那些是我们的遗嘱执行人。Spark Streaming负责制作一小批用户(或订单),Spark将把工作分配给咖啡师,这样我们就可以并行制作咖啡并加快咖啡供应速度。

感谢您对分区/RDD的更正。我不知道。@maasg我还是不明白!正如您所说,“在每个批处理间隔,每个数据流都会生成一个且只有一个RDD”,它不需要为foreach RDD()调用
foreachRDD()
,因为只有一个RDD,
foreachRDD()
可以命名为
getRDD()
并返回RDD对象。您的示例可以这样修改:   <代码>val用户数据流:数据流[用户]=???   
userDstream.getRDD.foreach{user=>serveCoffee(user)}
@maasg您的意思是使用15分钟作为时间间隔,9:00生成RDD,9:15生成RDD,9:30生成RDD,您可以使用
foreachRDD()
来处理每三个RDD(包含9:00,9:15,9:30),但假设现在的时间是9:30,9:00和9:15的RDD是以前处理过的,如果使用
foreachRDD()
,则只能处理一个9:30的RDD,如何处理9:30之前9:30的RDD?9:30之前的数据或RDD会在9:30消失,不是吗?在Spark steaming中,每个时间间隔处理当前批次间隔的数据,为什么在9:30处理6:00的RDD,6:00的RDD应该在6:00处理。@郭,不,我不是这个意思。我想让你知道,这个预言是有时间限制的。您应该将
foreachRDD
理解为
scheduleOperationOnRddForEachTimeInterval(rdd=>operation(rdd))
@coolbreeze,就像在Spark中一样,如果没有操作,转换就不会具体化。此外,如果我们没有在流式处理上下文中注册输出操作(如
foreachRDD
),当我们尝试启动它时,它将抛出一个异常:
没有注册输出操作,因此没有要执行的操作
,您最终是否真正理解了答案?