Spark Streaming

Spark Streaming介绍
随着大数据的发展,人们对大数据的处理要求也越来越高,传统的MapReduce等批处理框架在某些特定领域(如实时用户推荐、用户行为分析)已经无法满足人们对实时性的需求,因此诞生了一批如S4、Storm的流式的、实时计算框架。而Spark由于其优秀的调度机制,快速的分布式计算能力,能够以极快的速度进行迭代运算。正是由于Spark的这些优势,使得Spark能够在某种程度上进行实时处理,Spark Streaming正是构建在此之上的流式框架。
Spark Streaming作为Spark的核心组件之一,同Apache Storm一样,主要对数据进行实时的流处理。但是不同于Storm,在Spark Streaming中数据处理的单位是一批而不是一条。Spark会等采集的源头数据累积到设置的间隔条件后,对数据进行统一的微批处理。这个间隔是Spark Streaming中的核心概念和关键参数,直接决定了Spark Streaming作业的数据处理延迟,当然也决定着数据处理的吞吐量和性能。相对于Storm的毫秒级延迟来说,Spark Streaming的延迟最低只能到几百毫秒,一般是在秒级甚至分钟级。因此对于实时数据处理延迟要求非常高的场合,Spark Streaming并不合适。另外,Spark Streaming底层依赖于Spark Core的RDD实现,即它和Spark框架整体是绑定在一起的,这是优点也是缺点。
对于已经采用Spark作为大数据处理框架,同时对数据延迟性要求又不是很高的场合,Spark Streaming 非常适合作为实时流处理的工具和方案,原因如下:
Spark Streaming内部的实现和调度方式高度依赖于Spark的DAG调度器和RDD,Spark Streaming的离散化流(DStream)本质上是RDD 在流式数据上的抽象,因此熟悉Spark 和RDD概念的用户非常容易理解Spark Streaming以及其DStream;
Spark上各个组件编程模型基本都是类似的,所以如果熟悉Spark的API,那么对Spark Streaming 的API也非常容易上手和掌握;
但是如果已经采用了其他诸如Hadoop和Storm 的数据处理方案,那么如果使用Spark Streaming, 则面临着Spark以及Spark Streaming的概念和原理的学习成本。
总体上来说,Spark Streaming作为Spark核心API的一个扩展,它对实时流式数据的处理具有可扩展性、高吞吐量、可容错性等特点。

Spark Streaming架构

Spark Streaming使用“微批次”的架构,把流式计算当作一系列连续的小规模批处理来对待。Spark Streammg从各种输人源中读取数据,并把数据分组为小的批次。新的批次按均匀的时间间隔创建出来。在每个时间区间开始的时候,一个新的批次就创建出来,在该区间内收到的数据都会被添加到这个批次中。在时间区间结束时,批次停止增长。时间区间的大小是由次间隔这个参数决定的。批次间隔一般设在500 毫秒到几秒之间,由应用开发者配置。每个输入批次都形成一个RDD, 以Spark作业的方式处理并生成其他的RDD。处理的结果可以以批处理的方式传给外部系统。
Spark Streaming的架构如下图所示:
Spark Streaming_第1张图片如上图所示,Spark Streaming接收输入数据流,并在内部将数据流分为多个较小的batch(batch 大小取决于batch的间隔)。Spark Streaimg引擎将这些输入数据的batch处理后,生成处理过数据的batch结果集。

DStream

Spark Streaming中基本的抽象是离散化流(即DStream),它代表一个连续的数据流。在Spark Streaming的架构中,DStream实际上是由一系列连续的RDD组成的。每个RDD包含确定时间间隔内的数据,这些离散的RDD连在一起,共同组成了对应的DStream。RDD和DStream的关系如下图所示:
Spark Streaming_第2张图片所以,实际上任何对DStream的操作都转换成了对DStream隐含的一系列对应RDD的操作。入下图所示:

Spark Streaming_第3张图片上图中对lines DStream的flatMap操作,实际上应用于lines对应每个RDD的操作,并生成了对应的works DStream的RDD。
这也就是上文所说的,Spark Streaming底层依赖于Spark Core的RDD实现。从本质上来说, Spark Streaming只不过是将流式的数据流根据设定的间隔分成了一系列的RDD,然后在每个RDD上应用相应的各种操作和动作,所以Spark Streaming底层的运行引擎实际上是Spark Core。

