Spark Streaming 是Spark处理模块,可以处理多种类型数据源的流数据(kafka,flume,twitter,ZeroMQ,TCP sockets等),支持对这些数据进行一系列操作(map,reduce,join,window等),处理结果可以保存到数据库或文件系统中。 内部实现上,Spark Streaming接收流入的数据并将其划分为一系列的批数据,进而利用Spark对这些批数据进行处理,数据处理流程如下图所示:

6.1

例子

下面是一个NetworkWordCount的例子,代码如下:

// Create the context with a 1 second batch size
val sparkConf = new SparkConf().setAppName("NetworkWordCount")
val ssc = new StreamingContext(sparkConf, Seconds(1))
// Create a socket stream on target ip:port and count the
// words in input stream of \n delimited text (eg. generated by 'nc')
// Note that no duplication in storage level only for running locally.
// Replication necessary in distributed scenario for fault tolerance.
val lines = ssc.socketTextStream(“localhost”,9999)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)
wordCounts.print()
ssc.start()
ssc.awaitTermination()

阅读代码,流程如下:

1、 首先实例化一个StreamingContext 2、 调用StreamingContext的socketTextStream,会接受本地9999端口的输入流数据 3、 对获得的DStream进行处理 4、 调用StreamingContext的start方法,开始接受数据 5、 调用StreamingContext的awaitTermination方法,开始处理数据

DStream

Spark Streaming 提供了一种数据结构DStream,用来表示连续的流数据,可以从数据源直接创建或者从其它DStream操作创建,内部DStream由一系列的RDD组成,如下图所示:

6.2

对于DStream的任何操作最终会转化为对内部RDD的操作,例如上述例子中的操作将会执行如下图的转化:

6.3

对DStream的计算最终会由对RDD的计算来实现。 例子中的socketTextStream会生成一个SocketInputStream对象用来处理socket 的输入数据,对于每一个Input DStream都会有一个相应的Receiver从数据源接收数据并将其保存到Spark的内存中进行处理。

操作

DStream除了支持一些与RDD类似的转化操作如map、flatMap、filter等,还支持一类Window操作,该类操作将转换函数应用在一个窗口内的数据上,该窗口是滑动的,如下图所示:

6.4

window类操作需要两个额外的参数,窗口长度和滑动间隔(图中分别是3和2),对于开始的word count例子,如果希望每10秒得到过去30秒的数据,可以使用如下函数: val windowedWordCounts = pairs.reduceByKeyAndWindow((a:Int,b:Int) => (a + b), Seconds(30), Seconds(10)) 此外,还有一些其它的window函数如countByWindow、reduceByWindow和countByValueAndWindow等。

小结

本章通过一个例子介绍了Spark Streaming的编程模式及应用场景,并介绍了DStream这种数据结构的实现以及操作。

参考

Spark code

Spark internal