4、转化操作
DStream的转化操作可以分为无状态(stateless)和有状态(stateful)两种。
无状态转化操作中,每个批次的处理不依赖于之前批次的数据。
有状态转化操作需要使用之前批次的数据或者是中间结果来计算当前批次的数据。有状态转化操作包括基于滑动窗口的转化操作和追踪状态变化的转化操作。
4.1、无状态转化操作
无状态转化操作就是把简单的RDD转化操作应用到每个批次上,也就是转化DStream中的每一个RDD。部分无状态转化操作列如下表。
针对键值对的DStream转化操作(比如reduceByKey())要添加inport StreamingContext._才能在Scala中使用。和RDD一样,在Java中需要通过mapToPair()创建出一个JavaPairDStream()才能使用。
函数名称 |
目的 |
Scale示例 |
用来操作DStream[T]的用户自定义函数的函数签名 |
map() |
对DStream中的每个元素应用给定函数,返回由各元素输出的迭代器组成的DStream。 |
ds.map(x => x + 1 |
f: (T) - > U |
flatMap() |
对DStream中的每个元素应用给定函数,返回由各元素输出的迭代器组成的DStream。 |
ds.flatMap(x => x.split(“ “) |
f: T -> Iterator[U] |
filter() |
返回由给定DStream中通过筛选的元素组成的DStream。 |
ds.filter(x => x != 1) |
f: T -> Boolean |
repartition() |
改变DStream的分区数 |
ds.repartition(10) |
N/A |
reduceByKey() |
将每个批次中键相同的记录归约。 |
ds.reduceByKey((x, y) => x + y) |
f: T, T -> T |
groupByKey() |
将每个批次中的记录根据键分组。 |
ds.groupByKey() |
N/A |
这些函数看起来像作用在整个流上一样,但事实上每个 DStream 在内部是由许多 RDD(批次)组成,且无状态转化操作是分别应用到每个 RDD 上的。例如,reduceByKey() 会归约每个时间区间中的数据,但不会归约不同区间之间的数据。
4.2、有状态转化操作
DStream 的有状态转化操作是跨时间区间跟踪数据的操作;也就是说,一些先前批次的数据也被用来在新的批次中计算结果。主要的两种类型是滑动窗口和 updateStateByKey() ,前者以一个时间阶段为滑动窗口进行操作,后者则用来跟踪每个键的状态变化(例如构建一个代表用户会话的对象)。有状态转化操作需要在你的 StreamingContext 中打开检查点机制来确保容错性。
设置检查点:
ssc.checkpoint("hdfs://...")
进行本地开发时,你也可以使用本地路径(例如 /tmp)取代 HDFS。
一般都是基于窗口的转化操作,基于窗口的操作会在一个比 StreamingContext 的批次间隔更长的时间范围内,通过整合多个批次的结果,计算出整个窗口的结果。后面WindowOperations有详解。