Spark Streaming中状态算子的使用

流处理中状态的概念

流处理中,有个状态(state)的概念:

  • 无状态的:当前批次处理完之后,数据只与当前批次有关
  • 有状态的:前后批次的数据处理完之后,之间是有关系的

官网的介绍:
http://spark.apache.org/docs/latest/streaming-programming-guide.html#updatestatebykey-operation

updateStateByKey解读

updateStateByKey:返回的是一个新的并且带有状态的DStream,会根据每一个key进行更新,更新的规则是根据自己定义的function来确定的
需要2个步骤:

  • 定义state;以wordcount为例,value是作为state来处理的,是根据key来更新我们的value的
  • 定义一个state update function:将旧state的值与新state的值根据所定义的规则给相互作用在一起

自定义updateFunction

我们自定义的updateFunction函数如下所示:

def updateFunction(newValues: Seq[Int], preValues: Option[Int]): Option[Int] = {
    val curCount = newValues.sum //当前
    val preCount = preValues.getOrElse(0) //老的能获取就获取,获取不到就直接赋值为0
    Some(curCount + preCount)
  }

可以发现针对于newValues定义的类型为Seq,针对于preValues定义的类型为Option
比如有两个批次:
批次1 a a a d d
批次2 b b b c c a
newValues代表当前批次的值,key所对应的新值可能有多个,因此定义为Seq类型
preValues代表以前批次的累加值,key可能存在也可能不存在(比如b和c),因此定义为Option类型

checkpoint

直接运行产生报错

在这里插入图片描述
提示我们需要去设置checkpoint,ssc.checkpoint(“.”)
原因在于目前是有状态的,需要当前批次和以前批次的值去累加起来的,因此是需要将这些状态通过checkpoint的方式给落地存起来的
设置完之后,运行程序就完全OK了

目前所存在的问题

关闭Streaming程序后,进行重启,发现原先进来的几个批次处理计算累加过后的数据,在重启之后不再进行展示了,直接是从头开始的,啥都没有了
假设我们的流处理程序某个时间点挂了,重启之后就会发现什么都没了,因此目前的这种方式肯定是还存在一定的问题的

checkpoint官网解读

参照checkpoint在Spark官网的相关内容

官网:
http://spark.apache.org/docs/latest/streaming-programming-guide.html#checkpointing

Spark Streaming的应用程序必须是7*24h的,因此对于可靠性的考虑是必要的(比如系统挂掉、JVM crash等等)。因此对于这些可能存在的问题,Spark Streaming需要我们去checkpoint,将足够的信息给存到可容错的存储系统中去(比如HDFS)
checkpoint的信息可以分为两大类:

  • Metadata checkpoint:
    包括了Configuration、DStream operations、Incomplete batches(未完成的批次)
  • Data checkpoint:真正传输过来的数据

何时开启checkpoint

  • 使用带状态的transformation算子的时候,比如:updateStateByKey、reduceByKeyAndWindow
  • 应用程序的driver端挂掉后,对应的metadata需要能够通过checkpoint的方式给恢复过来

如何配置checkpoint

其实核心代码就一句:

// 当作业挂了时,从checkpoint中去获取StreamingContext的相关内容
val ssc = StreamingContext.getOrCreate(checkpointDirectory, functionToCreateContext)

这样配置之后,每次重启之后,都会将历史的数据信息给获取到

使用注意点

如果想使用checkpoint,必须保证一点:代码不能发生任何变化;一旦代码发生了变化,也就意味着metadata发生了变化,重启过后,会存在不生效的情况,即对于历史状态的数据信息会读取不到,因此checkpoint这种方式在生产中慎用(尤其是在offset维护的场景中)

代码

object StreamingCheckpointApp {

  val checkpointDirectory = "."

  def main(args: Array[String]): Unit = {
    // 当作业挂了时,从checkpoint中去获取StreamingContext的相关内容
    val ssc = StreamingContext.getOrCreate(checkpointDirectory, functionToCreateContext)
    ssc.start()
    ssc.awaitTermination()
  }

  def functionToCreateContext(): StreamingContext = {
    val ssc = ContextUtils.getStreamingContext(this.getClass.getSimpleName, 5)
    ssc.checkpoint(checkpointDirectory)

    val lines = ssc.socketTextStream("localhost", 9999)
    val result = lines.flatMap(_.split(","))
      .map((_,1))
      .updateStateByKey(updateFunction)
    result.print()

    ssc
  }

  def updateFunction(newValues: Seq[Int], preValues: Option[Int]): Option[Int] = {
    val curCount = newValues.sum //当前
    val preCount = preValues.getOrElse(0) //老的能获取就获取,获取不到就直接赋值为0
    Some(curCount + preCount)
  }

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值