Spark Streaming状态操作: updateStateByKey、mapWithState

在Spark Streaming中,DStream的转换分为有状态和无状态两种。无状态的操作,即当前批次的处理不依赖于先前批次的数据,如map()、flatMap()、filter()、reduceByKey()、groupByKey()等等;而有状态的操作,即当前批次的处理需要依赖先前批次的数据,这样的话,就需要跨批次维护状态。

总结spark streaming中的状态操作:updateStateByKey、mapWithState

updateStateByKey

对整个实时计算的所有时间间隔内产生的相关数据进行统计。 spark streaming 的解决方案是累加器,工作原理是定义一个类似全局的可更新的变量,每个 时间窗口内得到的统计值都累加到上个时间窗口得到的值,这样整个累加值就是跨越多个时间间隔。
updateStateByKey 操作可以让我们为每个 key 维护一份 state ,并持续不断的更新该 state
  • 首先,要定义一个 state,可以是任意的数据类型;
  • 其次,要定义 state 更新函数(指定一个函数如何使用之前的 state 和新值来更新 state)。 对于每个 batchspark 都会为每个之前已经存在的 key 去应用一次 state 更新函数,无论这个 key batch 中是否有新的数据。如果 state 更新函数返回 none,那么 key 对应的 state 就会被删除。 当然对于每个新出现的 key 也会执行 state 更新函数。
注意
updatestateBykey 要求必须开启 checkpoint 机制。
updateStateByKey 返回的都是 DStream 类型。根据 updateFunc 这个函数来更新状态。其中参数:Seq[V] 是本次的数据类型, Option[S] 是前次计算结果类型,本次计算结果类型也是 Option[S]。计算肯定需要 Partitioner 。因为 Hash 高效率且不做排序,默认 Partitioner 是 HashPartitoner。 由于 cogroup 会对所有数据进行扫描,再按 key 进行分组,所以性能上会有问题。特别是随着时间的推移,这样的计算到后面会越算越慢。
所以数据量大的计算、复杂的计算,都不建议使用 updateStateByKey
 

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合并,状态较大时,性能较低。

 

你可能感兴趣的:(Spark,Streaming)