大数据求索(8):Spark Streaming简易入门一
一、Spark Streaming简单介绍
Spark Streaming是基于Spark Core上的一个应用程序,可伸缩,高吞吐,容错(这里主要是借助Spark Core的容错方式)处理在线数据流,数据可以有不同的来源,以及同时处理不同来源的数据。Spark Streaming处理的数据可以结合ML和Graph。
Spark Streaming本身是随着流进来的数据按照时间为单位生成Job,然后触发Job,在Cluster执行的一个流式处理引擎,本质上说是加上了时间维度的批处理。
二、Spark Streaming作用
Spark Streaming支持从多种数据源中读取数据,如Kafka,Flume,HDFS,Kinesis,Twitter等,并且可以使用高阶函数如map,reduce,join,window等操作,处理后的数据可以保存到文件系统,数据库,Dashboard等。
三、Spark Streaming原理
Spark Streaming工作原理如下图所示:
- 以时间为单位将数据流切分成离散的数据单位
- 将每批数据看做RDD,使用RDD操作符处理
- 最终结果以RDD为单位返回
输入的数据流经过Spark Streaming的receiver,数据切分为DStream(类似RDD,DStream是Spark Streaming中流数据的逻辑抽象),然后DStream被Spark Core的离线计算引擎执行并行处理。
简言之,Spark Streaming就是把数据按时间切分,然后按传统离线处理的方式计算。从计算流程角度看就是多了对数据收集和按时间节分。
四、Spark Streaming核心概念
4.1 Streaming Context
类似于Spark Core,要想使用Spark Streaming,需要创建一个StreamingContext对象作为入口。类似代码如下:
import org.apache.spark._
import org.apache.spark.streaming._
val conf = new SparkConf().setAppName(appName).setMaster(master)
val ssc = new StreamingContext(conf, Seconds(1))
观察源码可以发现,其实StreamingContext实现还是创建了一个SparkContext。其中,第二个参数Seconds(1)表示1秒处理一次。目前还是基于秒级的计算,无法做到毫秒级。
Spark Streaming也可以通过传入一个SparkContext对象来创建
import org.apache.spark.streaming._
val sc = ... // existing SparkContext
val ssc = new StreamingContext(sc, Seconds(1))
当创建好上下文对象以后,需要做如下事情:
- 通过创建一个DStreams来定义输入源
- 通过将transformation 和output 操作应用于DStream来定义流式计算
- 开始接收数据并使用streamingContext.start()启动
- 等待使用streamingContext.awaitTermination()停止处理(手动或由于任何错误)
- 可以使用streamingContext.stop()手动停止处理
注意:
- 一旦上下文已经启动,就不能设置或添加新的流式计算。
- 一旦上下文停止后,无法重新启动。(不要和重新运行程序重新创建一个混淆)
- 在JVM中只能同时运行一个StreamingContext
- StreamingContext上的stop也会停止SparkContext。要仅停止StreamingContext,将stopSparkContext的stop的可选参数设置为false。
- 只要在创建下一个StreamingContext之前停止前一个StreamingContext(不停止SparkContext),就可以重复使用SparkContext来创建多个StreamingContexts。
4.2 Discretized Streams (DStreams)
DStream可以说是SPark Streaming 的核心。它代表连续的数据流,可以是从源接收的输入数据流,也可以由转换操作生成的已经处理过的数据流。内部实现上,DStreams其实是一个连续的RDD序列,其中的每个RDD都包含来自特定时间间隔的数据。如下图所示:
任何应用在DStream上的操作都会转换为底层RDD上的操作。对于词频统计来说,flatMap算子应用于DStream每行中上的每一个RDD以生成单词DStream的RDDs。如下图所示:
4.2 Input DStreams 和 Receivers
Input DStreams代表从Streaming源接收到的数据构成的DStreams。每一个Input DStream(除了file stream)都与一个Receiver对象相关联,这个对象从源接收数据并将其存储在Spark的内存中进行处理。
Spark Streaming提供两种策略用于内置的streaming源
-
basic sources:
sources直接在StreamingContext的API中得到,如文件系统、socket连接等
-
advanced sources:
像Kafka、Flume等源,可通过额外的工具类获得,这些需要引入额外的jar包。
注意,如果想在streaming程序中并行接收多个streams数据,可以创建多个input DStreams。这将创建多个Receivers,这些receiver将同时接收多个数据流。但是,Spark的worker/exector是一个长期运行的任务,因此它占用了分配给Spark Streaming应用程序的其中一个核(线程)。所以采用local模式运行,至少分配2个核,不然无法进行下面的计算。
注意点:
- 在本地运行Spark Streaming程序时,请勿使用“local”或“local [1]”作为主URL。这两种模式都意味着只有一个线程用于本地运行任务。如果此时再用receiver接收Input DStream,这单个线程便用来运行Receiver,不会用于接下来的处理数据了。因此,采用“local[n]”,这里的n要大于Receiver的数量。
- 在集群上运行时,分配给Spark Streaming应用程序的核心数必须大于接收器数。否则系统将接收数据,但无法处理数据。
4.3 Basic Sources
上面的举例中,是从套接字中接收文本信息创建一个DStream。除了sockets,StreamingContext API提供了从文件作为输入源创建DStream的方法。
streamingContext.fileStream[KeyClass, ValueClass, InputFormatClass](dataDirectory)
fileStream:用于从与HDFS API兼容的任何文件系统上的文件中读取数据(如HDFS、S3、NFS等),创建一个DStream。
Spark Streaming将会监视传入的dataDirectory目录,并处理在这个目录下创建的所有文件,但不支持嵌套目录
注意:
- 文件必须有相同的格式
- 必须通过原子move或rename的到此目录下的文件
- 一旦移动,这个文件将不能改变。因此,即使这个文件后面被追加了数据,新数据也不会被读取。
下一篇将继续介绍。