10.3 转化操作
转化操作可以分为无状态(stateless)和有状态(stateful)两种。
-
在无状态转化操作中,每个批次的处理不依赖于之前批次的数据。
常见的RDD转化操作,例如 map() 、 filter() 、 reduceByKey() 等,都是无状态转化操作。 -
有状态转化操作需要使用之前批次的数据或者是中间结果来计算当前批次的数据。
有状态转化操作包括基于滑动窗口的转化操作和追踪状态变化的转化操作。
无状态转化操作
无状态转化操作就是把简单的 RDD 转化操作应用到每个批次上,也就是转化 DStream 中的每一个 RDD。
有状态转化操作
有状态转化操作是跨时间区间跟踪数据的操作;也就是说,一些先前批次的数据也被用来在新的批次中计算结果。
主要的两种类型是滑动窗口和 updateStateByKey(),前者以一个时间阶段为滑动窗口进行操作,后者则用来跟踪每个键的状态变化(例如构建一个代表用户会话的对象)。
基于窗口的转化操作
基于窗口的操作会在一个比 StreamingContext 的批次间隔更长的时间范围内,通过整合多个批次的结果,计算出整个窗口的结果。
所有基于窗口的操作都需要两个参数,分别为窗口时长以及滑动步长,两者都必须是 StreamContext 的批次间隔的整数倍。
窗口时长控制每次计算最近的多少个批次的数据,其实就是最近的 windowDuration/batchInterval 个批次。
可以用的最简单窗口操作是 window() ,它返回一个新的 DStream 来表示所请求的窗口操作的结果数据。
UpdateStateByKey 转化操作
有时,我们需要在 DStream 中跨批次维护状态(例如跟踪用户访问网站的会话)。
针对这种情况, updateStateByKey() 为我们提供了对一个状态变量的访问,用于键值对形式的 DStream。
给定一个由(键,事件)对构成的 DStream,并传递一个指定如何根据新的事件更新每个键对应状态的函数,它可以构建出一个新的 DStream,其内部数据为(键,状态)对。
要使用 updateStateByKey() ,提供了一个 update(events, oldState) 函数,接收与某键相关 的事件以及该键之前对应的状态,返回这个键对应的新状态。
这个函数的签名如下所示。
- events :是在当前批次中收到的事件的列表(可能为空)。
- oldState :是一个可选的状态对象,存放在 Option 内;如果一个键没有之前的状态, 这个值可以空缺。
- newState :由函数返回,也以 Option 形式存在;我们可以返回一个空的 Option 来表示想要删除该状态。
updateStateByKey() 的结果会是一个新的 DStream,其内部的 RDD 序列是由每个时间区间对应的(键,状态)对组成的。