Spark Streaming的执行流程

Spark Streaming的执行流程如下图所示:
Spark Streaming_第4张图片Spark Streaming为每个输入源启动对应的接收器。接收器以任务的形式运行在应用的执行器进程中,从输入源收集数据并转换为RDD。接收器收集到数据后会把数据复制到另一个执行器进程来保障容错性。在驱动器程序中的StreamingContext会周期性地运行Spark作业来处理这些数据,并把当前时间区间中的RDD与之前时间区间中的RDD进行整合。
Spark Streaming对DStream提供的容错性与Spark为RDD所提供的容错性是一致:只要输入数据还在,它就可以使用RDD的血缘关系重算出任意状态的RDD。默认情况下,收到的数据分别存在于两个节点上,这样Spark可以容忍一个工作节点的故障。不过,如果只用血缘关系来恢复的话,重算有可能会花很长时间,因为需要处理从程序启动以来的所有数据。因此,Spark Streaming也提供了checkpoint(检查点)机制,可以把状态阶段性地存储到可靠文件系统中(HDFS)。一般来说,你需要每处理5到10个批次的数据后就保存一次。这样在恢复数据时,Spark Streaming只需要回溯到上一个检查点即可。

DStream的使用

DStream的转化操作可以分为无状态(stateless)和有状态(stateful)两种。
在无状态转化操作中,每个批次的处理不依赖于之前批次的数据;
相对地,有状态转化操作需要使用之前批次的数据或者是中间结果来计算当前批次的数据。

有状态转化操作

DStream的有状态转化操作是跨时间区间跟踪数据的操作;也就是说,一些先前批次的数据也被用来在新的批次中计算结果。主要的两种类型是滑动窗口和updateStateByKey()。前者以一个时间阶段为滑动窗口进行操作,后者则用来跟踪每个键的状态变化(例如构建一个代表用户会话的对象)。
有状态转化操作需要在你的StreamingContext中打开检查点机制来确保容错性。我们会在后续章节中更详细地讨论检查点机制,现在你只需要知道可以通过传递一个目录作为参数给ssc.checkpoint()来打开它,如以下代码所示:

ssc.checkpoint("file:///D:/spark")

基于窗口的操作会在一个比StreamingContext的批次间隔更长的时间范围内,通过整合多个批次的结果,计算出整个窗口的结果。所有基于窗口的操作都需要两个参数,分别为窗口时长以及滑动步长,两者都必须是StreamContext的批次间隔的整数倍。窗口时长控制每次计算最近的多少个批次的数据,其实就是最近的windowDuration/batchInterval个批次。如果有一个以10秒为批次间隔的源DStream,要创建一个最近30秒的时间窗口(即最近3个批次),就应当把windowDuration设为30秒。而滑动步长的默认值与批次间隔相等,用来控制对新的DStream进行计算的间隔。如果源 DStream 批次间隔为10秒,并且我们只希望每两个批次计算一次窗口结果,就应该把滑动步长设置为20秒。具体如下图所示:
Spark Streaming_第5张图片对DStream可以用的最简单窗口操作是window(),它返回一个新的DStream来表示所请求的窗口操作的结果数据。换句话说,window()生成的DStream中的每个 RDD 会包含多个批次中的数据,可以对这些数据进行count()、transform()等操作。使用代码如下所示:

lines = lines.window(Seconds(60), Seconds(5))

尽管可以使用window()写出所有的窗口操作,Spark Streaming还是提供了一些其他的窗口操作,让用户可以高效而方便地使用。首先,reduceByWindow()和reduceByKeyAndWindow()让我们可以对每个窗口更高效地进行归约操作。它们接收一个归约函数,在整个窗口上执行,比如 +。除此以外,它们还有一种特殊形式,通过只考虑新进入窗口的数据和离开窗口的数据,让Spark增量计算归约结果。这种特殊形式需要提供归约函数的一个逆函数,比如+对应的逆函数为-。对于较大的窗口,提供逆函数可以大大提高执行效率。具体流程如下图所示:
Spark Streaming_第6张图片
最后,DStream还提供了countByWindow()和countByValueAndWindow()作为对数据进行计数操作的简写。countByWindow()返回一个表示每个窗口中元素个数DStream,而countByValueAndWindow()返回的DStream则包含窗口中每个值的个数。

你可能感兴趣的:(笔记,spark,big,data,scala)