- Spark Streaming提供了一个高层次的抽象叫做离散流(discretized stream)或者DStream,代表了持续性的数据流
- DStream可以通过外部数据源(Kafka,Flume,Twitter等)来获取,也可以通过现有DStream的高级操作(Transformation操作)获得
- 在内部,DStream代表着一系列的持续的RDDs,DStream是一个没有边界的集合,也就是它没有大小的限制,它代表的是一个时空的概念。
- DStream中的每个RDD都是一小段时间(interval)分割开来的数据集
- 对DStream的任何操作都会转化成对底层RDDs的操作
- 例如,对lines DStream做flatMap操作,实际上就是对它内部的所有RDD做flatMap操作。即对DStream的操作可以通过RDD的Transformation生成新的DStream。
在Spark Streaming中所有的操作都是基于流,而输入源是这一系列操作的起点,Spark Streaming提供基础和高级两种输入源,基础输入源和高级输入源, 它们称为Input DStream。Input DStream是DStream的一种,它是流数据源中获取的原始数据流。
- 基础输入源是指能够直接应用于StreamingContext API的输入源。例如文件流、套接字流(socket)、RDD队列流。
- 套接字流
- 任何用户在用Socket(套接字)通信之前,首先要先申请一个Socket号,Socket号相当于该用户的电话号码。同时要知道对方的Socket,相当于对方也有一个电话号码。然后向对方拨号呼叫,相当于发出连接请求。对方假如在场并空闲,相当于通信的另一主机开机且可以接受连接请求,拿起电话话筒,双方就可以正式通话,相当于连接成功。
- 双方通话的过程,是Socket发送数据和从Socket接受数据的过程,相当于向电话机发出信号和从电话机接受信号。通话结束后,一方关闭Socket,相当于挂起电话机,撤销连接。所以套接字流是通过监听Socket端口接收的数据,相当于Socket之间的通信。
- 文件流
- 文件流从兼容于HDFS API的文件系统(如HDFS、S3、NFS)中读取文件中的数据,它会对文件系统中的某个目录进行监听,一旦发现有新的文件生成,SparkStreaming就会自动把文件内容读取,文件流的DStream创建方法为textFileStream:
StreamingContext.textFileStream(dataDirectory)
- Directory中的文件需要满足以下约束条件:(1)这些文件格式必须相同,如:统一为文本文件;(2)这些文件在目录dataDirectory中的创建形式比较特殊:必须以原子方式被“移动”或“重命名”至目录dataDirectory中;
- (3)一旦文件被“移动”或“重命名”至目录dataDirectory中,文件不可以被改变,例如:追加至这些文件的数据可能不会被处理。
- 文件流从兼容于HDFS API的文件系统(如HDFS、S3、NFS)中读取文件中的数据,它会对文件系统中的某个目录进行监听,一旦发现有新的文件生成,SparkStreaming就会自动把文件内容读取,文件流的DStream创建方法为textFileStream:
- RDD队列流
- 在编写Spark Streaming应用程序时,可调用StreamingContext对象的queueStream()方法创建基于RDD队列的Dstream。例如val inputStream = ssc.queueStream(rddQueue)中的rddQueue是RDD队列,inputStream是“RDD队列流”类型的数据源,可以通过对StreamingContext的设置调整批处理间隔,实现每隔一段时间从rddQueue队列中取出数据进行处理。
- 套接字流
- 高级输入源指Spark不包含的库,如Kafka、Flume等。
DStream支持两种操作,一种是转换操作,生成一个新的DStream,另一种是输出操作,可以把数据写入外部系统中。DStream的转换操作可以分为无状态和有状态两种。
- 无状态转换操作含义
- 以上列出的这些操作,大部分(如map,flatMap,filter等)与RDD的转换操作类似
- transform(func)方法值得 深入地探讨
- transform操作极大地丰富了DStream上能够进行的操作内容。
- 使用transform操作后,除了可以使用DStream提供的一些转换方法之外,还能够直接调用任意RDD上的操作方法。
DStream的有状态转换操作需要使用之前批次的数据或者是中间结果来计算当前批次的数据,是跨时间区间跟踪数据的操作,也就是说,一些先前批次的数据也被用来在新的批次中计算结果。主要的两种类型是基于窗口的操作和updateStateByKey操作,前者以一个时间阶段为滑动窗口进行操作,后者则用来跟踪每个键的状态变化。
- 窗口操作
- 窗口函数,就是在DStream流上,以一个可配置的长度为窗口,以一个可配置的速率向前移动窗口,根据窗口函数的具体内容,对窗口内的数据执行计算操作,每次掉落在窗口内的RDD的数据会被聚合起来执行计算操作,然后生成的RDD会作为Window DStream的一个RDD。
- 下图表述的是滑动窗口长度为3秒,这三秒内的3个RDD会被聚合起来进行处理,然后过了两秒钟,又会对最近三秒内的数据执行滑动窗口计算。所以每个滑动窗口操作,都必须指定两个参数,窗口长度以及滑动间隔,而且这两个参数值都必须是batch(批处理时间)间隔的整数倍。
常用的窗口转换操作方法如表所示
这些操作都需要两个参数,windowLength(窗口长度)和slideInterval(时间间隔)。