在Spark Streaming中,DStream的转换分为有状态和无状态两种。无状态的操作,即当前批次的处理不依赖于先前批次的数据,如map()、flatMap()、filter()、reduceByKey()、groupByKey()等等;而有状态的操作,即当前批次的处理需要依赖先前批次的数据,这样的话,就需要跨批次维护状态。
总结spark streaming中的状态操作:updateStateByKey、mapWithState
updateStateByKey
- 首先,要定义一个 state,可以是任意的数据类型;
- 其次,要定义 state 更新函数(指定一个函数如何使用之前的 state 和新值来更新 state)。 对于每个 batch,spark 都会为每个之前已经存在的 key 去应用一次 state 更新函数,无论这个 key 在 batch 中是否有新的数据。如果 state 更新函数返回 none,那么 key 对应的 state 就会被删除。 当然对于每个新出现的 key 也会执行 state 更新函数。
mapWithState
mapWithState从spark 1.6.0开始出现,可以看做是updateStateByKey的升级版,有一些updateStateByKey所没有的特征:
1、支持输出只发生更新的状态和全量状态
mapWithState默认每个批次只会返回当前批次中有新数据的Key的状态,也可返回全量状态。updateStateByKey每个批次都会返回所有状态。
2、内置状态超时管理
内置状态超时管理,可对超时的Key单独处理。也可实现如会话超时(Session Timeout)的功能。在updateStateByKey中,如果要实现类似功能,需要大量编码。
3、初始化状态
可以选择自定义的RDD来初始化状态。
4、可以返回任何我们期望的类型
由mapWithState函数可知,可以返回任何我们期望的类型,而updateStateByKey做不到这一点。
5、性能更高
实现上,mapWithState只是增量更新,updateStateByKey每个批次都会对历史全量状态和当前增量数据进行cogroup合并,状态较大时,性能较低。